[ACS-6140] reduce access to internal material classes (#9053)

* cleanup login (demo shell)

* cleanup e2e from useless calls

* [ci:force] cleanup e2e from useless calls

* [ci:force] cleanup e2e from useless calls

* [ci:force] improved uploader selectors

* [ci:force] remove useless selectors when automation id provided

* [ci:force] improved tests and selectors

* [ci:force] improved tests and selectors

* [ci:force] improved tests and selectors

* [ci:force] improved tests and selectors

* [ci:force] improved tests and selectors

* [ci:force] improved tests and selectors

* [ci:force] switch edit task filter to angular harness

* [ci:force] switch edit process filter to angular harness

* [ci:force] switch search chip list to angular harness

* [ci:force] switch search panel to angular harness

* [ci:force] switch search radio to angular harness

* [ci:force] switch search text to angular harness

* [ci:force] search logical filter

* [ci:force] search form component

* [ci:force] search filter container

* [ci:force] fix viewer test

* [ci:force] search facet chip harness

* [ci:force] search facet chip harness

* [ci:force] dropdown breadcrumb

* [ci:force] search check list

* [ci:force] folder dialog

* [ci:force] search filter component

* [ci:force] json cell

* [ci:force] amount widget

* [ci:force] checkbox widget

* [ci:force] multiline-text widget

* [ci:force] number widget

* [ci:force] text widget

* [ci:force] card view array item

* add permission dialog

* permission container component

* permission list component

* card view components

* search widget chip

* search facet chip

* edit service task filter

* card view components

* sites dropdown

* share dialog

* header component

* datetime widget

* remove comments
This commit is contained in:
Denys Vuika
2023-11-03 10:05:34 +00:00
committed by GitHub
parent 9278d9296f
commit 93fd0bec6c
62 changed files with 2335 additions and 2660 deletions

View File

@@ -26,7 +26,6 @@ import { of } from 'rxjs';
import { TranslateModule } from '@ngx-translate/core';
describe('DropdownBreadcrumb', () => {
let component: DropdownBreadcrumbComponent;
let fixture: ComponentFixture<DropdownBreadcrumbComponent>;
let documentList: DocumentListComponent;
@@ -34,10 +33,7 @@ describe('DropdownBreadcrumb', () => {
beforeEach(() => {
TestBed.configureTestingModule({
imports: [
TranslateModule.forRoot(),
ContentTestingModule
],
imports: [TranslateModule.forRoot(), ContentTestingModule],
schemas: [CUSTOM_ELEMENTS_SCHEMA],
providers: [{ provide: DocumentListService, useValue: documentListService }]
});
@@ -64,7 +60,7 @@ describe('DropdownBreadcrumb', () => {
};
const clickOnTheFirstOption = () => {
const option: any = document.querySelector('[id^="mat-option"]');
const option: any = document.querySelector(`[data-automation-class="dropdown-breadcrumb-path-option"]`);
option.click();
};
@@ -75,7 +71,6 @@ describe('DropdownBreadcrumb', () => {
triggerComponentChange(fakeNodeWithCreatePermissionInstance);
fixture.whenStable().then(() => {
openSelect();
const currentFolder = fixture.debugElement.query(By.css('[data-automation-id="current-folder"]'));
@@ -99,7 +94,6 @@ describe('DropdownBreadcrumb', () => {
triggerComponentChange(fakeNodeWithCreatePermissionInstance);
fixture.whenStable().then(() => {
openSelect();
const path = fixture.debugElement.query(By.css('[data-automation-id="dropdown-breadcrumb-path"]'));
@@ -110,7 +104,6 @@ describe('DropdownBreadcrumb', () => {
});
});
it('should update document list when clicking on an option', async () => {
component.target = documentList;
const fakeNodeWithCreatePermissionInstance = JSON.parse(JSON.stringify(fakeNodeWithCreatePermission));

View File

@@ -607,7 +607,7 @@ describe('ContentMetadataComponent', () => {
it('should hide metadata fields if displayDefaultProperties is set to false', () => {
component.displayDefaultProperties = false;
fixture.detectChanges();
const metadataContainer = fixture.debugElement.query(By.css('mat-expansion-panel[data-automation-id="adf-metadata-group-properties"]'));
const metadataContainer = fixture.debugElement.query(By.css('[data-automation-id="adf-metadata-group-properties"]'));
fixture.detectChanges();
expect(metadataContainer).toBeNull();
});
@@ -615,7 +615,7 @@ describe('ContentMetadataComponent', () => {
it('should display metadata fields if displayDefaultProperties is set to true', () => {
component.displayDefaultProperties = true;
fixture.detectChanges();
const metadataContainer = fixture.debugElement.query(By.css('mat-expansion-panel[data-automation-id="adf-metadata-group-properties"]'));
const metadataContainer = fixture.debugElement.query(By.css('[data-automation-id="adf-metadata-group-properties"]'));
fixture.detectChanges();
expect(metadataContainer).toBeDefined();
});

View File

@@ -24,7 +24,6 @@ import { By } from '@angular/platform-browser';
import { FileModel } from '../common/models/file.model';
import { FileUploadEvent } from '../common/events/file.event';
import { UploadService } from '../common/services/upload.service';
import { of } from 'rxjs';
import { ContentTestingModule } from '../testing/content.testing.module';
import { DocumentListService } from '../document-list/services/document-list.service';
@@ -58,12 +57,7 @@ describe('ContentNodeSelectorComponent', () => {
};
TestBed.configureTestingModule({
imports: [
TranslateModule.forRoot(),
ContentTestingModule,
MatDialogModule,
UploadModule
],
imports: [TranslateModule.forRoot(), ContentTestingModule, MatDialogModule, UploadModule],
providers: [
{ provide: MAT_DIALOG_DATA, useValue: data },
{
@@ -118,6 +112,8 @@ describe('ContentNodeSelectorComponent', () => {
fixture.destroy();
});
const getTabInfoButton = () => fixture.debugElement.query(By.css('[data-automation-id="adf-content-node-selector-disabled-tab-info-icon"]'));
const enableLocalUpload = () => {
component.data.showLocalUploadButton = true;
component.hasAllowableOperations = true;
@@ -125,15 +121,16 @@ describe('ContentNodeSelectorComponent', () => {
component.isLoading = false;
};
const getTabLabel = (idx: number) => fixture.debugElement.queryAll(By.css('.mat-tab-label'))[idx];
const selectTabByIndex = (tabIndex: number) => {
const uploadFromLocalTab = fixture.debugElement.queryAll(By.css('.mat-tab-label'))[tabIndex];
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"', () => {
it('should show the INJECTED title', () => {
const titleElement = fixture.debugElement.query(By.css('[data-automation-id="content-node-selector-title"]'));
expect(titleElement).not.toBeNull();
@@ -149,101 +146,105 @@ describe('ContentNodeSelectorComponent', () => {
it('should pass through the injected currentFolderId to the documentList', () => {
const documentList = fixture.debugElement.query(By.directive(DocumentListComponent));
expect(documentList).not.toBeNull('Document list should be shown');
expect(documentList).not.toBeNull();
expect(documentList.componentInstance.currentFolderId).toBe('cat-girl-nuku-nuku');
});
it('should pass through the injected rowFilter to the documentList', () => {
const documentList = fixture.debugElement.query(By.directive(DocumentListComponent));
expect(documentList).not.toBeNull('Document list should be shown');
expect(documentList.componentInstance.rowFilter({
node: {
entry: new Node({
name: 'impossible-name',
id: 'name'
})
}
}))
.toBe(data.rowFilter({
expect(documentList).not.toBeNull();
expect(
documentList.componentInstance.rowFilter({
node: {
entry: new Node({
name: 'impossible-name',
id: 'name'
})
}
}));
})
).toBe(
data.rowFilter({
node: {
entry: new Node({
name: 'impossible-name',
id: 'name'
})
}
})
);
});
it('should pass through the injected imageResolver to the documentList', () => {
const documentList = fixture.debugElement.query(By.directive(DocumentListComponent));
expect(documentList).not.toBeNull('Document list should be shown');
expect(documentList).not.toBeNull();
expect(documentList.componentInstance.imageResolver).toBe(data.imageResolver);
});
});
});
describe('Cancel button', () => {
const getCancelButton = () => fixture.debugElement.query(By.css('[data-automation-id="content-node-selector-actions-cancel"]'));
it('should not be shown if dialogRef is NOT injected', () => {
const closeButton = fixture.debugElement.query(By.css('[content-node-selector-actions-cancel]'));
expect(closeButton).toBeNull();
});
it('should close the dialog', () => {
let cancelButton = fixture.debugElement.query(By.css('[data-automation-id="content-node-selector-actions-cancel"]'));
let cancelButton = getCancelButton();
cancelButton.triggerEventHandler('click', {});
expect(dialog.close).toHaveBeenCalled();
fixture.detectChanges();
cancelButton = fixture.debugElement.query(By.css('[data-automation-id="content-node-selector-actions-cancel"]'));
cancelButton = getCancelButton();
expect(cancelButton).not.toBeNull();
});
});
describe('Action button for the chosen node', () => {
const getActionButton = () =>
fixture.debugElement.query(By.css('[data-automation-id="content-node-selector-actions-choose"]'))?.nativeElement as HTMLButtonElement;
it('should be disabled by default', () => {
fixture.detectChanges();
const actionButton = fixture.debugElement.query(By.css('[data-automation-id="content-node-selector-actions-choose"]'));
expect(actionButton.nativeElement.disabled).toBeTruthy();
const actionButton = getActionButton();
expect(actionButton.disabled).toBeTruthy();
});
it('should be enabled when a node is chosen', () => {
component.onSelect([new Node({ id: 'fake' })]);
fixture.detectChanges();
const actionButton = fixture.debugElement.query(By.css('[data-automation-id="content-node-selector-actions-choose"]'));
expect(actionButton.nativeElement.disabled).toBeFalsy();
const actionButton = getActionButton();
expect(actionButton.disabled).toBeFalsy();
});
it('should be disabled when no node chosen', () => {
component.onSelect([new Node({ id: 'fake' })]);
fixture.detectChanges();
const actionButtonWithNodeSelected = fixture.debugElement.query(By.css('[data-automation-id="content-node-selector-actions-choose"]'));
expect(actionButtonWithNodeSelected.nativeElement.disabled).toBe(false);
const actionButtonWithNodeSelected = getActionButton();
expect(actionButtonWithNodeSelected.disabled).toBe(false);
component.onSelect([]);
fixture.detectChanges();
const actionButtonWithoutNodeSelected = fixture.debugElement.query(By.css('[data-automation-id="content-node-selector-actions-choose"]'));
expect(actionButtonWithoutNodeSelected.nativeElement.disabled).toBe(true);
const actionButtonWithoutNodeSelected = getActionButton();
expect(actionButtonWithoutNodeSelected.disabled).toBe(true);
});
it('should close the dialog when action button is clicked', async () => {
it('should close the dialog when action button is clicked', () => {
component.onSelect([new Node({ id: 'fake' })]);
fixture.detectChanges();
const actionButton = fixture.debugElement.query(By.css('[data-automation-id="content-node-selector-actions-choose"]'));
await actionButton.nativeElement.click();
const actionButton = getActionButton();
actionButton.click();
expect(dialog.close).toHaveBeenCalled();
});
});
describe('Title', () => {
it('should be updated when a site is chosen', () => {
const fakeSiteTitle = 'My fake site';
const contentNodePanel = fixture.debugElement.query(By.directive(ContentNodeSelectorPanelComponent));
@@ -253,17 +254,18 @@ describe('ContentNodeSelectorComponent', () => {
const titleElement = fixture.debugElement.query(By.css('[data-automation-id="content-node-selector-title"]'));
expect(titleElement).not.toBeNull();
expect(titleElement.nativeElement.innerText).toBe('NODE_SELECTOR.CHOOSE_ITEM');
});
});
});
});
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', () => {
enableLocalUpload();
fixture.detectChanges();
let infoMatIcon = fixture.debugElement.query(By.css('[data-automation-id="adf-content-node-selector-disabled-tab-info-icon"]'));
let uploadFromLocalTab = fixture.debugElement.queryAll(By.css('.mat-tab-label'))[1];
let infoMatIcon = getTabInfoButton();
let uploadFromLocalTab = getTabLabel(1);
expect(uploadFromLocalTab.nativeElement.getAttribute('aria-disabled')).toBe('false');
expect(infoMatIcon).toBeFalsy();
@@ -271,8 +273,8 @@ describe('ContentNodeSelectorComponent', () => {
component.showingSearch = true;
fixture.detectChanges();
uploadFromLocalTab = fixture.debugElement.queryAll(By.css('.mat-tab-label'))[1];
infoMatIcon = fixture.debugElement.query(By.css('[data-automation-id="adf-content-node-selector-disabled-tab-info-icon"]'));
uploadFromLocalTab = getTabLabel(1);
infoMatIcon = getTabInfoButton();
expect(uploadFromLocalTab.nativeElement.getAttribute('aria-disabled')).toBe('true');
expect(infoMatIcon).toBeTruthy();
@@ -281,8 +283,8 @@ describe('ContentNodeSelectorComponent', () => {
component.showingSearch = false;
fixture.detectChanges();
uploadFromLocalTab = fixture.debugElement.queryAll(By.css('.mat-tab-label'))[1];
infoMatIcon = fixture.debugElement.query(By.css('[data-automation-id="adf-content-node-selector-disabled-tab-info-icon"]'));
uploadFromLocalTab = getTabLabel(1);
infoMatIcon = getTabInfoButton();
expect(uploadFromLocalTab.nativeElement.getAttribute('aria-disabled')).toBe('false');
expect(infoMatIcon).toBeFalsy();
@@ -305,10 +307,10 @@ describe('ContentNodeSelectorComponent', () => {
component.hasAllowableOperations = true;
fixture.detectChanges();
const adfUploadButton = fixture.debugElement.query(By.css('adf-upload-button button'));
const adfUploadButton = getUploadButton();
expect(adfUploadButton).not.toBeNull();
expect(adfUploadButton.nativeElement.disabled).toBe(true);
expect(adfUploadButton.disabled).toBe(true);
});
it('should be able to enable UploadButton if showingSearch set to false', () => {
@@ -317,10 +319,10 @@ describe('ContentNodeSelectorComponent', () => {
component.hasAllowableOperations = true;
fixture.detectChanges();
const adfUploadButton = fixture.debugElement.query(By.css('adf-upload-button button'));
const adfUploadButton = getUploadButton();
expect(adfUploadButton).not.toBeNull();
expect(adfUploadButton.nativeElement.disabled).toBe(false);
expect(adfUploadButton.disabled).toBe(false);
});
it('should be able to show warning message while searching', () => {
@@ -330,7 +332,7 @@ describe('ContentNodeSelectorComponent', () => {
selectTabByIndex(1);
fixture.detectChanges();
const infoMatIcon = fixture.debugElement.query(By.css('[data-automation-id="adf-content-node-selector-disabled-tab-info-icon"]'));
const infoMatIcon = getTabInfoButton();
const iconTooltipMessage = infoMatIcon.attributes['ng-reflect-message'];
const expectedMessage = 'NODE_SELECTOR.UPLOAD_BUTTON_SEARCH_WARNING_MESSAGE';
@@ -354,10 +356,10 @@ describe('ContentNodeSelectorComponent', () => {
selectTabByIndex(1);
fixture.detectChanges();
const adfUploadButton = fixture.debugElement.query(By.css('adf-upload-button button'));
const adfUploadButton = getUploadButton();
expect(adfUploadButton).not.toBeNull();
expect(adfUploadButton.nativeElement.disabled).toBe(true);
expect(adfUploadButton.disabled).toBe(true);
});
it('should be able to enable UploadButton if user has allowable operations', () => {
@@ -365,10 +367,10 @@ describe('ContentNodeSelectorComponent', () => {
component.hasAllowableOperations = true;
fixture.detectChanges();
const adfUploadButton = fixture.debugElement.query(By.css('adf-upload-button button'));
const adfUploadButton = getUploadButton();
expect(adfUploadButton).not.toBeNull();
expect(adfUploadButton.nativeElement.disabled).toBe(false);
expect(adfUploadButton.disabled).toBe(false);
});
it('should not be able to show warning message if user has allowable operations', () => {
@@ -388,7 +390,7 @@ describe('ContentNodeSelectorComponent', () => {
selectTabByIndex(1);
fixture.detectChanges();
const infoMatIcon = fixture.debugElement.query(By.css('[data-automation-id="adf-content-node-selector-disabled-tab-info-icon"]'));
const infoMatIcon = getTabInfoButton();
const iconTooltipMessage = infoMatIcon.attributes['ng-reflect-message'];
const expectedMessage = 'NODE_SELECTOR.UPLOAD_BUTTON_PERMISSION_WARNING_MESSAGE';
@@ -424,11 +426,11 @@ describe('ContentNodeSelectorComponent', () => {
});
it('should tabs be headless when local upload is not enabled', () => {
component.data.showLocalUploadButton = false;
fixture.detectChanges();
const tabGroup = fixture.debugElement.queryAll(By.css('.adf-content-node-selector-headless-tabs'))[0];
component.data.showLocalUploadButton = false;
fixture.detectChanges();
const tabGroup = fixture.debugElement.queryAll(By.css('.adf-content-node-selector-headless-tabs'))[0];
expect(tabGroup).not.toBe(undefined);
expect(tabGroup).not.toBe(undefined);
});
it('should tabs show headers when local upload is enabled', () => {
@@ -441,12 +443,14 @@ describe('ContentNodeSelectorComponent', () => {
});
describe('Drag and drop area', () => {
const getEmptyList = () => fixture.nativeElement.querySelector('[data-automation-id="adf-empty-list"]');
it('should uploadStarted be false by default', () => {
expect(component.uploadStarted).toBe(false);
});
it('should uploadStarted become true when the first upload gets started', () => {
const fileUploadEvent = new FileUploadEvent(new FileModel({ name: 'fake-name', size: 100 } as File));
const fileUploadEvent = new FileUploadEvent(new FileModel({ name: 'fake-name', size: 100 } as File));
uploadService.fileUploadStarting.next(fileUploadEvent);
expect(component.uploadStarted).toBe(true);
@@ -454,12 +458,13 @@ describe('ContentNodeSelectorComponent', () => {
it('should show drag and drop area with the empty list template when no upload has started', async () => {
enableLocalUpload();
const uploadFromLocalTab = fixture.debugElement.queryAll(By.css('.mat-tab-label'))[1];
const uploadFromLocalTab = getTabLabel(1);
uploadFromLocalTab.nativeElement.click();
fixture.detectChanges();
await fixture.whenRenderingDone();
const emptyListTemplate = fixture.nativeElement.querySelector('[data-automation-id="adf-empty-list"]');
const emptyListTemplate = getEmptyList();
const dragAndDropArea = fixture.debugElement.query(By.css('.adf-upload-drag-area'));
expect(emptyListTemplate).not.toBeNull();
@@ -468,19 +473,21 @@ describe('ContentNodeSelectorComponent', () => {
it('should not show the empty list template when an upload has started', async () => {
enableLocalUpload();
const uploadFromLocalTab = fixture.debugElement.queryAll(By.css('.mat-tab-label'))[1];
const uploadFromLocalTab = getTabLabel(1);
uploadFromLocalTab.nativeElement.click();
component.uploadStarted = true;
fixture.detectChanges();
await fixture.whenRenderingDone();
const emptyListTemplate = fixture.nativeElement.querySelector('[data-automation-id="adf-empty-list"]');
const emptyListTemplate = getEmptyList();
expect(emptyListTemplate).toBeNull();
});
});
describe('Selected nodes counter', () => {
const getNodeCounter = () => fixture.debugElement.nativeElement.querySelector('adf-node-counter');
it('should getSelectedCount return 0 by default', () => {
expect(component.getSelectedCount()).toBe(0);
});
@@ -494,19 +501,19 @@ describe('ContentNodeSelectorComponent', () => {
it('should show the counter depending on the action', () => {
component.action = NodeAction.ATTACH;
fixture.detectChanges();
expect(fixture.debugElement.nativeElement.querySelector('adf-node-counter')).not.toBe(null);
expect(getNodeCounter()).not.toBe(null);
component.action = NodeAction.CHOOSE;
fixture.detectChanges();
expect(fixture.debugElement.nativeElement.querySelector('adf-node-counter')).not.toBe(null);
expect(getNodeCounter()).not.toBe(null);
component.action = NodeAction.COPY;
fixture.detectChanges();
expect(fixture.debugElement.nativeElement.querySelector('adf-node-counter')).toBe(null);
expect(getNodeCounter()).toBe(null);
component.action = NodeAction.MOVE;
fixture.detectChanges();
expect(fixture.debugElement.nativeElement.querySelector('adf-node-counter')).toBe(null);
expect(getNodeCounter()).toBe(null);
});
});
});

View File

@@ -15,7 +15,7 @@
* limitations under the License.
*/
import { TestBed, fakeAsync, ComponentFixture, tick } from '@angular/core/testing';
import { TestBed, ComponentFixture } from '@angular/core/testing';
import { MatDialogRef, MAT_DIALOG_DATA, MatDialog } from '@angular/material/dialog';
import { of } from 'rxjs';
import { NotificationService, AppConfigService } from '@alfresco/adf-core';
@@ -28,8 +28,12 @@ import { TranslateModule } from '@ngx-translate/core';
import { format, endOfDay } from 'date-fns';
import { By } from '@angular/platform-browser';
import { NodeEntry } from '@alfresco/js-api';
import { HarnessLoader } from '@angular/cdk/testing';
import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed';
import { MatSlideToggleHarness } from '@angular/material/slide-toggle/testing';
describe('ShareDialogComponent', () => {
let loader: HarnessLoader;
let node: NodeEntry;
let matDialog: MatDialog;
const notificationServiceMock = {
@@ -45,8 +49,6 @@ describe('ShareDialogComponent', () => {
const shareToggleId = '[data-automation-id="adf-share-toggle"]';
const expireToggle = '[data-automation-id="adf-expire-toggle"]';
const getShareToggleLinkedClasses = (): DOMTokenList => fixture.nativeElement.querySelector(shareToggleId).classList;
const fillInDatepickerInput = (value: string) => {
const input = fixture.debugElement.query(By.css('.adf-share-link__input')).nativeElement;
input.value = value;
@@ -55,10 +57,6 @@ describe('ShareDialogComponent', () => {
fixture.detectChanges();
};
const clickExpireToggleButton = () => fixture.nativeElement.querySelector(`${expireToggle} label`).dispatchEvent(new MouseEvent('click'));
const clickShareToggleButton = () => fixture.nativeElement.querySelector(`${shareToggleId} label`).dispatchEvent(new MouseEvent('click'));
beforeEach(() => {
TestBed.configureTestingModule({
imports: [TranslateModule.forRoot(), ContentTestingModule],
@@ -99,6 +97,7 @@ describe('ShareDialogComponent', () => {
};
spyOn(nodesApiService, 'updateNode').and.returnValue(of(null));
loader = TestbedHarnessEnvironment.loader(fixture);
});
afterEach(() => {
@@ -133,7 +132,7 @@ describe('ShareDialogComponent', () => {
});
});
it(`should toggle share action when property 'sharedId' does not exists`, () => {
it(`should toggle share action when property 'sharedId' does not exists`, async () => {
spyOn(sharedLinksApiService, 'createSharedLinks').and.returnValue(
of({
entry: { id: 'sharedId', sharedId: 'sharedId' }
@@ -151,7 +150,9 @@ describe('ShareDialogComponent', () => {
expect(sharedLinksApiService.createSharedLinks).toHaveBeenCalled();
expect(renditionService.getNodeRendition).toHaveBeenCalled();
expect(fixture.nativeElement.querySelector('input[formcontrolname="sharedUrl"]').value).toBe('some-url/sharedId');
expect(getShareToggleLinkedClasses()).toContain('mat-checked');
const toggle = await loader.getHarness(MatSlideToggleHarness.with({ selector: shareToggleId }));
expect(await toggle.isChecked()).toBe(true);
});
it(`should not toggle share action when file has 'sharedId' property`, async () => {
@@ -176,10 +177,12 @@ describe('ShareDialogComponent', () => {
expect(sharedLinksApiService.createSharedLinks).not.toHaveBeenCalled();
expect(fixture.nativeElement.querySelector('input[formcontrolname="sharedUrl"]').value).toBe('some-url/sharedId');
expect(getShareToggleLinkedClasses()).toContain('mat-checked');
const toggle = await loader.getHarness(MatSlideToggleHarness.with({ selector: shareToggleId }));
expect(await toggle.isChecked()).toBe(true);
});
it('should open a confirmation dialog when unshare button is triggered', () => {
it('should open a confirmation dialog when unshare button is triggered', async () => {
spyOn(matDialog, 'open').and.returnValue({ beforeClosed: () => of(false) } as any);
spyOn(sharedLinksApiService, 'deleteSharedLink').and.callThrough();
@@ -192,14 +195,13 @@ describe('ShareDialogComponent', () => {
fixture.detectChanges();
clickShareToggleButton();
fixture.detectChanges();
const toggle = await loader.getHarness(MatSlideToggleHarness.with({ selector: shareToggleId }));
await toggle.toggle();
expect(matDialog.open).toHaveBeenCalled();
});
it('should unshare file when confirmation dialog returns true', fakeAsync(() => {
it('should unshare file when confirmation dialog returns true', async () => {
spyOn(matDialog, 'open').and.returnValue({ beforeClosed: () => of(true) } as any);
spyOn(sharedLinksApiService, 'deleteSharedLink').and.returnValue(of({}));
node.entry.properties['qshare:sharedId'] = 'sharedId';
@@ -211,14 +213,13 @@ describe('ShareDialogComponent', () => {
fixture.detectChanges();
clickShareToggleButton();
fixture.detectChanges();
const toggle = await loader.getHarness(MatSlideToggleHarness.with({ selector: shareToggleId }));
await toggle.toggle();
expect(sharedLinksApiService.deleteSharedLink).toHaveBeenCalled();
}));
});
it('should not unshare file when confirmation dialog returns false', fakeAsync(() => {
it('should not unshare file when confirmation dialog returns false', async () => {
spyOn(matDialog, 'open').and.returnValue({ beforeClosed: () => of(false) } as any);
spyOn(sharedLinksApiService, 'deleteSharedLink').and.callThrough();
node.entry.properties['qshare:sharedId'] = 'sharedId';
@@ -230,14 +231,13 @@ describe('ShareDialogComponent', () => {
fixture.detectChanges();
clickShareToggleButton();
fixture.detectChanges();
const toggle = await loader.getHarness(MatSlideToggleHarness.with({ selector: shareToggleId }));
await toggle.toggle();
expect(sharedLinksApiService.deleteSharedLink).not.toHaveBeenCalled();
}));
});
it('should not allow unshare when node has no update permission', () => {
it('should not allow unshare when node has no update permission', async () => {
node.entry.properties['qshare:sharedId'] = 'sharedId';
node.entry.allowableOperations = [];
@@ -248,7 +248,8 @@ describe('ShareDialogComponent', () => {
fixture.detectChanges();
expect(getShareToggleLinkedClasses()).toContain('mat-disabled');
const toggle = await loader.getHarness(MatSlideToggleHarness.with({ selector: shareToggleId }));
expect(await toggle.isChecked()).toBe(true);
});
it('should delete the current link generated with expiry date and generate a new link without expiry date when toggle is unchecked', async () => {
@@ -266,9 +267,9 @@ describe('ShareDialogComponent', () => {
fixture.detectChanges();
component.form.controls['time'].setValue(new Date());
fixture.detectChanges();
clickExpireToggleButton();
fixture.detectChanges();
await fixture.whenStable();
const toggle = await loader.getHarness(MatSlideToggleHarness.with({ selector: expireToggle }));
await toggle.toggle();
expect(sharedLinksApiService.deleteSharedLink).toHaveBeenCalled();
expect(sharedLinksApiService.createSharedLinks).toHaveBeenCalledWith('nodeId', undefined);
@@ -286,7 +287,9 @@ describe('ShareDialogComponent', () => {
fixture.detectChanges();
await fixture.whenStable();
expect(fixture.nativeElement.querySelector('.mat-slide-toggle[data-automation-id="adf-expire-toggle"]').classList).toContain('mat-disabled');
const toggle = await loader.getHarness(MatSlideToggleHarness.with({ selector: `[data-automation-id="adf-expire-toggle"]` }));
expect(await toggle.isDisabled()).toBe(true);
expect(fixture.nativeElement.querySelector('[data-automation-id="adf-slide-toggle-checked"]').style.display).toEqual('none');
});
@@ -303,18 +306,19 @@ describe('ShareDialogComponent', () => {
};
});
it('should update node with input date and end of day time when type is `date`', fakeAsync(() => {
it('should update node with input date and end of day time when type is `date`', async () => {
const dateTimePickerType = 'date';
const date = new Date('2525-01-01');
spyOn(appConfigService, 'get').and.callFake(() => dateTimePickerType as any);
fixture.detectChanges();
clickExpireToggleButton();
const toggle = await loader.getHarness(MatSlideToggleHarness.with({ selector: expireToggle }));
await toggle.toggle();
fixture.componentInstance.time.setValue(date);
component.onTimeChanged();
fixture.detectChanges();
tick(500);
const expiryDate = format(endOfDay(date as Date), `yyyy-MM-dd'T'HH:mm:ss.SSSxx`);
@@ -323,11 +327,14 @@ describe('ShareDialogComponent', () => {
nodeId: 'nodeId',
expiresAt: expiryDate
});
}));
});
it('should not update node when provided date is less than minDate', () => {
it('should not update node when provided date is less than minDate', async () => {
fixture.detectChanges();
clickExpireToggleButton();
const toggle = await loader.getHarness(MatSlideToggleHarness.with({ selector: expireToggle }));
await toggle.toggle();
fillInDatepickerInput('01.01.2010');
expect(component.form.invalid).toBeTrue();
@@ -335,9 +342,12 @@ describe('ShareDialogComponent', () => {
expect(sharedLinksApiService.createSharedLinks).not.toHaveBeenCalled();
});
it('should not accept alphabets in the datepicker input', () => {
it('should not accept alphabets in the datepicker input', async () => {
fixture.detectChanges();
clickExpireToggleButton();
const toggle = await loader.getHarness(MatSlideToggleHarness.with({ selector: expireToggle }));
await toggle.toggle();
fillInDatepickerInput('test');
expect(component.form.invalid).toBeTrue();
@@ -346,7 +356,10 @@ describe('ShareDialogComponent', () => {
it('should show an error if provided date is invalid', async () => {
fixture.detectChanges();
clickExpireToggleButton();
const toggle = await loader.getHarness(MatSlideToggleHarness.with({ selector: expireToggle }));
await toggle.toggle();
fillInDatepickerInput('incorrect');
fixture.detectChanges();
@@ -358,9 +371,12 @@ describe('ShareDialogComponent', () => {
expect(component.time.hasError('invalidDate')).toBeTrue();
});
it('should not show an error when provided date is valid', () => {
it('should not show an error when provided date is valid', async () => {
fixture.detectChanges();
clickExpireToggleButton();
const toggle = await loader.getHarness(MatSlideToggleHarness.with({ selector: expireToggle }));
await toggle.toggle();
fillInDatepickerInput('12.12.2525');
const error = fixture.debugElement.query(By.css('[data-automation-id="adf-share-link-input-warning"]'));

View File

@@ -1,4 +1,4 @@
<h2 mat-dialog-title>
<h2 data-automation-id="adf-folder-dialog-title" mat-dialog-title>
{{ (editing ? editTitle : createTitle) | translate }}
</h2>

View File

@@ -35,13 +35,8 @@ describe('FolderDialogComponent', () => {
beforeEach(() => {
TestBed.configureTestingModule({
imports: [
TranslateModule.forRoot(),
ContentTestingModule
],
providers: [
{ provide: MatDialogRef, useValue: dialogRef }
]
imports: [TranslateModule.forRoot(), ContentTestingModule],
providers: [{ provide: MatDialogRef, useValue: dialogRef }]
});
dialogRef.close.calls.reset();
fixture = TestBed.createComponent(FolderDialogComponent);
@@ -54,7 +49,6 @@ describe('FolderDialogComponent', () => {
});
describe('Edit', () => {
beforeEach(() => {
component.data = {
folder: {
@@ -100,16 +94,13 @@ describe('FolderDialogComponent', () => {
component.submit();
expect(nodesApi.updateNode).toHaveBeenCalledWith(
'node-id',
{
name: 'folder-name-update',
properties: {
'cm:title': 'folder-title-update',
'cm:description': 'folder-description-update'
}
expect(nodesApi.updateNode).toHaveBeenCalledWith('node-id', {
name: 'folder-name-update',
properties: {
'cm:title': 'folder-title-update',
'cm:description': 'folder-description-update'
}
);
});
});
it('should call dialog to close with form data when submit is successfully', () => {
@@ -174,10 +165,10 @@ describe('FolderDialogComponent', () => {
});
it('should have the proper title', () => {
const title = fixture.debugElement.query(By.css('[mat-dialog-title]'));
const title = fixture.debugElement.query(By.css(`[data-automation-id="adf-folder-dialog-title"]`));
expect(title === null).toBe(false);
expect(title.nativeElement.innerText.trim()).toBe('CORE.FOLDER_DIALOG.CREATE_FOLDER_TITLE');
});
});
it('should init form with empty inputs', () => {
expect(component.name).toBe('');
@@ -201,17 +192,14 @@ describe('FolderDialogComponent', () => {
component.submit();
expect(nodesApi.createFolder).toHaveBeenCalledWith(
'parentNodeId',
{
name: 'folder-name-update',
properties: {
'cm:title': 'folder-title-update',
'cm:description': 'folder-description-update'
},
nodeType: 'cm:folder'
}
);
expect(nodesApi.createFolder).toHaveBeenCalledWith('parentNodeId', {
name: 'folder-name-update',
properties: {
'cm:title': 'folder-title-update',
'cm:description': 'folder-description-update'
},
nodeType: 'cm:folder'
});
});
it('should submit updated values if form is valid (with custom nodeType)', () => {
@@ -224,17 +212,14 @@ describe('FolderDialogComponent', () => {
component.submit();
expect(nodesApi.createFolder).toHaveBeenCalledWith(
'parentNodeId',
{
name: 'folder-name-update',
properties: {
'cm:title': 'folder-title-update',
'cm:description': 'folder-description-update'
},
nodeType: 'cm:sushi'
}
);
expect(nodesApi.createFolder).toHaveBeenCalledWith('parentNodeId', {
name: 'folder-name-update',
properties: {
'cm:title': 'folder-title-update',
'cm:description': 'folder-description-update'
},
nodeType: 'cm:sushi'
});
});
it('should call dialog to close with form data when submit is successfully', () => {
@@ -315,5 +300,5 @@ describe('FolderDialogComponent', () => {
component.submit();
});
});
});
});
});

View File

@@ -26,9 +26,12 @@ import { ContentTestingModule } from '../../../testing/content.testing.module';
import { AddPermissionDialogComponent } from './add-permission-dialog.component';
import { AddPermissionDialogData } from './add-permission-dialog-data.interface';
import { fakeAuthorityResults } from '../../../mock/add-permission.component.mock';
import { HarnessLoader } from '@angular/cdk/testing';
import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed';
import { MatSelectHarness } from '@angular/material/select/testing';
describe('AddPermissionDialog', () => {
let loader: HarnessLoader;
let fixture: ComponentFixture<AddPermissionDialogComponent>;
let component: AddPermissionDialogComponent;
let element: HTMLElement;
@@ -53,7 +56,7 @@ describe('AddPermissionDialog', () => {
role: 'Consumer'
}
],
confirm: new Subject<PermissionElement[]> ()
confirm: new Subject<PermissionElement[]>()
};
const dialogRef = {
close: jasmine.createSpy('close')
@@ -61,10 +64,7 @@ describe('AddPermissionDialog', () => {
beforeEach(() => {
TestBed.configureTestingModule({
imports: [
TranslateModule.forRoot(),
ContentTestingModule
],
imports: [TranslateModule.forRoot(), ContentTestingModule],
providers: [
{ provide: MatDialogRef, useValue: dialogRef },
{ provide: MAT_DIALOG_DATA, useValue: data }
@@ -74,12 +74,15 @@ describe('AddPermissionDialog', () => {
component = fixture.componentInstance;
element = fixture.nativeElement;
fixture.detectChanges();
loader = TestbedHarnessEnvironment.loader(fixture);
});
afterEach(() => {
fixture.destroy();
});
const getConfirmButton = () => element.querySelector<HTMLButtonElement>('[data-automation-id="add-permission-dialog-confirm-button"]');
it('should show the INJECTED title', () => {
const titleElement = fixture.debugElement.query(By.css('#add-permission-dialog-title'));
expect(titleElement).not.toBeNull();
@@ -94,27 +97,31 @@ describe('AddPermissionDialog', () => {
});
it('should disable the confirm button when no selection is applied', () => {
const confirmButton = element.querySelector<HTMLButtonElement>('[data-automation-id="add-permission-dialog-confirm-button"]');
const confirmButton = getConfirmButton();
expect(confirmButton.disabled).toBeTruthy();
});
it('should enable the button when a selection is done', async () => {
const addPermissionPanelComponent: AddPermissionPanelComponent = fixture.debugElement.query(By.directive(AddPermissionPanelComponent)).componentInstance;
const addPermissionPanelComponent: AddPermissionPanelComponent = fixture.debugElement.query(
By.directive(AddPermissionPanelComponent)
).componentInstance;
addPermissionPanelComponent.select.emit(fakeAuthorityResults);
let confirmButton = element.querySelector<HTMLButtonElement>('[data-automation-id="add-permission-dialog-confirm-button"]');
let confirmButton = getConfirmButton();
expect(confirmButton.disabled).toBeTruthy();
fixture.detectChanges();
await fixture.whenStable();
confirmButton = element.querySelector<HTMLButtonElement>('[data-automation-id="add-permission-dialog-confirm-button"]');
confirmButton = getConfirmButton();
expect(confirmButton.disabled).toBe(false);
});
it('should update the role after selection', async () => {
spyOn(component, 'onMemberUpdate').and.callThrough();
const addPermissionPanelComponent: AddPermissionPanelComponent = fixture.debugElement.query(By.directive(AddPermissionPanelComponent)).componentInstance;
let confirmButton = element.querySelector<HTMLButtonElement>('[data-automation-id="add-permission-dialog-confirm-button"]');
const addPermissionPanelComponent: AddPermissionPanelComponent = fixture.debugElement.query(
By.directive(AddPermissionPanelComponent)
).componentInstance;
let confirmButton = getConfirmButton();
expect(confirmButton.disabled).toBe(true);
addPermissionPanelComponent.select.emit([fakeAuthorityResults[0]]);
@@ -127,17 +134,12 @@ describe('AddPermissionDialog', () => {
fixture.detectChanges();
await fixture.whenStable();
const selectBox = fixture.debugElement.query(By.css(('[id="adf-select-role-permission"] .mat-select-trigger')));
selectBox.nativeElement.dispatchEvent(new Event('click'));
fixture.detectChanges();
const select = await loader.getHarness(MatSelectHarness.with({ ancestor: `#adf-select-role-permission` }));
await select.open();
const options = fixture.debugElement.queryAll(By.css('mat-option'));
expect(options).not.toBeNull();
const options = await select.getOptions();
expect(options.length).toBe(2);
options[0].triggerEventHandler('click', {});
fixture.detectChanges();
await fixture.whenStable();
await options[0].click();
expect(component.onMemberUpdate).toHaveBeenCalled();
@@ -147,7 +149,7 @@ describe('AddPermissionDialog', () => {
currentSelection = selection;
});
confirmButton = element.querySelector<HTMLButtonElement>('[data-automation-id="add-permission-dialog-confirm-button"]');
confirmButton = getConfirmButton();
expect(confirmButton.disabled).toBe(false);
confirmButton.click();
@@ -156,8 +158,10 @@ describe('AddPermissionDialog', () => {
it('should update all the user role on header column update', async () => {
spyOn(component, 'onBulkUpdate').and.callThrough();
const addPermissionPanelComponent: AddPermissionPanelComponent = fixture.debugElement.query(By.directive(AddPermissionPanelComponent)).componentInstance;
let confirmButton = element.querySelector<HTMLButtonElement>('[data-automation-id="add-permission-dialog-confirm-button"]');
const addPermissionPanelComponent: AddPermissionPanelComponent = fixture.debugElement.query(
By.directive(AddPermissionPanelComponent)
).componentInstance;
let confirmButton = getConfirmButton();
expect(confirmButton.disabled).toBe(true);
addPermissionPanelComponent.select.emit(fakeAuthorityResults);
@@ -170,19 +174,12 @@ describe('AddPermissionDialog', () => {
fixture.detectChanges();
await fixture.whenStable();
const selectBox = fixture.debugElement.query(By.css(('[id="adf-bulk-select-role-permission"] .mat-select-trigger')));
selectBox.nativeElement.dispatchEvent(new Event('click'));
const select = await loader.getHarness(MatSelectHarness.with({ ancestor: `#adf-bulk-select-role-permission` }));
await select.open();
fixture.detectChanges();
await fixture.whenStable();
const options = fixture.debugElement.queryAll(By.css('mat-option'));
expect(options).not.toBeNull();
const options = await select.getOptions();
expect(options.length).toBe(2);
options[0].triggerEventHandler('click', {});
fixture.detectChanges();
await fixture.whenStable();
await options[0].click();
expect(component.onBulkUpdate).toHaveBeenCalled();
@@ -190,7 +187,7 @@ describe('AddPermissionDialog', () => {
expect(selection.length).toBe(3);
});
confirmButton = element.querySelector<HTMLButtonElement>('[data-automation-id="add-permission-dialog-confirm-button"]');
confirmButton = getConfirmButton();
expect(confirmButton.disabled).toBe(false);
confirmButton.click();
});
@@ -198,8 +195,10 @@ describe('AddPermissionDialog', () => {
it('should delete the user after selection', async () => {
spyOn(component, 'onMemberUpdate').and.callThrough();
spyOn(component, 'onMemberDelete').and.callThrough();
const addPermissionPanelComponent: AddPermissionPanelComponent = fixture.debugElement.query(By.directive(AddPermissionPanelComponent)).componentInstance;
let confirmButton = element.querySelector<HTMLButtonElement>('[data-automation-id="add-permission-dialog-confirm-button"]');
const addPermissionPanelComponent: AddPermissionPanelComponent = fixture.debugElement.query(
By.directive(AddPermissionPanelComponent)
).componentInstance;
let confirmButton = getConfirmButton();
expect(confirmButton.disabled).toBe(true);
addPermissionPanelComponent.select.emit(fakeAuthorityResults);
@@ -212,22 +211,16 @@ describe('AddPermissionDialog', () => {
fixture.detectChanges();
await fixture.whenStable();
const selectBox = fixture.debugElement.query(By.css(('[id="adf-select-role-permission"] .mat-select-trigger')));
selectBox.nativeElement.dispatchEvent(new Event('click'));
const select = await loader.getHarness(MatSelectHarness.with({ ancestor: `#adf-select-role-permission` }));
await select.open();
fixture.detectChanges();
await fixture.whenStable();
const options = fixture.debugElement.queryAll(By.css('mat-option'));
expect(options).not.toBeNull();
const options = await select.getOptions();
expect(options.length).toBe(2);
options[0].triggerEventHandler('click', {});
fixture.detectChanges();
await fixture.whenStable();
await options[0].click();
expect(component.onMemberUpdate).toHaveBeenCalled();
confirmButton = element.querySelector<HTMLButtonElement>('[data-automation-id="add-permission-dialog-confirm-button"]');
confirmButton = getConfirmButton();
expect(confirmButton.disabled).toBe(true);
const deleteButton = element.querySelectorAll('[data-automation-id="adf-delete-permission-button"]') as any;
deleteButton[1].click();
@@ -246,7 +239,9 @@ describe('AddPermissionDialog', () => {
});
it('should stream the confirmed selection on the confirm subject', async () => {
const addPermissionPanelComponent: AddPermissionPanelComponent = fixture.debugElement.query(By.directive(AddPermissionPanelComponent)).componentInstance;
const addPermissionPanelComponent: AddPermissionPanelComponent = fixture.debugElement.query(
By.directive(AddPermissionPanelComponent)
).componentInstance;
addPermissionPanelComponent.select.emit(fakeAuthorityResults);
fixture.detectChanges();
@@ -255,7 +250,7 @@ describe('AddPermissionDialog', () => {
let authorityResult = fixture.debugElement.query(By.css('[data-automation-id="datatable-row-0"]'));
expect(authorityResult).toBeNull();
const confirmButton = element.querySelector<HTMLButtonElement>('[data-automation-id="add-permission-dialog-confirm-button"]');
const confirmButton = getConfirmButton();
confirmButton.click();
fixture.detectChanges();

View File

@@ -16,23 +16,23 @@
*/
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { By } from '@angular/platform-browser';
import { TranslateModule } from '@ngx-translate/core';
import { PermissionContainerComponent } from './permission-container.component';
import { ContentTestingModule } from '../../../testing/content.testing.module';
import { HarnessLoader } from '@angular/cdk/testing';
import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed';
import { MatSelectHarness } from '@angular/material/select/testing';
import { MatButtonHarness } from '@angular/material/button/testing';
describe('PermissionContainerComponent', () => {
let loader: HarnessLoader;
let fixture: ComponentFixture<PermissionContainerComponent>;
let component: PermissionContainerComponent;
let element: HTMLElement;
beforeEach(() => {
TestBed.configureTestingModule({
imports: [
TranslateModule.forRoot(),
ContentTestingModule
]
imports: [TranslateModule.forRoot(), ContentTestingModule]
});
fixture = TestBed.createComponent(PermissionContainerComponent);
component = fixture.componentInstance;
@@ -60,6 +60,7 @@ describe('PermissionContainerComponent', () => {
];
fixture.detectChanges();
loader = TestbedHarnessEnvironment.loader(fixture);
});
afterEach(() => {
@@ -72,26 +73,24 @@ describe('PermissionContainerComponent', () => {
expect(element.querySelector('#adf-select-role-permission').textContent).toContain('consumer');
});
it('should emit update event on role change', () => {
it('should emit update event on role change', async () => {
spyOn(component.update, 'emit');
const selectBox = fixture.debugElement.query(By.css(('[id="adf-select-role-permission"] .mat-select-trigger')));
selectBox.triggerEventHandler('click', null);
fixture.detectChanges();
const select = await loader.getHarness(MatSelectHarness.with({ ancestor: `#adf-select-role-permission` }));
await select.open();
const options = fixture.debugElement.queryAll(By.css('mat-option'));
expect(options).not.toBeNull();
const options = await select.getOptions();
expect(options.length).toBe(2);
options[0].triggerEventHandler('click', {});
fixture.detectChanges();
await options[0].click();
expect(component.update.emit).toHaveBeenCalledWith({ role: 'Test', permission: component.permissions[0] });
});
it('should delete update event on row delete', () => {
it('should delete update event on row delete', async () => {
spyOn(component.delete, 'emit');
const deleteButton: HTMLButtonElement = element.querySelector('[data-automation-id="adf-delete-permission-button-GROUP_EVERYONE"]');
deleteButton.click();
fixture.detectChanges();
const deleteButton = await loader.getHarness(
MatButtonHarness.with({ selector: `[data-automation-id="adf-delete-permission-button-GROUP_EVERYONE"]` })
);
await deleteButton.click();
expect(component.delete.emit).toHaveBeenCalledWith(component.permissions[0]);
});
});

View File

@@ -16,7 +16,6 @@
*/
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { By } from '@angular/platform-browser';
import { TranslateModule } from '@ngx-translate/core';
import { of, throwError } from 'rxjs';
import { SearchService } from '../../../search/services/search.service';
@@ -36,8 +35,13 @@ import {
import { ContentTestingModule } from '../../../testing/content.testing.module';
import { Node } from '@alfresco/js-api';
import { NodesApiService } from '../../../common/services/nodes-api.service';
import { HarnessLoader } from '@angular/cdk/testing';
import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed';
import { MatSlideToggleHarness } from '@angular/material/slide-toggle/testing';
import { MatSelectHarness } from '@angular/material/select/testing';
describe('PermissionListComponent', () => {
let loader: HarnessLoader;
let fixture: ComponentFixture<PermissionListComponent>;
let component: PermissionListComponent;
let element: HTMLElement;
@@ -64,6 +68,7 @@ describe('PermissionListComponent', () => {
searchQuerySpy = spyOn(searchApiService, 'searchByQueryBody').and.returnValue(of(fakeEmptyResponse));
component.nodeId = 'fake-node-id';
fixture.detectChanges();
loader = TestbedHarnessEnvironment.loader(fixture);
});
afterEach(() => {
@@ -117,7 +122,9 @@ describe('PermissionListComponent', () => {
fixture.detectChanges();
await fixture.whenStable();
expect(element.querySelector('.adf-inherit-container .mat-checked')).toBeDefined();
const toggle = await loader.getHarness(MatSlideToggleHarness);
expect(await toggle.isChecked()).toBe(true);
expect(element.querySelector('.adf-inherit-container h3').textContent.trim()).toBe(
'PERMISSION_MANAGER.LABELS.INHERITED-PERMISSIONS PERMISSION_MANAGER.LABELS.ON'
);
@@ -127,10 +134,11 @@ describe('PermissionListComponent', () => {
it('should toggle the inherited button', async () => {
getNodeSpy.and.returnValue(of(fakeNodeInheritedOnly));
component.ngOnInit();
fixture.detectChanges();
expect(element.querySelector('.adf-inherit-container .mat-checked')).toBeDefined();
const toggle = await loader.getHarness(MatSlideToggleHarness);
expect(await toggle.isChecked()).toBe(true);
expect(element.querySelector('.adf-inherit-container h3').textContent.trim()).toBe(
'PERMISSION_MANAGER.LABELS.INHERITED-PERMISSIONS PERMISSION_MANAGER.LABELS.ON'
);
@@ -138,12 +146,8 @@ describe('PermissionListComponent', () => {
spyOn(nodeService, 'updateNode').and.returnValue(of(fakeLocalPermission));
const slider = fixture.debugElement.query(By.css('mat-slide-toggle'));
slider.triggerEventHandler('change', { source: { checked: false } });
await toggle.uncheck();
fixture.detectChanges();
expect(element.querySelector('.adf-inherit-container .mat-checked')).toBe(null);
expect(element.querySelector('.adf-inherit-container h3').textContent.trim()).toBe(
'PERMISSION_MANAGER.LABELS.INHERITED-PERMISSIONS PERMISSION_MANAGER.LABELS.OFF'
);
@@ -157,7 +161,9 @@ describe('PermissionListComponent', () => {
fixture.detectChanges();
await fixture.whenStable();
expect(element.querySelector('.adf-inherit-container .mat-checked')).toBeDefined();
const toggle = await loader.getHarness(MatSlideToggleHarness);
expect(await toggle.isChecked()).toBe(true);
expect(element.querySelector('.adf-inherit-container h3').textContent.trim()).toBe(
'PERMISSION_MANAGER.LABELS.INHERITED-PERMISSIONS PERMISSION_MANAGER.LABELS.ON'
);
@@ -165,13 +171,8 @@ describe('PermissionListComponent', () => {
spyOn(nodeService, 'updateNode').and.returnValue(of(fakeLocalPermission));
const slider = fixture.debugElement.query(By.css('mat-slide-toggle'));
slider.triggerEventHandler('change', { source: { checked: false } });
await toggle.uncheck();
fixture.detectChanges();
await fixture.whenStable();
expect(element.querySelector('.adf-inherit-container .mat-checked')).toBeDefined();
expect(element.querySelector('.adf-inherit-container h3').textContent.trim()).toBe(
'PERMISSION_MANAGER.LABELS.INHERITED-PERMISSIONS PERMISSION_MANAGER.LABELS.ON'
);
@@ -206,17 +207,16 @@ describe('PermissionListComponent', () => {
expect(element.querySelector('adf-user-name-column').textContent).toContain('GROUP_EVERYONE');
expect(element.querySelector('#adf-select-role-permission').textContent).toContain('Contributor');
const selectBox = fixture.debugElement.query(By.css('[id="adf-select-role-permission"] .mat-select-trigger'));
selectBox.triggerEventHandler('click', null);
fixture.detectChanges();
const select = await loader.getHarness(MatSelectHarness.with({ ancestor: `#adf-select-role-permission` }));
await select.open();
const options = fixture.debugElement.queryAll(By.css('mat-option'));
expect(options).not.toBeNull();
const options = await select.getOptions();
expect(options.length).toBe(4);
expect(options[0].nativeElement.innerText).toContain('ADF.ROLES.SITECOLLABORATOR');
expect(options[1].nativeElement.innerText).toContain('ADF.ROLES.SITECONSUMER');
expect(options[2].nativeElement.innerText).toContain('ADF.ROLES.SITECONTRIBUTOR');
expect(options[3].nativeElement.innerText).toContain('ADF.ROLES.SITEMANAGER');
expect(await options[0].getText()).toContain('ADF.ROLES.SITECOLLABORATOR');
expect(await options[1].getText()).toContain('ADF.ROLES.SITECONSUMER');
expect(await options[2].getText()).toContain('ADF.ROLES.SITECONTRIBUTOR');
expect(await options[3].getText()).toContain('ADF.ROLES.SITEMANAGER');
});
it('should show readonly member for site manager to toggle the inherit permission', async () => {
@@ -247,14 +247,12 @@ describe('PermissionListComponent', () => {
expect(element.querySelector('adf-user-name-column').textContent).toContain('GROUP_EVERYONE');
expect(element.querySelector('#adf-select-role-permission').textContent).toContain('Contributor');
const selectBox = fixture.debugElement.query(By.css('[id="adf-select-role-permission"] .mat-select-trigger'));
selectBox.triggerEventHandler('click', null);
fixture.detectChanges();
const options = fixture.debugElement.queryAll(By.css('mat-option'));
expect(options).not.toBeNull();
const select = await loader.getHarness(MatSelectHarness.with({ ancestor: `#adf-select-role-permission` }));
await select.open();
const options = await select.getOptions();
expect(options.length).toBe(5);
options[3].triggerEventHandler('click', {});
fixture.detectChanges();
await options[3].click();
expect(nodeService.updateNode).toHaveBeenCalledWith('f472543f-7218-403d-917b-7a5861257244', {
permissions: { locallySet: [{ accessStatus: 'ALLOWED', name: 'Editor', authorityId: 'GROUP_EVERYONE' }] }
});

View File

@@ -22,35 +22,33 @@ import { UserIconColumnComponent } from './user-icon-column.component';
import { NodeEntry } from '@alfresco/js-api';
describe('UserIconColumnComponent', () => {
let fixture: ComponentFixture<UserIconColumnComponent>;
let component: UserIconColumnComponent;
let element: HTMLElement;
const person = {
const person = {
firstName: 'fake',
lastName: 'user',
email: 'fake@test.com'
};
const group = {
const group = {
id: 'fake-id',
displayName: 'fake authority'
};
beforeEach(() => {
TestBed.configureTestingModule({
imports: [
TranslateModule.forRoot(),
ContentTestingModule
]
imports: [TranslateModule.forRoot(), ContentTestingModule]
});
fixture = TestBed.createComponent(UserIconColumnComponent);
fixture = TestBed.createComponent(UserIconColumnComponent);
component = fixture.componentInstance;
element = fixture.nativeElement;
fixture.detectChanges();
});
describe('person initial', () => {
const getInitials = () => element.querySelector('[data-automation-id="user-initials-image"]')?.textContent;
it('should render person value from context', () => {
component.context = {
row: {
@@ -61,7 +59,7 @@ describe('UserIconColumnComponent', () => {
};
component.ngOnInit();
fixture.detectChanges();
expect(element.querySelector('[data-automation-id="user-initials-image"]').textContent).toContain('fu');
expect(getInitials()).toContain('fu');
});
it('should render person value from node', () => {
@@ -69,8 +67,8 @@ describe('UserIconColumnComponent', () => {
entry: {
nodeType: 'cm:person',
properties: {
'cm:firstName': 'Fake',
'cm:lastName': 'User',
'cm:firstName': 'Fake',
'cm:lastName': 'User',
'cm:email': 'fake-user@test.com',
'cm:userName': 'fake-user'
}
@@ -78,11 +76,13 @@ describe('UserIconColumnComponent', () => {
} as NodeEntry;
component.ngOnInit();
fixture.detectChanges();
expect(element.querySelector('[data-automation-id="user-initials-image"]').textContent).toContain('FU');
expect(getInitials()).toContain('FU');
});
});
describe('group initial', () => {
const getGroupIcon = () => element.querySelector('[id="group-icon"] .adf-group-icon');
it('should render group value from context', () => {
component.context = {
row: {
@@ -93,8 +93,8 @@ describe('UserIconColumnComponent', () => {
};
component.ngOnInit();
fixture.detectChanges();
expect(element.querySelector('[id="group-icon"] mat-icon')).toBeDefined();
expect(element.querySelector('[id="group-icon"] mat-icon').textContent).toContain('people_alt_outline');
expect(getGroupIcon()).toBeDefined();
expect(getGroupIcon().textContent).toContain('people_alt_outline');
});
it('should render person value from node', () => {
@@ -102,14 +102,14 @@ describe('UserIconColumnComponent', () => {
entry: {
nodeType: 'cm:authorityContainer',
properties: {
'cm:authorityName': 'Fake authorityN'
'cm:authorityName': 'Fake authorityN'
}
}
} as NodeEntry;
component.ngOnInit();
fixture.detectChanges();
expect(element.querySelector('[id="group-icon"] mat-icon')).toBeDefined();
expect(element.querySelector('[id="group-icon"] mat-icon').textContent).toContain('people_alt_outline');
expect(getGroupIcon()).toBeDefined();
expect(getGroupIcon().textContent).toContain('people_alt_outline');
});
});

View File

@@ -20,22 +20,24 @@ import { SearchFilterList } from '../../models/search-filter-list.model';
import { ContentTestingModule } from '../../../testing/content.testing.module';
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { sizeOptions, stepOne, stepThree } from '../../../mock';
import { By } from '@angular/platform-browser';
import { TranslateModule } from '@ngx-translate/core';
import { HarnessLoader, TestKey } from '@angular/cdk/testing';
import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed';
import { MatCheckboxHarness } from '@angular/material/checkbox/testing';
import { MatButtonHarness } from '@angular/material/button/testing';
describe('SearchCheckListComponent', () => {
let loader: HarnessLoader;
let fixture: ComponentFixture<SearchCheckListComponent>;
let component: SearchCheckListComponent;
beforeEach(() => {
TestBed.configureTestingModule({
imports: [
TranslateModule.forRoot(),
ContentTestingModule
]
imports: [TranslateModule.forRoot(), ContentTestingModule]
});
fixture = TestBed.createComponent(SearchCheckListComponent);
component = fixture.componentInstance;
loader = TestbedHarnessEnvironment.loader(fixture);
});
it('should setup options from settings', () => {
@@ -49,7 +51,7 @@ describe('SearchCheckListComponent', () => {
expect(component.options.items).toEqual(options);
});
it('should handle enter key as click on checkboxes', () => {
it('should handle enter key as click on checkboxes', async () => {
component.options = new SearchFilterList<SearchListOption>([
{ name: 'Folder', value: `TYPE:'cm:folder'`, checked: false },
{ name: 'Document', value: `TYPE:'cm:content'`, checked: false }
@@ -58,13 +60,13 @@ describe('SearchCheckListComponent', () => {
component.ngOnInit();
fixture.detectChanges();
const optionElements = fixture.debugElement.queryAll(By.css('mat-checkbox'));
const option = await loader.getHarness(MatCheckboxHarness);
optionElements[0].triggerEventHandler('keydown.enter', {});
expect(component.options.items[0].checked).toBeTruthy();
await (await option.host()).sendKeys(TestKey.ENTER);
expect(await option.isChecked()).toBe(true);
optionElements[0].triggerEventHandler('keydown.enter', {});
expect(component.options.items[0].checked).toBeFalsy();
await (await option.host()).sendKeys(TestKey.ENTER);
expect(await option.isChecked()).toBe(false);
});
it('should setup operator from the settings', () => {
@@ -95,21 +97,13 @@ describe('SearchCheckListComponent', () => {
spyOn(component.context, 'update').and.stub();
component.changeHandler(
{ checked: true } as any,
component.options.items[0]
);
component.changeHandler({ checked: true } as any, component.options.items[0]);
expect(component.context.queryFragments[component.id]).toEqual(`TYPE:'cm:folder'`);
component.changeHandler(
{ checked: true } as any,
component.options.items[1]
);
component.changeHandler({ checked: true } as any, component.options.items[1]);
expect(component.context.queryFragments[component.id]).toEqual(
`TYPE:'cm:folder' OR TYPE:'cm:content'`
);
expect(component.context.queryFragments[component.id]).toEqual(`TYPE:'cm:folder' OR TYPE:'cm:content'`);
});
it('should reset selected boxes', () => {
@@ -147,7 +141,7 @@ describe('SearchCheckListComponent', () => {
});
describe('Pagination', () => {
it('should show 5 items when pageSize not defined', () => {
it('should show 5 items when pageSize not defined', async () => {
component.id = 'checklist';
component.context = {
queryFragments: {
@@ -160,13 +154,14 @@ describe('SearchCheckListComponent', () => {
component.ngOnInit();
fixture.detectChanges();
const optionElements = fixture.debugElement.queryAll(By.css('mat-checkbox'));
expect(optionElements.length).toEqual(5);
const labels = Array.from(optionElements).map(element => element.nativeElement.innerText);
const options = await loader.getAllHarnesses(MatCheckboxHarness);
expect(options.length).toBe(5);
const labels = await Promise.all(options.map((element) => element.getLabelText()));
expect(labels).toEqual(stepOne);
});
it('should show all items when pageSize is high', () => {
it('should show all items when pageSize is high', async () => {
component.id = 'checklist';
component.context = {
queryFragments: {
@@ -178,14 +173,15 @@ describe('SearchCheckListComponent', () => {
component.ngOnInit();
fixture.detectChanges();
const optionElements = fixture.debugElement.queryAll(By.css('mat-checkbox'));
expect(optionElements.length).toEqual(13);
const labels = Array.from(optionElements).map(element => element.nativeElement.innerText);
const options = await loader.getAllHarnesses(MatCheckboxHarness);
expect(options.length).toBe(13);
const labels = await Promise.all(options.map((element) => element.getLabelText()));
expect(labels).toEqual(stepThree);
});
});
it('should able to check/reset the checkbox', () => {
it('should able to check/reset the checkbox', async () => {
component.id = 'checklist';
component.context = {
queryFragments: {
@@ -198,16 +194,15 @@ describe('SearchCheckListComponent', () => {
component.ngOnInit();
fixture.detectChanges();
const optionElements = fixture.debugElement.query(By.css('mat-checkbox'));
optionElements.triggerEventHandler('change', { checked: true });
const option = await loader.getHarness(MatCheckboxHarness);
await option.check();
expect(component.submitValues).toHaveBeenCalled();
const clearAllElement = fixture.debugElement.query(By.css('button[title="SEARCH.FILTER.ACTIONS.CLEAR-ALL"]'));
clearAllElement.triggerEventHandler('click', {} );
fixture.detectChanges();
const clearButton = await loader.getHarness(MatButtonHarness.with({ selector: `[title="SEARCH.FILTER.ACTIONS.CLEAR-ALL"]` }));
await clearButton.click();
const selectedElements = fixture.debugElement.queryAll(By.css('.mat-checkbox-checked'));
expect(selectedElements.length).toBe(0);
const checkedElements = await loader.getAllHarnesses(MatCheckboxHarness.with({ checked: true }));
expect(checkedElements.length).toBe(0);
});
});

View File

@@ -21,15 +21,13 @@ import { By } from '@angular/platform-browser';
import { SearchFacetFiltersService } from '../../services/search-facet-filters.service';
import { ContentTestingModule } from '../../../testing/content.testing.module';
import { TranslateModule } from '@ngx-translate/core';
import { HarnessLoader } from '@angular/cdk/testing';
import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed';
import { MatChipHarness, MatChipRemoveHarness } from '@angular/material/chips/testing';
@Component({
selector: 'adf-test-component',
template: `
<adf-search-chip-list
[searchFilter]="searchFilter"
[clearAll]="allowClear">
</adf-search-chip-list>
`
template: ` <adf-search-chip-list [searchFilter]="searchFilter" [clearAll]="allowClear"> </adf-search-chip-list> `
})
class TestComponent {
allowClear = true;
@@ -40,23 +38,22 @@ class TestComponent {
}
describe('SearchChipListComponent', () => {
let loader: HarnessLoader;
let fixture: ComponentFixture<TestComponent>;
let component: TestComponent;
let searchFacetFiltersService: SearchFacetFiltersService;
beforeEach(() => {
TestBed.configureTestingModule({
imports: [
TranslateModule.forRoot(),
ContentTestingModule
],
declarations: [
TestComponent
]
imports: [TranslateModule.forRoot(), ContentTestingModule],
declarations: [TestComponent]
});
fixture = TestBed.createComponent(TestComponent);
component = fixture.componentInstance;
searchFacetFiltersService = TestBed.inject(SearchFacetFiltersService);
fixture.detectChanges();
loader = TestbedHarnessEnvironment.loader(fixture);
});
it('should display clear button only when entries present', () => {
@@ -65,24 +62,26 @@ describe('SearchChipListComponent', () => {
let clearButton = fixture.debugElement.query(By.css(`[data-automation-id="reset-filter"]`));
expect(clearButton).toBeNull();
searchFacetFiltersService.selectedBuckets = [{
bucket: {
count: 1,
label: 'test',
filterQuery: 'query'
},
field: null
}];
searchFacetFiltersService.selectedBuckets = [
{
bucket: {
count: 1,
label: 'test',
filterQuery: 'query'
},
field: null
}
];
fixture.detectChanges();
clearButton = fixture.debugElement.query(By.css(`[data-automation-id="reset-filter"]`));
expect(clearButton).toBeDefined();
});
it('should reflect changes in the search filter', () => {
it('should reflect changes in the search filter', async () => {
const selectedBuckets = searchFacetFiltersService.selectedBuckets;
fixture.detectChanges();
let chips = fixture.debugElement.queryAll(By.css(`[data-automation-id="chip-list-entry"]`));
let chips = await loader.getAllHarnesses(MatChipHarness.with({ selector: '[data-automation-id="chip-list-entry"]' }));
expect(chips.length).toBe(0);
selectedBuckets.push({
@@ -95,7 +94,7 @@ describe('SearchChipListComponent', () => {
});
fixture.detectChanges();
chips = fixture.debugElement.queryAll(By.css(`[data-automation-id="chip-list-entry"]`));
chips = await loader.getAllHarnesses(MatChipHarness.with({ selector: '[data-automation-id="chip-list-entry"]' }));
expect(chips.length).toBe(1);
});
@@ -115,32 +114,30 @@ describe('SearchChipListComponent', () => {
fixture.detectChanges();
const chips = fixture.debugElement.queryAll(By.css(`[data-automation-id="chip-list-entry"] .mat-chip-remove`));
chips[0].nativeElement.click();
const removeButton = await loader.getHarness(MatChipRemoveHarness.with({ ancestor: `[data-automation-id="chip-list-entry"]` }));
await removeButton.click();
await fixture.whenStable();
expect(searchFacetFiltersService.unselectFacetBucket).toHaveBeenCalled();
});
it('should remove items from the search filter on clear button click', () => {
it('should remove items from the search filter on clear button click', async () => {
spyOn(searchFacetFiltersService, 'unselectFacetBucket').and.stub();
const selectedBucket1: any = { field: { id: 1 }, bucket: {label: 'bucket1'} };
const selectedBucket2: any = { field: { id: 2 }, bucket: {label: 'bucket2'} };
const selectedBucket1: any = { field: { id: 1 }, bucket: { label: 'bucket1' } };
const selectedBucket2: any = { field: { id: 2 }, bucket: { label: 'bucket2' } };
searchFacetFiltersService.selectedBuckets = [selectedBucket1, selectedBucket2];
fixture.detectChanges();
const closeButtons = fixture.debugElement.nativeElement.querySelectorAll('.mat-chip-remove');
const closeButtons = await loader.getAllHarnesses(MatChipRemoveHarness);
expect(closeButtons.length).toBe(2);
closeButtons[0].click();
fixture.detectChanges();
await closeButtons[0].click();
expect(searchFacetFiltersService.unselectFacetBucket).toHaveBeenCalledWith(selectedBucket1.field, selectedBucket1.bucket);
});
it('should disable clear mode via input properties', () => {
it('should disable clear mode via input properties', async () => {
spyOn(component.searchFilter, 'unselectFacetBucket').and.callThrough();
component.allowClear = false;
@@ -157,10 +154,10 @@ describe('SearchChipListComponent', () => {
fixture.detectChanges();
const chips = fixture.debugElement.queryAll(By.css(`[data-automation-id="chip-list-entry"] .mat-chip-remove`));
expect(chips.length).toBe(1);
const closeButtons = await loader.getAllHarnesses(MatChipRemoveHarness.with({ ancestor: `[data-automation-id="chip-list-entry"]` }));
expect(closeButtons.length).toBe(1);
const clearButton = fixture.debugElement.query(By.css(`[data-automation-id="reset-filter"]`));
expect(clearButton).toBeNull();
const hasClearButton = await loader.hasHarness(MatChipRemoveHarness.with({ selector: `[data-automation-id="reset-filter"]` }));
expect(hasClearButton).toBe(false);
});
});

View File

@@ -32,10 +32,7 @@ describe('SearchDateRangeComponent', () => {
beforeEach(() => {
TestBed.configureTestingModule({
imports: [
TranslateModule.forRoot(),
ContentTestingModule
]
imports: [TranslateModule.forRoot(), ContentTestingModule]
});
fixture = TestBed.createComponent(SearchDateRangeComponent);
component = fixture.componentInstance;
@@ -43,6 +40,9 @@ describe('SearchDateRangeComponent', () => {
afterEach(() => fixture.destroy());
const getFromInput = () => fixture.debugElement.nativeElement.querySelector('[data-automation-id="date-range-from-input"]');
const getToInput = () => fixture.debugElement.nativeElement.querySelector('[data-automation-id="date-range-to-input"]');
it('should setup form elements on init', () => {
fixture.detectChanges();
@@ -74,7 +74,6 @@ describe('SearchDateRangeComponent', () => {
});
it('should reset form', () => {
fixture.detectChanges();
component.form.setValue({ from: fromDate, to: toDate });
@@ -129,10 +128,13 @@ describe('SearchDateRangeComponent', () => {
spyOn(context, 'update').and.stub();
fixture.detectChanges();
component.apply({
from: fromDate,
to: toDate
}, true);
component.apply(
{
from: fromDate,
to: toDate
},
true
);
const startDate = startOfDay(fromDate).toISOString();
const endDate = endOfDay(toDate).toISOString();
@@ -146,7 +148,7 @@ describe('SearchDateRangeComponent', () => {
it('should show date-format error when Invalid found', async () => {
fixture.detectChanges();
const input = fixture.debugElement.nativeElement.querySelector('[data-automation-id="date-range-from-input"]');
const input = getFromInput();
input.value = '10-f-18';
input.dispatchEvent(new Event('input'));
@@ -159,7 +161,7 @@ describe('SearchDateRangeComponent', () => {
it('should hide date-format error when correcting input', async () => {
fixture.detectChanges();
const input = fixture.debugElement.nativeElement.querySelector('[data-automation-id="date-range-from-input"]');
const input = getFromInput();
input.value = '10-f-18';
input.dispatchEvent(new Event('input'));
@@ -181,7 +183,7 @@ describe('SearchDateRangeComponent', () => {
component.settings = { field: 'cm:created', maxDate: 'today' };
fixture.detectChanges();
const input = fixture.debugElement.nativeElement.querySelector('[data-automation-id="date-range-from-input"]');
const input = getFromInput();
input.value = format(addDays(new Date(), 1), 'dd-MM-yyyy');
input.dispatchEvent(new Event('input'));
@@ -194,11 +196,11 @@ describe('SearchDateRangeComponent', () => {
it('should show error for required constraint', async () => {
fixture.detectChanges();
const fromInput = fixture.debugElement.nativeElement.querySelector('[data-automation-id="date-range-from-input"]');
const fromInput = getFromInput();
fromInput.value = '';
fromInput.dispatchEvent(new Event('input'));
const toInput = fixture.debugElement.nativeElement.querySelector('[data-automation-id="date-range-to-input"]');
const toInput = getToInput();
toInput.value = '';
toInput.dispatchEvent(new Event('input'));
@@ -212,11 +214,11 @@ describe('SearchDateRangeComponent', () => {
it('should show error for incorrect date range', async () => {
fixture.detectChanges();
const fromInput = fixture.debugElement.nativeElement.querySelector('[data-automation-id="date-range-from-input"]');
const fromInput = getFromInput();
fromInput.value = '11-10-2018';
fromInput.dispatchEvent(new Event('input'));
const toInput = fixture.debugElement.nativeElement.querySelector('[data-automation-id="date-range-to-input"]');
const toInput = getToInput();
toInput.value = '10-10-2018';
toInput.dispatchEvent(new Event('input'));
@@ -230,7 +232,7 @@ describe('SearchDateRangeComponent', () => {
it('should not show date-format error when valid found', async () => {
fixture.detectChanges();
const input = fixture.debugElement.nativeElement.querySelector('[data-automation-id="date-range-from-input"]');
const input = getFromInput();
input.value = '10-10-2018';
input.dispatchEvent(new Event('input'));

View File

@@ -23,8 +23,13 @@ import { SearchFilterList } from '../../../models/search-filter-list.model';
import { SearchFacetChipTabbedComponent } from './search-facet-chip-tabbed.component';
import { FacetField } from '../../../models/facet-field.interface';
import { NO_ERRORS_SCHEMA } from '@angular/core';
import { HarnessLoader, TestKey } from '@angular/cdk/testing';
import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed';
import { MatChipHarness } from '@angular/material/chips/testing';
import { MatIconHarness } from '@angular/material/icon/testing';
describe('SearchFacetChipTabbedComponent', () => {
let loader: HarnessLoader;
let component: SearchFacetChipTabbedComponent;
let fixture: ComponentFixture<SearchFacetChipTabbedComponent>;
@@ -48,17 +53,9 @@ describe('SearchFacetChipTabbedComponent', () => {
}
};
fixture.detectChanges();
loader = TestbedHarnessEnvironment.loader(fixture);
});
/**
* Open the facet
*/
function openFacet() {
const chip = fixture.debugElement.query(By.css('mat-chip'));
chip.triggerEventHandler('click', {});
fixture.detectChanges();
}
/**
* Get the filter display value
*
@@ -90,71 +87,92 @@ describe('SearchFacetChipTabbedComponent', () => {
expect(displayValue).toBe('SEARCH.FILTER.ANY');
});
it('should display remove icon and disable facet when no items are loaded', () => {
const chip = fixture.debugElement.query(By.css('mat-chip'));
const icon = fixture.debugElement.query(By.css('mat-chip mat-icon')).nativeElement.innerText;
expect(chip.classes['mat-chip-disabled']).toBeTrue();
expect(icon).toEqual('remove');
it('should display remove icon and disable facet when no items are loaded', async () => {
const chip = await loader.getHarness(MatChipHarness);
const icon = await chip.getHarness(MatIconHarness);
expect(await chip.isDisabled()).toBe(true);
expect(await icon.getName()).toEqual('remove');
});
it('should not open context menu when no items are loaded', () => {
it('should not open context menu when no items are loaded', async () => {
spyOn(component.menuTrigger, 'openMenu');
const chip = fixture.debugElement.query(By.css('mat-chip')).nativeElement;
chip.dispatchEvent(new KeyboardEvent('keyup', { key: 'Enter' }));
const chip = await loader.getHarness(MatChipHarness);
const host = await chip.host();
await host.sendKeys(TestKey.ENTER);
expect(component.menuTrigger.openMenu).not.toHaveBeenCalled();
});
it('should display correct title when facet is opened', () => {
openFacet();
it('should display correct title when facet is opened', async () => {
const chip = await loader.getHarness(MatChipHarness);
await (await chip.host()).click();
const title = fixture.debugElement.query(By.css('.adf-search-filter-title')).nativeElement.innerText.split('\n')[0];
expect(title).toBe(component.tabbedFacet.label);
});
it('should display adf-search-facet-tabbed-content component', () => {
openFacet();
it('should display adf-search-facet-tabbed-content component', async () => {
const chip = await loader.getHarness(MatChipHarness);
await (await chip.host()).click();
const activeTabLabel = fixture.debugElement.query(By.css('adf-search-facet-tabbed-content'));
expect(activeTabLabel).toBeTruthy();
});
it('should display arrow down icon and not disable the chip when items are loaded', () => {
it('should display arrow down icon and not disable the chip when items are loaded', async () => {
component.isPopulated = true;
fixture.detectChanges();
const chip = fixture.debugElement.query(By.css('mat-chip'));
const icon = fixture.debugElement.query(By.css('mat-chip mat-icon')).nativeElement.innerText;
expect(chip.classes['mat-chip-disabled']).toBeUndefined();
expect(icon).toEqual('keyboard_arrow_down');
const chip = await loader.getHarness(MatChipHarness);
const icon = await chip.getHarness(MatIconHarness);
expect(await chip.isDisabled()).toBe(false);
expect(await icon.getName()).toBe('keyboard_arrow_down');
});
it('should display arrow up icon when menu is opened', async () => {
openFacet();
const chip = await loader.getHarness(MatChipHarness);
await (await chip.host()).click();
emitChildEvent('isPopulated', true);
await fixture.whenStable();
const icon = fixture.debugElement.query(By.css('mat-chip mat-icon')).nativeElement.innerText;
expect(icon).toEqual('keyboard_arrow_up');
const icon = await chip.getHarness(MatIconHarness);
expect(await icon.getName()).toBe('keyboard_arrow_up');
});
it('should update display value when new displayValue$ emitted', () => {
it('should update display value when new displayValue$ emitted', async () => {
const displayValue = 'field_LABEL: test, test2';
openFacet();
const chip = await loader.getHarness(MatChipHarness);
await (await chip.host()).click();
emitChildEvent('displayValue$', displayValue);
fixture.detectChanges();
expect(getDisplayValue()).toBe(displayValue);
});
it('should call onApply and close modal when apply btn is clicked', () => {
it('should call onApply and close modal when apply btn is clicked', async () => {
spyOn(component.menuTrigger, 'closeMenu').and.callThrough();
spyOn(component, 'onApply').and.callThrough();
openFacet();
const chip = await loader.getHarness(MatChipHarness);
await (await chip.host()).click();
const applyButton = fixture.debugElement.query(By.css('#apply-filter-button'));
applyButton.triggerEventHandler('click', {});
expect(component.menuTrigger.closeMenu).toHaveBeenCalled();
expect(component.onApply).toHaveBeenCalled();
});
it('should call onRemove and close modal when cancel btn is clicked', () => {
it('should call onRemove and close modal when cancel btn is clicked', async () => {
spyOn(component.menuTrigger, 'closeMenu').and.callThrough();
spyOn(component, 'onRemove').and.callThrough();
openFacet();
const chip = await loader.getHarness(MatChipHarness);
await (await chip.host()).click();
const applyButton = fixture.debugElement.query(By.css('#cancel-filter-button'));
applyButton.triggerEventHandler('click', {});
expect(component.menuTrigger.closeMenu).toHaveBeenCalled();

View File

@@ -5,7 +5,7 @@
[disabled]="!isPopulated()"
tabIndex="0"
[matMenuTriggerFor]="menu"
(onMenuOpen)="onMenuOpen()"
(menuOpened)="onMenuOpen()"
(keydown.enter)="onEnterKeydown()"
(keydown.escape)="onEscKeydown()"
[attr.title]="facetField.displayValue$ | async"

View File

@@ -19,77 +19,85 @@ import { ComponentFixture, TestBed } from '@angular/core/testing';
import { SearchFacetChipComponent } from './search-facet-chip.component';
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 { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed';
import { MatMenuHarness } from '@angular/material/menu/testing';
import { HarnessLoader, TestKey } from '@angular/cdk/testing';
import { MatButtonHarness } from '@angular/material/button/testing';
import { MatIconHarness } from '@angular/material/icon/testing';
describe('SearchFacetChipComponent', () => {
let component: SearchFacetChipComponent;
let fixture: ComponentFixture<SearchFacetChipComponent>;
let queryBuilder: SearchQueryBuilderService;
let loader: HarnessLoader;
let component: SearchFacetChipComponent;
let fixture: ComponentFixture<SearchFacetChipComponent>;
let queryBuilder: SearchQueryBuilderService;
beforeEach(() => {
TestBed.configureTestingModule({
imports: [
TranslateModule.forRoot(),
ContentTestingModule
]
});
fixture = TestBed.createComponent(SearchFacetChipComponent);
component = fixture.componentInstance;
queryBuilder = TestBed.inject(SearchQueryBuilderService);
spyOn(queryBuilder, 'update').and.stub();
beforeEach(() => {
TestBed.configureTestingModule({
imports: [TranslateModule.forRoot(), ContentTestingModule]
});
fixture = TestBed.createComponent(SearchFacetChipComponent);
component = fixture.componentInstance;
queryBuilder = TestBed.inject(SearchQueryBuilderService);
spyOn(queryBuilder, 'update').and.stub();
component.field = { type: 'field', label: 'f2', field: 'f2', buckets: new SearchFilterList() };
fixture.detectChanges();
});
it('should update search query on apply click', () => {
const chip = fixture.debugElement.query(By.css('mat-chip'));
chip.triggerEventHandler('click', { stopPropagation: () => null });
component.field = { type: 'field', label: 'f2', field: 'f2', buckets: new SearchFilterList() };
fixture.detectChanges();
const applyButton = fixture.debugElement.query(By.css('#apply-filter-button'));
applyButton.triggerEventHandler('click', {});
loader = TestbedHarnessEnvironment.loader(fixture);
});
it('should update search query on apply click', async () => {
const menu = await loader.getHarness(MatMenuHarness);
await menu.open();
const applyButton = await menu.getHarness(MatButtonHarness.with({ selector: '#apply-filter-button' }));
await applyButton.click();
expect(queryBuilder.update).toHaveBeenCalled();
});
it('should update search query on cancel click', () => {
const chip = fixture.debugElement.query(By.css('mat-chip'));
chip.triggerEventHandler('click', { stopPropagation: () => null });
fixture.detectChanges();
const applyButton = fixture.debugElement.query(By.css('#cancel-filter-button'));
applyButton.triggerEventHandler('click', {});
it('should update search query on cancel click', async () => {
const menu = await loader.getHarness(MatMenuHarness);
await menu.open();
const cancelButton = await menu.getHarness(MatButtonHarness.with({ selector: '#cancel-filter-button' }));
await cancelButton.click();
expect(queryBuilder.update).toHaveBeenCalled();
});
it('should display arrow down icon and not disable the chip when items are loaded', () => {
it('should display arrow down icon and not disable the chip when items are loaded', async () => {
component.field.buckets.items = [{ count: 1, label: 'test', filterQuery: '' }];
fixture.detectChanges();
const chip = fixture.debugElement.query(By.css('mat-chip'));
const icon = fixture.debugElement.query(By.css('mat-chip mat-icon')).nativeElement.innerText;
expect(chip.classes['mat-chip-disabled']).toBeUndefined();
expect(icon).toEqual('keyboard_arrow_down');
const menu = await loader.getHarness(MatMenuHarness);
expect(await menu.isDisabled()).toBe(false);
const icon = await loader.getHarness(MatIconHarness);
expect(await icon.getName()).toBe('keyboard_arrow_down');
});
it('should display arrow up icon when menu is opened', () => {
it('should display arrow up icon when menu is opened', async () => {
component.field.buckets.items = [{ count: 1, label: 'test', filterQuery: '' }];
component.onMenuOpen();
fixture.detectChanges();
const icon = fixture.debugElement.query(By.css('mat-chip mat-icon')).nativeElement.innerText;
expect(icon).toEqual('keyboard_arrow_up');
const menu = await loader.getHarness(MatMenuHarness);
await menu.open();
const icon = await loader.getHarness(MatIconHarness);
expect(await icon.getName()).toBe('keyboard_arrow_up');
});
it('should display remove icon and disable facet when no items are loaded', () => {
const chip = fixture.debugElement.query(By.css('mat-chip'));
const icon = fixture.debugElement.query(By.css('mat-chip mat-icon')).nativeElement.innerText;
expect(chip.classes['mat-chip-disabled']).toBeTrue();
expect(icon).toEqual('remove');
it('should display remove icon and disable facet when no items are loaded', async () => {
const menu = await loader.getHarness(MatMenuHarness);
expect(await menu.isDisabled()).toBe(true);
const icon = await loader.getHarness(MatIconHarness);
expect(await icon.getName()).toBe('remove');
});
it('should not open context menu when no items are loaded', () => {
spyOn(component.menuTrigger, 'openMenu');
const chip = fixture.debugElement.query(By.css('mat-chip')).nativeElement;
chip.dispatchEvent(new KeyboardEvent('keyup', { key: 'Enter' }));
expect(component.menuTrigger.openMenu).not.toHaveBeenCalled();
it('should not open context menu when no items are loaded', async () => {
const menu = await loader.getHarness(MatMenuHarness);
await (await menu.host()).sendKeys(TestKey.ENTER);
expect(await menu.isOpen()).toBe(false);
});
});

View File

@@ -4,7 +4,7 @@
[class.adf-search-toggle-chip]="(widget.getDisplayValue() | async) || menuTrigger.menuOpen"
tabIndex="0"
[matMenuTriggerFor]="menu"
(onMenuOpen)="onMenuOpen()"
(menuOpened)="onMenuOpen()"
(keydown.enter)="onEnterKeydown()"
(keydown.escape)="onEscKeydown()"
[attr.title]="widget.getDisplayValue() | async"

View File

@@ -23,19 +23,20 @@ import { ContentTestingModule } from '../../../../testing/content.testing.module
import { MatMenuModule } from '@angular/material/menu';
import { By } from '@angular/platform-browser';
import { SearchQueryBuilderService } from '../../../services/search-query-builder.service';
import { HarnessLoader } from '@angular/cdk/testing';
import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed';
import { MatChipHarness } from '@angular/material/chips/testing';
import { MatIconHarness } from '@angular/material/icon/testing';
describe('SearchWidgetChipComponent', () => {
let loader: HarnessLoader;
let component: SearchWidgetChipComponent;
let fixture: ComponentFixture<SearchWidgetChipComponent>;
let queryBuilder: SearchQueryBuilderService;
beforeEach(() => {
TestBed.configureTestingModule({
imports: [
MatMenuModule,
TranslateModule.forRoot(),
ContentTestingModule
]
imports: [MatMenuModule, TranslateModule.forRoot(), ContentTestingModule]
});
queryBuilder = TestBed.inject(SearchQueryBuilderService);
fixture = TestBed.createComponent(SearchWidgetChipComponent);
@@ -44,35 +45,40 @@ describe('SearchWidgetChipComponent', () => {
component.category = simpleCategories[1];
fixture.detectChanges();
loader = TestbedHarnessEnvironment.loader(fixture);
});
it('should update search query on apply click', () => {
const chip = fixture.debugElement.query(By.css('mat-chip'));
chip.triggerEventHandler('click', { stopPropagation: () => null });
fixture.detectChanges();
const applyButton = fixture.debugElement.query(By.css('#apply-filter-button'));
applyButton.triggerEventHandler('click', {});
expect(queryBuilder.update).toHaveBeenCalled();
it('should update search query on apply click', async () => {
const chip = await loader.getHarness(MatChipHarness);
await (await chip.host()).click();
const applyButton = fixture.debugElement.query(By.css('#apply-filter-button'));
applyButton.triggerEventHandler('click', {});
expect(queryBuilder.update).toHaveBeenCalled();
});
it('should update search query on cancel click', () => {
const chip = fixture.debugElement.query(By.css('mat-chip'));
chip.triggerEventHandler('click', { stopPropagation: () => null });
fixture.detectChanges();
const applyButton = fixture.debugElement.query(By.css('#cancel-filter-button'));
applyButton.triggerEventHandler('click', {});
expect(queryBuilder.update).toHaveBeenCalled();
it('should update search query on cancel click', async () => {
const chip = await loader.getHarness(MatChipHarness);
await (await chip.host()).click();
const applyButton = fixture.debugElement.query(By.css('#cancel-filter-button'));
applyButton.triggerEventHandler('click', {});
expect(queryBuilder.update).toHaveBeenCalled();
});
it('should display arrow down icon', () => {
const icon = fixture.debugElement.query(By.css('mat-chip mat-icon')).nativeElement.innerText;
expect(icon).toEqual('keyboard_arrow_down');
it('should display arrow down icon', async () => {
const chip = await loader.getHarness(MatChipHarness);
const icon = await chip.getHarness(MatIconHarness);
expect(await icon.getName()).toBe('keyboard_arrow_down');
});
it('should display arrow up icon when menu is opened', () => {
component.onMenuOpen();
fixture.detectChanges();
const icon = fixture.debugElement.query(By.css('mat-chip mat-icon')).nativeElement.innerText;
expect(icon).toEqual('keyboard_arrow_up');
it('should display arrow up icon when menu is opened', async () => {
component.onMenuOpen();
fixture.detectChanges();
const chip = await loader.getHarness(MatChipHarness);
const icon = await chip.getHarness(MatIconHarness);
expect(await icon.getName()).toBe('keyboard_arrow_up');
});
});

View File

@@ -24,8 +24,13 @@ import { ContentTestingModule } from '../../../testing/content.testing.module';
import { SEARCH_QUERY_SERVICE_TOKEN } from '../../search-query-service.token';
import { By } from '@angular/platform-browser';
import { SearchFilterContainerComponent } from './search-filter-container.component';
import { MatMenuTrigger } from '@angular/material/menu';
import { SearchCategory } from '../../models/search-category.interface';
import { HarnessLoader } from '@angular/cdk/testing';
import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed';
import { MatInputHarness } from '@angular/material/input/testing';
import { MatMenuHarness } from '@angular/material/menu/testing';
import { MatButtonHarness } from '@angular/material/button/testing';
import { MatBadgeHarness } from '@angular/material/badge/testing';
const mockCategory: SearchCategory = {
id: 'queryName',
@@ -44,6 +49,7 @@ const mockCategory: SearchCategory = {
};
describe('SearchFilterContainerComponent', () => {
let loader: HarnessLoader;
let fixture: ComponentFixture<SearchFilterContainerComponent>;
let component: SearchFilterContainerComponent;
let queryBuilder: SearchHeaderQueryBuilderService;
@@ -54,10 +60,7 @@ describe('SearchFilterContainerComponent', () => {
beforeEach(() => {
TestBed.configureTestingModule({
imports: [
TranslateModule.forRoot(),
ContentTestingModule
],
imports: [TranslateModule.forRoot(), ContentTestingModule],
providers: [
{ provide: SearchService, useValue: searchMock },
{ provide: SEARCH_QUERY_SERVICE_TOKEN, useClass: SearchHeaderQueryBuilderService }
@@ -66,9 +69,10 @@ describe('SearchFilterContainerComponent', () => {
fixture = TestBed.createComponent(SearchFilterContainerComponent);
component = fixture.componentInstance;
queryBuilder = fixture.componentInstance['searchFilterQueryBuilder'];
component.col = {key: '123', type: 'text'};
component.col = { key: '123', type: 'text' };
spyOn(queryBuilder, 'getCategoryForColumn').and.returnValue(mockCategory);
fixture.detectChanges();
loader = TestbedHarnessEnvironment.loader(fixture);
});
afterEach(() => {
@@ -86,26 +90,23 @@ describe('SearchFilterContainerComponent', () => {
});
it('should set/update the active filter after the Apply button is clicked', async () => {
const menuButton: HTMLButtonElement = fixture.nativeElement.querySelector('[data-automation-id="filter-menu-button"]');
menuButton.click();
fixture.detectChanges();
await fixture.whenStable();
const menu = await loader.getHarness(MatMenuHarness);
await menu.open();
component.widgetContainer.componentRef.instance.value = 'searchText';
const applyButton = fixture.debugElement.query(By.css('#apply-filter-button'));
applyButton.triggerEventHandler('click', {});
fixture.detectChanges();
await fixture.whenStable();
const applyButton = await menu.getHarness(MatButtonHarness.with({ selector: '#apply-filter-button' }));
await applyButton.click();
expect(queryBuilder.getActiveFilters().length).toBe(1);
expect(queryBuilder.getActiveFilters()[0].key).toBe('name');
expect(queryBuilder.getActiveFilters()[0].value).toBe('searchText');
menuButton.click();
fixture.detectChanges();
await fixture.whenStable();
await menu.open();
component.widgetContainer.componentRef.instance.value = 'updated text';
applyButton.triggerEventHandler('click', {});
fixture.detectChanges();
await fixture.whenStable();
await applyButton.click();
expect(queryBuilder.getActiveFilters().length).toBe(1);
expect(queryBuilder.getActiveFilters()[0].key).toBe('name');
expect(queryBuilder.getActiveFilters()[0].value).toBe('updated text');
@@ -113,16 +114,15 @@ describe('SearchFilterContainerComponent', () => {
it('should remove active filter after the Clear button is clicked', async () => {
queryBuilder.setActiveFilter('name', 'searchText');
const menuButton: HTMLButtonElement = fixture.nativeElement.querySelector('[data-automation-id="filter-menu-button"]');
menuButton.click();
fixture.detectChanges();
await fixture.whenStable();
const menu = await loader.getHarness(MatMenuHarness);
await menu.open();
component.widgetContainer.componentRef.instance.value = 'searchText';
const fakeEvent = jasmine.createSpyObj('event', ['stopPropagation']);
const clearButton = fixture.debugElement.query(By.css('#clear-filter-button'));
clearButton.triggerEventHandler('click', fakeEvent);
fixture.detectChanges();
await fixture.whenStable();
const clearButton = await menu.getHarness(MatButtonHarness.with({ selector: '#clear-filter-button' }));
await clearButton.click();
expect(queryBuilder.getActiveFilters().length).toBe(0);
});
@@ -133,15 +133,13 @@ describe('SearchFilterContainerComponent', () => {
component.filterChange.subscribe(() => {
eventRaised = true;
});
const menuButton: HTMLButtonElement = fixture.nativeElement.querySelector('[data-automation-id="filter-menu-button"]');
menuButton.click();
fixture.detectChanges();
await fixture.whenStable();
const menu = await loader.getHarness(MatMenuHarness);
await menu.open();
component.widgetContainer.componentRef.instance.value = 'searchText';
const widgetContainer = fixture.debugElement.query(By.css('adf-search-widget-container'));
widgetContainer.triggerEventHandler('keypress', {key: 'Enter'});
widgetContainer.triggerEventHandler('keypress', { key: 'Enter' });
fixture.detectChanges();
await fixture.whenStable();
@@ -150,39 +148,33 @@ describe('SearchFilterContainerComponent', () => {
});
it('should hide the red dot after the filter is cleared', async () => {
const badge: HTMLElement = fixture.nativeElement.querySelector(`[data-automation-id="filter-menu-button"] .mat-badge-content`);
expect(window.getComputedStyle(badge).display).toBe('none');
const badge = await loader.getHarness(MatBadgeHarness);
expect(await badge.isHidden()).toBe(true);
const menu = await loader.getHarness(MatMenuHarness);
await menu.open();
const menuButton: HTMLButtonElement = fixture.nativeElement.querySelector('[data-automation-id="filter-menu-button"]');
menuButton.click();
fixture.detectChanges();
await fixture.whenStable();
component.widgetContainer.componentRef.instance.value = 'searchText';
const widgetContainer = fixture.debugElement.query(By.css('adf-search-widget-container'));
widgetContainer.triggerEventHandler('keypress', {key: 'Enter'});
widgetContainer.triggerEventHandler('keypress', { key: 'Enter' });
fixture.detectChanges();
await fixture.whenStable();
expect(window.getComputedStyle(badge).display).not.toBe('none');
expect(await badge.isHidden()).toBe(false);
menuButton.click();
fixture.detectChanges();
await fixture.whenStable();
const fakeEvent = jasmine.createSpyObj('event', ['stopPropagation']);
const clearButton = fixture.debugElement.query(By.css('#clear-filter-button'));
clearButton.triggerEventHandler('click', fakeEvent);
fixture.detectChanges();
await fixture.whenStable();
expect(window.getComputedStyle(badge).display).toBe('none');
await menu.open();
const clearButton = await menu.getHarness(MatButtonHarness.with({ selector: '#clear-filter-button' }));
await clearButton.click();
expect(await badge.isHidden()).toBe(true);
});
describe('Accessibility', () => {
it('should set up a focus trap on the filter when the menu is opened', async () => {
expect(component.focusTrap).toBeUndefined();
const menuButton: HTMLButtonElement = fixture.nativeElement.querySelector('[data-automation-id="filter-menu-button"]');
menuButton.click();
fixture.detectChanges();
const menu = await loader.getHarness(MatMenuHarness);
await menu.open();
expect(component.focusTrap).toBeDefined();
// eslint-disable-next-line no-underscore-dangle
@@ -190,32 +182,19 @@ describe('SearchFilterContainerComponent', () => {
});
it('should focus the input element when the menu is opened', async () => {
const menuButton: HTMLButtonElement = fixture.nativeElement.querySelector('[data-automation-id="filter-menu-button"]');
menuButton.click();
fixture.detectChanges();
await fixture.whenStable();
const inputElement = fixture.debugElement.query(By.css('.mat-input-element'));
expect(document.activeElement).toBe(inputElement.nativeElement);
const menu = await loader.getHarness(MatMenuHarness);
await menu.open();
const input = await menu.getHarness(MatInputHarness);
expect(await input.isFocused()).toBe(true);
});
it('should focus the menu trigger when the menu is closed', async () => {
const menuButton: HTMLButtonElement = fixture.nativeElement.querySelector('[data-automation-id="filter-menu-button"]');
menuButton.click();
const menu = await loader.getHarness(MatMenuHarness);
await menu.open();
fixture.detectChanges();
await fixture.whenStable();
const matMenuTrigger = fixture.debugElement.query(By.directive(MatMenuTrigger)).injector.get(MatMenuTrigger);
matMenuTrigger.closeMenu();
fixture.detectChanges();
await fixture.whenStable();
const matMenuButton = fixture.debugElement.query(By.css('[data-automation-id="filter-menu-button"]'));
expect(document.activeElement).toBe(matMenuButton.nativeElement);
await menu.close();
expect(await menu.isFocused()).toBe(true);
});
});
});

View File

@@ -18,7 +18,7 @@
import { SearchFilterComponent } from './search-filter.component';
import { SearchQueryBuilderService } from '../../services/search-query-builder.service';
import { AppConfigService, TranslationService } from '@alfresco/adf-core';
import { SearchService } from '../../services/search.service';
import { SearchService } from '../../services/search.service';
import { Subject } from 'rxjs';
import { SearchFilterList } from '../../models/search-filter-list.model';
import { ComponentFixture, TestBed } from '@angular/core/testing';
@@ -40,8 +40,15 @@ import {
import { TranslateModule } from '@ngx-translate/core';
import { SearchFacetFiltersService } from '../../services/search-facet-filters.service';
import { SearchFacetFieldComponent } from '../search-facet-field/search-facet-field.component';
import { HarnessLoader } from '@angular/cdk/testing';
import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed';
import { MatExpansionPanelHarness } from '@angular/material/expansion/testing';
import { MatCheckboxHarness } from '@angular/material/checkbox/testing';
import { MatButtonHarness } from '@angular/material/button/testing';
import { MatInputHarness } from '@angular/material/input/testing';
describe('SearchFilterComponent', () => {
let loader: HarnessLoader;
let fixture: ComponentFixture<SearchFilterComponent>;
let component: SearchFilterComponent;
let queryBuilder: SearchQueryBuilderService;
@@ -53,21 +60,17 @@ describe('SearchFilterComponent', () => {
beforeEach(() => {
TestBed.configureTestingModule({
imports: [
TranslateModule.forRoot(),
ContentTestingModule
],
providers: [
{ provide: SearchService, useValue: searchMock }
]
imports: [TranslateModule.forRoot(), ContentTestingModule],
providers: [{ provide: SearchService, useValue: searchMock }]
});
searchFacetFiltersService = TestBed.inject(SearchFacetFiltersService);
queryBuilder = TestBed.inject(SearchQueryBuilderService);
fixture = TestBed.createComponent(SearchFilterComponent);
appConfigService = TestBed.inject(AppConfigService);
const translationService = fixture.debugElement.injector.get(TranslationService);
spyOn(translationService, 'instant').and.callFake((key) => key ? `${key}_translated` : null);
spyOn(translationService, 'instant').and.callFake((key) => (key ? `${key}_translated` : null));
component = fixture.componentInstance;
loader = TestbedHarnessEnvironment.loader(fixture);
});
afterEach(() => fixture.destroy());
@@ -79,27 +82,41 @@ describe('SearchFilterComponent', () => {
spyOn(queryBuilder, 'execute').and.stub();
queryBuilder.config = {
categories: [],
facetFields: { fields: [
facetFields: {
fields: [
{ label: 'f1', field: 'f1' },
{ label: 'f2', field: 'f2' }
]},
]
},
facetQueries: {
queries: []
}
};
searchFacetFiltersService.responseFacets = [
{ type: 'field', label: 'f1', field: 'f1', buckets: new SearchFilterList([
{ label: 'b1', count: 10, filterQuery: 'filter', checked: true },
{ label: 'b2', count: 1, filterQuery: 'filter2' }]) },
{
type: 'field',
label: 'f1',
field: 'f1',
buckets: new SearchFilterList([
{ label: 'b1', count: 10, filterQuery: 'filter', checked: true },
{ label: 'b2', count: 1, filterQuery: 'filter2' }
])
},
{ type: 'field', label: 'f2', field: 'f2', buckets: new SearchFilterList([]) }
];
queryBuilder.addUserFacetBucket('f1', searchFacetFiltersService.responseFacets[0].buckets.items[0]);
const serverResponseFields: any = [
{ type: 'field', label: 'f1', field: 'f1', buckets: [
{ label: 'b1', metrics: [{value: {count: 6}}], filterQuery: 'filter' },
{ label: 'b2', metrics: [{value: {count: 1}}], filterQuery: 'filter2' }] },
{
type: 'field',
label: 'f1',
field: 'f1',
buckets: [
{ label: 'b1', metrics: [{ value: { count: 6 } }], filterQuery: 'filter' },
{ label: 'b2', metrics: [{ value: { count: 1 } }], filterQuery: 'filter2' }
]
},
{ type: 'field', label: 'f2', field: 'f2', buckets: [] }
];
const data = {
@@ -123,27 +140,41 @@ describe('SearchFilterComponent', () => {
spyOn(queryBuilder, 'execute').and.stub();
queryBuilder.config = {
categories: [],
facetFields: { fields: [
facetFields: {
fields: [
{ label: 'f1', field: 'f1' },
{ label: 'f2', field: 'f2' }
]},
]
},
facetQueries: {
queries: []
}
};
searchFacetFiltersService.responseFacets = [
{ type: 'field', label: 'f1', field: 'f1', buckets: new SearchFilterList([
{ label: 'b1', count: 10, filterQuery: 'filter', checked: true },
{ label: 'b2', count: 1, filterQuery: 'filter2' }]) },
{
type: 'field',
label: 'f1',
field: 'f1',
buckets: new SearchFilterList([
{ label: 'b1', count: 10, filterQuery: 'filter', checked: true },
{ label: 'b2', count: 1, filterQuery: 'filter2' }
])
},
{ type: 'field', label: 'f2', field: 'f2', buckets: new SearchFilterList([]) }
];
searchFacetFiltersService.queryBuilder.addUserFacetBucket('f1', searchFacetFiltersService.responseFacets[0].buckets.items[0]);
const serverResponseFields: any = [
{ type: 'field', label: 'f1', field: 'f1', buckets: [
{ label: 'b1', metrics: [{value: {count: 6}}], filterQuery: 'filter' },
{ label: 'b2', metrics: [{value: {count: 1}}], filterQuery: 'filter2' }] },
{
type: 'field',
label: 'f1',
field: 'f1',
buckets: [
{ label: 'b1', metrics: [{ value: { count: 6 } }], filterQuery: 'filter' },
{ label: 'b2', metrics: [{ value: { count: 1 } }], filterQuery: 'filter2' }
]
},
{ type: 'field', label: 'f2', field: 'f2', buckets: [] }
];
const data = {
@@ -167,19 +198,27 @@ describe('SearchFilterComponent', () => {
spyOn(queryBuilder, 'execute').and.stub();
queryBuilder.config = {
categories: [],
facetFields: { fields: [
facetFields: {
fields: [
{ label: 'f1', field: 'f1' },
{ label: 'f2', field: 'f2' }
]},
]
},
facetQueries: {
queries: []
}
};
searchFacetFiltersService.responseFacets = [
{ type: 'field', label: 'f1', field: 'f1', buckets: new SearchFilterList([
{ label: 'b1', count: 10, filterQuery: 'filter', checked: true },
{ label: 'b2', count: 1, filterQuery: 'filter2' }]) },
{
type: 'field',
label: 'f1',
field: 'f1',
buckets: new SearchFilterList([
{ label: 'b1', count: 10, filterQuery: 'filter', checked: true },
{ label: 'b2', count: 1, filterQuery: 'filter2' }
])
},
{ type: 'field', label: 'f2', field: 'f2', buckets: new SearchFilterList() }
];
searchFacetFiltersService.queryBuilder.addUserFacetBucket('f1', searchFacetFiltersService.responseFacets[0].buckets.items[0]);
@@ -205,9 +244,10 @@ describe('SearchFilterComponent', () => {
const queryResponse = {
label: 'query response',
buckets: new SearchFilterList([
{ label: 'q1', query: 'q1', checked: true, metrics: [{value: {count: 1}}] },
{ label: 'q2', query: 'q2', checked: false, metrics: [{value: {count: 1}}] },
{ label: 'q3', query: 'q3', checked: true, metrics: [{value: {count: 1}}] }])
{ label: 'q1', query: 'q1', checked: true, metrics: [{ value: { count: 1 } }] },
{ label: 'q2', query: 'q2', checked: false, metrics: [{ value: { count: 1 } }] },
{ label: 'q3', query: 'q3', checked: true, metrics: [{ value: { count: 1 } }] }
])
} as any;
searchFacetFiltersService.responseFacets = [queryResponse];
@@ -222,10 +262,9 @@ describe('SearchFilterComponent', () => {
expect(entry.checked).toEqual(false);
}
});
});
});
describe('widgets', () => {
it('should have expandable categories', async () => {
fixture.detectChanges();
await fixture.whenStable();
@@ -235,24 +274,8 @@ describe('SearchFilterComponent', () => {
fixture.detectChanges();
await fixture.whenStable();
const panels = fixture.debugElement.queryAll(By.css('.mat-expansion-panel'));
const panels = await loader.getAllHarnesses(MatExpansionPanelHarness);
expect(panels.length).toBe(1);
const element: HTMLElement = panels[0].nativeElement;
(element.childNodes[0] as HTMLElement).click();
fixture.detectChanges();
await fixture.whenStable();
expect(element.classList.contains('mat-expanded')).toBeTruthy();
(element.childNodes[0] as HTMLElement).click();
fixture.detectChanges();
await fixture.whenStable();
expect(element.classList.contains('mat-expanded')).toEqual(false);
});
it('should not show the disabled widget', async () => {
@@ -262,7 +285,7 @@ describe('SearchFilterComponent', () => {
fixture.detectChanges();
await fixture.whenStable();
const panels = fixture.debugElement.queryAll(By.css('.mat-expansion-panel'));
const panels = await loader.getAllHarnesses(MatExpansionPanelHarness);
expect(panels.length).toBe(0);
});
@@ -273,21 +296,11 @@ describe('SearchFilterComponent', () => {
fixture.detectChanges();
await fixture.whenStable();
const panels = fixture.debugElement.queryAll(By.css('.mat-expansion-panel'));
const panels = await loader.getAllHarnesses(MatExpansionPanelHarness);
expect(panels.length).toBe(1);
const title = fixture.debugElement.query(By.css('.mat-expansion-panel-header-title'));
expect(title.nativeElement.innerText.trim()).toBe('Type');
const element: HTMLElement = panels[0].nativeElement;
expect(element.classList.contains('mat-expanded')).toBeTruthy();
(element.childNodes[0] as HTMLElement).click();
fixture.detectChanges();
await fixture.whenStable();
expect(element.classList.contains('mat-expanded')).toEqual(false);
expect(await panels[0].getTitle()).toBe('Type');
expect(await panels[0].isExpanded()).toBe(true);
});
it('should show the widgets only if configured', async () => {
@@ -297,11 +310,11 @@ describe('SearchFilterComponent', () => {
fixture.detectChanges();
await fixture.whenStable();
const panels = fixture.debugElement.queryAll(By.css('.mat-expansion-panel'));
const panels = await loader.getAllHarnesses(MatExpansionPanelHarness);
expect(panels.length).toBe(2);
const titleElements = fixture.debugElement.queryAll(By.css('.mat-expansion-panel-header-title'));
expect(titleElements.map(title => title.nativeElement.innerText.trim())).toEqual(['Name', 'Type']);
expect(await panels[0].getTitle()).toBe('Name');
expect(await panels[1].getTitle()).toBe('Type');
});
it('should be update the search query when name changed', async () => {
@@ -311,17 +324,19 @@ describe('SearchFilterComponent', () => {
fixture.detectChanges();
await fixture.whenStable();
let panels = fixture.debugElement.queryAll(By.css('.mat-expansion-panel'));
let panels = await loader.getAllHarnesses(MatExpansionPanelHarness);
expect(panels.length).toBe(6);
const inputElement = fixture.debugElement.query(By.css('[data-automation-id="expansion-panel-Name"] input'));
inputElement.triggerEventHandler('change', { target: { value: '*' } });
expect(queryBuilder.update).toHaveBeenCalled();
queryBuilder.executed.next(mockSearchResult);
fixture.detectChanges();
panels = fixture.debugElement.queryAll(By.css('.mat-expansion-panel'));
panels = await loader.getAllHarnesses(MatExpansionPanelHarness);
expect(panels.length).toBe(8);
});
@@ -332,19 +347,20 @@ describe('SearchFilterComponent', () => {
fixture.detectChanges();
await fixture.whenStable();
const inputElement = fixture.debugElement.query(By.css('[data-automation-id="expansion-panel-Name"] input'));
inputElement.triggerEventHandler('change', { target: { value: '*' } });
const input = await loader.getHarness(MatInputHarness);
await input.setValue('*');
queryBuilder.executed.next(getMockSearchResultWithResponseBucket());
fixture.detectChanges();
const panels = fixture.debugElement.queryAll(By.css('.mat-expansion-panel'));
const panels = await loader.getAllHarnesses(MatExpansionPanelHarness);
expect(panels.length).toBe(9);
});
it('should show the long facet options list with pagination', () => {
const panel = '[data-automation-id="expansion-panel-Size facet queries"]';
it('should show the long facet options list with pagination', async () => {
const showMoreButton = MatButtonHarness.with({ selector: `[title="SEARCH.FILTER.ACTIONS.SHOW-MORE"]` });
const showLessButton = MatButtonHarness.with({ selector: `[title="SEARCH.FILTER.ACTIONS.SHOW-LESS"]` });
appConfigService.config.search = searchFilter;
queryBuilder.resetToDefaults();
@@ -352,58 +368,51 @@ describe('SearchFilterComponent', () => {
queryBuilder.executed.next(mockSearchResult);
fixture.detectChanges();
let sizes = getAllMenus(`${panel} mat-checkbox`, fixture);
expect(sizes).toEqual(stepOne);
const panel = await loader.getHarness(
MatExpansionPanelHarness.with({
selector: `[data-automation-id="expansion-panel-Size facet queries"]`
})
);
let moreButton = fixture.debugElement.query(By.css(`${panel} button[title="SEARCH.FILTER.ACTIONS.SHOW-MORE"]`));
let lessButton = fixture.debugElement.query(By.css(`${panel} button[title="SEARCH.FILTER.ACTIONS.SHOW-LESS"]`));
let sizes = await panel.getAllHarnesses(MatCheckboxHarness);
let sizeLabels = await Promise.all(sizes.map((element) => element.getLabelText()));
expect(sizeLabels).toEqual(stepOne);
expect(lessButton).toEqual(null);
expect(moreButton).toBeDefined();
let moreButton = await loader.getHarness(showMoreButton);
expect(await loader.hasHarness(showLessButton)).toBe(false);
moreButton.triggerEventHandler('click', {});
fixture.detectChanges();
await moreButton.click();
sizes = getAllMenus(`${panel} mat-checkbox`, fixture);
expect(sizes).toEqual(stepTwo);
sizes = await panel.getAllHarnesses(MatCheckboxHarness);
sizeLabels = await Promise.all(sizes.map((element) => element.getLabelText()));
expect(sizeLabels).toEqual(stepTwo);
moreButton = fixture.debugElement.query(By.css(`${panel} button[title="SEARCH.FILTER.ACTIONS.SHOW-MORE"]`));
lessButton = fixture.debugElement.query(By.css(`${panel} button[title="SEARCH.FILTER.ACTIONS.SHOW-LESS"]`));
expect(lessButton).toBeDefined();
expect(moreButton).toBeDefined();
moreButton = await loader.getHarness(showMoreButton);
expect(await loader.hasHarness(showLessButton)).toBe(true);
await moreButton.click();
moreButton.triggerEventHandler('click', {});
fixture.detectChanges();
sizes = getAllMenus(`${panel} mat-checkbox`, fixture);
sizes = await panel.getAllHarnesses(MatCheckboxHarness);
sizeLabels = await Promise.all(sizes.map((element) => element.getLabelText()));
expect(sizeLabels).toEqual(stepThree);
expect(sizes).toEqual(stepThree);
expect(await loader.hasHarness(showMoreButton)).toBe(false);
let lessButton = await loader.getHarness(showLessButton);
await lessButton.click();
moreButton = fixture.debugElement.query(By.css(`${panel} button[title="SEARCH.FILTER.ACTIONS.SHOW-MORE"]`));
lessButton = fixture.debugElement.query(By.css(`${panel} button[title="SEARCH.FILTER.ACTIONS.SHOW-LESS"]`));
expect(lessButton).toBeDefined();
expect(moreButton).toEqual(null);
sizes = await panel.getAllHarnesses(MatCheckboxHarness);
sizeLabels = await Promise.all(sizes.map((element) => element.getLabelText()));
expect(sizeLabels).toEqual(stepTwo);
lessButton.triggerEventHandler('click', {});
fixture.detectChanges();
expect(await loader.hasHarness(showMoreButton)).toBe(true);
lessButton = await loader.getHarness(showLessButton);
await lessButton.click();
sizes = getAllMenus(`${panel} mat-checkbox`, fixture);
expect(sizes).toEqual(stepTwo);
sizes = await panel.getAllHarnesses(MatCheckboxHarness);
sizeLabels = await Promise.all(sizes.map((element) => element.getLabelText()));
expect(sizeLabels).toEqual(stepOne);
moreButton = fixture.debugElement.query(By.css(`${panel} button[title="SEARCH.FILTER.ACTIONS.SHOW-MORE"]`));
lessButton = fixture.debugElement.query(By.css(`${panel} button[title="SEARCH.FILTER.ACTIONS.SHOW-LESS"]`));
expect(lessButton).toBeDefined();
expect(moreButton).toBeDefined();
lessButton.triggerEventHandler('click', {});
fixture.detectChanges();
sizes = getAllMenus(`${panel} mat-checkbox`, fixture);
expect(sizes).toEqual(stepOne);
moreButton = fixture.debugElement.query(By.css(`${panel} button[title="SEARCH.FILTER.ACTIONS.SHOW-MORE"]`));
lessButton = fixture.debugElement.query(By.css(`${panel} button[title="SEARCH.FILTER.ACTIONS.SHOW-LESS"]`));
expect(lessButton).toEqual(null);
expect(moreButton).toBeDefined();
expect(await loader.hasHarness(showMoreButton)).toBe(true);
expect(await loader.hasHarness(showLessButton)).toBe(false);
});
it('should not show facets if filter is not available', () => {
@@ -422,8 +431,8 @@ describe('SearchFilterComponent', () => {
expect(facetElement).toEqual(null);
});
it('should search the facets options and select it', () => {
const panel = '[data-automation-id="expansion-panel-Size facet queries"]';
it('should search the facets options and select it', async () => {
const panelSelector = '[data-automation-id="expansion-panel-Size facet queries"]';
appConfigService.config.search = searchFilter;
queryBuilder.resetToDefaults();
fixture.detectChanges();
@@ -432,41 +441,39 @@ describe('SearchFilterComponent', () => {
spyOn(queryBuilder, 'update').and.stub();
const inputElement = fixture.debugElement.query(By.css(`${panel} input`));
inputElement.nativeElement.value = 'Extra';
inputElement.nativeElement.dispatchEvent(new Event('input'));
fixture.detectChanges();
const panel = await loader.getHarness(
MatExpansionPanelHarness.with({
selector: panelSelector
})
);
let filteredMenu = getAllMenus(`${panel} mat-checkbox`, fixture);
expect(filteredMenu).toEqual(['Extra Small (10239)']);
const input = await panel.getHarness(MatInputHarness);
await input.setValue('Extra');
inputElement.nativeElement.value = 'my';
inputElement.nativeElement.dispatchEvent(new Event('input'));
fixture.detectChanges();
let checkboxes = await panel.getAllHarnesses(MatCheckboxHarness);
expect(checkboxes.length).toBe(1);
expect(await checkboxes[0].getLabelText()).toBe('Extra Small (10239)');
filteredMenu = getAllMenus(`${panel} mat-checkbox`, fixture);
expect(filteredMenu).toEqual(filteredResult);
await input.setValue('my');
const clearButton = fixture.debugElement.query(By.css(`${panel} mat-form-field button`));
clearButton.triggerEventHandler('click', {});
fixture.detectChanges();
checkboxes = await panel.getAllHarnesses(MatCheckboxHarness);
let labels = await Promise.all(checkboxes.map((element) => element.getLabelText()));
expect(labels).toEqual(filteredResult);
filteredMenu = getAllMenus(`${panel} mat-checkbox`, fixture);
expect(filteredMenu).toEqual(stepOne);
const clearButton = await panel.getHarness(MatButtonHarness.with({ selector: '[title="SEARCH.FILTER.BUTTONS.CLEAR"]' }));
await clearButton.click();
const firstOption = fixture.debugElement.query(By.css(`${panel} mat-checkbox`));
firstOption.triggerEventHandler('change', { checked: true });
fixture.detectChanges();
const checkedOption = fixture.debugElement.query(By.css(`${panel} mat-checkbox.mat-checkbox-checked`));
expect(checkedOption.nativeElement.innerText).toEqual('Extra Small (10239)');
checkboxes = await panel.getAllHarnesses(MatCheckboxHarness);
labels = await Promise.all(checkboxes.map((element) => element.getLabelText()));
expect(labels).toEqual(stepOne);
await checkboxes[0].check();
expect(queryBuilder.update).toHaveBeenCalledTimes(1);
});
it('should preserve the filter state if other fields edited', () => {
const panel1 = '[data-automation-id="expansion-panel-Size facet queries"]';
const panel2 = '[data-automation-id="expansion-panel-Type facet queries"]';
it('should preserve the filter state if other fields edited', async () => {
const panel1Selector = '[data-automation-id="expansion-panel-Size facet queries"]';
const panel2selector = '[data-automation-id="expansion-panel-Type facet queries"]';
appConfigService.config.search = searchFilter;
queryBuilder.resetToDefaults();
fixture.detectChanges();
@@ -474,39 +481,39 @@ describe('SearchFilterComponent', () => {
fixture.detectChanges();
spyOn(queryBuilder, 'update').and.stub();
const inputElement = fixture.debugElement.query(By.css(`${panel1} input`));
const inputElement = fixture.debugElement.query(By.css(`${panel1Selector} input`));
inputElement.nativeElement.value = 'my';
inputElement.nativeElement.dispatchEvent(new Event('input'));
fixture.detectChanges();
let filteredMenu = getAllMenus(`${panel1} mat-checkbox`, fixture);
expect(filteredMenu).toEqual(filteredResult);
const panel1 = await loader.getHarness(MatExpansionPanelHarness.with({ selector: panel1Selector }));
const firstOption = fixture.debugElement.query(By.css(`${panel1} mat-checkbox`));
firstOption.triggerEventHandler('change', { checked: true });
fixture.detectChanges();
let checkboxes = await panel1.getAllHarnesses(MatCheckboxHarness);
let labels = await Promise.all(checkboxes.map((element) => element.getLabelText()));
expect(labels).toEqual(filteredResult);
let panel1CheckedOption = fixture.debugElement.query(By.css(`${panel1} mat-checkbox.mat-checkbox-checked`));
expect(panel1CheckedOption.nativeElement.innerText).toEqual('my1 (806)');
await checkboxes[0].check();
expect(await checkboxes[0].isChecked()).toBe(true);
expect(await checkboxes[0].getLabelText()).toBe('my1 (806)');
const panel2Options = fixture.debugElement.query(By.css(`${panel2} mat-checkbox`));
panel2Options.triggerEventHandler('change', { checked: true });
fixture.detectChanges();
const panel2 = await loader.getHarness(MatExpansionPanelHarness.with({ selector: panel2selector }));
checkboxes = await panel2.getAllHarnesses(MatCheckboxHarness);
await checkboxes[0].check();
expect(await checkboxes[0].isChecked()).toBe(true);
expect(await checkboxes[0].getLabelText()).toBe('SEARCH.FACET_QUERIES.MIMETYPE (13)');
const panel2CheckedOption = fixture.debugElement.query(By.css(`${panel2} mat-checkbox.mat-checkbox-checked`));
expect(panel2CheckedOption.nativeElement.innerText).toEqual('SEARCH.FACET_QUERIES.MIMETYPE (13)');
checkboxes = await panel1.getAllHarnesses(MatCheckboxHarness);
labels = await Promise.all(checkboxes.map((element) => element.getLabelText()));
expect(labels).toEqual(filteredResult);
filteredMenu = getAllMenus(`${panel1} mat-checkbox`, fixture);
expect(filteredMenu).toEqual(filteredResult);
panel1CheckedOption = fixture.debugElement.query(By.css(`${panel1} mat-checkbox.mat-checkbox-checked`));
expect(panel1CheckedOption.nativeElement.innerText).toEqual('my1 (806)');
const checkedOption = await panel1.getHarness(MatCheckboxHarness.with({ checked: true }));
expect(await checkedOption.getLabelText()).toBe('my1 (806)');
expect(queryBuilder.update).toHaveBeenCalledTimes(2);
});
it('should reset the query fragments when reset All is clicked', () => {
component.queryBuilder.queryFragments = { fragment1 : 'value1'};
component.queryBuilder.queryFragments = { fragment1: 'value1' };
appConfigService.config.search = searchFilter;
searchFacetFiltersService.responseFacets = [];
component.displayResetButton = true;
@@ -519,11 +526,10 @@ describe('SearchFilterComponent', () => {
expect(component.queryBuilder.queryFragments).toEqual({});
expect(queryBuilder.resetToDefaults).toHaveBeenCalled();
});
});
});
export const getAllMenus = (regex, fixture: ComponentFixture<any>): string[] => {
const elements = fixture.debugElement.queryAll(By.css(regex));
return Array.from(elements).map(element => element.nativeElement.innerText);
return Array.from(elements).map((element) => element.nativeElement.innerText);
};

View File

@@ -23,8 +23,13 @@ import { SEARCH_QUERY_SERVICE_TOKEN } from '../../search-query-service.token';
import { SearchQueryBuilderService } from '../../services/search-query-builder.service';
import { SearchForm } from '../../models/search-form.interface';
import { By } from '@angular/platform-browser';
import { HarnessLoader } from '@angular/cdk/testing';
import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed';
import { MatMenuHarness } from '@angular/material/menu/testing';
import { MatButtonHarness } from '@angular/material/button/testing';
describe('SearchFormComponent', () => {
let loader: HarnessLoader;
let fixture: ComponentFixture<SearchFormComponent>;
let component: SearchFormComponent;
let queryBuilder: SearchQueryBuilderService;
@@ -36,62 +41,62 @@ describe('SearchFormComponent', () => {
beforeEach(() => {
TestBed.configureTestingModule({
imports: [
TranslateModule.forRoot(),
ContentTestingModule
],
providers: [
{ provide: SEARCH_QUERY_SERVICE_TOKEN, useClass: SearchQueryBuilderService }
]
imports: [TranslateModule.forRoot(), ContentTestingModule],
providers: [{ provide: SEARCH_QUERY_SERVICE_TOKEN, useClass: SearchQueryBuilderService }]
});
fixture = TestBed.createComponent(SearchFormComponent);
component = fixture.componentInstance;
queryBuilder = TestBed.inject<SearchQueryBuilderService>(SEARCH_QUERY_SERVICE_TOKEN);
queryBuilder.searchForms.next(mockSearchForms);
fixture.detectChanges();
loader = TestbedHarnessEnvironment.loader(fixture);
});
const getTitle = () => fixture.debugElement.query(By.css('.adf-search-form-title'))?.nativeElement as HTMLSpanElement;
it('should show search forms', () => {
const title = fixture.debugElement.query(By.css('.adf-search-form-title'));
expect(title.nativeElement.innerText).toContain(mockSearchForms[1].name);
const title = getTitle();
expect(title.innerText).toContain(mockSearchForms[1].name);
});
it('should emit on form change', (done) => {
it('should emit on form change', async () => {
spyOn(queryBuilder, 'updateSelectedConfiguration').and.stub();
component.formChange.subscribe((form) => {
expect(form).toEqual(mockSearchForms[2]);
expect(queryBuilder.updateSelectedConfiguration).toHaveBeenCalled();
done();
});
const button = fixture.debugElement.query(By.css('.adf-search-form')).nativeElement;
button.click();
fixture.detectChanges();
let changedForm: SearchForm;
component.formChange.subscribe((form) => (changedForm = form));
const matOption = fixture.debugElement.queryAll(By.css('.mat-menu-item'))[2].nativeElement;
matOption.click();
const menu = await loader.getHarness(MatMenuHarness);
await menu.open();
const menuItems = await menu.getItems();
expect(menuItems.length).toEqual(3);
await menuItems[2].click();
expect(changedForm).toEqual(mockSearchForms[2]);
expect(queryBuilder.updateSelectedConfiguration).toHaveBeenCalled();
});
it('should not show menu if only one config found', () => {
it('should not show menu if only one config found', async () => {
queryBuilder.searchForms.next([{ name: 'one', selected: true, default: true, index: 0 }]);
fixture.detectChanges();
const button = fixture.debugElement.query(By.css('.adf-search-form')).nativeElement;
button.click();
const button = await loader.getHarness(MatButtonHarness.with({ selector: '.adf-search-form' }));
await button.click();
const title = fixture.debugElement.query(By.css('.adf-search-form-title'));
expect(title.nativeElement.innerText).toContain('one');
const title = getTitle();
expect(title.innerText).toContain('one');
fixture.detectChanges();
const matOption = fixture.debugElement.query(By.css('.mat-menu-item'));
expect(matOption).toBe(null, 'should not show mat menu');
const hasMenu = await loader.hasHarness(MatMenuHarness);
expect(hasMenu).toBe(false);
});
it('should not display search form if no form configured', () => {
queryBuilder.searchForms.next([]);
fixture.detectChanges();
const field = fixture.debugElement.query(By.css('.adf-search-form-title'));
expect(field).toEqual(null, 'search form displayed for empty configuration');
const field = getTitle();
expect(field).toBeUndefined();
});
});

View File

@@ -1,6 +1,6 @@
<div class="adf-search-logical-filter-container">
<div *ngFor="let field of fields" class="adf-search-input">
<mat-label>{{('SEARCH.LOGICAL_SEARCH.' + field + '_LABEL') | translate}}</mat-label>
<mat-label data-automation-id="adf-search-input-label">{{('SEARCH.LOGICAL_SEARCH.' + field + '_LABEL') | translate}}</mat-label>
<input type="text"
[(ngModel)]="searchCondition[LogicalSearchFields[field]]"
placeholder="{{ ('SEARCH.LOGICAL_SEARCH.' + field + '_HINT') | translate }}"

View File

@@ -28,10 +28,7 @@ describe('SearchLogicalFilterComponent', () => {
beforeEach(() => {
TestBed.configureTestingModule({
declarations: [SearchLogicalFilterComponent],
imports: [
TranslateModule.forRoot(),
ContentTestingModule
]
imports: [TranslateModule.forRoot(), ContentTestingModule]
});
fixture = TestBed.createComponent(SearchLogicalFilterComponent);
@@ -62,7 +59,7 @@ describe('SearchLogicalFilterComponent', () => {
* @returns list of labels
*/
function getInputsLabels(): string[] {
return fixture.debugElement.queryAll(By.css('.adf-search-input mat-label')).map((label) => label.nativeElement.innerText);
return fixture.debugElement.queryAll(By.css(`[data-automation-id="adf-search-input-label"]`)).map((label) => label.nativeElement.innerText);
}
/**
@@ -164,7 +161,9 @@ describe('SearchLogicalFilterComponent', () => {
enterNewPhrase('test5 test6 ', 2);
component.submitValues();
expect(component.context.update).toHaveBeenCalled();
expect(component.context.queryFragments[component.id]).toBe('((NOT field1:"test5" AND NOT field1:"test6") AND (NOT field2:"test5" AND NOT field2:"test6"))');
expect(component.context.queryFragments[component.id]).toBe(
'((NOT field1:"test5" AND NOT field1:"test6") AND (NOT field2:"test5" AND NOT field2:"test6"))'
);
});
it('should form correct query from match exact field and trim it', () => {

View File

@@ -20,22 +20,26 @@ import { SearchFilterList } from '../../models/search-filter-list.model';
import { ContentTestingModule } from '../../../testing/content.testing.module';
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { sizeOptions, stepOne, stepThree } from '../../../mock';
import { By } from '@angular/platform-browser';
import { TranslateModule } from '@ngx-translate/core';
import { HarnessLoader, TestKey } from '@angular/cdk/testing';
import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed';
import { MatCheckboxHarness } from '@angular/material/checkbox/testing';
import { By } from '@angular/platform-browser';
describe('SearchCheckListComponent', () => {
let loader: HarnessLoader;
let fixture: ComponentFixture<SearchCheckListComponent>;
let component: SearchCheckListComponent;
beforeEach(() => {
TestBed.configureTestingModule({
imports: [
TranslateModule.forRoot(),
ContentTestingModule
]
imports: [TranslateModule.forRoot(), ContentTestingModule]
});
fixture = TestBed.createComponent(SearchCheckListComponent);
component = fixture.componentInstance;
fixture.detectChanges();
loader = TestbedHarnessEnvironment.loader(fixture);
});
it('should setup options from settings', () => {
@@ -49,7 +53,7 @@ describe('SearchCheckListComponent', () => {
expect(component.options.items).toEqual(options);
});
it('should handle enter key as click on checkboxes', () => {
it('should handle enter key as click on checkboxes', async () => {
component.options = new SearchFilterList<SearchListOption>([
{ name: 'Folder', value: `TYPE:'cm:folder'`, checked: false },
{ name: 'Document', value: `TYPE:'cm:content'`, checked: false }
@@ -58,13 +62,12 @@ describe('SearchCheckListComponent', () => {
component.ngOnInit();
fixture.detectChanges();
const optionElements = fixture.debugElement.queryAll(By.css('mat-checkbox'));
const options = await loader.getAllHarnesses(MatCheckboxHarness);
await (await options[0].host()).sendKeys(TestKey.ENTER);
expect(await options[0].isChecked()).toBe(true);
optionElements[0].triggerEventHandler('keydown.enter', {});
expect(component.options.items[0].checked).toBeTruthy();
optionElements[0].triggerEventHandler('keydown.enter', {});
expect(component.options.items[0].checked).toBeFalsy();
await (await options[0].host()).sendKeys(TestKey.ENTER);
expect(await options[0].isChecked()).toBe(false);
});
it('should setup operator from the settings', () => {
@@ -95,21 +98,13 @@ describe('SearchCheckListComponent', () => {
spyOn(component.context, 'update').and.stub();
component.changeHandler(
{ checked: true } as any,
component.options.items[0]
);
component.changeHandler({ checked: true } as any, component.options.items[0]);
expect(component.context.queryFragments[component.id]).toEqual(`TYPE:'cm:folder'`);
component.changeHandler(
{ checked: true } as any,
component.options.items[1]
);
component.changeHandler({ checked: true } as any, component.options.items[1]);
expect(component.context.queryFragments[component.id]).toEqual(
`TYPE:'cm:folder' OR TYPE:'cm:content'`
);
expect(component.context.queryFragments[component.id]).toEqual(`TYPE:'cm:folder' OR TYPE:'cm:content'`);
});
it('should reset selected boxes', () => {
@@ -147,7 +142,7 @@ describe('SearchCheckListComponent', () => {
});
describe('Pagination', () => {
it('should show 5 items when pageSize not defined', () => {
it('should show 5 items when pageSize not defined', async () => {
component.id = 'checklist';
component.context = {
queryFragments: {
@@ -160,13 +155,14 @@ describe('SearchCheckListComponent', () => {
component.ngOnInit();
fixture.detectChanges();
const optionElements = fixture.debugElement.queryAll(By.css('mat-checkbox'));
expect(optionElements.length).toEqual(5);
const labels = Array.from(optionElements).map(element => element.nativeElement.innerText);
const options = await loader.getAllHarnesses(MatCheckboxHarness);
expect(options.length).toEqual(5);
const labels = await Promise.all(Array.from(options).map(async (element) => element.getLabelText()));
expect(labels).toEqual(stepOne);
});
it('should show all items when pageSize is high', () => {
it('should show all items when pageSize is high', async () => {
component.id = 'checklist';
component.context = {
queryFragments: {
@@ -178,14 +174,15 @@ describe('SearchCheckListComponent', () => {
component.ngOnInit();
fixture.detectChanges();
const optionElements = fixture.debugElement.queryAll(By.css('mat-checkbox'));
expect(optionElements.length).toEqual(13);
const labels = Array.from(optionElements).map(element => element.nativeElement.innerText);
const options = await loader.getAllHarnesses(MatCheckboxHarness);
expect(options.length).toEqual(13);
const labels = await Promise.all(Array.from(options).map(async (element) => element.getLabelText()));
expect(labels).toEqual(stepThree);
});
});
it('should able to check/reset the checkbox', () => {
it('should able to check/reset the checkbox', async () => {
component.id = 'checklist';
component.context = {
queryFragments: {
@@ -198,16 +195,15 @@ describe('SearchCheckListComponent', () => {
component.ngOnInit();
fixture.detectChanges();
const optionElements = fixture.debugElement.query(By.css('mat-checkbox'));
optionElements.triggerEventHandler('change', { checked: true });
const checkbox = await loader.getHarness(MatCheckboxHarness);
await checkbox.check();
expect(component.submitValues).toHaveBeenCalled();
const clearAllElement = fixture.debugElement.query(By.css('button[title="SEARCH.FILTER.ACTIONS.CLEAR-ALL"]'));
clearAllElement.triggerEventHandler('click', {} );
clearAllElement.triggerEventHandler('click', {});
fixture.detectChanges();
const selectedElements = fixture.debugElement.queryAll(By.css('.mat-checkbox-checked'));
expect(selectedElements.length).toBe(0);
expect(await checkbox.isChecked()).toBe(false);
});
});

View File

@@ -16,29 +16,31 @@
*/
import { sizeOptions, stepOne, stepThree } from '../../../mock';
import { By } from '@angular/platform-browser';
import { SearchRadioComponent } from './search-radio.component';
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { ContentTestingModule } from '../../../testing/content.testing.module';
import { TranslateModule } from '@ngx-translate/core';
import { HarnessLoader } from '@angular/cdk/testing';
import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed';
import { MatRadioButtonHarness, MatRadioGroupHarness } from '@angular/material/radio/testing';
describe('SearchRadioComponent', () => {
let fixture: ComponentFixture<SearchRadioComponent>;
let component: SearchRadioComponent;
let loader: HarnessLoader;
let fixture: ComponentFixture<SearchRadioComponent>;
let component: SearchRadioComponent;
beforeEach(() => {
TestBed.configureTestingModule({
imports: [
TranslateModule.forRoot(),
ContentTestingModule
]
});
fixture = TestBed.createComponent(SearchRadioComponent);
component = fixture.componentInstance;
});
beforeEach(() => {
TestBed.configureTestingModule({
imports: [TranslateModule.forRoot(), ContentTestingModule]
});
fixture = TestBed.createComponent(SearchRadioComponent);
component = fixture.componentInstance;
describe('Pagination', () => {
it('should show 5 items when pageSize not defined', () => {
loader = TestbedHarnessEnvironment.loader(fixture);
});
describe('Pagination', () => {
it('should show 5 items when pageSize not defined', async () => {
component.id = 'radio';
component.context = {
queryFragments: {
@@ -51,13 +53,14 @@ describe('SearchRadioComponent', () => {
component.ngOnInit();
fixture.detectChanges();
const optionElements = fixture.debugElement.queryAll(By.css('mat-radio-button'));
expect(optionElements.length).toEqual(5);
const labels = Array.from(optionElements).map(element => element.nativeElement.innerText);
const options = await loader.getAllHarnesses(MatRadioButtonHarness);
expect(options.length).toEqual(5);
const labels = await Promise.all(Array.from(options).map(async (element) => element.getLabelText()));
expect(labels).toEqual(stepOne);
});
it('should show all items when pageSize is high', () => {
it('should show all items when pageSize is high', async () => {
component.id = 'radio';
component.context = {
queryFragments: {
@@ -69,14 +72,15 @@ describe('SearchRadioComponent', () => {
component.ngOnInit();
fixture.detectChanges();
const optionElements = fixture.debugElement.queryAll(By.css('mat-radio-button'));
expect(optionElements.length).toEqual(13);
const labels = Array.from(optionElements).map(element => element.nativeElement.innerText);
const options = await loader.getAllHarnesses(MatRadioButtonHarness);
expect(options.length).toEqual(13);
const labels = await Promise.all(Array.from(options).map(async (element) => element.getLabelText()));
expect(labels).toEqual(stepThree);
});
});
it('should able to check the radio button', async () => {
it('should able to check the radio button', async () => {
component.id = 'radio';
component.context = {
queryFragments: {
@@ -85,15 +89,10 @@ describe('SearchRadioComponent', () => {
update: () => {}
} as any;
component.settings = { options: sizeOptions } as any;
spyOn(component.context, 'update').and.stub();
fixture.detectChanges();
await fixture.whenStable();
const optionElements = fixture.debugElement.query(By.css('mat-radio-group'));
optionElements.triggerEventHandler('change', { value: sizeOptions[0].value });
fixture.detectChanges();
const group = await loader.getHarness(MatRadioGroupHarness);
await group.checkRadioButton({ selector: `[data-automation-id="search-radio-${sizeOptions[0].name}"]` });
expect(component.context.update).toHaveBeenCalled();
expect(component.context.queryFragments[component.id]).toBe(sizeOptions[0].value);
});
});

View File

@@ -19,17 +19,19 @@ import { SearchTextComponent } from './search-text.component';
import { ContentTestingModule } from '../../../testing/content.testing.module';
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { TranslateModule } from '@ngx-translate/core';
import { HarnessLoader } from '@angular/cdk/testing';
import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed';
import { MatInputHarness } from '@angular/material/input/testing';
import { MatButtonHarness } from '@angular/material/button/testing';
describe('SearchTextComponent', () => {
let loader: HarnessLoader;
let fixture: ComponentFixture<SearchTextComponent>;
let component: SearchTextComponent;
beforeEach(() => {
TestBed.configureTestingModule({
imports: [
TranslateModule.forRoot(),
ContentTestingModule
]
imports: [TranslateModule.forRoot(), ContentTestingModule]
});
fixture = TestBed.createComponent(SearchTextComponent);
component = fixture.componentInstance;
@@ -44,6 +46,8 @@ describe('SearchTextComponent', () => {
queryFragments: {},
update: () => {}
} as any;
loader = TestbedHarnessEnvironment.loader(fixture);
});
it('should parse value from the context at startup', () => {
@@ -100,16 +104,19 @@ describe('SearchTextComponent', () => {
fixture.detectChanges();
await fixture.whenStable();
expect(component.value).toEqual('secret.pdf');
const input = fixture.debugElement.nativeElement.querySelector('.mat-form-field-infix input');
expect(input.value).toEqual('secret.pdf');
const input = await loader.getHarness(MatInputHarness);
expect(await input.getValue()).toBe('secret.pdf');
});
it('should be able to reset by clicking clear button', async () => {
it('should be able to reset by clicking clear button', async () => {
component.context.queryFragments[component.id] = `cm:name:'secret.pdf'`;
fixture.detectChanges();
await fixture.whenStable();
const clearElement = fixture.debugElement.nativeElement.querySelector('button');
clearElement.click();
const clearButton = await loader.getHarness(MatButtonHarness);
await clearButton.click();
expect(component.value).toBe('');
expect(component.context.queryFragments[component.id]).toBe('');
});

View File

@@ -15,13 +15,12 @@
* limitations under the License.
*/
import { DebugElement } from '@angular/core';
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { By } from '@angular/platform-browser';
import { DropdownSitesComponent, Relations } from './sites-dropdown.component';
import { AuthenticationService } from '@alfresco/adf-core';
import { of } from 'rxjs';
import { getFakeSitePaging,
import {
getFakeSitePaging,
getFakeSitePagingNoMoreItems,
getFakeSitePagingFirstPage,
getFakeSitePagingLastPage,
@@ -30,6 +29,10 @@ import { getFakeSitePaging,
import { ContentTestingModule } from '../testing/content.testing.module';
import { TranslateModule } from '@ngx-translate/core';
import { SitesService } from '../common/services/sites.service';
import { HarnessLoader } from '@angular/cdk/testing';
import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed';
import { MatSelectHarness } from '@angular/material/select/testing';
import { SiteEntry } from '@alfresco/js-api';
const customSiteList = {
list: {
@@ -51,70 +54,57 @@ const customSiteList = {
};
describe('DropdownSitesComponent', () => {
let loader: HarnessLoader;
let component: any;
let fixture: ComponentFixture<DropdownSitesComponent>;
let debug: DebugElement;
let element: HTMLElement;
let siteService: SitesService;
let authService: AuthenticationService;
beforeEach(() => {
TestBed.configureTestingModule({
imports: [
TranslateModule.forRoot(),
ContentTestingModule
]
imports: [TranslateModule.forRoot(), ContentTestingModule]
});
});
describe('Rendering tests', () => {
describe('Infinite Loading', () => {
beforeEach(() => {
siteService = TestBed.inject(SitesService);
fixture = TestBed.createComponent(DropdownSitesComponent);
debug = fixture.debugElement;
element = fixture.nativeElement;
component = fixture.componentInstance;
spyOn(siteService, 'getSites').and.returnValue(of(getFakeSitePaging()));
loader = TestbedHarnessEnvironment.loader(fixture);
});
it('Should show loading item if there are more itemes', async () => {
it('Should show loading item if there are more items', async () => {
fixture.detectChanges();
await fixture.whenStable();
expect(element.querySelector('[data-automation-id="site-loading"]')).toBeDefined();
});
it('Should not show loading item if there are more itemes', async () => {
it('Should not show loading item if there are more items', async () => {
fixture.detectChanges();
await fixture.whenStable();
fixture.detectChanges();
expect(element.querySelector('[data-automation-id="site-loading"]')).toBeNull();
});
});
describe('Sites', () => {
beforeEach(() => {
siteService = TestBed.inject(SitesService);
spyOn(siteService, 'getSites').and.returnValue(of(getFakeSitePagingNoMoreItems()));
fixture = TestBed.createComponent(DropdownSitesComponent);
debug = fixture.debugElement;
element = fixture.nativeElement;
component = fixture.componentInstance;
loader = TestbedHarnessEnvironment.loader(fixture);
});
const openSelectBox = () => {
const selectBox = debug.query(By.css(('[data-automation-id="site-my-files-option"] .mat-select-trigger')));
selectBox.triggerEventHandler('click', null);
};
it('Dropdown sites should be rendered', async () => {
fixture.detectChanges();
await fixture.whenStable();
@@ -131,13 +121,11 @@ describe('DropdownSitesComponent', () => {
fixture.detectChanges();
await fixture.whenStable();
debug.query(By.css('.mat-select-trigger')).triggerEventHandler('click', null);
const select = await loader.getHarness(MatSelectHarness);
await select.open();
fixture.detectChanges();
await fixture.whenStable();
const options: any = debug.queryAll(By.css('mat-option'));
expect(options[0].nativeElement.innerText).toContain('DROPDOWN.MY_FILES_OPTION');
const options = await select.getOptions();
expect(await options[0].getText()).toContain('DROPDOWN.MY_FILES_OPTION');
});
it('should hide the "My files" option if the developer desires that way', async () => {
@@ -146,23 +134,19 @@ describe('DropdownSitesComponent', () => {
fixture.detectChanges();
await fixture.whenStable();
debug.query(By.css('.mat-select-trigger')).triggerEventHandler('click', null);
const select = await loader.getHarness(MatSelectHarness);
await select.open();
fixture.detectChanges();
await fixture.whenStable();
const options: any = debug.queryAll(By.css('mat-option'));
expect(options[0].nativeElement.innerText).not.toContain('DROPDOWN.MY_FILES_OPTION');
const options = await select.getOptions();
expect(await options[0].getText()).not.toContain('DROPDOWN.MY_FILES_OPTION');
});
it('should show the default placeholder label by default', async () => {
fixture.detectChanges();
await fixture.whenStable();
openSelectBox();
fixture.detectChanges();
await fixture.whenStable();
const select = await loader.getHarness(MatSelectHarness);
await select.open();
expect(fixture.nativeElement.innerText.trim()).toContain('NODE_SELECTOR.LOCATION');
});
@@ -173,10 +157,8 @@ describe('DropdownSitesComponent', () => {
fixture.detectChanges();
await fixture.whenStable();
openSelectBox();
fixture.detectChanges();
await fixture.whenStable();
const select = await loader.getHarness(MatSelectHarness);
await select.open();
expect(fixture.nativeElement.innerText.trim()).toContain('NODE_SELECTOR.LOCATION');
});
@@ -187,51 +169,42 @@ describe('DropdownSitesComponent', () => {
fixture.detectChanges();
await fixture.whenStable();
openSelectBox();
const select = await loader.getHarness(MatSelectHarness);
await select.open();
fixture.detectChanges();
await fixture.whenStable();
const options = await select.getOptions();
const options = debug.queryAll(By.css('mat-option'));
options[0].triggerEventHandler('click', null);
fixture.detectChanges();
await fixture.whenStable();
expect(options[0].nativeElement.innerText).toContain('PERSONAL_FILES');
expect(options[1].nativeElement.innerText).toContain('FILE_LIBRARIES');
expect(await options[0].getText()).toContain('PERSONAL_FILES');
expect(await options[1].getText()).toContain('FILE_LIBRARIES');
});
it('should load sites by default', async () => {
fixture.detectChanges();
await fixture.whenStable();
debug.query(By.css('.mat-select-trigger')).triggerEventHandler('click', null);
const select = await loader.getHarness(MatSelectHarness);
await select.open();
const options = await select.getOptions();
expect(await options[1].getText()).toContain('fake-test-site');
expect(await options[2].getText()).toContain('fake-test-2');
});
it('should raise an event when a site is selected', async () => {
fixture.detectChanges();
await fixture.whenStable();
const options: any = debug.queryAll(By.css('mat-option'));
expect(options[1].nativeElement.innerText).toContain('fake-test-site');
expect(options[2].nativeElement.innerText).toContain('fake-test-2');
});
let site: SiteEntry;
component.change.subscribe((value) => (site = value));
it('should raise an event when a site is selected', (done) => {
fixture.detectChanges();
const select = await loader.getHarness(MatSelectHarness);
await select.open();
fixture.whenStable().then(() => {
fixture.detectChanges();
debug.query(By.css('.mat-select-trigger')).triggerEventHandler('click', null);
fixture.detectChanges();
const options: any = debug.queryAll(By.css('mat-option'));
options[1].nativeElement.click();
fixture.detectChanges();
});
const options = await select.getOptions();
await options[1].click();
component.change.subscribe((site) => {
expect(site.entry.guid).toBe('fake-1');
done();
});
expect(site.entry.guid).toBe('fake-1');
});
it('should be possible to select the default value', async () => {
@@ -245,13 +218,13 @@ describe('DropdownSitesComponent', () => {
});
describe('Default value', () => {
beforeEach(() => {
siteService = TestBed.inject(SitesService);
spyOn(siteService, 'getSites').and.returnValues(of(getFakeSitePagingFirstPage()), of(getFakeSitePagingLastPage()));
fixture = TestBed.createComponent(DropdownSitesComponent);
component = fixture.componentInstance;
loader = TestbedHarnessEnvironment.loader(fixture);
});
it('should load new sites if default value is not in the first page', (done) => {
@@ -277,15 +250,14 @@ describe('DropdownSitesComponent', () => {
});
describe('Sites with members', () => {
beforeEach(() => {
siteService = TestBed.inject(SitesService);
spyOn(siteService, 'getSites').and.returnValue(of(getFakeSitePagingWithMembers()));
fixture = TestBed.createComponent(DropdownSitesComponent);
debug = fixture.debugElement;
element = fixture.nativeElement;
component = fixture.componentInstance;
loader = TestbedHarnessEnvironment.loader(fixture);
});
afterEach(() => {
@@ -293,28 +265,23 @@ describe('DropdownSitesComponent', () => {
});
describe('No relations', () => {
beforeEach(() => {
component.relations = Relations.Members;
authService = TestBed.inject(AuthenticationService);
});
it('should show only sites which logged user is member of when member relation is set', (done) => {
it('should show only sites which logged user is member of when member relation is set', async () => {
spyOn(authService, 'getEcmUsername').and.returnValue('test');
fixture.detectChanges();
fixture.whenStable().then(() => {
fixture.detectChanges();
debug.query(By.css('.mat-select-trigger')).triggerEventHandler('click', null);
fixture.detectChanges();
fixture.whenStable().then(() => {
const options: any = debug.queryAll(By.css('mat-option'));
expect(options[1].nativeElement.innerText).toContain('FAKE-SITE-PUBLIC');
expect(options[2].nativeElement.innerText).toContain('FAKE-PRIVATE-SITE-MEMBER');
expect(options[3]).toBeUndefined();
done();
});
});
await fixture.whenStable();
const select = await loader.getHarness(MatSelectHarness);
await select.open();
const options = await select.getOptions();
expect(await options[1].getText()).toContain('FAKE-SITE-PUBLIC');
expect(await options[2].getText()).toContain('FAKE-PRIVATE-SITE-MEMBER');
});
});
@@ -324,22 +291,19 @@ describe('DropdownSitesComponent', () => {
authService = TestBed.inject(AuthenticationService);
});
it('should show all the sites if no relation is set', (done) => {
it('should show all the sites if no relation is set', async () => {
spyOn(authService, 'getEcmUsername').and.returnValue('test');
fixture.detectChanges();
fixture.whenStable().then(() => {
fixture.detectChanges();
debug.query(By.css('.mat-select-trigger')).triggerEventHandler('click', null);
fixture.detectChanges();
fixture.whenStable().then(() => {
const options: any = debug.queryAll(By.css('mat-option'));
expect(options[1].nativeElement.innerText).toContain('FAKE-MODERATED-SITE');
expect(options[2].nativeElement.innerText).toContain('FAKE-SITE-PUBLIC');
expect(options[3].nativeElement.innerText).toContain('FAKE-PRIVATE-SITE-MEMBER');
done();
});
});
await fixture.whenStable();
const select = await loader.getHarness(MatSelectHarness);
await select.open();
const options = await select.getOptions();
expect(await options[1].getText()).toContain('FAKE-MODERATED-SITE');
expect(await options[2].getText()).toContain('FAKE-SITE-PUBLIC');
expect(await options[3].getText()).toContain('FAKE-PRIVATE-SITE-MEMBER');
});
});
});

View File

@@ -8,6 +8,7 @@
<header class="adf-upload-dialog__header">
<button
mat-button
[attr.data-automation-id]="'adf-upload-dialog__toggle-minimize'"
[attr.aria-label]="(isDialogMinimized ?
'ADF_FILE_UPLOAD.ARIA-LABEL.DIALOG_MAXIMIZE':
'ADF_FILE_UPLOAD.ARIA-LABEL.DIALOG_MINIMIZE') | translate"

View File

@@ -29,15 +29,15 @@ describe('FileUploadingListRowComponent', () => {
beforeEach(() => {
TestBed.configureTestingModule({
imports: [
TranslateModule.forRoot(),
ContentTestingModule
]
imports: [TranslateModule.forRoot(), ContentTestingModule]
});
fixture = TestBed.createComponent(FileUploadingListRowComponent);
component = fixture.componentInstance;
});
const getCancelButton = () =>
fixture.debugElement.query(By.css('[data-automation-id="cancel-upload-progress"]'))?.nativeElement as HTMLButtonElement;
describe('events', () => {
beforeEach(() => {
component.file = file;
@@ -58,9 +58,7 @@ describe('FileUploadingListRowComponent', () => {
fixture.detectChanges();
expect(fixture.nativeElement.querySelector(
'.adf-file-uploading-row__version'
).textContent).toContain('1');
expect(fixture.nativeElement.querySelector('.adf-file-uploading-row__version').textContent).toContain('1');
});
it('should show cancel button when upload is in progress', async () => {
@@ -71,7 +69,7 @@ describe('FileUploadingListRowComponent', () => {
fixture.detectChanges();
await fixture.whenStable();
const cancelButton = fixture.debugElement.query(By.css('[data-automation-id="cancel-upload-progress"]'));
const cancelButton = getCancelButton();
expect(cancelButton).not.toBeNull();
});
@@ -83,7 +81,7 @@ describe('FileUploadingListRowComponent', () => {
fixture.detectChanges();
await fixture.whenStable();
const cancelButton = fixture.debugElement.query(By.css('[data-automation-id="cancel-upload-progress"]'));
const cancelButton = getCancelButton();
expect(cancelButton).not.toBeNull();
});
@@ -95,8 +93,8 @@ describe('FileUploadingListRowComponent', () => {
fixture.detectChanges();
await fixture.whenStable();
const cancelButton = fixture.debugElement.query(By.css('[data-automation-id="cancel-upload-progress"]'));
expect(cancelButton).toBeNull();
const cancelButton = getCancelButton();
expect(cancelButton).toBeUndefined();
});
it('should provide tooltip for the cancel button', async () => {
@@ -107,7 +105,7 @@ describe('FileUploadingListRowComponent', () => {
fixture.detectChanges();
await fixture.whenStable();
const cancelButton: HTMLDivElement = fixture.debugElement.query(By.css('[data-automation-id="cancel-upload-progress"]')).nativeElement;
const cancelButton = getCancelButton();
expect(cancelButton.title).toBe('ADF_FILE_UPLOAD.BUTTON.STOP_FILE');
});
});

View File

@@ -178,6 +178,9 @@ describe('AlfrescoViewerComponent', () => {
fixture.destroy();
});
const getNextButton = () => element.querySelector<HTMLButtonElement>('[data-automation-id="adf-toolbar-next-file"]');
const getPrevButton = () => element.querySelector<HTMLButtonElement>('[data-automation-id="adf-toolbar-pref-file"]');
describe('Extension Type Test', () => {
it('should use external viewer to display node by id', fakeAsync(() => {
const extension: ViewerExtensionRef = {
@@ -482,10 +485,10 @@ describe('AlfrescoViewerComponent', () => {
fixture.detectChanges();
await fixture.whenStable();
const nextButton = element.querySelector<HTMLButtonElement>('[data-automation-id="adf-toolbar-next-file"]');
const nextButton = getNextButton();
expect(nextButton).not.toBeNull();
const prevButton = element.querySelector<HTMLButtonElement>('[data-automation-id="adf-toolbar-pref-file"]');
const prevButton = getPrevButton();
expect(prevButton).toBeNull();
});
@@ -497,7 +500,7 @@ describe('AlfrescoViewerComponent', () => {
fixture.detectChanges();
await fixture.whenStable();
const nextButton = element.querySelector<HTMLButtonElement>('[data-automation-id="adf-toolbar-next-file"]');
const nextButton = getNextButton();
expect(nextButton.title).toBe('ADF_VIEWER.ACTIONS.NEXT_FILE');
});
@@ -509,10 +512,10 @@ describe('AlfrescoViewerComponent', () => {
fixture.detectChanges();
await fixture.whenStable();
const nextButton = element.querySelector<HTMLButtonElement>('[data-automation-id="adf-toolbar-next-file"]');
const nextButton = getNextButton();
expect(nextButton).toBeNull();
const prevButton = element.querySelector<HTMLButtonElement>('[data-automation-id="adf-toolbar-pref-file"]');
const prevButton = getPrevButton();
expect(prevButton).not.toBeNull();
});
@@ -524,7 +527,7 @@ describe('AlfrescoViewerComponent', () => {
fixture.detectChanges();
await fixture.whenStable();
const prevButton = element.querySelector<HTMLButtonElement>('[data-automation-id="adf-toolbar-pref-file"]');
const prevButton = getPrevButton();
expect(prevButton.title).toBe('ADF_VIEWER.ACTIONS.PREV_FILE');
});
@@ -536,10 +539,10 @@ describe('AlfrescoViewerComponent', () => {
fixture.detectChanges();
await fixture.whenStable();
const nextButton = element.querySelector<HTMLButtonElement>('[data-automation-id="adf-toolbar-next-file"]');
const nextButton = getNextButton();
expect(nextButton).not.toBeNull();
const prevButton = element.querySelector<HTMLButtonElement>('[data-automation-id="adf-toolbar-pref-file"]');
const prevButton = getPrevButton();
expect(prevButton).not.toBeNull();
});
@@ -549,10 +552,10 @@ describe('AlfrescoViewerComponent', () => {
fixture.detectChanges();
await fixture.whenStable();
const nextButton = element.querySelector<HTMLButtonElement>('[data-automation-id="adf-toolbar-next-file"]');
const nextButton = getNextButton();
expect(nextButton).toBeNull();
const prevButton = element.querySelector<HTMLButtonElement>('[data-automation-id="adf-toolbar-pref-file"]');
const prevButton = getPrevButton();
expect(prevButton).toBeNull();
});
@@ -564,10 +567,10 @@ describe('AlfrescoViewerComponent', () => {
fixture.detectChanges();
await fixture.whenStable();
const nextButton = element.querySelector<HTMLButtonElement>('[data-automation-id="adf-toolbar-next-file"]');
const nextButton = getNextButton();
expect(nextButton).toBeNull();
const prevButton = element.querySelector<HTMLButtonElement>('[data-automation-id="adf-toolbar-pref-file"]');
const prevButton = getPrevButton();
expect(prevButton).toBeNull();
});
@@ -787,21 +790,13 @@ describe('AlfrescoViewerComponent', () => {
});
});
it('should not close the viewer on Escape event if dialog was opened', (done) => {
it('should not close the viewer on Escape event if dialog was opened', async () => {
const event = new KeyboardEvent('keydown', {
bubbles: true,
keyCode: 27
key: 'Escape'
} as KeyboardEventInit);
const dialogRef = dialog.open(DummyDialogComponent);
dialogRef.afterClosed().subscribe(() => {
EventMock.keyDown(27);
fixture.detectChanges();
expect(element.querySelector('.adf-viewer-content')).toBeNull();
done();
});
dialog.open(DummyDialogComponent);
fixture.detectChanges();
document.body.dispatchEvent(event);