AAE-20140 Removing material locators from unit tests part 1 (#9345)

* AAE-20140 Removing material locators from unit tests part 1

* AAE-20140: Fixed lint and test issues
This commit is contained in:
Ehsan Rezaei
2024-02-16 13:43:49 +01:00
committed by GitHub
parent 40d64d299f
commit 05d23bc8a5
11 changed files with 285 additions and 258 deletions

View File

@@ -35,6 +35,9 @@ import { NodeAction } from '../document-list/models/node-action.enum';
import { SitesService } from '../common/services/sites.service';
import { NodesApiService } from '../common/services/nodes-api.service';
import { ContentService } from '../common/services/content.service';
import { HarnessLoader } from '@angular/cdk/testing';
import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed';
import { MatTabGroupHarness } from '@angular/material/tabs/testing';
describe('ContentNodeSelectorComponent', () => {
let component: ContentNodeSelectorComponent;
@@ -42,6 +45,7 @@ describe('ContentNodeSelectorComponent', () => {
let data: any;
let uploadService: UploadService;
let dialog: MatDialogRef<ContentNodeSelectorComponent>;
let loader: HarnessLoader;
beforeEach(() => {
data = {
@@ -86,6 +90,7 @@ describe('ContentNodeSelectorComponent', () => {
fixture = TestBed.createComponent(ContentNodeSelectorComponent);
component = fixture.componentInstance;
loader = TestbedHarnessEnvironment.loader(fixture);
const contentService = TestBed.inject(ContentService);
spyOn(contentService, 'hasAllowableOperations').and.returnValue(true);
@@ -121,13 +126,11 @@ describe('ContentNodeSelectorComponent', () => {
component.isLoading = false;
};
const getTabLabel = (idx: number) => fixture.debugElement.queryAll(By.css('.mat-tab-label'))[idx];
const selectTabByIndex = async (tabIndex: number): Promise<void> => {
const tabGroup = await loader.getHarness(MatTabGroupHarness.with({ selector: '.adf-content-node-selector-dialog-content' }));
const tabToSelect = (await tabGroup.getTabs())[tabIndex];
const selectTabByIndex = (tabIndex: number) => {
const uploadFromLocalTab = getTabLabel(tabIndex);
const attributes = uploadFromLocalTab.nativeNode.attributes as NamedNodeMap;
const tabPositionInSet = Number(attributes.getNamedItem('aria-posinset').value) - 1;
component.onTabSelectionChange(tabPositionInSet);
return tabToSelect.select();
};
describe('Data injecting with the "Material dialog way"', () => {
@@ -260,39 +263,38 @@ describe('ContentNodeSelectorComponent', () => {
describe('Upload button', () => {
const getUploadButton = () => fixture.debugElement.query(By.css('adf-upload-button button'))?.nativeElement as HTMLButtonElement;
it('Should not be able to upload a file whilst a search is still running', () => {
it('Should not be able to upload a file whilst a search is still running', async () => {
enableLocalUpload();
fixture.detectChanges();
const tabGroup = await loader.getHarness(MatTabGroupHarness.with({ selector: '.adf-content-node-selector-dialog-content' }));
const uploadFromLocalTab = (await tabGroup.getTabs())[1];
let infoMatIcon = getTabInfoButton();
let uploadFromLocalTab = getTabLabel(1);
expect(uploadFromLocalTab.nativeElement.getAttribute('aria-disabled')).toBe('false');
expect(await uploadFromLocalTab.isDisabled()).toBeFalse();
expect(infoMatIcon).toBeFalsy();
component.showingSearch = true;
fixture.detectChanges();
uploadFromLocalTab = getTabLabel(1);
infoMatIcon = getTabInfoButton();
expect(uploadFromLocalTab.nativeElement.getAttribute('aria-disabled')).toBe('true');
expect(await uploadFromLocalTab.isDisabled()).toBeTrue();
expect(infoMatIcon).toBeTruthy();
expect(component.getWarningMessage()).toEqual('NODE_SELECTOR.UPLOAD_BUTTON_SEARCH_WARNING_MESSAGE');
component.showingSearch = false;
fixture.detectChanges();
uploadFromLocalTab = getTabLabel(1);
infoMatIcon = getTabInfoButton();
expect(uploadFromLocalTab.nativeElement.getAttribute('aria-disabled')).toBe('false');
expect(await uploadFromLocalTab.isDisabled()).toBeFalse();
expect(infoMatIcon).toBeFalsy();
});
it('should be able to show upload button if showLocalUploadButton set to true', async () => {
enableLocalUpload();
selectTabByIndex(1);
await selectTabByIndex(1);
fixture.detectChanges();
const adfUploadButton = fixture.debugElement.query(By.css('adf-upload-button'));
@@ -301,8 +303,8 @@ describe('ContentNodeSelectorComponent', () => {
expect(adfUploadButton.nativeElement.textContent).toEqual('file_uploadFORM.FIELD.UPLOAD');
});
it('should be able to disable UploadButton if showingSearch set to true', () => {
selectTabByIndex(1);
it('should be able to disable UploadButton if showingSearch set to true', async () => {
await selectTabByIndex(1);
component.showingSearch = true;
component.hasAllowableOperations = true;
@@ -313,8 +315,8 @@ describe('ContentNodeSelectorComponent', () => {
expect(adfUploadButton.disabled).toBe(true);
});
it('should be able to enable UploadButton if showingSearch set to false', () => {
selectTabByIndex(1);
it('should be able to enable UploadButton if showingSearch set to false', async () => {
await selectTabByIndex(1);
component.showingSearch = false;
component.hasAllowableOperations = true;
@@ -325,11 +327,11 @@ describe('ContentNodeSelectorComponent', () => {
expect(adfUploadButton.disabled).toBe(false);
});
it('should be able to show warning message while searching', () => {
it('should be able to show warning message while searching', async () => {
component.data.showLocalUploadButton = true;
component.showingSearch = true;
component.hasAllowableOperations = false;
selectTabByIndex(1);
await selectTabByIndex(1);
fixture.detectChanges();
const infoMatIcon = getTabInfoButton();
@@ -351,9 +353,11 @@ describe('ContentNodeSelectorComponent', () => {
expect(warningMessage).toBeNull();
});
it('should be able to disable UploadButton if user does not have allowable operations', () => {
it('should be able to disable UploadButton if user does not have allowable operations', async () => {
component.hasAllowableOperations = false;
selectTabByIndex(1);
await selectTabByIndex(1);
component.onTabSelectionChange(1);
fixture.detectChanges();
const adfUploadButton = getUploadButton();
@@ -362,8 +366,8 @@ describe('ContentNodeSelectorComponent', () => {
expect(adfUploadButton.disabled).toBe(true);
});
it('should be able to enable UploadButton if user has allowable operations', () => {
selectTabByIndex(1);
it('should be able to enable UploadButton if user has allowable operations', async () => {
await selectTabByIndex(1);
component.hasAllowableOperations = true;
fixture.detectChanges();
@@ -373,21 +377,21 @@ describe('ContentNodeSelectorComponent', () => {
expect(adfUploadButton.disabled).toBe(false);
});
it('should not be able to show warning message if user has allowable operations', () => {
it('should not be able to show warning message if user has allowable operations', async () => {
enableLocalUpload();
selectTabByIndex(1);
await selectTabByIndex(1);
fixture.detectChanges();
const warningMessage = fixture.debugElement.query(By.css('.adf-content-node-upload-button-warning-message span'));
expect(warningMessage).toBeNull();
});
it('should be able to show warning message if user does not have allowable operations', () => {
it('should be able to show warning message if user does not have allowable operations', async () => {
component.data.showLocalUploadButton = true;
component.hasAllowableOperations = false;
component.showingSearch = false;
component.isLoading = false;
selectTabByIndex(1);
await selectTabByIndex(1);
fixture.detectChanges();
const infoMatIcon = getTabInfoButton();
@@ -412,15 +416,15 @@ describe('ContentNodeSelectorComponent', () => {
});
describe('Tabs', () => {
it('should isFileServerTabSelected return true when tabIndex 0 is selected', () => {
selectTabByIndex(0);
it('should isFileServerTabSelected return true when tabIndex 0 is selected', async () => {
await selectTabByIndex(0);
expect(component.isFileServerTabSelected()).toEqual(true);
});
it('should isLocalUploadTabSelected return true when tabIndex 1 is selected', () => {
it('should isLocalUploadTabSelected return true when tabIndex 1 is selected', async () => {
enableLocalUpload();
selectTabByIndex(1);
await selectTabByIndex(1);
expect(component.isLocalUploadTabSelected()).toEqual(true);
});
@@ -460,8 +464,7 @@ describe('ContentNodeSelectorComponent', () => {
it('should show drag and drop area with the empty list template when no upload has started', async () => {
enableLocalUpload();
const uploadFromLocalTab = getTabLabel(1);
uploadFromLocalTab.nativeElement.click();
await selectTabByIndex(1);
fixture.detectChanges();
await fixture.whenRenderingDone();
@@ -475,8 +478,7 @@ describe('ContentNodeSelectorComponent', () => {
it('should not show the empty list template when an upload has started', async () => {
enableLocalUpload();
const uploadFromLocalTab = getTabLabel(1);
uploadFromLocalTab.nativeElement.click();
await selectTabByIndex(1);
component.uploadStarted = true;
fixture.detectChanges();

View File

@@ -24,6 +24,10 @@ import { ContentTypeDialogComponent } from './content-type-dialog.component';
import { ContentTypeService } from './content-type.service';
import { ContentTypeDialogComponentData } from './content-type-metadata.interface';
import { TypeEntry } from '@alfresco/js-api';
import { HarnessLoader } from '@angular/cdk/testing';
import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed';
import { MatExpansionPanelHarness } from '@angular/material/expansion/testing';
import { MatTableHarness } from '@angular/material/table/testing';
const elementCustom: TypeEntry = {
entry: {
@@ -82,6 +86,7 @@ describe('Content Type Dialog Component', () => {
let fixture: ComponentFixture<ContentTypeDialogComponent>;
let contentTypeService: ContentTypeService;
let data: ContentTypeDialogComponentData;
let loader: HarnessLoader;
beforeEach(async () => {
data = {
@@ -116,6 +121,7 @@ describe('Content Type Dialog Component', () => {
contentTypeService = TestBed.inject(ContentTypeService);
spyOn(contentTypeService, 'getContentTypeByPrefix').and.returnValue(of(elementCustom));
fixture = TestBed.createComponent(ContentTypeDialogComponent);
loader = TestbedHarnessEnvironment.loader(fixture);
fixture.detectChanges();
});
@@ -147,13 +153,11 @@ describe('Content Type Dialog Component', () => {
});
it('should show the property with the aspect prefix not the inherited ones', async () => {
const showPropertyAccordion: HTMLButtonElement = fixture.nativeElement.querySelector('.adf-content-type-accordion .mat-expansion-panel-header');
expect(showPropertyAccordion).toBeDefined();
showPropertyAccordion.click();
fixture.detectChanges();
await fixture.whenStable();
const propertyShowed: NodeList = fixture.nativeElement.querySelectorAll('.adf-content-type-table .mat-row');
expect(propertyShowed.length).toBe(3);
await (await loader.getHarness(MatExpansionPanelHarness)).toggle();
const table = await loader.getHarness(MatTableHarness.with({ selector: '.adf-content-type-table' }));
expect((await table.getRows()).length).toBe(3);
});
it('should emit true when apply is clicked', (done) => {

View File

@@ -25,13 +25,17 @@ import { SearchService } from '../../../search/services/search.service';
import { DebugElement } from '@angular/core';
import { TranslateModule } from '@ngx-translate/core';
import { MatIconTestingModule } from '@angular/material/icon/testing';
import { HarnessLoader } from '@angular/cdk/testing';
import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed';
import { MatSelectionListHarness } from '@angular/material/list/testing';
import { MatInputHarness } from '@angular/material/input/testing';
describe('AddPermissionPanelComponent', () => {
let fixture: ComponentFixture<AddPermissionPanelComponent>;
let component: AddPermissionPanelComponent;
let element: HTMLElement;
let searchApiService: SearchService;
let debugElement: DebugElement;
let loader: HarnessLoader;
beforeEach(() => {
TestBed.configureTestingModule({
@@ -42,9 +46,9 @@ describe('AddPermissionPanelComponent', () => {
]
});
fixture = TestBed.createComponent(AddPermissionPanelComponent);
loader = TestbedHarnessEnvironment.loader(fixture);
searchApiService = fixture.componentRef.injector.get(SearchService);
debugElement = fixture.debugElement;
element = fixture.nativeElement;
component = fixture.componentInstance;
@@ -55,12 +59,10 @@ describe('AddPermissionPanelComponent', () => {
fixture.destroy();
});
const typeWordIntoSearchInput = (word: string): void => {
const inputDebugElement = debugElement.query(By.css('#searchInput'));
inputDebugElement.nativeElement.value = word;
inputDebugElement.nativeElement.focus();
inputDebugElement.nativeElement.dispatchEvent(new Event('input'));
fixture.detectChanges();
const typeWordIntoSearchInput = async (word: string): Promise<void> => {
const input = await loader.getHarness(MatInputHarness.with({ selector: '#searchInput' }));
return input.setValue(word);
};
it('should be able to render the component', () => {
@@ -73,9 +75,7 @@ describe('AddPermissionPanelComponent', () => {
expect(element.querySelector('#adf-add-permission-type-search')).not.toBeNull();
expect(element.querySelector('#searchInput')).not.toBeNull();
typeWordIntoSearchInput('a');
await fixture.whenStable();
fixture.detectChanges();
await typeWordIntoSearchInput('a');
expect(element.querySelector('#adf-add-permission-authority-results')).not.toBeNull();
expect(element.querySelector('#result_option_0')).not.toBeNull();
@@ -90,9 +90,7 @@ describe('AddPermissionPanelComponent', () => {
expect(items[0].entry.id).toBe(fakeAuthorityListResult.list.entries[0].entry.id);
});
typeWordIntoSearchInput('a');
await fixture.whenStable();
fixture.detectChanges();
await typeWordIntoSearchInput('a');
const listElement: DebugElement = fixture.debugElement.query(By.css('#result_option_0'));
expect(listElement).toBeTruthy();
@@ -104,9 +102,7 @@ describe('AddPermissionPanelComponent', () => {
expect(element.querySelector('#adf-add-permission-type-search')).not.toBeNull();
expect(element.querySelector('#searchInput')).not.toBeNull();
typeWordIntoSearchInput('a');
await fixture.whenStable();
fixture.detectChanges();
await typeWordIntoSearchInput('a');
expect(element.querySelector('#adf-add-permission-authority-results')).toBeTruthy();
expect(element.querySelector('#result_option_0')).toBeTruthy();
@@ -118,10 +114,8 @@ describe('AddPermissionPanelComponent', () => {
spyOn(searchApiService, 'search').and.returnValue(of(fakeAuthorityListResult));
expect(element.querySelector('#adf-add-permission-type-search')).not.toBeNull();
expect(element.querySelector('#searchInput')).not.toBeNull();
typeWordIntoSearchInput('a');
await typeWordIntoSearchInput('a');
await fixture.whenStable();
fixture.detectChanges();
expect(element.querySelector('#result_option_0')).toBeTruthy();
const clearButton = fixture.debugElement.query(By.css('#adf-permission-clear-input'));
@@ -136,9 +130,7 @@ describe('AddPermissionPanelComponent', () => {
it('should remove element from selection on click when is already selected', async () => {
spyOn(searchApiService, 'search').and.returnValue(of(fakeAuthorityListResult));
typeWordIntoSearchInput('a');
await fixture.whenStable();
fixture.detectChanges();
await typeWordIntoSearchInput('a');
let selectedUserIcon = fixture.debugElement.query(By.css('.adf-people-select-icon'));
const listElement: DebugElement = fixture.debugElement.query(By.css('#result_option_0'));
@@ -162,9 +154,7 @@ describe('AddPermissionPanelComponent', () => {
spyOn(searchApiService, 'search').and.returnValue(of(fakeAuthorityListResult));
component.selectedItems.push(fakeAuthorityListResult.list.entries[0]);
typeWordIntoSearchInput('a');
await fixture.whenStable();
fixture.detectChanges();
await typeWordIntoSearchInput('a');
expect(element.querySelector('#adf-add-permission-authority-results')).toBeTruthy();
expect(element.querySelector('#adf-add-permission-group-everyone')).toBeTruthy();
@@ -177,9 +167,7 @@ describe('AddPermissionPanelComponent', () => {
spyOn(searchApiService, 'search').and.returnValue(of({ list: { entries: [] } }));
component.selectedItems.push(fakeAuthorityListResult.list.entries[0]);
typeWordIntoSearchInput('a');
await fixture.whenStable();
fixture.detectChanges();
await typeWordIntoSearchInput('a');
expect(element.querySelector('#adf-add-permission-authority-results')).not.toBeNull();
expect(element.querySelector('#adf-add-permission-group-everyone')).toBeDefined();
@@ -191,13 +179,12 @@ describe('AddPermissionPanelComponent', () => {
component.selectedItems.push(fakeNameListResult.list.entries[0]);
component.selectedItems.push(fakeNameListResult.list.entries[1]);
typeWordIntoSearchInput('a');
await fixture.whenStable();
fixture.detectChanges();
await typeWordIntoSearchInput('a');
expect(element.querySelector('#result_option_0 .mat-list-text')).toBeTruthy();
expect(element.querySelector('#result_option_1 .mat-list-text')).toBeTruthy();
expect(element.querySelector('#result_option_0 .mat-list-text').innerHTML).not.toEqual(element.querySelector('#result_option_1 .mat-list-text').innerHTML);
const list = await loader.getHarness(MatSelectionListHarness);
const items = await list.getItems();
expect(items.length).toBe(3);
expect(await items[0].getText()).not.toEqual(await items[1].getText());
});
it('should emit unique element in between multiple search', async () => {
@@ -212,9 +199,7 @@ describe('AddPermissionPanelComponent', () => {
expect(items[0].entry.id).toBe(fakeAuthorityListResult.list.entries[0].entry.id);
});
typeWordIntoSearchInput('a');
await fixture.whenStable();
fixture.detectChanges();
await typeWordIntoSearchInput('a');
let listElement: DebugElement = fixture.debugElement.query(By.css('#result_option_0'));
expect(listElement).not.toBeNull();
@@ -226,9 +211,7 @@ describe('AddPermissionPanelComponent', () => {
clearButton.triggerEventHandler('click', {});
fixture.detectChanges();
typeWordIntoSearchInput('abc');
await fixture.whenStable();
fixture.detectChanges();
await typeWordIntoSearchInput('abc');
listElement = fixture.debugElement.query(By.css('#result_option_0'));
expect(listElement).not.toBeNull();

View File

@@ -16,17 +16,23 @@
*/
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { MatChip, MatChipRemove } from '@angular/material/chips';
import { MatChipRemove } from '@angular/material/chips';
import { By } from '@angular/platform-browser';
import { TranslateModule } from '@ngx-translate/core';
import { Subject } from 'rxjs';
import { ContentTestingModule } from '../../../testing/content.testing.module';
import { SearchChipAutocompleteInputComponent } from './search-chip-autocomplete-input.component';
import { DebugElement } from '@angular/core';
import { HarnessLoader } from '@angular/cdk/testing';
import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed';
import { MatChipHarness, MatChipListHarness } from '@angular/material/chips/testing';
import { MatAutocompleteHarness } from '@angular/material/autocomplete/testing';
import { MatOptionHarness } from '@angular/material/core/testing';
describe('SearchChipAutocompleteInputComponent', () => {
let component: SearchChipAutocompleteInputComponent;
let fixture: ComponentFixture<SearchChipAutocompleteInputComponent>;
let loader: HarnessLoader;
const onResetSubject = new Subject<void>();
beforeEach(() => {
@@ -39,6 +45,7 @@ describe('SearchChipAutocompleteInputComponent', () => {
});
fixture = TestBed.createComponent(SearchChipAutocompleteInputComponent);
loader = TestbedHarnessEnvironment.loader(fixture);
component = fixture.componentInstance;
component.onReset$ = onResetSubject.asObservable();
component.autocompleteOptions = [{value: 'option1'}, {value: 'option2'}];
@@ -85,8 +92,9 @@ describe('SearchChipAutocompleteInputComponent', () => {
*
* @returns list of chips
*/
function getChipList(): MatChip[] {
return fixture.debugElement.queryAll(By.css('mat-chip')).map((chip) => chip.nativeElement);
async function getChipList(): Promise<MatChipHarness[]> {
const harness = await loader.getHarness(MatChipListHarness);
return harness.getChips();
}
/**
@@ -95,8 +103,9 @@ describe('SearchChipAutocompleteInputComponent', () => {
* @param index index of the chip
* @returns chip value
*/
function getChipValue(index: number): string {
return fixture.debugElement.queryAll(By.css('mat-chip span')).map((chip) => chip.nativeElement)[index].innerText;
async function getChipValue(index: number): Promise<string> {
const chipList = await getChipList();
return chipList[index].getText();
}
/**
@@ -104,8 +113,9 @@ describe('SearchChipAutocompleteInputComponent', () => {
*
* @returns list of debug elements
*/
function getOptionElements(): DebugElement[] {
return fixture.debugElement.queryAll(By.css('mat-option'));
async function getOptionElements(): Promise<MatOptionHarness[]> {
const autocomplete = await loader.getHarness(MatAutocompleteHarness);
return autocomplete.getOptions();
}
/**
@@ -117,29 +127,29 @@ describe('SearchChipAutocompleteInputComponent', () => {
return fixture.debugElement.queryAll(By.css('.adf-autocomplete-added-option'));
}
it('should add new option only if value is predefined when allowOnlyPredefinedValues = true', () => {
it('should add new option only if value is predefined when allowOnlyPredefinedValues = true', async () => {
addNewOption('test');
addNewOption('option1');
expect(getChipList().length).toBe(1);
expect(getChipValue(0)).toBe('option1');
expect((await getChipList()).length).toBe(1);
expect(await getChipValue(0)).toBe('option1');
});
it('should add new option even if value is not predefined when allowOnlyPredefinedValues = false', () => {
it('should add new option even if value is not predefined when allowOnlyPredefinedValues = false', async () => {
component.allowOnlyPredefinedValues = false;
addNewOption('test');
addNewOption('option1');
expect(getChipList().length).toBe(2);
expect(getChipValue(0)).toBe('test');
expect((await getChipList()).length).toBe(2);
expect(await getChipValue(0)).toBe('test');
});
it('should add new formatted option based on formatChipValue', () => {
it('should add new formatted option based on formatChipValue', async () => {
component.allowOnlyPredefinedValues = false;
const option = 'abc';
component.formatChipValue = (value) => value.replace('.', '');
addNewOption(`.${option}`);
expect(getChipList().length).toBe(1);
expect(getChipValue(0)).toBe(option);
expect((await getChipList()).length).toBe(1);
expect(await getChipValue(0)).toBe(option);
});
it('should add new option upon clicking on option from autocomplete', async () => {
@@ -148,15 +158,15 @@ describe('SearchChipAutocompleteInputComponent', () => {
await fixture.whenStable();
fixture.detectChanges();
const matOptions = getOptionElements();
const matOptions = await getOptionElements();
expect(matOptions.length).toBe(2);
const optionToClick = matOptions[0].nativeElement as HTMLElement;
optionToClick.click();
const optionToClick = matOptions[0];
await optionToClick.click();
expect(optionsChangedSpy).toHaveBeenCalledOnceWith([{value: 'option1'}]);
expect(component.selectedOptions).toEqual([{value: 'option1'}]);
expect(getChipList().length).toBe(1);
expect((await getChipList()).length).toBe(1);
});
it('should apply class to already selected options', async () => {
@@ -192,20 +202,20 @@ describe('SearchChipAutocompleteInputComponent', () => {
await fixture.whenStable();
fixture.detectChanges();
expect(getOptionElements().length).toBe(15);
expect((await getOptionElements()).length).toBe(15);
});
it('should not add a value if same value has already been added', () => {
it('should not add a value if same value has already been added', async () => {
addNewOption('option1');
addNewOption('option1');
expect(getChipList().length).toBe(1);
expect((await getChipList()).length).toBe(1);
});
it('should show autocomplete list if similar predefined values exists', async () => {
enterNewInputValue('op');
await fixture.whenStable();
fixture.detectChanges();
expect(getOptionElements().length).toBe(2);
expect((await getOptionElements()).length).toBe(2);
});
it('should show autocomplete list based on custom filtering', async () => {
@@ -214,22 +224,23 @@ describe('SearchChipAutocompleteInputComponent', () => {
enterNewInputValue('test1');
await fixture.whenStable();
fixture.detectChanges();
expect(getOptionElements().length).toBe(1);
expect((await getOptionElements()).length).toBe(1);
});
it('should not show autocomplete list if there are no similar predefined values', async () => {
enterNewInputValue('test');
await fixture.whenStable();
fixture.detectChanges();
expect(getOptionElements().length).toBe(0);
const autocomplete = await loader.getHarness(MatAutocompleteHarness);
expect(await autocomplete.isOpen()).toBeFalse();
});
it('should emit new value when selected options changed', () => {
it('should emit new value when selected options changed', async () => {
const optionsChangedSpy = spyOn(component.optionsChanged, 'emit');
addNewOption('option1');
expect(optionsChangedSpy).toHaveBeenCalledOnceWith([{value: 'option1'}]);
expect(getChipList().length).toBe(1);
expect(getChipValue(0)).toBe('option1');
expect((await getChipList()).length).toBe(1);
expect(await getChipValue(0)).toBe('option1');
});
it('should clear the input after a new value is added', () => {
@@ -248,7 +259,7 @@ describe('SearchChipAutocompleteInputComponent', () => {
expect(getInput().placeholder).toBe(component.placeholder);
});
it('should reset all options when onReset$ event is emitted', () => {
it('should reset all options when onReset$ event is emitted', async () => {
addNewOption('option1');
addNewOption('option2');
const optionsChangedSpy = spyOn(component.optionsChanged, 'emit');
@@ -256,11 +267,11 @@ describe('SearchChipAutocompleteInputComponent', () => {
fixture.detectChanges();
expect(optionsChangedSpy).toHaveBeenCalledOnceWith([]);
expect(getChipList()).toEqual([]);
expect((await getChipList())).toEqual([]);
expect(component.selectedOptions).toEqual([]);
});
it('should remove option upon clicking remove button', () => {
it('should remove option upon clicking remove button', async () => {
addNewOption('option1');
addNewOption('option2');
const optionsChangedSpy = spyOn(component.optionsChanged, 'emit');
@@ -269,16 +280,16 @@ describe('SearchChipAutocompleteInputComponent', () => {
fixture.detectChanges();
expect(optionsChangedSpy).toHaveBeenCalledOnceWith([{value: 'option2'}]);
expect(getChipList().length).toEqual(1);
expect((await getChipList()).length).toEqual(1);
});
it('should show full category path when fullPath provided', () => {
it('should show full category path when fullPath provided', async () => {
component.filteredOptions = [{id: 'test-id', value: 'test-value', fullPath: 'test-full-path'}];
enterNewInputValue('test-value');
const matOption = fixture.debugElement.query(By.css('.mat-option span')).nativeElement;
fixture.detectChanges();
expect(matOption.innerHTML).toEqual(' test-full-path ');
enterNewInputValue('test-value');
const matOption = fixture.debugElement.query(By.css('.adf-search-chip-autocomplete-added-option')).nativeElement;
expect(matOption.textContent).toEqual(' test-full-path ');
});
it('should emit input value when input changed', async () => {

View File

@@ -22,10 +22,15 @@ import { ContentTestingModule } from '../../../../testing/content.testing.module
import { SearchDateRangeComponent } from './search-date-range.component';
import { addDays, endOfToday, format, parse, startOfYesterday, subDays } from 'date-fns';
import { Validators } from '@angular/forms';
import { HarnessLoader } from '@angular/cdk/testing';
import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed';
import { MatCalendarHarness, MatDatepickerToggleHarness } from '@angular/material/datepicker/testing';
import { MatRadioButtonHarness } from '@angular/material/radio/testing';
describe('SearchDateRangeComponent', () => {
let component: SearchDateRangeComponent;
let fixture: ComponentFixture<SearchDateRangeComponent>;
let loader: HarnessLoader;
const startDateSampleValue = parse('05-Jun-23', 'dd-MMM-yy', new Date());
const endDateSampleValue = parse('07-Jun-23', 'dd-MMM-yy', new Date());
@@ -51,6 +56,7 @@ describe('SearchDateRangeComponent', () => {
betweenStartDate: null,
betweenEndDate: null
});
loader = TestbedHarnessEnvironment.documentRootLoader(fixture);
fixture.detectChanges();
});
@@ -179,12 +185,15 @@ describe('SearchDateRangeComponent', () => {
component.form.controls.dateRangeType.setValue(component.DateRangeType.BETWEEN);
component.maxDate = 'today';
fixture.detectChanges();
getElementBySelector('[data-automation-id="date-range-between-datepicker-toggle"]').click();
fixture.detectChanges();
const datePicker = await loader.getHarness(MatDatepickerToggleHarness);
await datePicker.openCalendar();
const calendar = await loader.getHarness(MatCalendarHarness);
const afterDate = format(addDays(new Date(), 1), 'MMM d, yyyy');
const afterDateItem = document.querySelector(`.mat-calendar-body-cell[aria-label="${afterDate}"]`);
expect(afterDateItem.getAttribute('aria-disabled')).toBeTruthy();
const cell = await calendar.getCells({ disabled: true });
expect(await cell[0].getAriaLabel()).toEqual(afterDate);
});
it('should emit valid as false when form is invalid', () => {
@@ -216,7 +225,7 @@ describe('SearchDateRangeComponent', () => {
expect(component.valid.emit).toHaveBeenCalledWith(true);
});
it('should not emit values when form is invalid', () => {
it('should not emit values when form is invalid', async () => {
spyOn(component.changed, 'emit');
let value = {
dateRangeType: component.DateRangeType.IN_LAST,
@@ -225,8 +234,8 @@ describe('SearchDateRangeComponent', () => {
betweenStartDate: undefined,
betweenEndDate: undefined
};
let dateRangeTypeRadioButton = getElementBySelector('[data-automation-id="date-range-in-last"] .mat-radio-input');
dateRangeTypeRadioButton.click();
let dateRangeTypeRadioButton = await loader.getHarness(MatRadioButtonHarness.with({ selector: '[data-automation-id="date-range-in-last"]' }));
await dateRangeTypeRadioButton.check();
selectDropdownOption('date-range-in-last-option-weeks');
enterValueInInputFieldAndTriggerEvent('date-range-in-last-input', '');
expect(component.changed.emit).not.toHaveBeenCalledWith(value);
@@ -246,13 +255,13 @@ describe('SearchDateRangeComponent', () => {
betweenStartDate: '',
betweenEndDate: ''
};
dateRangeTypeRadioButton = getElementBySelector('[data-automation-id="date-range-between"] .mat-radio-input');
dateRangeTypeRadioButton.click();
dateRangeTypeRadioButton = await loader.getHarness(MatRadioButtonHarness.with({ selector: '[data-automation-id="date-range-between"]' }));
await dateRangeTypeRadioButton.check();
fixture.detectChanges();
expect(component.changed.emit).not.toHaveBeenCalledWith(value);
});
it('should emit values when form is valid', () => {
it('should emit values when form is valid', async () => {
spyOn(component.changed, 'emit');
let value = {
dateRangeType: component.DateRangeType.IN_LAST,
@@ -261,8 +270,8 @@ describe('SearchDateRangeComponent', () => {
betweenStartDate: null,
betweenEndDate: null
};
let dateRangeTypeRadioButton = getElementBySelector('[data-automation-id="date-range-in-last"] .mat-radio-input');
dateRangeTypeRadioButton.click();
let dateRangeTypeRadioButton = await loader.getHarness(MatRadioButtonHarness.with({ selector: '[data-automation-id="date-range-in-last"]' }));
await dateRangeTypeRadioButton.check();
selectDropdownOption('date-range-in-last-option-weeks');
enterValueInInputFieldAndTriggerEvent('date-range-in-last-input', '5');
fixture.detectChanges();
@@ -283,8 +292,8 @@ describe('SearchDateRangeComponent', () => {
betweenStartDate: startDateSampleValue,
betweenEndDate: endDateSampleValue
};
dateRangeTypeRadioButton = getElementBySelector('[data-automation-id="date-range-between"] .mat-radio-input');
dateRangeTypeRadioButton.click();
dateRangeTypeRadioButton = await loader.getHarness(MatRadioButtonHarness.with({ selector: '[data-automation-id="date-range-between"]' }));
await dateRangeTypeRadioButton.check();
component.betweenStartDateFormControl.setValue(startDateSampleValue);
component.betweenEndDateFormControl.setValue(endDateSampleValue);
fixture.detectChanges();

View File

@@ -18,7 +18,6 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { ContentTestingModule } from '../../../../testing/content.testing.module';
import { TranslateModule } from '@ngx-translate/core';
import { By } from '@angular/platform-browser';
import { SearchQueryBuilderService } from '../../../services/search-query-builder.service';
import { SearchFilterList } from '../../../models/search-filter-list.model';
import { FacetField } from '../../../models/facet-field.interface';
@@ -26,12 +25,16 @@ import { SearchFacetFiltersService } from '../../../services/search-facet-filter
import { NO_ERRORS_SCHEMA, SimpleChange } from '@angular/core';
import { SearchFacetTabbedContentComponent } from './search-facet-tabbed-content.component';
import { of } from 'rxjs';
import { HarnessLoader } from '@angular/cdk/testing';
import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed';
import { MatTabGroupHarness, MatTabHarness } from '@angular/material/tabs/testing';
describe('SearchFacetTabbedContentComponent', () => {
let component: SearchFacetTabbedContentComponent;
let fixture: ComponentFixture<SearchFacetTabbedContentComponent>;
let queryBuilder: SearchQueryBuilderService;
let searchFacetService: SearchFacetFiltersService;
let loader: HarnessLoader;
beforeEach(() => {
TestBed.configureTestingModule({
@@ -39,6 +42,7 @@ describe('SearchFacetTabbedContentComponent', () => {
schemas: [NO_ERRORS_SCHEMA]
});
fixture = TestBed.createComponent(SearchFacetTabbedContentComponent);
loader = TestbedHarnessEnvironment.loader(fixture);
component = fixture.componentInstance;
queryBuilder = TestBed.inject(SearchQueryBuilderService);
searchFacetService = TestBed.inject(SearchFacetFiltersService);
@@ -67,18 +71,10 @@ describe('SearchFacetTabbedContentComponent', () => {
*
* @returns list of native elements
*/
function getTabs(): HTMLDivElement[] {
return fixture.debugElement.queryAll(By.css('.mat-tab-label-content')).map((element) => element.nativeElement);
}
async function getTabs(): Promise<MatTabHarness[]> {
const tabGroup = await loader.getHarness(MatTabGroupHarness);
/**
* Set selected tab
*
* @param tabIndex index of the tab
*/
function changeTab(tabIndex: number) {
getTabs()[tabIndex].click();
fixture.detectChanges();
return tabGroup.getTabs();
}
/**
@@ -107,20 +103,22 @@ describe('SearchFacetTabbedContentComponent', () => {
triggerComponentChanges();
}
it('should display 2 tabs with specific labels', () => {
const tabLabels = getTabs();
it('should display 2 tabs with specific labels', async () => {
const tabLabels = await getTabs();
expect(tabLabels.length).toBe(2);
expect(tabLabels[0].innerText).toBe(component.tabbedFacet.facets['field'].label);
expect(tabLabels[1].innerText).toBe(component.tabbedFacet.facets['field2'].label);
expect(await tabLabels[0].getLabel()).toBe(component.tabbedFacet.facets['field'].label);
expect(await tabLabels[1].getLabel()).toBe(component.tabbedFacet.facets['field2'].label);
});
it('should display creator tab as active initially and allow navigation', () => {
let activeTabLabel = fixture.debugElement.query(By.css('.mat-tab-label-active .mat-tab-label-content')).nativeElement.innerText;
expect(activeTabLabel).toBe(component.tabbedFacet.facets['field'].label);
it('should display creator tab as active initially and allow navigation', async () => {
let tabs = await getTabs();
expect(await tabs[0].isSelected()).toBeTrue();
expect(await tabs[1].isSelected()).toBeFalse();
changeTab(1);
activeTabLabel = fixture.debugElement.query(By.css('.mat-tab-label-active .mat-tab-label-content')).nativeElement.innerText;
expect(activeTabLabel).toBe(component.tabbedFacet.facets['field2'].label);
await tabs[1].select();
expect(await tabs[0].isSelected()).toBeFalse();
expect(await tabs[1].isSelected()).toBeTrue();
});
it('should create empty selected options for each tab initially', () => {

View File

@@ -34,14 +34,19 @@ import {
stepThree,
stepTwo
} from '../../../mock';
import { getAllMenus } from '../search-filter/search-filter.component.spec';
import { AppConfigService } from '@alfresco/adf-core';
import { MatButtonHarness } from '@angular/material/button/testing';
import { HarnessLoader } from '@angular/cdk/testing';
import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed';
import { MatCheckboxHarness } from '@angular/material/checkbox/testing';
import { MatChipHarness } from '@angular/material/chips/testing';
describe('SearchFilterChipsComponent', () => {
let fixture: ComponentFixture<SearchFilterChipsComponent>;
let searchFacetFiltersService: SearchFacetFiltersService;
let queryBuilder: SearchQueryBuilderService;
let appConfigService: AppConfigService;
let loader: HarnessLoader;
beforeEach(() => {
TestBed.configureTestingModule({
@@ -54,9 +59,10 @@ describe('SearchFilterChipsComponent', () => {
appConfigService = TestBed.inject(AppConfigService);
searchFacetFiltersService = TestBed.inject(SearchFacetFiltersService);
fixture = TestBed.createComponent(SearchFilterChipsComponent);
loader = TestbedHarnessEnvironment.documentRootLoader(fixture);
});
it('should fetch facet fields from response payload and show the already checked items', () => {
it('should fetch facet fields from response payload and show the already checked items', async () => {
spyOn(queryBuilder, 'execute').and.stub();
queryBuilder.config = {
categories: [],
@@ -93,10 +99,8 @@ describe('SearchFilterChipsComponent', () => {
fixture.detectChanges();
const facetChip = fixture.debugElement.query(By.css('[data-automation-id="search-fact-chip-f1"] mat-chip'));
facetChip.triggerEventHandler('click', { stopPropagation: () => null });
fixture.detectChanges();
const facetChip = await loader.getHarness(MatChipHarness.with({ selector: '[data-automation-id="search-filter-chip-f1"]' }));
await (await facetChip.host()).click();
const facetField: SearchFacetFieldComponent = fixture.debugElement.query(By.css('adf-search-facet-field')).componentInstance;
facetField.selectFacetBucket({ field: 'f1', label: 'f1' }, searchFacetFiltersService.responseFacets[0].buckets.items[1]);
@@ -106,7 +110,7 @@ describe('SearchFilterChipsComponent', () => {
expect(searchFacetFiltersService.responseFacets[0].buckets.items[0].checked).toEqual(true, 'should show the already checked item');
});
it('should fetch facet fields from response payload and show the newly checked items', () => {
it('should fetch facet fields from response payload and show the newly checked items', async () => {
spyOn(queryBuilder, 'execute').and.stub();
queryBuilder.config = {
categories: [],
@@ -142,10 +146,8 @@ describe('SearchFilterChipsComponent', () => {
};
fixture.detectChanges();
const facetChip = fixture.debugElement.query(By.css('[data-automation-id="search-fact-chip-f1"] mat-chip'));
facetChip.triggerEventHandler('click', { stopPropagation: () => null });
fixture.detectChanges();
const facetChip = await loader.getHarness(MatChipHarness.with({ selector: '[data-automation-id="search-filter-chip-f1"]' }));
await (await facetChip.host()).click();
const facetField: SearchFacetFieldComponent = fixture.debugElement.query(By.css('adf-search-facet-field')).componentInstance;
facetField.selectFacetBucket({ field: 'f1', label: 'f1' }, searchFacetFiltersService.responseFacets[0].buckets.items[1]);
@@ -155,7 +157,7 @@ describe('SearchFilterChipsComponent', () => {
expect(searchFacetFiltersService.responseFacets[0].buckets.items[1].checked).toEqual(true, 'should show the newly checked item');
});
it('should show buckets with 0 values when there are no facet fields on the response payload', () => {
it('should show buckets with 0 values when there are no facet fields on the response payload', async () => {
spyOn(queryBuilder, 'execute').and.stub();
queryBuilder.config = {
categories: [],
@@ -182,10 +184,8 @@ describe('SearchFilterChipsComponent', () => {
};
fixture.detectChanges();
const facetChip = fixture.debugElement.query(By.css('[data-automation-id="search-fact-chip-f1"] mat-chip'));
facetChip.triggerEventHandler('click', { stopPropagation: () => null });
fixture.detectChanges();
const facetChip = await loader.getHarness(MatChipHarness.with({ selector: '[data-automation-id="search-filter-chip-f1"]' }));
await (await facetChip.host()).click();
const facetField: SearchFacetFieldComponent = fixture.debugElement.query(By.css('adf-search-facet-field')).componentInstance;
facetField.selectFacetBucket({ field: 'f1', label: 'f1' }, searchFacetFiltersService.responseFacets[0].buckets.items[1]);
@@ -195,7 +195,7 @@ describe('SearchFilterChipsComponent', () => {
expect(searchFacetFiltersService.responseFacets[0].buckets.items[1].count).toEqual(0);
});
it('should update query builder upon resetting selected queries', () => {
it('should update query builder upon resetting selected queries', async () => {
spyOn(queryBuilder, 'update').and.stub();
spyOn(queryBuilder, 'removeUserFacetBucket').and.callThrough();
@@ -211,9 +211,9 @@ describe('SearchFilterChipsComponent', () => {
fixture.detectChanges();
const facetChip = fixture.debugElement.query(By.css(`[data-automation-id="search-fact-chip-query-response"] mat-chip`));
facetChip.triggerEventHandler('click', { stopPropagation: () => null });
fixture.detectChanges();
const facetChip = await loader.getHarness(MatChipHarness.with({ selector: '[data-automation-id="search-filter-chip-query response"]' }));
await (await facetChip.host()).click();
const facetField: SearchFacetFieldComponent = fixture.debugElement.query(By.css('adf-search-facet-field')).componentInstance;
facetField.resetSelectedBuckets(queryResponse);
@@ -232,9 +232,8 @@ describe('SearchFilterChipsComponent', () => {
appConfigService.config.search = { categories: disabledCategories };
queryBuilder.resetToDefaults();
fixture.detectChanges();
await fixture.whenStable();
const chips = fixture.debugElement.queryAll(By.css('mat-chip'));
const chips = await loader.getAllHarnesses(MatChipHarness);
expect(chips.length).toBe(0);
});
@@ -242,10 +241,7 @@ describe('SearchFilterChipsComponent', () => {
appConfigService.config.search = { categories: simpleCategories };
queryBuilder.resetToDefaults();
fixture.detectChanges();
await fixture.whenStable();
const chips = fixture.debugElement.queryAll(By.css('mat-chip'));
const chips = await loader.getAllHarnesses(MatChipHarness);
expect(chips.length).toBe(2);
const titleElements = fixture.debugElement.queryAll(By.css('.adf-search-filter-placeholder'));
@@ -257,9 +253,7 @@ describe('SearchFilterChipsComponent', () => {
appConfigService.config.search = searchFilter;
queryBuilder.resetToDefaults();
fixture.detectChanges();
await fixture.whenStable();
let chips = fixture.debugElement.queryAll(By.css('mat-chip'));
let chips = await loader.getAllHarnesses(MatChipHarness);
expect(chips.length).toBe(6);
fixture.detectChanges();
@@ -272,14 +266,12 @@ describe('SearchFilterChipsComponent', () => {
expect(queryBuilder.update).toHaveBeenCalled();
queryBuilder.executed.next(mockSearchResult);
await fixture.whenStable();
fixture.detectChanges();
chips = fixture.debugElement.queryAll(By.css('mat-chip'));
chips = await loader.getAllHarnesses(MatChipHarness);
expect(chips.length).toBe(8);
});
it('should show the long facet options list with pagination', () => {
it('should show the long facet options list with pagination', async () => {
const field = `[data-automation-id="search-field-Size facet queries"]`;
appConfigService.config.search = searchFilter;
queryBuilder.resetToDefaults();
@@ -293,58 +285,67 @@ describe('SearchFilterChipsComponent', () => {
searchChip.triggerEventHandler('click', { stopPropagation: () => null });
fixture.detectChanges();
let sizes = getAllMenus(`${field} mat-checkbox`, fixture);
expect(sizes).toEqual(stepOne);
let sizes = await loader.getAllHarnesses(MatCheckboxHarness.with({ selector: '.adf-search-filter-facet-checkbox' }));
stepOne.forEach(async (item, index) => {
expect(await sizes[index].getLabelText()).toEqual(item);
});
let moreButton = fixture.debugElement.query(By.css(`${field} button[title="SEARCH.FILTER.ACTIONS.SHOW-MORE"]`));
let lessButton = fixture.debugElement.query(By.css(`${field} button[title="SEARCH.FILTER.ACTIONS.SHOW-LESS"]`));
expect(lessButton).toEqual(null);
expect(moreButton).toBeDefined();
expect(moreButton).not.toEqual(null);
moreButton.triggerEventHandler('click', {});
fixture.detectChanges();
sizes = getAllMenus(`${field} mat-checkbox`, fixture);
expect(sizes).toEqual(stepTwo);
sizes = await loader.getAllHarnesses(MatCheckboxHarness.with({ selector: '.adf-search-filter-facet-checkbox' }));
stepTwo.forEach(async (item, index) => {
expect(await sizes[index].getLabelText()).toEqual(item);
});
moreButton = fixture.debugElement.query(By.css(`${field} button[title="SEARCH.FILTER.ACTIONS.SHOW-MORE"]`));
lessButton = fixture.debugElement.query(By.css(`${field} button[title="SEARCH.FILTER.ACTIONS.SHOW-LESS"]`));
expect(lessButton).toBeDefined();
expect(moreButton).toBeDefined();
expect(moreButton).not.toEqual(null);
moreButton.triggerEventHandler('click', {});
fixture.detectChanges();
sizes = getAllMenus(`${field} mat-checkbox`, fixture);
expect(sizes).toEqual(stepThree);
sizes = await loader.getAllHarnesses(MatCheckboxHarness.with({ selector: '.adf-search-filter-facet-checkbox' }));
stepThree.forEach(async (item, index) => {
expect(await sizes[index].getLabelText()).toEqual(item);
});
moreButton = fixture.debugElement.query(By.css(`${field} button[title="SEARCH.FILTER.ACTIONS.SHOW-MORE"]`));
lessButton = fixture.debugElement.query(By.css(`${field} button[title="SEARCH.FILTER.ACTIONS.SHOW-LESS"]`));
expect(lessButton).toBeDefined();
expect(lessButton).not.toEqual(null);
expect(moreButton).toEqual(null);
lessButton.triggerEventHandler('click', {});
fixture.detectChanges();
sizes = getAllMenus(`${field} mat-checkbox`, fixture);
expect(sizes).toEqual(stepTwo);
sizes = await loader.getAllHarnesses(MatCheckboxHarness.with({ selector: '.adf-search-filter-facet-checkbox' }));
stepTwo.forEach(async (item, index) => {
expect(await sizes[index].getLabelText()).toEqual(item);
});
moreButton = fixture.debugElement.query(By.css(`${field} button[title="SEARCH.FILTER.ACTIONS.SHOW-MORE"]`));
lessButton = fixture.debugElement.query(By.css(`${field} button[title="SEARCH.FILTER.ACTIONS.SHOW-LESS"]`));
expect(lessButton).toBeDefined();
expect(moreButton).toBeDefined();
expect(lessButton).not.toEqual(null);
expect(moreButton).not.toEqual(null);
lessButton.triggerEventHandler('click', {});
fixture.detectChanges();
sizes = getAllMenus(`${field} mat-checkbox`, fixture);
expect(sizes).toEqual(stepOne);
sizes = await loader.getAllHarnesses(MatCheckboxHarness.with({ selector: '.adf-search-filter-facet-checkbox' }));
stepOne.forEach(async (item, index) => {
expect(await sizes[index].getLabelText()).toEqual(item);
});
moreButton = fixture.debugElement.query(By.css(`${field} button[title="SEARCH.FILTER.ACTIONS.SHOW-MORE"]`));
lessButton = fixture.debugElement.query(By.css(`${field} button[title="SEARCH.FILTER.ACTIONS.SHOW-LESS"]`));
expect(lessButton).toEqual(null);
expect(moreButton).toBeDefined();
expect(moreButton).not.toEqual(null);
});
it('should not show facets if filter is not available', () => {
@@ -363,7 +364,7 @@ describe('SearchFilterChipsComponent', () => {
expect(facetElement).toEqual(null);
});
it('should search the facets options and select it', () => {
it('should search the facets options and select it', async () => {
const field = `[data-automation-id="search-field-Size facet queries"]`;
appConfigService.config.search = searchFilter;
queryBuilder.resetToDefaults();
@@ -382,30 +383,30 @@ describe('SearchFilterChipsComponent', () => {
inputElement.nativeElement.dispatchEvent(new Event('input'));
fixture.detectChanges();
let filteredMenu = getAllMenus(`${field} mat-checkbox`, fixture);
expect(filteredMenu).toEqual(['Extra Small (10239)']);
let filteredMenu = await loader.getAllHarnesses(MatCheckboxHarness.with({ selector: '.adf-search-filter-facet-checkbox' }));
expect(filteredMenu.length).toBe(1);
expect(await filteredMenu[0].getLabelText()).toEqual('Extra Small (10239)');
inputElement.nativeElement.value = 'my';
inputElement.nativeElement.dispatchEvent(new Event('input'));
fixture.detectChanges();
filteredMenu = getAllMenus(`${field} mat-checkbox`, fixture);
expect(filteredMenu).toEqual(filteredResult);
filteredMenu = await loader.getAllHarnesses(MatCheckboxHarness.with({ selector: '.adf-search-filter-facet-checkbox' }));
filteredResult.forEach(async (item, index) => {
expect(await filteredMenu[index].getLabelText()).toEqual(item);
});
const clearButton = fixture.debugElement.query(By.css(`${field} mat-form-field button`));
clearButton.triggerEventHandler('click', {});
fixture.detectChanges();
const clearButton = await loader.getHarness(MatButtonHarness.with({selector: '[title="SEARCH.FILTER.BUTTONS.CLEAR"]' }));
await clearButton.click();
filteredMenu = getAllMenus(`${field} mat-checkbox`, fixture);
expect(filteredMenu).toEqual(stepOne);
filteredMenu = await loader.getAllHarnesses(MatCheckboxHarness.with({ selector: '.adf-search-filter-facet-checkbox' }));
stepOne.forEach(async (item, index) => {
expect(await filteredMenu[index].getLabelText()).toEqual(item);
});
const firstOption = fixture.debugElement.query(By.css(`${field} mat-checkbox`));
firstOption.triggerEventHandler('change', { checked: true });
fixture.detectChanges();
const checkedOption = fixture.debugElement.query(By.css(`${field} mat-checkbox.mat-checkbox-checked`));
expect(checkedOption.nativeElement.innerText).toEqual('Extra Small (10239)');
await filteredMenu[0].check();
expect(await filteredMenu[0].getLabelText()).toEqual('Extra Small (10239)');
expect(queryBuilder.update).toHaveBeenCalledTimes(1);
});

View File

@@ -31,12 +31,16 @@ import { EMPTY, of, throwError } from 'rxjs';
import { DebugElement } from '@angular/core';
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
import { MatListModule } from '@angular/material/list';
import { HarnessLoader } from '@angular/cdk/testing';
import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed';
import { MatProgressSpinnerHarness } from '@angular/material/progress-spinner/testing';
describe('TagsCreatorComponent', () => {
let fixture: ComponentFixture<TagsCreatorComponent>;
let component: TagsCreatorComponent;
let tagService: TagService;
let notificationService: NotificationService;
let loader: HarnessLoader;
beforeEach(() => {
TestBed.configureTestingModule({
@@ -76,6 +80,7 @@ describe('TagsCreatorComponent', () => {
});
fixture = TestBed.createComponent(TagsCreatorComponent);
loader = TestbedHarnessEnvironment.loader(fixture);
component = fixture.componentInstance;
tagService = TestBed.inject(TagService);
notificationService = TestBed.inject(NotificationService);
@@ -725,34 +730,37 @@ describe('TagsCreatorComponent', () => {
*
* @returns debug element
*/
function getSpinner(): DebugElement {
return fixture.debugElement.query(By.css(`.mat-progress-spinner`));
async function getSpinner(): Promise<MatProgressSpinnerHarness> {
const progressSpinner = await loader.getHarnessOrNull(MatProgressSpinnerHarness);
return progressSpinner;
}
it('should be displayed when existing tags are loading', fakeAsync(() => {
it('should be displayed when existing tags are loading', fakeAsync(async () => {
typeTag('tag', 0);
component.tagNameControl.markAsTouched();
fixture.detectChanges();
const spinner = getSpinner();
const spinner = await getSpinner();
expect(spinner).toBeTruthy();
discardPeriodicTasks();
flush();
}));
it('should not be displayed when existing tags stopped loading', fakeAsync(() => {
it('should not be displayed when existing tags stopped loading', fakeAsync(async () => {
typeTag('tag');
const spinner = getSpinner();
const spinner = await getSpinner();
expect(spinner).toBeFalsy();
}));
it('should have correct diameter', fakeAsync(() => {
it('should have correct diameter', fakeAsync(async () => {
typeTag('tag', 0);
const spinner = getSpinner();
expect(spinner.componentInstance.diameter).toBe(50);
const spinner = await getSpinner();
expect((await (await spinner.host()).getDimensions()).width).toBe(50);
expect((await (await spinner.host()).getDimensions()).height).toBe(50);
discardPeriodicTasks();
flush();

View File

@@ -134,7 +134,7 @@ describe('TreeViewComponent', () => {
expect(element.querySelector('#fake-child-name-tree-child-node')).not.toBeNull();
expect(element.querySelector('#fake-second-name-tree-child-node')).not.toBeNull();
expect(element.querySelectorAll('mat-tree-node').length).toBe(4);
expect(element.querySelectorAll('.adf-tree-view-node').length).toBe(4);
});
it('should throw a nodeClicked event when a node is clicked', (done) => {
@@ -153,13 +153,13 @@ describe('TreeViewComponent', () => {
it('should change the icon of the opened folders', async () => {
const rootFolderButton = element.querySelector<HTMLButtonElement>('#button-fake-node-name');
expect(rootFolderButton).not.toBeNull();
expect(element.querySelector('#button-fake-node-name .mat-icon').textContent.trim()).toBe('folder');
expect(element.querySelector('#button-fake-node-name .adf-tree-view-icon').textContent.trim()).toBe('folder');
rootFolderButton.click();
fixture.detectChanges();
await fixture.whenStable();
expect(element.querySelector('#button-fake-node-name .mat-icon').textContent.trim()).toBe('folder_open');
expect(element.querySelector('#button-fake-node-name .adf-tree-view-icon').textContent.trim()).toBe('folder_open');
});
it('should show the subfolders of a subfolder if there are any', async () => {
@@ -197,7 +197,7 @@ describe('TreeViewComponent', () => {
fixture.detectChanges();
await fixture.whenStable();
expect(element.querySelector('#button-fake-node-name .mat-icon').textContent.trim()).toBe('folder');
expect(element.querySelector('#button-fake-node-name .adf-tree-view-icon').textContent.trim()).toBe('folder');
expect(element.querySelector('#fake-child-name-tree-child-node')).toBeNull();
expect(element.querySelector('#fake-second-name-tree-child-node')).toBeNull();
});

View File

@@ -72,14 +72,16 @@
[id]="node.id"
[checked]="descendantsAllSelected(node)"
[indeterminate]="descendantsPartiallySelected(node)"
(change)="onNodeSelected(node)">
(change)="onNodeSelected(node)"
data-automation-id="has-children-node-checkbox">
</mat-checkbox>
<ng-template #noChildrenNodeCheckbox>
<mat-checkbox
color="primary"
[id]="node.id"
[checked]="treeNodesSelection.isSelected(node)"
(change)="onNodeSelected(node)">
(change)="onNodeSelected(node)"
data-automation-id="no-children-node-checkbox">
</mat-checkbox>
</ng-template>
</ng-container>

View File

@@ -33,13 +33,18 @@ import { TreeServiceMock } from '../mock/tree-service.service.mock';
import { By } from '@angular/platform-browser';
import { SelectionChange } from '@angular/cdk/collections';
import { DebugElement } from '@angular/core';
import { HarnessLoader } from '@angular/cdk/testing';
import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed';
import { MatProgressSpinnerHarness } from '@angular/material/progress-spinner/testing';
import { MatCheckboxHarness } from '@angular/material/checkbox/testing';
describe('TreeComponent', () => {
let fixture: ComponentFixture<TreeComponent<TreeNode>>;
let component: TreeComponent<TreeNode>;
let userPreferenceService: UserPreferencesService;
let loader: HarnessLoader;
const composeNodeSelector = (nodeId: string) => `.mat-tree-node[data-automation-id="node_${nodeId}"]`;
const composeNodeSelector = (nodeId: string) => `[data-automation-id="node_${nodeId}"]`;
const getNode = (nodeId: string) => fixture.debugElement.query(By.css(composeNodeSelector(nodeId)));
@@ -49,12 +54,13 @@ describe('TreeComponent', () => {
const getNodePadding = (nodeId: string) => parseInt(getComputedStyle(getNode(nodeId).nativeElement).paddingLeft, 10);
const getNodeSpinner = (nodeId: string) => fixture.nativeElement.querySelector(`${composeNodeSelector(nodeId)} .mat-progress-spinner`);
const getNodeSpinner = async (nodeId: string) => loader.getHarnessOrNull(MatProgressSpinnerHarness.with({ ancestor: composeNodeSelector(nodeId) }));
const getExpandCollapseBtn = (nodeId: string) => fixture.nativeElement.querySelector(`${composeNodeSelector(nodeId)} .adf-icon`);
const tickCheckbox = (index: number) => {
const nodeCheckboxes = fixture.debugElement.queryAll(By.css('mat-checkbox'));
const selector = `[data-automation-id="${index === 0 ? 'has-children-node-checkbox' : 'no-children-node-checkbox'}"]`;
const nodeCheckboxes = fixture.debugElement.queryAll(By.css(selector));
nodeCheckboxes[index].nativeElement.dispatchEvent(new Event('change'));
};
@@ -73,6 +79,7 @@ describe('TreeComponent', () => {
});
fixture = TestBed.createComponent(TreeComponent);
loader = TestbedHarnessEnvironment.loader(fixture);
component = fixture.componentInstance;
userPreferenceService = TestBed.inject(UserPreferencesService);
});
@@ -126,20 +133,21 @@ describe('TreeComponent', () => {
expect(nodeLevel1Padding).toBeGreaterThan(nodeLevel0Padding);
});
it('should show a spinner for nodes that are loading subnodes', () => {
it('should show a spinner for nodes that are loading subnodes', async () => {
component.treeService.treeNodes = Array.from(treeNodesChildrenMockExpanded);
fixture.detectChanges();
component.treeService.treeControl.dataNodes[0].isLoading = true;
fixture.detectChanges();
const nodeSpinner = getNodeSpinner('testId1');
const nodeSpinner = await getNodeSpinner('testId1');
expect(nodeSpinner).not.toBeNull();
});
it('should show a spinner while the tree is loading', () => {
it('should show a spinner while the tree is loading', async () => {
fixture.detectChanges();
component.loadingRoot$ = of(true);
fixture.detectChanges();
const matSpinnerElement = fixture.nativeElement.querySelector('.adf-tree-loading-spinner-container .mat-progress-spinner');
const matSpinnerElement = await loader.getHarnessOrNull(MatProgressSpinnerHarness.with({ ancestor: '.adf-tree-loading-spinner-container' }));
expect(matSpinnerElement).not.toBeNull();
});
@@ -172,13 +180,13 @@ describe('TreeComponent', () => {
expect(getNodesSpy).toHaveBeenCalledWith('-root-', 0, 25, 'some term');
});
it('should not collapse node when loading', () => {
it('should not collapse node when loading', async () => {
component.refreshTree();
component.treeService.treeNodes[0].isLoading = true;
fixture.detectChanges();
const collapseSpy = spyOn(component.treeService, 'collapseNode');
spyOn(component.treeService.treeControl, 'isExpanded').and.returnValue(true);
getNodeSpinner(component.treeService.treeNodes[0].id).dispatchEvent(new Event('click'));
await (await ((await getNodeSpinner(component.treeService.treeNodes[0].id)).host())).click();
expect(collapseSpy).not.toHaveBeenCalled();
});
@@ -192,13 +200,13 @@ describe('TreeComponent', () => {
expect(collapseSpy).toHaveBeenCalledWith(component.treeService.treeNodes[0]);
});
it('should not expand node when loading', () => {
it('should not expand node when loading', async () => {
component.refreshTree();
component.treeService.treeNodes[0].isLoading = true;
fixture.detectChanges();
const expandSpy = spyOn(component.treeService, 'expandNode');
spyOn(component.treeService.treeControl, 'isExpanded').and.returnValue(false);
getNodeSpinner(component.treeService.treeNodes[0].id).dispatchEvent(new Event('click'));
await (await ((await getNodeSpinner(component.treeService.treeNodes[0].id)).host())).click();
expect(expandSpy).not.toHaveBeenCalled();
});
@@ -292,10 +300,11 @@ describe('TreeComponent', () => {
.toBeUndefined();
});
it('selection should be disabled by default, no checkboxes should be displayed', () => {
it('selection should be disabled by default, no checkboxes should be displayed', async () => {
component.refreshTree();
fixture.detectChanges();
const nodeCheckboxes = fixture.debugElement.queryAll(By.css('mat-checkbox'));
const nodeCheckboxes = await loader.getAllHarnesses(MatCheckboxHarness);
expect(nodeCheckboxes.length).toEqual(0);
expect(component.selectableNodes).toEqual(false);
});
@@ -305,10 +314,10 @@ describe('TreeComponent', () => {
component.selectableNodes = true;
});
it('should display checkboxes when selection is enabled', () => {
it('should display checkboxes when selection is enabled', async () => {
component.refreshTree();
fixture.detectChanges();
const nodeCheckboxes = fixture.debugElement.queryAll(By.css('mat-checkbox'));
const nodeCheckboxes = await loader.getAllHarnesses(MatCheckboxHarness);
const selectableNodes = component.treeService.treeNodes.filter((node: TreeNode) => node.nodeType !== TreeNodeType.LoadMoreNode);
expect(nodeCheckboxes.length).toEqual(selectableNodes.length);
});
@@ -336,7 +345,7 @@ describe('TreeComponent', () => {
spyOn(component.treeService, 'getSubNodes').and.returnValue(of({ pagination: {}, entries: Array.from(treeNodesChildrenMockExpanded) }));
fixture.detectChanges();
tickCheckbox(0);
tickCheckbox(2);
tickCheckbox(1);
expect(component.descendantsPartiallySelected(component.treeService.treeNodes[0])).toBeTrue();
expect(component.descendantsPartiallySelected(component.treeService.treeNodes[1])).toBeTrue();
});