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

View File

@@ -24,6 +24,10 @@ import { ContentTypeDialogComponent } from './content-type-dialog.component';
import { ContentTypeService } from './content-type.service'; import { ContentTypeService } from './content-type.service';
import { ContentTypeDialogComponentData } from './content-type-metadata.interface'; import { ContentTypeDialogComponentData } from './content-type-metadata.interface';
import { TypeEntry } from '@alfresco/js-api'; 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 = { const elementCustom: TypeEntry = {
entry: { entry: {
@@ -82,6 +86,7 @@ describe('Content Type Dialog Component', () => {
let fixture: ComponentFixture<ContentTypeDialogComponent>; let fixture: ComponentFixture<ContentTypeDialogComponent>;
let contentTypeService: ContentTypeService; let contentTypeService: ContentTypeService;
let data: ContentTypeDialogComponentData; let data: ContentTypeDialogComponentData;
let loader: HarnessLoader;
beforeEach(async () => { beforeEach(async () => {
data = { data = {
@@ -116,6 +121,7 @@ describe('Content Type Dialog Component', () => {
contentTypeService = TestBed.inject(ContentTypeService); contentTypeService = TestBed.inject(ContentTypeService);
spyOn(contentTypeService, 'getContentTypeByPrefix').and.returnValue(of(elementCustom)); spyOn(contentTypeService, 'getContentTypeByPrefix').and.returnValue(of(elementCustom));
fixture = TestBed.createComponent(ContentTypeDialogComponent); fixture = TestBed.createComponent(ContentTypeDialogComponent);
loader = TestbedHarnessEnvironment.loader(fixture);
fixture.detectChanges(); 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 () => { 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'); await (await loader.getHarness(MatExpansionPanelHarness)).toggle();
expect(showPropertyAccordion).toBeDefined();
showPropertyAccordion.click(); const table = await loader.getHarness(MatTableHarness.with({ selector: '.adf-content-type-table' }));
fixture.detectChanges();
await fixture.whenStable(); expect((await table.getRows()).length).toBe(3);
const propertyShowed: NodeList = fixture.nativeElement.querySelectorAll('.adf-content-type-table .mat-row');
expect(propertyShowed.length).toBe(3);
}); });
it('should emit true when apply is clicked', (done) => { 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 { DebugElement } from '@angular/core';
import { TranslateModule } from '@ngx-translate/core'; import { TranslateModule } from '@ngx-translate/core';
import { MatIconTestingModule } from '@angular/material/icon/testing'; 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', () => { describe('AddPermissionPanelComponent', () => {
let fixture: ComponentFixture<AddPermissionPanelComponent>; let fixture: ComponentFixture<AddPermissionPanelComponent>;
let component: AddPermissionPanelComponent; let component: AddPermissionPanelComponent;
let element: HTMLElement; let element: HTMLElement;
let searchApiService: SearchService; let searchApiService: SearchService;
let debugElement: DebugElement; let loader: HarnessLoader;
beforeEach(() => { beforeEach(() => {
TestBed.configureTestingModule({ TestBed.configureTestingModule({
@@ -42,9 +46,9 @@ describe('AddPermissionPanelComponent', () => {
] ]
}); });
fixture = TestBed.createComponent(AddPermissionPanelComponent); fixture = TestBed.createComponent(AddPermissionPanelComponent);
loader = TestbedHarnessEnvironment.loader(fixture);
searchApiService = fixture.componentRef.injector.get(SearchService); searchApiService = fixture.componentRef.injector.get(SearchService);
debugElement = fixture.debugElement;
element = fixture.nativeElement; element = fixture.nativeElement;
component = fixture.componentInstance; component = fixture.componentInstance;
@@ -55,12 +59,10 @@ describe('AddPermissionPanelComponent', () => {
fixture.destroy(); fixture.destroy();
}); });
const typeWordIntoSearchInput = (word: string): void => { const typeWordIntoSearchInput = async (word: string): Promise<void> => {
const inputDebugElement = debugElement.query(By.css('#searchInput')); const input = await loader.getHarness(MatInputHarness.with({ selector: '#searchInput' }));
inputDebugElement.nativeElement.value = word;
inputDebugElement.nativeElement.focus(); return input.setValue(word);
inputDebugElement.nativeElement.dispatchEvent(new Event('input'));
fixture.detectChanges();
}; };
it('should be able to render the component', () => { 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('#adf-add-permission-type-search')).not.toBeNull();
expect(element.querySelector('#searchInput')).not.toBeNull(); expect(element.querySelector('#searchInput')).not.toBeNull();
typeWordIntoSearchInput('a'); await typeWordIntoSearchInput('a');
await fixture.whenStable();
fixture.detectChanges();
expect(element.querySelector('#adf-add-permission-authority-results')).not.toBeNull(); expect(element.querySelector('#adf-add-permission-authority-results')).not.toBeNull();
expect(element.querySelector('#result_option_0')).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); expect(items[0].entry.id).toBe(fakeAuthorityListResult.list.entries[0].entry.id);
}); });
typeWordIntoSearchInput('a'); await typeWordIntoSearchInput('a');
await fixture.whenStable();
fixture.detectChanges();
const listElement: DebugElement = fixture.debugElement.query(By.css('#result_option_0')); const listElement: DebugElement = fixture.debugElement.query(By.css('#result_option_0'));
expect(listElement).toBeTruthy(); expect(listElement).toBeTruthy();
@@ -104,9 +102,7 @@ describe('AddPermissionPanelComponent', () => {
expect(element.querySelector('#adf-add-permission-type-search')).not.toBeNull(); expect(element.querySelector('#adf-add-permission-type-search')).not.toBeNull();
expect(element.querySelector('#searchInput')).not.toBeNull(); expect(element.querySelector('#searchInput')).not.toBeNull();
typeWordIntoSearchInput('a'); await typeWordIntoSearchInput('a');
await fixture.whenStable();
fixture.detectChanges();
expect(element.querySelector('#adf-add-permission-authority-results')).toBeTruthy(); expect(element.querySelector('#adf-add-permission-authority-results')).toBeTruthy();
expect(element.querySelector('#result_option_0')).toBeTruthy(); expect(element.querySelector('#result_option_0')).toBeTruthy();
@@ -118,10 +114,8 @@ describe('AddPermissionPanelComponent', () => {
spyOn(searchApiService, 'search').and.returnValue(of(fakeAuthorityListResult)); spyOn(searchApiService, 'search').and.returnValue(of(fakeAuthorityListResult));
expect(element.querySelector('#adf-add-permission-type-search')).not.toBeNull(); expect(element.querySelector('#adf-add-permission-type-search')).not.toBeNull();
expect(element.querySelector('#searchInput')).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(); expect(element.querySelector('#result_option_0')).toBeTruthy();
const clearButton = fixture.debugElement.query(By.css('#adf-permission-clear-input')); 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 () => { it('should remove element from selection on click when is already selected', async () => {
spyOn(searchApiService, 'search').and.returnValue(of(fakeAuthorityListResult)); spyOn(searchApiService, 'search').and.returnValue(of(fakeAuthorityListResult));
typeWordIntoSearchInput('a'); await typeWordIntoSearchInput('a');
await fixture.whenStable();
fixture.detectChanges();
let selectedUserIcon = fixture.debugElement.query(By.css('.adf-people-select-icon')); let selectedUserIcon = fixture.debugElement.query(By.css('.adf-people-select-icon'));
const listElement: DebugElement = fixture.debugElement.query(By.css('#result_option_0')); const listElement: DebugElement = fixture.debugElement.query(By.css('#result_option_0'));
@@ -162,9 +154,7 @@ describe('AddPermissionPanelComponent', () => {
spyOn(searchApiService, 'search').and.returnValue(of(fakeAuthorityListResult)); spyOn(searchApiService, 'search').and.returnValue(of(fakeAuthorityListResult));
component.selectedItems.push(fakeAuthorityListResult.list.entries[0]); component.selectedItems.push(fakeAuthorityListResult.list.entries[0]);
typeWordIntoSearchInput('a'); await typeWordIntoSearchInput('a');
await fixture.whenStable();
fixture.detectChanges();
expect(element.querySelector('#adf-add-permission-authority-results')).toBeTruthy(); expect(element.querySelector('#adf-add-permission-authority-results')).toBeTruthy();
expect(element.querySelector('#adf-add-permission-group-everyone')).toBeTruthy(); expect(element.querySelector('#adf-add-permission-group-everyone')).toBeTruthy();
@@ -177,9 +167,7 @@ describe('AddPermissionPanelComponent', () => {
spyOn(searchApiService, 'search').and.returnValue(of({ list: { entries: [] } })); spyOn(searchApiService, 'search').and.returnValue(of({ list: { entries: [] } }));
component.selectedItems.push(fakeAuthorityListResult.list.entries[0]); component.selectedItems.push(fakeAuthorityListResult.list.entries[0]);
typeWordIntoSearchInput('a'); await typeWordIntoSearchInput('a');
await fixture.whenStable();
fixture.detectChanges();
expect(element.querySelector('#adf-add-permission-authority-results')).not.toBeNull(); expect(element.querySelector('#adf-add-permission-authority-results')).not.toBeNull();
expect(element.querySelector('#adf-add-permission-group-everyone')).toBeDefined(); 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[0]);
component.selectedItems.push(fakeNameListResult.list.entries[1]); component.selectedItems.push(fakeNameListResult.list.entries[1]);
typeWordIntoSearchInput('a'); await typeWordIntoSearchInput('a');
await fixture.whenStable();
fixture.detectChanges();
expect(element.querySelector('#result_option_0 .mat-list-text')).toBeTruthy(); const list = await loader.getHarness(MatSelectionListHarness);
expect(element.querySelector('#result_option_1 .mat-list-text')).toBeTruthy(); const items = await list.getItems();
expect(element.querySelector('#result_option_0 .mat-list-text').innerHTML).not.toEqual(element.querySelector('#result_option_1 .mat-list-text').innerHTML); 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 () => { 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); expect(items[0].entry.id).toBe(fakeAuthorityListResult.list.entries[0].entry.id);
}); });
typeWordIntoSearchInput('a'); await typeWordIntoSearchInput('a');
await fixture.whenStable();
fixture.detectChanges();
let listElement: DebugElement = fixture.debugElement.query(By.css('#result_option_0')); let listElement: DebugElement = fixture.debugElement.query(By.css('#result_option_0'));
expect(listElement).not.toBeNull(); expect(listElement).not.toBeNull();
@@ -226,9 +211,7 @@ describe('AddPermissionPanelComponent', () => {
clearButton.triggerEventHandler('click', {}); clearButton.triggerEventHandler('click', {});
fixture.detectChanges(); fixture.detectChanges();
typeWordIntoSearchInput('abc'); await typeWordIntoSearchInput('abc');
await fixture.whenStable();
fixture.detectChanges();
listElement = fixture.debugElement.query(By.css('#result_option_0')); listElement = fixture.debugElement.query(By.css('#result_option_0'));
expect(listElement).not.toBeNull(); expect(listElement).not.toBeNull();

View File

@@ -16,17 +16,23 @@
*/ */
import { ComponentFixture, TestBed } from '@angular/core/testing'; 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 { By } from '@angular/platform-browser';
import { TranslateModule } from '@ngx-translate/core'; import { TranslateModule } from '@ngx-translate/core';
import { Subject } from 'rxjs'; import { Subject } from 'rxjs';
import { ContentTestingModule } from '../../../testing/content.testing.module'; import { ContentTestingModule } from '../../../testing/content.testing.module';
import { SearchChipAutocompleteInputComponent } from './search-chip-autocomplete-input.component'; import { SearchChipAutocompleteInputComponent } from './search-chip-autocomplete-input.component';
import { DebugElement } from '@angular/core'; 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', () => { describe('SearchChipAutocompleteInputComponent', () => {
let component: SearchChipAutocompleteInputComponent; let component: SearchChipAutocompleteInputComponent;
let fixture: ComponentFixture<SearchChipAutocompleteInputComponent>; let fixture: ComponentFixture<SearchChipAutocompleteInputComponent>;
let loader: HarnessLoader;
const onResetSubject = new Subject<void>(); const onResetSubject = new Subject<void>();
beforeEach(() => { beforeEach(() => {
@@ -39,6 +45,7 @@ describe('SearchChipAutocompleteInputComponent', () => {
}); });
fixture = TestBed.createComponent(SearchChipAutocompleteInputComponent); fixture = TestBed.createComponent(SearchChipAutocompleteInputComponent);
loader = TestbedHarnessEnvironment.loader(fixture);
component = fixture.componentInstance; component = fixture.componentInstance;
component.onReset$ = onResetSubject.asObservable(); component.onReset$ = onResetSubject.asObservable();
component.autocompleteOptions = [{value: 'option1'}, {value: 'option2'}]; component.autocompleteOptions = [{value: 'option1'}, {value: 'option2'}];
@@ -85,8 +92,9 @@ describe('SearchChipAutocompleteInputComponent', () => {
* *
* @returns list of chips * @returns list of chips
*/ */
function getChipList(): MatChip[] { async function getChipList(): Promise<MatChipHarness[]> {
return fixture.debugElement.queryAll(By.css('mat-chip')).map((chip) => chip.nativeElement); const harness = await loader.getHarness(MatChipListHarness);
return harness.getChips();
} }
/** /**
@@ -95,8 +103,9 @@ describe('SearchChipAutocompleteInputComponent', () => {
* @param index index of the chip * @param index index of the chip
* @returns chip value * @returns chip value
*/ */
function getChipValue(index: number): string { async function getChipValue(index: number): Promise<string> {
return fixture.debugElement.queryAll(By.css('mat-chip span')).map((chip) => chip.nativeElement)[index].innerText; const chipList = await getChipList();
return chipList[index].getText();
} }
/** /**
@@ -104,8 +113,9 @@ describe('SearchChipAutocompleteInputComponent', () => {
* *
* @returns list of debug elements * @returns list of debug elements
*/ */
function getOptionElements(): DebugElement[] { async function getOptionElements(): Promise<MatOptionHarness[]> {
return fixture.debugElement.queryAll(By.css('mat-option')); 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')); 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('test');
addNewOption('option1'); addNewOption('option1');
expect(getChipList().length).toBe(1); expect((await getChipList()).length).toBe(1);
expect(getChipValue(0)).toBe('option1'); 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; component.allowOnlyPredefinedValues = false;
addNewOption('test'); addNewOption('test');
addNewOption('option1'); addNewOption('option1');
expect(getChipList().length).toBe(2); expect((await getChipList()).length).toBe(2);
expect(getChipValue(0)).toBe('test'); 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; component.allowOnlyPredefinedValues = false;
const option = 'abc'; const option = 'abc';
component.formatChipValue = (value) => value.replace('.', ''); component.formatChipValue = (value) => value.replace('.', '');
addNewOption(`.${option}`); addNewOption(`.${option}`);
expect(getChipList().length).toBe(1); expect((await getChipList()).length).toBe(1);
expect(getChipValue(0)).toBe(option); expect(await getChipValue(0)).toBe(option);
}); });
it('should add new option upon clicking on option from autocomplete', async () => { it('should add new option upon clicking on option from autocomplete', async () => {
@@ -148,15 +158,15 @@ describe('SearchChipAutocompleteInputComponent', () => {
await fixture.whenStable(); await fixture.whenStable();
fixture.detectChanges(); fixture.detectChanges();
const matOptions = getOptionElements(); const matOptions = await getOptionElements();
expect(matOptions.length).toBe(2); expect(matOptions.length).toBe(2);
const optionToClick = matOptions[0].nativeElement as HTMLElement; const optionToClick = matOptions[0];
optionToClick.click(); await optionToClick.click();
expect(optionsChangedSpy).toHaveBeenCalledOnceWith([{value: 'option1'}]); expect(optionsChangedSpy).toHaveBeenCalledOnceWith([{value: 'option1'}]);
expect(component.selectedOptions).toEqual([{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 () => { it('should apply class to already selected options', async () => {
@@ -192,20 +202,20 @@ describe('SearchChipAutocompleteInputComponent', () => {
await fixture.whenStable(); await fixture.whenStable();
fixture.detectChanges(); 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');
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 () => { it('should show autocomplete list if similar predefined values exists', async () => {
enterNewInputValue('op'); enterNewInputValue('op');
await fixture.whenStable(); await fixture.whenStable();
fixture.detectChanges(); fixture.detectChanges();
expect(getOptionElements().length).toBe(2); expect((await getOptionElements()).length).toBe(2);
}); });
it('should show autocomplete list based on custom filtering', async () => { it('should show autocomplete list based on custom filtering', async () => {
@@ -214,22 +224,23 @@ describe('SearchChipAutocompleteInputComponent', () => {
enterNewInputValue('test1'); enterNewInputValue('test1');
await fixture.whenStable(); await fixture.whenStable();
fixture.detectChanges(); 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 () => { it('should not show autocomplete list if there are no similar predefined values', async () => {
enterNewInputValue('test'); enterNewInputValue('test');
await fixture.whenStable();
fixture.detectChanges(); const autocomplete = await loader.getHarness(MatAutocompleteHarness);
expect(getOptionElements().length).toBe(0);
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'); const optionsChangedSpy = spyOn(component.optionsChanged, 'emit');
addNewOption('option1'); addNewOption('option1');
expect(optionsChangedSpy).toHaveBeenCalledOnceWith([{value: 'option1'}]); expect(optionsChangedSpy).toHaveBeenCalledOnceWith([{value: 'option1'}]);
expect(getChipList().length).toBe(1); expect((await getChipList()).length).toBe(1);
expect(getChipValue(0)).toBe('option1'); expect(await getChipValue(0)).toBe('option1');
}); });
it('should clear the input after a new value is added', () => { it('should clear the input after a new value is added', () => {
@@ -248,7 +259,7 @@ describe('SearchChipAutocompleteInputComponent', () => {
expect(getInput().placeholder).toBe(component.placeholder); 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('option1');
addNewOption('option2'); addNewOption('option2');
const optionsChangedSpy = spyOn(component.optionsChanged, 'emit'); const optionsChangedSpy = spyOn(component.optionsChanged, 'emit');
@@ -256,11 +267,11 @@ describe('SearchChipAutocompleteInputComponent', () => {
fixture.detectChanges(); fixture.detectChanges();
expect(optionsChangedSpy).toHaveBeenCalledOnceWith([]); expect(optionsChangedSpy).toHaveBeenCalledOnceWith([]);
expect(getChipList()).toEqual([]); expect((await getChipList())).toEqual([]);
expect(component.selectedOptions).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('option1');
addNewOption('option2'); addNewOption('option2');
const optionsChangedSpy = spyOn(component.optionsChanged, 'emit'); const optionsChangedSpy = spyOn(component.optionsChanged, 'emit');
@@ -269,16 +280,16 @@ describe('SearchChipAutocompleteInputComponent', () => {
fixture.detectChanges(); fixture.detectChanges();
expect(optionsChangedSpy).toHaveBeenCalledOnceWith([{value: 'option2'}]); 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'}]; 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 () => { 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 { SearchDateRangeComponent } from './search-date-range.component';
import { addDays, endOfToday, format, parse, startOfYesterday, subDays } from 'date-fns'; import { addDays, endOfToday, format, parse, startOfYesterday, subDays } from 'date-fns';
import { Validators } from '@angular/forms'; 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', () => { describe('SearchDateRangeComponent', () => {
let component: SearchDateRangeComponent; let component: SearchDateRangeComponent;
let fixture: ComponentFixture<SearchDateRangeComponent>; let fixture: ComponentFixture<SearchDateRangeComponent>;
let loader: HarnessLoader;
const startDateSampleValue = parse('05-Jun-23', 'dd-MMM-yy', new Date()); const startDateSampleValue = parse('05-Jun-23', 'dd-MMM-yy', new Date());
const endDateSampleValue = parse('07-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, betweenStartDate: null,
betweenEndDate: null betweenEndDate: null
}); });
loader = TestbedHarnessEnvironment.documentRootLoader(fixture);
fixture.detectChanges(); fixture.detectChanges();
}); });
@@ -179,12 +185,15 @@ describe('SearchDateRangeComponent', () => {
component.form.controls.dateRangeType.setValue(component.DateRangeType.BETWEEN); component.form.controls.dateRangeType.setValue(component.DateRangeType.BETWEEN);
component.maxDate = 'today'; component.maxDate = 'today';
fixture.detectChanges(); 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 afterDate = format(addDays(new Date(), 1), 'MMM d, yyyy');
const afterDateItem = document.querySelector(`.mat-calendar-body-cell[aria-label="${afterDate}"]`); const cell = await calendar.getCells({ disabled: true });
expect(afterDateItem.getAttribute('aria-disabled')).toBeTruthy(); expect(await cell[0].getAriaLabel()).toEqual(afterDate);
}); });
it('should emit valid as false when form is invalid', () => { it('should emit valid as false when form is invalid', () => {
@@ -216,7 +225,7 @@ describe('SearchDateRangeComponent', () => {
expect(component.valid.emit).toHaveBeenCalledWith(true); 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'); spyOn(component.changed, 'emit');
let value = { let value = {
dateRangeType: component.DateRangeType.IN_LAST, dateRangeType: component.DateRangeType.IN_LAST,
@@ -225,8 +234,8 @@ describe('SearchDateRangeComponent', () => {
betweenStartDate: undefined, betweenStartDate: undefined,
betweenEndDate: undefined betweenEndDate: undefined
}; };
let dateRangeTypeRadioButton = getElementBySelector('[data-automation-id="date-range-in-last"] .mat-radio-input'); let dateRangeTypeRadioButton = await loader.getHarness(MatRadioButtonHarness.with({ selector: '[data-automation-id="date-range-in-last"]' }));
dateRangeTypeRadioButton.click(); await dateRangeTypeRadioButton.check();
selectDropdownOption('date-range-in-last-option-weeks'); selectDropdownOption('date-range-in-last-option-weeks');
enterValueInInputFieldAndTriggerEvent('date-range-in-last-input', ''); enterValueInInputFieldAndTriggerEvent('date-range-in-last-input', '');
expect(component.changed.emit).not.toHaveBeenCalledWith(value); expect(component.changed.emit).not.toHaveBeenCalledWith(value);
@@ -246,13 +255,13 @@ describe('SearchDateRangeComponent', () => {
betweenStartDate: '', betweenStartDate: '',
betweenEndDate: '' betweenEndDate: ''
}; };
dateRangeTypeRadioButton = getElementBySelector('[data-automation-id="date-range-between"] .mat-radio-input'); dateRangeTypeRadioButton = await loader.getHarness(MatRadioButtonHarness.with({ selector: '[data-automation-id="date-range-between"]' }));
dateRangeTypeRadioButton.click(); await dateRangeTypeRadioButton.check();
fixture.detectChanges(); fixture.detectChanges();
expect(component.changed.emit).not.toHaveBeenCalledWith(value); 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'); spyOn(component.changed, 'emit');
let value = { let value = {
dateRangeType: component.DateRangeType.IN_LAST, dateRangeType: component.DateRangeType.IN_LAST,
@@ -261,8 +270,8 @@ describe('SearchDateRangeComponent', () => {
betweenStartDate: null, betweenStartDate: null,
betweenEndDate: null betweenEndDate: null
}; };
let dateRangeTypeRadioButton = getElementBySelector('[data-automation-id="date-range-in-last"] .mat-radio-input'); let dateRangeTypeRadioButton = await loader.getHarness(MatRadioButtonHarness.with({ selector: '[data-automation-id="date-range-in-last"]' }));
dateRangeTypeRadioButton.click(); await dateRangeTypeRadioButton.check();
selectDropdownOption('date-range-in-last-option-weeks'); selectDropdownOption('date-range-in-last-option-weeks');
enterValueInInputFieldAndTriggerEvent('date-range-in-last-input', '5'); enterValueInInputFieldAndTriggerEvent('date-range-in-last-input', '5');
fixture.detectChanges(); fixture.detectChanges();
@@ -283,8 +292,8 @@ describe('SearchDateRangeComponent', () => {
betweenStartDate: startDateSampleValue, betweenStartDate: startDateSampleValue,
betweenEndDate: endDateSampleValue betweenEndDate: endDateSampleValue
}; };
dateRangeTypeRadioButton = getElementBySelector('[data-automation-id="date-range-between"] .mat-radio-input'); dateRangeTypeRadioButton = await loader.getHarness(MatRadioButtonHarness.with({ selector: '[data-automation-id="date-range-between"]' }));
dateRangeTypeRadioButton.click(); await dateRangeTypeRadioButton.check();
component.betweenStartDateFormControl.setValue(startDateSampleValue); component.betweenStartDateFormControl.setValue(startDateSampleValue);
component.betweenEndDateFormControl.setValue(endDateSampleValue); component.betweenEndDateFormControl.setValue(endDateSampleValue);
fixture.detectChanges(); fixture.detectChanges();

View File

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

View File

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

View File

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

View File

@@ -134,7 +134,7 @@ describe('TreeViewComponent', () => {
expect(element.querySelector('#fake-child-name-tree-child-node')).not.toBeNull(); expect(element.querySelector('#fake-child-name-tree-child-node')).not.toBeNull();
expect(element.querySelector('#fake-second-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) => { 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 () => { it('should change the icon of the opened folders', async () => {
const rootFolderButton = element.querySelector<HTMLButtonElement>('#button-fake-node-name'); const rootFolderButton = element.querySelector<HTMLButtonElement>('#button-fake-node-name');
expect(rootFolderButton).not.toBeNull(); 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(); rootFolderButton.click();
fixture.detectChanges(); fixture.detectChanges();
await fixture.whenStable(); 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 () => { it('should show the subfolders of a subfolder if there are any', async () => {
@@ -197,7 +197,7 @@ describe('TreeViewComponent', () => {
fixture.detectChanges(); fixture.detectChanges();
await fixture.whenStable(); 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-child-name-tree-child-node')).toBeNull();
expect(element.querySelector('#fake-second-name-tree-child-node')).toBeNull(); expect(element.querySelector('#fake-second-name-tree-child-node')).toBeNull();
}); });

View File

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

View File

@@ -33,13 +33,18 @@ import { TreeServiceMock } from '../mock/tree-service.service.mock';
import { By } from '@angular/platform-browser'; import { By } from '@angular/platform-browser';
import { SelectionChange } from '@angular/cdk/collections'; import { SelectionChange } from '@angular/cdk/collections';
import { DebugElement } from '@angular/core'; 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', () => { describe('TreeComponent', () => {
let fixture: ComponentFixture<TreeComponent<TreeNode>>; let fixture: ComponentFixture<TreeComponent<TreeNode>>;
let component: TreeComponent<TreeNode>; let component: TreeComponent<TreeNode>;
let userPreferenceService: UserPreferencesService; 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))); 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 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 getExpandCollapseBtn = (nodeId: string) => fixture.nativeElement.querySelector(`${composeNodeSelector(nodeId)} .adf-icon`);
const tickCheckbox = (index: number) => { 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')); nodeCheckboxes[index].nativeElement.dispatchEvent(new Event('change'));
}; };
@@ -73,6 +79,7 @@ describe('TreeComponent', () => {
}); });
fixture = TestBed.createComponent(TreeComponent); fixture = TestBed.createComponent(TreeComponent);
loader = TestbedHarnessEnvironment.loader(fixture);
component = fixture.componentInstance; component = fixture.componentInstance;
userPreferenceService = TestBed.inject(UserPreferencesService); userPreferenceService = TestBed.inject(UserPreferencesService);
}); });
@@ -126,20 +133,21 @@ describe('TreeComponent', () => {
expect(nodeLevel1Padding).toBeGreaterThan(nodeLevel0Padding); 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); component.treeService.treeNodes = Array.from(treeNodesChildrenMockExpanded);
fixture.detectChanges(); fixture.detectChanges();
component.treeService.treeControl.dataNodes[0].isLoading = true; component.treeService.treeControl.dataNodes[0].isLoading = true;
fixture.detectChanges(); fixture.detectChanges();
const nodeSpinner = getNodeSpinner('testId1'); const nodeSpinner = await getNodeSpinner('testId1');
expect(nodeSpinner).not.toBeNull(); 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(); fixture.detectChanges();
component.loadingRoot$ = of(true); component.loadingRoot$ = of(true);
fixture.detectChanges(); 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(); expect(matSpinnerElement).not.toBeNull();
}); });
@@ -172,13 +180,13 @@ describe('TreeComponent', () => {
expect(getNodesSpy).toHaveBeenCalledWith('-root-', 0, 25, 'some term'); 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.refreshTree();
component.treeService.treeNodes[0].isLoading = true; component.treeService.treeNodes[0].isLoading = true;
fixture.detectChanges(); fixture.detectChanges();
const collapseSpy = spyOn(component.treeService, 'collapseNode'); const collapseSpy = spyOn(component.treeService, 'collapseNode');
spyOn(component.treeService.treeControl, 'isExpanded').and.returnValue(true); 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(); expect(collapseSpy).not.toHaveBeenCalled();
}); });
@@ -192,13 +200,13 @@ describe('TreeComponent', () => {
expect(collapseSpy).toHaveBeenCalledWith(component.treeService.treeNodes[0]); 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.refreshTree();
component.treeService.treeNodes[0].isLoading = true; component.treeService.treeNodes[0].isLoading = true;
fixture.detectChanges(); fixture.detectChanges();
const expandSpy = spyOn(component.treeService, 'expandNode'); const expandSpy = spyOn(component.treeService, 'expandNode');
spyOn(component.treeService.treeControl, 'isExpanded').and.returnValue(false); 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(); expect(expandSpy).not.toHaveBeenCalled();
}); });
@@ -292,10 +300,11 @@ describe('TreeComponent', () => {
.toBeUndefined(); .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(); component.refreshTree();
fixture.detectChanges(); fixture.detectChanges();
const nodeCheckboxes = fixture.debugElement.queryAll(By.css('mat-checkbox')); const nodeCheckboxes = await loader.getAllHarnesses(MatCheckboxHarness);
expect(nodeCheckboxes.length).toEqual(0); expect(nodeCheckboxes.length).toEqual(0);
expect(component.selectableNodes).toEqual(false); expect(component.selectableNodes).toEqual(false);
}); });
@@ -305,10 +314,10 @@ describe('TreeComponent', () => {
component.selectableNodes = true; component.selectableNodes = true;
}); });
it('should display checkboxes when selection is enabled', () => { it('should display checkboxes when selection is enabled', async () => {
component.refreshTree(); component.refreshTree();
fixture.detectChanges(); 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); const selectableNodes = component.treeService.treeNodes.filter((node: TreeNode) => node.nodeType !== TreeNodeType.LoadMoreNode);
expect(nodeCheckboxes.length).toEqual(selectableNodes.length); expect(nodeCheckboxes.length).toEqual(selectableNodes.length);
}); });
@@ -336,7 +345,7 @@ describe('TreeComponent', () => {
spyOn(component.treeService, 'getSubNodes').and.returnValue(of({ pagination: {}, entries: Array.from(treeNodesChildrenMockExpanded) })); spyOn(component.treeService, 'getSubNodes').and.returnValue(of({ pagination: {}, entries: Array.from(treeNodesChildrenMockExpanded) }));
fixture.detectChanges(); fixture.detectChanges();
tickCheckbox(0); tickCheckbox(0);
tickCheckbox(2); tickCheckbox(1);
expect(component.descendantsPartiallySelected(component.treeService.treeNodes[0])).toBeTrue(); expect(component.descendantsPartiallySelected(component.treeService.treeNodes[0])).toBeTrue();
expect(component.descendantsPartiallySelected(component.treeService.treeNodes[1])).toBeTrue(); expect(component.descendantsPartiallySelected(component.treeService.treeNodes[1])).toBeTrue();
}); });