From e6278109d8ff86c0f6ce31b456d05d290d63b495 Mon Sep 17 00:00:00 2001 From: MichalKinas <113341662+MichalKinas@users.noreply.github.com> Date: Tue, 28 Jan 2025 12:27:08 +0100 Subject: [PATCH] [ACS-8582] Introduce UnitTestingUtils class and transform existing tests in core library (#10571) * [ACS-8582] Add UnitTestingUtils class, adapt first batch of unit tests * [ACS-8582] Extend UnitTestingUtils, cover second batch of unit tests * [ACS-8582] Extend UnitTestingUtils, cover third batch of unit tests * [ACS-8582] Extend UnitTestingUtils, cover final batch of unit tests * [ci:force] * [ci:force] * [ACS-8582] CR fixes * [ACS-8582] CR fixes --- .../lib/directives/features.directive.spec.ts | 13 +- .../directives/not-features.directive.spec.ts | 13 +- .../src/lib/avatar/avatar.component.spec.ts | 14 +- .../card-view-arrayitem.component.spec.ts | 55 +- .../card-view-boolitem.component.spec.ts | 94 ++- .../card-view-dateitem.component.spec.ts | 73 +-- ...ard-view-item-dispatcher.component.spec.ts | 14 +- ...d-view-keyvaluepairsitem.component.spec.ts | 39 +- .../card-view-mapitem.component.spec.ts | 44 +- .../card-view-selectitem.component.spec.ts | 67 +-- .../select-filter-input.component.spec.ts | 4 +- .../card-view-textitem.component.spec.ts | 225 ++++--- .../card-view/card-view.component.spec.ts | 69 +-- .../lib/clipboard/clipboard.directive.spec.ts | 53 +- .../comment-list.component.spec.ts | 47 +- .../lib/comments/comments.component.spec.ts | 54 +- .../context-menu.directive.spec.ts | 29 +- .../amount-cell/amount-cell.component.spec.ts | 13 +- .../boolean-cell.component.spec.ts | 5 +- .../columns-selector.component.spec.ts | 33 +- .../datatable-cell.component.spec.ts | 7 +- .../datatable/datatable.component.spec.ts | 323 +++++----- .../date-cell/date-cell.component.spec.ts | 9 +- .../empty-list/empty-list.component.spec.ts | 5 +- .../icon-cell/icon-cell.component.spec.ts | 7 +- .../json-cell/json-cell.component.spec.ts | 7 +- .../number-cell/number-cell.component.spec.ts | 13 +- .../confirm-dialog/confirm.dialog.spec.ts | 28 +- .../dialogs/dialog/dialog.component.spec.ts | 61 +- .../unsaved-changes-dialog.component.spec.ts | 19 +- .../directives/highlight.directive.spec.ts | 14 +- .../infinite-select-scroll.directive.spec.ts | 8 +- .../lib/directives/logout.directive.spec.ts | 28 +- .../dynamic-chip-list.component.spec.ts | 56 +- .../form-field/form-field.component.spec.ts | 27 +- .../form-renderer.component.spec.ts | 552 +++++++----------- .../inplace-form-input.component.spec.ts | 10 +- .../widgets/amount/amount.widget.spec.ts | 73 +-- .../widgets/checkbox/checkbox.widget.spec.ts | 30 +- .../date-time/date-time.widget.spec.ts | 88 ++- .../widgets/date/date.widget.spec.ts | 37 +- .../widgets/decimal/decimal.component.spec.ts | 38 +- .../widgets/error/error.component.spec.ts | 10 +- .../widgets/header/header.widget.spec.ts | 24 +- .../hyperlink/hyperlink.widget.spec.ts | 18 +- .../multiline-text.widget.spec.ts | 23 +- .../widgets/number/number.widget.spec.ts | 34 +- .../widgets/text/text.widget.spec.ts | 115 ++-- .../src/lib/header/header.component.spec.ts | 7 +- .../navbar/navbar-item.component.spec.ts | 5 +- .../header/navbar/navbar.component.spec.ts | 7 +- .../identity-user-info.component.spec.ts | 54 +- .../info-drawer/info-drawer.component.spec.ts | 41 +- .../header/header.component.spec.ts | 87 ++- .../sidebar-action-menu.component.spec.ts | 27 +- .../sidenav-layout.component.spec.ts | 30 +- .../login-dialog-panel.component.spec.ts | 17 +- .../components/login/login.component.spec.ts | 138 +++-- .../notification-history.component.spec.ts | 8 +- .../services/notification.service.spec.ts | 21 +- .../infinite-pagination.component.spec.ts | 31 +- .../lib/progress/progress.component.spec.ts | 13 +- .../search-text-input.component.spec.ts | 26 +- .../snackbar-content.component.spec.ts | 21 +- .../empty-content.component.spec.ts | 12 +- .../error-content.component.spec.ts | 15 +- lib/core/src/lib/testing/index.ts | 1 + .../src/lib/testing/unit-testing-utils.ts | 470 +++++++++++++++ .../src/lib/toolbar/toolbar.component.spec.ts | 7 +- .../download-prompt-dialog.component.spec.ts | 13 +- .../img-viewer/img-viewer.component.spec.ts | 69 +-- .../pdf-viewer-thumbnails.component.spec.ts | 7 +- .../pdf-viewer/pdf-viewer.component.spec.ts | 80 ++- .../txt-viewer/txt-viewer.component.spec.ts | 10 +- .../viewer-render.component.spec.ts | 56 +- .../components/viewer.component.spec.ts | 127 ++-- 76 files changed, 2068 insertions(+), 1954 deletions(-) create mode 100644 lib/core/src/lib/testing/unit-testing-utils.ts diff --git a/lib/core/feature-flags/src/lib/directives/features.directive.spec.ts b/lib/core/feature-flags/src/lib/directives/features.directive.spec.ts index 1a50c489c6..75c94ce145 100644 --- a/lib/core/feature-flags/src/lib/directives/features.directive.spec.ts +++ b/lib/core/feature-flags/src/lib/directives/features.directive.spec.ts @@ -20,7 +20,7 @@ import { Component } from '@angular/core'; import { ComponentFixture, TestBed } from '@angular/core/testing'; import { provideMockFeatureFlags } from '../mocks/features-service-mock.factory'; import { FeaturesDirective } from './features.directive'; -import { By } from '@angular/platform-browser'; +import { UnitTestingUtils } from '../../../../src/lib/testing/unit-testing-utils'; @Component({ template: ` @@ -46,6 +46,7 @@ class TestWithDisabledFlagComponent { describe('FeaturesDirective', () => { let enabledFixture: ComponentFixture; let disabledFixture: ComponentFixture; + let testingUtils: UnitTestingUtils; beforeEach(async () => { TestBed.configureTestingModule({ @@ -66,16 +67,20 @@ describe('FeaturesDirective', () => { disabledFixture = TestBed.createComponent(TestWithDisabledFlagComponent); disabledFixture.detectChanges(); + testingUtils = new UnitTestingUtils(enabledFixture.debugElement); + await enabledFixture.whenStable(); await disabledFixture.whenStable(); }); it('should render the element with enabled features', () => { - expect(enabledFixture.debugElement.query(By.css('#underFeatureFlag'))).toBeDefined(); - expect(enabledFixture.debugElement.query(By.css('#underFeatureFlag')).nativeElement).toBeDefined(); + const enabledFixtureElement = testingUtils.getByCSS('#underFeatureFlag'); + expect(enabledFixtureElement).toBeDefined(); + expect(enabledFixtureElement.nativeElement).toBeDefined(); }); it('should not render the element with disabled features', () => { - expect(disabledFixture.debugElement.query(By.css('#underFeatureFlag'))).toBeNull(); + testingUtils.setDebugElement(disabledFixture.debugElement); + expect(testingUtils.getByCSS('#underFeatureFlag')).toBeNull(); }); }); diff --git a/lib/core/feature-flags/src/lib/directives/not-features.directive.spec.ts b/lib/core/feature-flags/src/lib/directives/not-features.directive.spec.ts index f8df2d633d..d590fb6fe0 100644 --- a/lib/core/feature-flags/src/lib/directives/not-features.directive.spec.ts +++ b/lib/core/feature-flags/src/lib/directives/not-features.directive.spec.ts @@ -18,9 +18,9 @@ import { CommonModule } from '@angular/common'; import { Component } from '@angular/core'; import { ComponentFixture, TestBed } from '@angular/core/testing'; -import { By } from '@angular/platform-browser'; import { provideMockFeatureFlags } from '../mocks/features-service-mock.factory'; import { NotFeaturesDirective } from './not-features.directive'; +import { UnitTestingUtils } from '../../../../src/lib/testing/unit-testing-utils'; @Component({ template: ` @@ -47,6 +47,7 @@ class TestWithDisabledFlagComponent { describe('NotFeaturesDirective', () => { let enabledFixture: ComponentFixture; let disabledFixture: ComponentFixture; + let testingUtils: UnitTestingUtils; beforeEach(async () => { TestBed.configureTestingModule({ @@ -66,14 +67,18 @@ describe('NotFeaturesDirective', () => { disabledFixture = TestBed.createComponent(TestWithDisabledFlagComponent); disabledFixture.detectChanges(); + + testingUtils = new UnitTestingUtils(disabledFixture.debugElement); }); it('should render the element with disabled features', () => { - expect(disabledFixture.debugElement.query(By.css('#underFeatureFlag'))).toBeDefined(); - expect(disabledFixture.debugElement.query(By.css('#underFeatureFlag')).nativeElement).toBeDefined(); + const disabledFixtureElement = testingUtils.getByCSS('#underFeatureFlag'); + expect(disabledFixtureElement).toBeDefined(); + expect(disabledFixtureElement.nativeElement).toBeDefined(); }); it('should not render the element with enabled features', () => { - expect(enabledFixture.debugElement.query(By.css('#underFeatureFlag'))).toBeNull(); + testingUtils.setDebugElement(enabledFixture.debugElement); + expect(testingUtils.getByCSS('#underFeatureFlag')).toBeNull(); }); }); diff --git a/lib/core/src/lib/avatar/avatar.component.spec.ts b/lib/core/src/lib/avatar/avatar.component.spec.ts index edebb3205f..497db50eb0 100644 --- a/lib/core/src/lib/avatar/avatar.component.spec.ts +++ b/lib/core/src/lib/avatar/avatar.component.spec.ts @@ -15,12 +15,14 @@ * limitations under the License. */ -import { AvatarComponent } from '@alfresco/adf-core'; +import { UnitTestingUtils } from '../testing/unit-testing-utils'; import { ComponentFixture, TestBed } from '@angular/core/testing'; +import { AvatarComponent } from './avatar.component'; describe('AvatarComponent', () => { let component: AvatarComponent; let fixture: ComponentFixture; + let testingUtils: UnitTestingUtils; beforeEach(async () => { await TestBed.configureTestingModule({ @@ -29,15 +31,17 @@ describe('AvatarComponent', () => { fixture = TestBed.createComponent(AvatarComponent); component = fixture.componentInstance; + testingUtils = new UnitTestingUtils(fixture.debugElement); fixture.detectChanges(); }); - const getAvatarImageElement = (): HTMLImageElement => fixture.nativeElement.querySelector('.adf-avatar__image'); + const getAvatarImageElement = (): HTMLImageElement => testingUtils.getByCSS('.adf-avatar__image').nativeElement; + const getAvatarInitialsElement = (): HTMLDivElement => testingUtils.getByCSS('.adf-avatar__initials').nativeElement; it('should display initials when src is not provided', () => { component.src = ''; fixture.detectChanges(); - const avatarElement: HTMLElement = fixture.nativeElement.querySelector('.adf-avatar__initials'); + const avatarElement = getAvatarInitialsElement(); expect(avatarElement.textContent).toContain(component.initials); }); @@ -49,14 +53,14 @@ describe('AvatarComponent', () => { it('should use default initials when not provided', () => { fixture.detectChanges(); - const avatarElement: HTMLElement = fixture.nativeElement.querySelector('.adf-avatar__initials'); + const avatarElement = getAvatarInitialsElement(); expect(avatarElement.textContent).toContain('U'); }); it('should use custom initials', () => { component.initials = 'DV'; fixture.detectChanges(); - const avatarElement: HTMLElement = fixture.nativeElement.querySelector('.adf-avatar__initials'); + const avatarElement = getAvatarInitialsElement(); expect(avatarElement.textContent).toContain('DV'); }); diff --git a/lib/core/src/lib/card-view/components/card-view-arrayitem/card-view-arrayitem.component.spec.ts b/lib/core/src/lib/card-view/components/card-view-arrayitem/card-view-arrayitem.component.spec.ts index b5e2b72c41..807705a1e6 100644 --- a/lib/core/src/lib/card-view/components/card-view-arrayitem/card-view-arrayitem.component.spec.ts +++ b/lib/core/src/lib/card-view/components/card-view-arrayitem/card-view-arrayitem.component.spec.ts @@ -19,14 +19,11 @@ import { ComponentFixture, TestBed } from '@angular/core/testing'; import { of } from 'rxjs'; import { CardViewArrayItemComponent } from './card-view-arrayitem.component'; import { CardViewArrayItemModel, CardViewArrayItem } from '../../models/card-view-arrayitem.model'; -import { By } from '@angular/platform-browser'; import { CardViewUpdateService } from '../../services/card-view-update.service'; import { HarnessLoader } from '@angular/cdk/testing'; import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed'; -import { MatChipHarness, MatChipListboxHarness } from '@angular/material/chips/testing'; -import { MatButtonHarness } from '@angular/material/button/testing'; -import { MatIconHarness } from '@angular/material/icon/testing'; -import { NoopTranslateModule } from '@alfresco/adf-core'; +import { NoopTranslateModule } from '../../../testing/noop-translate.module'; +import { UnitTestingUtils } from '../../../testing/unit-testing-utils'; describe('CardViewArrayItemComponent', () => { let loader: HarnessLoader; @@ -34,6 +31,7 @@ describe('CardViewArrayItemComponent', () => { let fixture: ComponentFixture; let service: CardViewUpdateService; let serviceSpy: jasmine.Spy; + let testingUtils: UnitTestingUtils; const mockData = [ { icon: 'person', value: 'Zlatan' }, @@ -58,6 +56,7 @@ describe('CardViewArrayItemComponent', () => { component = fixture.componentInstance; component.property = new CardViewArrayItemModel(mockDefaultProps); loader = TestbedHarnessEnvironment.loader(fixture); + testingUtils = new UnitTestingUtils(fixture.debugElement, loader); }); afterEach(() => { @@ -76,25 +75,17 @@ describe('CardViewArrayItemComponent', () => { }); it('should call service on chip click', async () => { - const chip = await loader.getHarness(MatChipHarness); - await (await chip.host()).click(); - + await testingUtils.clickMatChip('card-arrayitem-chip-Zlatan'); expect(serviceSpy).toHaveBeenCalled(); }); it('should call service on edit icon click', async () => { - const button = await loader.getHarness( - MatButtonHarness.with({ selector: `[data-automation-id="card-array-item-clickable-icon-array"]` }) - ); - await button.click(); - + await testingUtils.clickMatButtonByDataAutomationId('card-array-item-clickable-icon-array'); expect(serviceSpy).toHaveBeenCalled(); }); it('should NOT call service on chip list container click', async () => { - const chipList = await loader.getHarness(MatChipListboxHarness); - await (await chipList.host()).click(); - + await testingUtils.clickMatChipListbox('card-arrayitem-chip-list-container'); expect(serviceSpy).not.toHaveBeenCalled(); }); }); @@ -103,9 +94,7 @@ describe('CardViewArrayItemComponent', () => { it('should render the label', () => { fixture.detectChanges(); - const labelValue = fixture.debugElement.query(By.css('.adf-property-label')); - expect(labelValue).not.toBeNull(); - expect(labelValue.nativeElement.innerText).toBe('Array of items'); + expect(testingUtils.getInnerTextByCSS('.adf-property-label')).toBe('Array of items'); }); it('should render chip list', async () => { @@ -115,7 +104,7 @@ describe('CardViewArrayItemComponent', () => { }); fixture.detectChanges(); - const chipListBox = await loader.getAllHarnesses(MatChipHarness); + const chipListBox = await testingUtils.getMatChips(); expect(chipListBox).not.toBeNull(); expect(chipListBox.length).toBe(4); @@ -132,12 +121,12 @@ describe('CardViewArrayItemComponent', () => { }); fixture.detectChanges(); - const chipListBox = await loader.getAllHarnesses(MatChipHarness); + const chipListBox = await testingUtils.getMatChips(); expect(chipListBox).not.toBeNull(); expect(chipListBox.length).toBe(4); - const chip1Icon = await loader.getHarness(MatIconHarness.with({ ancestor: `[data-automation-id="card-arrayitem-chip-Zlatan"]` })); - const chip2Icon = await loader.getHarness(MatIconHarness.with({ ancestor: `[data-automation-id="card-arrayitem-chip-Lionel Messi"]` })); + const chip1Icon = await testingUtils.getMatIconWithAncestorByDataAutomationId('card-arrayitem-chip-Zlatan'); + const chip2Icon = await testingUtils.getMatIconWithAncestorByDataAutomationId('card-arrayitem-chip-Lionel Messi'); const firstChipText = await chipListBox[0].getText(); const secondChipText = await chipListBox[1].getText(); @@ -147,15 +136,14 @@ describe('CardViewArrayItemComponent', () => { expect(await chip2Icon.getName()).toBe('group'); }); - it('should render defined icon if clickable set to true', () => { + it('should render defined icon if clickable set to true', async () => { component.property = new CardViewArrayItemModel({ ...mockDefaultProps, clickable: true }); fixture.detectChanges(); - const editIcon = fixture.nativeElement.querySelector('[data-automation-id="card-array-item-clickable-icon-array"]'); - expect(editIcon).toBeDefined(); - expect(editIcon.innerText).toBe('edit'); + const editIcon = await testingUtils.getMatIconWithAncestorByDataAutomationId('card-array-item-clickable-icon-array'); + expect(await editIcon.getName()).toBe('edit'); }); it('should not render defined icon if clickable set to false', async () => { @@ -164,19 +152,16 @@ describe('CardViewArrayItemComponent', () => { clickable: false }); fixture.detectChanges(); - const editExists = await loader.hasHarness( - MatButtonHarness.with({ selector: `[data-automation-id="card-array-item-clickable-icon-array"]` }) - ); - expect(editExists).toBe(false); + + expect(await testingUtils.checkIfMatButtonExistsWithDataAutomationId('card-array-item-clickable-icon-array')).toBe(false); }); it('should render all values if noOfItemsToDisplay is not defined', async () => { fixture.detectChanges(); - const chipList = await loader.getAllHarnesses(MatChipHarness); + const chipList = await testingUtils.getMatChips(); - const moreElement = fixture.debugElement.query(By.css('[data-automation-id="card-arrayitem-more-chip"]')); - expect(moreElement).toBeNull(); + expect(await testingUtils.checkIfMatChipExistsWithDataAutomationId('card-arrayitem-more-chip')).toBeFalse(); expect(chipList.length).toBe(4); }); @@ -187,7 +172,7 @@ describe('CardViewArrayItemComponent', () => { }); fixture.detectChanges(); - const chipList = await loader.getAllHarnesses(MatChipHarness); + const chipList = await testingUtils.getMatChips(); expect(chipList.length).toBe(3); expect(await chipList[2].getText()).toBe('2 CORE.CARDVIEW.MORE'); diff --git a/lib/core/src/lib/card-view/components/card-view-boolitem/card-view-boolitem.component.spec.ts b/lib/core/src/lib/card-view/components/card-view-boolitem/card-view-boolitem.component.spec.ts index 153c1c1cb8..4928c0cca4 100644 --- a/lib/core/src/lib/card-view/components/card-view-boolitem/card-view-boolitem.component.spec.ts +++ b/lib/core/src/lib/card-view/components/card-view-boolitem/card-view-boolitem.component.spec.ts @@ -16,16 +16,20 @@ */ import { ComponentFixture, TestBed } from '@angular/core/testing'; -import { By } from '@angular/platform-browser'; -import { MatCheckbox, MatCheckboxChange } from '@angular/material/checkbox'; +import { MatCheckboxChange } from '@angular/material/checkbox'; import { CardViewUpdateService } from '../../services/card-view-update.service'; import { CardViewBoolItemComponent } from './card-view-boolitem.component'; import { CardViewBoolItemModel } from '../../models/card-view-boolitem.model'; import { NoopTranslateModule } from '../../../testing/noop-translate.module'; +import { UnitTestingUtils } from '../../../testing/unit-testing-utils'; +import { HarnessLoader } from '@angular/cdk/testing'; +import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed'; describe('CardViewBoolItemComponent', () => { let fixture: ComponentFixture; let component: CardViewBoolItemComponent; + let loader: HarnessLoader; + let testingUtils: UnitTestingUtils; beforeEach(() => { TestBed.configureTestingModule({ @@ -40,24 +44,25 @@ describe('CardViewBoolItemComponent', () => { default: false, editable: false }); + loader = TestbedHarnessEnvironment.loader(fixture); + testingUtils = new UnitTestingUtils(fixture.debugElement, loader); }); afterEach(() => { fixture.destroy(); }); + const getPropertyLabel = () => testingUtils.getByCSS('.adf-property-label'); + const getPropertyValue = () => testingUtils.getByCSS('.adf-property-value'); + describe('Rendering', () => { it('should render the label and value if the property is editable', () => { component.editable = true; component.property.editable = true; fixture.detectChanges(); - const label = fixture.debugElement.query(By.css('.adf-property-label')); - expect(label).not.toBeNull(); - expect(label.nativeElement.innerText).toBe('Boolean label'); - - const value = fixture.debugElement.query(By.css('.adf-property-value')); - expect(value).not.toBeNull(); + expect(getPropertyLabel().nativeElement.innerText).toBe('Boolean label'); + expect(getPropertyValue()).not.toBeNull(); }); it('should NOT render the label and value if the property is NOT editable and has no proper boolean value set', () => { @@ -66,11 +71,8 @@ describe('CardViewBoolItemComponent', () => { component.property.editable = false; fixture.detectChanges(); - const label = fixture.debugElement.query(By.css('.adf-property-label')); - expect(label).toBeNull(); - - const value = fixture.debugElement.query(By.css('.adf-property-value')); - expect(value).toBeNull(); + expect(getPropertyLabel()).toBeNull(); + expect(getPropertyValue()).toBeNull(); }); it('should render the label and value if the property is NOT editable but has a proper boolean value set', () => { @@ -79,86 +81,83 @@ describe('CardViewBoolItemComponent', () => { component.property.editable = false; fixture.detectChanges(); - const label = fixture.debugElement.query(By.css('.adf-property-label')); - expect(label).not.toBeNull(); - - const value = fixture.debugElement.query(By.css('.adf-property-value')); - expect(value).not.toBeNull(); + expect(getPropertyLabel()).not.toBeNull(); + expect(getPropertyValue()).not.toBeNull(); }); - it('should render ticked checkbox if property value is true', () => { + it('should render ticked checkbox if property value is true', async () => { component.property.value = true; fixture.detectChanges(); - const value = fixture.debugElement.query(By.css('.adf-property-value input[type="checkbox"]')); - expect(value).not.toBeNull(); - expect(value.nativeElement.checked).toBe(true); + const checkbox = await testingUtils.getMatCheckboxByDataAutomationId('card-boolean-boolKey'); + expect(checkbox).toBeDefined(); + expect(await checkbox.isChecked()).toBeTrue(); }); - it('should render ticked checkbox if property value is not set but default is true and editable', () => { + it('should render ticked checkbox if property value is not set but default is true and editable', async () => { component.editable = true; component.property.editable = true; component.property.value = undefined; component.property.default = true; fixture.detectChanges(); - const value = fixture.debugElement.query(By.css('.adf-property-value input[type="checkbox"]')); - expect(value).not.toBeNull(); - expect(value.nativeElement.checked).toBe(true); + const checkbox = await testingUtils.getMatCheckboxByDataAutomationId('card-boolean-boolKey'); + expect(checkbox).toBeDefined(); + expect(await checkbox.isChecked()).toBeTrue(); }); - it('should render un-ticked checkbox if property value is false', () => { + it('should render un-ticked checkbox if property value is false', async () => { component.property.value = false; fixture.detectChanges(); - const value = fixture.debugElement.query(By.css('.adf-property-value input[type="checkbox"]')); - expect(value).not.toBeNull(); - expect(value.nativeElement.checked).toBe(false); + const checkbox = await testingUtils.getMatCheckboxByDataAutomationId('card-boolean-boolKey'); + expect(checkbox).toBeDefined(); + expect(await checkbox.isChecked()).toBeFalse(); }); - it('should render un-ticked checkbox if property value is not set but default is false and editable', () => { + it('should render un-ticked checkbox if property value is not set but default is false and editable', async () => { component.editable = true; component.property.editable = true; component.property.value = undefined; component.property.default = false; fixture.detectChanges(); - const value = fixture.debugElement.query(By.css('.adf-property-value input[type="checkbox"]')); - expect(value).not.toBeNull(); - expect(value.nativeElement.checked).toBe(false); + const checkbox = await testingUtils.getMatCheckboxByDataAutomationId('card-boolean-boolKey'); + expect(checkbox).toBeDefined(); + expect(await checkbox.isChecked()).toBeFalse(); }); - it('should render enabled checkbox if property and component are both editable', () => { + it('should render enabled checkbox if property and component are both editable', async () => { component.editable = true; component.property.editable = true; component.property.value = true; fixture.detectChanges(); - const value = fixture.debugElement.query(By.css('.adf-property-value input[type="checkbox"]')); - expect(value).not.toBeNull(); - expect(value.nativeElement.hasAttribute('disabled')).toBe(false); + const checkbox = await testingUtils.getMatCheckboxByDataAutomationId('card-boolean-boolKey'); + expect(checkbox).toBeDefined(); + expect(await checkbox.isDisabled()).toBeFalse(); }); - it('should render disabled checkbox if property is not editable', () => { + it('should render disabled checkbox if property is not editable', async () => { component.editable = true; component.property.editable = false; component.property.value = true; fixture.detectChanges(); - const value = fixture.debugElement.query(By.css('.adf-property-value input[type="checkbox"]')); - expect(value).not.toBeNull(); - expect(value.nativeElement.hasAttribute('disabled')).toBe(true); + const checkbox = await testingUtils.getMatCheckboxByDataAutomationId('card-boolean-boolKey'); + expect(checkbox).toBeDefined(); + expect(await checkbox.isDisabled()).toBeTrue(); }); - it('should render disabled checkbox if component is not editable', () => { + it('should render disabled checkbox if component is not editable', async () => { component.editable = false; component.property.editable = true; component.property.value = true; fixture.detectChanges(); - const value = fixture.debugElement.query(By.css('.adf-property-value input[type="checkbox"]')); - expect(value).not.toBeNull(); - expect(value.nativeElement.hasAttribute('disabled')).toBe(true); + const checkbox = await testingUtils.getMatCheckboxByDataAutomationId('card-boolean-boolKey'); + expect(checkbox).toBeDefined(); + expect(await checkbox.isDisabled()).toBeTrue(); }); }); @@ -204,8 +203,7 @@ describe('CardViewBoolItemComponent', () => { done(); }); - const labelElement = fixture.debugElement.query(By.directive(MatCheckbox)).nativeElement.querySelector('label'); - labelElement.click(); + testingUtils.clickByDataAutomationId('card-boolean-label-boolKey'); }); }); }); diff --git a/lib/core/src/lib/card-view/components/card-view-dateitem/card-view-dateitem.component.spec.ts b/lib/core/src/lib/card-view/components/card-view-dateitem/card-view-dateitem.component.spec.ts index f5daee6349..ffe32b6190 100644 --- a/lib/core/src/lib/card-view/components/card-view-dateitem/card-view-dateitem.component.spec.ts +++ b/lib/core/src/lib/card-view/components/card-view-dateitem/card-view-dateitem.component.spec.ts @@ -16,7 +16,6 @@ */ import { ComponentFixture, TestBed } from '@angular/core/testing'; -import { By } from '@angular/platform-browser'; import { CardViewDateItemModel } from '../../models/card-view-dateitem.model'; import { CardViewUpdateService } from '../../services/card-view-update.service'; import { CardViewDateItemComponent } from './card-view-dateitem.component'; @@ -26,15 +25,16 @@ import { AppConfigService } from '../../../app-config/app-config.service'; import { MatDatetimepickerInputEvent } from '@mat-datetimepicker/core'; import { HarnessLoader } from '@angular/cdk/testing'; import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed'; -import { MatChipHarness } from '@angular/material/chips/testing'; import { addMinutes } from 'date-fns'; -import { NoopTranslateModule } from '@alfresco/adf-core'; +import { NoopTranslateModule } from '../../../testing/noop-translate.module'; +import { UnitTestingUtils } from '../../../testing/unit-testing-utils'; describe('CardViewDateItemComponent', () => { let loader: HarnessLoader; let fixture: ComponentFixture; let component: CardViewDateItemComponent; let appConfigService: AppConfigService; + let testingUtils: UnitTestingUtils; beforeEach(() => { TestBed.configureTestingModule({ @@ -59,20 +59,19 @@ describe('CardViewDateItemComponent', () => { }); loader = TestbedHarnessEnvironment.loader(fixture); + testingUtils = new UnitTestingUtils(fixture.debugElement, loader); }); afterEach(() => fixture.destroy()); + const getPropertyLabel = (): string => testingUtils.getInnerTextByCSS('.adf-property-label'); + const getPropertyValue = (): string => testingUtils.getInnerTextByCSS('.adf-property-value'); + it('should render the label and value', () => { fixture.detectChanges(); - const labelValue = fixture.debugElement.query(By.css('.adf-property-label')); - expect(labelValue).not.toBeNull(); - expect(labelValue.nativeElement.innerText).toBe('Date label'); - - const value = fixture.debugElement.query(By.css('.adf-property-value')); - expect(value).not.toBeNull(); - expect(value.nativeElement.innerText.trim()).toBe('Jul 10, 2017'); + expect(getPropertyLabel()).toBe('Date label'); + expect(getPropertyValue().trim()).toBe('Jul 10, 2017'); }); it('should NOT render the default as value if the value is empty, editable:false and displayEmpty is false', () => { @@ -88,9 +87,7 @@ describe('CardViewDateItemComponent', () => { component.displayEmpty = false; fixture.detectChanges(); - const value = fixture.debugElement.query(By.css('.adf-property-value')); - expect(value).not.toBeNull(); - expect(value.nativeElement.innerText.trim()).toBe(''); + expect(getPropertyValue().trim()).toBe(''); }); it('should render the default as value if the value is empty, editable:false and displayEmpty is true', () => { @@ -106,9 +103,7 @@ describe('CardViewDateItemComponent', () => { component.displayEmpty = true; fixture.detectChanges(); - const value = fixture.debugElement.query(By.css('.adf-property-value')); - expect(value).not.toBeNull(); - expect(value.nativeElement.innerText.trim()).toBe('FAKE-DEFAULT-KEY'); + expect(getPropertyValue().trim()).toBe('FAKE-DEFAULT-KEY'); }); it('should render the default as value if the value is empty and editable:true', () => { @@ -124,9 +119,7 @@ describe('CardViewDateItemComponent', () => { component.editable = true; fixture.detectChanges(); - const value = fixture.debugElement.query(By.css('.adf-property-value')); - expect(value).not.toBeNull(); - expect(value.nativeElement.innerText.trim()).toBe('FAKE-DEFAULT-KEY'); + expect(getPropertyValue().trim()).toBe('FAKE-DEFAULT-KEY'); }); it('should render value when editable:true', () => { @@ -135,9 +128,7 @@ describe('CardViewDateItemComponent', () => { component.property.editable = true; fixture.detectChanges(); - const value = fixture.debugElement.query(By.css('.adf-property-value')); - expect(value).not.toBeNull(); - expect(value.nativeElement.innerText.trim()).toBe('Jul 10, 2017'); + expect(getPropertyValue().trim()).toBe('Jul 10, 2017'); }); it('should render the picker and toggle in case of editable:true', () => { @@ -145,8 +136,8 @@ describe('CardViewDateItemComponent', () => { component.property.editable = true; fixture.detectChanges(); - const datePicker = fixture.debugElement.query(By.css(`[data-automation-id="datepicker-${component.property.key}"]`)); - const datePickerToggle = fixture.debugElement.query(By.css(`[data-automation-id="datepickertoggle-${component.property.key}"]`)); + const datePicker = testingUtils.getByDataAutomationId(`datepicker-${component.property.key}`); + const datePickerToggle = testingUtils.getByDataAutomationId(`datepickertoggle-${component.property.key}`); expect(datePicker).not.toBeNull('Datepicker should be in DOM'); expect(datePickerToggle).not.toBeNull('Datepicker toggle should be shown'); }); @@ -155,8 +146,8 @@ describe('CardViewDateItemComponent', () => { component.property.editable = false; fixture.detectChanges(); - const datePicker = fixture.debugElement.query(By.css(`[data-automation-id="datepicker-${component.property.key}"]`)); - const datePickerToggle = fixture.debugElement.query(By.css(`[data-automation-id="datepickertoggle-${component.property.key}"]`)); + const datePicker = testingUtils.getByDataAutomationId(`datepicker-${component.property.key}`); + const datePickerToggle = testingUtils.getByDataAutomationId(`datepickertoggle-${component.property.key}`); expect(datePicker).toBeNull('Datepicker should NOT be in DOM'); expect(datePickerToggle).toBeNull('Datepicker toggle should NOT be shown'); }); @@ -167,8 +158,8 @@ describe('CardViewDateItemComponent', () => { fixture.detectChanges(); expect(component.isEditable).toBe(false); - const datePicker = fixture.debugElement.query(By.css(`[data-automation-id="datepicker-${component.property.key}"]`)); - const datePickerToggle = fixture.debugElement.query(By.css(`[data-automation-id="datepickertoggle-${component.property.key}"]`)); + const datePicker = testingUtils.getByDataAutomationId(`datepicker-${component.property.key}`); + const datePickerToggle = testingUtils.getByDataAutomationId(`datepickertoggle-${component.property.key}`); expect(datePicker).toBeNull('Datepicker should NOT be in DOM'); expect(datePickerToggle).toBeNull('Datepicker toggle should NOT be shown'); }); @@ -179,8 +170,7 @@ describe('CardViewDateItemComponent', () => { fixture.detectChanges(); spyOn(component.datepicker, 'open'); - const datePickerLabelToggle = fixture.debugElement.query(By.css(`[data-automation-id="datepicker-label-toggle-${component.property.key}"]`)); - datePickerLabelToggle.triggerEventHandler('click', {}); + testingUtils.getByDataAutomationId(`datepicker-label-toggle-${component.property.key}`).nativeElement.click(); expect(component.datepicker.open).toHaveBeenCalled(); }); @@ -223,8 +213,7 @@ describe('CardViewDateItemComponent', () => { component.editable = false; fixture.detectChanges(); - const doubleClickEl = fixture.debugElement.query(By.css(`[data-automation-id="card-dateitem-${component.property.key}"]`)); - doubleClickEl.triggerEventHandler('dblclick', new MouseEvent('dblclick')); + testingUtils.doubleClickByDataAutomationId(`card-dateitem-${component.property.key}`); fixture.detectChanges(); expect(clipboardService.copyContentToClipboard).toHaveBeenCalledWith('Jul 10, 2017', 'CORE.METADATA.ACCESSIBILITY.COPY_TO_CLIPBOARD_MESSAGE'); @@ -237,9 +226,7 @@ describe('CardViewDateItemComponent', () => { component.property.value = new Date('Jul 10 2017'); fixture.detectChanges(); - const datePickerClearToggle = fixture.debugElement.query( - By.css(`[data-automation-id="datepicker-date-clear-${component.property.key}"]`) - ); + const datePickerClearToggle = testingUtils.getByDataAutomationId(`datepicker-date-clear-${component.property.key}`); expect(datePickerClearToggle).not.toBeNull('Clean Icon should be in DOM'); }); @@ -249,9 +236,7 @@ describe('CardViewDateItemComponent', () => { component.property.value = null; fixture.detectChanges(); - const datePickerClearToggle = fixture.debugElement.query( - By.css(`[data-automation-id="datepicker-date-clear--${component.property.key}"]`) - ); + const datePickerClearToggle = testingUtils.getByDataAutomationId(`datepicker-date-clear-${component.property.key}`); expect(datePickerClearToggle).toBeNull('Clean Icon should not be in DOM'); }); @@ -262,9 +247,7 @@ describe('CardViewDateItemComponent', () => { component.property.value = new Date('Jul 10 2017'); fixture.detectChanges(); - const datePickerClearToggle = fixture.debugElement.query( - By.css(`[data-automation-id="datepicker-date-clear--${component.property.key}"]`) - ); + const datePickerClearToggle = testingUtils.getByDataAutomationId(`datepicker-date-clear-${component.property.key}`); expect(datePickerClearToggle).toBeNull('Clean Icon should not be in DOM'); }); @@ -329,9 +312,7 @@ describe('CardViewDateItemComponent', () => { await fixture.whenStable(); fixture.detectChanges(); - const element = fixture.debugElement.nativeElement.querySelector('span[data-automation-id="card-date-value-fake-key"]'); - expect(element).toBeDefined(); - expect(element.innerText).toEqual('Jul 10, 2017'); + expect(testingUtils.getInnerTextByDataAutomationId('card-date-value-fake-key')).toEqual('Jul 10, 2017'); component.onDateChanged({ value: expectedDate } as MatDatetimepickerInputEvent); fixture.detectChanges(); @@ -350,7 +331,7 @@ describe('CardViewDateItemComponent', () => { fixture.detectChanges(); await fixture.whenStable(); - const chips = await loader.getAllHarnesses(MatChipHarness); + const chips = await testingUtils.getMatChips(); expect(chips.length).toBe(3); expect(await chips[0].getText()).toBe('Jul 10, 2017'); expect(await chips[1].getText()).toBe('Jul 11, 2017'); @@ -369,7 +350,7 @@ describe('CardViewDateItemComponent', () => { fixture.detectChanges(); await fixture.whenStable(); - const chips = await loader.getAllHarnesses(MatChipHarness); + const chips = await testingUtils.getMatChips(); expect(chips.length).toBe(3); expect(await chips[0].getText()).toBe('Jul 10, 2017, 0:01'); expect(await chips[1].getText()).toBe('Jul 11, 2017, 0:01'); diff --git a/lib/core/src/lib/card-view/components/card-view-item-dispatcher/card-view-item-dispatcher.component.spec.ts b/lib/core/src/lib/card-view/components/card-view-item-dispatcher/card-view-item-dispatcher.component.spec.ts index 043e2f7713..edb6da37d0 100644 --- a/lib/core/src/lib/card-view/components/card-view-item-dispatcher/card-view-item-dispatcher.component.spec.ts +++ b/lib/core/src/lib/card-view/components/card-view-item-dispatcher/card-view-item-dispatcher.component.spec.ts @@ -19,10 +19,10 @@ import { Component, Input, SimpleChange } from '@angular/core'; import { ComponentFixture, TestBed } from '@angular/core/testing'; -import { By } from '@angular/platform-browser'; import { CardViewItem } from '../../interfaces/card-view-item.interface'; import { CardItemTypeService } from '../../services/card-item-types.service'; import { CardViewItemDispatcherComponent } from './card-view-item-dispatcher.component'; +import { UnitTestingUtils } from '../../../testing/unit-testing-utils'; @Component({ selector: 'whatever-you-want-to-have', @@ -38,6 +38,7 @@ describe('CardViewItemDispatcherComponent', () => { let fixture: ComponentFixture; let cardItemTypeService: CardItemTypeService; let component: CardViewItemDispatcherComponent; + let testingUtils: UnitTestingUtils; beforeEach(() => { cardItemTypeService = new CardItemTypeService(); @@ -67,6 +68,7 @@ describe('CardViewItemDispatcherComponent', () => { }; component.editable = true; component.displayEmpty = true; + testingUtils = new UnitTestingUtils(fixture.debugElement); fixture.detectChanges(); component.ngOnChanges({}); @@ -79,7 +81,7 @@ describe('CardViewItemDispatcherComponent', () => { describe('Sub-component creation', () => { it('should load the CardViewShinyCustomElementItemComponent', () => { - const innerElement = fixture.debugElement.query(By.css('[data-automation-id="found-me"]')); + const innerElement = testingUtils.getByDataAutomationId('found-me'); expect(innerElement).not.toBeNull(); }); @@ -89,13 +91,13 @@ describe('CardViewItemDispatcherComponent', () => { component.ngOnChanges({}); fixture.detectChanges(); - const shinyCustomElementItemComponent = fixture.debugElement.queryAll(By.css('whatever-you-want-to-have')); + const shinyCustomElementItemComponent = testingUtils.getAllByCSS('whatever-you-want-to-have'); expect(shinyCustomElementItemComponent.length).toEqual(1); }); it('should pass through the property, editable and displayEmpty parameters', () => { - const shinyCustomElementItemComponent = fixture.debugElement.query(By.css('whatever-you-want-to-have')).componentInstance; + const shinyCustomElementItemComponent = testingUtils.getByCSS('whatever-you-want-to-have').componentInstance; expect(shinyCustomElementItemComponent.property).toBe(component.property); expect(shinyCustomElementItemComponent.editable).toBe(component.editable); @@ -121,7 +123,7 @@ describe('CardViewItemDispatcherComponent', () => { displayLabelForChips: new SimpleChange(false, expectedDisplayLabel, false) }); - const shinyCustomElementItemComponent = fixture.debugElement.query(By.css('whatever-you-want-to-have')).componentInstance; + const shinyCustomElementItemComponent = testingUtils.getByCSS('whatever-you-want-to-have').componentInstance; expect(shinyCustomElementItemComponent.property).toBe(expectedProperty); expect(shinyCustomElementItemComponent.editable).toBe(expectedEditable); expect(shinyCustomElementItemComponent.displayEmpty).toBe(expectedDisplayEmpty); @@ -147,7 +149,7 @@ describe('CardViewItemDispatcherComponent', () => { ]; beforeEach(() => { - shinyCustomElementItemComponent = fixture.debugElement.query(By.css('whatever-you-want-to-have')).componentInstance; + shinyCustomElementItemComponent = testingUtils.getByCSS('whatever-you-want-to-have').componentInstance; }); it('should call through the life-cycle methods', () => { diff --git a/lib/core/src/lib/card-view/components/card-view-keyvaluepairsitem/card-view-keyvaluepairsitem.component.spec.ts b/lib/core/src/lib/card-view/components/card-view-keyvaluepairsitem/card-view-keyvaluepairsitem.component.spec.ts index 2713b8f331..f1b0cd11a1 100644 --- a/lib/core/src/lib/card-view/components/card-view-keyvaluepairsitem/card-view-keyvaluepairsitem.component.spec.ts +++ b/lib/core/src/lib/card-view/components/card-view-keyvaluepairsitem/card-view-keyvaluepairsitem.component.spec.ts @@ -16,16 +16,20 @@ */ import { ComponentFixture, TestBed } from '@angular/core/testing'; -import { By } from '@angular/platform-browser'; import { CardViewKeyValuePairsItemModel } from '../../models/card-view-keyvaluepairs.model'; import { CardViewKeyValuePairsItemComponent } from './card-view-keyvaluepairsitem.component'; import { CardViewUpdateService } from '../../services/card-view-update.service'; -import { NoopTranslateModule } from '@alfresco/adf-core'; +import { NoopTranslateModule } from '../../../testing/noop-translate.module'; +import { UnitTestingUtils } from '../../../testing/unit-testing-utils'; +import { HarnessLoader } from '@angular/cdk/testing'; +import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed'; describe('CardViewKeyValuePairsItemComponent', () => { let fixture: ComponentFixture; let component: CardViewKeyValuePairsItemComponent; let cardViewUpdateService: CardViewUpdateService; + let loader: HarnessLoader; + let testingUtils: UnitTestingUtils; const mockEmptyData = [{ name: '', value: '' }]; const mockData = [{ name: 'test-name', value: 'test-value' }]; @@ -35,6 +39,8 @@ describe('CardViewKeyValuePairsItemComponent', () => { }); fixture = TestBed.createComponent(CardViewKeyValuePairsItemComponent); cardViewUpdateService = TestBed.inject(CardViewUpdateService); + loader = TestbedHarnessEnvironment.loader(fixture); + testingUtils = new UnitTestingUtils(fixture.debugElement, loader); component = fixture.componentInstance; component.property = new CardViewKeyValuePairsItemModel({ label: 'Key Value Pairs', @@ -53,9 +59,7 @@ describe('CardViewKeyValuePairsItemComponent', () => { it('should render the label', () => { fixture.detectChanges(); - const labelValue = fixture.debugElement.query(By.css('.adf-property-label')); - expect(labelValue).not.toBeNull(); - expect(labelValue.nativeElement.innerText).toBe('Key Value Pairs'); + expect(testingUtils.getInnerTextByCSS('.adf-property-label')).toBe('Key Value Pairs'); }); it('should render readOnly table is editable property is FALSE', () => { @@ -70,47 +74,44 @@ describe('CardViewKeyValuePairsItemComponent', () => { fixture.detectChanges(); expect(component.isEditable).toBe(false); - const table = fixture.debugElement.query(By.css('.adf-card-view__key-value-pairs__read-only')); - const form = fixture.debugElement.query(By.css('.adf-card-view__key-value-pairs')); + const table = testingUtils.getByCSS('.adf-card-view__key-value-pairs__read-only'); + const form = testingUtils.getByCSS('.adf-card-view__key-value-pairs'); expect(table).not.toBeNull(); expect(form).toBeNull(); }); - it('should add new item on ADD button click', () => { + it('should add new item on ADD button click', async () => { component.ngOnChanges(); fixture.detectChanges(); - const addButton = fixture.debugElement.query(By.css('.adf-card-view__key-value-pairs__add-btn')); - addButton.triggerEventHandler('click', null); + await testingUtils.clickMatButtonByDataAutomationId('card-key-value-pairs-button-key-value-pairs'); fixture.detectChanges(); expect(JSON.stringify(component.values)).toBe(JSON.stringify(mockEmptyData)); - const content = fixture.debugElement.query(By.css('.adf-card-view__key-value-pairs')); + const content = testingUtils.getByCSS('.adf-card-view__key-value-pairs'); expect(content).not.toBeNull(); - const nameInput = fixture.debugElement.query(By.css(`[data-automation-id="card-${component.property.key}-name-input-0"]`)); - const valueInput = fixture.debugElement.query(By.css(`[data-automation-id="card-${component.property.key}-value-input-0"]`)); + const nameInput = testingUtils.getByDataAutomationId(`card-${component.property.key}-name-input-0`); + const valueInput = testingUtils.getByDataAutomationId(`card-${component.property.key}-value-input-0`); expect(nameInput).not.toBeNull(); expect(valueInput).not.toBeNull(); }); - it('should remove an item from list on REMOVE button click', () => { + it('should remove an item from list on REMOVE button click', async () => { spyOn(cardViewUpdateService, 'update'); component.ngOnChanges(); fixture.detectChanges(); - const addButton = fixture.debugElement.query(By.css('.adf-card-view__key-value-pairs__add-btn')); - addButton.triggerEventHandler('click', null); + await testingUtils.clickMatButtonByDataAutomationId('card-key-value-pairs-button-key-value-pairs'); fixture.detectChanges(); - const removeButton = fixture.debugElement.query(By.css('.adf-property-col-delete')); - removeButton.triggerEventHandler('click', null); + await testingUtils.clickMatButtonByCSS('.adf-property-col-delete'); fixture.detectChanges(); expect(component.values.length).toBe(0); - const content = fixture.debugElement.query(By.css('.adf-card-view__key-value-pairs')); + const content = testingUtils.getByCSS('.adf-card-view__key-value-pairs'); expect(content).toBeNull(); expect(cardViewUpdateService.update).toHaveBeenCalled(); diff --git a/lib/core/src/lib/card-view/components/card-view-mapitem/card-view-mapitem.component.spec.ts b/lib/core/src/lib/card-view/components/card-view-mapitem/card-view-mapitem.component.spec.ts index 9fdd627cd4..0fd48cd9b8 100644 --- a/lib/core/src/lib/card-view/components/card-view-mapitem/card-view-mapitem.component.spec.ts +++ b/lib/core/src/lib/card-view/components/card-view-mapitem/card-view-mapitem.component.spec.ts @@ -15,21 +15,18 @@ * limitations under the License. */ -import { DebugElement } from '@angular/core'; import { ComponentFixture, TestBed } from '@angular/core/testing'; -import { By } from '@angular/platform-browser'; import { CardViewMapItemModel } from '../../models/card-view-mapitem.model'; import { CardViewUpdateService } from '../../services/card-view-update.service'; import { CardViewMapItemComponent } from './card-view-mapitem.component'; -import { NoopTranslateModule } from '@alfresco/adf-core'; +import { NoopTranslateModule } from '../../../testing/noop-translate.module'; +import { UnitTestingUtils } from '../../../testing/unit-testing-utils'; describe('CardViewMapItemComponent', () => { let service: CardViewUpdateService; - let fixture: ComponentFixture; let component: CardViewMapItemComponent; - let debug: DebugElement; - let element: HTMLElement; + let testingUtils: UnitTestingUtils; beforeEach(() => { TestBed.configureTestingModule({ @@ -38,14 +35,16 @@ describe('CardViewMapItemComponent', () => { fixture = TestBed.createComponent(CardViewMapItemComponent); service = TestBed.inject(CardViewUpdateService); component = fixture.componentInstance; - debug = fixture.debugElement; - element = fixture.nativeElement; + testingUtils = new UnitTestingUtils(fixture.debugElement); }); afterEach(() => { fixture.destroy(); }); + const getPropertyLabel = (): string => testingUtils.getInnerTextByCSS('.adf-property-label'); + const getPropertyValue = (): string => testingUtils.getInnerTextByDataAutomationId(`card-mapitem-value-${component.property.key}`); + it('should render the default if the value is empty and displayEmpty is true', () => { component.property = new CardViewMapItemModel({ label: 'Map label', @@ -57,13 +56,8 @@ describe('CardViewMapItemComponent', () => { component.displayEmpty = true; fixture.detectChanges(); - const labelValue = debug.query(By.css('.adf-property-label')); - expect(labelValue).not.toBeNull(); - expect(labelValue.nativeElement.innerText).toBe('Map label'); - - const value = debug.query(By.css(`[data-automation-id="card-mapitem-value-${component.property.key}"]`)); - expect(value).not.toBeNull(); - expect(value.nativeElement.innerText.trim()).toBe('Fake default'); + expect(getPropertyLabel()).toBe('Map label'); + expect(getPropertyValue().trim()).toBe('Fake default'); }); it('should NOT render the default if the value is empty and displayEmpty is false', () => { @@ -77,12 +71,8 @@ describe('CardViewMapItemComponent', () => { component.displayEmpty = false; fixture.detectChanges(); - const labelValue = debug.query(By.css('.adf-property-label')); - expect(labelValue).toBeNull(); - - const value = debug.query(By.css(`[data-automation-id="card-mapitem-value-${component.property.key}"]`)); - expect(value).not.toBeNull(); - expect(value.nativeElement.innerText.trim()).toBe(''); + expect(testingUtils.getByCSS('.adf-property-label')).toBeNull(); + expect(getPropertyValue().trim()).toBe(''); }); it('should render the label and value', () => { @@ -95,13 +85,8 @@ describe('CardViewMapItemComponent', () => { fixture.detectChanges(); - const labelValue = debug.query(By.css('.adf-property-label')); - expect(labelValue).not.toBeNull(); - expect(labelValue.nativeElement.innerText).toBe('Map label'); - - const value = debug.query(By.css(`[data-automation-id="card-mapitem-value-${component.property.key}"]`)); - expect(value).not.toBeNull(); - expect(value.nativeElement.innerText.trim()).toBe('fakeProcessName'); + expect(getPropertyLabel()).toBe('Map label'); + expect(getPropertyValue().trim()).toBe('fakeProcessName'); }); it('should render a clickable value', (done) => { @@ -114,7 +99,6 @@ describe('CardViewMapItemComponent', () => { }); fixture.detectChanges(); - const value: any = element.querySelector('.adf-mapitem-clickable-value'); const disposableUpdate = service.itemClicked$.subscribe((response) => { expect(response.target).not.toBeNull(); @@ -125,6 +109,6 @@ describe('CardViewMapItemComponent', () => { done(); }); - value.click(); + testingUtils.clickByCSS('.adf-mapitem-clickable-value'); }); }); diff --git a/lib/core/src/lib/card-view/components/card-view-selectitem/card-view-selectitem.component.spec.ts b/lib/core/src/lib/card-view/components/card-view-selectitem/card-view-selectitem.component.spec.ts index baf092e4c3..3ae3936edd 100644 --- a/lib/core/src/lib/card-view/components/card-view-selectitem/card-view-selectitem.component.spec.ts +++ b/lib/core/src/lib/card-view/components/card-view-selectitem/card-view-selectitem.component.spec.ts @@ -16,19 +16,17 @@ */ import { ComponentFixture, TestBed } from '@angular/core/testing'; -import { By } from '@angular/platform-browser'; import { CardViewSelectItemModel } from '../../models/card-view-selectitem.model'; import { CardViewSelectItemComponent } from './card-view-selectitem.component'; import { of } from 'rxjs'; import { AppConfigService } from '../../../app-config/app-config.service'; import { HarnessLoader } from '@angular/cdk/testing'; import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed'; -import { MatSelectHarness } from '@angular/material/select/testing'; -import { MatFormFieldHarness } from '@angular/material/form-field/testing'; -import { CardViewUpdateService, NoopTranslateModule } from '@alfresco/adf-core'; import { NoopAnimationsModule } from '@angular/platform-browser/animations'; import { MatAutocompleteSelectedEvent } from '@angular/material/autocomplete'; -import { MatAutocompleteHarness } from '@angular/material/autocomplete/testing'; +import { NoopTranslateModule } from '../../../testing/noop-translate.module'; +import { UnitTestingUtils } from '../../../testing/unit-testing-utils'; +import { CardViewUpdateService } from '../../services/card-view-update.service'; describe('CardViewSelectItemComponent', () => { let loader: HarnessLoader; @@ -36,6 +34,7 @@ describe('CardViewSelectItemComponent', () => { let component: CardViewSelectItemComponent; let appConfig: AppConfigService; let cardViewUpdateService: CardViewUpdateService; + let testingUtils: UnitTestingUtils; const mockData = [ { key: 'one', label: 'One' }, { key: 'two', label: 'Two' }, @@ -71,6 +70,7 @@ describe('CardViewSelectItemComponent', () => { cardViewUpdateService = TestBed.inject(CardViewUpdateService); component.property = new CardViewSelectItemModel(mockDefaultProps); loader = TestbedHarnessEnvironment.loader(fixture); + testingUtils = new UnitTestingUtils(fixture.debugElement, loader); }); afterEach(() => { @@ -84,9 +84,7 @@ describe('CardViewSelectItemComponent', () => { editable: false }); fixture.detectChanges(); - const labelValue = fixture.debugElement.query(By.css('.adf-property-label')); - expect(labelValue).not.toBeNull(); - expect(labelValue.nativeElement.innerText).toBe('Select box label'); + expect(testingUtils.getInnerTextByCSS('.adf-property-label')).toBe('Select box label'); }); it('should render readOnly value is editable property is FALSE', () => { @@ -98,8 +96,8 @@ describe('CardViewSelectItemComponent', () => { component.ngOnChanges({}); fixture.detectChanges(); - const readOnly = fixture.debugElement.query(By.css('[data-automation-class="read-only-value"]')); - const selectBox = fixture.debugElement.query(By.css('[data-automation-class="select-box"]')); + const readOnly = testingUtils.getByDataAutomationClass('read-only-value'); + const selectBox = testingUtils.getByDataAutomationClass('select-box'); expect(readOnly).not.toBeNull(); expect(selectBox).toBeNull(); @@ -118,10 +116,7 @@ describe('CardViewSelectItemComponent', () => { expect(component.value).toEqual('two'); expect(component.isEditable).toBe(true); - const select = await loader.getHarness(MatSelectHarness); - await select.open(); - - const options = await select.getOptions(); + const options = await testingUtils.getMatSelectOptions(); expect(options.length).toEqual(4); await options[1].click(); @@ -141,10 +136,7 @@ describe('CardViewSelectItemComponent', () => { expect(component.value).toEqual(2); expect(component.isEditable).toBe(true); - const select = await loader.getHarness(MatSelectHarness); - await select.open(); - - const options = await select.getOptions(); + const options = await testingUtils.getMatSelectOptions(); expect(options.length).toEqual(4); await options[1].click(); @@ -164,10 +156,8 @@ describe('CardViewSelectItemComponent', () => { expect(component.isEditable).toBe(true); - const select = await loader.getHarness(MatSelectHarness); - await select.open(); + const options = await testingUtils.getMatSelectOptions(); - const options = await select.getOptions(); expect(await options[0].getText()).toBe('CORE.CARDVIEW.NONE'); }); @@ -176,7 +166,7 @@ describe('CardViewSelectItemComponent', () => { component.editable = true; fixture.detectChanges(); - expect(await loader.hasHarness(MatSelectHarness)).toBe(true); + expect(await testingUtils.checkIfMatSelectExists()).toBe(true); }); it('should not have label twice', async () => { @@ -184,7 +174,7 @@ describe('CardViewSelectItemComponent', () => { component.editable = true; fixture.detectChanges(); - const field = await loader.getHarness(MatFormFieldHarness.with({ selector: '.adf-property-value' })); + const field = await testingUtils.getMatFormFieldByCSS('.adf-property-value'); expect(await field.hasLabel()).toBeFalse(); }); @@ -204,17 +194,11 @@ describe('CardViewSelectItemComponent', () => { component.ngOnChanges({}); fixture.detectChanges(); - const select = await loader.getHarness(MatSelectHarness); - await select.open(); - - let options = await select.getOptions(); + let options = await testingUtils.getMatSelectOptions(); expect(options.length).toBe(3); - const filterInput = fixture.debugElement.query(By.css('.adf-select-filter-input input')); - filterInput.nativeElement.value = mockData[0].label; - filterInput.nativeElement.dispatchEvent(new Event('input')); - - options = await select.getOptions(); + testingUtils.fillInputByCSS('.adf-select-filter-input input', mockData[0].label); + options = await testingUtils.getMatSelectOptions(true); expect(options.length).toBe(1); expect(await options[0].getText()).toEqual(mockData[0].label); }); @@ -232,11 +216,9 @@ describe('CardViewSelectItemComponent', () => { component.ngOnChanges({}); fixture.detectChanges(); - const select = await loader.getHarness(MatSelectHarness); - await select.open(); - - const filterInput = fixture.debugElement.query(By.css('.adf-select-filter-input')); - expect(filterInput).toBe(null); + await testingUtils.openMatSelect(); + const filterInput = testingUtils.getInputByCSS('.adf-select-filter-input input'); + expect(filterInput).toBeUndefined(); }); it('should show filter if options are greater then limit', async () => { @@ -252,10 +234,9 @@ describe('CardViewSelectItemComponent', () => { component.ngOnChanges({}); fixture.detectChanges(); - const select = await loader.getHarness(MatSelectHarness); - await select.open(); + await testingUtils.openMatSelect(); - const filterInput = fixture.debugElement.query(By.css('.adf-select-filter-input')); + const filterInput = testingUtils.getInputByCSS('.adf-select-filter-input input'); expect(filterInput).not.toBe(null); }); }); @@ -339,11 +320,7 @@ describe('CardViewSelectItemComponent', () => { component.ngOnChanges({}); fixture.detectChanges(); - const autocomplete = await loader.getHarness(MatAutocompleteHarness); - await autocomplete.enterText('Op'); - fixture.detectChanges(); - - const options = await autocomplete.getOptions(); + const options = await testingUtils.typeAndGetOptionsForMatAutoComplete(fixture, 'Op'); expect(options.length).toBe(2); expect(await options[0].getText()).toContain('Option 1'); expect(await options[1].getText()).toContain('Option 2'); diff --git a/lib/core/src/lib/card-view/components/card-view-selectitem/select-filter-input/select-filter-input.component.spec.ts b/lib/core/src/lib/card-view/components/card-view-selectitem/select-filter-input/select-filter-input.component.spec.ts index 123eb7b093..e833e4ab37 100644 --- a/lib/core/src/lib/card-view/components/card-view-selectitem/select-filter-input/select-filter-input.component.spec.ts +++ b/lib/core/src/lib/card-view/components/card-view-selectitem/select-filter-input/select-filter-input.component.spec.ts @@ -19,7 +19,7 @@ import { ComponentFixture, TestBed } from '@angular/core/testing'; import { SelectFilterInputComponent } from './select-filter-input.component'; import { MatSelect, MatSelectModule } from '@angular/material/select'; import { NoopAnimationsModule } from '@angular/platform-browser/animations'; -import { NoopTranslateModule } from '@alfresco/adf-core'; +import { NoopTranslateModule } from '../../../../testing/noop-translate.module'; describe('SelectFilterInputComponent', () => { let fixture: ComponentFixture; @@ -78,7 +78,7 @@ describe('SelectFilterInputComponent', () => { component.onModelChange('some-search-term'); expect(component.term).toBe('some-search-term'); - component.selectFilterInput.nativeElement.dispatchEvent(new KeyboardEvent('keydown', { code: 'Escape' } as any)); + component.selectFilterInput.nativeElement.dispatchEvent(new KeyboardEvent('keydown', { code: 'Escape' })); fixture.detectChanges(); expect(component.term).toBe(''); }); diff --git a/lib/core/src/lib/card-view/components/card-view-textitem/card-view-textitem.component.spec.ts b/lib/core/src/lib/card-view/components/card-view-textitem/card-view-textitem.component.spec.ts index 3133f8cabf..a009799be6 100644 --- a/lib/core/src/lib/card-view/components/card-view-textitem/card-view-textitem.component.spec.ts +++ b/lib/core/src/lib/card-view/components/card-view-textitem/card-view-textitem.component.spec.ts @@ -16,7 +16,6 @@ */ import { ComponentFixture, TestBed } from '@angular/core/testing'; -import { By } from '@angular/platform-browser'; import { CardViewTextItemModel } from '../../models/card-view-textitem.model'; import { CardViewUpdateService } from '../../services/card-view-update.service'; import { CardViewTextItemComponent } from './card-view-textitem.component'; @@ -30,36 +29,38 @@ import { DebugElement, SimpleChange } from '@angular/core'; import { CardViewItemValidator } from '../../interfaces/card-view-item-validator.interface'; import { HarnessLoader } from '@angular/cdk/testing'; import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed'; -import { MatChipHarness, MatChipGridHarness } from '@angular/material/chips/testing'; import { MatInputHarness } from '@angular/material/input/testing'; -import { NoopTranslateModule } from '@alfresco/adf-core'; +import { NoopTranslateModule } from '../../../testing/noop-translate.module'; +import { UnitTestingUtils } from '../../../testing/unit-testing-utils'; import { NoopAnimationsModule } from '@angular/platform-browser/animations'; describe('CardViewTextItemComponent', () => { let loader: HarnessLoader; let fixture: ComponentFixture; let component: CardViewTextItemComponent; + let testingUtils: UnitTestingUtils; const expectedErrorMessages = [{ message: 'Something went wrong' } as CardViewItemValidator]; - const getTextField = (key: string): HTMLInputElement => - fixture.debugElement.query(By.css(`[data-automation-id="card-textitem-value-${key}"]`)).nativeElement; + const getTextField = (key: string): Promise => testingUtils.getMatInputByDataAutomationId(`card-textitem-value-${key}`); - const updateTextField = (key: string, value) => { - const editInput = getTextField(key); - editInput.value = value; - editInput.dispatchEvent(new Event('input')); + const getTextFieldValue = async (key: string): Promise => { + const textField = await getTextField(key); + return textField.getValue(); + }; + + const updateTextField = async (key: string, value: string) => { + await testingUtils.fillMatInputByDataAutomationId(`card-textitem-value-${key}`, value); fixture.detectChanges(); }; - const getTextFieldValue = (key: string): string => { - const textItemInput = getTextField(key); - expect(textItemInput).not.toBeNull(); - return textItemInput.value; + const updateTextFieldWithNumber = (key: string, value: number) => { + testingUtils.fillInputByDataAutomationId(`card-textitem-value-${key}`, value); + fixture.detectChanges(); }; const getErrorElements = (key: string, includeItems = false): DebugElement[] => - fixture.debugElement.queryAll(By.css(`[data-automation-id="card-textitem-error-${key}"]${includeItems ? ' li' : ''}`)); + testingUtils.getAllByCSS(`[data-automation-id="card-textitem-error-${key}"]${includeItems ? ' li' : ''}`); const getTextFieldError = (key: string): string => { const textItemInputErrors = getErrorElements(key, true); @@ -103,7 +104,7 @@ describe('CardViewTextItemComponent', () => { fixture.detectChanges(); await fixture.whenStable(); - const valueChips = await loader.getAllHarnesses(MatChipHarness); + const valueChips = await testingUtils.getMatChips(); expect(valueChips.length).toBe(length); expect(await valueChips[0].getText()).toBe(param1); expect(await valueChips[1].getText()).toBe(param2); @@ -117,6 +118,7 @@ describe('CardViewTextItemComponent', () => { fixture = TestBed.createComponent(CardViewTextItemComponent); component = fixture.componentInstance; loader = TestbedHarnessEnvironment.loader(fixture); + testingUtils = new UnitTestingUtils(fixture.debugElement, loader); }); afterEach(() => { @@ -140,12 +142,8 @@ describe('CardViewTextItemComponent', () => { fixture.detectChanges(); await fixture.whenStable(); - const labelValue = fixture.debugElement.query(By.css('.adf-property-label')); - expect(labelValue).not.toBeNull(); - expect(labelValue.nativeElement.innerText).toBe('Text label'); - - const value = getTextFieldValue(component.property.key); - expect(value).toBe('Lorem ipsum'); + expect(testingUtils.getInnerTextByCSS('.adf-property-label')).toBe('Text label'); + expect(await getTextFieldValue(component.property.key)).toBe('Lorem ipsum'); }); it('should render the displayName as value when available', async () => { @@ -157,8 +155,8 @@ describe('CardViewTextItemComponent', () => { component.ngOnChanges({ property: new SimpleChange(null, null, true) }); fixture.detectChanges(); await fixture.whenStable(); - const value = getTextFieldValue(component.property.key); - expect(value).toBe('User Name'); + + expect(await getTextFieldValue(component.property.key)).toBe('User Name'); }); it('should render the default as value if the value is empty, editable is false and displayEmpty is true', async () => { @@ -173,8 +171,8 @@ describe('CardViewTextItemComponent', () => { component.ngOnChanges({ property: new SimpleChange(null, null, true) }); fixture.detectChanges(); await fixture.whenStable(); - const value = getTextFieldValue(component.property.key); - expect(value).toBe('FAKE-DEFAULT-KEY'); + + expect(await getTextFieldValue(component.property.key)).toBe('FAKE-DEFAULT-KEY'); }); it('should render the default as value if the value is empty and editable true', async () => { @@ -189,8 +187,8 @@ describe('CardViewTextItemComponent', () => { component.ngOnChanges({ property: new SimpleChange(null, null, true) }); fixture.detectChanges(); await fixture.whenStable(); - const value = getTextFieldValue(component.property.key); - expect(value).toBe('FAKE-DEFAULT-KEY'); + + expect(await getTextFieldValue(component.property.key)).toBe('FAKE-DEFAULT-KEY'); }); it('should render value when editable:true', async () => { @@ -198,8 +196,8 @@ describe('CardViewTextItemComponent', () => { component.property.editable = true; fixture.detectChanges(); await fixture.whenStable(); - const value = getTextFieldValue(component.property.key); - expect(value).toBe('Lorem ipsum'); + + expect(await getTextFieldValue(component.property.key)).toBe('Lorem ipsum'); }); it('should NOT render the picker and toggle in case of editable:true but (general) editable:false', async () => { @@ -208,8 +206,10 @@ describe('CardViewTextItemComponent', () => { fixture.detectChanges(); await fixture.whenStable(); - const editIcon = fixture.debugElement.query(By.css(`[data-automation-id="card-textitem-edit-icon-${component.property.key}"]`)); - expect(editIcon).toBeNull('Edit icon should NOT be shown'); + const editIcon = await testingUtils.checkIfMatIconExistsWithAncestorByDataAutomationId( + `card-textitem-clickable-icon-${component.property.key}` + ); + expect(editIcon).toBeFalse(); }); it('should render chips for multivalue properties when chips are enabled', async () => { @@ -259,19 +259,19 @@ describe('CardViewTextItemComponent', () => { await renderChipsForMultiValuedProperties(cardViewTextItemFloatObject, true, 3, '10', '20.2', '35.8'); const floatValidator: CardViewItemValidator = new CardViewItemFloatValidator(); component.property.validators = [floatValidator]; - const inputElement = fixture.debugElement.query(By.css('[data-automation-id="card-textitem-editchipinput-textkey"]')).nativeElement; + const inputElement = testingUtils.getByDataAutomationId('card-textitem-editchipinput-textkey').nativeElement; component.addValueToList({ value: 'abcd', chipInput: inputElement } as MatChipInputEvent); fixture.detectChanges(); expect(getTextFieldError('textkey')).toBe('CORE.CARDVIEW.VALIDATORS.FLOAT_VALIDATION_ERROR'); - let valueChips = await loader.getAllHarnesses(MatChipHarness); + let valueChips = await testingUtils.getMatChips(); expect(valueChips.length).toBe(3); component.addValueToList({ value: '22.1', chipInput: inputElement } as MatChipInputEvent); fixture.detectChanges(); verifyNoErrors('textkey'); - valueChips = await loader.getAllHarnesses(MatChipHarness); + valueChips = await testingUtils.getMatChips(); expect(valueChips.length).toBe(4); }); @@ -290,9 +290,9 @@ describe('CardViewTextItemComponent', () => { fixture.detectChanges(); await fixture.whenStable(); - const value = getTextFieldValue(component.property.key); - expect(value).toBe('item1,item2,item3'); - expect(await loader.hasHarness(MatChipGridHarness)).toBe(false); + + expect(await getTextFieldValue(component.property.key)).toBe('item1,item2,item3'); + expect(await testingUtils.checkIfMatChipGridExists()).toBe(false); }); it('should display the label for multi-valued chips if displayLabelForChips is true', async () => { @@ -313,9 +313,7 @@ describe('CardViewTextItemComponent', () => { fixture.detectChanges(); await fixture.whenStable(); - const labelElement = fixture.debugElement.query(By.css(`.adf-property-label`)); - expect(labelElement).not.toBeNull(); - expect(labelElement.nativeElement.innerText).toBe('Text label'); + expect(testingUtils.getInnerTextByCSS('.adf-property-label')).toBe('Text label'); }); it('should NOT display the label for multi-valued chips if displayLabelForChips is false', async () => { @@ -336,8 +334,7 @@ describe('CardViewTextItemComponent', () => { fixture.detectChanges(); await fixture.whenStable(); - const labelElement = fixture.debugElement.query(By.css(`.adf-property-label`)); - expect(labelElement).toBeNull(); + expect(testingUtils.getByCSS('.adf-property-label')).toBeNull(); }); it('should return true when editable is true, and property.editable is false', () => { @@ -375,8 +372,7 @@ describe('CardViewTextItemComponent', () => { fixture.detectChanges(); await fixture.whenStable(); - const value = getTextFieldValue(component.property.key); - expect(value).toBe('FAKE-DEFAULT-KEY'); + expect(await getTextFieldValue(component.property.key)).toBe('FAKE-DEFAULT-KEY'); }); it('should render the default as value if the value is empty and clickable true', async () => { @@ -385,8 +381,8 @@ describe('CardViewTextItemComponent', () => { fixture.detectChanges(); await fixture.whenStable(); fixture.detectChanges(); - const value = getTextFieldValue(component.property.key); - expect(value).toBe('FAKE-DEFAULT-KEY'); + + expect(await getTextFieldValue(component.property.key)).toBe('FAKE-DEFAULT-KEY'); }); it('should not render the edit icon in case of clickable true but edit false', async () => { @@ -395,8 +391,11 @@ describe('CardViewTextItemComponent', () => { fixture.detectChanges(); await fixture.whenStable(); fixture.detectChanges(); - const value = fixture.debugElement.query(By.css('.adf-textitem-edit-icon')); - expect(value).toBeNull(); + + const editIcon = await testingUtils.checkIfMatIconExistsWithAncestorByDataAutomationId( + `card-textitem-clickable-icon-${component.property.key}` + ); + expect(editIcon).toBeFalse(); }); it('should not render the clickable icon in case editable set to false', async () => { @@ -408,8 +407,10 @@ describe('CardViewTextItemComponent', () => { await fixture.whenStable(); fixture.detectChanges(); - const value = fixture.debugElement.query(By.css(`[data-automation-id="card-textitem-clickable-icon-${component.property.key}"]`)); - expect(value).toBeNull('icon should NOT be shown'); + const editIcon = await testingUtils.checkIfMatIconExistsWithAncestorByDataAutomationId( + `card-textitem-clickable-icon-${component.property.key}` + ); + expect(editIcon).toBeFalse(); }); it('should render the defined clickable icon in case of clickable true and editable input set to true', async () => { @@ -422,9 +423,9 @@ describe('CardViewTextItemComponent', () => { await fixture.whenStable(); fixture.detectChanges(); - const value = fixture.debugElement.query(By.css(`[data-automation-id="card-textitem-clickable-icon-${component.property.key}"]`)); - expect(value).not.toBeNull(); - expect(value.nativeElement.innerText).toBe('FAKE_ICON'); + const editIcon = await testingUtils.getMatIconWithAncestorByDataAutomationId(`card-textitem-clickable-icon-${component.property.key}`); + expect(editIcon).not.toBeNull(); + expect(await editIcon.getName()).toBe('FAKE_ICON'); }); it('should not render clickable icon in case of clickable true and icon undefined', async () => { @@ -435,8 +436,10 @@ describe('CardViewTextItemComponent', () => { await fixture.whenStable(); fixture.detectChanges(); - const value = fixture.debugElement.query(By.css(`[data-automation-id="card-textitem-clickable-icon-${component.property.key}"]`)); - expect(value).toBeNull('icon should NOT be shown'); + const editIcon = await testingUtils.checkIfMatIconExistsWithAncestorByDataAutomationId( + `card-textitem-clickable-icon-${component.property.key}` + ); + expect(editIcon).toBeFalse(); }); it('should not render the edit icon in case of clickable false and icon defined', async () => { @@ -447,8 +450,10 @@ describe('CardViewTextItemComponent', () => { await fixture.whenStable(); fixture.detectChanges(); - const value = fixture.debugElement.query(By.css(`[data-automation-id="card-textitem-edit-icon-${component.property.icon}"]`)); - expect(value).toBeNull('Edit icon should NOT be shown'); + const editIcon = await testingUtils.checkIfMatIconExistsWithAncestorByDataAutomationId( + `card-textitem-clickable-icon-${component.property.key}` + ); + expect(editIcon).toBeFalse(); }); it('should call back function when clickable property enabled', async () => { @@ -463,9 +468,9 @@ describe('CardViewTextItemComponent', () => { await fixture.whenStable(); fixture.detectChanges(); - const value = fixture.debugElement.query(By.css(`[data-automation-id="card-textitem-clickable-icon-${component.property.key}"]`)); - expect(value.nativeElement.innerText).toBe('FAKE_ICON'); - value.nativeElement.click(); + const editIcon = await testingUtils.getMatIconWithAncestorByDataAutomationId(`card-textitem-clickable-icon-${component.property.key}`); + expect(await editIcon.getName()).toBe('FAKE_ICON'); + await testingUtils.clickMatIconWithAncestorByDataAutomationId(`card-textitem-clickable-icon-${component.property.key}`); fixture.detectChanges(); expect(callBackSpy).toHaveBeenCalled(); }); @@ -483,8 +488,7 @@ describe('CardViewTextItemComponent', () => { await fixture.whenStable(); fixture.detectChanges(); - const value = fixture.debugElement.query(By.css(`[data-automation-id="card-textitem-toggle-${component.property.key}"]`)); - value.nativeElement.click(); + testingUtils.clickByDataAutomationId(`card-textitem-toggle-${component.property.key}`); fixture.detectChanges(); expect(cardViewUpdateService.clicked).toHaveBeenCalled(); }); @@ -497,7 +501,7 @@ describe('CardViewTextItemComponent', () => { component.property.isValid = () => true; const expectedText = 'changed text'; - updateTextField(component.property.key, expectedText); + await updateTextField(component.property.key, expectedText); await fixture.whenStable(); expect(itemUpdatedSpy).toHaveBeenCalledWith({ @@ -506,7 +510,8 @@ describe('CardViewTextItemComponent', () => { textkey: expectedText } }); - expect(getTextFieldValue(component.property.key)).toEqual(expectedText); + + expect(await getTextFieldValue(component.property.key)).toEqual(expectedText); }); it('should copy value to clipboard on double click', async () => { @@ -521,10 +526,9 @@ describe('CardViewTextItemComponent', () => { await fixture.whenStable(); fixture.detectChanges(); - const doubleClickEl = fixture.debugElement.query(By.css(`[data-automation-id="card-textitem-value-${component.property.key}"]`)); - doubleClickEl.triggerEventHandler('dblclick', new MouseEvent('dblclick')); - + testingUtils.doubleClickByDataAutomationId(`card-textitem-value-${component.property.key}`); fixture.detectChanges(); + expect(clipboardService.copyContentToClipboard).toHaveBeenCalledWith( 'myValueToCopy', 'CORE.METADATA.ACCESSIBILITY.COPY_TO_CLIPBOARD_MESSAGE' @@ -537,9 +541,8 @@ describe('CardViewTextItemComponent', () => { component.ngOnChanges({}); loader = TestbedHarnessEnvironment.loader(fixture); - const inputHarness = await loader.getHarness( - MatInputHarness.with({ selector: `[data-automation-id="card-textitem-value-${component.property.key}"]` }) - ); + testingUtils.setLoader(loader); + const inputHarness = await testingUtils.getMatInputByDataAutomationId(`card-textitem-value-${component.property.key}`); expect(component.isEditable).toBe(false); expect(await inputHarness.isReadonly()).toBe(true); @@ -563,7 +566,7 @@ describe('CardViewTextItemComponent', () => { it('should call the isValid method with the edited value', async () => { spyOn(component.property, 'isValid'); - updateTextField(component.property.key, 'updated-value'); + await updateTextField(component.property.key, 'updated-value'); await fixture.whenStable(); expect(component.property.isValid).toHaveBeenCalledWith('updated-value'); @@ -574,7 +577,7 @@ describe('CardViewTextItemComponent', () => { spyOn(cardViewUpdateService, 'update'); component.property.isValid = () => true; - updateTextField(component.property.key, 'updated-value'); + await updateTextField(component.property.key, 'updated-value'); await fixture.whenStable(); const property = { ...component.property }; @@ -586,7 +589,7 @@ describe('CardViewTextItemComponent', () => { spyOn(cardViewUpdateService, 'update'); component.property.isValid = () => false; - updateTextField(component.property.key, '@invalid-value'); + await updateTextField(component.property.key, '@invalid-value'); await fixture.whenStable(); expect(cardViewUpdateService.update).not.toHaveBeenCalled(); @@ -597,7 +600,7 @@ describe('CardViewTextItemComponent', () => { spyOn(cardViewUpdateService, 'update'); component.property.isValid = () => true; - updateTextField(component.property.key, 'valid-value'); + await updateTextField(component.property.key, 'valid-value'); await fixture.whenStable(); expect(cardViewUpdateService.update).toHaveBeenCalled(); @@ -607,7 +610,7 @@ describe('CardViewTextItemComponent', () => { component.property.isValid = () => false; component.property.getValidationErrors = () => expectedErrorMessages; - updateTextField(component.property.key, 'updated-value'); + await updateTextField(component.property.key, 'updated-value'); await fixture.whenStable(); expect(component.errors).toBe(expectedErrorMessages); @@ -616,7 +619,7 @@ describe('CardViewTextItemComponent', () => { it('should set the errorMessages properly if the editedValue is valid', async () => { component.property.isValid = () => true; - updateTextField(component.property.key, 'updated-value'); + await updateTextField(component.property.key, 'updated-value'); await fixture.whenStable(); expect(component.errors).toEqual([]); @@ -627,8 +630,8 @@ describe('CardViewTextItemComponent', () => { component.editable = true; fixture.detectChanges(); - const errorMessage: HTMLElement = fixture.debugElement.nativeElement.querySelector('.adf-textitem-error'); - expect(errorMessage.textContent).toBe(expectedErrorMessages[0].message); + const errorMessages = getErrorElements(component.property.key, true); + expect(errorMessages[0].nativeElement.textContent).toBe(expectedErrorMessages[0].message); }); it('should NOT display error when exiting editable mode', () => { @@ -636,14 +639,14 @@ describe('CardViewTextItemComponent', () => { component.editable = true; fixture.detectChanges(); - let errorMessage: HTMLElement = fixture.debugElement.nativeElement.querySelector('.adf-textitem-error'); - expect(errorMessage.textContent).toBe(expectedErrorMessages[0].message); + let errorMessages = getErrorElements(component.property.key, true); + expect(errorMessages[0].nativeElement.textContent).toBe(expectedErrorMessages[0].message); component.editable = false; fixture.detectChanges(); - errorMessage = fixture.debugElement.nativeElement.querySelector('.adf-textitem-error'); - expect(errorMessage).toBeNull(); + errorMessages = getErrorElements(component.property.key, false); + expect(errorMessages).toEqual([]); }); it('should update the property value after a successful update attempt', async () => { @@ -659,7 +662,7 @@ describe('CardViewTextItemComponent', () => { component.property.isValid = () => true; const expectedText = 'changed text'; - updateTextField(component.property.key, expectedText); + await updateTextField(component.property.key, expectedText); await fixture.whenStable(); expect(itemUpdatedSpy).toHaveBeenCalledWith({ @@ -670,33 +673,30 @@ describe('CardViewTextItemComponent', () => { }); }); - it('should update the value using the updateItem$ subject', () => { + it('should update the value using the updateItem$ subject', async () => { const cardViewUpdateService = TestBed.inject(CardViewUpdateService); component.property.isValid = () => true; const expectedText = 'changed text'; - let value = getTextFieldValue(component.property.key); - expect(value).toEqual('Lorem ipsum'); + expect(await getTextFieldValue(component.property.key)).toEqual('Lorem ipsum'); expect(component.property.value).toBe('Lorem ipsum'); cardViewUpdateService.updateElement({ key: component.property.key, value: expectedText } as any); - component.ngOnChanges({ property: new SimpleChange(value, expectedText, false) }); + component.ngOnChanges({ property: new SimpleChange(await getTextFieldValue(component.property.key), expectedText, false) }); fixture.detectChanges(); - value = getTextFieldValue(component.property.key); - expect(value).toEqual(expectedText); + expect(await getTextFieldValue(component.property.key)).toEqual(expectedText); expect(component.property.value).toBe(expectedText); }); - it('should render the default as value if the value is empty, clickable is true and displayEmpty is true', () => { + it('should render the default as value if the value is empty, clickable is true and displayEmpty is true', async () => { component.property.value = ''; component.property.clickable = true; component.displayEmpty = true; fixture.detectChanges(); - const inputField = getTextFieldValue(component.property.key); - expect(inputField).toBe('Lorem ipsum'); + expect(await getTextFieldValue(component.property.key)).toBe('Lorem ipsum'); }); it('should update multiline input the value on input updated', async () => { @@ -707,7 +707,7 @@ describe('CardViewTextItemComponent', () => { component.property.multiline = true; const expectedText = 'changed text'; - updateTextField(component.property.key, expectedText); + await updateTextField(component.property.key, expectedText); await fixture.whenStable(); expect(itemUpdatedSpy).toHaveBeenCalledWith({ @@ -718,7 +718,7 @@ describe('CardViewTextItemComponent', () => { }); expect(component.update).toHaveBeenCalled(); - expect(getTextFieldValue(component.property.key)).toEqual(expectedText); + expect(await getTextFieldValue(component.property.key)).toEqual(expectedText); expect(component.property.value).toBe(expectedText); }); @@ -754,7 +754,7 @@ describe('CardViewTextItemComponent', () => { }); it('should show validation error when string passed', async () => { - updateTextField(component.property.key, 'update number'); + await updateTextField(component.property.key, 'update number'); await fixture.whenStable(); fixture.detectChanges(); @@ -763,7 +763,7 @@ describe('CardViewTextItemComponent', () => { }); it('should NOT show validation error for empty string', async () => { - updateTextField(component.property.key, ''); + await updateTextField(component.property.key, ''); await fixture.whenStable(); fixture.detectChanges(); @@ -771,17 +771,16 @@ describe('CardViewTextItemComponent', () => { }); it('should NOT show validation error for null', async () => { - updateTextField(component.property.key, null); + await updateTextField(component.property.key, null); await fixture.whenStable(); fixture.detectChanges(); - const inputElement = getTextField('textkey'); - expect(inputElement.value).toBe(''); + expect(await getTextFieldValue('textkey')).toBe(''); verifyNoErrors('textkey'); }); it('should show validation error for only spaces string', async () => { - updateTextField(component.property.key, ' '); + await updateTextField(component.property.key, ' '); await fixture.whenStable(); fixture.detectChanges(); @@ -790,7 +789,7 @@ describe('CardViewTextItemComponent', () => { }); it('should show validation error for float number', async () => { - updateTextField(component.property.key, 123.456); + updateTextFieldWithNumber(component.property.key, 123.456); await fixture.whenStable(); fixture.detectChanges(); @@ -800,7 +799,7 @@ describe('CardViewTextItemComponent', () => { }); it('should show validation error for exceed the number limit (2147483648)', async () => { - updateTextField(component.property.key, 2147483648); + updateTextFieldWithNumber(component.property.key, 2147483648); await fixture.whenStable(); fixture.detectChanges(); @@ -810,7 +809,7 @@ describe('CardViewTextItemComponent', () => { }); it('should not show validation error for below the number limit (2147483647)', async () => { - updateTextField(component.property.key, 2147483647); + updateTextFieldWithNumber(component.property.key, 2147483647); await fixture.whenStable(); fixture.detectChanges(); @@ -823,7 +822,7 @@ describe('CardViewTextItemComponent', () => { const itemUpdatedSpy = spyOn(cardViewUpdateService.itemUpdated$, 'next'); spyOn(component, 'update').and.callThrough(); - updateTextField(component.property.key, expectedNumber); + updateTextFieldWithNumber(component.property.key, expectedNumber); await fixture.whenStable(); expect(itemUpdatedSpy).toHaveBeenCalledWith({ @@ -834,7 +833,7 @@ describe('CardViewTextItemComponent', () => { }); verifyNoErrors(component.property.key); - expect(getTextFieldValue(component.property.key)).toEqual(expectedNumber.toString()); + expect(await getTextFieldValue(component.property.key)).toEqual(expectedNumber.toString()); expect(component.property.value).toBe(expectedNumber.toString()); }); }); @@ -859,23 +858,19 @@ describe('CardViewTextItemComponent', () => { }); it('should show validation error when string passed', async () => { - updateTextField(component.property.key, 'hello there'); + await updateTextField(component.property.key, 'hello there'); await fixture.whenStable(); fixture.detectChanges(); - const error = getTextFieldError(component.property.key); - expect(error).toEqual('CORE.CARDVIEW.VALIDATORS.FLOAT_VALIDATION_ERROR'); - expect(component.property.value).toBe(floatValue); + expect(getTextFieldError(component.property.key)).toEqual('CORE.CARDVIEW.VALIDATORS.FLOAT_VALIDATION_ERROR'); }); it('should show validation error for empty string (float)', async () => { - updateTextField(component.property.key, ' '); + await updateTextField(component.property.key, ' '); await fixture.whenStable(); fixture.detectChanges(); - const error = getTextFieldError(component.property.key); - expect(error).toEqual('CORE.CARDVIEW.VALIDATORS.FLOAT_VALIDATION_ERROR'); - expect(component.property.value).toBe(floatValue); + expect(getTextFieldError(component.property.key)).toEqual('CORE.CARDVIEW.VALIDATORS.FLOAT_VALIDATION_ERROR'); }); it('should update input the value on input updated', async () => { @@ -883,7 +878,7 @@ describe('CardViewTextItemComponent', () => { const itemUpdatedSpy = spyOn(cardViewUpdateService.itemUpdated$, 'next'); spyOn(component, 'update').and.callThrough(); - updateTextField(component.property.key, expectedNumber); + updateTextFieldWithNumber(component.property.key, expectedNumber); await fixture.whenStable(); expect(itemUpdatedSpy).toHaveBeenCalledWith({ @@ -894,7 +889,7 @@ describe('CardViewTextItemComponent', () => { }); verifyNoErrors(component.property.key); - expect(getTextFieldValue(component.property.key)).toEqual(expectedNumber.toString()); + expect(await getTextFieldValue(component.property.key)).toEqual(expectedNumber.toString()); expect(component.property.value).toBe(expectedNumber.toString()); }); }); diff --git a/lib/core/src/lib/card-view/components/card-view/card-view.component.spec.ts b/lib/core/src/lib/card-view/components/card-view/card-view.component.spec.ts index 0e4946a84d..50254d8cb1 100644 --- a/lib/core/src/lib/card-view/components/card-view/card-view.component.spec.ts +++ b/lib/core/src/lib/card-view/components/card-view/card-view.component.spec.ts @@ -16,7 +16,6 @@ */ import { ComponentFixture, TestBed } from '@angular/core/testing'; -import { By } from '@angular/platform-browser'; import { CardViewDateItemModel } from '../../models/card-view-dateitem.model'; import { CardViewTextItemModel } from '../../models/card-view-textitem.model'; import { CardViewComponent } from './card-view.component'; @@ -27,9 +26,9 @@ import { CardViewItem } from '../../interfaces/card-view-item.interface'; import { CardViewItemDispatcherComponent } from '../card-view-item-dispatcher/card-view-item-dispatcher.component'; import { HarnessLoader } from '@angular/cdk/testing'; import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed'; -import { MatSelectHarness } from '@angular/material/select/testing'; import { MatDialogModule } from '@angular/material/dialog'; -import { NoopTranslateModule } from '@alfresco/adf-core'; +import { NoopTranslateModule } from '../../../testing/noop-translate.module'; +import { UnitTestingUtils } from '../../../testing/unit-testing-utils'; import { NoopAnimationsModule } from '@angular/platform-browser/animations'; import { MatSnackBarModule } from '@angular/material/snack-bar'; @@ -37,6 +36,7 @@ describe('CardViewComponent', () => { let loader: HarnessLoader; let fixture: ComponentFixture; let component: CardViewComponent; + let testingUtils: UnitTestingUtils; beforeEach(() => { TestBed.configureTestingModule({ @@ -46,25 +46,27 @@ describe('CardViewComponent', () => { fixture = TestBed.createComponent(CardViewComponent); component = fixture.componentInstance; loader = TestbedHarnessEnvironment.loader(fixture); + testingUtils = new UnitTestingUtils(fixture.debugElement, loader); }); afterEach(() => { fixture.destroy(); }); + const getPropertyLabel = (): string => testingUtils.getInnerTextByCSS('.adf-property-label'); + const getPropertyValue = (): string => testingUtils.getByCSS('.adf-property-value').nativeElement.value; + const getPropertyValueText = (): string => testingUtils.getInnerTextByCSS('.adf-property-value'); + const getPropertyValueByDataAutomationId = (dataAutomationId: string): string => + testingUtils.getByDataAutomationId(dataAutomationId).nativeElement.value; + it('should render the label and value', async () => { component.properties = [new CardViewTextItemModel({ label: 'My label', value: 'My value', key: 'some key' })]; fixture.detectChanges(); await fixture.whenStable(); - const labelValue = fixture.debugElement.query(By.css('.adf-property-label')); - expect(labelValue).not.toBeNull(); - expect(labelValue.nativeElement.innerText).toBe('My label'); - - const value = fixture.debugElement.query(By.css('.adf-property-value')); - expect(value).not.toBeNull(); - expect(value.nativeElement.value).toBe('My value'); + expect(getPropertyLabel()).toBe('My label'); + expect(getPropertyValue()).toBe('My value'); }); it('should pass through editable property to the items', () => { @@ -80,8 +82,7 @@ describe('CardViewComponent', () => { fixture.detectChanges(); - const datePicker = fixture.debugElement.query(By.css(`[data-automation-id="datepicker-some-key"]`)); - expect(datePicker).not.toBeNull('Datepicker should be in DOM'); + expect(testingUtils.getByDataAutomationId('datepicker-some-key')).not.toBeNull('Datepicker should be in DOM'); }); it('should render the date in the correct format', async () => { @@ -97,13 +98,8 @@ describe('CardViewComponent', () => { fixture.detectChanges(); await fixture.whenStable(); - const labelValue = fixture.debugElement.query(By.css('.adf-property-label')); - expect(labelValue).not.toBeNull(); - expect(labelValue.nativeElement.innerText).toBe('My date label'); - - const value = fixture.debugElement.query(By.css('.adf-property-value')); - expect(value).not.toBeNull(); - expect(value.nativeElement.innerText).toBe('6/14/17, 12:00 AM'); + expect(getPropertyLabel()).toBe('My date label'); + expect(getPropertyValueText()).toBe('6/14/17, 12:00 AM'); }); it('should render the default value if the value is empty, not editable and displayEmpty is true', async () => { @@ -122,13 +118,8 @@ describe('CardViewComponent', () => { fixture.detectChanges(); await fixture.whenStable(); - const labelValue = fixture.debugElement.query(By.css('.adf-property-label')); - expect(labelValue).not.toBeNull(); - expect(labelValue.nativeElement.innerText).toBe('My default label'); - - const value = fixture.debugElement.query(By.css('[data-automation-id="card-textitem-value-some-key"]')); - expect(value).not.toBeNull(); - expect(value.nativeElement.value).toBe('default value'); + expect(getPropertyLabel()).toBe('My default label'); + expect(getPropertyValueByDataAutomationId('card-textitem-value-some-key')).toBe('default value'); }); it('should render the default value if the value is empty and is editable', async () => { @@ -147,13 +138,8 @@ describe('CardViewComponent', () => { fixture.detectChanges(); await fixture.whenStable(); - const labelValue = fixture.debugElement.query(By.css('.adf-property-label')); - expect(labelValue).not.toBeNull(); - expect(labelValue.nativeElement.innerText).toBe('My default label'); - - const value = fixture.debugElement.query(By.css('[data-automation-id="card-textitem-value-some-key"]')); - expect(value).not.toBeNull(); - expect(value.nativeElement.value).toBe('default value'); + expect(getPropertyLabel()).toBe('My default label'); + expect(getPropertyValueByDataAutomationId('card-textitem-value-some-key')).toBe('default value'); }); it('should render the select element with the None option when not set in the properties', async () => { @@ -177,10 +163,7 @@ describe('CardViewComponent', () => { fixture.detectChanges(); await fixture.whenStable(); - const select = await loader.getHarness(MatSelectHarness); - await select.open(); - - const currentOptions = await select.getOptions(); + const currentOptions = await testingUtils.getMatSelectOptions(); expect(currentOptions.length).toBe(3); expect(await currentOptions[0].getText()).toContain('CORE.CARDVIEW.NONE'); expect(await currentOptions[1].getText()).toContain(options[0].label); @@ -209,10 +192,7 @@ describe('CardViewComponent', () => { fixture.detectChanges(); await fixture.whenStable(); - const select = await loader.getHarness(MatSelectHarness); - await select.open(); - - const currentOptions = await select.getOptions(); + const currentOptions = await testingUtils.getMatSelectOptions(); expect(currentOptions.length).toBe(3); expect(await currentOptions[0].getText()).toContain('CORE.CARDVIEW.NONE'); expect(await currentOptions[1].getText()).toContain(options[0].label); @@ -241,10 +221,7 @@ describe('CardViewComponent', () => { fixture.detectChanges(); await fixture.whenStable(); - const select = await loader.getHarness(MatSelectHarness); - await select.open(); - - const currentOptions = await select.getOptions(); + const currentOptions = await testingUtils.getMatSelectOptions(); expect(currentOptions.length).toBe(2); expect(await currentOptions[0].getText()).toContain(options[0].label); expect(await currentOptions[1].getText()).toContain(options[1].label); @@ -276,7 +253,7 @@ describe('CardViewComponent', () => { * @returns the dispatcher component instance */ function getCardViewItemDispatcherComponent(): CardViewItemDispatcherComponent { - const cardViewItemDispatcherDebugElement = fixture.debugElement.query(By.directive(CardViewItemDispatcherComponent)); + const cardViewItemDispatcherDebugElement = testingUtils.getByDirective(CardViewItemDispatcherComponent); return cardViewItemDispatcherDebugElement.componentInstance as CardViewItemDispatcherComponent; } }); diff --git a/lib/core/src/lib/clipboard/clipboard.directive.spec.ts b/lib/core/src/lib/clipboard/clipboard.directive.spec.ts index 6d7b201a69..c7843e8e85 100644 --- a/lib/core/src/lib/clipboard/clipboard.directive.spec.ts +++ b/lib/core/src/lib/clipboard/clipboard.directive.spec.ts @@ -20,12 +20,15 @@ import { ComponentFixture, TestBed, tick, fakeAsync } from '@angular/core/testin import { ClipboardService } from './clipboard.service'; import { ClipboardDirective } from './clipboard.directive'; import { MatSnackBarModule } from '@angular/material/snack-bar'; -import { NoopTranslateModule } from '@alfresco/adf-core'; +import { NoopTranslateModule } from '../testing/noop-translate.module'; +import { UnitTestingUtils } from '../testing/unit-testing-utils'; +import { HarnessLoader, TestKey } from '@angular/cdk/testing'; +import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed'; @Component({ selector: 'adf-test-component', template: ` - + ` @@ -35,6 +38,8 @@ class TestTargetClipboardComponent {} describe('ClipboardDirective', () => { let fixture: ComponentFixture; let clipboardService: ClipboardService; + let loader: HarnessLoader; + let testingUtils: UnitTestingUtils; beforeEach(() => { TestBed.configureTestingModule({ @@ -43,21 +48,23 @@ describe('ClipboardDirective', () => { }); fixture = TestBed.createComponent(TestTargetClipboardComponent); clipboardService = TestBed.inject(ClipboardService); + loader = TestbedHarnessEnvironment.loader(fixture); + testingUtils = new UnitTestingUtils(fixture.debugElement, loader); fixture.detectChanges(); }); - it('should notify copy target value on button click event', () => { + it('should notify copy target value on button click event', async () => { spyOn(clipboardService, 'copyToClipboard'); - fixture.nativeElement.querySelector('input').value = 'some value'; - fixture.nativeElement.querySelector('button').dispatchEvent(new MouseEvent('click')); + testingUtils.fillInputByCSS('input', 'some value'); + await testingUtils.clickMatButton(); expect(clipboardService.copyToClipboard).toHaveBeenCalled(); }); - it('should notify copy target value on keydown event', () => { + it('should notify copy target value on keydown event', async () => { spyOn(clipboardService, 'copyToClipboard'); - fixture.nativeElement.querySelector('input').value = 'some value'; - fixture.nativeElement.querySelector('button').dispatchEvent(new KeyboardEvent('keydown', { code: 'Enter', key: 'Enter' })); + testingUtils.fillInputByCSS('input', 'some value'); + await testingUtils.sendKeysToMatButton([TestKey.ENTER]); expect(clipboardService.copyToClipboard).toHaveBeenCalled(); }); @@ -77,7 +84,7 @@ describe('CopyClipboardDirective', () => { } let fixture: ComponentFixture; - let element: HTMLElement; + let testingUtils: UnitTestingUtils; beforeEach(() => { TestBed.configureTestingModule({ @@ -85,53 +92,45 @@ describe('CopyClipboardDirective', () => { declarations: [TestCopyClipboardComponent] }); fixture = TestBed.createComponent(TestCopyClipboardComponent); - element = fixture.debugElement.nativeElement; + testingUtils = new UnitTestingUtils(fixture.debugElement); fixture.detectChanges(); }); it('should show tooltip when hover element', () => { - const spanHTMLElement = element.querySelector('span'); - spanHTMLElement.dispatchEvent(new Event('mouseenter')); + testingUtils.hoverOverByCSS('span'); fixture.detectChanges(); - expect(fixture.debugElement.nativeElement.querySelector('.adf-copy-tooltip')).not.toBeNull(); + expect(testingUtils.getByCSS('.adf-copy-tooltip')).not.toBeNull(); }); it('should not show tooltip when element it is not hovered', () => { - const spanHTMLElement = element.querySelector('span'); - spanHTMLElement.dispatchEvent(new Event('mouseenter')); + testingUtils.hoverOverByCSS('span'); fixture.detectChanges(); - expect(fixture.debugElement.nativeElement.querySelector('.adf-copy-tooltip')).not.toBeNull(); + expect(testingUtils.getByCSS('.adf-copy-tooltip')).not.toBeNull(); - spanHTMLElement.dispatchEvent(new Event('mouseleave')); + testingUtils.mouseLeaveByCSS('span'); fixture.detectChanges(); - expect(fixture.debugElement.nativeElement.querySelector('.adf-copy-tooltip')).toBeNull(); + expect(testingUtils.getByCSS('.adf-copy-tooltip')).toBeNull(); }); it('should copy the content of element when click it', fakeAsync(() => { - const spanHTMLElement = element.querySelector('span'); - fixture.detectChanges(); spyOn(navigator.clipboard, 'writeText'); - spanHTMLElement.dispatchEvent(new Event('click')); + testingUtils.clickByCSS('span'); tick(); fixture.detectChanges(); expect(navigator.clipboard.writeText).toHaveBeenCalledWith('text to copy'); })); it('should copy the content of element on keydown event', fakeAsync(() => { - const spanHTMLElement = element.querySelector('span'); - fixture.detectChanges(); spyOn(navigator.clipboard, 'writeText'); - spanHTMLElement.dispatchEvent(new KeyboardEvent('keydown', { code: 'Enter', key: 'Enter' })); + testingUtils.keyBoardEventByCSS('span', 'keydown', 'Enter', 'Enter'); tick(); fixture.detectChanges(); expect(navigator.clipboard.writeText).toHaveBeenCalledWith('text to copy'); })); it('should not copy the content of element when click it', fakeAsync(() => { - const spanHTMLElement = element.querySelector('span'); - fixture.detectChanges(); spyOn(navigator.clipboard, 'writeText'); - spanHTMLElement.dispatchEvent(new Event('mouseleave')); + testingUtils.mouseLeaveByCSS('span'); tick(); fixture.detectChanges(); expect(navigator.clipboard.writeText).not.toHaveBeenCalled(); diff --git a/lib/core/src/lib/comments/comment-list/comment-list.component.spec.ts b/lib/core/src/lib/comments/comment-list/comment-list.component.spec.ts index 9e28458335..00ea7b5475 100644 --- a/lib/core/src/lib/comments/comment-list/comment-list.component.spec.ts +++ b/lib/core/src/lib/comments/comment-list/comment-list.component.spec.ts @@ -18,16 +18,16 @@ import { ComponentFixture, TestBed } from '@angular/core/testing'; import { CommentModel } from '../../models/comment.model'; import { CommentListComponent } from './comment-list.component'; -import { By } from '@angular/platform-browser'; import { commentUserNoPictureDefined, commentUserPictureDefined, mockCommentOne, testUser } from './mocks/comment-list.mock'; import { CommentListServiceMock } from './mocks/comment-list.service.mock'; import { ADF_COMMENTS_SERVICE } from '../interfaces/comments.token'; -import { NoopTranslateModule } from '@alfresco/adf-core'; +import { NoopTranslateModule } from '../../testing/noop-translate.module'; +import { UnitTestingUtils } from '../../testing/unit-testing-utils'; describe('CommentListComponent', () => { let commentList: CommentListComponent; let fixture: ComponentFixture; - let element: HTMLElement; + let testingUtils: UnitTestingUtils; beforeEach(() => { TestBed.configureTestingModule({ @@ -41,8 +41,8 @@ describe('CommentListComponent', () => { }); fixture = TestBed.createComponent(CommentListComponent); commentList = fixture.componentInstance; + testingUtils = new UnitTestingUtils(fixture.debugElement); - element = fixture.nativeElement; fixture.detectChanges(); }); @@ -62,15 +62,14 @@ describe('CommentListComponent', () => { fixture.detectChanges(); - const comment = fixture.debugElement.query(By.css('.adf-comment-list-item')); - comment.triggerEventHandler('click', null); + testingUtils.clickByCSS('.adf-comment-list-item'); }); it('should not show comment list if no input is given', async () => { fixture.detectChanges(); await fixture.whenStable(); - expect(fixture.nativeElement.querySelector('adf-datatable')).toBeNull(); + expect(testingUtils.getByCSS('adf-datatable')).toBeNull(); }); it('should show comment message when input is given', async () => { @@ -79,10 +78,10 @@ describe('CommentListComponent', () => { fixture.detectChanges(); await fixture.whenStable(); - const elements = fixture.nativeElement.querySelectorAll('.adf-comment-message'); + const elements = testingUtils.getAllByCSS('.adf-comment-message'); expect(elements.length).toBe(1); - expect(elements[0].innerText).toBe(mockCommentOne.message); - expect(fixture.nativeElement.querySelector('.adf-comment-message:empty')).toBeNull(); + expect(elements[0].nativeElement.innerText).toBe(mockCommentOne.message); + expect(testingUtils.getByCSS('.adf-comment-message:empty')).toBeNull(); }); it('should show comment user when input is given', async () => { @@ -91,10 +90,10 @@ describe('CommentListComponent', () => { fixture.detectChanges(); await fixture.whenStable(); - const elements = fixture.nativeElement.querySelectorAll('.adf-comment-user-name'); + const elements = testingUtils.getAllByCSS('.adf-comment-user-name'); expect(elements.length).toBe(1); - expect(elements[0].innerText).toBe(mockCommentOne.userDisplayName); - expect(fixture.nativeElement.querySelector('.adf-comment-user-name:empty')).toBeNull(); + expect(elements[0].nativeElement.innerText).toBe(mockCommentOne.userDisplayName); + expect(testingUtils.getByCSS('.adf-comment-user-name:empty')).toBeNull(); }); it('comment date time should start with few seconds ago when comment date is few seconds ago', async () => { @@ -106,8 +105,7 @@ describe('CommentListComponent', () => { fixture.detectChanges(); await fixture.whenStable(); - element = fixture.nativeElement.querySelector('.adf-comment-message-time'); - expect(element.innerText).toContain('less than a minute ago'); + expect(testingUtils.getInnerTextByCSS('.adf-comment-message-time')).toContain('less than a minute ago'); }); it('comment date time should start with Yesterday when comment date is yesterday', async () => { @@ -118,8 +116,7 @@ describe('CommentListComponent', () => { fixture.detectChanges(); await fixture.whenStable(); - element = fixture.nativeElement.querySelector('.adf-comment-message-time'); - expect(element.innerText).toContain('1 day ago'); + expect(testingUtils.getInnerTextByCSS('.adf-comment-message-time')).toContain('1 day ago'); }); it('comment date time should not start with Today/Yesterday when comment date is before yesterday', async () => { @@ -130,9 +127,9 @@ describe('CommentListComponent', () => { fixture.detectChanges(); await fixture.whenStable(); - element = fixture.nativeElement.querySelector('.adf-comment-message-time'); - expect(element.innerText).not.toContain('Today'); - expect(element.innerText).not.toContain('Yesterday'); + const msgTime = testingUtils.getInnerTextByCSS('.adf-comment-message-time'); + expect(msgTime).not.toContain('Today'); + expect(msgTime).not.toContain('Yesterday'); }); it('should show user icon when input is given', async () => { @@ -141,10 +138,10 @@ describe('CommentListComponent', () => { fixture.detectChanges(); await fixture.whenStable(); - const elements = fixture.nativeElement.querySelectorAll('.adf-comment-img-container'); + const elements = testingUtils.getAllByCSS('.adf-comment-img-container'); expect(elements.length).toBe(1); - expect(elements[0].innerText).toContain(mockCommentOne.userInitials); - expect(fixture.nativeElement.querySelector('.adf-comment-img-container:empty')).toBeNull(); + expect(elements[0].nativeElement.innerText).toContain(mockCommentOne.userInitials); + expect(testingUtils.getByCSS('.adf-comment-img-container:empty')).toBeNull(); }); it('should return picture when is a user with a picture', async () => { @@ -153,7 +150,7 @@ describe('CommentListComponent', () => { fixture.detectChanges(); await fixture.whenStable(); - const elements = fixture.nativeElement.querySelectorAll('.adf-people-img'); + const elements = testingUtils.getAllByCSS('.adf-people-img'); expect(elements.length).toBe(1); }); @@ -163,7 +160,7 @@ describe('CommentListComponent', () => { fixture.detectChanges(); await fixture.whenStable(); - const elements = fixture.nativeElement.querySelectorAll('.adf-comment-user-icon'); + const elements = testingUtils.getAllByCSS('.adf-comment-user-icon'); expect(elements.length).toBe(1); }); }); diff --git a/lib/core/src/lib/comments/comments.component.spec.ts b/lib/core/src/lib/comments/comments.component.spec.ts index 079a2e1cb8..32cc76f97b 100644 --- a/lib/core/src/lib/comments/comments.component.spec.ts +++ b/lib/core/src/lib/comments/comments.component.spec.ts @@ -23,7 +23,8 @@ import { of, throwError } from 'rxjs'; import { ADF_COMMENTS_SERVICE } from './interfaces/comments.token'; import { CommentsService } from './interfaces/comments-service.interface'; import { NoopAnimationsModule } from '@angular/platform-browser/animations'; -import { NoopTranslateModule } from '@alfresco/adf-core'; +import { NoopTranslateModule } from '../testing/noop-translate.module'; +import { UnitTestingUtils } from '../testing/unit-testing-utils'; describe('CommentsComponent', () => { let component: CommentsComponent; @@ -31,6 +32,7 @@ describe('CommentsComponent', () => { let getCommentSpy: jasmine.Spy; let addCommentSpy: jasmine.Spy; let commentsService: CommentsService; + let testingUtils: UnitTestingUtils; beforeEach(() => { TestBed.configureTestingModule({ @@ -44,6 +46,7 @@ describe('CommentsComponent', () => { }); fixture = TestBed.createComponent(CommentsComponent); component = fixture.componentInstance; + testingUtils = new UnitTestingUtils(fixture.debugElement); commentsService = TestBed.inject(ADF_COMMENTS_SERVICE); @@ -64,7 +67,7 @@ describe('CommentsComponent', () => { it('should emit an error when an error occurs loading comments', () => { const emitSpy = spyOn(component.error, 'emit'); - getCommentSpy.and.returnValue(throwError({})); + getCommentSpy.and.returnValue(throwError(() => new Error('error'))); const change = new SimpleChange(null, '123', true); component.ngOnChanges({ id: change }); @@ -84,8 +87,8 @@ describe('CommentsComponent', () => { fixture.detectChanges(); await fixture.whenStable(); - expect(fixture.nativeElement.querySelectorAll('.adf-comment-message').length).toBe(3); - expect(fixture.nativeElement.querySelector('.adf-comment-message:empty')).toBeNull(); + expect(testingUtils.getAllByCSS('.adf-comment-message').length).toBe(3); + expect(testingUtils.getByCSS('.adf-comment-message:empty')).toBeNull(); }); it('should display comments count when the entity has comments', async () => { @@ -95,8 +98,7 @@ describe('CommentsComponent', () => { fixture.detectChanges(); await fixture.whenStable(); - const element = fixture.nativeElement.querySelector('#comment-header'); - expect(element.innerText).toBe('COMMENTS.HEADER'); + expect(testingUtils.getInnerTextByCSS('#comment-header')).toBe('COMMENTS.HEADER'); }); it('should not display comments when the entity has no comments', async () => { @@ -106,7 +108,7 @@ describe('CommentsComponent', () => { fixture.detectChanges(); await fixture.whenStable(); - expect(fixture.nativeElement.querySelector('#comment-container')).toBeNull(); + expect(testingUtils.getByCSS('#comment-container')).toBeNull(); }); it('should display comments input by default', async () => { @@ -116,7 +118,7 @@ describe('CommentsComponent', () => { fixture.detectChanges(); await fixture.whenStable(); - expect(fixture.nativeElement.querySelector('#comment-input')).not.toBeNull(); + expect(testingUtils.getByCSS('#comment-input')).not.toBeNull(); }); it('should not display comments input when the entity is readonly', async () => { @@ -125,7 +127,7 @@ describe('CommentsComponent', () => { fixture.detectChanges(); await fixture.whenStable(); - expect(fixture.nativeElement.querySelector('#comment-input')).toBeNull(); + expect(testingUtils.getByCSS('#comment-input')).toBeNull(); }); describe('Change detection id', () => { @@ -161,9 +163,8 @@ describe('CommentsComponent', () => { }); it('should normalize comment when user input contains spaces sequence', async () => { - const element = fixture.nativeElement.querySelector('.adf-comments-input-add'); component.message = 'test comment'; - element.dispatchEvent(new Event('click')); + testingUtils.clickByCSS('.adf-comments-input-add'); fixture.detectChanges(); await fixture.whenStable(); @@ -184,39 +185,32 @@ describe('CommentsComponent', () => { addCommentSpy.and.returnValue(commentsResponseMock.addComment(commentText)); component.message = commentText; - const addButton = fixture.nativeElement.querySelector('.adf-comments-input-add'); - addButton.dispatchEvent(new Event('click')); + testingUtils.clickByCSS('.adf-comments-input-add'); fixture.detectChanges(); await fixture.whenStable(); expect(addCommentSpy).toHaveBeenCalledWith('123', commentText); - - const messageElement = fixture.nativeElement.querySelector('.adf-comment-message'); - expect(messageElement.innerText).toBe(commentText); + expect(testingUtils.getInnerTextByCSS('.adf-comment-message')).toBe(commentText); }); it('should call service to add a comment when add button is pressed', async () => { - const element = fixture.nativeElement.querySelector('.adf-comments-input-add'); - component.message = 'Test Comment'; addCommentSpy.and.returnValue(commentsResponseMock.addComment(component.message)); - - element.dispatchEvent(new Event('click')); + testingUtils.clickByCSS('.adf-comments-input-add'); fixture.detectChanges(); await fixture.whenStable(); expect(addCommentSpy).toHaveBeenCalled(); - const elements = fixture.nativeElement.querySelectorAll('.adf-comment-message'); + const elements = testingUtils.getAllByCSS('.adf-comment-message'); expect(elements.length).toBe(1); - expect(elements[0].innerText).toBe('Test Comment'); + expect(elements[0].nativeElement.innerText).toBe('Test Comment'); }); it('should not call service to add a comment when comment is empty', async () => { - const element = fixture.nativeElement.querySelector('.adf-comments-input-add'); component.message = ''; - element.dispatchEvent(new Event('click')); + testingUtils.clickByCSS('.adf-comments-input-add'); fixture.detectChanges(); await fixture.whenStable(); @@ -225,27 +219,25 @@ describe('CommentsComponent', () => { }); it('should clear comment when escape key is pressed', async () => { - const event = new KeyboardEvent('keydown', { key: 'Escape' }); - let element = fixture.nativeElement.querySelector('#comment-input'); - element.dispatchEvent(event); + testingUtils.keyBoardEventByCSS('#comment-input', 'keydown', 'Escape', 'Escape'); fixture.detectChanges(); await fixture.whenStable(); - element = fixture.nativeElement.querySelector('#comment-input'); - expect(element.value).toBe(''); + const input = testingUtils.getByCSS('#comment-input'); + expect(input.nativeElement.value).toBe(''); }); it('should emit an error when an error occurs adding the comment', () => { const emitSpy = spyOn(component.error, 'emit'); - addCommentSpy.and.returnValue(throwError({})); + addCommentSpy.and.returnValue(throwError(() => new Error('error'))); component.message = 'Test comment'; component.addComment(); expect(emitSpy).toHaveBeenCalled(); }); it('should set beingAdded variable back to false when an error occurs adding the comment', () => { - addCommentSpy.and.returnValue(throwError({})); + addCommentSpy.and.returnValue(throwError(() => new Error('error'))); component.addComment(); expect(component.beingAdded).toBeFalse(); }); diff --git a/lib/core/src/lib/context-menu/context-menu.directive.spec.ts b/lib/core/src/lib/context-menu/context-menu.directive.spec.ts index e8237c43fa..321fc2058f 100644 --- a/lib/core/src/lib/context-menu/context-menu.directive.spec.ts +++ b/lib/core/src/lib/context-menu/context-menu.directive.spec.ts @@ -20,8 +20,8 @@ import { TestBed, ComponentFixture } from '@angular/core/testing'; import { CONTEXT_MENU_DIRECTIVES } from './context-menu.module'; import { CoreTestingModule } from '../testing/core.testing.module'; import { HarnessLoader } from '@angular/cdk/testing'; -import { MatIconHarness } from '@angular/material/icon/testing'; import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed'; +import { UnitTestingUtils } from '../testing/unit-testing-utils'; @Component({ selector: 'adf-test-component', @@ -114,6 +114,7 @@ const testCases = [ testCases.forEach((testCase) => { describe(`ContextMenuDirective ${testCase.description}`, () => { let fixture: ComponentFixture; + let testingUtils: UnitTestingUtils; beforeEach(() => { TestBed.configureTestingModule({ @@ -123,12 +124,12 @@ testCases.forEach((testCase) => { fixture = TestBed.createComponent(TestComponent); fixture.componentInstance.isEnabled = false; fixture.componentInstance.actions = testCase.actions; + testingUtils = new UnitTestingUtils(fixture.debugElement); fixture.detectChanges(); }); it('should not show menu on mouse contextmenu event when context menu is disabled', () => { - const targetElement = fixture.debugElement.nativeElement.querySelector('#target'); - targetElement.dispatchEvent(new CustomEvent('contextmenu')); + testingUtils.dispatchCustomEventByCSS('#target', 'contextmenu'); fixture.detectChanges(); const contextMenu = document.querySelector('.adf-context-menu'); @@ -136,15 +137,13 @@ testCases.forEach((testCase) => { }); describe('Events', () => { - let targetElement: HTMLElement; let contextMenu: HTMLElement | null; beforeEach(() => { fixture.componentInstance.isEnabled = true; fixture.detectChanges(); - targetElement = fixture.debugElement.nativeElement.querySelector('#target'); - targetElement.dispatchEvent(new CustomEvent('contextmenu')); + testingUtils.dispatchCustomEventByCSS('#target', 'contextmenu'); fixture.detectChanges(); contextMenu = document.querySelector('.adf-context-menu'); }); @@ -171,7 +170,6 @@ testCases.forEach((testCase) => { }); describe('Contextmenu list', () => { - let targetElement: HTMLElement; let contextMenu: HTMLElement | null; let loader: HarnessLoader; @@ -179,11 +177,11 @@ testCases.forEach((testCase) => { fixture.componentInstance.isEnabled = true; fixture.detectChanges(); - targetElement = fixture.debugElement.nativeElement.querySelector('#target'); - targetElement.dispatchEvent(new CustomEvent('contextmenu')); + testingUtils.dispatchCustomEventByCSS('#target', 'contextmenu'); fixture.detectChanges(); contextMenu = document.querySelector('.adf-context-menu'); loader = TestbedHarnessEnvironment.documentRootLoader(fixture); + testingUtils.setLoader(loader); }); it('should not render item with visibility property set to false', () => { @@ -195,7 +193,7 @@ testCases.forEach((testCase) => { }); it('should set first not disabled item as active', async () => { - const icon = await loader.getHarness(MatIconHarness.with({ ancestor: 'adf-context-menu' })); + const icon = await testingUtils.getMatIconWithAncestorByCSS('adf-context-menu'); expect(await icon.getName()).toEqual('action-icon-3'); }); @@ -215,16 +213,7 @@ testCases.forEach((testCase) => { }); it('should not render item icon if not set', async () => { - expect( - ( - await loader.getAllHarnesses( - MatIconHarness.with({ - ancestor: 'adf-context-menu', - name: 'Action 1' - }) - ) - ).length - ).toBe(0); + expect(await testingUtils.checkIfMatIconExistsWithAncestorByCSSAndName('adf-context-menu', 'Action 1')).toBeFalse(); }); }); }); diff --git a/lib/core/src/lib/datatable/components/amount-cell/amount-cell.component.spec.ts b/lib/core/src/lib/datatable/components/amount-cell/amount-cell.component.spec.ts index 93dced07a6..536045ab2b 100644 --- a/lib/core/src/lib/datatable/components/amount-cell/amount-cell.component.spec.ts +++ b/lib/core/src/lib/datatable/components/amount-cell/amount-cell.component.spec.ts @@ -22,20 +22,22 @@ import { BehaviorSubject } from 'rxjs'; import { LOCALE_ID } from '@angular/core'; import { registerLocaleData } from '@angular/common'; import localePL from '@angular/common/locales/pl'; +import { UnitTestingUtils } from '../../../testing/unit-testing-utils'; describe('AmountCellComponent', () => { let component: AmountCellComponent; let fixture: ComponentFixture; + let testingUtils: UnitTestingUtils; const renderAndCheckCurrencyValue = (currencyConfig: CurrencyConfig, value: number, expectedResult: string) => { component.value$ = new BehaviorSubject(value); component.currencyConfig = currencyConfig; fixture.detectChanges(); - const displayedAmount = fixture.nativeElement.querySelector('span'); + const displayedAmount = testingUtils.getByCSS('span'); expect(displayedAmount).toBeTruthy(); - expect(displayedAmount.textContent.trim()).toBe(expectedResult); + expect(displayedAmount.nativeElement.textContent.trim()).toBe(expectedResult); }; beforeEach(() => { @@ -44,6 +46,7 @@ describe('AmountCellComponent', () => { }); fixture = TestBed.createComponent(AmountCellComponent); component = fixture.componentInstance; + testingUtils = new UnitTestingUtils(fixture.debugElement); }); it('should set default currency config', () => { @@ -73,6 +76,7 @@ describe('AmountCellComponent', () => { describe('AmountCellComponent locale', () => { let component: AmountCellComponent; let fixture: ComponentFixture; + let testingUtils: UnitTestingUtils; it('should render currency value with custom locale', () => { TestBed.configureTestingModule({ @@ -82,15 +86,16 @@ describe('AmountCellComponent locale', () => { fixture = TestBed.createComponent(AmountCellComponent); component = fixture.componentInstance; + testingUtils = new UnitTestingUtils(fixture.debugElement); registerLocaleData(localePL); component.value$ = new BehaviorSubject(123.45); component.currencyConfig = { code: 'PLN', display: 'symbol', locale: 'pl-PL' }; fixture.detectChanges(); - const displayedAmount = fixture.nativeElement.querySelector('span'); + const displayedAmount = testingUtils.getByCSS('span'); expect(displayedAmount).toBeTruthy(); - expect(displayedAmount.textContent.trim()).toMatch(/123,45\s?zł/); + expect(displayedAmount.nativeElement.textContent.trim()).toMatch(/123,45\s?zł/); }); }); diff --git a/lib/core/src/lib/datatable/components/boolean-cell/boolean-cell.component.spec.ts b/lib/core/src/lib/datatable/components/boolean-cell/boolean-cell.component.spec.ts index 39f82e235d..30a314e53b 100644 --- a/lib/core/src/lib/datatable/components/boolean-cell/boolean-cell.component.spec.ts +++ b/lib/core/src/lib/datatable/components/boolean-cell/boolean-cell.component.spec.ts @@ -19,11 +19,13 @@ import { ComponentFixture, TestBed } from '@angular/core/testing'; import { BooleanCellComponent } from './boolean-cell.component'; import { ObjectDataTableAdapter } from '../../data/object-datatable-adapter'; import { ObjectDataColumn } from '../../data/object-datacolumn.model'; +import { UnitTestingUtils } from '../../../testing/unit-testing-utils'; describe('BooleanCellComponent', () => { let component: BooleanCellComponent; let fixture: ComponentFixture; let valueEl: HTMLElement; + let testingUtils: UnitTestingUtils; const renderAndGetResult = async (value: any) => { component.value$.next(value); @@ -37,7 +39,8 @@ describe('BooleanCellComponent', () => { }); fixture = TestBed.createComponent(BooleanCellComponent); component = fixture.componentInstance; - valueEl = fixture.nativeElement.querySelector('span'); + testingUtils = new UnitTestingUtils(fixture.debugElement); + valueEl = testingUtils.getByCSS('span').nativeElement; }); describe('Initialization', () => { diff --git a/lib/core/src/lib/datatable/components/columns-selector/columns-selector.component.spec.ts b/lib/core/src/lib/datatable/components/columns-selector/columns-selector.component.spec.ts index 0617470d76..81e81f2106 100644 --- a/lib/core/src/lib/datatable/components/columns-selector/columns-selector.component.spec.ts +++ b/lib/core/src/lib/datatable/components/columns-selector/columns-selector.component.spec.ts @@ -20,15 +20,15 @@ import { ColumnsSelectorComponent } from './columns-selector.component'; import { DataColumn } from '../../data/data-column.model'; import { Observable, Subject } from 'rxjs'; import { MatMenuTrigger } from '@angular/material/menu'; -import { By } from '@angular/platform-browser'; import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed'; import { HarnessLoader } from '@angular/cdk/testing'; -import { MatCheckboxHarness } from '@angular/material/checkbox/testing'; import { NoopTranslateModule } from '../../../testing/noop-translate.module'; +import { UnitTestingUtils } from '../../../testing/unit-testing-utils'; describe('ColumnsSelectorComponent', () => { let fixture: ComponentFixture; let loader: HarnessLoader; + let testingUtils: UnitTestingUtils; let component: ColumnsSelectorComponent; let inputColumns: DataColumn[] = []; @@ -45,6 +45,7 @@ describe('ColumnsSelectorComponent', () => { fixture = TestBed.createComponent(ColumnsSelectorComponent); loader = TestbedHarnessEnvironment.loader(fixture); + testingUtils = new UnitTestingUtils(fixture.debugElement, loader); component = fixture.componentInstance; inputColumns = [ @@ -97,16 +98,15 @@ describe('ColumnsSelectorComponent', () => { menuOpenedTrigger.next(); fixture.detectChanges(); - let searchInput = fixture.debugElement.query(By.css('.adf-columns-selector-search-input')).nativeElement; - searchInput.value = 'TEST'; - searchInput.dispatchEvent(new Event('input')); + let searchInput = testingUtils.getByCSS('.adf-columns-selector-search-input').nativeElement; + testingUtils.fillInputByCSS('.adf-columns-selector-search-input', 'TEST'); tick(300); expect(searchInput.value).toBe('TEST'); menuClosedTrigger.next(); tick(300); - searchInput = fixture.debugElement.query(By.css('.adf-columns-selector-search-input')).nativeElement; + searchInput = testingUtils.getByCSS('.adf-columns-selector-search-input').nativeElement; expect(searchInput.value).toBe(''); })); @@ -115,8 +115,7 @@ describe('ColumnsSelectorComponent', () => { menuOpenedTrigger.next(); fixture.detectChanges(); - const checkboxes = await loader.getAllHarnesses(MatCheckboxHarness); - + const checkboxes = await testingUtils.getAllMatCheckboxes(); const inputColumnsWithTitle = inputColumns.filter((column) => !!column.title); expect(checkboxes.length).toBe(inputColumnsWithTitle.length); @@ -132,14 +131,12 @@ describe('ColumnsSelectorComponent', () => { fixture.detectChanges(); menuOpenedTrigger.next(); - const searchInput = fixture.debugElement.query(By.css('.adf-columns-selector-search-input')).nativeElement; - searchInput.value = inputColumns[0].title; - searchInput.dispatchEvent(new Event('input')); + testingUtils.fillInputByCSS('.adf-columns-selector-search-input', inputColumns[0].title); tick(400); fixture.detectChanges(); - const columnCheckboxes = await loader.getAllHarnesses(MatCheckboxHarness); + const columnCheckboxes = await testingUtils.getAllMatCheckboxes(); expect(columnCheckboxes.length).toBe(1); expect(await columnCheckboxes[0].getLabelText()).toBe(inputColumns[0].title); @@ -149,7 +146,7 @@ describe('ColumnsSelectorComponent', () => { menuOpenedTrigger.next(); fixture.detectChanges(); - const firstColumnCheckbox = await loader.getHarness(MatCheckboxHarness); + const firstColumnCheckbox = await testingUtils.getMatCheckbox(); const checkBoxName = await firstColumnCheckbox.getLabelText(); const toggledColumnItem = component.columnItems.find((item) => item.title === checkBoxName); @@ -164,7 +161,7 @@ describe('ColumnsSelectorComponent', () => { menuOpenedTrigger.next(); fixture.detectChanges(); - const checkboxes = await loader.getAllHarnesses(MatCheckboxHarness); + const checkboxes = await testingUtils.getAllMatCheckboxes(); expect(await checkboxes[0].isChecked()).toBe(true); expect(await checkboxes[1].isChecked()).toBe(true); @@ -177,7 +174,7 @@ describe('ColumnsSelectorComponent', () => { menuOpenedTrigger.next(); fixture.detectChanges(); - const checkboxes = await loader.getAllHarnesses(MatCheckboxHarness); + const checkboxes = await testingUtils.getAllMatCheckboxes(); expect(await checkboxes[0].isDisabled()).toBe(false); expect(await checkboxes[1].isDisabled()).toBe(false); @@ -206,7 +203,7 @@ describe('ColumnsSelectorComponent', () => { menuOpenedTrigger.next(); fixture.detectChanges(); - const checkboxes = await loader.getAllHarnesses(MatCheckboxHarness); + const checkboxes = await testingUtils.getAllMatCheckboxes(); const labeTextOne = await checkboxes[0].getLabelText(); const labeTextTwo = await checkboxes[1].getLabelText(); @@ -220,7 +217,7 @@ describe('ColumnsSelectorComponent', () => { menuOpenedTrigger.next(); fixture.detectChanges(); - const checkboxes = await loader.getAllHarnesses(MatCheckboxHarness); + const checkboxes = await testingUtils.getAllMatCheckboxes(); const labeTextOne = await checkboxes[0].getLabelText(); const labeTextTwo = await checkboxes[1].getLabelText(); @@ -243,7 +240,7 @@ describe('ColumnsSelectorComponent', () => { menuOpenedTrigger.next(); fixture.detectChanges(); - const checkboxes = await loader.getAllHarnesses(MatCheckboxHarness); + const checkboxes = await testingUtils.getAllMatCheckboxes(); const labeTextOne = await checkboxes[0].getLabelText(); expect(labeTextOne).toBe(`${column.title} ${column.subtitle}`); }); diff --git a/lib/core/src/lib/datatable/components/datatable-cell/datatable-cell.component.spec.ts b/lib/core/src/lib/datatable/components/datatable-cell/datatable-cell.component.spec.ts index 7c8a6a83a1..26c127a914 100644 --- a/lib/core/src/lib/datatable/components/datatable-cell/datatable-cell.component.spec.ts +++ b/lib/core/src/lib/datatable/components/datatable-cell/datatable-cell.component.spec.ts @@ -22,11 +22,13 @@ import { BehaviorSubject } from 'rxjs/internal/BehaviorSubject'; import { DataTableService } from '../../services/datatable.service'; import { ObjectDataTableAdapter } from '../../data/object-datatable-adapter'; import { mockCarsData, mockCarsSchemaDefinition } from '../mocks/datatable.mock'; +import { UnitTestingUtils } from '../../../testing/unit-testing-utils'; describe('DataTableCellComponent', () => { let component: DataTableCellComponent; let fixture: ComponentFixture; let dataTableService: DataTableService; + let testingUtils: UnitTestingUtils; const renderTextCell = (value: string, tooltip: string) => { component.value$ = new BehaviorSubject(value); @@ -36,14 +38,14 @@ describe('DataTableCellComponent', () => { }; const checkDisplayedText = (expectedText: string) => { - const displayedText = fixture.nativeElement.querySelector('span').textContent.trim(); + const displayedText = testingUtils.getByCSS('span').nativeElement.textContent.trim(); expect(displayedText).toBeTruthy(); expect(displayedText).toBe(expectedText); }; const checkDisplayedTooltip = (expectedTooltip: string) => { - const displayedTooltip = fixture.nativeElement.querySelector('span').title; + const displayedTooltip = testingUtils.getByCSS('span').nativeElement.title; expect(displayedTooltip).toBeTruthy(); expect(displayedTooltip).toBe(expectedTooltip); @@ -58,6 +60,7 @@ describe('DataTableCellComponent', () => { fixture = TestBed.createComponent(DataTableCellComponent); component = fixture.componentInstance; dataTableService = TestBed.inject(DataTableService); + testingUtils = new UnitTestingUtils(fixture.debugElement); }); it('should display text and tooltip', () => { diff --git a/lib/core/src/lib/datatable/components/datatable/datatable.component.spec.ts b/lib/core/src/lib/datatable/components/datatable/datatable.component.spec.ts index 7d9c152cb5..377d2a0a55 100644 --- a/lib/core/src/lib/datatable/components/datatable/datatable.component.spec.ts +++ b/lib/core/src/lib/datatable/components/datatable/datatable.component.spec.ts @@ -29,10 +29,11 @@ import { DataColumnListComponent } from '../../data-column/data-column-list.comp import { DataColumnComponent } from '../../data-column/data-column.component'; import { CdkDrag, CdkDragDrop, CdkDropList } from '@angular/cdk/drag-drop'; import { take } from 'rxjs/operators'; -import { By } from '@angular/platform-browser'; import { mockCarsData, mockCarsSchemaDefinition } from '../mocks/datatable.mock'; import { MatCheckboxHarness } from '@angular/material/checkbox/testing'; import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed'; +import { UnitTestingUtils } from '../../../testing/unit-testing-utils'; +import { HarnessLoader } from '@angular/cdk/testing'; @Component({ selector: 'adf-custom-column-template-component', @@ -81,7 +82,8 @@ export const resolverFn = (row: DataRow, col: DataColumn) => { describe('DataTable', () => { let fixture: ComponentFixture; let dataTable: DataTableComponent; - let element: any; + let loader: HarnessLoader; + let testingUtils: UnitTestingUtils; const testNotShownHeader = (data: ObjectDataTableAdapter) => { dataTable.ngOnChanges({ @@ -90,15 +92,15 @@ describe('DataTable', () => { dataTable.showHeader = ShowHeaderMode.Data; fixture.detectChanges(); - expect(element.querySelector('.adf-datatable-header')).toBeNull(); + expect(testingUtils.getByCSS('.adf-datatable-header')).toBeNull(); dataTable.showHeader = ShowHeaderMode.Always; fixture.detectChanges(); - expect(element.querySelector('.adf-datatable-header')).toBeNull(); + expect(testingUtils.getByCSS('.adf-datatable-header')).toBeNull(); dataTable.showHeader = ShowHeaderMode.Never; fixture.detectChanges(); - expect(element.querySelector('.adf-datatable-header')).toBeNull(); + expect(testingUtils.getByCSS('.adf-datatable-header')).toBeNull(); }; const testIfRowIsSelected = (data: any[], done?: DoneFn) => { @@ -149,7 +151,8 @@ describe('DataTable', () => { }); fixture = TestBed.createComponent(DataTableComponent); dataTable = fixture.componentInstance; - element = fixture.debugElement.nativeElement; + loader = TestbedHarnessEnvironment.loader(fixture); + testingUtils = new UnitTestingUtils(fixture.debugElement, loader); }); afterEach(() => { @@ -265,8 +268,8 @@ describe('DataTable', () => { fixture.detectChanges(); - expect(element.querySelector('.adf-datatable-card')).toBeNull(); - expect(element.querySelector('.adf-datatable-list')).not.toBeNull(); + expect(testingUtils.getByCSS('.adf-datatable-card')).toBeNull(); + expect(testingUtils.getByCSS('.adf-datatable-list')).not.toBeNull(); }); describe('Header modes', () => { @@ -277,7 +280,7 @@ describe('DataTable', () => { dataTable.loading = false; dataTable.data = newData; fixture.detectChanges(); - return fixture.debugElement.query(By.directive(CdkDropList)).injector.get(CdkDropList); + return testingUtils.getByDirective(CdkDropList).injector.get(CdkDropList); }; it('should show the header if showHeader is `Data` and there is data', () => { @@ -289,7 +292,7 @@ describe('DataTable', () => { fixture.detectChanges(); - expect(element.querySelector('.adf-datatable-header')).toBeDefined(); + expect(testingUtils.getByCSS('.adf-datatable-header')).toBeDefined(); }); it('should hide the header if showHeader is `Data` and there is no data', () => { @@ -301,7 +304,7 @@ describe('DataTable', () => { fixture.detectChanges(); - expect(element.querySelector('.adf-datatable-header')).toBeNull(); + expect(testingUtils.getByCSS('.adf-datatable-header')).toBeNull(); }); it('should always show the header if showHeader is `Always`', () => { @@ -312,13 +315,13 @@ describe('DataTable', () => { data: new SimpleChange(null, newData, false) }); fixture.detectChanges(); - expect(element.querySelector('.adf-datatable-header')).toBeDefined(); + expect(testingUtils.getByCSS('.adf-datatable-header')).toBeDefined(); dataTable.ngOnChanges({ data: new SimpleChange(null, emptyData, false) }); fixture.detectChanges(); - expect(element.querySelector('.adf-datatable-header')).toBeDefined(); + expect(testingUtils.getByCSS('.adf-datatable-header')).toBeDefined(); }); it('should never show the header if showHeader is `Never`', () => { @@ -330,7 +333,7 @@ describe('DataTable', () => { fixture.detectChanges(); - expect(element.querySelector('.adf-datatable-header')).toBeNull(); + expect(testingUtils.getByCSS('.adf-datatable-header')).toBeNull(); dataTable.ngOnChanges({ data: new SimpleChange(null, emptyData, false) @@ -338,7 +341,7 @@ describe('DataTable', () => { fixture.detectChanges(); - expect(element.querySelector('.adf-datatable-header')).toBeNull(); + expect(testingUtils.getByCSS('.adf-datatable-header')).toBeNull(); }); it('should never show the header if noPermission is true', () => { @@ -399,9 +402,9 @@ describe('DataTable', () => { fixture.detectChanges(); dataTable.ngAfterViewInit(); - const headerColumns = fixture.debugElement.nativeElement.querySelectorAll('.adf-datatable-cell-header-content'); + const headerColumns = testingUtils.getAllByCSS('.adf-datatable-cell-header-content'); - headerColumns[0].click(); + headerColumns[0].nativeElement.click(); fixture.detectChanges(); }); @@ -414,8 +417,8 @@ describe('DataTable', () => { }); fixture.detectChanges(); - expect(element.querySelector('[data-automation-id="text_TEST"]')).not.toBeNull(); - expect(element.querySelector('[data-automation-id="text_FAKE"]')).not.toBeNull(); + expect(testingUtils.getByDataAutomationId('text_TEST')).not.toBeNull(); + expect(testingUtils.getByDataAutomationId('text_FAKE')).not.toBeNull(); }); it('should set rows to the data when rows defined', () => { @@ -448,7 +451,7 @@ describe('DataTable', () => { fixture.detectChanges(); dataTable.ngAfterViewInit(); - const rowElement = document.querySelectorAll('.adf-datatable-body .adf-datatable-row')[0]; + const rowElement = testingUtils.getAllByCSS('.adf-datatable-body .adf-datatable-row')[0].nativeElement; spyOn(dataTable.rowDblClick, 'emit'); @@ -682,7 +685,7 @@ describe('DataTable', () => { dataTable.actions = true; fixture.detectChanges(); - const actions = element.querySelectorAll('[id^=action_menu_right]'); + const actions = testingUtils.getAllByCSS('[id^=action_menu_right]'); expect(actions.length).toBe(4); }); @@ -696,7 +699,7 @@ describe('DataTable', () => { dataTable.actionsPosition = 'left'; fixture.detectChanges(); - const actions = element.querySelectorAll('[id^=action_menu_left]'); + const actions = testingUtils.getAllByCSS('[id^=action_menu_left]'); expect(actions.length).toBe(4); }); @@ -827,8 +830,8 @@ describe('DataTable', () => { const adapter = dataTable.data; spyOn(adapter, 'setSorting').and.callThrough(); - const headerColumns = fixture.debugElement.nativeElement.querySelectorAll('.adf-datatable-cell-header-content'); - headerColumns[0].click(); + const headerColumns = testingUtils.getAllByCSS('.adf-datatable-cell-header-content'); + headerColumns[0].nativeElement.click(); fixture.detectChanges(); expect(adapter.setSorting).not.toHaveBeenCalled(); @@ -842,8 +845,8 @@ describe('DataTable', () => { spyOn(adapter, 'setSorting').and.callThrough(); spyOn(dataTable.data, 'getSorting').and.returnValue(new DataSorting('column_1', 'desc', { numeric: true })); - const headerColumns = fixture.debugElement.nativeElement.querySelectorAll('.adf-datatable-cell-header-content'); - headerColumns[0].click(); + const headerColumns = testingUtils.getAllByCSS('.adf-datatable-cell-header-content'); + headerColumns[0].nativeElement.click(); fixture.detectChanges(); expect(adapter.setSorting).toHaveBeenCalledWith(new DataSorting('column_1', 'asc', { numeric: true })); @@ -858,17 +861,15 @@ describe('DataTable', () => { const sorting = new DataSorting('column_1', 'asc', { numeric: true }); spyOn(adapter, 'setSorting').and.callThrough(); spyOn(adapter, 'getSorting').and.returnValue(sorting); - const headerColumns = fixture.debugElement.nativeElement.querySelectorAll('.adf-datatable-cell-header-content'); - - // // check first click on the header - headerColumns[0].click(); + const headerColumns = testingUtils.getAllByCSS('.adf-datatable-cell-header-content'); + headerColumns[0].nativeElement.click(); fixture.detectChanges(); expect(adapter.setSorting).toHaveBeenCalledWith(new DataSorting('column_1', 'desc', { numeric: true })); // check second click on the header sorting.direction = 'desc'; - headerColumns[0].click(); + headerColumns[0].nativeElement.click(); fixture.detectChanges(); expect(adapter.setSorting).toHaveBeenCalledWith(new DataSorting('column_1', 'asc', { numeric: true })); @@ -883,9 +884,8 @@ describe('DataTable', () => { dataTable.ngAfterViewInit(); const [col1, col2] = dataTable.getSortableColumns(); - const headerColumns = fixture.debugElement.nativeElement.querySelectorAll('.adf-datatable-cell-header-content'); - - headerColumns[1].click(); + const headerColumns = testingUtils.getAllByCSS('.adf-datatable-cell-header-content'); + headerColumns[1].nativeElement.click(); fixture.detectChanges(); expect(dataTable.isColumnSortActive(col1)).toBe(false); @@ -1223,7 +1223,7 @@ describe('DataTable', () => { dataTable.loading = false; dataTable.noPermission = false; fixture.detectChanges(); - expect(element.querySelector('.adf-sticky-header')).not.toBeNull(); + expect(testingUtils.getByCSS('.adf-sticky-header')).not.toBeNull(); }); it('should disable sticky header if component is loading', () => { @@ -1236,7 +1236,7 @@ describe('DataTable', () => { dataTable.loading = true; dataTable.noPermission = false; fixture.detectChanges(); - expect(element.querySelector('.adf-sticky-header')).toBeNull(); + expect(testingUtils.getByCSS('.adf-sticky-header')).toBeNull(); }); it('should disable sticky header if user has no permissions', () => { @@ -1249,7 +1249,7 @@ describe('DataTable', () => { dataTable.loading = false; dataTable.noPermission = true; fixture.detectChanges(); - expect(element.querySelector('.adf-sticky-header')).toBeNull(); + expect(testingUtils.getByCSS('.adf-sticky-header')).toBeNull(); }); it('should disable sticky header if user has no content', () => { @@ -1259,7 +1259,7 @@ describe('DataTable', () => { dataTable.loading = false; dataTable.noPermission = false; fixture.detectChanges(); - expect(element.querySelector('.adf-sticky-header')).toBeNull(); + expect(testingUtils.getByCSS('.adf-sticky-header')).toBeNull(); }); it('should be able to define values using the resolver function', () => { @@ -1273,16 +1273,10 @@ describe('DataTable', () => { spyOn(dataTable, 'resolverFn').and.callFake(resolverFn); fixture.detectChanges(); - const id1 = element.querySelector('[data-automation-id="text_1"]'); - const id2 = element.querySelector('[data-automation-id="text_2"]'); - const namesId1 = element.querySelector('[data-automation-id="text_foo - bar"]'); - const namesId2 = element.querySelector('[data-automation-id="text_bar - baz"]'); - - expect(id1.innerText).toEqual('1'); - expect(namesId1.innerText).toEqual('foo - bar'); - expect(id2.innerText).toEqual('2'); - expect(namesId2.innerText).toEqual('bar - baz'); - + expect(testingUtils.getInnerTextByDataAutomationId('text_1')).toEqual('1'); + expect(testingUtils.getInnerTextByDataAutomationId('text_foo - bar')).toEqual('foo - bar'); + expect(testingUtils.getInnerTextByDataAutomationId('text_2')).toEqual('2'); + expect(testingUtils.getInnerTextByDataAutomationId('text_bar - baz')).toEqual('bar - baz'); expect(dataTable.data.getRows().length).toEqual(2); }); @@ -1309,11 +1303,8 @@ describe('DataTable', () => { ); fixture.detectChanges(); - const idColumn = element.querySelector('[data-automation-id="auto_id_id"]'); - const nameColumn = element.querySelector('[data-automation-id="auto_id_name"]'); - - expect(idColumn.innerText).toContain('ID'); - expect(nameColumn.innerText).toContain('CUSTOM HEADER'); + expect(testingUtils.getInnerTextByDataAutomationId('auto_id_id')).toContain('ID'); + expect(testingUtils.getInnerTextByDataAutomationId('auto_id_name')).toContain('CUSTOM HEADER'); }); it('should set isContextMenuSource to true for row whose id matches selectedRowId', () => { @@ -1362,8 +1353,7 @@ describe('DataTable', () => { dataTable.resetSelection(); const rowClickPromise = dataTable.rowClick.pipe(take(1)).toPromise(); - const rowElement = fixture.debugElement.query(By.css(`[data-automation-id="datatable-row-0"] > div`)).nativeElement as HTMLElement; - rowElement.dispatchEvent(new MouseEvent('click')); + testingUtils.clickByCSS('[data-automation-id="datatable-row-0"] > div'); fixture.detectChanges(); await rowClickPromise; @@ -1373,8 +1363,7 @@ describe('DataTable', () => { dataTable.resetSelection(); const cellClickPromise = dataTable.rowClick.pipe(take(1)).toPromise(); - const cellElement = fixture.debugElement.query(By.css(`[data-automation-id="datatable-row-1"] > div`)).nativeElement as HTMLElement; - cellElement.dispatchEvent(new MouseEvent('click', { bubbles: true })); + testingUtils.clickByCSS('[data-automation-id="datatable-row-1"] > div'); fixture.detectChanges(); await cellClickPromise; @@ -1390,7 +1379,6 @@ describe('DataTable', () => { dataTable.ngOnChanges({ rows: new SimpleChange(null, petRows, false) }); fixture.detectChanges(); - const loader = TestbedHarnessEnvironment.loader(fixture); const checkboxes = await loader.getAllHarnesses(MatCheckboxHarness); await checkboxes[2].check(); @@ -1461,32 +1449,23 @@ describe('DataTable', () => { }); describe('displayCheckboxesOnHover', () => { - const getCheckboxes = () => - fixture.debugElement.queryAll(By.css('.adf-datatable-checkbox-single .adf-checkbox-sr-only')).map((row) => row.nativeElement); - beforeEach(() => { dataTable.data = new ObjectDataTableAdapter([{ name: '1' }, { name: '2' }], [new ObjectDataColumn({ key: 'name' })]); dataTable.multiselect = true; }); - it('should always display checkboxes when displayCheckboxesOnHover is set to false', () => { + it('should always display checkboxes when displayCheckboxesOnHover is set to false', async () => { dataTable.displayCheckboxesOnHover = false; fixture.detectChanges(); - const checkboxes = getCheckboxes(); - checkboxes.forEach((checkbox) => { - expect(checkbox.classList).not.toContain('adf-datatable-hover-only'); - }); + expect(await testingUtils.checkIfMatCheckboxesHaveClass('adf-datatable-hover-only')).toBeTrue(); }); - it('should display checkboxes on hover when displayCheckboxesOnHover is set to true', () => { + it('should display checkboxes on hover when displayCheckboxesOnHover is set to true', async () => { dataTable.displayCheckboxesOnHover = true; fixture.detectChanges(); - const checkboxes = getCheckboxes(); - checkboxes.forEach((checkbox) => { - expect(checkbox.classList).toContain('adf-datatable-hover-only'); - }); + expect(await testingUtils.checkIfMatCheckboxesHaveClass('adf-datatable-hover-only')).toBeTrue(); }); }); }); @@ -1494,8 +1473,8 @@ describe('DataTable', () => { describe('Accesibility', () => { let fixture: ComponentFixture; let dataTable: DataTableComponent; - let element: any; let columnCustomTemplate: TemplateRef; + let testingUtils: UnitTestingUtils; beforeEach(() => { TestBed.configureTestingModule({ @@ -1505,7 +1484,7 @@ describe('Accesibility', () => { columnCustomTemplate = TestBed.createComponent(CustomColumnTemplateComponent).componentInstance.templateRef; fixture = TestBed.createComponent(DataTableComponent); dataTable = fixture.componentInstance; - element = fixture.debugElement.nativeElement; + testingUtils = new UnitTestingUtils(fixture.debugElement); }); afterEach(() => { @@ -1521,19 +1500,19 @@ describe('Accesibility', () => { }); fixture.detectChanges(); - const datatableAttributes = element.querySelector('.adf-datatable-list').attributes; - const datatableHeaderAttributes = element.querySelector('.adf-datatable-list .adf-datatable-header').attributes; - const datatableHeaderCellAttributes = element.querySelector('.adf-datatable-cell-header').attributes; - const datatableBodyAttributes = element.querySelector('.adf-datatable-body').attributes; - const datatableBodyRowAttributes = element.querySelector('.adf-datatable-body .adf-datatable-row').attributes; - const datatableBodyCellAttributes = element.querySelector('.adf-datatable-body .adf-datatable-cell').attributes; + const datatableAttributes = testingUtils.getByCSS('.adf-datatable-list').attributes; + const datatableHeaderAttributes = testingUtils.getByCSS('.adf-datatable-list .adf-datatable-header').attributes; + const datatableHeaderCellAttributes = testingUtils.getByCSS('.adf-datatable-cell-header').attributes; + const datatableBodyAttributes = testingUtils.getByCSS('.adf-datatable-body').attributes; + const datatableBodyRowAttributes = testingUtils.getByCSS('.adf-datatable-body .adf-datatable-row').attributes; + const datatableBodyCellAttributes = testingUtils.getByCSS('.adf-datatable-body .adf-datatable-cell').attributes; - expect(datatableAttributes.getNamedItem('role').value).toEqual('grid'); - expect(datatableHeaderAttributes.getNamedItem('role').value).toEqual('rowgroup'); - expect(datatableHeaderCellAttributes.getNamedItem('role').value).toEqual('columnheader'); - expect(datatableBodyAttributes.getNamedItem('role').value).toEqual('rowgroup'); - expect(datatableBodyRowAttributes.getNamedItem('role').value).toEqual('row'); - expect(datatableBodyCellAttributes.getNamedItem('role').value).toEqual('gridcell'); + expect(datatableAttributes['role']).toEqual('grid'); + expect(datatableHeaderAttributes['role']).toEqual('rowgroup'); + expect(datatableHeaderCellAttributes['role']).toEqual('columnheader'); + expect(datatableBodyAttributes['role']).toEqual('rowgroup'); + expect(datatableBodyRowAttributes['role']).toEqual('row'); + expect(datatableBodyCellAttributes['role']).toEqual('gridcell'); }); describe('aria-sort', () => { @@ -1593,10 +1572,10 @@ describe('Accesibility', () => { fixture.detectChanges(); dataTable.ngAfterViewInit(); - const rowElement = document.querySelectorAll('.adf-datatable-body .adf-datatable-row')[0]; - const rowCellElement = rowElement.querySelector('.adf-datatable-cell'); + const rowElement = testingUtils.getAllByCSS('.adf-datatable-body .adf-datatable-row')[0]; + testingUtils.setDebugElement(rowElement); + testingUtils.clickByCSS('.adf-datatable-cell'); - rowCellElement?.dispatchEvent(new MouseEvent('click', { bubbles: true })); fixture.debugElement.nativeElement.dispatchEvent(event); expect(document.activeElement?.getAttribute('data-automation-id')).toBe('datatable-row-1'); @@ -1610,10 +1589,10 @@ describe('Accesibility', () => { fixture.detectChanges(); dataTable.ngAfterViewInit(); - const rowElement = document.querySelectorAll('.adf-datatable-body .adf-datatable-row')[1]; - const rowCellElement = rowElement.querySelector('.adf-datatable-cell'); + const rowElement = testingUtils.getAllByCSS('.adf-datatable-body .adf-datatable-row')[1]; + testingUtils.setDebugElement(rowElement); + testingUtils.clickByCSS('.adf-datatable-cell'); - rowCellElement?.dispatchEvent(new MouseEvent('click', { bubbles: true })); fixture.debugElement.nativeElement.dispatchEvent(event); expect(document.activeElement?.getAttribute('data-automation-id')).toBe('datatable-row-0'); @@ -1629,10 +1608,10 @@ describe('Accesibility', () => { fixture.detectChanges(); dataTable.ngAfterViewInit(); - const rowElement = document.querySelector('.adf-datatable-row[data-automation-id="datatable-row-0"]'); - const rowCellElement = rowElement?.querySelector('.adf-datatable-cell'); + const rowElement = testingUtils.getAllByCSS('.adf-datatable-body .adf-datatable-row')[0]; + testingUtils.setDebugElement(rowElement); + testingUtils.clickByCSS('.adf-datatable-cell'); - rowCellElement?.dispatchEvent(new MouseEvent('click', { bubbles: true })); fixture.debugElement.nativeElement.dispatchEvent(event); expect(document.activeElement?.getAttribute('data-automation-id')).toBe('datatable-row-header'); @@ -1648,10 +1627,10 @@ describe('Accesibility', () => { fixture.detectChanges(); dataTable.ngAfterViewInit(); - const rowElement = document.querySelector('.adf-datatable-row[data-automation-id="datatable-row-0"]'); - const rowCellElement = rowElement?.querySelector('.adf-datatable-cell'); + const rowElement = testingUtils.getAllByCSS('.adf-datatable-body .adf-datatable-row')[0]; + testingUtils.setDebugElement(rowElement); + testingUtils.clickByCSS('.adf-datatable-cell'); - rowCellElement?.dispatchEvent(new MouseEvent('click')); fixture.debugElement.nativeElement.dispatchEvent(event); expect(document.activeElement?.getAttribute('data-automation-id')).toBe('datatable-row-1'); @@ -1671,8 +1650,8 @@ describe('Accesibility', () => { fixture.detectChanges(); dataTable.ngAfterViewInit(); - const cell = document.querySelector('.adf-datatable-row[data-automation-id="datatable-row-0"] .adf-cell-value'); - expect(cell?.getAttribute('tabindex')).toBe(null); + const cell = testingUtils.getByCSS('.adf-datatable-row[data-automation-id="datatable-row-0"] .adf-cell-value'); + expect(cell?.nativeElement.getAttribute('tabindex')).toBe(null); }); it('should allow element focus when [focus] is set to true', () => { @@ -1688,8 +1667,8 @@ describe('Accesibility', () => { fixture.detectChanges(); dataTable.ngAfterViewInit(); - const cell = document.querySelector('.adf-datatable-row[data-automation-id="datatable-row-0"] .adf-cell-value'); - expect(cell?.getAttribute('tabindex')).toBe('0'); + const cell = testingUtils.getByCSS('.adf-datatable-row[data-automation-id="datatable-row-0"] .adf-cell-value'); + expect(cell?.nativeElement.getAttribute('tabindex')).toBe('0'); }); }); @@ -1698,6 +1677,7 @@ describe('Drag&Drop column header', () => { let dataTable: DataTableComponent; let data: { id: number; name: string }[] = []; let dataTableSchema: DataColumn[] = []; + let testingUtils: UnitTestingUtils; beforeEach(() => { TestBed.configureTestingModule({ @@ -1705,6 +1685,7 @@ describe('Drag&Drop column header', () => { schemas: [NO_ERRORS_SCHEMA] }); fixture = TestBed.createComponent(DataTableComponent); + testingUtils = new UnitTestingUtils(fixture.debugElement); dataTable = fixture.componentInstance; data = [ { id: 1, name: 'name1' }, @@ -1722,32 +1703,24 @@ describe('Drag&Drop column header', () => { it('should show/hide drag indicator icon', () => { fixture.detectChanges(); - const headerColumn = fixture.debugElement.nativeElement.querySelector('[data-automation-id="auto_id_name"]'); - headerColumn.dispatchEvent(new MouseEvent('mouseenter')); + testingUtils.hoverOverByDataAutomationId('auto_id_name'); fixture.detectChanges(); - let dragIcon = fixture.debugElement.nativeElement.querySelector('[data-automation-id="adf-datatable-cell-header-drag-icon-name"]'); + expect(testingUtils.getByDataAutomationId('adf-datatable-cell-header-drag-icon-name')).toBeTruthy(); - expect(dragIcon).toBeTruthy(); - - headerColumn.dispatchEvent(new MouseEvent('mouseleave')); + testingUtils.mouseLeaveByDataAutomationId('auto_id_name'); fixture.detectChanges(); - dragIcon = fixture.debugElement.nativeElement.querySelector('[data-automation-id="adf-datatable-cell-header-drag-icon-name"]'); - - expect(dragIcon).toBeFalsy(); + expect(testingUtils.getByDataAutomationId('adf-datatable-cell-header-drag-icon-name')).toBeFalsy(); }); it('should not show drag indicator icon, when drag and drop is disabled', () => { fixture.detectChanges(); - const headerColumn = fixture.debugElement.nativeElement.querySelector('[data-automation-id="auto_id_id"]'); - headerColumn.dispatchEvent(new MouseEvent('mouseenter')); + testingUtils.hoverOverByDataAutomationId('auto_id_id'); fixture.detectChanges(); - const dragIcon = fixture.debugElement.nativeElement.querySelector('[data-automation-id="adf-datatable-cell-header-drag-icon-id"]'); - - expect(dragIcon).toBeFalsy(); + expect(testingUtils.getByDataAutomationId('adf-datatable-cell-header-drag-icon-id')).toBeFalsy(); }); it('should emit on change column order', () => { @@ -1783,13 +1756,13 @@ describe('Drag&Drop column header', () => { fixture.detectChanges(); const columns = dataTable.data.getColumns(); - const headerCells = fixture.debugElement.nativeElement.querySelectorAll('.adf-datatable-cell--text.adf-datatable-cell-header'); + const headerCells = testingUtils.getAllByCSS('.adf-datatable-cell--text.adf-datatable-cell-header'); expect(columns[0].key).toEqual(dataTableSchema[1].key); expect(columns[1].key).toEqual(dataTableSchema[0].key); - expect(headerCells[0].innerText).toBe(dataTableSchema[1].title); - expect(headerCells[1].innerText).toBe(dataTableSchema[0].title); + expect(headerCells[0].nativeElement.innerText).toBe(dataTableSchema[1].title); + expect(headerCells[1].nativeElement.innerText).toBe(dataTableSchema[0].title); }); }); @@ -1798,6 +1771,7 @@ describe('Show/hide columns', () => { let dataTable: DataTableComponent; let data: DataColumn[] = []; let dataTableSchema: DataColumn[] = []; + let testingUtils: UnitTestingUtils; beforeEach(() => { TestBed.configureTestingModule({ @@ -1819,12 +1793,13 @@ describe('Show/hide columns', () => { ]; dataTable.data = new ObjectDataTableAdapter([...data], [...dataTableSchema]); + testingUtils = new UnitTestingUtils(fixture.debugElement); fixture.detectChanges(); }); it('should hide columns with isHidden prop', () => { - const headerCells = fixture.debugElement.nativeElement.querySelectorAll('.adf-datatable-cell--text.adf-datatable-cell-header'); + const headerCells = testingUtils.getAllByCSS('.adf-datatable-cell--text.adf-datatable-cell-header'); expect(headerCells.length).toBe(2); }); @@ -1847,7 +1822,7 @@ describe('Show/hide columns', () => { fixture.detectChanges(); - const headerCells = fixture.debugElement.nativeElement.querySelectorAll('.adf-datatable-cell--text.adf-datatable-cell-header'); + const headerCells = testingUtils.getAllByCSS('.adf-datatable-cell--text.adf-datatable-cell-header'); expect(headerCells.length).toBe(1); }); @@ -1881,13 +1856,14 @@ describe('Column Resizing', () => { let dataTable: DataTableComponent; let data: { id: number; name: string }[] = []; let dataTableSchema: DataColumn[] = []; + let testingUtils: UnitTestingUtils; - const getTableBody = (): HTMLDivElement => fixture.debugElement.nativeElement.querySelector('.adf-datatable-body'); + const getTableBody = (): HTMLDivElement => testingUtils.getByCSS('.adf-datatable-body').nativeElement; - const getResizeHandler = (): HTMLDivElement => fixture.debugElement.nativeElement.querySelector('.adf-datatable__resize-handle'); + const getResizeHandler = (): HTMLDivElement => testingUtils.getByCSS('.adf-datatable__resize-handle')?.nativeElement; const getResizeHandlersCount = (): number => { - const resizeHandlers = fixture.debugElement.nativeElement.querySelectorAll('.adf-datatable__resize-handle'); + const resizeHandlers = testingUtils.getAllByCSS('.adf-datatable__resize-handle'); return resizeHandlers.length; }; @@ -1895,14 +1871,14 @@ describe('Column Resizing', () => { dataTable.isResizingEnabled = true; fixture.detectChanges(); - const resizeHandle: HTMLElement = getResizeHandler(); + const resizeHandle = getResizeHandler(); resizeHandle.dispatchEvent(new MouseEvent('mousedown')); fixture.detectChanges(); - const headerColumns = fixture.debugElement.nativeElement.querySelectorAll(headerColumnsSelector); + const headerColumns = testingUtils.getAllByCSS(headerColumnsSelector); expect(dataTable.isResizing).toBeTrue(); - headerColumns.forEach((header: HTMLElement) => expect(header.classList).not.toContain(excludedClass)); + headerColumns.forEach((header) => expect(header.nativeElement.classList).not.toContain(excludedClass)); }; beforeEach(() => { @@ -1925,17 +1901,19 @@ describe('Column Resizing', () => { dataTable.data = new ObjectDataTableAdapter([...data], [...dataTableSchema]); dataTable.isResizingEnabled = false; + testingUtils = new UnitTestingUtils(fixture.debugElement); + fixture.detectChanges(); }); it('should NOT display resize handle when the feature is Disabled [isResizingEnabled=false]', () => { const resizeHandle = getResizeHandler(); - expect(resizeHandle).toBeNull(); - const headerColumns = fixture.debugElement.nativeElement.querySelectorAll('.adf-datatable-cell-header'); + expect(resizeHandle).toBeUndefined(); + const headerColumns = testingUtils.getAllByCSS('.adf-datatable-cell-header'); - headerColumns.forEach((header: HTMLElement) => { - expect(header.classList).toContain('adf-datatable__cursor--pointer'); + headerColumns.forEach((header) => { + expect(header.nativeElement.classList).toContain('adf-datatable__cursor--pointer'); }); }); @@ -1962,10 +1940,10 @@ describe('Column Resizing', () => { const resizeHandle = getResizeHandler(); expect(resizeHandle).not.toBeNull(); - const headerColumns = fixture.debugElement.nativeElement.querySelectorAll('.adf-datatable-cell-header'); + const headerColumns = testingUtils.getAllByCSS('.adf-datatable-cell-header'); - headerColumns.forEach((header: HTMLElement) => { - expect(header.classList).toContain('adf-datatable__cursor--pointer'); + headerColumns.forEach((header) => { + expect(header.nativeElement.classList).toContain('adf-datatable__cursor--pointer'); }); }); @@ -1981,18 +1959,17 @@ describe('Column Resizing', () => { dataTable.isResizingEnabled = true; fixture.detectChanges(); - const headerColumn = fixture.debugElement.nativeElement.querySelector('[data-automation-id="auto_id_id"]'); - headerColumn.dispatchEvent(new MouseEvent('mouseenter')); + testingUtils.hoverOverByDataAutomationId('auto_id_id'); fixture.detectChanges(); - let dragIcon = fixture.debugElement.nativeElement.querySelector('[data-automation-id="adf-datatable-cell-header-drag-icon-id"]'); + let dragIcon = testingUtils.getByDataAutomationId('adf-datatable-cell-header-drag-icon-id'); expect(dragIcon).not.toBeNull(); - const resizeHandle: HTMLElement[] = fixture.debugElement.nativeElement.querySelectorAll('.adf-datatable__resize-handle'); - resizeHandle[0].dispatchEvent(new MouseEvent('mousedown')); + const resizeHandles = testingUtils.getAllByCSS('.adf-datatable__resize-handle'); + resizeHandles[0].nativeElement.dispatchEvent(new MouseEvent('mousedown')); fixture.detectChanges(); - dragIcon = fixture.debugElement.nativeElement.querySelector('[data-automation-id="adf-datatable-cell-header-drag-icon-id"]'); + dragIcon = testingUtils.getByDataAutomationId('adf-datatable-cell-header-drag-icon-id'); expect(dataTable.isResizing).toBeTrue(); expect(dragIcon).toBeNull(); @@ -2003,7 +1980,7 @@ describe('Column Resizing', () => { dataTable.isResizingEnabled = true; fixture.detectChanges(); - const resizeHandle: HTMLElement = getResizeHandler(); + const resizeHandle = getResizeHandler(); resizeHandle.dispatchEvent(new MouseEvent('mousedown')); fixture.detectChanges(); }); @@ -2085,8 +2062,8 @@ describe('Column Resizing', () => { tick(); fixture.detectChanges(); - const headerColumns: HTMLElement[] = fixture.debugElement.nativeElement.querySelectorAll('.adf-datatable-cell-header'); - expect(headerColumns[0].style.flex).toBe('0 1 125px'); + const headerColumns = testingUtils.getAllByCSS('.adf-datatable-cell-header'); + expect(headerColumns[0].nativeElement.style.flex).toBe('0 1 125px'); })); it('should set the column header to 100px on resizing when its width goes below 100', fakeAsync(() => { @@ -2094,8 +2071,8 @@ describe('Column Resizing', () => { tick(); fixture.detectChanges(); - const headerColumns: HTMLElement[] = fixture.debugElement.nativeElement.querySelectorAll('.adf-datatable-cell-header'); - expect(headerColumns[0].style.flex).toBe('0 1 100px'); + const headerColumns = testingUtils.getAllByCSS('.adf-datatable-cell-header'); + expect(headerColumns[0].nativeElement.style.flex).toBe('0 1 100px'); })); it('should set the style of all the table cells under the resizing header on resizing', fakeAsync(() => { @@ -2174,7 +2151,7 @@ describe('Column Resizing', () => { dataTable.enableDragRows = false; dataTable.showHeader = ShowHeaderMode.Never; fixture.detectChanges(); - const dragAndDrop = fixture.debugElement.query(By.directive(CdkDropList)).injector.get(CdkDropList); + const dragAndDrop = testingUtils.getByDirective(CdkDropList).injector.get(CdkDropList); dataTable.onDragDrop({} as CdkDragDrop); expect(dataTable.dragDropped.emit).not.toHaveBeenCalled(); expect(dragAndDrop.disabled).toBeTrue(); @@ -2193,16 +2170,19 @@ describe('Column Resizing', () => { it('should display 2 columns for no provided actions and no default actions', () => { dataTable.data = new ObjectDataTableAdapter( [{ name: '1' }], - [new ObjectDataColumn({ key: 'name', title: 'Name', sortable: true }), new ObjectDataColumn({ key: 'other', title: 'Other', sortable: true })] + [ + new ObjectDataColumn({ key: 'name', title: 'Name', sortable: true }), + new ObjectDataColumn({ key: 'other', title: 'Other', sortable: true }) + ] ); fixture.detectChanges(); - + const visibleColumns = dataTable.getVisibleColumns(); - - const datatableCellHeaders = fixture.debugElement.queryAll(By.css('.adf-datatable-cell-header')); - const datatableCells = fixture.debugElement.queryAll(By.css('.adf-datatable-cell')); - + + const datatableCellHeaders = testingUtils.getAllByCSS('.adf-datatable-cell-header'); + const datatableCells = testingUtils.getAllByCSS('.adf-datatable-cell'); + expect(visibleColumns.length).toBe(2); const expectedNumberOfColumns = 2; @@ -2216,14 +2196,14 @@ describe('Column Resizing', () => { [{ name: '1' }], [new ObjectDataColumn({ key: 'name', title: 'Name', sortable: true }), new ObjectDataColumn({ key: 'other', sortable: true })] ); - + fixture.detectChanges(); - + const visibleColumns = dataTable.getVisibleColumns(); - - const datatableCellHeaders = fixture.debugElement.queryAll(By.css('.adf-datatable-cell-header')); - const datatableCells = fixture.debugElement.queryAll(By.css('.adf-datatable-cell')); - + + const datatableCellHeaders = testingUtils.getAllByCSS('.adf-datatable-cell-header'); + const datatableCells = testingUtils.getAllByCSS('.adf-datatable-cell'); + expect(visibleColumns.length).toBe(2); const expectedNumberOfColumns = 2; @@ -2235,18 +2215,21 @@ describe('Column Resizing', () => { it('should display 3 columns if there are default actions', () => { dataTable.data = new ObjectDataTableAdapter( [{ name: '1' }], - [new ObjectDataColumn({ key: 'name', title: 'Name', sortable: true }), new ObjectDataColumn({ key: 'other', title: 'Other', sortable: true })] + [ + new ObjectDataColumn({ key: 'name', title: 'Name', sortable: true }), + new ObjectDataColumn({ key: 'other', title: 'Other', sortable: true }) + ] ); dataTable.actions = true; - + fixture.detectChanges(); - + const visibleColumns = dataTable.getVisibleColumns(); - - const datatableCellHeaders = fixture.debugElement.queryAll(By.css('.adf-datatable-cell-header')); - const datatableCells = fixture.debugElement.queryAll(By.css('.adf-datatable-cell')); - + + const datatableCellHeaders = testingUtils.getAllByCSS('.adf-datatable-cell-header'); + const datatableCells = testingUtils.getAllByCSS('.adf-datatable-cell'); + expect(visibleColumns.length).toBe(2); const expectedNumberOfColumns = 3; @@ -2263,14 +2246,14 @@ describe('Column Resizing', () => { dataTable.actions = true; dataTable.showProvidedActions = true; - + fixture.detectChanges(); - + const visibleColumns = dataTable.getVisibleColumns(); - - const datatableCellHeaders = fixture.debugElement.queryAll(By.css('.adf-datatable-cell-header')); - const datatableCells = fixture.debugElement.queryAll(By.css('.adf-datatable-cell')); - + + const datatableCellHeaders = testingUtils.getAllByCSS('.adf-datatable-cell-header'); + const datatableCells = testingUtils.getAllByCSS('.adf-datatable-cell'); + expect(visibleColumns.length).toBe(2); const expectedNumberOfColumns = 2; diff --git a/lib/core/src/lib/datatable/components/date-cell/date-cell.component.spec.ts b/lib/core/src/lib/datatable/components/date-cell/date-cell.component.spec.ts index 760bacd01b..130d992155 100644 --- a/lib/core/src/lib/datatable/components/date-cell/date-cell.component.spec.ts +++ b/lib/core/src/lib/datatable/components/date-cell/date-cell.component.spec.ts @@ -23,11 +23,13 @@ import { AppConfigService } from '../../../app-config'; import { LOCALE_ID } from '@angular/core'; import { registerLocaleData } from '@angular/common'; import localePL from '@angular/common/locales/pl'; -import { NoopTranslateModule } from '@alfresco/adf-core'; +import { NoopTranslateModule } from '../../../testing/noop-translate.module'; +import { UnitTestingUtils } from '../../../testing/unit-testing-utils'; let component: DateCellComponent; let appConfigService: AppConfigService; let fixture: ComponentFixture; +let testingUtils: UnitTestingUtils; let mockDate; let mockTooltip = ''; @@ -46,14 +48,14 @@ const renderDateCell = (dateConfig: DateConfig, value: number | string | Date, t }; const checkDisplayedDate = (expectedDate: string) => { - const displayedDate = fixture.nativeElement.querySelector('span').textContent.trim(); + const displayedDate = testingUtils.getByCSS('span').nativeElement.textContent.trim(); expect(displayedDate).toBeTruthy(); expect(displayedDate).toBe(expectedDate); }; const checkDisplayedTooltip = (expectedTooltip: string) => { - const displayedTooltip = fixture.nativeElement.querySelector('span').title; + const displayedTooltip = testingUtils.getByCSS('span').nativeElement.title; expect(displayedTooltip).toBeTruthy(); expect(displayedTooltip).toBe(expectedTooltip); @@ -66,6 +68,7 @@ const configureTestingModule = (providers: any[]) => { }); fixture = TestBed.createComponent(DateCellComponent); component = fixture.componentInstance; + testingUtils = new UnitTestingUtils(fixture.debugElement); appConfigService = TestBed.inject(AppConfigService); diff --git a/lib/core/src/lib/datatable/components/empty-list/empty-list.component.spec.ts b/lib/core/src/lib/datatable/components/empty-list/empty-list.component.spec.ts index 68d28e003a..e9bf546906 100644 --- a/lib/core/src/lib/datatable/components/empty-list/empty-list.component.spec.ts +++ b/lib/core/src/lib/datatable/components/empty-list/empty-list.component.spec.ts @@ -17,15 +17,18 @@ import { ComponentFixture, TestBed } from '@angular/core/testing'; import { EmptyListComponent } from './empty-list.component'; +import { UnitTestingUtils } from '../../../testing/unit-testing-utils'; describe('EmptyListComponentComponent', () => { let fixture: ComponentFixture; + let testingUtils: UnitTestingUtils; beforeEach(() => { TestBed.configureTestingModule({ imports: [EmptyListComponent] }); fixture = TestBed.createComponent(EmptyListComponent); + testingUtils = new UnitTestingUtils(fixture.debugElement); }); afterEach(() => { @@ -36,6 +39,6 @@ describe('EmptyListComponentComponent', () => { fixture.detectChanges(); await fixture.whenStable(); - expect(fixture.nativeElement.querySelector('.adf-empty-list_template')).toBeDefined(); + expect(testingUtils.getByCSS('.adf-empty-list_template')).toBeDefined(); }); }); diff --git a/lib/core/src/lib/datatable/components/icon-cell/icon-cell.component.spec.ts b/lib/core/src/lib/datatable/components/icon-cell/icon-cell.component.spec.ts index d167d39211..611d78df57 100644 --- a/lib/core/src/lib/datatable/components/icon-cell/icon-cell.component.spec.ts +++ b/lib/core/src/lib/datatable/components/icon-cell/icon-cell.component.spec.ts @@ -22,17 +22,19 @@ import { ObjectDataTableAdapter } from '../../data/object-datatable-adapter'; import { ObjectDataColumn } from '../../data/object-datacolumn.model'; import { HarnessLoader } from '@angular/cdk/testing'; import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed'; -import { MatIconHarness } from '@angular/material/icon/testing'; +import { UnitTestingUtils } from '../../../testing/unit-testing-utils'; describe('IconCellComponent', () => { let component: IconCellComponent; let fixture: ComponentFixture; let loader: HarnessLoader; + let testingUtils: UnitTestingUtils; + const renderAndCheckResult = async (value: any, expectedOccurrence: boolean, expectedIconName?: string) => { component.value$.next(value); fixture.detectChanges(); - const icon = await loader.getHarnessOrNull(MatIconHarness); + const icon = await testingUtils.getMatIconOrNull(); expectedOccurrence ? expect(icon).not.toBeNull() : expect(icon).toBeNull(); if (expectedIconName) { @@ -48,6 +50,7 @@ describe('IconCellComponent', () => { fixture = TestBed.createComponent(IconCellComponent); component = fixture.componentInstance; loader = TestbedHarnessEnvironment.loader(fixture); + testingUtils = new UnitTestingUtils(fixture.debugElement, loader); }); describe('Initialization', () => { diff --git a/lib/core/src/lib/datatable/components/json-cell/json-cell.component.spec.ts b/lib/core/src/lib/datatable/components/json-cell/json-cell.component.spec.ts index 5cd793b412..3ef4950799 100644 --- a/lib/core/src/lib/datatable/components/json-cell/json-cell.component.spec.ts +++ b/lib/core/src/lib/datatable/components/json-cell/json-cell.component.spec.ts @@ -21,7 +21,7 @@ import { ObjectDataColumn } from '../../data/object-datacolumn.model'; import { JsonCellComponent } from './json-cell.component'; import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed'; import { HarnessLoader } from '@angular/cdk/testing'; -import { MatButtonHarness } from '@angular/material/button/testing'; +import { UnitTestingUtils } from '../../../testing/unit-testing-utils'; describe('JsonCellComponent', () => { let loader: HarnessLoader; @@ -30,6 +30,7 @@ describe('JsonCellComponent', () => { let dataTableAdapter: ObjectDataTableAdapter; let rowData: any; let columnData: any; + let testingUtils: UnitTestingUtils; beforeEach(() => { TestBed.configureTestingModule({ @@ -38,6 +39,7 @@ describe('JsonCellComponent', () => { fixture = TestBed.createComponent(JsonCellComponent); component = fixture.componentInstance; loader = TestbedHarnessEnvironment.loader(fixture); + testingUtils = new UnitTestingUtils(fixture.debugElement, loader); }); beforeEach(() => { @@ -73,8 +75,7 @@ describe('JsonCellComponent', () => { it('should render json button inside cell', async () => { fixture.detectChanges(); - const buttonExists = await loader.hasHarness(MatButtonHarness); - expect(buttonExists).toBe(true); + expect(await testingUtils.checkIfMatButtonExists()).toBe(true); }); it('should not setup cell when has no data', () => { diff --git a/lib/core/src/lib/datatable/components/number-cell/number-cell.component.spec.ts b/lib/core/src/lib/datatable/components/number-cell/number-cell.component.spec.ts index 5afb20835e..bb670c00ce 100644 --- a/lib/core/src/lib/datatable/components/number-cell/number-cell.component.spec.ts +++ b/lib/core/src/lib/datatable/components/number-cell/number-cell.component.spec.ts @@ -22,20 +22,22 @@ import { BehaviorSubject } from 'rxjs'; import { LOCALE_ID } from '@angular/core'; import { registerLocaleData } from '@angular/common'; import localePL from '@angular/common/locales/pl'; +import { UnitTestingUtils } from '../../../testing/unit-testing-utils'; describe('NumberCellComponent', () => { let component: NumberCellComponent; let fixture: ComponentFixture; + let testingUtils: UnitTestingUtils; const renderAndCheckNumberValue = (decimalConfig: DecimalConfig, value: number, expectedResult: string) => { component.value$ = new BehaviorSubject(value); component.decimalConfig = decimalConfig; fixture.detectChanges(); - const displayedNumber = fixture.nativeElement.querySelector('span'); + const displayedNumber = testingUtils.getByCSS('span'); expect(displayedNumber).toBeTruthy(); - expect(displayedNumber.textContent.trim()).toBe(expectedResult); + expect(displayedNumber.nativeElement.textContent.trim()).toBe(expectedResult); }; beforeEach(() => { @@ -44,6 +46,7 @@ describe('NumberCellComponent', () => { }); fixture = TestBed.createComponent(NumberCellComponent); component = fixture.componentInstance; + testingUtils = new UnitTestingUtils(fixture.debugElement); }); it('should set default decimal config', () => { @@ -63,6 +66,7 @@ describe('NumberCellComponent', () => { describe('NumberCellComponent locale', () => { let component: NumberCellComponent; let fixture: ComponentFixture; + let testingUtils: UnitTestingUtils; it('should render decimal value with custom locale', () => { TestBed.configureTestingModule({ @@ -72,15 +76,16 @@ describe('NumberCellComponent locale', () => { fixture = TestBed.createComponent(NumberCellComponent); component = fixture.componentInstance; + testingUtils = new UnitTestingUtils(fixture.debugElement); registerLocaleData(localePL); component.value$ = new BehaviorSubject(123.45); component.decimalConfig = { locale: 'pl-PL' }; fixture.detectChanges(); - const displayedNumber = fixture.nativeElement.querySelector('span'); + const displayedNumber = testingUtils.getByCSS('span'); expect(displayedNumber).toBeTruthy(); - expect(displayedNumber.textContent.trim()).toBe('123,45'); + expect(displayedNumber.nativeElement.textContent.trim()).toBe('123,45'); }); }); diff --git a/lib/core/src/lib/dialogs/confirm-dialog/confirm.dialog.spec.ts b/lib/core/src/lib/dialogs/confirm-dialog/confirm.dialog.spec.ts index ecb465c3bb..af5cc044be 100644 --- a/lib/core/src/lib/dialogs/confirm-dialog/confirm.dialog.spec.ts +++ b/lib/core/src/lib/dialogs/confirm-dialog/confirm.dialog.spec.ts @@ -18,13 +18,14 @@ import { TestBed, ComponentFixture } from '@angular/core/testing'; import { MatDialogRef, MAT_DIALOG_DATA, MatDialogModule } from '@angular/material/dialog'; import { ConfirmDialogComponent } from './confirm.dialog'; -import { By } from '@angular/platform-browser'; import { NoopAnimationsModule } from '@angular/platform-browser/animations'; -import { NoopTranslateModule } from '@alfresco/adf-core'; +import { NoopTranslateModule } from '../../testing/noop-translate.module'; +import { UnitTestingUtils } from '../../testing/unit-testing-utils'; describe('Confirm Dialog Component', () => { let fixture: ComponentFixture; let component: ConfirmDialogComponent; + let testingUtils: UnitTestingUtils; const dialogRef = { close: jasmine.createSpy('close') @@ -48,6 +49,7 @@ describe('Confirm Dialog Component', () => { dialogRef.close.calls.reset(); fixture = TestBed.createComponent(ConfirmDialogComponent); component = fixture.componentInstance; + testingUtils = new UnitTestingUtils(fixture.debugElement); }); afterEach(() => { @@ -67,25 +69,25 @@ describe('Confirm Dialog Component', () => { }); it('should render the title', () => { - const titleElement = fixture.debugElement.query(By.css('[data-automation-id="adf-confirm-dialog-title"]')); + const titleElement = testingUtils.getByDataAutomationId('adf-confirm-dialog-title'); expect(titleElement).not.toBeNull(); expect(titleElement.nativeElement.innerText).toBe('Fake Title'); }); it('should render the message', () => { - const messageElement = fixture.debugElement.query(By.css('[data-automation-id="adf-confirm-dialog-base-message"]')); + const messageElement = testingUtils.getByDataAutomationId('adf-confirm-dialog-base-message'); expect(messageElement).not.toBeNull(); expect(messageElement.nativeElement.innerText).toBe('Base Message'); }); it('should render the YES label', () => { - const messageElement = fixture.debugElement.query(By.css('[data-automation-id="adf-confirm-dialog-confirmation"]')); + const messageElement = testingUtils.getByDataAutomationId('adf-confirm-dialog-confirmation'); expect(messageElement).not.toBeNull(); expect(messageElement.nativeElement.innerText).toBe('TAKE THIS'); }); it('should render the NO label', () => { - const messageElement = fixture.debugElement.query(By.css('[data-automation-id="adf-confirm-dialog-reject"]')); + const messageElement = testingUtils.getByDataAutomationId('adf-confirm-dialog-reject'); expect(messageElement).not.toBeNull(); expect(messageElement.nativeElement.innerText).toBe('MAYBE NO'); }); @@ -98,25 +100,25 @@ describe('Confirm Dialog Component', () => { }); it('should render the title', () => { - const titleElement = fixture.debugElement.query(By.css('[data-automation-id="adf-confirm-dialog-title"]')); + const titleElement = testingUtils.getByDataAutomationId('adf-confirm-dialog-title'); expect(titleElement).not.toBeNull(); expect(titleElement.nativeElement.innerText).toBe('Fake Title'); }); it('should render the custom html', () => { - const customElement = fixture.nativeElement.querySelector('[data-automation-id="adf-confirm-dialog-custom-content"] div'); + const customElement = testingUtils.getByCSS('[data-automation-id="adf-confirm-dialog-custom-content"] div'); expect(customElement).not.toBeNull(); - expect(customElement.innerText).toBe('I am about to do to you what Limp Bizkit did to music in the late ’90s.'); + expect(customElement.nativeElement.innerText).toBe('I am about to do to you what Limp Bizkit did to music in the late ’90s.'); }); it('should render the YES label', () => { - const messageElement = fixture.debugElement.query(By.css('[data-automation-id="adf-confirm-dialog-confirmation"]')); + const messageElement = testingUtils.getByDataAutomationId('adf-confirm-dialog-confirmation'); expect(messageElement).not.toBeNull(); expect(messageElement.nativeElement.innerText).toBe('TAKE THIS'); }); it('should render the NO label', () => { - const messageElement = fixture.debugElement.query(By.css('[data-automation-id="adf-confirm-dialog-reject"]')); + const messageElement = testingUtils.getByDataAutomationId('adf-confirm-dialog-reject'); expect(messageElement).not.toBeNull(); expect(messageElement.nativeElement.innerText).toBe('MAYBE NO'); }); @@ -126,14 +128,14 @@ describe('Confirm Dialog Component', () => { it('should NOT render the thirdOption if is thirdOptionLabel is not passed', () => { component.thirdOptionLabel = undefined; fixture.detectChanges(); - const thirdOptionElement = fixture.debugElement.query(By.css('[data-automation-id="adf-confirm-dialog-confirm-all"]')); + const thirdOptionElement = testingUtils.getByDataAutomationId('adf-confirm-dialog-confirm-all'); expect(thirdOptionElement).toBeFalsy(); }); it('should render the thirdOption if thirdOptionLabel is passed', () => { component.thirdOptionLabel = 'Yes All'; fixture.detectChanges(); - const thirdOptionElement = fixture.debugElement.query(By.css('[data-automation-id="adf-confirm-dialog-confirm-all"]')); + const thirdOptionElement = testingUtils.getByDataAutomationId('adf-confirm-dialog-confirm-all'); expect(thirdOptionElement).not.toBeNull(); expect(thirdOptionElement.nativeElement.innerText.toUpperCase()).toBe('YES ALL'); }); diff --git a/lib/core/src/lib/dialogs/dialog/dialog.component.spec.ts b/lib/core/src/lib/dialogs/dialog/dialog.component.spec.ts index c0a8225a91..669ca1f49e 100644 --- a/lib/core/src/lib/dialogs/dialog/dialog.component.spec.ts +++ b/lib/core/src/lib/dialogs/dialog/dialog.component.spec.ts @@ -17,12 +17,11 @@ import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog'; import { ComponentFixture, TestBed } from '@angular/core/testing'; -import { By } from '@angular/platform-browser'; import { DIALOG_COMPONENT_DATA, DialogComponent } from './dialog.component'; import { DialogData } from './dialog-data.interface'; import { DialogSize } from './dialog.model'; -import { CoreTestingModule } from '../../testing'; -import { Component, DebugElement, inject } from '@angular/core'; +import { CoreTestingModule, UnitTestingUtils } from '../../testing'; +import { Component, inject } from '@angular/core'; import { Subject } from 'rxjs'; @Component({ @@ -39,6 +38,8 @@ describe('DialogComponent', () => { let cancelButton: HTMLButtonElement; let confirmButton: HTMLButtonElement; let dialogContainer: HTMLElement; + let testingUtils: UnitTestingUtils; + const mockId = 'mockId'; const mockDataOnConfirm$ = new Subject(); @@ -65,12 +66,13 @@ describe('DialogComponent', () => { dialogRef.close.calls.reset(); fixture = TestBed.createComponent(DialogComponent); component = fixture.componentInstance; + testingUtils = new UnitTestingUtils(fixture.debugElement); fixture.detectChanges(); - confirmButton = fixture.nativeElement.querySelector('[data-automation-id="adf-dialog-actions-confirm"]'); - closeButton = fixture.nativeElement.querySelector('[data-automation-id="adf-dialog-close-button"]'); - cancelButton = fixture.nativeElement.querySelector('[data-automation-id="adf-dialog-actions-cancel"]'); - dialogContainer = fixture.debugElement.nativeElement.querySelector('[data-automation-id="adf-dialog-container"]'); + confirmButton = testingUtils.getByDataAutomationId('adf-dialog-actions-confirm').nativeElement; + closeButton = testingUtils.getByDataAutomationId('adf-dialog-close-button')?.nativeElement; + cancelButton = testingUtils.getByDataAutomationId('adf-dialog-actions-cancel')?.nativeElement; + dialogContainer = testingUtils.getByDataAutomationId('adf-dialog-container').nativeElement; }; describe('when init with default data', () => { @@ -80,9 +82,9 @@ describe('DialogComponent', () => { it('should have default template elements', () => { expect(dialogContainer).toBeDefined(); - expect(fixture.nativeElement.querySelector('.adf-dialog-header')).toBeDefined(); - expect(fixture.nativeElement.querySelector('.adf-dialog-content')).toBeDefined(); - expect(fixture.nativeElement.querySelector('.adf-dialog-actions')).toBeDefined(); + expect(testingUtils.getByCSS('.adf-dialog-header')).toBeDefined(); + expect(testingUtils.getByCSS('.adf-dialog-content')).toBeDefined(); + expect(testingUtils.getByCSS('.adf-dialog-actions')).toBeDefined(); }); it('should have default values for the dialog', () => { @@ -173,11 +175,11 @@ describe('DialogComponent', () => { }); it('should hide close button', () => { - expect(closeButton).toBeNull(); + expect(closeButton).toBeUndefined(); }); it('should hide close button', () => { - expect(cancelButton).toBeNull(); + expect(cancelButton).toBeUndefined(); }); }); @@ -195,11 +197,8 @@ describe('DialogComponent', () => { }); it('should not have header and actions border', () => { - const headerBorder = fixture.nativeElement.querySelector('.adf-alert .adf-dialog-header::after'); - const actionsBorder = fixture.nativeElement.querySelector('.adf-alert .adf-dialog-actions::after'); - - expect(headerBorder).toBeDefined(); - expect(actionsBorder).toBeDefined(); + expect(testingUtils.getByCSS('.adf-alert .adf-dialog-header::after')).toBeDefined(); + expect(testingUtils.getByCSS('.adf-alert .adf-dialog-actions::after')).toBeDefined(); }); }); @@ -217,11 +216,8 @@ describe('DialogComponent', () => { }); it('should not have header and actions border', () => { - const headerBorder = fixture.nativeElement.querySelector('.adf-alert .adf-dialog-header::after'); - const actionsBorder = fixture.nativeElement.querySelector('.adf-alert .adf-dialog-actions::after'); - - expect(headerBorder).toBeDefined(); - expect(actionsBorder).toBeDefined(); + expect(testingUtils.getByCSS('.adf-alert .adf-dialog-header::after')).toBeDefined(); + expect(testingUtils.getByCSS('.adf-alert .adf-dialog-actions::after')).toBeDefined(); }); }); @@ -240,17 +236,12 @@ describe('DialogComponent', () => { }); it('should not have header and actions border', () => { - const headerBorder = fixture.nativeElement.querySelector('.adf-alert .adf-dialog-header::after'); - const actionsBorder = fixture.nativeElement.querySelector('.adf-alert .adf-dialog-actions::after'); - - expect(headerBorder).toBeNull(); - expect(actionsBorder).toBeNull(); + expect(testingUtils.getByCSS('.adf-alert .adf-dialog-header::after')).toBeNull(); + expect(testingUtils.getByCSS('.adf-alert .adf-dialog-actions::after')).toBeNull(); }); it('should not center header content', () => { - const header = fixture.nativeElement.querySelector('.adf-centered-header'); - - expect(header).toBeNull(); + expect(testingUtils.getByCSS('.adf-centered-header')).toBeNull(); }); }); @@ -264,15 +255,11 @@ describe('DialogComponent', () => { }); it('should have icon element', () => { - const headerIcon = fixture.nativeElement.querySelector('.adf-dialog-header-icon'); - - expect(headerIcon).toBeDefined(); + expect(testingUtils.getByCSS('.adf-dialog-header-icon')).toBeDefined(); }); it('should center header content', () => { - const header = fixture.nativeElement.querySelector('.adf-centered-header'); - - expect(header).toBeDefined(); + expect(testingUtils.getByCSS('.adf-centered-header')).toBeDefined(); }); }); }); @@ -289,7 +276,7 @@ describe('DialogComponent', () => { }); it('should generate component with injectoted data', () => { - const debugElement: DebugElement = fixture.debugElement.query(By.directive(DummyComponent)); + const debugElement = testingUtils.getByDirective(DummyComponent); const dummyComponentInstance = debugElement.componentInstance; expect(dummyComponentInstance).toBeTruthy(); diff --git a/lib/core/src/lib/dialogs/unsaved-changes-dialog/unsaved-changes-dialog.component.spec.ts b/lib/core/src/lib/dialogs/unsaved-changes-dialog/unsaved-changes-dialog.component.spec.ts index 51e7fbfcab..08f7742865 100644 --- a/lib/core/src/lib/dialogs/unsaved-changes-dialog/unsaved-changes-dialog.component.spec.ts +++ b/lib/core/src/lib/dialogs/unsaved-changes-dialog/unsaved-changes-dialog.component.spec.ts @@ -17,15 +17,16 @@ import { ComponentFixture, TestBed } from '@angular/core/testing'; import { AppConfigValues, CoreTestingModule, UnsavedChangesDialogComponent, UserPreferencesService } from '@alfresco/adf-core'; -import { By } from '@angular/platform-browser'; import { DebugElement } from '@angular/core'; import { MAT_DIALOG_DATA, MatDialogClose } from '@angular/material/dialog'; import { UnsavedChangesDialogData } from './unsaved-changes-dialog.model'; +import { UnitTestingUtils } from '../../testing/unit-testing-utils'; describe('UnsavedChangesDialog', () => { let fixture: ComponentFixture; let userPreferencesService: UserPreferencesService; let savePreferenceCheckbox: DebugElement; + let testingUtils: UnitTestingUtils; const setupBeforeEach = (unsavedChangesDialogData?: UnsavedChangesDialogData) => { TestBed.configureTestingModule({ @@ -40,14 +41,15 @@ describe('UnsavedChangesDialog', () => { userPreferencesService = TestBed.inject(UserPreferencesService); fixture = TestBed.createComponent(UnsavedChangesDialogComponent); + testingUtils = new UnitTestingUtils(fixture.debugElement); fixture.detectChanges(); - savePreferenceCheckbox = fixture.debugElement.query(By.css('[data-automation-id="adf-unsaved-changes-dialog-content-checkbox"]')); + savePreferenceCheckbox = testingUtils.getByDataAutomationId('adf-unsaved-changes-dialog-content-checkbox'); }; const getElements = (): { header: HTMLElement; content: HTMLElement; discardChangesButton: HTMLElement } => { - const header = fixture.nativeElement.querySelector('.adf-unsaved-changes-dialog-header'); - const content = fixture.nativeElement.querySelector('.adf-unsaved-changes-dialog-content'); - const discardChangesButton = fixture.nativeElement.querySelector('.adf-unsaved-changes-dialog-actions-discard-changes-button'); + const header = testingUtils.getByCSS('.adf-unsaved-changes-dialog-header').nativeElement; + const content = testingUtils.getByCSS('.adf-unsaved-changes-dialog-content').nativeElement; + const discardChangesButton = testingUtils.getByCSS('.adf-unsaved-changes-dialog-actions-discard-changes-button').nativeElement; return { header, content, discardChangesButton }; }; @@ -65,16 +67,13 @@ describe('UnsavedChangesDialog', () => { it('should have assigned dialog close button with true as result', () => { expect( - fixture.debugElement - .query(By.css('[data-automation-id="adf-unsaved-changes-dialog-discard-changes-button"]')) - .injector.get(MatDialogClose).dialogResult + testingUtils.getByDataAutomationId('adf-unsaved-changes-dialog-discard-changes-button').injector.get(MatDialogClose).dialogResult ).toBeTrue(); }); it('should have assigned dialog close button with false as result', () => { expect( - fixture.debugElement.query(By.css('[data-automation-id="adf-unsaved-changes-dialog-cancel-button"]')).injector.get(MatDialogClose) - .dialogResult + testingUtils.getByDataAutomationId('adf-unsaved-changes-dialog-cancel-button').injector.get(MatDialogClose).dialogResult ).toBeFalse(); }); }); diff --git a/lib/core/src/lib/directives/highlight.directive.spec.ts b/lib/core/src/lib/directives/highlight.directive.spec.ts index cbab5ded0c..25a325d4c5 100644 --- a/lib/core/src/lib/directives/highlight.directive.spec.ts +++ b/lib/core/src/lib/directives/highlight.directive.spec.ts @@ -17,9 +17,9 @@ import { Component, ViewChildren } from '@angular/core'; import { ComponentFixture, TestBed } from '@angular/core/testing'; -import { By } from '@angular/platform-browser'; import { HighlightTransformService } from '../common/services/highlight-transform.service'; import { HighlightDirective } from './highlight.directive'; +import { UnitTestingUtils } from '../testing/unit-testing-utils'; /* spellchecker: disable */ @Component({ @@ -43,6 +43,7 @@ class TestComponent { describe('HighlightDirective', () => { let fixture: ComponentFixture; let component: TestComponent; + let testingUtils: UnitTestingUtils; beforeEach(() => { TestBed.configureTestingModule({ @@ -50,6 +51,7 @@ describe('HighlightDirective', () => { }); fixture = TestBed.createComponent(TestComponent); component = fixture.componentInstance; + testingUtils = new UnitTestingUtils(fixture.debugElement); fixture.detectChanges(); }); @@ -57,7 +59,7 @@ describe('HighlightDirective', () => { component.highlightDirectives.last.highlight('salana-eyong-aysis'); fixture.detectChanges(); - const containerElement = fixture.debugElement.query(By.css('#innerDiv21')); + const containerElement = testingUtils.getByCSS('#innerDiv21'); expect(containerElement).not.toBeNull(); expect(containerElement.nativeElement.innerHTML).toBe('Lorem ipsum salana-eyong-aysis dolor sit amet'); }); @@ -66,8 +68,8 @@ describe('HighlightDirective', () => { component.highlightDirectives.first.highlight('salana-eyong-aysis'); fixture.detectChanges(); - const containerElement1 = fixture.debugElement.query(By.css('#innerDiv11')); - const containerElement2 = fixture.debugElement.query(By.css('#innerDiv14')); + const containerElement1 = testingUtils.getByCSS('#innerDiv11'); + const containerElement2 = testingUtils.getByCSS('#innerDiv14'); expect(containerElement1).not.toBeNull(); expect(containerElement2).not.toBeNull(); expect(containerElement1.nativeElement.innerHTML).toBe( @@ -82,7 +84,7 @@ describe('HighlightDirective', () => { component.highlightDirectives.first.highlight('salana-eyong-aysis'); fixture.detectChanges(); - const containerElement1 = fixture.debugElement.query(By.css('#innerDiv12')); + const containerElement1 = testingUtils.getByCSS('#innerDiv12'); expect(containerElement1).not.toBeNull(); expect(containerElement1.nativeElement.innerHTML).toBe('Lorem ipsum salana-eyong-aysis dolor sit amet'); }); @@ -93,7 +95,7 @@ describe('HighlightDirective', () => { component.highlightDirectives.first.highlight('salana-eyong-aysis'); fixture.detectChanges(); - const containerElement = fixture.debugElement.query(By.css('#innerDiv11')); + const containerElement = testingUtils.getByCSS('#innerDiv11'); expect(containerElement).not.toBeNull(); expect(containerElement.nativeElement.innerHTML).not.toContain('Modified text'); }); diff --git a/lib/core/src/lib/directives/infinite-select-scroll.directive.spec.ts b/lib/core/src/lib/directives/infinite-select-scroll.directive.spec.ts index 05b9491ae9..9e1678d933 100644 --- a/lib/core/src/lib/directives/infinite-select-scroll.directive.spec.ts +++ b/lib/core/src/lib/directives/infinite-select-scroll.directive.spec.ts @@ -22,7 +22,7 @@ import { MatSelect, MatSelectModule } from '@angular/material/select'; import { NoopAnimationsModule } from '@angular/platform-browser/animations'; import { HarnessLoader } from '@angular/cdk/testing'; import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed'; -import { MatSelectHarness } from '@angular/material/select/testing'; +import { UnitTestingUtils } from '../testing/unit-testing-utils'; @Component({ template: ` @@ -50,6 +50,7 @@ describe('InfiniteSelectScrollDirective', () => { let fixture: ComponentFixture; let component: TestComponent; let loader: HarnessLoader; + let testingUtils: UnitTestingUtils; beforeEach(() => { TestBed.configureTestingModule({ @@ -65,13 +66,12 @@ describe('InfiniteSelectScrollDirective', () => { component.open(); fixture.detectChanges(); loader = TestbedHarnessEnvironment.loader(fixture); + testingUtils = new UnitTestingUtils(fixture.debugElement, loader); flush(); })); it('should call an action on scrollEnd event', async () => { - const select = await loader.getHarness(MatSelectHarness); - const panel = await select.host(); - + const panel = await testingUtils.getMatSelectHost(); await panel.dispatchEvent('scrollEnd'); expect(component.options.length).toBe(60); diff --git a/lib/core/src/lib/directives/logout.directive.spec.ts b/lib/core/src/lib/directives/logout.directive.spec.ts index 67cb238384..192849fdc1 100644 --- a/lib/core/src/lib/directives/logout.directive.spec.ts +++ b/lib/core/src/lib/directives/logout.directive.spec.ts @@ -22,7 +22,8 @@ import { of, throwError } from 'rxjs'; import { AuthenticationService } from '../auth/services/authentication.service'; import { AppConfigService } from '../app-config/app-config.service'; import { LogoutDirective } from './logout.directive'; -import { NoopAuthModule } from '@alfresco/adf-core'; +import { NoopAuthModule } from '../testing/noop-auth.module'; +import { UnitTestingUtils } from '../testing/unit-testing-utils'; describe('LogoutDirective', () => { describe('No input', () => { @@ -41,6 +42,7 @@ describe('LogoutDirective', () => { let router: Router; let authService: AuthenticationService; let appConfig: AppConfigService; + let testingUtils: UnitTestingUtils; beforeEach(() => { TestBed.configureTestingModule({ @@ -50,6 +52,7 @@ describe('LogoutDirective', () => { authService = TestBed.inject(AuthenticationService); appConfig = TestBed.inject(AppConfigService); fixture = TestBed.createComponent(TestComponent); + testingUtils = new UnitTestingUtils(fixture.debugElement); fixture.detectChanges(); appConfig.config['loginRoute'] = undefined; }); @@ -58,8 +61,7 @@ describe('LogoutDirective', () => { spyOn(router, 'navigate'); spyOn(authService, 'logout').and.returnValue(of(true)); - const button = fixture.nativeElement.querySelector('button'); - button.click(); + testingUtils.clickByCSS('button'); expect(authService.logout).toHaveBeenCalled(); expect(router.navigate).toHaveBeenCalledWith(['/login']); @@ -71,8 +73,7 @@ describe('LogoutDirective', () => { appConfig.config['loginRoute'] = 'fake-base-logout'; spyOn(authService, 'logout').and.returnValue(of(true)); - const button = fixture.nativeElement.querySelector('button'); - button.click(); + testingUtils.clickByCSS('button'); expect(authService.logout).toHaveBeenCalled(); expect(router.navigate).toHaveBeenCalledWith(['fake-base-logout']); @@ -83,8 +84,7 @@ describe('LogoutDirective', () => { spyOn(authService, 'isOauth').and.returnValue(true); spyOn(authService, 'logout').and.returnValue(of(true)); - const button = fixture.nativeElement.querySelector('button'); - button.click(); + testingUtils.clickByCSS('button'); expect(authService.logout).toHaveBeenCalled(); expect(router.navigate).not.toHaveBeenCalled(); @@ -94,8 +94,7 @@ describe('LogoutDirective', () => { spyOn(router, 'navigate'); spyOn(authService, 'logout').and.returnValue(throwError('err')); - const button = fixture.nativeElement.querySelector('button'); - button.click(); + testingUtils.clickByCSS('button'); expect(authService.logout).toHaveBeenCalled(); expect(router.navigate).toHaveBeenCalledWith(['/login']); @@ -117,6 +116,7 @@ describe('LogoutDirective', () => { let fixture: ComponentFixture; let router: Router; let authService: AuthenticationService; + let testingUtils: UnitTestingUtils; beforeEach(() => { TestBed.configureTestingModule({ @@ -125,6 +125,7 @@ describe('LogoutDirective', () => { router = TestBed.inject(Router); authService = TestBed.inject(AuthenticationService); fixture = TestBed.createComponent(TestComponent); + testingUtils = new UnitTestingUtils(fixture.debugElement); fixture.detectChanges(); }); @@ -132,8 +133,7 @@ describe('LogoutDirective', () => { spyOn(router, 'navigate'); spyOn(authService, 'logout').and.returnValue(of(true)); - const button = fixture.nativeElement.querySelector('button'); - button.click(); + testingUtils.clickByCSS('button'); expect(authService.logout).toHaveBeenCalled(); expect(router.navigate).toHaveBeenCalledWith(['/myCustomUri']); @@ -155,6 +155,7 @@ describe('LogoutDirective', () => { let fixture: ComponentFixture; let router: Router; let authService: AuthenticationService; + let testingUtils: UnitTestingUtils; beforeEach(() => { TestBed.configureTestingModule({ @@ -163,14 +164,15 @@ describe('LogoutDirective', () => { router = TestBed.inject(Router); authService = TestBed.inject(AuthenticationService); fixture = TestBed.createComponent(TestComponent); + testingUtils = new UnitTestingUtils(fixture.debugElement); fixture.detectChanges(); }); it('should not redirect if enableRedirect is false', () => { spyOn(router, 'navigate'); spyOn(authService, 'logout').and.returnValue(of(true)); - const button = fixture.nativeElement.querySelector('button'); - button.click(); + + testingUtils.clickByCSS('button'); expect(authService.logout).toHaveBeenCalled(); expect(router.navigate).not.toHaveBeenCalled(); diff --git a/lib/core/src/lib/dynamic-chip-list/dynamic-chip-list.component.spec.ts b/lib/core/src/lib/dynamic-chip-list/dynamic-chip-list.component.spec.ts index 4b656a0bc6..7b0d6a1ba5 100644 --- a/lib/core/src/lib/dynamic-chip-list/dynamic-chip-list.component.spec.ts +++ b/lib/core/src/lib/dynamic-chip-list/dynamic-chip-list.component.spec.ts @@ -15,10 +15,12 @@ * limitations under the License. */ -import { Chip, CoreTestingModule, DynamicChipListComponent } from '@alfresco/adf-core'; -import { SimpleChange } from '@angular/core'; +import { DebugElement, SimpleChange } from '@angular/core'; import { ComponentFixture, fakeAsync, TestBed, tick } from '@angular/core/testing'; -import { By } from '@angular/platform-browser'; +import { Chip } from './chip'; +import { DynamicChipListComponent } from './dynamic-chip-list.component'; +import { CoreTestingModule } from '../testing/core.testing.module'; +import { UnitTestingUtils } from '../testing/unit-testing-utils'; describe('DynamicChipListComponent', () => { let chips: Chip[] = [ @@ -41,7 +43,7 @@ describe('DynamicChipListComponent', () => { ]; let component: DynamicChipListComponent; let fixture: ComponentFixture; - let element: HTMLElement; + let testingUtils: UnitTestingUtils; let resizeCallback: ResizeObserverCallback; /** @@ -50,7 +52,7 @@ describe('DynamicChipListComponent', () => { * @returns native element */ function findViewMoreButton(): HTMLButtonElement { - return element.querySelector('[data-automation-id="adf-dynamic-chip-list-view-more-button"]'); + return testingUtils.getByDataAutomationId('adf-dynamic-chip-list-view-more-button').nativeElement; } /** @@ -58,8 +60,8 @@ describe('DynamicChipListComponent', () => { * * @returns native element list */ - function findChips(): NodeListOf { - return element.querySelectorAll('.adf-dynamic-chip-list-chip'); + function findChips(): DebugElement[] { + return testingUtils.getAllByCSS('.adf-dynamic-chip-list-chip'); } beforeEach(() => { @@ -68,9 +70,9 @@ describe('DynamicChipListComponent', () => { }); const resizeObserverSpy = spyOn(window, 'ResizeObserver').and.callThrough(); fixture = TestBed.createComponent(DynamicChipListComponent); - element = fixture.nativeElement; component = fixture.componentInstance; component.chips = chips; + testingUtils = new UnitTestingUtils(fixture.debugElement); fixture.detectChanges(); resizeCallback = resizeObserverSpy.calls.mostRecent().args[0]; }); @@ -83,13 +85,12 @@ describe('DynamicChipListComponent', () => { fixture.detectChanges(); await fixture.whenStable(); - expect(element.querySelector('#adf-dynamic-chip-list-chip-name-0')?.innerHTML).toBe('test1'); - expect(element.querySelector('#adf-dynamic-chip-list-chip-name-1')?.innerHTML).toBe('test2'); - expect(element.querySelector('#adf-dynamic-chip-list-chip-name-2')?.innerHTML).toBe('test3'); - - expect(element.querySelector('#adf-dynamic-chip-list-delete-test1')).not.toBe(null); - expect(element.querySelector('#adf-dynamic-chip-list-delete-test2')).not.toBe(null); - expect(element.querySelector('#adf-dynamic-chip-list-delete-test3')).not.toBe(null); + expect(testingUtils.getInnerTextByCSS('#adf-dynamic-chip-list-chip-name-0')).toBe('test1'); + expect(testingUtils.getInnerTextByCSS('#adf-dynamic-chip-list-chip-name-1')).toBe('test2'); + expect(testingUtils.getInnerTextByCSS('#adf-dynamic-chip-list-chip-name-2')).toBe('test3'); + expect(testingUtils.getByCSS('#adf-dynamic-chip-list-delete-test1')).not.toBe(null); + expect(testingUtils.getByCSS('#adf-dynamic-chip-list-delete-test2')).not.toBe(null); + expect(testingUtils.getByCSS('#adf-dynamic-chip-list-delete-test3')).not.toBe(null); }); it('should emit removedChip event when clicked on delete icon', async () => { @@ -101,8 +102,7 @@ describe('DynamicChipListComponent', () => { fixture.detectChanges(); await fixture.whenStable(); - const deleteButton: any = element.querySelector('#adf-dynamic-chip-list-delete-test1'); - deleteButton.click(); + testingUtils.clickByCSS('#adf-dynamic-chip-list-delete-test1'); expect(component.removedChip.emit).toHaveBeenCalledWith('0ee933fa-57fc-4587-8a77-b787e814f1d2'); }); @@ -116,8 +116,7 @@ describe('DynamicChipListComponent', () => { fixture.detectChanges(); await fixture.whenStable(); - const deleteButton: any = element.querySelector('#adf-dynamic-chip-list-delete-test1'); - expect(deleteButton).toBeNull(); + expect(testingUtils.getByCSS('#adf-dynamic-chip-list-delete-test1')).toBeNull(); }); it('should show the delete button if showDelete is true', async () => { @@ -129,8 +128,7 @@ describe('DynamicChipListComponent', () => { fixture.detectChanges(); await fixture.whenStable(); - const deleteButton: any = element.querySelector('#adf-dynamic-chip-list-delete-test1'); - expect(deleteButton).not.toBeNull(); + expect(testingUtils.getByCSS('#adf-dynamic-chip-list-delete-test1')).not.toBeNull(); }); it('should round up chips if roundUpChips is true', async () => { @@ -142,7 +140,7 @@ describe('DynamicChipListComponent', () => { fixture.detectChanges(); await fixture.whenStable(); - const chip = fixture.debugElement.query(By.css('.adf-dynamic-chip-list-chip')); + const chip = testingUtils.getByCSS('.adf-dynamic-chip-list-chip'); expect(getComputedStyle(chip.nativeElement).borderRadius).toBe('20px'); }); @@ -155,7 +153,7 @@ describe('DynamicChipListComponent', () => { fixture.detectChanges(); await fixture.whenStable(); - const chip = fixture.debugElement.query(By.css('.adf-dynamic-chip-list-delete-icon')); + const chip = testingUtils.getByCSS('.adf-dynamic-chip-list-delete-icon'); expect(Object.keys(chip.attributes)).toContain('disabled'); }); @@ -192,7 +190,7 @@ describe('DynamicChipListComponent', () => { beforeEach(() => { component.limitChipsDisplayed = true; component.ngOnInit(); - element.style.maxWidth = '309px'; + fixture.nativeElement.style.maxWidth = '309px'; }); afterEach(() => { @@ -213,7 +211,7 @@ describe('DynamicChipListComponent', () => { it('should not render view more button when limiting is enabled and all chips fits into container', fakeAsync(() => { renderChips(); - element.style.maxWidth = '800px'; + fixture.nativeElement.style.maxWidth = '800px'; component.ngOnChanges({ chips: new SimpleChange(undefined, component.chips, true) }); @@ -288,7 +286,7 @@ describe('DynamicChipListComponent', () => { }); tick(); fixture.detectChanges(); - element.style.maxWidth = '800px'; + fixture.nativeElement.style.maxWidth = '800px'; resizeCallback([], null); fixture.detectChanges(); @@ -299,14 +297,14 @@ describe('DynamicChipListComponent', () => { it('should render view more button when there is not enough space after resizing', fakeAsync(() => { renderChips(); - element.style.maxWidth = '800px'; + fixture.nativeElement.style.maxWidth = '800px'; component.ngOnChanges({ chips: new SimpleChange(undefined, component.chips, true) }); tick(); fixture.detectChanges(); - element.style.maxWidth = '100px'; + fixture.nativeElement.style.maxWidth = '100px'; resizeCallback([], null); fixture.detectChanges(); @@ -324,7 +322,7 @@ describe('DynamicChipListComponent', () => { const viewMoreButton = findViewMoreButton(); viewMoreButton.click(); fixture.detectChanges(); - element.style.maxWidth = '309px'; + fixture.nativeElement.style.maxWidth = '309px'; resizeCallback([], null); fixture.detectChanges(); diff --git a/lib/core/src/lib/form/components/form-field/form-field.component.spec.ts b/lib/core/src/lib/form/components/form-field/form-field.component.spec.ts index 11b754cb12..5ce57b6f37 100644 --- a/lib/core/src/lib/form/components/form-field/form-field.component.spec.ts +++ b/lib/core/src/lib/form/components/form-field/form-field.component.spec.ts @@ -16,7 +16,7 @@ */ import { ComponentFixture, TestBed } from '@angular/core/testing'; -import { CoreTestingModule } from '../../../testing'; +import { CoreTestingModule, UnitTestingUtils } from '../../../testing'; import { FormRenderingService } from '../../services/form-rendering.service'; import { CheckboxWidgetComponent, FormFieldModel, FormFieldTypes, FormModel, TextWidgetComponent } from '../widgets'; import { FormFieldComponent } from './form-field.component'; @@ -25,6 +25,7 @@ describe('FormFieldComponent', () => { let fixture: ComponentFixture; let component: FormFieldComponent; let form: FormModel; + let testingUtils: UnitTestingUtils; let formRenderingService: FormRenderingService; @@ -34,6 +35,7 @@ describe('FormFieldComponent', () => { }); fixture = TestBed.createComponent(FormFieldComponent); component = fixture.componentInstance; + testingUtils = new UnitTestingUtils(fixture.debugElement); formRenderingService = fixture.debugElement.injector.get(FormRenderingService); form = new FormModel(); }); @@ -117,9 +119,9 @@ describe('FormFieldComponent', () => { fixture.detectChanges(); - const debugElement = fixture.nativeElement.querySelector('#field-FAKE-TXT-WIDGET-container').style; - expect(debugElement.visibility).toEqual('hidden'); - expect(debugElement.display).toEqual('none'); + const styles = testingUtils.getByCSS('#field-FAKE-TXT-WIDGET-container').styles; + expect(styles.visibility).toEqual('hidden'); + expect(styles.display).toEqual('none'); }); it('should show the field when it is visible', () => { @@ -132,8 +134,9 @@ describe('FormFieldComponent', () => { fixture.detectChanges(); - expect(fixture.nativeElement.querySelector('#field-FAKE-TXT-WIDGET-container').style.visibility).toEqual('visible'); - expect(fixture.nativeElement.querySelector('#field-FAKE-TXT-WIDGET-container').style.display).toEqual('block'); + const styles = testingUtils.getByCSS('#field-FAKE-TXT-WIDGET-container').styles; + expect(styles.visibility).toEqual('visible'); + expect(styles.display).toEqual('block'); }); it('should hide a visible element', () => { @@ -144,12 +147,14 @@ describe('FormFieldComponent', () => { component.field = field; fixture.detectChanges(); - expect(fixture.nativeElement.querySelector('#field-FAKE-TXT-WIDGET-container').style.visibility).toEqual('visible'); - expect(fixture.nativeElement.querySelector('#field-FAKE-TXT-WIDGET-container').style.display).toEqual('block'); + let styles = testingUtils.getByCSS('#field-FAKE-TXT-WIDGET-container').styles; + expect(styles.visibility).toEqual('visible'); + expect(styles.display).toEqual('block'); component.field.isVisible = false; fixture.detectChanges(); - expect(fixture.nativeElement.querySelector('#field-FAKE-TXT-WIDGET-container').style.visibility).toEqual('hidden'); - expect(fixture.nativeElement.querySelector('#field-FAKE-TXT-WIDGET-container').style.display).toEqual('none'); + styles = testingUtils.getByCSS('#field-FAKE-TXT-WIDGET-container').styles; + expect(styles.visibility).toEqual('hidden'); + expect(styles.display).toEqual('none'); }); it('[C213878] - Should fields be correctly rendered when filled with process variables', () => { @@ -199,7 +204,7 @@ describe('FormFieldComponent', () => { component.field = field; fixture.detectChanges(); - const hyperlink: HTMLLinkElement = fixture.nativeElement.querySelector('#field-label2-container hyperlink-widget a'); + const hyperlink: HTMLLinkElement = testingUtils.getByCSS('#field-label2-container hyperlink-widget a').nativeElement; expect(hyperlink).not.toBeNull(); expect(hyperlink.href).toBe('http://testtest/'); expect(hyperlink.textContent).toBe('testtest'); diff --git a/lib/core/src/lib/form/components/form-renderer.component.spec.ts b/lib/core/src/lib/form/components/form-renderer.component.spec.ts index f67e5fc8d9..fa591f40fd 100644 --- a/lib/core/src/lib/form/components/form-renderer.component.spec.ts +++ b/lib/core/src/lib/form/components/form-renderer.component.spec.ts @@ -16,7 +16,7 @@ */ import { ComponentFixture, TestBed } from '@angular/core/testing'; -import { CoreTestingModule } from '../../testing'; +import { CoreTestingModule, UnitTestingUtils } from '../../testing'; import { FormRulesManager } from '../models/form-rules.model'; import { FormRenderingService } from '../services/form-rendering.service'; import { FormService } from '../services/form.service'; @@ -46,34 +46,35 @@ import { } from './mock/form-renderer.component.mock'; import { TextWidgetComponent } from './widgets'; -const typeIntoInput = (targetInput: HTMLInputElement, message: string) => { - expect(targetInput).toBeTruthy('Expected input to set to be valid and not null'); - targetInput.value = message; - targetInput.dispatchEvent(new Event('input')); +const typeIntoInput = (testingUtils: UnitTestingUtils, selector: string, message: string) => { + testingUtils.fillInputByCSS(selector, message); }; -const expectElementToBeHidden = (targetElement: HTMLElement): void => { +const expectElementToBeHidden = (testingUtils: UnitTestingUtils, selector: string): void => { + const targetElement = testingUtils.getByCSS(selector).nativeElement; expect(targetElement).toBeTruthy(); expect(targetElement.style.visibility).toBe('hidden', `${targetElement.id} should be hidden but it is not`); }; -const expectElementToBeVisible = (targetElement: HTMLElement): void => { +const expectElementToBeVisible = (testingUtils: UnitTestingUtils, selector: string): void => { + const targetElement = testingUtils.getByCSS(selector).nativeElement; expect(targetElement).toBeTruthy(); expect(targetElement.style.visibility).not.toBe('hidden', `${targetElement.id} should be visibile but it is not`); }; -const expectInputElementValueIs = (targetElement: HTMLInputElement, value: string): void => { +const expectInputElementValueIs = (testingUtils: UnitTestingUtils, selector: string, value: string): void => { + const targetElement = testingUtils.getByCSS(selector).nativeElement; expect(targetElement).toBeTruthy(); expect(targetElement.value).toBe(value, `invalid value for ${targetElement.name}`); }; -const expectElementToBeInvalid = (fieldId: string, fixture: ComponentFixture>): void => { - const invalidElementContainer = fixture.nativeElement.querySelector(`#field-${fieldId}-container .adf-invalid`); +const expectElementToBeInvalid = (testingUtils: UnitTestingUtils, fieldId: string): void => { + const invalidElementContainer = testingUtils.getByCSS(`#field-${fieldId}-container .adf-invalid`); expect(invalidElementContainer).toBeTruthy(); }; -const expectElementToBeValid = (fieldId: string, fixture: ComponentFixture>): void => { - const invalidElementContainer = fixture.nativeElement.querySelector(`#field-${fieldId}-container .adf-invalid`); +const expectElementToBeValid = (testingUtils: UnitTestingUtils, fieldId: string): void => { + const invalidElementContainer = testingUtils.getByCSS(`#field-${fieldId}-container .adf-invalid`); expect(invalidElementContainer).toBeFalsy(); }; @@ -83,6 +84,7 @@ describe('Form Renderer Component', () => { let formService: FormService; let formRenderingService: FormRenderingService; let rulesManager: FormRulesManager; + let testingUtils: UnitTestingUtils; beforeEach(() => { TestBed.configureTestingModule({ @@ -90,6 +92,7 @@ describe('Form Renderer Component', () => { }); fixture = TestBed.createComponent(FormRendererComponent); formRendererComponent = fixture.componentInstance; + testingUtils = new UnitTestingUtils(fixture.debugElement); formService = TestBed.inject(FormService); formRenderingService = TestBed.inject(FormRenderingService); rulesManager = fixture.debugElement.injector.get(FormRulesManager); @@ -105,18 +108,13 @@ describe('Form Renderer Component', () => { fixture.detectChanges(); await fixture.whenStable(); - const inputDateTestOne = fixture.nativeElement.querySelector('#Date0hwq20') as HTMLInputElement; - let displayTextElementContainer: HTMLInputElement = fixture.nativeElement.querySelector('#field-Text0pqd1u-container'); - expectElementToBeHidden(displayTextElementContainer); - - inputDateTestOne.value = '2019-11-19'; - inputDateTestOne.dispatchEvent(new Event('input')); + expectElementToBeHidden(testingUtils, '#field-Text0pqd1u-container'); + testingUtils.fillInputByCSS('#Date0hwq20', '2019-11-19'); fixture.detectChanges(); await fixture.whenStable(); - displayTextElementContainer = fixture.nativeElement.querySelector('#field-Text0pqd1u-container'); - expectElementToBeVisible(displayTextElementContainer); + expectElementToBeVisible(testingUtils, '#field-Text0pqd1u-container'); }); it('Should not be able to see a widget when the visibility condition refers to another fields with specific date', async () => { @@ -124,19 +122,14 @@ describe('Form Renderer Component', () => { fixture.detectChanges(); await fixture.whenStable(); - const inputDateTestOne = fixture.nativeElement.querySelector('#Date0hwq20') as HTMLInputElement; + expectElementToBeVisible(testingUtils, '#field-Text0uyqd3-container'); - let displayTextElementContainer: HTMLDivElement = fixture.nativeElement.querySelector('#field-Text0uyqd3-container'); - expectElementToBeVisible(displayTextElementContainer); - - inputDateTestOne.value = '2019-11-19'; - inputDateTestOne.dispatchEvent(new Event('input')); + testingUtils.fillInputByCSS('#Date0hwq20', '2019-11-19'); fixture.detectChanges(); await fixture.whenStable(); - displayTextElementContainer = fixture.nativeElement.querySelector('#field-Text0uyqd3-container'); - expectElementToBeHidden(displayTextElementContainer); + expectElementToBeHidden(testingUtils, '#field-Text0uyqd3-container'); }); it('[C310336] - Should be able to set visibility conditions for Date widget', async () => { @@ -144,17 +137,14 @@ describe('Form Renderer Component', () => { fixture.detectChanges(); await fixture.whenStable(); - const textInputElement = fixture.nativeElement.querySelector('#Text5asd0a'); - const textInputContainer = fixture.nativeElement.querySelector('#field-Text5asd0a-container'); - let dateContainer = fixture.nativeElement.querySelector('#field-Date8wbe3d-container'); - expectElementToBeVisible(textInputContainer); - expectElementToBeHidden(dateContainer); + expectElementToBeVisible(testingUtils, '#field-Text5asd0a-container'); + expectElementToBeHidden(testingUtils, '#field-Date8wbe3d-container'); - typeIntoInput(textInputElement, 'Date'); + typeIntoInput(testingUtils, '#Text5asd0a', 'Date'); fixture.detectChanges(); await fixture.whenStable(); - dateContainer = fixture.nativeElement.querySelector('#field-Date8wbe3d-container'); - expectElementToBeVisible(dateContainer); + + expectElementToBeVisible(testingUtils, '#field-Date8wbe3d-container'); }); }); @@ -164,117 +154,95 @@ describe('Form Renderer Component', () => { fixture.detectChanges(); await fixture.whenStable(); - let displayValueElementContainer: HTMLDivElement = fixture.nativeElement.querySelector('#field-Displayvalue0g6092-container'); - const formInputText: HTMLInputElement = fixture.nativeElement.querySelector('#Text0bq3ar'); - expectElementToBeHidden(displayValueElementContainer); - typeIntoInput(formInputText, 'DisplayValue'); + expectElementToBeHidden(testingUtils, '#field-Displayvalue0g6092-container'); + typeIntoInput(testingUtils, '#Text0bq3ar', 'DisplayValue'); fixture.detectChanges(); await fixture.whenStable(); - displayValueElementContainer = fixture.nativeElement.querySelector('#field-Displayvalue0g6092-container'); - expectElementToBeVisible(displayValueElementContainer); - const displayValueElement: HTMLInputElement = fixture.nativeElement.querySelector('#Displayvalue0g6092'); - expectInputElementValueIs(displayValueElement, 'No field selected'); + expectElementToBeVisible(testingUtils, '#field-Displayvalue0g6092-container'); + expectInputElementValueIs(testingUtils, '#Displayvalue0g6092', 'No field selected'); }); it('[C309863] - Should be able to see Display value widget when visibility condition refers to a form variable and a field', async () => { formRendererComponent.formDefinition = formService.parseForm(formDisplayValueForm.formRepresentation.formDefinition); fixture.detectChanges(); await fixture.whenStable(); - let displayValueElementContainer: HTMLDivElement = fixture.nativeElement.querySelector('#field-DisplayValueOne-container'); - expectElementToBeHidden(displayValueElementContainer); + expectElementToBeHidden(testingUtils, '#field-DisplayValueOne-container'); - const formInputText: HTMLInputElement = fixture.nativeElement.querySelector('#Text0howrc'); - typeIntoInput(formInputText, 'aaa'); + typeIntoInput(testingUtils, '#Text0howrc', 'aaa'); fixture.detectChanges(); await fixture.whenStable(); - displayValueElementContainer = fixture.nativeElement.querySelector('#field-DisplayValueOne-container'); - expectElementToBeVisible(displayValueElementContainer); - const displayValueElement: HTMLInputElement = fixture.nativeElement.querySelector('#DisplayValueOne'); - expectInputElementValueIs(displayValueElement, 'No field selected'); + expectElementToBeVisible(testingUtils, '#field-DisplayValueOne-container'); + expectInputElementValueIs(testingUtils, '#DisplayValueOne', 'No field selected'); - typeIntoInput(formInputText, 'aaab'); + typeIntoInput(testingUtils, '#Text0howrc', 'aaab'); fixture.detectChanges(); await fixture.whenStable(); - displayValueElementContainer = fixture.nativeElement.querySelector('#field-DisplayValueOne-container'); - expectElementToBeHidden(displayValueElementContainer); + expectElementToBeHidden(testingUtils, '#field-DisplayValueOne-container'); }); it('[C309864] - Should be able to see Display value widget when visibility condition refers to another field and form variable', async () => { formRendererComponent.formDefinition = formService.parseForm(formDisplayValueForm.formRepresentation.formDefinition); fixture.detectChanges(); await fixture.whenStable(); - let displayValueElementContainer: HTMLDivElement = fixture.nativeElement.querySelector('#field-DisplayValueVariableField-container'); - expectElementToBeHidden(displayValueElementContainer); + expectElementToBeHidden(testingUtils, '#field-DisplayValueVariableField-container'); - const formInputText: HTMLInputElement = fixture.nativeElement.querySelector('#TextOne'); - typeIntoInput(formInputText, 'aaa'); + typeIntoInput(testingUtils, '#TextOne', 'aaa'); fixture.detectChanges(); await fixture.whenStable(); - displayValueElementContainer = fixture.nativeElement.querySelector('#field-DisplayValueVariableField-container'); - expectElementToBeVisible(displayValueElementContainer); - const displayValueElement: HTMLInputElement = fixture.nativeElement.querySelector('#DisplayValueVariableField'); - expectInputElementValueIs(displayValueElement, 'No field selected'); + expectElementToBeVisible(testingUtils, '#field-DisplayValueVariableField-container'); + expectInputElementValueIs(testingUtils, '#DisplayValueVariableField', 'No field selected'); - typeIntoInput(formInputText, 'aaab'); + typeIntoInput(testingUtils, '#TextOne', 'aaab'); fixture.detectChanges(); await fixture.whenStable(); - displayValueElementContainer = fixture.nativeElement.querySelector('#field-DisplayValueVariableField-container'); - expectElementToBeHidden(displayValueElementContainer); + expectElementToBeHidden(testingUtils, '#field-DisplayValueVariableField-container'); }); it('[C309865] - Should be able to see Display value widget when has multiple visibility conditions and next condition operators', async () => { formRendererComponent.formDefinition = formService.parseForm(formDisplayValueCombinedVisibility.formRepresentation.formDefinition); fixture.detectChanges(); await fixture.whenStable(); - const textInputElement: HTMLInputElement = fixture.nativeElement.querySelector('#Text0bq3ar'); - const textTwoInputElement: HTMLInputElement = fixture.nativeElement.querySelector('#TextTwo'); - let displayValueHiddenContainer: HTMLDivElement = fixture.nativeElement.querySelector('#field-Displayvalue0g6092-container'); - expectElementToBeVisible(textInputElement); - expectElementToBeVisible(textTwoInputElement); - expectElementToBeHidden(displayValueHiddenContainer); + expectElementToBeVisible(testingUtils, '#Text0bq3ar'); + expectElementToBeVisible(testingUtils, '#TextTwo'); + expectElementToBeHidden(testingUtils, '#field-Displayvalue0g6092-container'); - typeIntoInput(textInputElement, 'aaa'); + typeIntoInput(testingUtils, '#Text0bq3ar', 'aaa'); fixture.detectChanges(); await fixture.whenStable(); - displayValueHiddenContainer = fixture.nativeElement.querySelector('#field-Displayvalue0g6092-container'); - expectInputElementValueIs(textInputElement, 'aaa'); - expectInputElementValueIs(textTwoInputElement, ''); - expectElementToBeVisible(displayValueHiddenContainer); + typeIntoInput(testingUtils, '#Text0bq3ar', 'aaa'); + expectInputElementValueIs(testingUtils, '#TextTwo', ''); + expectElementToBeVisible(testingUtils, '#field-Displayvalue0g6092-container'); - typeIntoInput(textInputElement, 'bbb'); + typeIntoInput(testingUtils, '#Text0bq3ar', 'bbb'); fixture.detectChanges(); await fixture.whenStable(); - displayValueHiddenContainer = fixture.nativeElement.querySelector('#field-Displayvalue0g6092-container'); - expectInputElementValueIs(textInputElement, 'bbb'); - expectInputElementValueIs(textTwoInputElement, ''); - expectElementToBeHidden(displayValueHiddenContainer); + typeIntoInput(testingUtils, '#Text0bq3ar', 'bbb'); + expectInputElementValueIs(testingUtils, '#TextTwo', ''); + expectElementToBeHidden(testingUtils, '#field-Displayvalue0g6092-container'); - typeIntoInput(textTwoInputElement, 'aaa'); + typeIntoInput(testingUtils, '#TextTwo', 'aaa'); fixture.detectChanges(); await fixture.whenStable(); - displayValueHiddenContainer = fixture.nativeElement.querySelector('#field-Displayvalue0g6092-container'); - expectInputElementValueIs(textInputElement, 'bbb'); - expectInputElementValueIs(textTwoInputElement, 'aaa'); - expectElementToBeHidden(displayValueHiddenContainer); + typeIntoInput(testingUtils, '#Text0bq3ar', 'bbb'); + expectInputElementValueIs(testingUtils, '#TextTwo', 'aaa'); + expectElementToBeHidden(testingUtils, '#field-Displayvalue0g6092-container'); - typeIntoInput(textInputElement, 'aaa'); + typeIntoInput(testingUtils, '#Text0bq3ar', 'aaa'); fixture.detectChanges(); await fixture.whenStable(); - displayValueHiddenContainer = fixture.nativeElement.querySelector('#field-Displayvalue0g6092-container'); - expectInputElementValueIs(textInputElement, 'aaa'); - expectInputElementValueIs(textTwoInputElement, 'aaa'); - expectElementToBeHidden(displayValueHiddenContainer); + typeIntoInput(testingUtils, '#Text0bq3ar', 'aaa'); + expectInputElementValueIs(testingUtils, '#TextTwo', 'aaa'); + expectElementToBeHidden(testingUtils, '#field-Displayvalue0g6092-container'); - typeIntoInput(textTwoInputElement, 'bbb'); + typeIntoInput(testingUtils, '#TextTwo', 'bbb'); fixture.detectChanges(); await fixture.whenStable(); - displayValueHiddenContainer = fixture.nativeElement.querySelector('#field-Displayvalue0g6092-container'); - expectInputElementValueIs(textInputElement, 'aaa'); - expectInputElementValueIs(textTwoInputElement, 'bbb'); - expectElementToBeVisible(displayValueHiddenContainer); + typeIntoInput(testingUtils, '#Text0bq3ar', 'aaa'); + expectInputElementValueIs(testingUtils, '#TextTwo', 'bbb'); + expectElementToBeVisible(testingUtils, '#field-Displayvalue0g6092-container'); }); }); @@ -284,30 +252,24 @@ describe('Form Renderer Component', () => { fixture.detectChanges(); await fixture.whenStable(); - let inputNumberOne = fixture.nativeElement.querySelector('#Number1'); - let inputNumber2Container = fixture.nativeElement.querySelector('#field-Number2-container'); - expectElementToBeVisible(inputNumberOne); - expectElementToBeHidden(inputNumber2Container); + expectElementToBeVisible(testingUtils, '#Number1'); + expectElementToBeHidden(testingUtils, '#field-Number2-container'); expect(formRendererComponent.formDefinition.isValid).toBe(true, 'Form should be valid by default'); - typeIntoInput(inputNumberOne, '5'); + typeIntoInput(testingUtils, '#Number1', '5'); fixture.detectChanges(); await fixture.whenStable(); - inputNumberOne = fixture.nativeElement.querySelector('#Number1'); - inputNumber2Container = fixture.nativeElement.querySelector('#field-Number2-container'); - expectElementToBeVisible(inputNumberOne); - expectElementToBeVisible(inputNumber2Container); + expectElementToBeVisible(testingUtils, '#Number1'); + expectElementToBeVisible(testingUtils, '#field-Number2-container'); expect(formRendererComponent.formDefinition.isValid).toBe(true, 'Form should be valid with a valid value'); - typeIntoInput(inputNumberOne, 'az'); + typeIntoInput(testingUtils, '#Number1', 'az'); fixture.detectChanges(); await fixture.whenStable(); - inputNumberOne = fixture.nativeElement.querySelector('#Number1'); - inputNumber2Container = fixture.nativeElement.querySelector('#field-Number2-container'); - expectElementToBeVisible(inputNumberOne); - expectElementToBeHidden(inputNumber2Container); + expectElementToBeVisible(testingUtils, '#Number1'); + expectElementToBeHidden(testingUtils, '#field-Number2-container'); expect(formRendererComponent.formDefinition.isValid).toBe(false, 'Form should be invalid with an invalid value'); }); @@ -316,22 +278,18 @@ describe('Form Renderer Component', () => { fixture.detectChanges(); await fixture.whenStable(); - const textInput: HTMLInputElement = fixture.nativeElement.querySelector('#Text'); - let numberFieldContainer: HTMLDivElement = fixture.nativeElement.querySelector('#field-NumberFieldValue-container'); - expectElementToBeVisible(textInput); - expectElementToBeHidden(numberFieldContainer); + expectElementToBeVisible(testingUtils, '#Text'); + expectElementToBeHidden(testingUtils, '#field-NumberFieldValue-container'); - typeIntoInput(textInput, 'aaa'); + typeIntoInput(testingUtils, '#Text', 'aaa'); fixture.detectChanges(); await fixture.whenStable(); - numberFieldContainer = fixture.nativeElement.querySelector('#field-NumberFieldValue-container'); - expectElementToBeVisible(numberFieldContainer); + expectElementToBeVisible(testingUtils, '#field-NumberFieldValue-container'); - typeIntoInput(textInput, 'bbb'); + typeIntoInput(testingUtils, '#Text', 'bbb'); fixture.detectChanges(); await fixture.whenStable(); - numberFieldContainer = fixture.nativeElement.querySelector('#field-NumberFieldValue-container'); - expectElementToBeHidden(numberFieldContainer); + expectElementToBeHidden(testingUtils, '#field-NumberFieldValue-container'); }); it('[C315170] - Should be able to complete a task with a form with required number widgets', async () => { @@ -339,23 +297,19 @@ describe('Form Renderer Component', () => { fixture.detectChanges(); await fixture.whenStable(); - const inputElementNumber: HTMLInputElement = fixture.nativeElement.querySelector('#Number1'); - let numberContainerElement: HTMLDivElement = fixture.nativeElement.querySelector('#field-Number2-container'); - expectElementToBeHidden(numberContainerElement); - expectElementToBeVisible(inputElementNumber); + expectElementToBeHidden(testingUtils, '#field-Number2-container'); + expectElementToBeVisible(testingUtils, '#Number1'); - typeIntoInput(inputElementNumber, '5'); + typeIntoInput(testingUtils, '#Number1', '5'); fixture.detectChanges(); await fixture.whenStable(); - numberContainerElement = fixture.nativeElement.querySelector('#field-Number2-container'); - expectElementToBeVisible(numberContainerElement); + expectElementToBeVisible(testingUtils, '#field-Number2-container'); - typeIntoInput(inputElementNumber, '123'); + typeIntoInput(testingUtils, '#Number1', '123'); fixture.detectChanges(); await fixture.whenStable(); - numberContainerElement = fixture.nativeElement.querySelector('#field-Number2-container'); - expectElementToBeHidden(numberContainerElement); - const errorWidgetText: HTMLDivElement = fixture.nativeElement.querySelector('#field-Number1-container error-widget .adf-error-text'); + expectElementToBeHidden(testingUtils, '#field-Number2-container'); + const errorWidgetText = testingUtils.getByCSS('#field-Number1-container error-widget .adf-error-text').nativeElement; expect(errorWidgetText.textContent).toBe(`FORM.FIELD.VALIDATOR.NOT_GREATER_THAN`); expect(formRendererComponent.formDefinition.isValid).toBe(false, 'Form should not be valid without mandatory field'); }); @@ -364,19 +318,17 @@ describe('Form Renderer Component', () => { formRendererComponent.formDefinition = formService.parseForm(formNumberTextJson.formRepresentation.formDefinition); fixture.detectChanges(); await fixture.whenStable(); - const numberRequired: HTMLInputElement = fixture.nativeElement.querySelector('#NumberReq'); - const numberNotRequired: HTMLInputElement = fixture.nativeElement.querySelector('#NumberNotReq'); - expectElementToBeVisible(numberRequired); - expectElementToBeVisible(numberNotRequired); + expectElementToBeVisible(testingUtils, '#NumberReq'); + expectElementToBeVisible(testingUtils, '#NumberNotReq'); expect(formRendererComponent.formDefinition.isValid).toBe(false, 'Form should be invalid with an empty required value'); - typeIntoInput(numberNotRequired, '5'); + typeIntoInput(testingUtils, '#NumberNotReq', '5'); fixture.detectChanges(); await fixture.whenStable(); expect(formRendererComponent.formDefinition.isValid).toBe(false, 'Form should be invalid with an empty required value'); - typeIntoInput(numberRequired, '5'); - typeIntoInput(numberNotRequired, ''); + typeIntoInput(testingUtils, '#NumberReq', '5'); + typeIntoInput(testingUtils, '#NumberNotReq', ''); fixture.detectChanges(); await fixture.whenStable(); expect(formRendererComponent.formDefinition.isValid).toBe(true, 'Form should be valid when required field are filled'); @@ -386,18 +338,17 @@ describe('Form Renderer Component', () => { formRendererComponent.formDefinition = formService.parseForm(colspanForm.formRepresentation.formDefinition, null, false, true); fixture.detectChanges(); await fixture.whenStable(); - const formSizedElement = fixture.nativeElement.querySelector('#field-2bc275fb-e113-4d7d-885f-6e74a7332d40-container div.adf-grid-list'); - expectElementToBeVisible(formSizedElement); - const sectionGridElement: HTMLElement[] = fixture.nativeElement.querySelectorAll( - '#field-2bc275fb-e113-4d7d-885f-6e74a7332d40-container div .adf-grid-list-item' - ); + expectElementToBeVisible(testingUtils, '#field-2bc275fb-e113-4d7d-885f-6e74a7332d40-container div.adf-grid-list'); + const sectionGridElement: HTMLElement[] = testingUtils + .getAllByCSS('#field-2bc275fb-e113-4d7d-885f-6e74a7332d40-container div .adf-grid-list-item') + .map((element) => element.nativeElement); sectionGridElement.forEach((element) => { expect(element.style['grid-area']).toBe('auto / auto / span 1 / span 1', 'Elemens is wrong sized for this section'); }); - const fullWidthElement = fixture.nativeElement.querySelector( + const fullWidthElement = testingUtils.getByCSS( '#field-d52ada4e-cbdc-4f0c-a480-5b85fa00e4f8-container div.adf-grid-list .adf-grid-list-item' - ); + ).nativeElement; expect(fullWidthElement.style['grid-area']).toBe('auto / auto / span 1 / span 2'); }); @@ -405,19 +356,16 @@ describe('Form Renderer Component', () => { formRendererComponent.formDefinition = formService.parseForm(colspanForm.formRepresentation.formDefinition, null, false, false); fixture.detectChanges(); await fixture.whenStable(); - const formSizedElement = fixture.nativeElement.querySelector( - '#field-2bc275fb-e113-4d7d-885f-6e74a7332d40-container section.adf-grid-list-column-view' - ); - expectElementToBeVisible(formSizedElement); - const sectionGridElement: HTMLElement[] = fixture.nativeElement.querySelectorAll( - '#field-2bc275fb-e113-4d7d-885f-6e74a7332d40-container section .adf-grid-list-single-column' - ); + expectElementToBeVisible(testingUtils, '#field-2bc275fb-e113-4d7d-885f-6e74a7332d40-container section.adf-grid-list-column-view'); + const sectionGridElement = testingUtils + .getAllByCSS('#field-2bc275fb-e113-4d-7d-885f-6e74a7332d40-container section .adf-grid-list-single-column') + .map((element) => element.nativeElement); sectionGridElement.forEach((element) => { expect(element.style['width']).toBe('50%', 'Elemens is wrong sized for this section'); }); - const fullWidthElement = fixture.nativeElement.querySelector( + const fullWidthElement = testingUtils.getByCSS( '#field-d52ada4e-cbdc-4f0c-a480-5b85fa00e4f8-container section.adf-grid-list-column-view .adf-grid-list-single-column' - ); + ).nativeElement; expect(fullWidthElement.style['width']).toBe('100%'); }); @@ -428,17 +376,16 @@ describe('Form Renderer Component', () => { const twoSpanTextWidgetContainerId = '#field-1ff21afc-7df4-4607-8363-1dc8576e1c8e-container'; const oneSpanTextWidgetContainerId = '#field-f4285ad-g123-1a73-521d-7nm4a7231aul0-container'; - const formSizedElement = fixture.nativeElement.querySelector(`${oneSpanTextWidgetContainerId} section.adf-grid-list-column-view`); - expectElementToBeVisible(formSizedElement); - const sectionGridElement: HTMLElement[] = fixture.nativeElement.querySelectorAll( - `${oneSpanTextWidgetContainerId} section .adf-grid-list-single-column` - ); + expectElementToBeVisible(testingUtils, `${oneSpanTextWidgetContainerId} section.adf-grid-list-column-view`); + const sectionGridElement = testingUtils + .getAllByCSS(`${oneSpanTextWidgetContainerId} section .adf-grid-list-single-column`) + .map((element) => element.nativeElement); sectionGridElement.forEach((element) => { expect(element.style['width']).toBe('50%'); }); - const fullWidthElement = fixture.nativeElement.querySelector( + const fullWidthElement = testingUtils.getByCSS( `${twoSpanTextWidgetContainerId} section.adf-grid-list-column-view .adf-grid-list-single-column` - ); + ).nativeElement; expect(fullWidthElement.style['width']).toBe('100%'); }); @@ -447,79 +394,77 @@ describe('Form Renderer Component', () => { fixture.detectChanges(); await fixture.whenStable(); - const numberInputRequired: HTMLInputElement = fixture.nativeElement.querySelector('#Number0x8cbv'); - expectElementToBeVisible(numberInputRequired); - expectElementToBeValid('Number0x8cbv', fixture); + expectElementToBeVisible(testingUtils, '#Number0x8cbv'); + expectElementToBeValid(testingUtils, 'Number0x8cbv'); - numberInputRequired.dispatchEvent(new Event('blur')); + testingUtils.blurByCSS('#Number0x8cbv'); fixture.detectChanges(); await fixture.whenStable(); - expectElementToBeInvalid('Number0x8cbv', fixture); + expectElementToBeInvalid(testingUtils, 'Number0x8cbv'); - typeIntoInput(numberInputRequired, '5'); + typeIntoInput(testingUtils, '#Number0x8cbv', '5'); fixture.detectChanges(); await fixture.whenStable(); - expectElementToBeValid('Number0x8cbv', fixture); + expectElementToBeValid(testingUtils, 'Number0x8cbv'); - typeIntoInput(numberInputRequired, 'a'); + typeIntoInput(testingUtils, '#Number0x8cbv', 'a'); fixture.detectChanges(); await fixture.whenStable(); - expectElementToBeInvalid('Number0x8cbv', fixture); - let errorWidgetText: HTMLDivElement = fixture.nativeElement.querySelector('#field-Number0x8cbv-container error-widget .adf-error-text'); + expectElementToBeInvalid(testingUtils, 'Number0x8cbv'); + let errorWidgetText = testingUtils.getByCSS('#field-Number0x8cbv-container error-widget .adf-error-text').nativeElement; expect(errorWidgetText.textContent).toBe(`FORM.FIELD.VALIDATOR.INVALID_NUMBER`); expect(formRendererComponent.formDefinition.isValid).toBe(false, 'Form should not be valid without mandatory field'); - typeIntoInput(numberInputRequired, '?'); + typeIntoInput(testingUtils, '#Number0x8cbv', '?'); fixture.detectChanges(); await fixture.whenStable(); - expectElementToBeInvalid('Number0x8cbv', fixture); - errorWidgetText = fixture.nativeElement.querySelector('#field-Number0x8cbv-container error-widget .adf-error-text'); + expectElementToBeInvalid(testingUtils, 'Number0x8cbv'); + errorWidgetText = testingUtils.getByCSS('#field-Number0x8cbv-container error-widget .adf-error-text').nativeElement; expect(errorWidgetText.textContent).toBe(`FORM.FIELD.VALIDATOR.INVALID_NUMBER`); expect(formRendererComponent.formDefinition.isValid).toBe(false, 'Form should not be valid without mandatory field'); - typeIntoInput(numberInputRequired, '-5'); + typeIntoInput(testingUtils, '#Number0x8cbv', '-5'); fixture.detectChanges(); await fixture.whenStable(); - expectElementToBeValid('Number0x8cbv', fixture); + expectElementToBeValid(testingUtils, 'Number0x8cbv'); }); it('[C309660] - Should display validation error message when Number widget value is not respecting min max interval', async () => { formRendererComponent.formDefinition = formService.parseForm(numberMinMaxForm.formRepresentation.formDefinition); fixture.detectChanges(); await fixture.whenStable(); - const numberInputElement: HTMLInputElement = fixture.nativeElement.querySelector('#Number0him2z'); - expectElementToBeVisible(numberInputElement); - expectElementToBeValid('Number0him2z', fixture); + expectElementToBeVisible(testingUtils, '#Number0him2z'); + expectElementToBeValid(testingUtils, 'Number0him2z'); - numberInputElement.dispatchEvent(new Event('blur')); - typeIntoInput(numberInputElement, '9'); + testingUtils.blurByCSS('#Number0him2z'); + typeIntoInput(testingUtils, '#Number0him2z', '9'); fixture.detectChanges(); await fixture.whenStable(); - expectElementToBeInvalid('Number0him2z', fixture); - let errorWidgetText = fixture.nativeElement.querySelector('#field-Number0him2z-container error-widget .adf-error-text'); + expectElementToBeInvalid(testingUtils, 'Number0him2z'); + let errorWidgetText = testingUtils.getByCSS('#field-Number0him2z-container error-widget .adf-error-text').nativeElement; expect(errorWidgetText.textContent).toBe(`FORM.FIELD.VALIDATOR.NOT_LESS_THAN`); expect(formRendererComponent.formDefinition.isValid).toBe(false, 'Form should not be valid without valid field'); - typeIntoInput(numberInputElement, '10'); + typeIntoInput(testingUtils, '#Number0him2z', '10'); fixture.detectChanges(); await fixture.whenStable(); - expectElementToBeValid('Number0him2z', fixture); + expectElementToBeValid(testingUtils, 'Number0him2z'); - typeIntoInput(numberInputElement, '60'); + typeIntoInput(testingUtils, '#Number0him2z', '60'); fixture.detectChanges(); await fixture.whenStable(); - expectElementToBeValid('Number0him2z', fixture); + expectElementToBeValid(testingUtils, 'Number0him2z'); - typeIntoInput(numberInputElement, '61'); + typeIntoInput(testingUtils, '#Number0him2z', '61'); fixture.detectChanges(); await fixture.whenStable(); - expectElementToBeInvalid('Number0him2z', fixture); - errorWidgetText = fixture.nativeElement.querySelector('#field-Number0him2z-container error-widget .adf-error-text'); + expectElementToBeInvalid(testingUtils, 'Number0him2z'); + errorWidgetText = testingUtils.getByCSS('#field-Number0him2z-container error-widget .adf-error-text').nativeElement; expect(errorWidgetText.textContent).toBe(`FORM.FIELD.VALIDATOR.NOT_GREATER_THAN`); expect(formRendererComponent.formDefinition.isValid).toBe(false, 'Form should not be valid without valid field'); }); @@ -528,86 +473,68 @@ describe('Form Renderer Component', () => { formRendererComponent.formDefinition = formService.parseForm(formNumberTextJson.formRepresentation.formDefinition); fixture.detectChanges(); await fixture.whenStable(); - const inputText: HTMLInputElement = fixture.nativeElement.querySelector('#Text'); + const inputText = testingUtils.getByCSS('#Text').nativeElement; expect(inputText).not.toBeNull(); - let numberFieldValueContainer: HTMLDivElement = fixture.nativeElement.querySelector('#field-NumberFieldValue-container'); - expectElementToBeHidden(numberFieldValueContainer); + expectElementToBeHidden(testingUtils, '#field-NumberFieldValue-container'); - typeIntoInput(inputText, 'aaa'); + typeIntoInput(testingUtils, '#Text', 'aaa'); fixture.detectChanges(); await fixture.whenStable(); - numberFieldValueContainer = fixture.nativeElement.querySelector('#field-NumberFieldValue-container'); - expectElementToBeVisible(numberFieldValueContainer); + expectElementToBeVisible(testingUtils, '#field-NumberFieldValue-container'); - typeIntoInput(inputText, 'bbb'); + typeIntoInput(testingUtils, '#Text', 'bbb'); fixture.detectChanges(); await fixture.whenStable(); - numberFieldValueContainer = fixture.nativeElement.querySelector('#field-NumberFieldValue-container'); - expectElementToBeHidden(numberFieldValueContainer); + expectElementToBeHidden(testingUtils, '#field-NumberFieldValue-container'); }); it('[C309665] - Should be able to see Number widget when visibility condition refers to another field and form variable', async () => { formRendererComponent.formDefinition = formService.parseForm(formNumberTextJson.formRepresentation.formDefinition); fixture.detectChanges(); await fixture.whenStable(); - const inputText: HTMLInputElement = fixture.nativeElement.querySelector('#Text'); + const inputText = testingUtils.getByCSS('#Text').nativeElement; expect(inputText).not.toBeNull(); - let numberFieldVariableContainer: HTMLDivElement = fixture.nativeElement.querySelector('#field-NumberFieldVariable-container'); - expectElementToBeHidden(numberFieldVariableContainer); + expectElementToBeHidden(testingUtils, '#field-NumberFieldVariable-container'); - typeIntoInput(inputText, 'aaa'); + typeIntoInput(testingUtils, '#Text', 'aaa'); fixture.detectChanges(); await fixture.whenStable(); - numberFieldVariableContainer = fixture.nativeElement.querySelector('#field-NumberFieldVariable-container'); - expectElementToBeVisible(numberFieldVariableContainer); + expectElementToBeVisible(testingUtils, '#field-NumberFieldVariable-container'); - typeIntoInput(inputText, 'bbb'); + typeIntoInput(testingUtils, '#Text', 'bbb'); fixture.detectChanges(); await fixture.whenStable(); - numberFieldVariableContainer = fixture.nativeElement.querySelector('#field-NumberFieldVariable-container'); - expectElementToBeHidden(numberFieldVariableContainer); + expectElementToBeHidden(testingUtils, '#field-NumberFieldVariable-container'); }); it('[C309666] - Should be able to see Number widget when has multiple visibility conditions and next condition operators', async () => { formRendererComponent.formDefinition = formService.parseForm(numberWidgetVisibilityForm.formRepresentation.formDefinition); fixture.detectChanges(); await fixture.whenStable(); - let numberFieldContainer = fixture.nativeElement.querySelector('#field-Number0wxaur-container'); - let testOneInput: HTMLInputElement = fixture.nativeElement.querySelector('#Text0hs0gt'); - let testTwoInput: HTMLInputElement = fixture.nativeElement.querySelector('#Text0cuqet'); - expect(testOneInput).not.toBeNull(); - expect(testTwoInput).not.toBeNull(); - expectElementToBeHidden(numberFieldContainer); + expectElementToBeHidden(testingUtils, '#field-Number0wxaur-container'); - typeIntoInput(testOneInput, 'aaa'); + typeIntoInput(testingUtils, '#Text0hs0gt', 'aaa'); fixture.detectChanges(); await fixture.whenStable(); - numberFieldContainer = fixture.nativeElement.querySelector('#field-Number0wxaur-container'); - expectElementToBeVisible(numberFieldContainer); + expectElementToBeVisible(testingUtils, '#field-Number0wxaur-container'); - typeIntoInput(testOneInput, 'bbb'); + typeIntoInput(testingUtils, '#Text0hs0gt', 'bbb'); fixture.detectChanges(); await fixture.whenStable(); - numberFieldContainer = fixture.nativeElement.querySelector('#field-Number0wxaur-container'); - expectElementToBeHidden(numberFieldContainer); + expectElementToBeHidden(testingUtils, '#field-Number0wxaur-container'); - typeIntoInput(testTwoInput, 'aaa'); + typeIntoInput(testingUtils, '#Text0cuqet', 'aaa'); fixture.detectChanges(); await fixture.whenStable(); - numberFieldContainer = fixture.nativeElement.querySelector('#field-Number0wxaur-container'); - testOneInput = fixture.nativeElement.querySelector('#Text0hs0gt'); - expectElementToBeHidden(numberFieldContainer); - expectInputElementValueIs(testOneInput, 'bbb'); + expectElementToBeHidden(testingUtils, '#field-Number0wxaur-container'); + expectInputElementValueIs(testingUtils, '#Text0hs0gt', 'bbb'); - typeIntoInput(testOneInput, 'aaa'); + typeIntoInput(testingUtils, '#Text0hs0gt', 'aaa'); fixture.detectChanges(); await fixture.whenStable(); - numberFieldContainer = fixture.nativeElement.querySelector('#field-Number0wxaur-container'); - testOneInput = fixture.nativeElement.querySelector('#Text0hs0gt'); - testTwoInput = fixture.nativeElement.querySelector('#Text0cuqet'); - expectInputElementValueIs(testOneInput, 'aaa'); - expectInputElementValueIs(testTwoInput, 'aaa'); - expectElementToBeHidden(numberFieldContainer); + expectInputElementValueIs(testingUtils, '#Text0hs0gt', 'aaa'); + expectInputElementValueIs(testingUtils, '#Text0cuqet', 'aaa'); + expectElementToBeHidden(testingUtils, '#field-Number0wxaur-container'); }); }); @@ -616,39 +543,26 @@ describe('Form Renderer Component', () => { formRendererComponent.formDefinition = formService.parseForm(textWidgetVisibility.formRepresentation.formDefinition); fixture.detectChanges(); await fixture.whenStable(); - const inputElementTestOne: HTMLInputElement = fixture.nativeElement.querySelector('#textOne'); - const inputElementTestTwo: HTMLInputElement = fixture.nativeElement.querySelector('#textTwo'); - expectElementToBeVisible(inputElementTestOne); - let elementThreeContainer = fixture.nativeElement.querySelector('#field-textThree-container'); - const elementTwoContainer = fixture.nativeElement.querySelector('#field-textTwo-container'); - let elementFourContainer = fixture.nativeElement.querySelector('#field-textFour-container'); - expectElementToBeHidden(elementThreeContainer); - expectElementToBeHidden(elementTwoContainer); - expectElementToBeVisible(elementFourContainer); + expectElementToBeVisible(testingUtils, '#textOne'); + expectElementToBeHidden(testingUtils, '#field-textThree-container'); + expectElementToBeHidden(testingUtils, '#field-textTwo-container'); + expectElementToBeVisible(testingUtils, '#field-textFour-container'); - typeIntoInput(inputElementTestOne, 'Test'); + typeIntoInput(testingUtils, '#textOne', 'Test'); fixture.detectChanges(); await fixture.whenStable(); - let containerInputOne = fixture.nativeElement.querySelector('#field-textOne-container'); - let containerInputTwo = fixture.nativeElement.querySelector('#field-textTwo-container'); - elementThreeContainer = fixture.nativeElement.querySelector('#field-textThree-container'); - elementFourContainer = fixture.nativeElement.querySelector('#field-textFour-container'); - expectElementToBeVisible(containerInputOne); - expectElementToBeVisible(containerInputTwo); - expectElementToBeVisible(elementThreeContainer); - expectElementToBeHidden(elementFourContainer); + expectElementToBeVisible(testingUtils, '#field-textOne-container'); + expectElementToBeVisible(testingUtils, '#field-textTwo-container'); + expectElementToBeVisible(testingUtils, '#field-textThree-container'); + expectElementToBeHidden(testingUtils, '#field-textFour-container'); - typeIntoInput(inputElementTestTwo, 'Test'); + typeIntoInput(testingUtils, '#textTwo', 'Test'); fixture.detectChanges(); await fixture.whenStable(); - containerInputOne = fixture.nativeElement.querySelector('#field-textOne-container'); - containerInputTwo = fixture.nativeElement.querySelector('#field-textTwo-container'); - elementThreeContainer = fixture.nativeElement.querySelector('#field-textThree-container'); - elementFourContainer = fixture.nativeElement.querySelector('#field-textFour-container'); - expectElementToBeVisible(containerInputOne); - expectElementToBeVisible(containerInputTwo); - expectElementToBeVisible(elementFourContainer); - expectElementToBeHidden(elementThreeContainer); + expectElementToBeVisible(testingUtils, '#field-textOne-container'); + expectElementToBeVisible(testingUtils, '#field-textTwo-container'); + expectElementToBeVisible(testingUtils, '#field-textFour-container'); + expectElementToBeHidden(testingUtils, '#field-textThree-container'); }); }); @@ -657,17 +571,13 @@ describe('Form Renderer Component', () => { formRendererComponent.formDefinition = formService.parseForm(radioWidgetVisibilityForm.formRepresentation.formDefinition); fixture.detectChanges(); await fixture.whenStable(); - const textInputElement = fixture.nativeElement.querySelector('#Text0cee7g'); - const textInputContainer = fixture.nativeElement.querySelector('#field-Text0cee7g-container'); - let radioButtonContainer = fixture.nativeElement.querySelector('#field-Radiobuttons03rkbo-container'); - expectElementToBeVisible(textInputContainer); - expectElementToBeHidden(radioButtonContainer); + expectElementToBeVisible(testingUtils, '#field-Text0cee7g-container'); + expectElementToBeHidden(testingUtils, '#field-Radiobuttons03rkbo-container'); - typeIntoInput(textInputElement, 'Radio'); + typeIntoInput(testingUtils, '#Text0cee7g', 'Radio'); fixture.detectChanges(); await fixture.whenStable(); - radioButtonContainer = fixture.nativeElement.querySelector('#field-Radiobuttons03rkbo-container'); - expectElementToBeVisible(radioButtonContainer); + expectElementToBeVisible(testingUtils, '#field-Radiobuttons03rkbo-container'); }); }); @@ -677,10 +587,8 @@ describe('Form Renderer Component', () => { formRendererComponent.formDefinition = formService.parseForm(customWidgetForm.formRepresentation.formDefinition); fixture.detectChanges(); await fixture.whenStable(); - const textInputElement = fixture.nativeElement.querySelector('#Text0vdi18'); - const customWidgetElement = fixture.nativeElement.querySelector('#bananaforevah0k8gui'); - expectElementToBeVisible(textInputElement); - expectElementToBeVisible(customWidgetElement); + expectElementToBeVisible(testingUtils, '#Text0vdi18'); + expectElementToBeVisible(testingUtils, '#bananaforevah0k8gui'); }); it('Should be able to correctly use visibility in a custom process cloud widget ', async () => { @@ -688,14 +596,11 @@ describe('Form Renderer Component', () => { formRendererComponent.formDefinition = formService.parseForm(customWidgetFormWithVisibility.formRepresentation.formDefinition); fixture.detectChanges(); await fixture.whenStable(); - const textInputElement = fixture.nativeElement.querySelector('#Text0vdi18'); - let customWidgetElementContainer = fixture.nativeElement.querySelector('#field-bananaforevah0k8gui-container'); - expectElementToBeHidden(customWidgetElementContainer); - typeIntoInput(textInputElement, 'no'); + expectElementToBeHidden(testingUtils, '#field-bananaforevah0k8gui-container'); + typeIntoInput(testingUtils, '#Text0vdi18', 'no'); fixture.detectChanges(); await fixture.whenStable(); - customWidgetElementContainer = fixture.nativeElement.querySelector('#field-bananaforevah0k8gui-container'); - expectElementToBeVisible(customWidgetElementContainer); + expectElementToBeVisible(testingUtils, '#field-bananaforevah0k8gui-container'); }); }); @@ -736,21 +641,15 @@ describe('Form Renderer Component', () => { fixture.detectChanges(); await fixture.whenStable(); - const textInputElement = fixture.nativeElement.querySelector('#Text0id3ic'); - const textInputContainer = fixture.nativeElement.querySelector('#field-Text0id3ic-container'); - const numberInputElement = fixture.nativeElement.querySelector('#Number0yggl7'); - const numberInputContainer = fixture.nativeElement.querySelector('#field-Number0yggl7-container'); - let amountContainer = fixture.nativeElement.querySelector('#field-Amount0kceqc-container'); - expectElementToBeVisible(textInputContainer); - expectElementToBeVisible(numberInputContainer); - expectElementToBeHidden(amountContainer); + expectElementToBeVisible(testingUtils, '#field-Text0id3ic-container'); + expectElementToBeVisible(testingUtils, '#field-Number0yggl7-container'); + expectElementToBeHidden(testingUtils, '#field-Amount0kceqc-container'); - typeIntoInput(textInputElement, 'text1'); - typeIntoInput(numberInputElement, '77'); + typeIntoInput(testingUtils, '#Text0id3ic', 'text1'); + typeIntoInput(testingUtils, '#Number0yggl7', '77'); fixture.detectChanges(); await fixture.whenStable(); - amountContainer = fixture.nativeElement.querySelector('#field-Amount0kceqc-container'); - expectElementToBeVisible(amountContainer); + expectElementToBeVisible(testingUtils, '#field-Amount0kceqc-container'); }); }); @@ -760,25 +659,19 @@ describe('Form Renderer Component', () => { fixture.detectChanges(); await fixture.whenStable(); - const firstCheckboxInputElement = fixture.nativeElement.querySelector('#Checkbox0pr51m-input'); - const firstCheckboxInputContainer = fixture.nativeElement.querySelector('#field-Checkbox0pr51m-container'); - const secondCheckboxInputElement = fixture.nativeElement.querySelector('#Checkbox0fp0zf-input'); - const secondCheckboxInputContainer = fixture.nativeElement.querySelector('#field-Checkbox0fp0zf-container'); - let visibilityCheckboxContainer = fixture.nativeElement.querySelector('#field-Checkbox0lb7ze-container'); - expectElementToBeVisible(firstCheckboxInputContainer); - expectElementToBeVisible(secondCheckboxInputContainer); - expectElementToBeHidden(visibilityCheckboxContainer); + expectElementToBeVisible(testingUtils, '#field-Checkbox0pr51m-container'); + expectElementToBeVisible(testingUtils, '#field-Checkbox0fp0zf-container'); + expectElementToBeHidden(testingUtils, '#field-Checkbox0lb7ze-container'); - firstCheckboxInputElement.click(); + testingUtils.clickByCSS('#Checkbox0pr51m-input'); fixture.detectChanges(); await fixture.whenStable(); - expectElementToBeHidden(visibilityCheckboxContainer); + expectElementToBeHidden(testingUtils, '#field-Checkbox0lb7ze-container'); - secondCheckboxInputElement.click(); + testingUtils.clickByCSS('#Checkbox0fp0zf-input'); fixture.detectChanges(); await fixture.whenStable(); - visibilityCheckboxContainer = fixture.nativeElement.querySelector('#field-Checkbox0lb7ze-container'); - expectElementToBeVisible(visibilityCheckboxContainer); + expectElementToBeVisible(testingUtils, '#field-Checkbox0lb7ze-container'); }); }); @@ -788,23 +681,18 @@ describe('Form Renderer Component', () => { fixture.detectChanges(); await fixture.whenStable(); - const textInputElement = fixture.nativeElement.querySelector('#Text'); - const textInputContainer = fixture.nativeElement.querySelector('#field-Text-container'); - let multilineContainer = fixture.nativeElement.querySelector('#field-MultilineTextId-container'); - expectElementToBeVisible(textInputContainer); - expectElementToBeVisible(multilineContainer); + expectElementToBeVisible(testingUtils, '#field-Text-container'); + expectElementToBeVisible(testingUtils, '#field-MultilineTextId-container'); - typeIntoInput(textInputElement, 'textwrong'); + typeIntoInput(testingUtils, '#Text', 'textwrong'); fixture.detectChanges(); await fixture.whenStable(); - multilineContainer = fixture.nativeElement.querySelector('#field-MultilineTextId-container'); - expectElementToBeHidden(multilineContainer); + expectElementToBeHidden(testingUtils, '#field-MultilineTextId-container'); - typeIntoInput(textInputElement, 'text'); + typeIntoInput(testingUtils, '#Text', 'text'); fixture.detectChanges(); await fixture.whenStable(); - multilineContainer = fixture.nativeElement.querySelector('#field-MultilineTextId-container'); - expectElementToBeVisible(multilineContainer); + expectElementToBeVisible(testingUtils, '#field-MultilineTextId-container'); }); }); @@ -814,23 +702,18 @@ describe('Form Renderer Component', () => { fixture.detectChanges(); await fixture.whenStable(); - const textInputElement = fixture.nativeElement.querySelector('#Text0tzu53'); - const textInputContainer = fixture.nativeElement.querySelector('#field-Text0tzu53-container'); - let displayTextContainer = fixture.nativeElement.querySelector('#field-Displaytext0q4w02-container'); - expectElementToBeVisible(textInputContainer); - expectElementToBeHidden(displayTextContainer); + expectElementToBeVisible(testingUtils, '#field-Text0tzu53-container'); + expectElementToBeHidden(testingUtils, '#field-Displaytext0q4w02-container'); - typeIntoInput(textInputElement, 'aaa-value'); + typeIntoInput(testingUtils, '#Text0tzu53', 'aaa-value'); fixture.detectChanges(); await fixture.whenStable(); - displayTextContainer = fixture.nativeElement.querySelector('#field-Displaytext0q4w02-container'); - expectElementToBeVisible(displayTextContainer); + expectElementToBeVisible(testingUtils, '#field-Displaytext0q4w02-container'); - typeIntoInput(textInputElement, 'bbb'); + typeIntoInput(testingUtils, '#Text0tzu53', 'bbb'); fixture.detectChanges(); await fixture.whenStable(); - displayTextContainer = fixture.nativeElement.querySelector('#field-Displaytext0q4w02-container'); - expectElementToBeHidden(displayTextContainer); + expectElementToBeHidden(testingUtils, '#field-Displaytext0q4w02-container'); }); it('[C309870] - Should be able to see Display text widget when visibility condition refers to another field and form variable', async () => { @@ -838,23 +721,18 @@ describe('Form Renderer Component', () => { fixture.detectChanges(); await fixture.whenStable(); - const textInputElement = fixture.nativeElement.querySelector('#Text0tzu53'); - const textInputContainer = fixture.nativeElement.querySelector('#field-Text0tzu53-container'); - let displayTextContainer = fixture.nativeElement.querySelector('#field-Displaytext8bac2e-container'); - expectElementToBeVisible(textInputContainer); - expectElementToBeHidden(displayTextContainer); + expectElementToBeVisible(testingUtils, '#field-Text0tzu53-container'); + expectElementToBeHidden(testingUtils, '#field-Displaytext8bac2e-container'); - typeIntoInput(textInputElement, 'aaa-variable'); + typeIntoInput(testingUtils, '#Text0tzu53', 'aaa-variable'); fixture.detectChanges(); await fixture.whenStable(); - displayTextContainer = fixture.nativeElement.querySelector('#field-Displaytext8bac2e-container'); - expectElementToBeVisible(displayTextContainer); + expectElementToBeVisible(testingUtils, '#field-Displaytext8bac2e-container'); - typeIntoInput(textInputElement, 'bbb'); + typeIntoInput(testingUtils, '#Text0tzu53', 'bbb'); fixture.detectChanges(); await fixture.whenStable(); - displayTextContainer = fixture.nativeElement.querySelector('#field-Displaytext8bac2e-container'); - expectElementToBeHidden(displayTextContainer); + expectElementToBeHidden(testingUtils, '#field-Displaytext8bac2e-container'); }); }); @@ -864,7 +742,7 @@ describe('Form Renderer Component', () => { fixture.detectChanges(); await fixture.whenStable(); - const decimalInputElement = fixture.nativeElement.querySelector('#Decimal0tzu53'); + const decimalInputElement = testingUtils.getByCSS('#Decimal0tzu53').nativeElement; expect(decimalInputElement.value).toBeTruthy('10.12'); }); }); diff --git a/lib/core/src/lib/form/components/inplace-form-input/inplace-form-input.component.spec.ts b/lib/core/src/lib/form/components/inplace-form-input/inplace-form-input.component.spec.ts index dab06484c2..6ec0ee2d8b 100644 --- a/lib/core/src/lib/form/components/inplace-form-input/inplace-form-input.component.spec.ts +++ b/lib/core/src/lib/form/components/inplace-form-input/inplace-form-input.component.spec.ts @@ -17,13 +17,14 @@ import { ComponentFixture, TestBed } from '@angular/core/testing'; import { UntypedFormControl } from '@angular/forms'; -import { CoreTestingModule } from '../../../testing'; +import { CoreTestingModule, UnitTestingUtils } from '../../../testing'; import { InplaceFormInputComponent } from './inplace-form-input.component'; describe('InplaceFormInputComponent', () => { let component: InplaceFormInputComponent; let fixture: ComponentFixture; let formControl: UntypedFormControl; + let testingUtils: UnitTestingUtils; beforeEach(async () => { await TestBed.configureTestingModule({ @@ -37,13 +38,14 @@ describe('InplaceFormInputComponent', () => { component = fixture.componentInstance; component.control = formControl; + testingUtils = new UnitTestingUtils(fixture.debugElement); }); it('should update form value', () => { formControl.setValue('New Value'); fixture.detectChanges(); - const input = fixture.nativeElement.querySelector('[data-automation-id="adf-inplace-input"]'); + const input = testingUtils.getByDataAutomationId('adf-inplace-input').nativeElement; expect(input.value).toBe('New Value'); }); @@ -56,7 +58,7 @@ describe('InplaceFormInputComponent', () => { fixture.detectChanges(); - const error = fixture.nativeElement.querySelector('[data-automation-id="adf-inplace-input-error"]'); + const error = testingUtils.getByDataAutomationId('adf-inplace-input-error'); expect(error).toBeTruthy(); }); @@ -66,7 +68,7 @@ describe('InplaceFormInputComponent', () => { fixture.detectChanges(); - const error = fixture.nativeElement.querySelector('[data-automation-id="adf-inplace-input-label"]'); + const error = testingUtils.getByDataAutomationId('adf-inplace-input-label'); expect(error).toBeTruthy(); }); diff --git a/lib/core/src/lib/form/components/widgets/amount/amount.widget.spec.ts b/lib/core/src/lib/form/components/widgets/amount/amount.widget.spec.ts index ad16f65ae1..7934286892 100644 --- a/lib/core/src/lib/form/components/widgets/amount/amount.widget.spec.ts +++ b/lib/core/src/lib/form/components/widgets/amount/amount.widget.spec.ts @@ -23,16 +23,15 @@ import { FormFieldTypes } from '../core/form-field-types'; import { FormModel } from '../core/form.model'; import { HarnessLoader } from '@angular/cdk/testing'; import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed'; -import { MatInputHarness } from '@angular/material/input/testing'; -import { MatFormFieldHarness } from '@angular/material/form-field/testing'; import { NoopAnimationsModule } from '@angular/platform-browser/animations'; -import { NoopTranslateModule } from '@alfresco/adf-core'; +import { NoopTranslateModule } from '../../../../testing/noop-translate.module'; +import { UnitTestingUtils } from '../../../../testing/unit-testing-utils'; describe('AmountWidgetComponent', () => { let loader: HarnessLoader; let widget: AmountWidgetComponent; let fixture: ComponentFixture; - let element: HTMLElement; + let testingUtils: UnitTestingUtils; beforeEach(() => { TestBed.configureTestingModule({ @@ -40,8 +39,8 @@ describe('AmountWidgetComponent', () => { }); fixture = TestBed.createComponent(AmountWidgetComponent); widget = fixture.componentInstance; - element = fixture.nativeElement; loader = TestbedHarnessEnvironment.loader(fixture); + testingUtils = new UnitTestingUtils(fixture.debugElement, loader); }); it('should setup currency from field', () => { @@ -90,10 +89,10 @@ describe('AmountWidgetComponent', () => { }); it('should show tooltip', async () => { - const input = await loader.getHarness(MatInputHarness); - await (await input.host()).hover(); + const host = await testingUtils.getMatInputHost(); + await host.hover(); - const tooltip = await (await input.host()).getAttribute('title'); + const tooltip = await host.getAttribute('title'); expect(tooltip).toBe('my custom tooltip'); }); }); @@ -107,19 +106,18 @@ describe('AmountWidgetComponent', () => { }); it('should be marked as invalid after interaction', async () => { - const input = await loader.getHarness(MatInputHarness); - const host = await input.host(); + const host = await testingUtils.getMatInputHost(); - expect(element.querySelector('.adf-invalid')).toBeFalsy(); + expect(testingUtils.getByCSS('.adf-invalid')).toBeFalsy(); await host.blur(); - expect(element.querySelector('.adf-invalid')).toBeTruthy(); + expect(testingUtils.getByCSS('.adf-invalid')).toBeTruthy(); }); it('should be able to display label with asterisk', async () => { fixture.detectChanges(); await fixture.whenStable(); - const asterisk = element.querySelector('.adf-asterisk'); + const asterisk = testingUtils.getByCSS('.adf-asterisk').nativeElement; expect(asterisk).toBeTruthy(); expect(asterisk.textContent).toEqual('*'); @@ -131,7 +129,7 @@ describe('AmountWidgetComponent - rendering', () => { let loader: HarnessLoader; let widget: AmountWidgetComponent; let fixture: ComponentFixture; - let element: HTMLElement; + let testingUtils: UnitTestingUtils; beforeEach(() => { TestBed.configureTestingModule({ @@ -139,8 +137,8 @@ describe('AmountWidgetComponent - rendering', () => { }); fixture = TestBed.createComponent(AmountWidgetComponent); widget = fixture.componentInstance; - element = fixture.nativeElement; loader = TestbedHarnessEnvironment.loader(fixture); + testingUtils = new UnitTestingUtils(fixture.debugElement, loader); }); it('[C289915] - Should be able to display different currency icons', async () => { @@ -152,7 +150,7 @@ describe('AmountWidgetComponent - rendering', () => { }); fixture.detectChanges(); - const field = await loader.getHarness(MatFormFieldHarness); + const field = await testingUtils.getMatFormField(); expect(await field.getPrefixText()).toBe('$'); widget.field.currency = '£'; @@ -189,23 +187,23 @@ describe('AmountWidgetComponent - rendering', () => { fixture.detectChanges(); await fixture.whenStable(); - const field = await loader.getHarness(MatFormFieldHarness); - const inputField = await loader.getHarness(MatInputHarness.with({ placeholder: 'Check Placeholder Text' })); + const field = await testingUtils.getMatFormField(); + const inputField = await testingUtils.getMatInputByPlaceholder('Check Placeholder Text'); expect(inputField).toBeTruthy(); expect(await field.getPrefixText()).toBe('$'); - const widgetLabel = fixture.nativeElement.querySelector('label.adf-label'); + const widgetLabel = testingUtils.getByCSS('label.adf-label').nativeElement; expect(widgetLabel.textContent.trim()).toBe('Test Amount*'); expect(widget.field.isValid).toBe(false); - const input = await loader.getHarness(MatInputHarness); + const input = await testingUtils.getMatInput(); await input.setValue('90'); expect(widget.field.isValid).toBe(true); await input.setValue('gdfgdf'); expect(widget.field.isValid).toBe(false); - const errorWidget = fixture.nativeElement.querySelector('error-widget .adf-error-text'); + const errorWidget = testingUtils.getByCSS('error-widget .adf-error-text').nativeElement; expect(errorWidget.textContent).toBe('FORM.FIELD.VALIDATOR.INVALID_NUMBER'); }); @@ -230,24 +228,24 @@ describe('AmountWidgetComponent - rendering', () => { fixture.detectChanges(); await fixture.whenStable(); - const widgetLabel = fixture.nativeElement.querySelector('label.adf-label'); + const widgetLabel = testingUtils.getByCSS('label.adf-label').nativeElement; expect(widgetLabel.textContent.trim()).toBe('Test Amount*'); - const field = await loader.getHarness(MatFormFieldHarness); + const field = await testingUtils.getMatFormField(); expect(await field.getPrefixText()).toBe('£'); expect(widget.field.isValid).toBe(false); - const input = await loader.getHarness(MatInputHarness); + const input = await testingUtils.getMatInput(); await input.setValue('8'); expect(widget.field.isValid).toBe(false); - let errorMessage = fixture.nativeElement.querySelector('.adf-error-text'); + let errorMessage = testingUtils.getByCSS('.adf-error-text').nativeElement; expect(errorMessage.textContent.trim()).toContain('FORM.FIELD.VALIDATOR.NOT_LESS_THAN'); await input.setValue('99'); expect(widget.field.isValid).toBe(false); - errorMessage = fixture.nativeElement.querySelector('.adf-error-text'); + errorMessage = testingUtils.getByCSS('.adf-error-text').nativeElement; expect(errorMessage.textContent.trim()).toContain('FORM.FIELD.VALIDATOR.NOT_GREATER_THAN'); await input.setValue('80'); @@ -258,7 +256,7 @@ describe('AmountWidgetComponent - rendering', () => { await input.setValue('incorrect format'); expect(widget.field.isValid).toBe(false); - errorMessage = fixture.nativeElement.querySelector('.adf-error-text'); + errorMessage = testingUtils.getByCSS('.adf-error-text').nativeElement; expect(errorMessage.textContent.trim()).toContain('FORM.FIELD.VALIDATOR.INVALID_NUMBER'); }); @@ -276,11 +274,8 @@ describe('AmountWidgetComponent - rendering', () => { fixture.detectChanges(); await fixture.whenStable(); - const widgetContainer = element.querySelector('.adf-left-label-input-container'); - expect(widgetContainer).not.toBeNull(); - - const adfLeftLabel = element.querySelector('.adf-left-label'); - expect(adfLeftLabel).not.toBeNull(); + expect(testingUtils.getByCSS('.adf-left-label-input-container')).not.toBeNull(); + expect(testingUtils.getByCSS('.adf-left-label')).not.toBeNull(); }); it('should not have left labels classes on leftLabels false', async () => { @@ -296,11 +291,8 @@ describe('AmountWidgetComponent - rendering', () => { fixture.detectChanges(); await fixture.whenStable(); - const widgetContainer = element.querySelector('.adf-left-label-input-container'); - expect(widgetContainer).toBeNull(); - - const adfLeftLabel = element.querySelector('.adf-left-label'); - expect(adfLeftLabel).toBeNull(); + expect(testingUtils.getByCSS('.adf-left-label-input-container')).toBeNull(); + expect(testingUtils.getByCSS('.adf-left-label')).toBeNull(); }); it('should not have left labels classes on leftLabels not present', async () => { @@ -316,11 +308,8 @@ describe('AmountWidgetComponent - rendering', () => { fixture.detectChanges(); await fixture.whenStable(); - const widgetContainer = element.querySelector('.adf-left-label-input-container'); - expect(widgetContainer).toBeNull(); - - const adfLeftLabel = element.querySelector('.adf-left-label'); - expect(adfLeftLabel).toBeNull(); + expect(testingUtils.getByCSS('.adf-left-label-input-container')).toBeNull(); + expect(testingUtils.getByCSS('.adf-left-label')).toBeNull(); }); }); }); diff --git a/lib/core/src/lib/form/components/widgets/checkbox/checkbox.widget.spec.ts b/lib/core/src/lib/form/components/widgets/checkbox/checkbox.widget.spec.ts index 6a4946bced..35e12e1674 100644 --- a/lib/core/src/lib/form/components/widgets/checkbox/checkbox.widget.spec.ts +++ b/lib/core/src/lib/form/components/widgets/checkbox/checkbox.widget.spec.ts @@ -19,9 +19,8 @@ import { HarnessLoader } from '@angular/cdk/testing'; import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed'; import { ComponentFixture, TestBed } from '@angular/core/testing'; import { MatCheckboxModule } from '@angular/material/checkbox'; -import { MatCheckboxHarness } from '@angular/material/checkbox/testing'; import { TranslateLoader } from '@ngx-translate/core'; -import { CoreTestingModule } from '../../../../testing'; +import { CoreTestingModule, UnitTestingUtils } from '../../../../testing'; import { TranslateLoaderService } from '../../../../translation'; import { FormFieldModel, FormFieldTypes, FormModel } from '../core'; import { CheckboxWidgetComponent } from './checkbox.widget'; @@ -30,7 +29,7 @@ describe('CheckboxWidgetComponent', () => { let loader: HarnessLoader; let widget: CheckboxWidgetComponent; let fixture: ComponentFixture; - let element: HTMLElement; + let testingUtils: UnitTestingUtils; beforeEach(() => { TestBed.configureTestingModule({ @@ -38,11 +37,9 @@ describe('CheckboxWidgetComponent', () => { providers: [{ provide: TranslateLoader, useClass: TranslateLoaderService }] }); fixture = TestBed.createComponent(CheckboxWidgetComponent); - widget = fixture.componentInstance; - element = fixture.nativeElement; - loader = TestbedHarnessEnvironment.loader(fixture); + testingUtils = new UnitTestingUtils(fixture.debugElement, loader); }); afterEach(() => fixture.destroy()); @@ -60,20 +57,20 @@ describe('CheckboxWidgetComponent', () => { }); it('should be marked as invalid when required after interaction', async () => { - const checkbox = await loader.getHarness(MatCheckboxHarness); - expect(element.querySelector('.adf-invalid')).toBeFalsy(); + const checkbox = await testingUtils.getMatCheckbox(); + expect(testingUtils.getByCSS('.adf-invalid')).toBeFalsy(); await checkbox.check(); await checkbox.uncheck(); - expect(element.querySelector('.adf-invalid')).toBeTruthy(); + expect(testingUtils.getByCSS('.adf-invalid')).toBeTruthy(); }); it('should be able to display label with asterisk', async () => { fixture.detectChanges(); await fixture.whenStable(); - const asterisk = element.querySelector('.adf-asterisk'); + const asterisk = testingUtils.getByCSS('.adf-asterisk').nativeElement; expect(asterisk).toBeTruthy(); expect(asterisk.textContent).toEqual('*'); @@ -83,16 +80,14 @@ describe('CheckboxWidgetComponent', () => { widget.field.value = true; fixture.detectChanges(); - const checkbox = await loader.getHarness(MatCheckboxHarness); - expect(await checkbox.isChecked()).toBe(true); + expect(await testingUtils.checkIfMatCheckboxIsChecked()).toBe(true); }); it('should not be checked if false is passed', async () => { widget.field.value = false; fixture.detectChanges(); - const checkbox = await loader.getHarness(MatCheckboxHarness); - expect(await checkbox.isChecked()).toBe(false); + expect(await testingUtils.checkIfMatCheckboxIsChecked()).toBe(false); }); describe('when tooltip is set', () => { @@ -105,10 +100,9 @@ describe('CheckboxWidgetComponent', () => { }); it('should show tooltip', async () => { - const checkbox = await loader.getHarness(MatCheckboxHarness); - await (await checkbox.host()).hover(); - - const tooltip = await (await checkbox.host()).getAttribute('title'); + await testingUtils.hoverOverMatCheckbox(); + const host = await testingUtils.getMatCheckboxHost(); + const tooltip = await host.getAttribute('title'); expect(tooltip).toBe('my custom tooltip'); }); }); diff --git a/lib/core/src/lib/form/components/widgets/date-time/date-time.widget.spec.ts b/lib/core/src/lib/form/components/widgets/date-time/date-time.widget.spec.ts index d926d8246b..b472f1a7dc 100644 --- a/lib/core/src/lib/form/components/widgets/date-time/date-time.widget.spec.ts +++ b/lib/core/src/lib/form/components/widgets/date-time/date-time.widget.spec.ts @@ -20,22 +20,22 @@ import { FormFieldModel } from '../core/form-field.model'; import { FormModel } from '../core/form.model'; import { DateTimeWidgetComponent } from './date-time.widget'; import { FormFieldTypes } from '../core/form-field-types'; -import { HarnessLoader } from '@angular/cdk/testing'; +import { HarnessLoader, TestKey } from '@angular/cdk/testing'; import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed'; -import { MatInputHarness } from '@angular/material/input/testing'; import { addMinutes } from 'date-fns'; import { MatDialogModule } from '@angular/material/dialog'; import { MatDatetimepickerModule, MatNativeDatetimeModule } from '@mat-datetimepicker/core'; import { MatDatepickerModule } from '@angular/material/datepicker'; import { NoopAnimationsModule } from '@angular/platform-browser/animations'; -import { NoopTranslateModule } from '@alfresco/adf-core'; +import { NoopTranslateModule } from '../../../../testing/noop-translate.module'; +import { UnitTestingUtils } from '../../../../testing/unit-testing-utils'; describe('DateTimeWidgetComponent', () => { let loader: HarnessLoader; let widget: DateTimeWidgetComponent; let fixture: ComponentFixture; - let element: HTMLElement; let form: FormModel; + let testingUtils: UnitTestingUtils; beforeEach(() => { TestBed.configureTestingModule({ @@ -50,12 +50,10 @@ describe('DateTimeWidgetComponent', () => { ] }); fixture = TestBed.createComponent(DateTimeWidgetComponent); - - element = fixture.nativeElement; widget = fixture.componentInstance; - form = new FormModel(); loader = TestbedHarnessEnvironment.loader(fixture); + testingUtils = new UnitTestingUtils(fixture.debugElement, loader); }); afterEach(() => { @@ -85,8 +83,8 @@ describe('DateTimeWidgetComponent', () => { }); fixture.detectChanges(); - expect(element.querySelector('#data-time-widget')).toBeDefined(); - expect(element.querySelector('#data-time-widget')).not.toBeNull(); + expect(testingUtils.getByCSS('#data-time-widget')).toBeDefined(); + expect(testingUtils.getByCSS('#data-time-widget')).not.toBeNull(); }); it('should setup max value for date picker', () => { @@ -187,14 +185,13 @@ describe('DateTimeWidgetComponent', () => { fixture.whenStable(); await fixture.whenStable(); - const input = await loader.getHarness(MatInputHarness); - await input.setValue('9999-09-12T09:10:00.000Z'); + await testingUtils.fillMatInput('9999-09-12T09:10:00.000Z'); expect(field.value).toEqual(new Date('9999-09-12T09:10:00.000Z')); expect(field.isValid).toBeTrue(); }); - it('should fail validating incorrect keyboard input', () => { + it('should fail validating incorrect keyboard input', async () => { const field = new FormFieldModel(form, { id: 'date-field-id', name: 'date-name', @@ -206,9 +203,7 @@ describe('DateTimeWidgetComponent', () => { fixture.detectChanges(); - const dateTimeInput = fixture.nativeElement.querySelector('input'); - dateTimeInput.value = '123abc'; - dateTimeInput.dispatchEvent(new Event('input')); + await testingUtils.fillMatInput('123abc'); expect(widget.datetimeInputControl.invalid).toBeTrue(); expect(field.value).toBe(null); @@ -229,8 +224,7 @@ describe('DateTimeWidgetComponent', () => { fixture.whenStable(); await fixture.whenStable(); - const input = await loader.getHarness(MatInputHarness); - await input.setValue(null); + await testingUtils.fillMatInput(null); expect(widget.datetimeInputControl.value).toBe(null); expect(widget.datetimeInputControl.valid).toBeTrue(); @@ -248,10 +242,10 @@ describe('DateTimeWidgetComponent', () => { }); it('should show tooltip', async () => { - const input = await loader.getHarness(MatInputHarness); - await (await input.host()).hover(); + const host = await testingUtils.getMatInputHost(); + await host.hover(); - const tooltip = await (await input.host()).getAttribute('title'); + const tooltip = await host.getAttribute('title'); expect(tooltip).toBe('my custom tooltip'); }); }); @@ -266,21 +260,17 @@ describe('DateTimeWidgetComponent', () => { it('should be marked as invalid after interaction', () => { fixture.detectChanges(); + expect(testingUtils.getByCSS('.adf-invalid')).toBeFalsy(); - const dateTimeInput = fixture.nativeElement.querySelector('input'); - expect(fixture.nativeElement.querySelector('.adf-invalid')).toBeFalsy(); - - dateTimeInput.dispatchEvent(new Event('blur')); - + testingUtils.blurByCSS('input'); fixture.detectChanges(); - expect(fixture.nativeElement.querySelector('.adf-invalid')).toBeTruthy(); + expect(testingUtils.getByCSS('.adf-invalid')).toBeTruthy(); }); it('should be able to display label with asterisk', () => { fixture.detectChanges(); - - const asterisk = element.querySelector('.adf-asterisk'); + const asterisk = testingUtils.getByCSS('.adf-asterisk').nativeElement; expect(asterisk).not.toBeNull(); expect(asterisk?.textContent).toEqual('*'); @@ -317,8 +307,7 @@ describe('DateTimeWidgetComponent', () => { fixture.detectChanges(); await fixture.whenStable(); - const input = await loader.getHarness(MatInputHarness); - expect(await input.getValue()).toBe('30-11-9999 10:30 AM'); + expect(await testingUtils.getMatInputValue()).toBe('30-11-9999 10:30 AM'); }); it('should show the correct format type', async () => { @@ -333,8 +322,7 @@ describe('DateTimeWidgetComponent', () => { fixture.detectChanges(); await fixture.whenStable(); - const input = await loader.getHarness(MatInputHarness); - expect(await input.getValue()).toBe('12-30-9999 10:30 AM'); + expect(await testingUtils.getMatInputValue()).toBe('12-30-9999 10:30 AM'); }); it('should disable date button when is readonly', () => { @@ -347,14 +335,16 @@ describe('DateTimeWidgetComponent', () => { }); fixture.detectChanges(); - let dateButton = element.querySelector('button'); + let dateButton = testingUtils.getByCSS('button').nativeElement; + expect(dateButton).not.toBeNull(); expect(dateButton?.disabled).toBeFalsy(); widget.field.readOnly = true; fixture.detectChanges(); - dateButton = element.querySelector('button'); + dateButton = testingUtils.getByCSS('button').nativeElement; + expect(dateButton).not.toBeNull(); expect(dateButton?.disabled).toBeTruthy(); }); @@ -373,7 +363,7 @@ describe('DateTimeWidgetComponent', () => { fixture.detectChanges(); await fixture.whenStable(); - const input = await loader.getHarness(MatInputHarness); + const input = await testingUtils.getMatInput(); expect(await input.getValue()).toBe('12-30-9999 10:30 AM'); widget.field.value = '2020-03-02T00:00:00.000Z'; @@ -398,7 +388,7 @@ describe('DateTimeWidgetComponent', () => { fixture.detectChanges(); await fixture.whenStable(); - const input = await loader.getHarness(MatInputHarness); + const input = await testingUtils.getMatInput(); expect(await input.getValue()).toBe('12/30/9999 10;30 AM'); widget.field.value = '2020-03-02T00:00:00.000Z'; @@ -423,13 +413,13 @@ describe('DateTimeWidgetComponent', () => { fixture.detectChanges(); - const widgetContainer = element.querySelector('.adf-left-label-input-container'); + const widgetContainer = testingUtils.getByCSS('.adf-left-label-input-container'); expect(widgetContainer).not.toBeNull(); - const leftDatePicker = element.querySelector('.adf-left-label-input-datepicker'); + const leftDatePicker = testingUtils.getByCSS('.adf-left-label-input-datepicker'); expect(leftDatePicker).not.toBeNull(); - const adfLeftLabel = element.querySelector('.adf-left-label'); + const adfLeftLabel = testingUtils.getByCSS('.adf-left-label'); expect(adfLeftLabel).not.toBeNull(); }); @@ -445,13 +435,13 @@ describe('DateTimeWidgetComponent', () => { fixture.detectChanges(); - const widgetContainer = element.querySelector('.adf-left-label-input-container'); + const widgetContainer = testingUtils.getByCSS('.adf-left-label-input-container'); expect(widgetContainer).toBeNull(); - const leftDatePicker = element.querySelector('.adf-left-label-input-datepicker'); + const leftDatePicker = testingUtils.getByCSS('.adf-left-label-input-datepicker'); expect(leftDatePicker).toBeNull(); - const adfLeftLabel = element.querySelector('.adf-left-label'); + const adfLeftLabel = testingUtils.getByCSS('.adf-left-label'); expect(adfLeftLabel).toBeNull(); }); @@ -467,13 +457,13 @@ describe('DateTimeWidgetComponent', () => { fixture.detectChanges(); - const widgetContainer = element.querySelector('.adf-left-label-input-container'); + const widgetContainer = testingUtils.getByCSS('.adf-left-label-input-container'); expect(widgetContainer).toBeNull(); - const leftDatePicker = element.querySelector('.adf-left-label-input-datepicker'); + const leftDatePicker = testingUtils.getByCSS('.adf-left-label-input-datepicker'); expect(leftDatePicker).toBeNull(); - const adfLeftLabel = element.querySelector('.adf-left-label'); + const adfLeftLabel = testingUtils.getByCSS('.adf-left-label'); expect(adfLeftLabel).toBeNull(); }); @@ -487,12 +477,10 @@ describe('DateTimeWidgetComponent', () => { required: true }); - const input = await loader.getHarness(MatInputHarness); - await input.focus(); - await (await input.host()).sendKeys('Enter'); + await testingUtils.focusMatInput(); + await testingUtils.sendKeysToMatInput([TestKey.ENTER]); - const picker = element.querySelector('[data-automation-id="adf-date-time-widget-picker"]'); - expect(picker).toBeTruthy(); + expect(testingUtils.getByDataAutomationId('adf-date-time-widget-picker')).toBeTruthy(); }); }); }); diff --git a/lib/core/src/lib/form/components/widgets/date/date.widget.spec.ts b/lib/core/src/lib/form/components/widgets/date/date.widget.spec.ts index dfdd31ffbc..d5365304d5 100644 --- a/lib/core/src/lib/form/components/widgets/date/date.widget.spec.ts +++ b/lib/core/src/lib/form/components/widgets/date/date.widget.spec.ts @@ -17,7 +17,7 @@ import { ComponentFixture, TestBed } from '@angular/core/testing'; import { DateAdapter } from '@angular/material/core'; -import { CoreTestingModule } from '../../../../testing'; +import { CoreTestingModule, UnitTestingUtils } from '../../../../testing'; import { FormFieldModel, FormFieldTypes, FormModel } from '../core'; import { DateWidgetComponent } from './date.widget'; import { DEFAULT_DATE_FORMAT } from '../../../../common'; @@ -26,9 +26,9 @@ import { isEqual } from 'date-fns'; describe('DateWidgetComponent', () => { let widget: DateWidgetComponent; let fixture: ComponentFixture; - let element: HTMLElement; let adapter: DateAdapter; let form: FormModel; + let testingUtils: UnitTestingUtils; beforeEach(() => { TestBed.configureTestingModule({ @@ -36,12 +36,10 @@ describe('DateWidgetComponent', () => { }); form = new FormModel(); - fixture = TestBed.createComponent(DateWidgetComponent); adapter = fixture.debugElement.injector.get(DateAdapter); - - element = fixture.nativeElement; widget = fixture.componentInstance; + testingUtils = new UnitTestingUtils(fixture.debugElement); }); it('[C310333] - should be able to set a placeholder', () => { @@ -122,8 +120,8 @@ describe('DateWidgetComponent', () => { fixture.detectChanges(); - expect(element.querySelector('#data-widget')).toBeDefined(); - expect(element.querySelector('#data-widget')).not.toBeNull(); + expect(testingUtils.getByCSS('#data-widget')).toBeDefined(); + expect(testingUtils.getByCSS('#data-widget')).not.toBeNull(); }); it('should setup max value for date picker', () => { @@ -166,14 +164,12 @@ describe('DateWidgetComponent', () => { it('should be marked as invalid after interaction', () => { fixture.detectChanges(); + expect(testingUtils.getByCSS('.adf-invalid')).toBeFalsy(); - const dateInput = fixture.nativeElement.querySelector('input'); - expect(fixture.nativeElement.querySelector('.adf-invalid')).toBeFalsy(); - - dateInput.dispatchEvent(new Event('blur')); + testingUtils.blurByCSS('input'); fixture.detectChanges(); - expect(fixture.nativeElement.querySelector('.adf-invalid')).toBeTruthy(); + expect(testingUtils.getByCSS('.adf-invalid')).toBeTruthy(); }); it('should be valid when field is hidden with empty value', () => { @@ -211,9 +207,9 @@ describe('DateWidgetComponent', () => { fixture.detectChanges(); - const dateElement = element.querySelector('#date-field-id'); - expect(dateElement).not.toBeNull(); + const dateElement = testingUtils.getByCSS('#date-field-id').nativeElement; + expect(dateElement).not.toBeNull(); expect(dateElement?.value).toContain('9-9-9999'); }); @@ -227,9 +223,9 @@ describe('DateWidgetComponent', () => { }); fixture.detectChanges(); - let dateElement = element.querySelector('#date-field-id'); - dateElement = element.querySelector('#date-field-id'); + const dateElement = testingUtils.getByCSS('#date-field-id').nativeElement; + expect(dateElement?.value).toContain('30.12.9999'); }); @@ -243,14 +239,16 @@ describe('DateWidgetComponent', () => { fixture.detectChanges(); - let dateButton = element.querySelector('button'); + let dateButton = testingUtils.getByCSS('button').nativeElement; + expect(dateButton).toBeDefined(); expect(dateButton.disabled).toBeFalsy(); widget.field.readOnly = true; fixture.detectChanges(); - dateButton = element.querySelector('button'); + dateButton = testingUtils.getByCSS('button').nativeElement; + expect(dateButton).toBeDefined(); expect(dateButton.disabled).toBeTruthy(); }); @@ -288,7 +286,8 @@ describe('DateWidgetComponent', () => { fixture.detectChanges(); - const dateElement = element.querySelector('#date-field-id'); + const dateElement = testingUtils.getByCSS('#date-field-id').nativeElement; + expect(dateElement).toBeDefined(); expect(dateElement.value).toContain('12-30-9999'); diff --git a/lib/core/src/lib/form/components/widgets/decimal/decimal.component.spec.ts b/lib/core/src/lib/form/components/widgets/decimal/decimal.component.spec.ts index 98c03d8b25..4777837cbc 100644 --- a/lib/core/src/lib/form/components/widgets/decimal/decimal.component.spec.ts +++ b/lib/core/src/lib/form/components/widgets/decimal/decimal.component.spec.ts @@ -19,18 +19,16 @@ import { HarnessLoader } from '@angular/cdk/testing'; import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed'; import { ComponentFixture, TestBed } from '@angular/core/testing'; import { MatInputModule } from '@angular/material/input'; -import { MatInputHarness } from '@angular/material/input/testing'; -import { CoreTestingModule } from '../../../../testing'; +import { CoreTestingModule, UnitTestingUtils } from '../../../../testing'; import { FormService } from '../../../services/form.service'; import { FormFieldModel, FormFieldTypes, FormModel } from '../core'; - import { DecimalWidgetComponent } from './decimal.component'; describe('DecimalComponent', () => { let loader: HarnessLoader; let widget: DecimalWidgetComponent; let fixture: ComponentFixture; - let element: HTMLElement; + let testingUtils: UnitTestingUtils; beforeEach(async () => { await TestBed.configureTestingModule({ @@ -40,8 +38,8 @@ describe('DecimalComponent', () => { fixture = TestBed.createComponent(DecimalWidgetComponent); widget = fixture.componentInstance; - element = fixture.nativeElement; loader = TestbedHarnessEnvironment.loader(fixture); + testingUtils = new UnitTestingUtils(fixture.debugElement, loader); }); describe('when tooltip is set', () => { @@ -54,10 +52,10 @@ describe('DecimalComponent', () => { }); it('should show tooltip', async () => { - const input = await loader.getHarness(MatInputHarness); - await (await input.host()).hover(); + const host = await testingUtils.getMatInputHost(); + await host.hover(); - const tooltip = await (await input.host()).getAttribute('title'); + const tooltip = await host.getAttribute('title'); expect(tooltip).toBe('my custom tooltip'); }); }); @@ -73,20 +71,16 @@ describe('DecimalComponent', () => { }); it('should be marked as invalid after interaction', async () => { - const input = await loader.getHarness(MatInputHarness); - expect(fixture.nativeElement.querySelector('.adf-invalid')).toBeFalsy(); + expect(testingUtils.getByCSS('.adf-invalid')).toBeFalsy(); - const inputHost = await input.host(); - await inputHost.blur(); + await testingUtils.blurMatInput(); fixture.detectChanges(); - const invalidElement = fixture.nativeElement.querySelector('.adf-invalid'); - - expect(invalidElement).toBeTruthy(); + expect(testingUtils.getByCSS('.adf-invalid')).toBeTruthy(); }); it('should be able to display label with asterisk', async () => { - const asterisk = element.querySelector('.adf-asterisk'); + const asterisk = testingUtils.getByCSS('.adf-asterisk').nativeElement; expect(asterisk).toBeTruthy(); expect(asterisk?.textContent).toEqual('*'); @@ -107,10 +101,10 @@ describe('DecimalComponent', () => { fixture.detectChanges(); await fixture.whenStable(); - const widgetContainer = element.querySelector('.adf-left-label-input-container'); + const widgetContainer = testingUtils.getByCSS('.adf-left-label-input-container'); expect(widgetContainer).not.toBeNull(); - const adfLeftLabel = element.querySelector('.adf-left-label'); + const adfLeftLabel = testingUtils.getByCSS('.adf-left-label'); expect(adfLeftLabel).not.toBeNull(); }); @@ -127,10 +121,10 @@ describe('DecimalComponent', () => { fixture.detectChanges(); await fixture.whenStable(); - const widgetContainer = element.querySelector('.adf-left-label-input-container'); + const widgetContainer = testingUtils.getByCSS('.adf-left-label-input-container'); expect(widgetContainer).toBeNull(); - const adfLeftLabel = element.querySelector('.adf-left-label'); + const adfLeftLabel = testingUtils.getByCSS('.adf-left-label'); expect(adfLeftLabel).toBeNull(); }); @@ -147,10 +141,10 @@ describe('DecimalComponent', () => { fixture.detectChanges(); await fixture.whenStable(); - const widgetContainer = element.querySelector('.adf-left-label-input-container'); + const widgetContainer = testingUtils.getByCSS('.adf-left-label-input-container'); expect(widgetContainer).toBeNull(); - const adfLeftLabel = element.querySelector('.adf-left-label'); + const adfLeftLabel = testingUtils.getByCSS('.adf-left-label'); expect(adfLeftLabel).toBeNull(); }); }); diff --git a/lib/core/src/lib/form/components/widgets/error/error.component.spec.ts b/lib/core/src/lib/form/components/widgets/error/error.component.spec.ts index f55dc31e61..ba2ffbf42f 100644 --- a/lib/core/src/lib/form/components/widgets/error/error.component.spec.ts +++ b/lib/core/src/lib/form/components/widgets/error/error.component.spec.ts @@ -17,14 +17,14 @@ import { SimpleChange, SimpleChanges } from '@angular/core'; import { ComponentFixture, TestBed } from '@angular/core/testing'; -import { CoreTestingModule } from '../../../../testing'; +import { CoreTestingModule, UnitTestingUtils } from '../../../../testing'; import { ErrorMessageModel } from '../core'; import { ErrorWidgetComponent } from './error.component'; describe('ErrorWidgetComponent', () => { let widget: ErrorWidgetComponent; let fixture: ComponentFixture; - let element: HTMLElement; + let testingUtils: UnitTestingUtils; beforeEach(() => { TestBed.configureTestingModule({ @@ -32,7 +32,7 @@ describe('ErrorWidgetComponent', () => { }); fixture = TestBed.createComponent(ErrorWidgetComponent); widget = fixture.componentInstance; - element = fixture.nativeElement; + testingUtils = new UnitTestingUtils(fixture.debugElement); }); const errorMessage: string = 'fake-error'; const errorMessageModel: ErrorMessageModel = new ErrorMessageModel({ message: errorMessage }); @@ -46,7 +46,7 @@ describe('ErrorWidgetComponent', () => { await fixture.whenStable(); fixture.detectChanges(); - const errorIcon = element.querySelector('.adf-error-icon').textContent; + const errorIcon = testingUtils.getByCSS('.adf-error-icon').nativeElement.textContent; expect(errorIcon).toEqual('error_outline'); }); @@ -62,7 +62,7 @@ describe('ErrorWidgetComponent', () => { await fixture.whenStable(); fixture.detectChanges(); - const requiredErrorText = element.querySelector('.adf-error-text').textContent; + const requiredErrorText = testingUtils.getByCSS('.adf-error-text').nativeElement.textContent; expect(requiredErrorText).toEqual(errorMessage); }); }); diff --git a/lib/core/src/lib/form/components/widgets/header/header.widget.spec.ts b/lib/core/src/lib/form/components/widgets/header/header.widget.spec.ts index fa9bf0b33d..10395fd15f 100644 --- a/lib/core/src/lib/form/components/widgets/header/header.widget.spec.ts +++ b/lib/core/src/lib/form/components/widgets/header/header.widget.spec.ts @@ -20,12 +20,13 @@ import { ContainerModel } from '../core/container.model'; import { FormFieldTypes } from '../core/form-field-types'; import { FormFieldModel } from '../core/form-field.model'; import { HeaderWidgetComponent } from './header.widget'; -import { NoopTranslateModule } from '../../../../testing'; +import { NoopTranslateModule, UnitTestingUtils } from '../../../../testing'; import { NoopAnimationsModule } from '@angular/platform-browser/animations'; describe('HeaderWidgetComponent', () => { let component: HeaderWidgetComponent; let fixture: ComponentFixture; + let testingUtils: UnitTestingUtils; beforeEach(() => { TestBed.configureTestingModule({ @@ -36,6 +37,7 @@ describe('HeaderWidgetComponent', () => { beforeEach(() => { fixture = TestBed.createComponent(HeaderWidgetComponent); component = fixture.componentInstance; + testingUtils = new UnitTestingUtils(fixture.debugElement); fixture.componentRef.setInput( 'element', new ContainerModel( @@ -61,8 +63,8 @@ describe('HeaderWidgetComponent', () => { it('should render header widget template when type is group', () => { fixture.detectChanges(); - expect(fixture.nativeElement.querySelector('.adf-container-widget-header')).not.toBe(null); - expect(fixture.nativeElement.querySelector('#container-header-label-test-id').textContent.trim()).toEqual('test-name'); + expect(testingUtils.getByCSS('.adf-container-widget-header')).not.toBe(null); + expect(testingUtils.getByCSS('#container-header-label-test-id').nativeElement.textContent.trim()).toEqual('test-name'); }); it('should NOT render header widget template when type is different then group', () => { @@ -70,13 +72,13 @@ describe('HeaderWidgetComponent', () => { fixture.detectChanges(); - expect(fixture.nativeElement.querySelector('.adf-container-widget-header')).toBe(null); + expect(testingUtils.getByCSS('.adf-container-widget-header')).toBe(null); }); it('should display header text when hideHeader is set to false', () => { fixture.detectChanges(); - expect(fixture.nativeElement.querySelector('.adf-container-widget-header__text')).not.toBe(null); + expect(testingUtils.getByCSS('.adf-container-widget-header__text')).not.toBe(null); }); it('should NOT display header text when hideHeader is set to true', () => { @@ -84,7 +86,7 @@ describe('HeaderWidgetComponent', () => { fixture.detectChanges(); - expect(fixture.nativeElement.querySelector('.adf-container-widget-header__text')).toBe(null); + expect(testingUtils.getByCSS('.adf-container-widget-header__text')).toBe(null); }); it('should display expander when allowCollapse is set to true', () => { @@ -92,13 +94,13 @@ describe('HeaderWidgetComponent', () => { fixture.detectChanges(); - expect(fixture.nativeElement.querySelector('.mdl-button--icon')).not.toBe(null); + expect(testingUtils.getByCSS('.mdl-button--icon')).not.toBe(null); }); it('should NOT display expander when allowCollapse is set to false', () => { fixture.detectChanges(); - expect(fixture.nativeElement.querySelector('.mdl-button--icon')).toBe(null); + expect(testingUtils.getByCSS('.mdl-button--icon')).toBe(null); }); it('should call onExpanderClicked method when expander is clicked', () => { @@ -107,8 +109,7 @@ describe('HeaderWidgetComponent', () => { spyOn(component, 'onExpanderClicked'); - const expander = fixture.nativeElement.querySelector('.mdl-button--icon'); - expander.click(); + testingUtils.clickByCSS('.mdl-button--icon'); expect(component.onExpanderClicked).toHaveBeenCalledWith(component.element); }); @@ -118,8 +119,7 @@ describe('HeaderWidgetComponent', () => { spyOn(component, 'onExpanderClicked'); - const headerText = fixture.nativeElement.querySelector('#container-header-label-test-id'); - headerText.click(); + testingUtils.clickByCSS('#container-header-label-test-id'); expect(component.onExpanderClicked).toHaveBeenCalledWith(component.element); }); diff --git a/lib/core/src/lib/form/components/widgets/hyperlink/hyperlink.widget.spec.ts b/lib/core/src/lib/form/components/widgets/hyperlink/hyperlink.widget.spec.ts index 580b27dece..7ca8bf0097 100644 --- a/lib/core/src/lib/form/components/widgets/hyperlink/hyperlink.widget.spec.ts +++ b/lib/core/src/lib/form/components/widgets/hyperlink/hyperlink.widget.spec.ts @@ -16,14 +16,14 @@ */ import { ComponentFixture, TestBed } from '@angular/core/testing'; -import { CoreTestingModule } from '../../../../testing'; +import { CoreTestingModule, UnitTestingUtils } from '../../../../testing'; import { FormFieldModel, FormFieldTypes, FormModel } from '../core'; import { HyperlinkWidgetComponent } from './hyperlink.widget'; describe('HyperlinkWidgetComponent', () => { let widget: HyperlinkWidgetComponent; let fixture: ComponentFixture; - let element: HTMLElement; + let testingUtils: UnitTestingUtils; beforeEach(() => { TestBed.configureTestingModule({ @@ -31,7 +31,7 @@ describe('HyperlinkWidgetComponent', () => { }); fixture = TestBed.createComponent(HyperlinkWidgetComponent); widget = fixture.componentInstance; - element = fixture.nativeElement; + testingUtils = new UnitTestingUtils(fixture.debugElement); }); it('should get link text from field display text', () => { @@ -142,8 +142,7 @@ describe('HyperlinkWidgetComponent', () => { widget.ngOnInit(); fixture.detectChanges(); - const hyperlinkWidgetLink = element.querySelector('a'); - expect(hyperlinkWidgetLink.innerText).toBe(url); + expect(testingUtils.getInnerTextByCSS('a')).toBe(url); }); it('should be able to set label property', () => { @@ -154,8 +153,7 @@ describe('HyperlinkWidgetComponent', () => { }); fixture.detectChanges(); - const hyperlinkWidgetLabel = element.querySelector('label'); - expect(hyperlinkWidgetLabel.innerText).toBe(label); + expect(testingUtils.getInnerTextByCSS('label')).toBe(label); }); it('should be able to set URL', () => { @@ -166,7 +164,7 @@ describe('HyperlinkWidgetComponent', () => { }); fixture.detectChanges(); - const hyperlinkWidgetLink = element.querySelector('a'); + const hyperlinkWidgetLink = testingUtils.getByCSS('a').nativeElement; expect(hyperlinkWidgetLink.href).toBe(url); }); @@ -180,7 +178,7 @@ describe('HyperlinkWidgetComponent', () => { }); fixture.detectChanges(); - const hyperlinkWidgetLink = element.querySelector('a'); + const hyperlinkWidgetLink = testingUtils.getByCSS('a').nativeElement; expect(hyperlinkWidgetLink.href).toBe(url); expect(hyperlinkWidgetLink.innerText).toBe(displayText); }); @@ -197,7 +195,7 @@ describe('HyperlinkWidgetComponent', () => { }); fixture.detectChanges(); - const checkbox = fixture.debugElement.nativeElement.querySelector('.adf-hyperlink-widget div'); + const checkbox = testingUtils.getByCSS('.adf-hyperlink-widget div').nativeElement; const tooltip = checkbox.getAttribute('title'); expect(tooltip).toEqual(widget.field.tooltip); diff --git a/lib/core/src/lib/form/components/widgets/multiline-text/multiline-text.widget.spec.ts b/lib/core/src/lib/form/components/widgets/multiline-text/multiline-text.widget.spec.ts index 9f3c71fcdb..b212cdf8e5 100644 --- a/lib/core/src/lib/form/components/widgets/multiline-text/multiline-text.widget.spec.ts +++ b/lib/core/src/lib/form/components/widgets/multiline-text/multiline-text.widget.spec.ts @@ -18,19 +18,19 @@ import { HarnessLoader } from '@angular/cdk/testing'; import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed'; import { NoopAnimationsModule } from '@angular/platform-browser/animations'; -import { MatInputHarness } from '@angular/material/input/testing'; import { FormModel } from '../core/form.model'; import { FormFieldModel } from '../core/form-field.model'; import { FormFieldTypes } from '../core/form-field-types'; import { MultilineTextWidgetComponentComponent } from './multiline-text.widget'; import { ComponentFixture, TestBed } from '@angular/core/testing'; -import { NoopTranslateModule } from '@alfresco/adf-core'; +import { NoopTranslateModule } from '../../../../testing/noop-translate.module'; +import { UnitTestingUtils } from '../../../../testing/unit-testing-utils'; describe('MultilineTextWidgetComponentComponent', () => { let loader: HarnessLoader; let widget: MultilineTextWidgetComponentComponent; let fixture: ComponentFixture; - let element: HTMLElement; + let testingUtils: UnitTestingUtils; beforeEach(() => { TestBed.configureTestingModule({ @@ -38,8 +38,8 @@ describe('MultilineTextWidgetComponentComponent', () => { }); fixture = TestBed.createComponent(MultilineTextWidgetComponentComponent); widget = fixture.componentInstance; - element = fixture.nativeElement; loader = TestbedHarnessEnvironment.loader(fixture); + testingUtils = new UnitTestingUtils(fixture.debugElement, loader); }); describe('when tooltip is set', () => { @@ -52,10 +52,10 @@ describe('MultilineTextWidgetComponentComponent', () => { }); it('should show tooltip', async () => { - const input = await loader.getHarness(MatInputHarness); - await (await input.host()).hover(); + const host = await testingUtils.getMatInputHost(); + await host.hover(); - const tooltip = await (await input.host()).getAttribute('title'); + const tooltip = await host.getAttribute('title'); expect(tooltip).toBe('my custom tooltip'); }); }); @@ -70,15 +70,14 @@ describe('MultilineTextWidgetComponentComponent', () => { }); it('should be marked as invalid after interaction', async () => { - const input = await loader.getHarness(MatInputHarness); - expect(fixture.nativeElement.querySelector('.adf-invalid')).toBeFalsy(); + expect(testingUtils.getByCSS('.adf-invalid')).toBeFalsy(); - await (await input.host()).blur(); - expect(fixture.nativeElement.querySelector('.adf-invalid')).toBeTruthy(); + await testingUtils.blurMatInput(); + expect(testingUtils.getByCSS('.adf-invalid')).toBeTruthy(); }); it('should be able to display label with asterisk', async () => { - const asterisk = element.querySelector('.adf-asterisk'); + const asterisk = testingUtils.getByCSS('.adf-asterisk').nativeElement; expect(asterisk).toBeTruthy(); expect(asterisk.textContent).toEqual('*'); diff --git a/lib/core/src/lib/form/components/widgets/number/number.widget.spec.ts b/lib/core/src/lib/form/components/widgets/number/number.widget.spec.ts index 25511c3f14..0c95448b12 100644 --- a/lib/core/src/lib/form/components/widgets/number/number.widget.spec.ts +++ b/lib/core/src/lib/form/components/widgets/number/number.widget.spec.ts @@ -20,8 +20,7 @@ import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed'; import { ComponentFixture, TestBed } from '@angular/core/testing'; import { MatIconModule } from '@angular/material/icon'; import { MatInputModule } from '@angular/material/input'; -import { MatInputHarness } from '@angular/material/input/testing'; -import { CoreTestingModule } from '../../../../testing'; +import { CoreTestingModule, UnitTestingUtils } from '../../../../testing'; import { FormFieldModel, FormFieldTypes, FormModel } from '../core'; import { NumberWidgetComponent } from './number.widget'; @@ -29,7 +28,7 @@ describe('NumberWidgetComponent', () => { let loader: HarnessLoader; let widget: NumberWidgetComponent; let fixture: ComponentFixture; - let element: HTMLElement; + let testingUtils: UnitTestingUtils; beforeEach(() => { TestBed.configureTestingModule({ @@ -37,8 +36,8 @@ describe('NumberWidgetComponent', () => { }); fixture = TestBed.createComponent(NumberWidgetComponent); widget = fixture.componentInstance; - element = fixture.nativeElement; loader = TestbedHarnessEnvironment.loader(fixture); + testingUtils = new UnitTestingUtils(fixture.debugElement, loader); }); describe('when tooltip is set', () => { @@ -51,10 +50,10 @@ describe('NumberWidgetComponent', () => { }); it('should show tooltip', async () => { - const input = await loader.getHarness(MatInputHarness); - await (await input.host()).hover(); + const host = await testingUtils.getMatInputHost(); + await host.hover(); - const tooltip = await (await input.host()).getAttribute('title'); + const tooltip = await host.getAttribute('title'); expect(tooltip).toBe('my custom tooltip'); }); }); @@ -69,16 +68,15 @@ describe('NumberWidgetComponent', () => { }); it('should be marked as invalid after interaction', async () => { - const input = await loader.getHarness(MatInputHarness); - expect(fixture.nativeElement.querySelector('.adf-invalid')).toBeFalsy(); + expect(testingUtils.getByCSS('.adf-invalid')).toBeFalsy(); - await (await input.host()).blur(); + await testingUtils.blurMatInput(); - expect(fixture.nativeElement.querySelector('.adf-invalid')).toBeTruthy(); + expect(testingUtils.getByCSS('.adf-invalid')).toBeTruthy(); }); it('should be able to display label with asterisk', async () => { - const asterisk = element.querySelector('.adf-asterisk'); + const asterisk = testingUtils.getByCSS('.adf-asterisk').nativeElement; expect(asterisk).toBeTruthy(); expect(asterisk.textContent).toEqual('*'); @@ -99,10 +97,10 @@ describe('NumberWidgetComponent', () => { fixture.detectChanges(); await fixture.whenStable(); - const widgetContainer = element.querySelector('.adf-left-label-input-container'); + const widgetContainer = testingUtils.getByCSS('.adf-left-label-input-container'); expect(widgetContainer).not.toBeNull(); - const adfLeftLabel = element.querySelector('.adf-left-label'); + const adfLeftLabel = testingUtils.getByCSS('.adf-left-label'); expect(adfLeftLabel).not.toBeNull(); }); @@ -119,10 +117,10 @@ describe('NumberWidgetComponent', () => { fixture.detectChanges(); await fixture.whenStable(); - const widgetContainer = element.querySelector('.adf-left-label-input-container'); + const widgetContainer = testingUtils.getByCSS('.adf-left-label-input-container'); expect(widgetContainer).toBeNull(); - const adfLeftLabel = element.querySelector('.adf-left-label'); + const adfLeftLabel = testingUtils.getByCSS('.adf-left-label'); expect(adfLeftLabel).toBeNull(); }); @@ -139,10 +137,10 @@ describe('NumberWidgetComponent', () => { fixture.detectChanges(); await fixture.whenStable(); - const widgetContainer = element.querySelector('.adf-left-label-input-container'); + const widgetContainer = testingUtils.getByCSS('.adf-left-label-input-container'); expect(widgetContainer).toBeNull(); - const adfLeftLabel = element.querySelector('.adf-left-label'); + const adfLeftLabel = testingUtils.getByCSS('.adf-left-label'); expect(adfLeftLabel).toBeNull(); }); }); diff --git a/lib/core/src/lib/form/components/widgets/text/text.widget.spec.ts b/lib/core/src/lib/form/components/widgets/text/text.widget.spec.ts index abe5b0faa8..f6015fcded 100644 --- a/lib/core/src/lib/form/components/widgets/text/text.widget.spec.ts +++ b/lib/core/src/lib/form/components/widgets/text/text.widget.spec.ts @@ -22,9 +22,9 @@ import { FormModel } from '../core/form.model'; import { TextWidgetComponent } from './text.widget'; import { HarnessLoader } from '@angular/cdk/testing'; import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed'; -import { MatInputHarness } from '@angular/material/input/testing'; import { NoopAnimationsModule } from '@angular/platform-browser/animations'; -import { NoopTranslateModule } from '@alfresco/adf-core'; +import { NoopTranslateModule } from '../../../../testing/noop-translate.module'; +import { UnitTestingUtils } from '../../../../testing/unit-testing-utils'; describe('TextWidgetComponent', () => { const form = new FormModel({ taskId: 'fake-task-id' }); @@ -32,8 +32,8 @@ describe('TextWidgetComponent', () => { let loader: HarnessLoader; let widget: TextWidgetComponent; let fixture: ComponentFixture; - let element: HTMLElement; let errorWidget: HTMLElement; + let testingUtils: UnitTestingUtils; beforeEach(() => { TestBed.configureTestingModule({ @@ -41,8 +41,8 @@ describe('TextWidgetComponent', () => { }); fixture = TestBed.createComponent(TextWidgetComponent); widget = fixture.componentInstance; - element = fixture.nativeElement; loader = TestbedHarnessEnvironment.loader(fixture); + testingUtils = new UnitTestingUtils(fixture.debugElement, loader); }); describe('when template is ready', () => { @@ -59,8 +59,7 @@ describe('TextWidgetComponent', () => { fixture.detectChanges(); expect(widget.field.value).toBe(''); - const input = await loader.getHarness(MatInputHarness); - await input.setValue('TEXT'); + await testingUtils.fillMatInput('TEXT'); expect(widget.field.value).toBe('TEXT'); }); @@ -75,8 +74,7 @@ describe('TextWidgetComponent', () => { }); fixture.detectChanges(); - const textWidgetLabel = element.querySelector('label'); - expect(textWidgetLabel.innerText).toBe('text-name'); + expect(testingUtils.getInnerTextByCSS('label')).toBe('text-name'); }); it('should be able to set a placeholder for Text widget', async () => { @@ -91,8 +89,7 @@ describe('TextWidgetComponent', () => { fixture.detectChanges(); await fixture.whenStable(); - const inputField = await loader.getHarness(MatInputHarness.with({ placeholder: 'Your name here' })); - expect(inputField).toBeTruthy(); + expect(await testingUtils.getMatInputByPlaceholder('Your name here')).toBeTruthy(); }); it('should be able to set min/max length properties for Text widget', async () => { @@ -107,22 +104,21 @@ describe('TextWidgetComponent', () => { }); fixture.detectChanges(); - const input = await loader.getHarness(MatInputHarness); - await input.setValue('TEXT'); + await testingUtils.fillMatInput('TEXT'); - errorWidget = element.querySelector('.adf-error-text'); + errorWidget = testingUtils.getByCSS('.adf-error-text').nativeElement; expect(errorWidget.innerHTML).toBe('FORM.FIELD.VALIDATOR.AT_LEAST_LONG'); expect(widget.field.isValid).toBe(false); - await input.setValue('TEXT VALUE'); + await testingUtils.fillMatInput('TEXT VALUE'); - errorWidget = element.querySelector('.adf-error-text'); + errorWidget = testingUtils.getByCSS('.adf-error-text')?.nativeElement; expect(widget.field.isValid).toBe(true); - await input.setValue('TEXT VALUE TOO LONG'); + await testingUtils.fillMatInput('TEXT VALUE TOO LONG'); expect(widget.field.isValid).toBe(false); - errorWidget = element.querySelector('.adf-error-text'); + errorWidget = testingUtils.getByCSS('.adf-error-text').nativeElement; expect(errorWidget.innerHTML).toBe('FORM.FIELD.VALIDATOR.NO_LONGER_THAN'); }); @@ -137,14 +133,13 @@ describe('TextWidgetComponent', () => { }); fixture.detectChanges(); - const input = await loader.getHarness(MatInputHarness); - await input.setValue('TEXT'); + await testingUtils.fillMatInput('TEXT'); expect(widget.field.isValid).toBe(false); - await input.setValue('8'); + await testingUtils.fillMatInput('8'); expect(widget.field.isValid).toBe(true); - await input.setValue('8XYZ'); + await testingUtils.fillMatInput('8XYZ'); expect(widget.field.isValid).toBe(false); }); }); @@ -159,10 +154,10 @@ describe('TextWidgetComponent', () => { }); it('should show tooltip', async () => { - const input = await loader.getHarness(MatInputHarness); - await (await input.host()).hover(); + const host = await testingUtils.getMatInputHost(); + await host.hover(); - const tooltip = await (await input.host()).getAttribute('title'); + const tooltip = await host.getAttribute('title'); expect(tooltip).toBe('my custom tooltip'); }); }); @@ -180,19 +175,18 @@ describe('TextWidgetComponent', () => { }); it('should be marked as invalid after interaction', async () => { - const input = await loader.getHarness(MatInputHarness); - expect(fixture.nativeElement.querySelector('.adf-invalid')).toBeFalsy(); + expect(testingUtils.getByCSS('.adf-invalid')).toBeFalsy(); - await (await input.host()).blur(); + await testingUtils.blurMatInput(); - expect(fixture.nativeElement.querySelector('.adf-invalid')).toBeTruthy(); + expect(testingUtils.getByCSS('.adf-invalid')).toBeTruthy(); }); it('should be able to display label with asterisk', async () => { fixture.detectChanges(); await fixture.whenStable(); - const asterisk = element.querySelector('.adf-asterisk'); + const asterisk = testingUtils.getByCSS('.adf-asterisk').nativeElement; expect(asterisk).toBeTruthy(); expect(asterisk.textContent).toEqual('*'); @@ -213,7 +207,7 @@ describe('TextWidgetComponent', () => { }); it('should be disabled on readonly forms', async () => { - const input = await loader.getHarness(MatInputHarness); + const input = await testingUtils.getMatInput(); expect(await input.isDisabled()).toBe(true); }); }); @@ -233,28 +227,25 @@ describe('TextWidgetComponent', () => { }); fixture.detectChanges(); - inputElement = element.querySelector('#text-id'); + inputElement = testingUtils.getByCSS('#text-id').nativeElement; }); it('should show text widget', async () => { - expect(await loader.hasHarness(MatInputHarness)).toBe(true); + expect(await testingUtils.checkIfMatInputExists()).toBe(true); }); it('should show the field placeholder', async () => { - const inputField = await loader.getHarness(MatInputHarness.with({ placeholder: 'simple placeholder' })); - expect(inputField).toBeTruthy(); + expect(await testingUtils.checkIfMatInputExistsWithPlaceholder('simple placeholder')).toBeTrue(); }); it('should show the field placeholder when clicked', async () => { - const input = await loader.getHarness(MatInputHarness); - await (await input.host()).click(); + await testingUtils.clickMatInput(); - const inputField = await loader.getHarness(MatInputHarness.with({ placeholder: 'simple placeholder' })); - expect(inputField).toBeTruthy(); + expect(await testingUtils.checkIfMatInputExistsWithPlaceholder('simple placeholder')).toBeTruthy(); }); it('should prevent text to be written if is not allowed by the mask on keyUp event', async () => { - expect(element.querySelector('#text-id')).not.toBeNull(); + expect(testingUtils.getByCSS('#text-id')).not.toBeNull(); inputElement.value = 'F'; widget.field.value = 'F'; @@ -265,12 +256,11 @@ describe('TextWidgetComponent', () => { fixture.detectChanges(); await fixture.whenStable(); - inputElement = element.querySelector('#text-id'); - expect(inputElement.value).toBe(''); + expect(testingUtils.getByCSS('#text-id').nativeElement.value).toBe(''); }); it('should prevent text to be written if is not allowed by the mask on input event', async () => { - expect(element.querySelector('#text-id')).not.toBeNull(); + expect(testingUtils.getByCSS('#text-id')).not.toBeNull(); inputElement.value = 'F'; widget.field.value = 'F'; @@ -279,15 +269,14 @@ describe('TextWidgetComponent', () => { fixture.detectChanges(); await fixture.whenStable(); - inputElement = element.querySelector('#text-id'); - expect(inputElement.value).toBe(''); + expect(testingUtils.getByCSS('#text-id').nativeElement.value).toBe(''); }); it('should allow masked configured value on keyUp event', async () => { fixture.detectChanges(); await fixture.whenStable(); - expect(element.querySelector('#text-id')).not.toBeNull(); + expect(testingUtils.getByCSS('#text-id')).not.toBeNull(); inputElement.value = '1'; widget.field.value = '1'; @@ -298,15 +287,14 @@ describe('TextWidgetComponent', () => { fixture.detectChanges(); await fixture.whenStable(); - const textEle = element.querySelector('#text-id'); - expect(textEle.value).toBe('1'); + expect(testingUtils.getByCSS('#text-id').nativeElement.value).toBe('1'); }); it('should auto-fill masked configured value on keyUp event', async () => { fixture.detectChanges(); await fixture.whenStable(); - expect(element.querySelector('#text-id')).not.toBeNull(); + expect(testingUtils.getByCSS('#text-id')).not.toBeNull(); inputElement.value = '12345678'; widget.field.value = '12345678'; @@ -317,8 +305,7 @@ describe('TextWidgetComponent', () => { fixture.detectChanges(); await fixture.whenStable(); - const textEle = element.querySelector('#text-id'); - expect(textEle.value).toBe('12-345,67%'); + expect(testingUtils.getByCSS('#text-id').nativeElement.value).toBe('12-345,67%'); }); }); @@ -336,7 +323,7 @@ describe('TextWidgetComponent', () => { }); fixture.detectChanges(); - inputElement = element.querySelector('#text-id'); + inputElement = testingUtils.getByCSS('#text-id').nativeElement; }); afterEach(() => { @@ -348,7 +335,7 @@ describe('TextWidgetComponent', () => { fixture.detectChanges(); await fixture.whenStable(); - expect(element.querySelector('#text-id')).not.toBeNull(); + expect(testingUtils.getByCSS('#text-id')).not.toBeNull(); inputElement.value = '1234'; widget.field.value = '1234'; @@ -359,8 +346,7 @@ describe('TextWidgetComponent', () => { fixture.detectChanges(); await fixture.whenStable(); - const textEle = element.querySelector('#text-id'); - expect(textEle.value).toBe('12,34%'); + expect(testingUtils.getByCSS('#text-id').nativeElement.value).toBe('12,34%'); }); }); @@ -380,16 +366,13 @@ describe('TextWidgetComponent', () => { }); it('should show the input mask placeholder', async () => { - const inputField = await loader.getHarness(MatInputHarness.with({ placeholder: 'Phone : (__) ___-___' })); - expect(inputField).toBeTruthy(); + expect(await testingUtils.checkIfMatInputExistsWithPlaceholder('Phone : (__) ___-___')).toBeTrue(); }); it('should show the input mask placeholder when clicked', async () => { - const input = await loader.getHarness(MatInputHarness); - await (await input.host()).click(); + await testingUtils.clickMatInput(); - const inputField = await loader.getHarness(MatInputHarness.with({ placeholder: 'Phone : (__) ___-___' })); - expect(inputField).toBeTruthy(); + expect(await testingUtils.checkIfMatInputExistsWithPlaceholder('Phone : (__) ___-___')).toBeTrue(); }); }); @@ -407,10 +390,10 @@ describe('TextWidgetComponent', () => { fixture.detectChanges(); await fixture.whenStable(); - const widgetContainer = element.querySelector('.adf-left-label-input-container'); + const widgetContainer = testingUtils.getByCSS('.adf-left-label-input-container'); expect(widgetContainer).not.toBeNull(); - const adfLeftLabel = element.querySelector('.adf-left-label'); + const adfLeftLabel = testingUtils.getByCSS('.adf-left-label'); expect(adfLeftLabel).not.toBeNull(); }); @@ -427,10 +410,10 @@ describe('TextWidgetComponent', () => { fixture.detectChanges(); await fixture.whenStable(); - const widgetContainer = element.querySelector('.adf-left-label-input-container'); + const widgetContainer = testingUtils.getByCSS('.adf-left-label-input-container'); expect(widgetContainer).toBeNull(); - const adfLeftLabel = element.querySelector('.adf-left-label'); + const adfLeftLabel = testingUtils.getByCSS('.adf-left-label'); expect(adfLeftLabel).toBeNull(); }); @@ -447,10 +430,10 @@ describe('TextWidgetComponent', () => { fixture.detectChanges(); await fixture.whenStable(); - const widgetContainer = element.querySelector('.adf-left-label-input-container'); + const widgetContainer = testingUtils.getByCSS('.adf-left-label-input-container'); expect(widgetContainer).toBeNull(); - const adfLeftLabel = element.querySelector('.adf-left-label'); + const adfLeftLabel = testingUtils.getByCSS('.adf-left-label'); expect(adfLeftLabel).toBeNull(); }); }); diff --git a/lib/core/src/lib/header/header.component.spec.ts b/lib/core/src/lib/header/header.component.spec.ts index a7f9e86dd2..8ad1798e25 100644 --- a/lib/core/src/lib/header/header.component.spec.ts +++ b/lib/core/src/lib/header/header.component.spec.ts @@ -18,13 +18,15 @@ import { ComponentFixture, TestBed } from '@angular/core/testing'; import { CommonModule } from '@angular/common'; import { HeaderComponent } from './header.component'; +import { UnitTestingUtils } from '../testing'; describe('HeaderComponent', () => { let component: HeaderComponent; let fixture: ComponentFixture; + let testingUtils: UnitTestingUtils; - const getLogoImgElement = () => fixture.nativeElement.querySelector('.adf-toolbar-logo'); - const getTitleElement = () => fixture.nativeElement.querySelector('.adf-toolbar-title'); + const getLogoImgElement = () => testingUtils.getByCSS('.adf-toolbar-logo')?.nativeElement; + const getTitleElement = () => testingUtils.getByCSS('.adf-toolbar-title')?.nativeElement; beforeEach(async () => { await TestBed.configureTestingModule({ @@ -33,6 +35,7 @@ describe('HeaderComponent', () => { fixture = TestBed.createComponent(HeaderComponent); component = fixture.componentInstance; + testingUtils = new UnitTestingUtils(fixture.debugElement); fixture.detectChanges(); }); diff --git a/lib/core/src/lib/header/navbar/navbar-item.component.spec.ts b/lib/core/src/lib/header/navbar/navbar-item.component.spec.ts index 07032ab223..e60e9e23fe 100644 --- a/lib/core/src/lib/header/navbar/navbar-item.component.spec.ts +++ b/lib/core/src/lib/header/navbar/navbar-item.component.spec.ts @@ -18,11 +18,13 @@ import { ComponentFixture, TestBed } from '@angular/core/testing'; import { RouterTestingModule } from '@angular/router/testing'; import { NavbarItemComponent } from './navbar-item.component'; +import { UnitTestingUtils } from '../../testing/unit-testing-utils'; describe('NavbarItemComponent', () => { let component: NavbarItemComponent; let fixture: ComponentFixture; let button: HTMLElement; + let testingUtils: UnitTestingUtils; beforeEach(async () => { await TestBed.configureTestingModule({ @@ -31,11 +33,12 @@ describe('NavbarItemComponent', () => { fixture = TestBed.createComponent(NavbarItemComponent); component = fixture.componentInstance; + testingUtils = new UnitTestingUtils(fixture.debugElement); component.label = 'Test Label'; component.routerLink = '/expected-route'; fixture.detectChanges(); - button = fixture.nativeElement.querySelector('.adf-navbar-item-btn'); + button = testingUtils.getByCSS('.adf-navbar-item-btn').nativeElement; }); it('should display label', () => { diff --git a/lib/core/src/lib/header/navbar/navbar.component.spec.ts b/lib/core/src/lib/header/navbar/navbar.component.spec.ts index feb3d81d00..5799104686 100644 --- a/lib/core/src/lib/header/navbar/navbar.component.spec.ts +++ b/lib/core/src/lib/header/navbar/navbar.component.spec.ts @@ -20,10 +20,12 @@ import { MatButtonModule } from '@angular/material/button'; import { CommonModule } from '@angular/common'; import { RouterModule } from '@angular/router'; import { NavbarComponent } from './navbar.component'; +import { UnitTestingUtils } from '../../testing/unit-testing-utils'; describe('NavbarComponent', () => { let component: NavbarComponent; let fixture: ComponentFixture; + let testingUtils: UnitTestingUtils; beforeEach(async () => { await TestBed.configureTestingModule({ @@ -32,6 +34,7 @@ describe('NavbarComponent', () => { fixture = TestBed.createComponent(NavbarComponent); component = fixture.componentInstance; + testingUtils = new UnitTestingUtils(fixture.debugElement); fixture.detectChanges(); }); @@ -42,7 +45,7 @@ describe('NavbarComponent', () => { ]; component.items = testItems; fixture.detectChanges(); - const renderedItems = fixture.nativeElement.querySelectorAll('.adf-navbar-item-btn'); + const renderedItems = testingUtils.getAllByCSS('.adf-navbar-item-btn'); expect(renderedItems.length).toBe(testItems.length); }); @@ -53,7 +56,7 @@ describe('NavbarComponent', () => { ]; component.items = testItems; fixture.detectChanges(); - const renderedItems = fixture.nativeElement.querySelectorAll('.adf-navbar-item-btn'); + const renderedItems = testingUtils.getAllByCSS('.adf-navbar-item-btn').map((item) => item.nativeElement); testItems.forEach((item, index) => { expect(renderedItems[index].textContent).toContain(item.label); expect(renderedItems[index].getAttribute('ng-reflect-router-link')).toContain(item.routerLink); diff --git a/lib/core/src/lib/identity-user-info/identity-user-info.component.spec.ts b/lib/core/src/lib/identity-user-info/identity-user-info.component.spec.ts index 5ea8a85132..5b069d982a 100644 --- a/lib/core/src/lib/identity-user-info/identity-user-info.component.spec.ts +++ b/lib/core/src/lib/identity-user-info/identity-user-info.component.spec.ts @@ -19,13 +19,13 @@ import { ComponentFixture, TestBed } from '@angular/core/testing'; import { IdentityUserInfoComponent } from './identity-user-info.component'; import { CoreTestingModule } from '../testing/core.testing.module'; import { MatMenuModule } from '@angular/material/menu'; -import { By } from '@angular/platform-browser'; import { IdentityUserModel } from '../auth/models/identity-user.model'; +import { UnitTestingUtils } from '../testing/unit-testing-utils'; describe('IdentityUserInfoComponent', () => { let component: IdentityUserInfoComponent; let fixture: ComponentFixture; - let element: HTMLElement; + let testingUtils: UnitTestingUtils; const identityUserMock = { firstName: 'fake-identity-first-name', @@ -55,7 +55,7 @@ describe('IdentityUserInfoComponent', () => { }); fixture = TestBed.createComponent(IdentityUserInfoComponent); component = fixture.componentInstance; - element = fixture.nativeElement; + testingUtils = new UnitTestingUtils(fixture.debugElement); spyOn(window, 'requestAnimationFrame').and.returnValue(1); }); @@ -65,15 +65,15 @@ describe('IdentityUserInfoComponent', () => { }); it('should not show any image if the user is not logged in', () => { - expect(element.querySelector('#userinfo_container')).toBeDefined(); - expect(element.querySelector('#logged-user-img')).toBeNull(); + expect(testingUtils.getByCSS('#userinfo_container')).toBeDefined(); + expect(testingUtils.getByCSS('#logged-user-img')).toBeNull(); }); it('should NOT have users immediately after ngOnInit', () => { - expect(element.querySelector('#userinfo_container')).toBeDefined(); - expect(element.querySelector('#ecm_username')).toBeNull(); - expect(element.querySelector('#bpm_username')).toBeNull(); - expect(element.querySelector('#user-profile-lists')).toBeNull(); + expect(testingUtils.getByCSS('#userinfo_container')).toBeDefined(); + expect(testingUtils.getByCSS('#ecm_username')).toBeNull(); + expect(testingUtils.getByCSS('#bpm_username')).toBeNull(); + expect(testingUtils.getByCSS('#user-profile-lists')).toBeNull(); }); describe('when identity user is logged in', () => { @@ -84,21 +84,21 @@ describe('IdentityUserInfoComponent', () => { it('should show the identity user initials', async () => { await whenFixtureReady(); - expect(element.querySelector('#userinfo_container')).toBeDefined(); - expect(element.querySelector('[data-automation-id="user-initials-image"]')?.textContent).toContain('ff'); + expect(testingUtils.getByCSS('#userinfo_container')).toBeDefined(); + expect(testingUtils.getByDataAutomationId('user-initials-image')?.nativeElement?.textContent).toContain('ff'); }); it('should show full name next to the user image', async () => { await whenFixtureReady(); - const imageButton = element.querySelector('#identity-user-image'); + const imageButton: HTMLButtonElement = fixture.nativeElement.querySelector('#identity-user-image'); imageButton?.click(); fixture.detectChanges(); - expect(element.querySelector('#userinfo_container')).not.toBeNull(); + expect(testingUtils.getByCSS('#userinfo_container')).not.toBeNull(); - const identityUserName = fixture.debugElement.query(By.css('#identity-username')); + const identityUserName = testingUtils.getByCSS('#identity-username'); expect(identityUserName).toBeDefined(); expect(identityUserName).not.toBeNull(); expect(identityUserName.nativeElement.textContent).toContain('fake-identity-first-name fake-identity-last-name'); @@ -108,35 +108,35 @@ describe('IdentityUserInfoComponent', () => { component.identityUser = identityUserWithOutFirstNameMock; await whenFixtureReady(); - const fullNameElement = element.querySelector('#adf-userinfo-identity-name-display'); - expect(element.querySelector('#userinfo_container')).toBeDefined(); - expect(element.querySelector('#adf-userinfo-identity-name-display')).not.toBeNull(); - expect(fullNameElement?.textContent).toContain('fake-identity-last-name'); - expect(fullNameElement?.textContent).not.toContain('fake-identity-first-name'); + const fullNameElement = testingUtils.getByCSS('#adf-userinfo-identity-name-display'); + expect(testingUtils.getByCSS('#userinfo_container')).toBeDefined(); + expect(testingUtils.getByCSS('#adf-userinfo-identity-name-display')).not.toBeNull(); + expect(fullNameElement?.nativeElement?.textContent).toContain('fake-identity-last-name'); + expect(fullNameElement?.nativeElement?.textContent).not.toContain('fake-identity-first-name'); }); it('should not show first name if it is null string', async () => { component.identityUser = identityUserWithOutFirstNameMock; await whenFixtureReady(); - const fullNameElement = element.querySelector('#adf-userinfo-identity-name-display'); + const fullNameElement = testingUtils.getByCSS('#adf-userinfo-identity-name-display'); fixture.detectChanges(); - expect(element.querySelector('#userinfo_container')).toBeDefined(); + expect(testingUtils.getByCSS('#userinfo_container')).toBeDefined(); expect(fullNameElement).toBeDefined(); - expect(fullNameElement?.textContent).toContain('fake-identity-last-name'); - expect(fullNameElement?.textContent).not.toContain('null'); + expect(fullNameElement?.nativeElement?.textContent).toContain('fake-identity-last-name'); + expect(fullNameElement?.nativeElement?.textContent).not.toContain('null'); }); it('should not show last name if it is null string', async () => { component.identityUser = identityUserWithOutLastNameMock; await whenFixtureReady(); - const fullNameElement = element.querySelector('#adf-userinfo-identity-name-display'); + const fullNameElement = testingUtils.getByCSS('#adf-userinfo-identity-name-display'); fixture.detectChanges(); - expect(element.querySelector('#userinfo_container')).toBeDefined(); + expect(testingUtils.getByCSS('#userinfo_container')).toBeDefined(); expect(fullNameElement).toBeDefined(); - expect(fullNameElement?.textContent).toContain('fake-identity-first-name'); - expect(fullNameElement?.textContent).not.toContain('null'); + expect(fullNameElement?.nativeElement?.textContent).toContain('fake-identity-first-name'); + expect(fullNameElement?.nativeElement?.textContent).not.toContain('null'); }); }); }); diff --git a/lib/core/src/lib/info-drawer/info-drawer.component.spec.ts b/lib/core/src/lib/info-drawer/info-drawer.component.spec.ts index db7c531d7b..ed660bd738 100644 --- a/lib/core/src/lib/info-drawer/info-drawer.component.spec.ts +++ b/lib/core/src/lib/info-drawer/info-drawer.component.spec.ts @@ -18,19 +18,18 @@ import { Component } from '@angular/core'; import { ComponentFixture, TestBed } from '@angular/core/testing'; import { MatTabChangeEvent } from '@angular/material/tabs'; -import { By } from '@angular/platform-browser'; import { InfoDrawerComponent, InfoDrawerTabComponent } from './info-drawer.component'; import { ESCAPE } from '@angular/cdk/keycodes'; import { HarnessLoader } from '@angular/cdk/testing'; import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed'; -import { MatTabGroupHarness } from '@angular/material/tabs/testing'; -import { NoopTranslateModule } from '@alfresco/adf-core'; import { NoopAnimationsModule } from '@angular/platform-browser/animations'; +import { NoopTranslateModule } from '../testing/noop-translate.module'; +import { UnitTestingUtils } from '../testing/unit-testing-utils'; describe('InfoDrawerComponent', () => { - let element: HTMLElement; let component: InfoDrawerComponent; let fixture: ComponentFixture; + let testingUtils: UnitTestingUtils; beforeEach(() => { TestBed.configureTestingModule({ @@ -38,12 +37,12 @@ describe('InfoDrawerComponent', () => { }); fixture = TestBed.createComponent(InfoDrawerComponent); - element = fixture.nativeElement; component = fixture.componentInstance; + testingUtils = new UnitTestingUtils(fixture.debugElement); }); it('should define InfoDrawerTabLayout', () => { - const infoDrawerTabLayout = element.querySelector('adf-info-drawer-layout'); + const infoDrawerTabLayout = testingUtils.getByCSS('adf-info-drawer-layout'); expect(infoDrawerTabLayout).toBeDefined(); }); @@ -57,7 +56,7 @@ describe('InfoDrawerComponent', () => { it('should render the title', () => { component.title = 'FakeTitle'; fixture.detectChanges(); - const title: any = fixture.debugElement.queryAll(By.css('[info-drawer-title]')); + const title = testingUtils.getAllByCSS('[info-drawer-title]'); expect(title.length).toBe(1); expect(title[0].nativeElement.innerText).toBe('FakeTitle'); }); @@ -101,8 +100,9 @@ describe('Custom InfoDrawer', () => { let fixture: ComponentFixture; let component: CustomInfoDrawerComponent; let loader: HarnessLoader; + let testingUtils: UnitTestingUtils; - const getNodeIcon = () => fixture.debugElement.queryAll(By.css('[info-drawer-node-icon]')); + const getNodeIcon = () => testingUtils.getAllByCSS('[info-drawer-node-icon]'); beforeEach(() => { TestBed.configureTestingModule({ @@ -113,6 +113,7 @@ describe('Custom InfoDrawer', () => { fixture.detectChanges(); component = fixture.componentInstance; loader = TestbedHarnessEnvironment.loader(fixture); + testingUtils = new UnitTestingUtils(fixture.debugElement, loader); }); afterEach(() => { @@ -121,36 +122,30 @@ describe('Custom InfoDrawer', () => { it('should render the title', () => { fixture.detectChanges(); - const title: any = fixture.debugElement.queryAll(By.css('[info-drawer-title]')); + const title = testingUtils.getAllByCSS('[info-drawer-title]'); expect(title.length).toBe(1); expect(title[0].nativeElement.innerText).toBe('Fake Title Custom'); }); it('should select the tab 1 (index 0) as default', async () => { fixture.detectChanges(); - const tabs = await loader.getHarness(MatTabGroupHarness); - const selectedTab = await tabs.getSelectedTab(); - expect(await selectedTab.getLabel()).toEqual('Tab1'); + expect(await testingUtils.getSelectedTabLabelFromMatTabGroup()).toEqual('Tab1'); }); it('should select the tab 2 (index 1)', async () => { component.tabIndex = 1; fixture.detectChanges(); - const tabs = await loader.getHarness(MatTabGroupHarness); - const selectedTab = await tabs.getSelectedTab(); - expect(await selectedTab.getLabel()).toEqual('Tab2'); + expect(await testingUtils.getSelectedTabLabelFromMatTabGroup()).toEqual('Tab2'); }); it('should render a tab with icon', async () => { component.tabIndex = 2; fixture.detectChanges(); - const tabs = await loader.getHarness(MatTabGroupHarness); - const selectedTab = await tabs.getSelectedTab(); - expect(await selectedTab.getLabel()).toContain('Tab3'); - expect(await selectedTab.getLabel()).toContain('tab-icon'); + expect(await testingUtils.getSelectedTabLabelFromMatTabGroup()).toContain('Tab3'); + expect(await testingUtils.getSelectedTabLabelFromMatTabGroup()).toContain('tab-icon'); }); it('should render a icon with title', () => { @@ -176,7 +171,8 @@ class VisibilityInfoDrawerComponent extends InfoDrawerComponent { describe('Header visibility InfoDrawer', () => { let fixture: ComponentFixture; let component: VisibilityInfoDrawerComponent; - const getNodeIcon = () => fixture.debugElement.queryAll(By.css('[info-drawer-node-icon]')); + let testingUtils: UnitTestingUtils; + const getNodeIcon = () => testingUtils.getAllByCSS('[info-drawer-node-icon]'); beforeEach(() => { TestBed.configureTestingModule({ @@ -185,12 +181,13 @@ describe('Header visibility InfoDrawer', () => { fixture = TestBed.createComponent(VisibilityInfoDrawerComponent); fixture.detectChanges(); component = fixture.componentInstance; + testingUtils = new UnitTestingUtils(fixture.debugElement); }); it('should show info drawer header by default', () => { component.icon = '/assets/images/ft_ic_miscellaneous.svg'; fixture.detectChanges(); - const title: any = fixture.debugElement.queryAll(By.css('[info-drawer-title]')); + const title = testingUtils.getAllByCSS('[info-drawer-title]'); const icon = getNodeIcon(); const srcAttribute = icon[0].nativeElement.getAttribute('src'); expect(title.length).toBe(1); @@ -203,7 +200,7 @@ describe('Header visibility InfoDrawer', () => { it('should not show info drawer header with icon when showHeader is false', () => { component.showHeader = false; fixture.detectChanges(); - const title: any = fixture.debugElement.queryAll(By.css('[info-drawer-title]')); + const title = testingUtils.getAllByCSS('[info-drawer-title]'); const icon = getNodeIcon(); expect(title.length).toBe(0); expect(icon.length).toBe(0); diff --git a/lib/core/src/lib/layout/components/header/header.component.spec.ts b/lib/core/src/lib/layout/components/header/header.component.spec.ts index 3030653b8c..50e97a607f 100644 --- a/lib/core/src/lib/layout/components/header/header.component.spec.ts +++ b/lib/core/src/lib/layout/components/header/header.component.spec.ts @@ -18,16 +18,16 @@ import { ComponentFixture, TestBed } from '@angular/core/testing'; import { HeaderLayoutComponent } from './header.component'; import { CoreTestingModule } from '../../../testing/core.testing.module'; -import { By } from '@angular/platform-browser'; import { Component } from '@angular/core'; import { HarnessLoader } from '@angular/cdk/testing'; import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed'; -import { MatToolbarHarness } from '@angular/material/toolbar/testing'; +import { UnitTestingUtils } from '../../../testing/unit-testing-utils'; describe('HeaderLayoutComponent', () => { let loader: HarnessLoader; let fixture: ComponentFixture; let component: HeaderLayoutComponent; + let testingUtils: UnitTestingUtils; describe('Input parameters', () => { beforeEach(() => { @@ -37,6 +37,7 @@ describe('HeaderLayoutComponent', () => { fixture = TestBed.createComponent(HeaderLayoutComponent); loader = TestbedHarnessEnvironment.loader(fixture); component = fixture.componentInstance; + testingUtils = new UnitTestingUtils(fixture.debugElement, loader); }); afterEach(() => { @@ -44,24 +45,21 @@ describe('HeaderLayoutComponent', () => { }); it('title element should been displayed', () => { - const titleElement = fixture.debugElement.query(By.css('.adf-app-title')); - expect(titleElement === null).toBeFalsy(); + expect(testingUtils.getByCSS('.adf-app-title')).toBeDefined(); }); it('should show TEST TITLE', () => { component.title = 'TEST TITLE'; fixture.detectChanges(); - const titleElement = fixture.nativeElement.querySelector('.adf-app-title'); - expect(titleElement.innerText).toEqual('TEST TITLE'); + expect(testingUtils.getInnerTextByCSS('.adf-app-title')).toEqual('TEST TITLE'); }); it('color attribute should be present on toolbar', async () => { component.color = 'primary'; fixture.detectChanges(); - const toolbar = await loader.getHarness(MatToolbarHarness); - const host = await toolbar.host(); + const host = await testingUtils.getMatToolbarHost(); expect(await host.getAttribute('ng-reflect-color')).toBe('primary'); }); @@ -70,17 +68,17 @@ describe('HeaderLayoutComponent', () => { component.color = '#42f57e'; fixture.detectChanges(); - const toolbarHarness = await loader.getHarness(MatToolbarHarness); - const toolbar = await toolbarHarness.host(); - expect(await toolbar.getCssValue('background-color')).toBe('rgb(66, 245, 126)'); + const host = await testingUtils.getMatToolbarHost(); + + expect(await host.getCssValue('background-color')).toBe('rgb(66, 245, 126)'); }); it('should background image be set to none if is not provided', async () => { fixture.detectChanges(); - const toolbarHarness = await loader.getHarness(MatToolbarHarness); - const toolbar = await toolbarHarness.host(); - expect(await toolbar.getCssValue('background-image')).toEqual('none'); + const host = await testingUtils.getMatToolbarHost(); + + expect(await host.getCssValue('background-image')).toEqual('none'); }); it('should background image be set to none if is provided as empty string', async () => { @@ -88,25 +86,25 @@ describe('HeaderLayoutComponent', () => { fixture.detectChanges(); - const toolbarHarness = await loader.getHarness(MatToolbarHarness); - const toolbar = await toolbarHarness.host(); - expect(await toolbar.getCssValue('background-image')).toEqual('none'); + const host = await testingUtils.getMatToolbarHost(); + + expect(await host.getCssValue('background-image')).toEqual('none'); }); it('should change background image when provided', async () => { component.backgroundImage = '/assets/someImage.png'; fixture.detectChanges(); - const toolbarHarness = await loader.getHarness(MatToolbarHarness); - const toolbar = await toolbarHarness.host(); - expect(await toolbar.getCssValue('background-image')).toContain('/assets/someImage.png'); + const host = await testingUtils.getMatToolbarHost(); + + expect(await host.getCssValue('background-image')).toContain('/assets/someImage.png'); }); it('should display the img element with the expected src if a logo path is set', () => { component.logo = 'logo.png'; fixture.detectChanges(); - const logo = fixture.nativeElement.querySelector('.adf-app-logo'); + const logo = testingUtils.getByCSS('.adf-app-logo').nativeElement; const src = logo.getAttribute('src'); expect(src).toEqual('logo.png'); }); @@ -115,7 +113,7 @@ describe('HeaderLayoutComponent', () => { component.redirectUrl = '/customHomePage'; fixture.detectChanges(); - const logoAnchor = fixture.nativeElement.querySelector('a'); + const logoAnchor = testingUtils.getByCSS('a').nativeElement; expect(/\/customHomePage$/.test(logoAnchor.href)).toEqual(true); }); @@ -123,7 +121,7 @@ describe('HeaderLayoutComponent', () => { component.tooltip = 'logo title'; fixture.detectChanges(); - const logoAnchor = fixture.nativeElement.querySelector('a'); + const logoAnchor = testingUtils.getByCSS('a').nativeElement; expect(logoAnchor.title).toEqual('logo title'); }); @@ -131,9 +129,8 @@ describe('HeaderLayoutComponent', () => { component.showSidenavToggle = true; fixture.detectChanges(); spyOn(component.clicked, 'emit'); - const button = fixture.nativeElement.querySelector('.adf-menu-icon'); - button.dispatchEvent(new Event('click')); + testingUtils.clickByCSS('.adf-menu-icon'); fixture.detectChanges(); expect(component.clicked.emit).toHaveBeenCalledWith(true); }); @@ -142,23 +139,21 @@ describe('HeaderLayoutComponent', () => { component.showSidenavToggle = true; fixture.detectChanges(); - const button = fixture.nativeElement.querySelector('.adf-menu-icon'); - expect(button === null).toBeFalsy(); + expect(testingUtils.getByCSS('.adf-menu-icon')).toBeDefined(); }); it('if showSidenavToggle is false the button menu should not be displayed', () => { component.showSidenavToggle = false; fixture.detectChanges(); - const button = fixture.nativeElement.querySelector('.adf-menu-icon'); - expect(button === null).toBeTruthy(); + expect(testingUtils.getByCSS('.adf-menu-icon')).toBeNull(); }); it('if expandedSidenav is false aria expanded should be false too', () => { component.expandedSidenav = false; fixture.detectChanges(); - const nodeAttributes = fixture.debugElement.nativeElement.querySelector('#adf-sidebar-toggle-start').attributes as NamedNodeMap; + const nodeAttributes = testingUtils.getByCSS('#adf-sidebar-toggle-start').nativeElement.attributes as NamedNodeMap; expect(nodeAttributes.getNamedItem('aria-expanded').value).toEqual('false'); }); @@ -166,7 +161,7 @@ describe('HeaderLayoutComponent', () => { component.expandedSidenav = true; fixture.detectChanges(); - const nodeAttributes = fixture.debugElement.nativeElement.querySelector('#adf-sidebar-toggle-start').attributes as NamedNodeMap; + const nodeAttributes = testingUtils.getByCSS('#adf-sidebar-toggle-start').nativeElement.attributes as NamedNodeMap; expect(nodeAttributes.getNamedItem('aria-expanded').value).toEqual('true'); }); @@ -174,7 +169,7 @@ describe('HeaderLayoutComponent', () => { component.expandedSidenav = false; fixture.detectChanges(); - const button = fixture.nativeElement.querySelector('#adf-sidebar-toggle-start'); + const button = testingUtils.getByCSS('#adf-sidebar-toggle-start').nativeElement; button.click(); fixture.detectChanges(); @@ -194,45 +189,37 @@ describe('HeaderLayoutComponent', () => { component.position = 'end'; fixture.detectChanges(); - const buttonStart = fixture.nativeElement.querySelector('#adf-sidebar-toggle-start'); - const buttonEnd = fixture.nativeElement.querySelector('#adf-sidebar-toggle-end'); - expect(buttonStart === null).toBeTruthy(); - expect(buttonEnd === null).toBeFalsy(); + expect(testingUtils.getByCSS('#adf-sidebar-toggle-start')).toBeNull(); + expect(testingUtils.getByCSS('#adf-sidebar-toggle-end')).toBeDefined(); }); it('if position is start the button menu should be at the start', () => { component.position = 'start'; fixture.detectChanges(); - const buttonStart = fixture.nativeElement.querySelector('#adf-sidebar-toggle-start'); - const buttonEnd = fixture.nativeElement.querySelector('#adf-sidebar-toggle-end'); - expect(buttonStart === null).toBeFalsy(); - expect(buttonEnd === null).toBeTruthy(); + expect(testingUtils.getByCSS('#adf-sidebar-toggle-start')).toBeDefined(); + expect(testingUtils.getByCSS('#adf-sidebar-toggle-end')).toBeNull(); }); it('should display the logo image when the input is set to true [showLogo=true]', () => { component.showLogo = true; fixture.detectChanges(); - const logo = fixture.debugElement.query(By.css('.adf-app-logo')); - - expect(logo.nativeElement).not.toBeNull(); + expect(testingUtils.getByCSS('.adf-app-logo')).not.toBeNull(); }); it('should NOT display the logo image when the input is set to false [showLogo=false]', () => { component.showLogo = false; fixture.detectChanges(); - const logo = fixture.debugElement.query(By.css('.adf-app-logo')); - - expect(logo).toBeNull(); + expect(testingUtils.getByCSS('.adf-app-logo')).toBeNull(); }); it('should display the default toggle icon', () => { component.showSidenavToggle = true; fixture.detectChanges(); - const toggleIcon = fixture.debugElement.query(By.css('.adf-menu-icon')); + const toggleIcon = testingUtils.getByCSS('.adf-menu-icon'); expect(toggleIcon.nativeElement.textContent.trim()).toBe('menu'); }); @@ -242,7 +229,7 @@ describe('HeaderLayoutComponent', () => { component.toggleIcon = 'apps'; fixture.detectChanges(); - const toggleIcon = fixture.debugElement.query(By.css('.adf-menu-icon')); + const toggleIcon = testingUtils.getByCSS('.adf-menu-icon'); expect(toggleIcon.nativeElement.textContent.trim()).toBe('apps'); }); @@ -268,9 +255,9 @@ describe('HeaderLayoutComponent', () => { it('should project the provided nodes into the component', () => { const hostFixture = TestBed.createComponent(HeaderLayoutTesterComponent); + testingUtils.setDebugElement(hostFixture.debugElement); hostFixture.detectChanges(); - const innerText = hostFixture.nativeElement.querySelector('p').innerText; - expect(innerText).toEqual('Test text'); + expect(testingUtils.getInnerTextByCSS('p')).toEqual('Test text'); }); }); }); diff --git a/lib/core/src/lib/layout/components/sidebar-action/sidebar-action-menu.component.spec.ts b/lib/core/src/lib/layout/components/sidebar-action/sidebar-action-menu.component.spec.ts index 7899fe650c..52a1e5afe0 100644 --- a/lib/core/src/lib/layout/components/sidebar-action/sidebar-action-menu.component.spec.ts +++ b/lib/core/src/lib/layout/components/sidebar-action/sidebar-action-menu.component.spec.ts @@ -22,19 +22,20 @@ import { CoreTestingModule } from '../../../testing/core.testing.module'; import { CommonModule } from '@angular/common'; import { MatIconModule } from '@angular/material/icon'; import { MatMenuModule } from '@angular/material/menu'; +import { UnitTestingUtils } from '../../../testing/unit-testing-utils'; describe('SidebarActionMenuComponent', () => { - let element: HTMLElement; let component: SidebarActionMenuComponent; let fixture: ComponentFixture; + let testingUtils: UnitTestingUtils; beforeEach(() => { TestBed.configureTestingModule({ imports: [CoreTestingModule, SidebarActionMenuComponent] }); fixture = TestBed.createComponent(SidebarActionMenuComponent); - element = fixture.nativeElement; component = fixture.componentInstance; + testingUtils = new UnitTestingUtils(fixture.debugElement); }); afterEach(() => { @@ -45,7 +46,7 @@ describe('SidebarActionMenuComponent', () => { component.title = 'Fake-Title'; component.expanded = true; fixture.detectChanges(); - const title = element.querySelector('.adf-sidebar-action-menu-text'); + const title = testingUtils.getByCSS('.adf-sidebar-action-menu-text').nativeElement; fixture.detectChanges(); expect(title.textContent).toBe('Fake-Title'); }); @@ -81,7 +82,7 @@ class CustomSidebarActionMenuComponent { describe('Custom SidebarActionMenuComponent', () => { let fixture: ComponentFixture; let component: CustomSidebarActionMenuComponent; - let element: HTMLElement; + let testingUtils: UnitTestingUtils; beforeEach(() => { TestBed.configureTestingModule({ @@ -90,43 +91,39 @@ describe('Custom SidebarActionMenuComponent', () => { fixture = TestBed.createComponent(CustomSidebarActionMenuComponent); fixture.detectChanges(); component = fixture.componentInstance; - element = fixture.nativeElement; + testingUtils = new UnitTestingUtils(fixture.debugElement); }); it('should defined adf-sidebar-action-menu', () => { fixture.detectChanges(); - element = fixture.nativeElement.querySelector('adf-sidebar-action-menu'); - expect(element).toBeDefined(); + expect(testingUtils.getByCSS('adf-sidebar-action-menu')).toBeDefined(); }); it('should display the title', () => { component.title = 'FakeTitle'; fixture.detectChanges(); - const title = element.querySelector('.adf-sidebar-action-menu-text'); + const title = testingUtils.getByCSS('.adf-sidebar-action-menu-text').nativeElement; fixture.detectChanges(); expect(title.textContent).toBe('FakeTitle'); }); it('should render the adf-sidebar-menu-options', async () => { fixture.detectChanges(); - const actionButton = fixture.nativeElement.querySelector('.adf-sidebar-action-menu-button'); - const options = fixture.nativeElement.querySelectorAll('.adf-sidebar-action-menu-options'); - actionButton.click(); + const options = testingUtils.getAllByCSS('.adf-sidebar-action-menu-options'); + testingUtils.clickByCSS('.adf-sidebar-action-menu-button'); fixture.detectChanges(); await fixture.whenStable(); - expect(actionButton).not.toBeNull(); - expect(actionButton).toBeDefined(); expect(options).toBeDefined(); - expect(actionButton.innerText.trim()).toBe('Fake titlearrow_drop_down'); + expect(testingUtils.getInnerTextByCSS('.adf-sidebar-action-menu-button').trim()).toBe('Fake titlearrow_drop_down'); }); it('should show icon on icon menu', () => { component.title = 'FakeTitle'; component.expanded = false; fixture.detectChanges(); - const actionIcon = fixture.nativeElement.querySelector('.adf-sidebar-action-menu-icon'); + const actionIcon = testingUtils.getByCSS('.adf-sidebar-action-menu-icon').nativeElement; expect(actionIcon).not.toBeNull(); expect(actionIcon).toBeDefined(); expect(actionIcon.innerText.trim()).toBe('queue'); diff --git a/lib/core/src/lib/layout/components/sidenav-layout/sidenav-layout.component.spec.ts b/lib/core/src/lib/layout/components/sidenav-layout/sidenav-layout.component.spec.ts index fdf60d1f12..d89d41e11d 100644 --- a/lib/core/src/lib/layout/components/sidenav-layout/sidenav-layout.component.spec.ts +++ b/lib/core/src/lib/layout/components/sidenav-layout/sidenav-layout.component.spec.ts @@ -16,7 +16,6 @@ */ import { ComponentFixture, TestBed } from '@angular/core/testing'; -import { By } from '@angular/platform-browser'; import { SidenavLayoutComponent } from './sidenav-layout.component'; import { Component } from '@angular/core'; import { MediaMatcher } from '@angular/cdk/layout'; @@ -27,6 +26,7 @@ import { UserPreferencesService } from '../../../common/services/user-preference import { CommonModule } from '@angular/common'; import { of } from 'rxjs'; import { NoopAnimationsModule } from '@angular/platform-browser/animations'; +import { UnitTestingUtils } from '../../../testing/unit-testing-utils'; @Component({ selector: 'adf-test-component-for-sidenav', @@ -157,6 +157,7 @@ describe('Template transclusion', () => { let fixture: ComponentFixture; let mediaMatcher: MediaMatcher; let mediaQueryList: any; + let testingUtils: UnitTestingUtils; beforeEach(() => { TestBed.configureTestingModule({ @@ -174,53 +175,46 @@ describe('Template transclusion', () => { spyOn(mediaMatcher, 'matchMedia').and.callFake(() => mediaQueryList); fixture = TestBed.createComponent(SidenavLayoutTesterComponent); + testingUtils = new UnitTestingUtils(fixture.debugElement); fixture.detectChanges(); }); describe('adf-sidenav-layout-navigation', () => { - const injectedElementSelector = By.css('[data-automation-id="adf-layout-container"] #nav-test'); + const injectedElementSelector = '[data-automation-id="adf-layout-container"] #nav-test'; it('should contain the transcluded side navigation template', () => { - const injectedElement = fixture.debugElement.query(injectedElementSelector); - - expect(injectedElement === null).toBe(false); + expect(testingUtils.getByCSS(injectedElementSelector)).toBeDefined(); }); it('should let the isMenuMinimized property of component to be accessed by the transcluded template', () => { - const injectedElement = fixture.debugElement.query(injectedElementSelector); - - expect(injectedElement.nativeElement.innerText.trim()).toBe('variable-is-injected'); + expect(testingUtils.getInnerTextByCSS(injectedElementSelector).trim()).toBe('variable-is-injected'); }); }); describe('adf-sidenav-layout-header', () => { - const outerHeaderSelector = By.css('.adf-sidenav-layout-full-space > #header-test'); - const innerHeaderSelector = By.css('.adf-layout__content > #header-test'); + const outerHeaderSelector = '.adf-sidenav-layout-full-space > #header-test'; + const innerHeaderSelector = '.adf-layout__content > #header-test'; it('should contain the transcluded header template outside of the layout-container', () => { mediaQueryList.matches = false; fixture.detectChanges(); - const outerHeaderElement = fixture.debugElement.query(outerHeaderSelector); - expect(outerHeaderElement).toBeDefined(); + expect(testingUtils.getByCSS(outerHeaderSelector)).toBeDefined(); }); it('should contain the transcluded header template inside of the layout-container', () => { mediaQueryList.matches = true; - fixture.detectChanges(); - const innerHeaderElement = fixture.debugElement.query(innerHeaderSelector); - expect(innerHeaderElement).toBeDefined(); + expect(testingUtils.getByCSS(innerHeaderSelector)).toBeDefined(); }); }); describe('adf-sidenav-layout-content', () => { - const injectedElementSelector = By.css('[data-automation-id="adf-layout-container"] #content-test'); + const injectedElementSelector = '[data-automation-id="adf-layout-container"] #content-test'; it('should contain the transcluded content template', () => { - const injectedElement = fixture.debugElement.query(injectedElementSelector); - expect(injectedElement === null).toBe(false); + expect(testingUtils.getByCSS(injectedElementSelector)).toBeDefined(); }); }); }); diff --git a/lib/core/src/lib/login/components/login-dialog-panel/login-dialog-panel.component.spec.ts b/lib/core/src/lib/login/components/login-dialog-panel/login-dialog-panel.component.spec.ts index a0b4d11c45..a2a1f588e5 100644 --- a/lib/core/src/lib/login/components/login-dialog-panel/login-dialog-panel.component.spec.ts +++ b/lib/core/src/lib/login/components/login-dialog-panel/login-dialog-panel.component.spec.ts @@ -15,18 +15,21 @@ * limitations under the License. */ -import { BasicAlfrescoAuthService, CoreTestingModule, LoginDialogPanelComponent } from '@alfresco/adf-core'; import { ComponentFixture, TestBed } from '@angular/core/testing'; import { of } from 'rxjs'; import { OidcAuthenticationService } from '../../../auth/oidc/oidc-authentication.service'; +import { UnitTestingUtils } from '../../../testing/unit-testing-utils'; +import { LoginDialogPanelComponent } from './login-dialog-panel.component'; +import { BasicAlfrescoAuthService } from '../../../auth/basic-auth/basic-alfresco-auth.service'; +import { CoreTestingModule } from '../../../testing/core.testing.module'; describe('LoginDialogPanelComponent', () => { let component: LoginDialogPanelComponent; let fixture: ComponentFixture; - let element: HTMLElement; let usernameInput: HTMLInputElement; let passwordInput: HTMLInputElement; let basicAlfrescoAuthService: BasicAlfrescoAuthService; + let testingUtils: UnitTestingUtils; beforeEach(async () => { TestBed.configureTestingModule({ @@ -36,14 +39,14 @@ describe('LoginDialogPanelComponent', () => { fixture = TestBed.createComponent(LoginDialogPanelComponent); basicAlfrescoAuthService = TestBed.inject(BasicAlfrescoAuthService); - element = fixture.nativeElement; component = fixture.componentInstance; + testingUtils = new UnitTestingUtils(fixture.debugElement); fixture.detectChanges(); await fixture.whenStable(); - usernameInput = element.querySelector('#username'); - passwordInput = element.querySelector('#password'); + usernameInput = testingUtils.getByCSS('#username').nativeElement; + passwordInput = testingUtils.getByCSS('#password').nativeElement; }); afterEach(() => { @@ -63,8 +66,8 @@ describe('LoginDialogPanelComponent', () => { }; it('should be created', () => { - expect(element.querySelector('#adf-login-form')).not.toBeNull(); - expect(element.querySelector('#adf-login-form')).toBeDefined(); + expect(testingUtils.getByCSS('#adf-login-form')).not.toBeNull(); + expect(testingUtils.getByCSS('#adf-login-form')).toBeDefined(); }); it('should be able to login', (done) => { diff --git a/lib/core/src/lib/login/components/login/login.component.spec.ts b/lib/core/src/lib/login/components/login/login.component.spec.ts index 4c060a1bc5..4187918310 100644 --- a/lib/core/src/lib/login/components/login/login.component.spec.ts +++ b/lib/core/src/lib/login/components/login/login.component.spec.ts @@ -15,41 +15,39 @@ * limitations under the License. */ -import { - AppConfigService, - AuthenticationService, - BasicAlfrescoAuthService, - CoreTestingModule, - LoginErrorEvent, - LoginSuccessEvent, - UserPreferencesService -} from '@alfresco/adf-core'; import { ComponentFixture, fakeAsync, TestBed } from '@angular/core/testing'; import { Validators } from '@angular/forms'; - import { Router } from '@angular/router'; import { EMPTY, of, throwError } from 'rxjs'; import { OidcAuthenticationService } from '../../../auth/oidc/oidc-authentication.service'; import { LoginComponent } from './login.component'; +import { AuthenticationService } from '../../../auth/services/authentication.service'; +import { UserPreferencesService } from '../../../common/services/user-preferences.service'; +import { AppConfigService } from '../../../app-config/app-config.service'; +import { BasicAlfrescoAuthService } from '../../../auth/basic-auth/basic-alfresco-auth.service'; +import { UnitTestingUtils } from '../../../testing/unit-testing-utils'; +import { CoreTestingModule } from '../../../testing/core.testing.module'; +import { LoginSuccessEvent } from '../../models/login-success.event'; +import { LoginErrorEvent } from '../../models/login-error.event'; describe('LoginComponent', () => { let component: LoginComponent; let fixture: ComponentFixture; - let element: any; let authService: AuthenticationService; let router: Router; let userPreferences: UserPreferencesService; let appConfigService: AppConfigService; let basicAlfrescoAuthService: BasicAlfrescoAuthService; + let testingUtils: UnitTestingUtils; let usernameInput; let passwordInput; - const getLoginErrorElement = () => element.querySelector('#login-error'); + const getLoginErrorElement = () => testingUtils.getByCSS('#login-error'); const getLoginErrorMessage = () => { const errorMessage = undefined; - const errorElement = element.querySelector('#login-error .adf-login-error-message'); + const errorElement = testingUtils.getByCSS('#login-error .adf-login-error-message')?.nativeElement; if (errorElement) { return errorElement.innerText; @@ -74,8 +72,8 @@ describe('LoginComponent', () => { ] }); fixture = TestBed.createComponent(LoginComponent); + testingUtils = new UnitTestingUtils(fixture.debugElement); - element = fixture.nativeElement; component = fixture.componentInstance; component.showRememberMe = true; component.showLoginActions = true; @@ -89,8 +87,8 @@ describe('LoginComponent', () => { fixture.detectChanges(); fixture.whenStable().then(() => { - usernameInput = element.querySelector('#username'); - passwordInput = element.querySelector('#password'); + usernameInput = testingUtils.getByCSS('#username')?.nativeElement; + passwordInput = testingUtils.getByCSS('#password')?.nativeElement; }); })); @@ -106,12 +104,12 @@ describe('LoginComponent', () => { passwordInput.dispatchEvent(new Event('input')); fixture.detectChanges(); - element.querySelector('.adf-login-button').click(); + fixture.nativeElement.querySelector('.adf-login-button').click(); fixture.detectChanges(); }; it('should be autocomplete off', () => { - expect(element.querySelector('#adf-login-form').getAttribute('autocomplete')).toBe('off'); + expect(testingUtils.getByCSS('#adf-login-form').nativeElement.getAttribute('autocomplete')).toBe('off'); }); it('should redirect to route on successful login', () => { @@ -188,8 +186,8 @@ describe('LoginComponent', () => { }); describe('Login button', () => { - const getLoginButton = () => element.querySelector('#login-button'); - const getLoginButtonText = () => element.querySelector('#login-button span.adf-login-button-label').innerText; + const getLoginButton = () => testingUtils.getByCSS('#login-button'); + const getLoginButtonText = () => testingUtils.getInnerTextByCSS('#login-button span.adf-login-button-label'); it('should be rendered with the proper key by default', () => { expect(getLoginButton()).not.toBeNull(); @@ -201,7 +199,7 @@ describe('LoginComponent', () => { loginWithCredentials('fake-username', 'fake-password'); - expect(element.querySelector('#checking-spinner')).not.toBeNull(); + expect(testingUtils.getByCSS('#checking-spinner')).toBeDefined(); expect(getLoginButtonText()).toEqual('LOGIN.BUTTON.CHECKING'); }); @@ -230,7 +228,7 @@ describe('LoginComponent', () => { fixture.detectChanges(); const loginButton = getLoginButton(); - expect(loginButton.disabled).toBe(false); + expect(loginButton.nativeElement.disabled).toBe(false); }); it('Should disable login button when username is not valid', () => { @@ -244,7 +242,7 @@ describe('LoginComponent', () => { fixture.detectChanges(); const loginButton = getLoginButton(); - expect(loginButton.disabled).toBe(true); + expect(loginButton.nativeElement.disabled).toBe(true); }); it('Should disable login button when password is not valid', () => { @@ -258,7 +256,7 @@ describe('LoginComponent', () => { fixture.detectChanges(); const loginButton = getLoginButton(); - expect(loginButton.disabled).toBe(true); + expect(loginButton.nativeElement.disabled).toBe(true); }); it('Should disable login button when username and password are empty', () => { @@ -272,22 +270,22 @@ describe('LoginComponent', () => { fixture.detectChanges(); const loginButton = getLoginButton(); - expect(loginButton.disabled).toBe(true); + expect(loginButton.nativeElement.disabled).toBe(true); }); }); describe('Remember me', () => { it('should be checked by default', () => { - expect(element.querySelector('#adf-login-remember input[type="checkbox"]').checked).toBe(true); + expect(testingUtils.getByCSS('#adf-login-remember input[type="checkbox"]').nativeElement.checked).toBe(true); }); it('should set the component rememberMe property properly', () => { - element.querySelector('#adf-login-remember').dispatchEvent(new Event('change')); + testingUtils.getByCSS('#adf-login-remember').nativeElement.dispatchEvent(new Event('change')); fixture.detectChanges(); expect(component.rememberMe).toBe(false); - element.querySelector('#adf-login-remember').dispatchEvent(new Event('change')); + testingUtils.getByCSS('#adf-login-remember').nativeElement.dispatchEvent(new Event('change')); fixture.detectChanges(); expect(component.rememberMe).toBe(true); @@ -304,26 +302,26 @@ describe('LoginComponent', () => { }); it('should render Login form with all the keys to be translated', () => { - expect(element.querySelector('[data-automation-id="username"]')).toBeDefined(); - expect(element.querySelectorAll('.adf-login-form-input-label')[0].innerText).toEqual('LOGIN.LABEL.USERNAME'); + expect(testingUtils.getByDataAutomationId('username')).toBeDefined(); + expect(testingUtils.getAllByCSS('.adf-login-form-input-label')[0].nativeElement.innerText).toEqual('LOGIN.LABEL.USERNAME'); - expect(element.querySelector('#adf-login-remember')).toBeDefined(); - expect(element.querySelector('#adf-login-remember').innerText).toContain('LOGIN.LABEL.REMEMBER'); + expect(testingUtils.getByCSS('#adf-login-remember')).toBeDefined(); + expect(testingUtils.getInnerTextByCSS('#adf-login-remember')).toContain('LOGIN.LABEL.REMEMBER'); - expect(element.querySelector('[data-automation-id="password"]')).toBeDefined(); - expect(element.querySelectorAll('.adf-login-form-input-label')[1].innerText).toContain('LOGIN.LABEL.PASSWORD'); + expect(testingUtils.getByDataAutomationId('password')).toBeDefined(); + expect(testingUtils.getAllByCSS('.adf-login-form-input-label')[1].nativeElement.innerText).toContain('LOGIN.LABEL.PASSWORD'); - expect(element.querySelector('#adf-login-action-left')).toBeDefined(); - expect(element.querySelector('#adf-login-action-left').innerText).toEqual('LOGIN.ACTION.HELP'); + expect(testingUtils.getByCSS('#adf-login-action-left')).toBeDefined(); + expect(testingUtils.getInnerTextByCSS('#adf-login-action-left')).toEqual('LOGIN.ACTION.HELP'); - expect(element.querySelector('#adf-login-action-right')).toBeDefined(); - expect(element.querySelector('#adf-login-action-right').innerText).toEqual('LOGIN.ACTION.REGISTER'); + expect(testingUtils.getByCSS('#adf-login-action-right')).toBeDefined(); + expect(testingUtils.getInnerTextByCSS('#adf-login-action-right')).toEqual('LOGIN.ACTION.REGISTER'); }); describe('Copyright text', () => { it('should render the default copyright text', () => { - expect(element.querySelector('[data-automation-id="login-copyright"]')).toBeDefined(); - expect(element.querySelector('[data-automation-id="login-copyright"]').innerText).toEqual( + expect(testingUtils.getByDataAutomationId('login-copyright')).toBeDefined(); + expect(testingUtils.getInnerTextByDataAutomationId('login-copyright')).toEqual( '\u00A9 2005-2024 Hyland Software, Inc. and its affiliates. All rights reserved.' ); }); @@ -332,17 +330,17 @@ describe('LoginComponent', () => { component.copyrightText = 'customised'; fixture.detectChanges(); - expect(element.querySelector('[data-automation-id="login-copyright"]')).toBeDefined(); - expect(element.querySelector('[data-automation-id="login-copyright"]').innerText).toEqual('customised'); + expect(testingUtils.getByDataAutomationId('login-copyright')).toBeDefined(); + expect(testingUtils.getInnerTextByDataAutomationId('login-copyright')).toEqual('customised'); }); }); it('should render user and password input fields with default values', () => { - expect(element.querySelector('form')).toBeDefined(); - expect(element.querySelector('input[type="password"]')).toBeDefined(); - expect(element.querySelector('input[type="text"]')).toBeDefined(); - expect(element.querySelector('input[type="password"]').value).toEqual(''); - expect(element.querySelector('input[type="text"]').value).toEqual(''); + expect(testingUtils.getByCSS('form')).toBeDefined(); + expect(testingUtils.getByCSS('input[type="password"]')).toBeDefined(); + expect(testingUtils.getByCSS('input[type="text"]')).toBeDefined(); + expect(testingUtils.getByCSS('input[type="password"]').nativeElement.value).toEqual(''); + expect(testingUtils.getByCSS('input[type="text"]').nativeElement.value).toEqual(''); }); it('should hide remember me if showRememberMe is false', () => { @@ -350,7 +348,7 @@ describe('LoginComponent', () => { fixture.detectChanges(); - expect(element.querySelector('#login-remember')).toBe(null); + expect(testingUtils.getByCSS('#login-remember')).toBe(null); }); it('should hide login actions if showLoginActions is false', () => { @@ -358,8 +356,8 @@ describe('LoginComponent', () => { fixture.detectChanges(); - expect(element.querySelector('#login-action-help')).toBe(null); - expect(element.querySelector('#login-action-register')).toBe(null); + expect(testingUtils.getByCSS('#login-action-help')).toBe(null); + expect(testingUtils.getByCSS('#login-action-register')).toBe(null); }); describe('Error', () => { @@ -380,8 +378,8 @@ describe('LoginComponent', () => { expect(component.formError).toBeDefined(); expect(component.formError.username).toBeDefined(); expect(component.formError.username).toEqual('LOGIN.MESSAGES.USERNAME-MIN'); - expect(element.querySelector('#username-error')).toBeDefined(); - expect(element.querySelector('#username-error').innerText).toEqual('LOGIN.MESSAGES.USERNAME-MIN'); + expect(testingUtils.getByCSS('#username-error')).toBeDefined(); + expect(testingUtils.getInnerTextByCSS('#username-error')).toEqual('LOGIN.MESSAGES.USERNAME-MIN'); }); it('should throw a validation min-length error by default when the username is not at least 2 characters long', () => { @@ -395,8 +393,8 @@ describe('LoginComponent', () => { expect(component.formError).toBeDefined(); expect(component.formError.username).toBeDefined(); expect(component.formError.username).toEqual('LOGIN.MESSAGES.USERNAME-MIN'); - expect(element.querySelector('#username-error')).toBeDefined(); - expect(element.querySelector('#username-error').innerText).toEqual('LOGIN.MESSAGES.USERNAME-MIN'); + expect(testingUtils.getByCSS('#username-error')).toBeDefined(); + expect(testingUtils.getInnerTextByCSS('#username-error')).toEqual('LOGIN.MESSAGES.USERNAME-MIN'); }); it('should render validation min-length error when the username is lower than 3 characters with a custom validation Validators.minLength(3)', () => { @@ -416,8 +414,8 @@ describe('LoginComponent', () => { expect(component.formError).toBeDefined(); expect(component.formError.username).toBeDefined(); expect(component.formError.username).toEqual('LOGIN.MESSAGES.USERNAME-MIN'); - expect(element.querySelector('#username-error')).toBeDefined(); - expect(element.querySelector('#username-error').innerText).toEqual('LOGIN.MESSAGES.USERNAME-MIN'); + expect(testingUtils.getByCSS('#username-error')).toBeDefined(); + expect(testingUtils.getInnerTextByCSS('#username-error')).toEqual('LOGIN.MESSAGES.USERNAME-MIN'); }); it('should render validation required error when the username is empty and dirty', () => { @@ -430,8 +428,8 @@ describe('LoginComponent', () => { expect(component.formError).toBeDefined(); expect(component.formError.username).toBeDefined(); expect(component.formError.username).toEqual('LOGIN.MESSAGES.USERNAME-REQUIRED'); - expect(element.querySelector('#username-error')).toBeDefined(); - expect(element.querySelector('#username-error').innerText).toEqual('LOGIN.MESSAGES.USERNAME-REQUIRED'); + expect(testingUtils.getByCSS('#username-error')).toBeDefined(); + expect(testingUtils.getInnerTextByCSS('#username-error')).toEqual('LOGIN.MESSAGES.USERNAME-REQUIRED'); }); it('should render validation required error when the password is empty and dirty', () => { @@ -444,8 +442,8 @@ describe('LoginComponent', () => { expect(component.formError).toBeDefined(); expect(component.formError.password).toBeDefined(); expect(component.formError.password).toEqual('LOGIN.MESSAGES.PASSWORD-REQUIRED'); - expect(element.querySelector('#password-required')).toBeDefined(); - expect(element.querySelector('#password-required').innerText).toEqual('LOGIN.MESSAGES.PASSWORD-REQUIRED'); + expect(testingUtils.getByCSS('#password-required')).toBeDefined(); + expect(testingUtils.getInnerTextByCSS('#password-required')).toEqual('LOGIN.MESSAGES.PASSWORD-REQUIRED'); }); it('should render no validation errors when the username and password are filled', () => { @@ -463,8 +461,8 @@ describe('LoginComponent', () => { expect(component.formError).toBeDefined(); expect(component.formError.username).toEqual(''); expect(component.formError.password).toEqual(''); - expect(element.querySelector('#username-error')).toBeNull(); - expect(element.querySelector('#password-required')).toBeNull(); + expect(testingUtils.getByCSS('#username-error')).toBeNull(); + expect(testingUtils.getByCSS('#password-required')).toBeNull(); }); it('should return error with a wrong username', (done) => { @@ -593,8 +591,8 @@ describe('LoginComponent', () => { fixture.detectChanges(); - expect(element.querySelector('input[type="text"]').value).toEqual('fake-change-username'); - expect(element.querySelector('input[type="password"]').value).toEqual('fake-change-password'); + expect(testingUtils.getByCSS('input[type="text"]').nativeElement.value).toEqual('fake-change-username'); + expect(testingUtils.getByCSS('input[type="password"]').nativeElement.value).toEqual('fake-change-password'); }); it('should return success event after the login have succeeded', (done) => { @@ -648,7 +646,7 @@ describe('LoginComponent', () => { fixture.detectChanges(); expect(component.isPasswordShow).toBe(true); - expect(element.querySelector('#password').type).toEqual('text'); + expect(testingUtils.getByCSS('#password').nativeElement.type).toEqual('text'); }); it('should password be hidden when show password is false', () => { @@ -658,7 +656,7 @@ describe('LoginComponent', () => { fixture.detectChanges(); expect(component.isPasswordShow).toBe(false); - expect(element.querySelector('#password').type).toEqual('password'); + expect(testingUtils.getByCSS('#password').nativeElement.type).toEqual('password'); }); it('should emit only the username and not the password as part of the executeSubmit', fakeAsync(() => { @@ -688,8 +686,8 @@ describe('LoginComponent', () => { fixture.detectChanges(); fixture.whenStable().then(() => { - expect(element.querySelector('#username')).toBeNull(); - expect(element.querySelector('#password')).toBeNull(); + expect(testingUtils.getByCSS('#username')).toBeNull(); + expect(testingUtils.getByCSS('#password')).toBeNull(); }); })); @@ -726,7 +724,7 @@ describe('LoginComponent', () => { fixture.detectChanges(); fixture.whenStable().then(() => { - expect(element.querySelector('#login-button')).toBeNull(); + expect(testingUtils.getByCSS('#login-button')).toBeNull(); }); })); @@ -737,7 +735,7 @@ describe('LoginComponent', () => { fixture.detectChanges(); fixture.whenStable().then(() => { - expect(element.querySelector('#login-button-sso')).toBeDefined(); + expect(testingUtils.getByCSS('#login-button-sso')).toBeDefined(); }); })); }); diff --git a/lib/core/src/lib/notifications/components/notification-history.component.spec.ts b/lib/core/src/lib/notifications/components/notification-history.component.spec.ts index f5a265ea1b..0f1a43da09 100644 --- a/lib/core/src/lib/notifications/components/notification-history.component.spec.ts +++ b/lib/core/src/lib/notifications/components/notification-history.component.spec.ts @@ -22,19 +22,19 @@ import { OverlayContainer } from '@angular/cdk/overlay'; import { NotificationService } from '../services/notification.service'; import { StorageService } from '../../common/services/storage.service'; import { NOTIFICATION_TYPE, NotificationModel } from '../models/notification.model'; +import { UnitTestingUtils } from '../../testing/unit-testing-utils'; describe('Notification History Component', () => { let fixture: ComponentFixture; let component: NotificationHistoryComponent; - let element: HTMLElement; let notificationService: NotificationService; let overlayContainerElement: HTMLElement; let storage: StorageService; + let testingUtils: UnitTestingUtils; const openNotification = () => { fixture.detectChanges(); - const button = element.querySelector('#adf-notification-history-open-button'); - button.click(); + testingUtils.clickByCSS('#adf-notification-history-open-button'); fixture.detectChanges(); }; @@ -44,7 +44,7 @@ describe('Notification History Component', () => { }); fixture = TestBed.createComponent(NotificationHistoryComponent); component = fixture.componentInstance; - element = fixture.nativeElement; + testingUtils = new UnitTestingUtils(fixture.debugElement); storage = TestBed.inject(StorageService); notificationService = TestBed.inject(NotificationService); diff --git a/lib/core/src/lib/notifications/services/notification.service.spec.ts b/lib/core/src/lib/notifications/services/notification.service.spec.ts index bc2747bdf7..37a687e076 100644 --- a/lib/core/src/lib/notifications/services/notification.service.spec.ts +++ b/lib/core/src/lib/notifications/services/notification.service.spec.ts @@ -22,10 +22,9 @@ import { NotificationService } from './notification.service'; import { TranslationService } from '../../translation/translation.service'; import { HarnessLoader } from '@angular/cdk/testing'; import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed'; -import { MatIconHarness } from '@angular/material/icon/testing'; -import { MatSnackBarHarness } from '@angular/material/snack-bar/testing'; import { NoopAnimationsModule } from '@angular/platform-browser/animations'; import { NoopTranslateModule } from '../../testing/noop-translate.module'; +import { UnitTestingUtils } from '../../testing/unit-testing-utils'; @Component({ template: '', @@ -89,6 +88,7 @@ describe('NotificationService', () => { let loader: HarnessLoader; let fixture: ComponentFixture; let translationService: TranslationService; + let testingUtils: UnitTestingUtils; beforeEach(() => { TestBed.configureTestingModule({ @@ -99,6 +99,7 @@ describe('NotificationService', () => { fixture = TestBed.createComponent(ProvidesNotificationServiceComponent); fixture.detectChanges(); loader = TestbedHarnessEnvironment.documentRootLoader(fixture); + testingUtils = new UnitTestingUtils(fixture.debugElement, loader); }); it('should translate messages', () => { @@ -131,49 +132,49 @@ describe('NotificationService', () => { fixture.componentInstance.sendMessage(); fixture.detectChanges(); - expect(await loader.hasHarness(MatSnackBarHarness)).toBe(true); + expect(await testingUtils.checkIfMatSnackbarExists()).toBe(true); }); it('should open a message notification bar without custom configuration', async () => { fixture.componentInstance.sendMessageWithoutConfig(); fixture.detectChanges(); - expect(await loader.hasHarness(MatSnackBarHarness)).toBe(true); + expect(await testingUtils.checkIfMatSnackbarExists()).toBe(true); }); it('should open a message notification bar with custom configuration', async () => { fixture.componentInstance.sendCustomMessage(); fixture.detectChanges(); - expect(await loader.hasHarness(MatSnackBarHarness)).toBe(true); + expect(await testingUtils.checkIfMatSnackbarExists()).toBe(true); }); it('should open a message notification bar with action', async () => { fixture.componentInstance.sendMessageAction(); - expect(await loader.hasHarness(MatSnackBarHarness)).toBe(true); + expect(await testingUtils.checkIfMatSnackbarExists()).toBe(true); }); it('should open a message notification bar with action and custom configuration', async () => { fixture.componentInstance.sendCustomMessageAction(); fixture.detectChanges(); - expect(await loader.hasHarness(MatSnackBarHarness)).toBe(true); + expect(await testingUtils.checkIfMatSnackbarExists()).toBe(true); }); it('should open a message notification bar with action and no custom configuration', async () => { fixture.componentInstance.sendMessageActionWithoutConfig(); fixture.detectChanges(); - expect(await loader.hasHarness(MatSnackBarHarness)).toBe(true); + expect(await testingUtils.checkIfMatSnackbarExists()).toBe(true); }); it('should open a message notification bar with a decorative icon', async () => { fixture.componentInstance.sendMessageWithDecorativeIcon(); - expect(await loader.hasHarness(MatIconHarness.with({ ancestor: `[data-automation-id="adf-snackbar-message-content"]` }))).toBe(true); + expect(await testingUtils.checkIfMatIconExistsWithAncestorByDataAutomationId('adf-snackbar-message-content')).toBe(true); }); it('should open a message notification bar with action and a decorative icon', async () => { fixture.componentInstance.sendMessageWithDecorativeIconAndAction(); - expect(await loader.hasHarness(MatIconHarness.with({ ancestor: `[data-automation-id="adf-snackbar-message-content"]` }))).toBe(true); + expect(await testingUtils.checkIfMatIconExistsWithAncestorByDataAutomationId('adf-snackbar-message-content')).toBe(true); }); }); diff --git a/lib/core/src/lib/pagination/infinite-pagination.component.spec.ts b/lib/core/src/lib/pagination/infinite-pagination.component.spec.ts index 36084a65e5..c59aee2594 100644 --- a/lib/core/src/lib/pagination/infinite-pagination.component.spec.ts +++ b/lib/core/src/lib/pagination/infinite-pagination.component.spec.ts @@ -16,7 +16,6 @@ */ import { ComponentFixture, TestBed } from '@angular/core/testing'; -import { By } from '@angular/platform-browser'; import { PaginationModel } from '../models/pagination.model'; import { InfinitePaginationComponent } from './infinite-pagination.component'; import { PaginatedComponent } from './paginated-component.interface'; @@ -24,6 +23,7 @@ import { BehaviorSubject } from 'rxjs'; import { CoreTestingModule } from '../testing/core.testing.module'; import { Component, ChangeDetectorRef } from '@angular/core'; import { RequestPaginationModel } from '../models/request-pagination.model'; +import { UnitTestingUtils } from '../testing/unit-testing-utils'; @Component({ template: `` @@ -54,6 +54,7 @@ describe('InfinitePaginationComponent', () => { let component: InfinitePaginationComponent; let pagination: PaginationModel; let changeDetectorRef: ChangeDetectorRef; + let testingUtils: UnitTestingUtils; beforeEach(() => { TestBed.configureTestingModule({ @@ -62,6 +63,7 @@ describe('InfinitePaginationComponent', () => { }); fixture = TestBed.createComponent(InfinitePaginationComponent); component = fixture.componentInstance; + testingUtils = new UnitTestingUtils(fixture.debugElement); changeDetectorRef = fixture.componentRef.injector.get(ChangeDetectorRef); component.target = TestBed.createComponent(TestPaginatedComponent).componentInstance; @@ -82,8 +84,7 @@ describe('InfinitePaginationComponent', () => { component.target = null; changeDetectorRef.detectChanges(); - const loadingSpinner = fixture.debugElement.query(By.css('[data-automation-id="adf-infinite-pagination-spinner"]')); - expect(loadingSpinner).not.toBeNull(); + expect(testingUtils.getByDataAutomationId('adf-infinite-pagination-spinner')).not.toBeNull(); }); it('should NOT show the loading spinner if NOT loading', () => { @@ -92,8 +93,7 @@ describe('InfinitePaginationComponent', () => { component.isLoading = false; changeDetectorRef.detectChanges(); - const loadingSpinner = fixture.debugElement.query(By.css('[data-automation-id="adf-infinite-pagination-spinner"]')); - expect(loadingSpinner).toBeNull(); + expect(testingUtils.getByDataAutomationId('adf-infinite-pagination-spinner')).toBeNull(); }); it('should show the load more button if NOT loading and has more items', () => { @@ -102,8 +102,7 @@ describe('InfinitePaginationComponent', () => { component.isLoading = false; changeDetectorRef.detectChanges(); - const loadMoreButton = fixture.debugElement.query(By.css('[data-automation-id="adf-infinite-pagination-button"]')); - expect(loadMoreButton).not.toBeNull(); + expect(testingUtils.getByDataAutomationId('adf-infinite-pagination-button')).not.toBeNull(); }); it('should NOT show the load more button if there are no more elements to load', (done) => { @@ -116,8 +115,7 @@ describe('InfinitePaginationComponent', () => { component.onLoadMore(); fixture.whenStable().then(() => { - const loadMoreButton = fixture.debugElement.query(By.css('[data-automation-id="adf-infinite-pagination-button"]')); - expect(loadMoreButton).toBeNull(); + expect(testingUtils.getByDataAutomationId('adf-infinite-pagination-button')).toBeNull(); done(); }); }); @@ -130,8 +128,7 @@ describe('InfinitePaginationComponent', () => { changeDetectorRef.detectChanges(); fixture.whenStable().then(() => { - const loadMoreButton = fixture.debugElement.query(By.css('[data-automation-id="adf-infinite-pagination-button"]')); - expect(loadMoreButton).not.toBeNull(); + expect(testingUtils.getByDataAutomationId('adf-infinite-pagination-button')).not.toBeNull(); done(); }); }); @@ -141,10 +138,8 @@ describe('InfinitePaginationComponent', () => { component.target.updatePagination(pagination); changeDetectorRef.detectChanges(); - const loadMoreButton = fixture.debugElement.query(By.css('[data-automation-id="adf-infinite-pagination-button"]')); - expect(loadMoreButton).toBeNull(); - const loadingSpinner = fixture.debugElement.query(By.css('[data-automation-id="adf-infinite-pagination-spinner"]')); - expect(loadingSpinner).toBeNull(); + expect(testingUtils.getByDataAutomationId('adf-infinite-pagination-button')).toBeNull(); + expect(testingUtils.getByDataAutomationId('adf-infinite-pagination-spinner')).toBeNull(); }); it('should trigger the loadMore event with skipcount 0 to reload all the elements', (done) => { @@ -161,8 +156,7 @@ describe('InfinitePaginationComponent', () => { done(); }); - const loadMoreButton = fixture.debugElement.query(By.css('[data-automation-id="adf-infinite-pagination-button"]')); - loadMoreButton.triggerEventHandler('click', {}); + testingUtils.clickByDataAutomationId('adf-infinite-pagination-button'); }); it('should trigger the loadMore event with merge true to reload all the elements', (done) => { @@ -179,8 +173,7 @@ describe('InfinitePaginationComponent', () => { done(); }); - const loadMoreButton = fixture.debugElement.query(By.css('[data-automation-id="adf-infinite-pagination-button"]')); - loadMoreButton.triggerEventHandler('click', {}); + testingUtils.clickByDataAutomationId('adf-infinite-pagination-button'); }); }); diff --git a/lib/core/src/lib/progress/progress.component.spec.ts b/lib/core/src/lib/progress/progress.component.spec.ts index b5f755f55d..b4934a6db3 100644 --- a/lib/core/src/lib/progress/progress.component.spec.ts +++ b/lib/core/src/lib/progress/progress.component.spec.ts @@ -21,13 +21,14 @@ import { MatProgressSpinnerModule } from '@angular/material/progress-spinner'; import { NoopAnimationsModule } from '@angular/platform-browser/animations'; import { HarnessLoader } from '@angular/cdk/testing'; import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed'; -import { MatProgressBarHarness } from '@angular/material/progress-bar/testing'; import { ProgressComponent } from './progress.component'; +import { UnitTestingUtils } from '../testing/unit-testing-utils'; describe('ProgressComponent', () => { let component: ProgressComponent; let fixture: ComponentFixture; let loader: HarnessLoader; + let testingUtils: UnitTestingUtils; beforeEach(async () => { await TestBed.configureTestingModule({ @@ -36,6 +37,7 @@ describe('ProgressComponent', () => { fixture = TestBed.createComponent(ProgressComponent); loader = TestbedHarnessEnvironment.loader(fixture); + testingUtils = new UnitTestingUtils(fixture.debugElement, loader); component = fixture.componentInstance; fixture.detectChanges(); }); @@ -74,8 +76,8 @@ describe('ProgressComponent', () => { component.ariaLabel = testLabel; fixture.detectChanges(); - const progress = await loader.getHarness(MatProgressBarHarness); - const host = await progress.host(); + const host = await testingUtils.getMatProgressBarHost(); + expect(await host.getAttribute('aria-label')).toBe(testLabel); }); @@ -83,8 +85,7 @@ describe('ProgressComponent', () => { component.ariaHidden = true; fixture.detectChanges(); - const progress = await loader.getHarness(MatProgressBarHarness); - const host = await progress.host(); + const host = await testingUtils.getMatProgressBarHost(); expect(await host.getAttribute('aria-hidden')).toBe('true'); }); @@ -93,7 +94,7 @@ describe('ProgressComponent', () => { const testId = 'progress-test-id'; component.testId = testId; fixture.detectChanges(); - const progressBarElement = fixture.nativeElement.querySelector(`[data-automation-id="${testId}"]`); + const progressBarElement = testingUtils.getByDataAutomationId(testId); expect(progressBarElement).not.toBeNull(); }); }); diff --git a/lib/core/src/lib/search-text/search-text-input.component.spec.ts b/lib/core/src/lib/search-text/search-text-input.component.spec.ts index 0ff63642b9..ec09635270 100644 --- a/lib/core/src/lib/search-text/search-text-input.component.spec.ts +++ b/lib/core/src/lib/search-text/search-text-input.component.spec.ts @@ -19,16 +19,16 @@ import { ComponentFixture, TestBed, discardPeriodicTasks, fakeAsync, tick } from import { CoreTestingModule } from '../testing/core.testing.module'; import { SearchTextInputComponent } from './search-text-input.component'; import { DebugElement } from '@angular/core'; -import { By } from '@angular/platform-browser'; import { Subject } from 'rxjs'; import { UserPreferencesService } from '../common/services/user-preferences.service'; +import { UnitTestingUtils } from '../testing/unit-testing-utils'; describe('SearchTextInputComponent', () => { let fixture: ComponentFixture; let component: SearchTextInputComponent; let debugElement: DebugElement; - let element: HTMLElement; let userPreferencesService: UserPreferencesService; + let testingUtils: UnitTestingUtils; beforeEach(() => { TestBed.configureTestingModule({ @@ -37,7 +37,7 @@ describe('SearchTextInputComponent', () => { fixture = TestBed.createComponent(SearchTextInputComponent); component = fixture.componentInstance; debugElement = fixture.debugElement; - element = fixture.nativeElement; + testingUtils = new UnitTestingUtils(debugElement); userPreferencesService = TestBed.inject(UserPreferencesService); component.focusListener = new Subject(); }); @@ -56,7 +56,7 @@ describe('SearchTextInputComponent', () => { fixture.detectChanges(); await fixture.whenStable(); - expect(element.querySelectorAll('input[type="search"]').length).toBe(1); + expect(testingUtils.getAllByCSS('input[type="search"]').length).toBe(1); }); }); @@ -67,8 +67,7 @@ describe('SearchTextInputComponent', () => { it('search button should be hidden', () => { fixture.detectChanges(); - const searchButton: any = element.querySelector('#adf-search-button'); - expect(searchButton).toBe(null); + expect(testingUtils.getByCSS('#adf-search-button')).toBe(null); }); it('should not have animation', () => { @@ -84,7 +83,7 @@ describe('SearchTextInputComponent', () => { fixture.detectChanges(); tick(100); - searchButton = debugElement.query(By.css('#adf-search-button')); + searchButton = testingUtils.getByCSS('#adf-search-button'); })); it('should NOT display a autocomplete list control when configured not to', fakeAsync(() => { @@ -143,7 +142,6 @@ describe('SearchTextInputComponent', () => { })); it('Search bar should close when user press ESC button', fakeAsync(() => { - const inputDebugElement = debugElement.query(By.css('#adf-control-input')); component.subscriptAnimationState.value = 'active'; fixture.detectChanges(); @@ -151,7 +149,7 @@ describe('SearchTextInputComponent', () => { expect(component.subscriptAnimationState.value).toBe('active'); - inputDebugElement.triggerEventHandler('keyup.escape', {}); + testingUtils.keyBoardEventByCSS('#adf-control-input', 'keyup', 'Escape', 'Escape'); tick(100); fixture.detectChanges(); @@ -173,8 +171,7 @@ describe('SearchTextInputComponent', () => { */ function clickSearchButton(): void { fixture.detectChanges(); - const searchButton: DebugElement = debugElement.query(By.css('#adf-search-button')); - searchButton.triggerEventHandler('click', null); + testingUtils.clickByCSS('#adf-search-button'); tick(100); fixture.detectChanges(); tick(100); @@ -227,7 +224,7 @@ describe('SearchTextInputComponent', () => { component.subscriptAnimationState.value = 'inactive'; fixture.detectChanges(); expect(component.subscriptAnimationState.value).toBe('inactive'); - expect(element.querySelector('.adf-search-button-inactive')).toBeTruthy(); + expect(testingUtils.getByCSS('.adf-search-button-inactive')).toBeTruthy(); })); it('should set browser autocomplete to on when configured', async () => { @@ -236,7 +233,7 @@ describe('SearchTextInputComponent', () => { fixture.detectChanges(); await fixture.whenStable(); - expect(element.querySelector('#adf-control-input').getAttribute('autocomplete')).toBe('on'); + expect(testingUtils.getByCSS('#adf-control-input').nativeElement.getAttribute('autocomplete')).toBe('on'); }); }); @@ -290,8 +287,7 @@ describe('SearchTextInputComponent', () => { tick(200); })); - const getClearSearchButton = (): HTMLButtonElement => - fixture.debugElement.query(By.css('[data-automation-id="adf-clear-search-button"]'))?.nativeElement; + const getClearSearchButton = (): HTMLButtonElement => testingUtils.getByDataAutomationId('adf-clear-search-button')?.nativeElement; it('should clear button be visible when showClearButton is set to true', async () => { component.showClearButton = true; diff --git a/lib/core/src/lib/snackbar-content/snackbar-content.component.spec.ts b/lib/core/src/lib/snackbar-content/snackbar-content.component.spec.ts index 91b553b8d0..0177317751 100644 --- a/lib/core/src/lib/snackbar-content/snackbar-content.component.spec.ts +++ b/lib/core/src/lib/snackbar-content/snackbar-content.component.spec.ts @@ -18,13 +18,15 @@ import { ComponentFixture, TestBed } from '@angular/core/testing'; import { MatIcon } from '@angular/material/icon'; import { MAT_SNACK_BAR_DATA, MatSnackBarRef } from '@angular/material/snack-bar'; -import { By } from '@angular/platform-browser'; import { SnackbarContentComponent } from './snackbar-content.component'; -import { CoreTestingModule, NoopTranslateModule } from '@alfresco/adf-core'; +import { UnitTestingUtils } from '../testing/unit-testing-utils'; +import { NoopTranslateModule } from '../testing/noop-translate.module'; +import { CoreTestingModule } from '../testing/core.testing.module'; describe('SnackbarContentComponent', () => { let component: SnackbarContentComponent; let fixture: ComponentFixture; + let testingUtils: UnitTestingUtils; beforeEach(() => { TestBed.configureTestingModule({ @@ -45,6 +47,7 @@ describe('SnackbarContentComponent', () => { }); fixture = TestBed.createComponent(SnackbarContentComponent); + testingUtils = new UnitTestingUtils(fixture.debugElement); component = fixture.componentInstance; }); @@ -53,12 +56,12 @@ describe('SnackbarContentComponent', () => { message: 'Some message' }; fixture.detectChanges(); - expect(fixture.nativeElement.querySelector('.adf-snackbar-message-content').innerText).toBe(component.data.message); + expect(testingUtils.getInnerTextByCSS('.adf-snackbar-message-content')).toBe(component.data.message); }); it('should not display message if message in data is not set', () => { fixture.detectChanges(); - expect(fixture.nativeElement.querySelector('.adf-snackbar-message-content').innerText).toBe(''); + expect(testingUtils.getInnerTextByCSS('.adf-snackbar-message-content')).toBe(''); }); it('should call snackBarRef.dismissWithAction() when button is clicked', () => { @@ -69,7 +72,7 @@ describe('SnackbarContentComponent', () => { }; spyOn(component.snackBarRef, 'dismissWithAction'); fixture.detectChanges(); - fixture.nativeElement.querySelector('.adf-snackbar-message-content-action-button').click(); + testingUtils.clickByCSS('.adf-snackbar-message-content-action-button'); expect(component.snackBarRef.dismissWithAction).toHaveBeenCalled(); }); @@ -80,7 +83,7 @@ describe('SnackbarContentComponent', () => { actionLabel: 'Some action action' }; fixture.detectChanges(); - expect(fixture.nativeElement.querySelector('.adf-snackbar-message-content-action-button').innerText).toBe(component.data.actionLabel); + expect(testingUtils.getInnerTextByCSS('.adf-snackbar-message-content-action-button')).toBe(component.data.actionLabel); }); it('should not display actionLabel if actionLabel in data is not set', () => { @@ -89,7 +92,7 @@ describe('SnackbarContentComponent', () => { showAction: true }; fixture.detectChanges(); - expect(fixture.nativeElement.querySelector('.adf-snackbar-message-content-action-button')).toBeNull(); + expect(testingUtils.getByCSS('.adf-snackbar-message-content-action-button')).toBeNull(); }); it('should render icon if actionIcon in data is set', () => { @@ -99,7 +102,7 @@ describe('SnackbarContentComponent', () => { actionIcon: 'close' }; fixture.detectChanges(); - expect(fixture.debugElement.query(By.directive(MatIcon))).toBeDefined(); + expect(testingUtils.getByDirective(MatIcon)).toBeDefined(); }); it('should not render icon if actionIcon in data is not set', () => { @@ -108,6 +111,6 @@ describe('SnackbarContentComponent', () => { showAction: true }; fixture.detectChanges(); - expect(fixture.debugElement.query(By.directive(MatIcon))).toBeNull(); + expect(testingUtils.getByDirective(MatIcon)).toBeNull(); }); }); diff --git a/lib/core/src/lib/templates/empty-content/empty-content.component.spec.ts b/lib/core/src/lib/templates/empty-content/empty-content.component.spec.ts index ba828edc7d..f155ff3257 100644 --- a/lib/core/src/lib/templates/empty-content/empty-content.component.spec.ts +++ b/lib/core/src/lib/templates/empty-content/empty-content.component.spec.ts @@ -17,11 +17,11 @@ import { Component } from '@angular/core'; import { ComponentFixture, TestBed } from '@angular/core/testing'; -import { By } from '@angular/platform-browser'; import { TranslateService } from '@ngx-translate/core'; import { of } from 'rxjs'; import { NoopTranslateModule } from '../../testing/noop-translate.module'; import { EmptyContentComponent } from './empty-content.component'; +import { UnitTestingUtils } from '../../testing/unit-testing-utils'; @Component({ selector: 'adf-test-component', @@ -40,12 +40,14 @@ class TestComponent {} describe('EmptyContentComponent', () => { let fixture: ComponentFixture; let translateService: TranslateService; + let testingUtils: UnitTestingUtils; beforeEach(() => { TestBed.configureTestingModule({ imports: [NoopTranslateModule, TestComponent] }); fixture = TestBed.createComponent(TestComponent); + testingUtils = new UnitTestingUtils(fixture.debugElement); translateService = TestBed.inject(TranslateService); }); @@ -53,7 +55,7 @@ describe('EmptyContentComponent', () => { fixture.detectChanges(); await fixture.whenStable(); - const title = fixture.debugElement.query(By.css('.adf-empty-content__title')); + const title = testingUtils.getByCSS('.adf-empty-content__title'); expect(title).toBeDefined(); expect(title.nativeElement.textContent).toContain('CUSTOM_TITLE'); }); @@ -73,8 +75,8 @@ describe('EmptyContentComponent', () => { fixture.detectChanges(); await fixture.whenStable(); - const title = fixture.debugElement.query(By.css('.adf-empty-content__title')); - const subtitle = fixture.debugElement.query(By.css('.adf-empty-content__subtitle')); + const title = testingUtils.getByCSS('.adf-empty-content__title'); + const subtitle = testingUtils.getByCSS('.adf-empty-content__subtitle'); expect(title).toBeDefined(); expect(title.nativeElement.textContent).toContain('ENG_CUSTOM_TITLE'); @@ -84,7 +86,7 @@ describe('EmptyContentComponent', () => { }); it('should render multiple subtitle elements', () => { - const subTitles = fixture.debugElement.queryAll(By.css('.adf-empty-content__text')); + const subTitles = testingUtils.getAllByCSS('.adf-empty-content__text'); expect(subTitles.length).toBe(3); expect(subTitles[0].nativeElement.textContent).toContain('SUBTITLE-1'); diff --git a/lib/core/src/lib/templates/error-content/error-content.component.spec.ts b/lib/core/src/lib/templates/error-content/error-content.component.spec.ts index 8ddda0daf2..fa2255c100 100644 --- a/lib/core/src/lib/templates/error-content/error-content.component.spec.ts +++ b/lib/core/src/lib/templates/error-content/error-content.component.spec.ts @@ -21,12 +21,13 @@ import { ErrorContentComponent } from './error-content.component'; import { TranslationService } from '../../translation/translation.service'; import { ActivatedRoute } from '@angular/router'; import { of } from 'rxjs'; +import { UnitTestingUtils } from '../../testing/unit-testing-utils'; describe('ErrorContentComponent', () => { let fixture: ComponentFixture; let errorContentComponent: ErrorContentComponent; - let element: HTMLElement; let translateService: TranslationService; + let testingUtils: UnitTestingUtils; beforeEach(() => { TestBed.configureTestingModule({ @@ -34,7 +35,7 @@ describe('ErrorContentComponent', () => { providers: [{ provide: ActivatedRoute, useValue: { params: of() } }] }); fixture = TestBed.createComponent(ErrorContentComponent); - element = fixture.nativeElement; + testingUtils = new UnitTestingUtils(fixture.debugElement); errorContentComponent = fixture.debugElement.componentInstance; translateService = TestBed.inject(TranslationService); }); @@ -49,7 +50,7 @@ describe('ErrorContentComponent', () => { fixture.detectChanges(); await fixture.whenStable(); - const errorContentElement = element.querySelector('.adf-error-content-code'); + const errorContentElement = testingUtils.getByCSS('.adf-error-content-code'); expect(errorContentElement).not.toBeNull(); expect(errorContentElement).toBeDefined(); }); @@ -58,7 +59,7 @@ describe('ErrorContentComponent', () => { fixture.detectChanges(); await fixture.whenStable(); - const errorContentElement = element.querySelector('.adf-error-content-title'); + const errorContentElement = testingUtils.getByCSS('.adf-error-content-title'); expect(errorContentElement).not.toBeNull(); expect(errorContentElement).toBeDefined(); }); @@ -67,7 +68,7 @@ describe('ErrorContentComponent', () => { fixture.detectChanges(); await fixture.whenStable(); - const errorContentElement = element.querySelector('.adf-error-content-description'); + const errorContentElement = testingUtils.getByCSS('.adf-error-content-description'); expect(errorContentElement).not.toBeNull(); expect(errorContentElement).toBeDefined(); }); @@ -76,7 +77,7 @@ describe('ErrorContentComponent', () => { fixture.detectChanges(); await fixture.whenStable(); - const errorContentElement = element.querySelector('.adf-error-content-description'); + const errorContentElement = testingUtils.getByCSS('.adf-error-content-description'); expect(errorContentElement).not.toBeNull(); expect(errorContentElement).toBeDefined(); }); @@ -86,7 +87,7 @@ describe('ErrorContentComponent', () => { fixture.detectChanges(); await fixture.whenStable(); - const errorContentElement = element.querySelector('.adf-error-content-description-link'); + const errorContentElement = testingUtils.getByCSS('.adf-error-content-description-link'); expect(errorContentElement).toBeNull(); }); diff --git a/lib/core/src/lib/testing/index.ts b/lib/core/src/lib/testing/index.ts index f4fccb7c41..1781a50543 100644 --- a/lib/core/src/lib/testing/index.ts +++ b/lib/core/src/lib/testing/index.ts @@ -19,3 +19,4 @@ export * from './core.testing.module'; export * from './core.story.module'; export * from './noop-translate.module'; export * from './noop-auth.module'; +export * from './unit-testing-utils'; diff --git a/lib/core/src/lib/testing/unit-testing-utils.ts b/lib/core/src/lib/testing/unit-testing-utils.ts new file mode 100644 index 0000000000..312f0ed790 --- /dev/null +++ b/lib/core/src/lib/testing/unit-testing-utils.ts @@ -0,0 +1,470 @@ +/*! + * @license + * Copyright © 2005-2024 Hyland Software, Inc. and its affiliates. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { HarnessLoader, TestElement, TestKey } from '@angular/cdk/testing'; +import { DebugElement, Type } from '@angular/core'; +import { By } from '@angular/platform-browser'; +import { MatSelectHarness } from '@angular/material/select/testing'; +import { MatOptionHarness } from '@angular/material/core/testing'; +import { MatChipGridHarness, MatChipHarness, MatChipListboxHarness } from '@angular/material/chips/testing'; +import { MatButtonHarness } from '@angular/material/button/testing'; +import { MatIconHarness } from '@angular/material/icon/testing'; +import { MatCheckboxHarness } from '@angular/material/checkbox/testing'; +import { MatErrorHarness, MatFormFieldHarness } from '@angular/material/form-field/testing'; +import { MatInputHarness } from '@angular/material/input/testing'; +import { MatAutocompleteHarness } from '@angular/material/autocomplete/testing'; +import { ComponentFixture } from '@angular/core/testing'; +import { MatTabGroupHarness, MatTabHarness } from '@angular/material/tabs/testing'; +import { MatToolbarHarness } from '@angular/material/toolbar/testing'; +import { MatSnackBarHarness } from '@angular/material/snack-bar/testing'; +import { MatProgressBarHarness } from '@angular/material/progress-bar/testing'; + +export class UnitTestingUtils { + constructor(private debugElement?: DebugElement, private loader?: HarnessLoader) { + this.debugElement = debugElement; + this.loader = loader; + } + + setDebugElement(debugElement: DebugElement): void { + this.debugElement = debugElement; + } + + setLoader(loader: HarnessLoader): void { + this.loader = loader; + } + + getByCSS(selector: string): DebugElement { + return this.debugElement.query(By.css(selector)); + } + + getAllByCSS(selector: string): DebugElement[] { + return this.debugElement.queryAll(By.css(selector)); + } + + getInnerTextByCSS(selector: string): string { + return this.getByCSS(selector).nativeElement.innerText; + } + + getByDataAutomationId(dataAutomationId: string): DebugElement { + return this.getByCSS(`[data-automation-id="${dataAutomationId}"]`); + } + + getByDataAutomationClass(dataAutomationClass: string): DebugElement { + return this.getByCSS(`[data-automation-class="${dataAutomationClass}"]`); + } + + getInnerTextByDataAutomationId(dataAutomationId: string): string { + return this.getByDataAutomationId(dataAutomationId).nativeElement.innerText; + } + + getByDirective(directive: Type): DebugElement { + return this.debugElement.query(By.directive(directive)); + } + + /** Perform actions */ + + clickByCSS(selector: string): void { + const element = this.getByCSS(selector); + element.triggerEventHandler('click', new MouseEvent('click')); + } + + clickByDataAutomationId(dataAutomationId: string): void { + this.getByDataAutomationId(dataAutomationId).nativeElement.click(); + } + + doubleClickByDataAutomationId(dataAutomationId: string): void { + const element = this.getByDataAutomationId(dataAutomationId); + element.triggerEventHandler('dblclick', new MouseEvent('dblclick')); + } + + blurByCSS(selector: string): void { + const element = this.getByCSS(selector); + element.triggerEventHandler('blur', new FocusEvent('blur')); + } + + hoverOverByCSS(selector: string): void { + const element = this.getByCSS(selector); + element.triggerEventHandler('mouseenter', new MouseEvent('mouseenter')); + } + + hoverOverByDataAutomationId(dataAutomationId: string): void { + const element = this.getByDataAutomationId(dataAutomationId); + element.triggerEventHandler('mouseenter', new MouseEvent('mouseenter')); + } + + mouseLeaveByCSS(selector: string): void { + const element = this.getByCSS(selector); + element.triggerEventHandler('mouseleave', new MouseEvent('mouseleave')); + } + + mouseLeaveByDataAutomationId(dataAutomationId: string): void { + const element = this.getByDataAutomationId(dataAutomationId); + element.triggerEventHandler('mouseleave', new MouseEvent('mouseleave')); + } + + keyBoardEventByCSS(selector: string, event: 'keyup' | 'keydown', code: string, key: string): void { + const element = this.getByCSS(selector); + element.nativeElement.dispatchEvent(new KeyboardEvent(event, { code, key })); + } + + dispatchCustomEventByCSS(selector: string, eventName: string): void { + const element = this.getByCSS(selector); + element.nativeElement.dispatchEvent(new CustomEvent(eventName)); + } + + /** Input related methods */ + + getInputByCSS(selector: string): HTMLInputElement { + return this.getByCSS(selector)?.nativeElement; + } + + getInputByDataAutomationId(dataAutomationId: string): HTMLInputElement { + return this.getByDataAutomationId(dataAutomationId)?.nativeElement; + } + + fillInputByCSS(selector: string, value: string): void { + const input = this.getInputByCSS(selector); + input.value = value; + input.dispatchEvent(new Event('input')); + } + + fillInputByDataAutomationId(dataAutomationId: string, value: any): void { + const input = this.getInputByDataAutomationId(dataAutomationId); + input.value = value; + input.dispatchEvent(new Event('input')); + } + + /** MatButton related methods */ + + async getMatButton(): Promise { + return this.loader.getHarness(MatButtonHarness); + } + + async getMatButtonByCSS(selector: string): Promise { + return this.loader.getHarness(MatButtonHarness.with({ selector })); + } + + async getMatButtonByDataAutomationId(dataAutomationId: string): Promise { + return this.loader.getHarness(MatButtonHarness.with({ selector: `[data-automation-id="${dataAutomationId}"]` })); + } + + async checkIfMatButtonExists(): Promise { + return this.loader.hasHarness(MatButtonHarness); + } + + async checkIfMatButtonExistsWithDataAutomationId(dataAutomationId: string): Promise { + return this.loader.hasHarness(MatButtonHarness.with({ selector: `[data-automation-id="${dataAutomationId}"]` })); + } + + async clickMatButton(): Promise { + const button = await this.getMatButton(); + await button.click(); + } + + async clickMatButtonByCSS(selector: string): Promise { + const button = await this.getMatButtonByCSS(selector); + await button.click(); + } + + async clickMatButtonByDataAutomationId(dataAutomationId: string): Promise { + const button = await this.getMatButtonByDataAutomationId(dataAutomationId); + await button.click(); + } + + async sendKeysToMatButton(keys: (string | TestKey)[]): Promise { + const button = await this.getMatButton(); + const host = await button.host(); + await host.sendKeys(...keys); + } + + /** MatCheckbox related methods */ + + async getMatCheckbox(): Promise { + return this.loader.getHarness(MatCheckboxHarness); + } + + async getMatCheckboxByDataAutomationId(dataAutomationId: string): Promise { + return this.loader.getHarness(MatCheckboxHarness.with({ selector: `[data-automation-id="${dataAutomationId}"]` })); + } + + async getMatCheckboxHost(): Promise { + const checkbox = await this.getMatCheckbox(); + return checkbox.host(); + } + + async getAllMatCheckboxes(): Promise { + return this.loader.getAllHarnesses(MatCheckboxHarness); + } + + async checkIfMatCheckboxIsChecked(): Promise { + const checkbox = await this.getMatCheckbox(); + return checkbox.isChecked(); + } + + async checkIfMatCheckboxesHaveClass(className: string): Promise { + const checkboxes = await this.getAllMatCheckboxes(); + return checkboxes.every(async (checkbox) => (await checkbox.host()).hasClass(className)); + } + + async hoverOverMatCheckbox(): Promise { + const host = await this.getMatCheckboxHost(); + await host.hover(); + } + + /** MatIcon related methods */ + + async getMatIconOrNull(): Promise { + return this.loader.getHarnessOrNull(MatIconHarness); + } + + async getMatIconWithAncestorByDataAutomationId(dataAutomationId: string): Promise { + return this.loader.getHarness(MatIconHarness.with({ ancestor: `[data-automation-id="${dataAutomationId}"]` })); + } + + async getMatIconWithAncestorByCSS(selector: string): Promise { + return this.loader.getHarness(MatIconHarness.with({ ancestor: selector })); + } + + async getMatIconWithAncestorByCSSAndName(selector: string, name: string): Promise { + return this.loader.getHarness(MatIconHarness.with({ ancestor: selector, name })); + } + + async checkIfMatIconExistsWithAncestorByDataAutomationId(dataAutomationId: string): Promise { + return this.loader.hasHarness(MatIconHarness.with({ ancestor: `[data-automation-id="${dataAutomationId}"]` })); + } + + async checkIfMatIconExistsWithAncestorByCSSAndName(selector: string, name: string): Promise { + return this.loader.hasHarness(MatIconHarness.with({ ancestor: selector, name })); + } + + async clickMatIconWithAncestorByDataAutomationId(dataAutomationId: string): Promise { + const icon = await this.getMatIconWithAncestorByDataAutomationId(dataAutomationId); + const host = await icon.host(); + await host.click(); + } + + /** MatSelect related methods */ + + async getMatSelectOptions(isOpened = false): Promise { + const select = await this.loader.getHarness(MatSelectHarness); + if (!isOpened) { + await select.open(); + } + return select.getOptions(); + } + + async getMatSelectHost(): Promise { + const select = await this.loader.getHarness(MatSelectHarness); + return select.host(); + } + + async checkIfMatSelectExists(): Promise { + return this.loader.hasHarness(MatSelectHarness); + } + + async openMatSelect(): Promise { + const select = await this.loader.getHarness(MatSelectHarness); + await select.open(); + } + + /** MatChips related methods */ + + async getMatChipByDataAutomationId(dataAutomationId: string): Promise { + return this.loader.getHarness(MatChipHarness.with({ selector: `[data-automation-id="${dataAutomationId}"]` })); + } + + async checkIfMatChipExistsWithDataAutomationId(dataAutomationId: string): Promise { + return this.loader.hasHarness(MatChipHarness.with({ selector: `[data-automation-id="${dataAutomationId}"]` })); + } + + async clickMatChip(dataAutomationId: string): Promise { + const chip = await this.getMatChipByDataAutomationId(dataAutomationId); + const host = await chip.host(); + await host.click(); + } + + async getMatChips(): Promise { + return this.loader.getAllHarnesses(MatChipHarness); + } + + /** MatChipListbox related methods */ + + async getMatChipListboxByDataAutomationId(dataAutomationId: string): Promise { + return this.loader.getHarness(MatChipListboxHarness.with({ selector: `[data-automation-id="${dataAutomationId}"]` })); + } + + async clickMatChipListbox(dataAutomationId: string): Promise { + const chipList = await this.getMatChipListboxByDataAutomationId(dataAutomationId); + const host = await chipList.host(); + await host.click(); + } + + /** MatChipGrid related methods */ + + async checkIfMatChipGridExists(): Promise { + return this.loader.hasHarness(MatChipGridHarness); + } + + /** MatFromField related methods */ + + async getMatFormField(): Promise { + return this.loader.getHarness(MatFormFieldHarness); + } + + async getMatFormFieldByCSS(selector: string): Promise { + return this.loader.getHarness(MatFormFieldHarness.with({ selector })); + } + + /** MatInput related methods */ + + async getMatInput(): Promise { + return this.loader.getHarness(MatInputHarness); + } + + async getMatInputByCSS(selector: string): Promise { + return this.loader.getHarness(MatInputHarness.with({ selector })); + } + + async getMatInputByDataAutomationId(dataAutomationId: string): Promise { + return this.loader.getHarness(MatInputHarness.with({ selector: `[data-automation-id="${dataAutomationId}"]` })); + } + + async getMatInputByPlaceholder(placeholder: string): Promise { + return this.loader.getHarness(MatInputHarness.with({ placeholder })); + } + + async getMatInputHost(): Promise { + const input = await this.getMatInput(); + return input.host(); + } + + async checkIfMatInputExists(): Promise { + return this.loader.hasHarness(MatInputHarness); + } + + async checkIfMatInputExistsWithCSS(selector: string): Promise { + return this.loader.hasHarness(MatInputHarness.with({ selector })); + } + + async checkIfMatInputExistsWithDataAutomationId(dataAutomationId: string): Promise { + return this.loader.hasHarness(MatInputHarness.with({ selector: `[data-automation-id="${dataAutomationId}"]` })); + } + + async checkIfMatInputExistsWithPlaceholder(placeholder: string): Promise { + return this.loader.hasHarness(MatInputHarness.with({ placeholder })); + } + + async clickMatInput(): Promise { + const input = await this.getMatInput(); + const host = await input.host(); + await host.click(); + } + + async fillMatInput(value: string): Promise { + const input = await this.getMatInput(); + await input.setValue(value); + } + + async fillMatInputByCSS(selector: string, value: string): Promise { + const input = await this.getMatInputByCSS(selector); + await input.setValue(value); + } + + async fillMatInputByDataAutomationId(dataAutomationId: string, value: string): Promise { + const input = await this.getMatInputByDataAutomationId(dataAutomationId); + await input.setValue(value); + await (await input.host()).dispatchEvent('input'); + } + + async focusMatInput(): Promise { + const input = await this.getMatInput(); + await input.focus(); + } + + async blurMatInput(): Promise { + const input = await this.getMatInput(); + await input.blur(); + } + + async getMatInputValue(): Promise { + const input = await this.getMatInput(); + return input.getValue(); + } + + async getMatInputValueByDataAutomationId(dataAutomationId: string): Promise { + const input = await this.getMatInputByDataAutomationId(dataAutomationId); + return input.getValue(); + } + + async sendKeysToMatInput(keys: (string | TestKey)[]): Promise { + const input = await this.getMatInput(); + const host = await input.host(); + await host.sendKeys(...keys); + } + + /** MatAutoComplete related methods */ + + async typeAndGetOptionsForMatAutoComplete(fixture: ComponentFixture, value: string): Promise { + const autocomplete = await this.loader.getHarness(MatAutocompleteHarness); + await autocomplete.enterText(value); + fixture.detectChanges(); + + return autocomplete.getOptions(); + } + + /** MatError related methods */ + + async getMatErrorByCSS(selector: string): Promise { + return this.loader.getHarness(MatErrorHarness.with({ selector })); + } + + async getMatErrorByDataAutomationId(dataAutomationId: string): Promise { + return this.loader.getHarness(MatErrorHarness.with({ selector: `[data-automation-id="${dataAutomationId}"]` })); + } + + /** MatTabGroup related methods */ + + async getSelectedTabFromMatTabGroup(): Promise { + const tabs = await this.loader.getHarness(MatTabGroupHarness); + return tabs.getSelectedTab(); + } + + async getSelectedTabLabelFromMatTabGroup(): Promise { + const tab = await this.getSelectedTabFromMatTabGroup(); + return tab.getLabel(); + } + + /** MatToolbar related methods */ + + async getMatToolbarHost(): Promise { + const toolbar = await this.loader.getHarness(MatToolbarHarness); + return toolbar.host(); + } + + /** MatSnackbar related methods */ + + async checkIfMatSnackbarExists(): Promise { + return this.loader.hasHarness(MatSnackBarHarness); + } + + /** MatProgressBar related methods */ + + async getMatProgressBarHost(): Promise { + const progress = await this.loader.getHarness(MatProgressBarHarness); + return progress.host(); + } +} diff --git a/lib/core/src/lib/toolbar/toolbar.component.spec.ts b/lib/core/src/lib/toolbar/toolbar.component.spec.ts index fe1f278dab..2ab1dd6ad6 100644 --- a/lib/core/src/lib/toolbar/toolbar.component.spec.ts +++ b/lib/core/src/lib/toolbar/toolbar.component.spec.ts @@ -17,10 +17,12 @@ import { ComponentFixture, TestBed } from '@angular/core/testing'; import { ToolbarComponent } from './toolbar.component'; -import { NoopTranslateModule } from '@alfresco/adf-core'; +import { NoopTranslateModule } from '../testing/noop-translate.module'; +import { UnitTestingUtils } from '../testing/unit-testing-utils'; describe('ToolbarComponent', () => { let fixture: ComponentFixture; + let testingUtils: UnitTestingUtils; beforeEach(() => { TestBed.configureTestingModule({ @@ -28,6 +30,7 @@ describe('ToolbarComponent', () => { }); fixture = TestBed.createComponent(ToolbarComponent); + testingUtils = new UnitTestingUtils(fixture.debugElement); }); it('should render title span', async () => { @@ -36,7 +39,7 @@ describe('ToolbarComponent', () => { fixture.detectChanges(); await fixture.whenStable(); - const title: HTMLSpanElement = fixture.nativeElement.querySelector('.adf-toolbar-title'); + const title: HTMLSpanElement = testingUtils.getByCSS('.adf-toolbar-title').nativeElement; expect(title.innerHTML).toBe('test-title'); }); }); diff --git a/lib/core/src/lib/viewer/components/download-prompt-dialog/download-prompt-dialog.component.spec.ts b/lib/core/src/lib/viewer/components/download-prompt-dialog/download-prompt-dialog.component.spec.ts index 9a21f85171..ca15d006ac 100644 --- a/lib/core/src/lib/viewer/components/download-prompt-dialog/download-prompt-dialog.component.spec.ts +++ b/lib/core/src/lib/viewer/components/download-prompt-dialog/download-prompt-dialog.component.spec.ts @@ -17,8 +17,7 @@ import { ComponentFixture, TestBed } from '@angular/core/testing'; import { MatDialogRef } from '@angular/material/dialog'; -import { By } from '@angular/platform-browser'; -import { CoreTestingModule } from '../../../testing'; +import { CoreTestingModule, UnitTestingUtils } from '../../../testing'; import { DownloadPromptActions } from '../../models/download-prompt.actions'; import { DownloadPromptDialogComponent } from './download-prompt-dialog.component'; @@ -29,8 +28,9 @@ const mockDialog = { describe('DownloadPromptDialogComponent', () => { let matDialogRef: MatDialogRef; let fixture: ComponentFixture; + let testingUtils: UnitTestingUtils; - const getButton = (buttonId: string) => fixture.debugElement.query(By.css(buttonId)).nativeElement; + const clickButton = (buttonId: string) => testingUtils.clickByCSS(buttonId); beforeEach(() => { TestBed.configureTestingModule({ @@ -40,12 +40,12 @@ describe('DownloadPromptDialogComponent', () => { matDialogRef = TestBed.inject(MatDialogRef); fixture = TestBed.createComponent(DownloadPromptDialogComponent); + testingUtils = new UnitTestingUtils(fixture.debugElement); fixture.detectChanges(); }); it('should emit DownloadPromptActions.WAIT and close dialog when clicking on the wait button', async () => { - const waitButton = getButton('#waitButton'); - waitButton.dispatchEvent(new Event('click')); + clickButton('#waitButton'); fixture.detectChanges(); await fixture.whenStable(); @@ -54,8 +54,7 @@ describe('DownloadPromptDialogComponent', () => { }); it('should emit DownloadPromptActions.DOWNLOAD and close dialog when clicking on the download button', async () => { - const waitButton = getButton('#downloadButton'); - waitButton.dispatchEvent(new Event('click')); + clickButton('#downloadButton'); fixture.detectChanges(); await fixture.whenStable(); diff --git a/lib/core/src/lib/viewer/components/img-viewer/img-viewer.component.spec.ts b/lib/core/src/lib/viewer/components/img-viewer/img-viewer.component.spec.ts index 2f73ef8bef..ed9c6d6d76 100644 --- a/lib/core/src/lib/viewer/components/img-viewer/img-viewer.component.spec.ts +++ b/lib/core/src/lib/viewer/components/img-viewer/img-viewer.component.spec.ts @@ -17,17 +17,16 @@ import { SimpleChange } from '@angular/core'; import { ComponentFixture, fakeAsync, TestBed, tick } from '@angular/core/testing'; -import { By } from '@angular/platform-browser'; import { AppConfigService } from '../../../app-config'; import { UrlService } from '../../../common'; -import { CoreTestingModule } from '../../../testing'; +import { CoreTestingModule, UnitTestingUtils } from '../../../testing'; import { ImgViewerComponent } from './img-viewer.component'; describe('Test Img viewer component ', () => { let component: ImgViewerComponent; let urlService: UrlService; let fixture: ComponentFixture; - let element: HTMLElement; + let testingUtils: UnitTestingUtils; const createFakeBlob = () => { const data = atob('iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk+M9QDwADhgGAWjR9awAAAABJRU5ErkJggg=='); @@ -44,8 +43,8 @@ describe('Test Img viewer component ', () => { beforeEach(() => { urlService = TestBed.inject(UrlService); fixture = TestBed.createComponent(ImgViewerComponent); + testingUtils = new UnitTestingUtils(fixture.debugElement); - element = fixture.nativeElement; component = fixture.componentInstance; component.urlFile = 'fake-url-file.png'; fixture.detectChanges(); @@ -81,7 +80,6 @@ describe('Test Img viewer component ', () => { urlService = TestBed.inject(UrlService); fixture = TestBed.createComponent(ImgViewerComponent); - element = fixture.nativeElement; component = fixture.componentInstance; component.urlFile = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg=='; @@ -109,8 +107,8 @@ describe('Test Img viewer component ', () => { beforeEach(() => { urlService = TestBed.inject(UrlService); fixture = TestBed.createComponent(ImgViewerComponent); + testingUtils.setDebugElement(fixture.debugElement); - element = fixture.nativeElement; component = fixture.componentInstance; fixture.detectChanges(); }); @@ -132,7 +130,7 @@ describe('Test Img viewer component ', () => { it('should present file name in the alt attribute', () => { component.fileName = 'fake-name'; fixture.detectChanges(); - expect(element.querySelector('#viewer-image').getAttribute('alt')).toEqual('fake-name'); + expect(testingUtils.getByCSS('#viewer-image').nativeElement.getAttribute('alt')).toEqual('fake-name'); }); it('should call replace on cropper with new url if blobFile is null', () => { @@ -161,8 +159,8 @@ describe('Test Img viewer component ', () => { describe('toolbar actions', () => { beforeEach(() => { fixture = TestBed.createComponent(ImgViewerComponent); - element = fixture.nativeElement; component = fixture.componentInstance; + testingUtils = new UnitTestingUtils(fixture.debugElement); component.blobFile = createFakeBlob(); const change = new SimpleChange(null, component.blobFile, true); component.ngOnChanges({ blobFile: change }); @@ -213,19 +211,16 @@ describe('Test Img viewer component ', () => { it('should show rotate button if not in read only mode', () => { component.readOnly = false; fixture.detectChanges(); - const rotateButtonElement = element.querySelector('#viewer-rotate-button'); - expect(rotateButtonElement).not.toEqual(null); + expect(testingUtils.getByCSS('#viewer-rotate-button')).not.toEqual(null); }); it('should not show rotate button by default', () => { - const rotateButtonElement = element.querySelector('#viewer-rotate-button'); - expect(rotateButtonElement).toEqual(null); + expect(testingUtils.getByCSS('#viewer-rotate-button')).toEqual(null); }); it('should not show crop button by default', () => { - const rotateButtonElement = element.querySelector('#viewer-crop-button'); - expect(rotateButtonElement).toEqual(null); + expect(testingUtils.getByCSS('#viewer-crop-button')).toEqual(null); }); it('should start cropping when clicking the crop button', fakeAsync(() => { @@ -234,8 +229,7 @@ describe('Test Img viewer component ', () => { spyOn(component.cropper, 'crop'); spyOn(component.cropper, 'setDragMode'); fixture.detectChanges(); - const cropButtonElement = fixture.debugElement.query(By.css('#viewer-crop-button')); - cropButtonElement.triggerEventHandler('click', null); + testingUtils.clickByCSS('#viewer-crop-button'); tick(); expect(component.cropImage).toHaveBeenCalled(); @@ -248,8 +242,7 @@ describe('Test Img viewer component ', () => { spyOn(component, 'rotateImage').and.callThrough(); spyOn(component.cropper, 'rotate'); fixture.detectChanges(); - const rotateButtonElement = fixture.debugElement.query(By.css('#viewer-rotate-button')); - rotateButtonElement.triggerEventHandler('click', null); + testingUtils.clickByCSS('#viewer-rotate-button'); tick(); expect(component.rotateImage).toHaveBeenCalled(); @@ -260,26 +253,23 @@ describe('Test Img viewer component ', () => { component.readOnly = false; component.isEditing = true; fixture.detectChanges(); - const secondaryToolbar = document.querySelector('.adf-secondary-toolbar'); - expect(secondaryToolbar).not.toEqual(null); + expect(testingUtils.getByCSS('.adf-secondary-toolbar')).not.toEqual(null); })); it('should not display the second toolbar when in read only mode', () => { component.readOnly = true; fixture.detectChanges(); - const secondaryToolbar = document.querySelector('.adf-secondary-toolbar'); - expect(secondaryToolbar).toEqual(null); + expect(testingUtils.getByCSS('.adf-secondary-toolbar')).toEqual(null); }); it('should not display the second toolbar when not in editing', () => { component.readOnly = true; component.isEditing = false; fixture.detectChanges(); - const secondaryToolbar = document.querySelector('.adf-secondary-toolbar'); - expect(secondaryToolbar).toEqual(null); + expect(testingUtils.getByCSS('.adf-secondary-toolbar')).toEqual(null); }); it('should display second toolbar in edit mode', fakeAsync(() => { @@ -287,13 +277,10 @@ describe('Test Img viewer component ', () => { component.isEditing = true; fixture.detectChanges(); - const secondaryToolbar = document.querySelector('.adf-secondary-toolbar'); - const resetButton = document.querySelector('#viewer-cancel-button'); - const saveButton = document.querySelector('#viewer-save-button'); - expect(secondaryToolbar).not.toEqual(null); - expect(resetButton).not.toEqual(null); - expect(saveButton).not.toEqual(null); + expect(testingUtils.getByCSS('.adf-secondary-toolbar')).not.toEqual(null); + expect(testingUtils.getByCSS('#viewer-cancel-button')).not.toEqual(null); + expect(testingUtils.getByCSS('#viewer-save-button')).not.toEqual(null); })); it('should not be in editing mode by default', () => { @@ -327,8 +314,7 @@ describe('Test Img viewer component ', () => { spyOn(component.cropper, 'zoomTo'); fixture.detectChanges(); - const cancelButtonElement = fixture.debugElement.query(By.css('#viewer-cancel-button')); - cancelButtonElement.triggerEventHandler('click', null); + testingUtils.clickByCSS('#viewer-cancel-button'); tick(); expect(component.reset).toHaveBeenCalled(); @@ -350,8 +336,7 @@ describe('Test Img viewer component ', () => { spyOn(component.cropper.getCroppedCanvas(), 'toBlob').and.callFake(() => component.isSaving.emit(false)); fixture.detectChanges(); - const saveButtonElement = fixture.debugElement.query(By.css('#viewer-save-button')); - saveButtonElement.triggerEventHandler('click', null); + testingUtils.clickByCSS('#viewer-save-button'); tick(); expect(component.save).toHaveBeenCalled(); @@ -374,7 +359,7 @@ describe('Test Img viewer component ', () => { describe('allowedEditActions', () => { beforeEach(() => { fixture = TestBed.createComponent(ImgViewerComponent); - element = fixture.nativeElement; + testingUtils.setDebugElement(fixture.debugElement); component = fixture.componentInstance; }); @@ -383,23 +368,17 @@ describe('Test Img viewer component ', () => { component.allowedEditActions = { rotate: true, crop: true }; fixture.detectChanges(); - let rotateButton = element.querySelector('#viewer-rotate-button'); - let cropButton = element.querySelector('#viewer-crop-button'); - // Check both buttons are visible when allowed - expect(rotateButton).not.toBeNull('Rotate button should be visible when allowed'); - expect(cropButton).not.toBeNull('Crop button should be visible when allowed'); + expect(testingUtils.getByCSS('#viewer-rotate-button')).not.toBeNull('Rotate button should be visible when allowed'); + expect(testingUtils.getByCSS('#viewer-crop-button')).not.toBeNull('Crop button should be visible when allowed'); // Change allowedEditActions to disallow both actions component.allowedEditActions = { rotate: false, crop: false }; fixture.detectChanges(); - rotateButton = element.querySelector('#viewer-rotate-button'); - cropButton = element.querySelector('#viewer-crop-button'); - // Check both buttons are not visible when not allowed - expect(rotateButton).toBeNull('Rotate button should not be visible when disallowed'); - expect(cropButton).toBeNull('Crop button should not be visible when disallowed'); + expect(testingUtils.getByCSS('#viewer-rotate-button')).toBeNull('Rotate button should not be visible when disallowed'); + expect(testingUtils.getByCSS('#viewer-crop-button')).toBeNull('Crop button should not be visible when disallowed'); }); }); }); diff --git a/lib/core/src/lib/viewer/components/pdf-viewer-thumbnails/pdf-viewer-thumbnails.component.spec.ts b/lib/core/src/lib/viewer/components/pdf-viewer-thumbnails/pdf-viewer-thumbnails.component.spec.ts index f845855485..8a9655f522 100644 --- a/lib/core/src/lib/viewer/components/pdf-viewer-thumbnails/pdf-viewer-thumbnails.component.spec.ts +++ b/lib/core/src/lib/viewer/components/pdf-viewer-thumbnails/pdf-viewer-thumbnails.component.spec.ts @@ -16,9 +16,8 @@ */ import { ComponentFixture, TestBed } from '@angular/core/testing'; -import { By } from '@angular/platform-browser'; import { PdfThumbListComponent } from './pdf-viewer-thumbnails.component'; -import { CoreTestingModule } from '../../../testing'; +import { CoreTestingModule, UnitTestingUtils } from '../../../testing'; import { DOWN_ARROW, ESCAPE, UP_ARROW } from '@angular/cdk/keycodes'; declare const pdfjsViewer: any; @@ -26,6 +25,7 @@ declare const pdfjsViewer: any; describe('PdfThumbListComponent', () => { let fixture: ComponentFixture; let component: PdfThumbListComponent; + let testingUtils: UnitTestingUtils; const page = (id) => ({ id, @@ -75,6 +75,7 @@ describe('PdfThumbListComponent', () => { imports: [CoreTestingModule] }); fixture = TestBed.createComponent(PdfThumbListComponent); + testingUtils = new UnitTestingUtils(fixture.debugElement); component = fixture.componentInstance; component.pdfViewer = viewerMock; @@ -83,7 +84,7 @@ describe('PdfThumbListComponent', () => { fixture.nativeElement.style.height = '700px'; fixture.nativeElement.style.overflow = 'scroll'; - const content = fixture.debugElement.query(By.css('.adf-pdf-thumbnails__content')).nativeElement; + const content = testingUtils.getByCSS('.adf-pdf-thumbnails__content').nativeElement; content.style.height = '2000px'; content.style.position = 'unset'; diff --git a/lib/core/src/lib/viewer/components/pdf-viewer/pdf-viewer.component.spec.ts b/lib/core/src/lib/viewer/components/pdf-viewer/pdf-viewer.component.spec.ts index 552775033c..ea9f7e0252 100644 --- a/lib/core/src/lib/viewer/components/pdf-viewer/pdf-viewer.component.spec.ts +++ b/lib/core/src/lib/viewer/components/pdf-viewer/pdf-viewer.component.spec.ts @@ -24,7 +24,7 @@ import { of } from 'rxjs'; import { take } from 'rxjs/operators'; import { AppConfigService } from '../../../app-config'; import { EventMock } from '../../../mock'; -import { CoreTestingModule } from '../../../testing'; +import { CoreTestingModule, UnitTestingUtils } from '../../../testing'; import { RenderingQueueServices } from '../../services/rendering-queue.services'; import { PdfThumbListComponent } from '../pdf-viewer-thumbnails/pdf-viewer-thumbnails.component'; import { PdfViewerComponent } from './pdf-viewer.component'; @@ -109,9 +109,9 @@ class BlobTestComponent { describe('Test PdfViewer component', () => { let component: PdfViewerComponent; let fixture: ComponentFixture; - let element: HTMLElement; let change: any; let dialog: MatDialog; + let testingUtils: UnitTestingUtils; beforeEach(async () => { TestBed.configureTestingModule({ @@ -127,11 +127,10 @@ describe('Test PdfViewer component', () => { ] }); fixture = TestBed.createComponent(PdfViewerComponent); + testingUtils = new UnitTestingUtils(fixture.debugElement); dialog = TestBed.inject(MatDialog); - element = fixture.nativeElement; component = fixture.componentInstance; - component.showToolbar = true; component.inputPage('1'); @@ -148,6 +147,7 @@ describe('Test PdfViewer component', () => { fixtureUrlTestComponent = TestBed.createComponent(UrlTestComponent); componentUrlTestComponent = fixtureUrlTestComponent.componentInstance; elementUrlTestComponent = fixtureUrlTestComponent.nativeElement; + testingUtils.setDebugElement(fixtureUrlTestComponent.debugElement); fixtureUrlTestComponent.detectChanges(); @@ -179,8 +179,7 @@ describe('Test PdfViewer component', () => { }, 55000); it('should nextPage move to the next page', (done) => { - const nextPageButton: any = elementUrlTestComponent.querySelector('#viewer-next-page-button'); - nextPageButton.click(); + testingUtils.clickByCSS('#viewer-next-page-button'); fixtureUrlTestComponent.detectChanges(); @@ -218,12 +217,9 @@ describe('Test PdfViewer component', () => { }, 55000); it('should previous page move to the previous page', (done) => { - const previousPageButton: any = elementUrlTestComponent.querySelector('#viewer-previous-page-button'); - const nextPageButton: any = elementUrlTestComponent.querySelector('#viewer-next-page-button'); - - nextPageButton.click(); - nextPageButton.click(); - previousPageButton.click(); + testingUtils.clickByCSS('#viewer-next-page-button'); + testingUtils.clickByCSS('#viewer-next-page-button'); + testingUtils.clickByCSS('#viewer-previous-page-button'); fixtureUrlTestComponent.detectChanges(); fixtureUrlTestComponent.whenStable().then(() => { @@ -256,10 +252,8 @@ describe('Test PdfViewer component', () => { it('should zoom in increment the scale value', (done) => { spyOn(componentUrlTestComponent.pdfViewerComponent.pdfViewer, 'forceRendering').and.callFake(() => {}); - const zoomInButton: any = elementUrlTestComponent.querySelector('#viewer-zoom-in-button'); - const zoomBefore = componentUrlTestComponent.pdfViewerComponent.pdfViewer.currentScaleValue; - zoomInButton.click(); + testingUtils.clickByCSS('#viewer-zoom-in-button'); fixtureUrlTestComponent.detectChanges(); expect(componentUrlTestComponent.pdfViewerComponent.currentScaleMode).toBe('auto'); @@ -270,10 +264,9 @@ describe('Test PdfViewer component', () => { it('should zoom out decrement the scale value', (done) => { spyOn(componentUrlTestComponent.pdfViewerComponent.pdfViewer, 'forceRendering').and.callFake(() => {}); - const zoomOutButton: any = elementUrlTestComponent.querySelector('#viewer-zoom-out-button'); const zoomBefore = componentUrlTestComponent.pdfViewerComponent.pdfViewer.currentScaleValue; - zoomOutButton.click(); + testingUtils.clickByCSS('#viewer-zoom-out-button'); fixtureUrlTestComponent.detectChanges(); expect(componentUrlTestComponent.pdfViewerComponent.currentScaleMode).toBe('auto'); @@ -284,17 +277,14 @@ describe('Test PdfViewer component', () => { it('should it-in button toggle page-fit and auto scale mode', fakeAsync(() => { spyOn(componentUrlTestComponent.pdfViewerComponent.pdfViewer, 'forceRendering').and.callFake(() => {}); - - const itPage: any = elementUrlTestComponent.querySelector('#viewer-scale-page-button'); - tick(250); expect(componentUrlTestComponent.pdfViewerComponent.currentScaleMode).toBe('init'); - itPage.click(); + testingUtils.clickByCSS('#viewer-scale-page-button'); expect(componentUrlTestComponent.pdfViewerComponent.currentScaleMode).toBe('page-fit'); - itPage.click(); + testingUtils.clickByCSS('#viewer-scale-page-button'); expect(componentUrlTestComponent.pdfViewerComponent.currentScaleMode).toBe('auto'); - itPage.click(); + testingUtils.clickByCSS('#viewer-scale-page-button'); expect(componentUrlTestComponent.pdfViewerComponent.currentScaleMode).toBe('page-fit'); }), 55000); }); @@ -322,14 +312,14 @@ describe('Test PdfViewer component', () => { }, 55000); it('should open thumbnails panel', (done) => { - expect(elementUrlTestComponent.querySelector('.adf-pdf-viewer__thumbnails')).toBeNull(); + expect(testingUtils.getByCSS('.adf-pdf-viewer__thumbnails')).toBeNull(); componentUrlTestComponent.pdfViewerComponent.toggleThumbnails(); fixtureUrlTestComponent.detectChanges(); fixtureUrlTestComponent.whenStable().then(() => { - expect(elementUrlTestComponent.querySelector('.adf-pdf-viewer__thumbnails')).not.toBeNull(); + expect(testingUtils.getByCSS('.adf-pdf-viewer__thumbnails')).not.toBeNull(); done(); }); }, 55000); @@ -391,7 +381,7 @@ describe('Test PdfViewer component', () => { }); it('should Loader be present', () => { - expect(element.querySelector('.adf-loader-container')).not.toBeNull(); + expect(testingUtils.getByCSS('.adf-loader-container')).not.toBeNull(); }); describe('Zoom customization', () => { @@ -527,6 +517,7 @@ describe('Test PdfViewer component', () => { beforeEach(async () => { fixtureUrlTestComponent = TestBed.createComponent(UrlTestComponent); elementUrlTestComponent = fixtureUrlTestComponent.nativeElement; + testingUtils.setDebugElement(fixtureUrlTestComponent.debugElement); fixtureUrlTestComponent.detectChanges(); await fixtureUrlTestComponent.whenStable(); @@ -541,8 +532,8 @@ describe('Test PdfViewer component', () => { fixtureUrlTestComponent.detectChanges(); fixtureUrlTestComponent.whenStable().then(() => { - expect(elementUrlTestComponent.querySelector('.adf-pdfViewer')).not.toBeNull(); - expect(elementUrlTestComponent.querySelector('.adf-viewer-pdf-viewer')).not.toBeNull(); + expect(testingUtils.getByCSS('.adf-pdfViewer')).not.toBeNull(); + expect(testingUtils.getByCSS('.adf-viewer-pdf-viewer')).not.toBeNull(); done(); }); }, 55000); @@ -551,11 +542,11 @@ describe('Test PdfViewer component', () => { fixtureUrlTestComponent.detectChanges(); fixtureUrlTestComponent.whenStable().then(() => { /* cspell:disable-next-line */ - expect(elementUrlTestComponent.querySelector('.viewer-pagenumber-input')).toBeDefined(); - expect(elementUrlTestComponent.querySelector('.viewer-total-pages')).toBeDefined(); + expect(testingUtils.getByCSS('.viewer-pagenumber-input')).toBeDefined(); + expect(testingUtils.getByCSS('.viewer-total-pages')).toBeDefined(); - expect(elementUrlTestComponent.querySelector('#viewer-previous-page-button')).not.toBeNull(); - expect(elementUrlTestComponent.querySelector('#viewer-next-page-button')).not.toBeNull(); + expect(testingUtils.getByCSS('#viewer-previous-page-button')).not.toBeNull(); + expect(testingUtils.getByCSS('#viewer-next-page-button')).not.toBeNull(); done(); }); }, 55000); @@ -565,8 +556,8 @@ describe('Test PdfViewer component', () => { fixtureUrlTestComponent.detectChanges(); fixtureUrlTestComponent.whenStable().then(() => { - expect(elementUrlTestComponent.querySelector('.viewer-toolbar-command')).toBeNull(); - expect(elementUrlTestComponent.querySelector('.viewer-toolbar-pagination')).toBeNull(); + expect(testingUtils.getByCSS('.viewer-toolbar-command')).toBeNull(); + expect(testingUtils.getByCSS('.viewer-toolbar-pagination')).toBeNull(); done(); }); }, 55000); @@ -579,6 +570,7 @@ describe('Test PdfViewer component', () => { beforeEach(async () => { fixtureBlobTestComponent = TestBed.createComponent(BlobTestComponent); elementBlobTestComponent = fixtureBlobTestComponent.nativeElement; + testingUtils.setDebugElement(fixtureBlobTestComponent.debugElement); fixtureBlobTestComponent.detectChanges(); await fixtureBlobTestComponent.whenStable(); @@ -593,8 +585,8 @@ describe('Test PdfViewer component', () => { fixtureBlobTestComponent.detectChanges(); fixtureBlobTestComponent.whenStable().then(() => { - expect(elementBlobTestComponent.querySelector('.adf-pdfViewer')).not.toBeNull(); - expect(elementBlobTestComponent.querySelector('.adf-viewer-pdf-viewer')).not.toBeNull(); + expect(testingUtils.getByCSS('.adf-pdfViewer')).not.toBeNull(); + expect(testingUtils.getByCSS('.adf-viewer-pdf-viewer')).not.toBeNull(); }); }); @@ -602,8 +594,8 @@ describe('Test PdfViewer component', () => { fixtureBlobTestComponent.detectChanges(); fixtureBlobTestComponent.whenStable().then(() => { - expect(elementBlobTestComponent.querySelector('#viewer-previous-page-button')).not.toBeNull(); - expect(elementBlobTestComponent.querySelector('#viewer-next-page-button')).not.toBeNull(); + expect(testingUtils.getByCSS('#viewer-previous-page-button')).not.toBeNull(); + expect(testingUtils.getByCSS('#viewer-next-page-button')).not.toBeNull(); done(); }); }, 55000); @@ -613,11 +605,11 @@ describe('Test PdfViewer component', () => { fixtureBlobTestComponent.whenStable().then(() => { /* cspell:disable-next-line */ - expect(elementBlobTestComponent.querySelector('.adf-viewer-pagenumber-input')).toBeDefined(); - expect(elementBlobTestComponent.querySelector('.adf-viewer-total-pages')).toBeDefined(); + expect(testingUtils.getByCSS('.adf-viewer-pagenumber-input')).toBeDefined(); + expect(testingUtils.getByCSS('.adf-viewer-total-pages')).toBeDefined(); - expect(elementBlobTestComponent.querySelector('#viewer-previous-page-button')).not.toBeNull(); - expect(elementBlobTestComponent.querySelector('#viewer-next-page-button')).not.toBeNull(); + expect(testingUtils.getByCSS('#viewer-previous-page-button')).not.toBeNull(); + expect(testingUtils.getByCSS('#viewer-next-page-button')).not.toBeNull(); done(); }); }, 55000); @@ -628,8 +620,8 @@ describe('Test PdfViewer component', () => { fixtureBlobTestComponent.detectChanges(); fixtureBlobTestComponent.whenStable().then(() => { - expect(elementBlobTestComponent.querySelector('.viewer-toolbar-command')).toBeNull(); - expect(elementBlobTestComponent.querySelector('.viewer-toolbar-pagination')).toBeNull(); + expect(testingUtils.getByCSS('.viewer-toolbar-command')).toBeNull(); + expect(testingUtils.getByCSS('.viewer-toolbar-pagination')).toBeNull(); done(); }); }, 55000); diff --git a/lib/core/src/lib/viewer/components/txt-viewer/txt-viewer.component.spec.ts b/lib/core/src/lib/viewer/components/txt-viewer/txt-viewer.component.spec.ts index bbc96f37eb..f6f422c720 100644 --- a/lib/core/src/lib/viewer/components/txt-viewer/txt-viewer.component.spec.ts +++ b/lib/core/src/lib/viewer/components/txt-viewer/txt-viewer.component.spec.ts @@ -18,25 +18,25 @@ import { SimpleChange } from '@angular/core'; import { ComponentFixture, TestBed } from '@angular/core/testing'; import { TxtViewerComponent } from './txt-viewer.component'; -import { CoreTestingModule } from '../../../testing'; +import { CoreTestingModule, UnitTestingUtils } from '../../../testing'; import { HttpClient } from '@angular/common/http'; import { of } from 'rxjs'; describe('Text View component', () => { let component: TxtViewerComponent; let fixture: ComponentFixture; - let element: HTMLElement; + let testingUtils: UnitTestingUtils; beforeEach(() => { TestBed.configureTestingModule({ imports: [CoreTestingModule, TxtViewerComponent] }); fixture = TestBed.createComponent(TxtViewerComponent); + testingUtils = new UnitTestingUtils(fixture.debugElement); const httpClient = TestBed.inject(HttpClient); spyOn(httpClient, 'get').and.returnValue(of('example')); - element = fixture.nativeElement; component = fixture.componentInstance; }); @@ -51,7 +51,7 @@ describe('Text View component', () => { fixture.detectChanges(); await fixture.whenStable(); - expect(element.querySelector('.adf-txt-viewer-content').textContent).toContain('example'); + expect(testingUtils.getByCSS('.adf-txt-viewer-content').nativeElement.textContent).toContain('example'); }); it('Should text container be present with Blob file', async () => { @@ -64,7 +64,7 @@ describe('Text View component', () => { fixture.detectChanges(); await fixture.whenStable(); - expect(element.querySelector('.adf-txt-viewer-content').textContent).toContain('example'); + expect(testingUtils.getByCSS('.adf-txt-viewer-content').nativeElement.textContent).toContain('example'); }); }); }); diff --git a/lib/core/src/lib/viewer/components/viewer-render/viewer-render.component.spec.ts b/lib/core/src/lib/viewer/components/viewer-render/viewer-render.component.spec.ts index 5cce60c4c5..154823ea63 100644 --- a/lib/core/src/lib/viewer/components/viewer-render/viewer-render.component.spec.ts +++ b/lib/core/src/lib/viewer/components/viewer-render/viewer-render.component.spec.ts @@ -21,8 +21,7 @@ import { SpyLocation } from '@angular/common/testing'; import { Component, TemplateRef, ViewChild } from '@angular/core'; import { ComponentFixture, TestBed } from '@angular/core/testing'; import { MatDialog, MatDialogModule } from '@angular/material/dialog'; -import { By } from '@angular/platform-browser'; -import { NoopTranslateModule } from '../../../testing'; +import { NoopTranslateModule, UnitTestingUtils } from '../../../testing'; import { RenderingQueueServices } from '../../services/rendering-queue.services'; import { ViewerRenderComponent } from './viewer-render.component'; import { ViewerExtensionDirective } from '@alfresco/adf-core'; @@ -66,9 +65,8 @@ class DoubleViewerComponent { describe('ViewerComponent', () => { let component: ViewerRenderComponent; let fixture: ComponentFixture; - let element: HTMLElement; - let extensionService: AppExtensionService; + let testingUtils: UnitTestingUtils; beforeEach(() => { TestBed.configureTestingModule({ @@ -76,7 +74,7 @@ describe('ViewerComponent', () => { providers: [RenderingQueueServices, { provide: Location, useClass: SpyLocation }, MatDialog] }); fixture = TestBed.createComponent(ViewerRenderComponent); - element = fixture.nativeElement; + testingUtils = new UnitTestingUtils(fixture.debugElement); component = fixture.componentInstance; extensionService = TestBed.inject(AppExtensionService); @@ -129,7 +127,7 @@ describe('ViewerComponent', () => { spyOn(extensionService, 'getViewerExtensions').and.returnValue([extension]); fixture = TestBed.createComponent(ViewerRenderComponent); - element = fixture.nativeElement; + testingUtils.setDebugElement(fixture.debugElement); component = fixture.componentInstance; component.urlFile = 'fake-test-file.pdf'; @@ -141,7 +139,7 @@ describe('ViewerComponent', () => { expect(component.externalExtensions.includes('*')).toBe(true); expect(component.externalViewer).toBe(extension); expect(component.viewerType).toBe('external'); - expect(element.querySelector('[data-automation-id="custom.component"]')).not.toBeNull(); + expect(testingUtils.getByDataAutomationId('custom.component')).not.toBeNull(); }); it('should display pdf with the first external viewer provided', async () => { @@ -160,7 +158,7 @@ describe('ViewerComponent', () => { spyOn(extensionService, 'getViewerExtensions').and.returnValue(extensions); fixture = TestBed.createComponent(ViewerRenderComponent); - element = fixture.nativeElement; + testingUtils.setDebugElement(fixture.debugElement); component = fixture.componentInstance; component.urlFile = 'fake-test-file.pdf'; @@ -169,8 +167,8 @@ describe('ViewerComponent', () => { fixture.detectChanges(); await fixture.whenStable(); - expect(element.querySelector('[data-automation-id="custom.component.1"]')).not.toBeNull(); - expect(element.querySelector('[data-automation-id="custom.component.2"]')).toBeNull(); + expect(testingUtils.getByDataAutomationId('custom.component.1')).not.toBeNull(); + expect(testingUtils.getByDataAutomationId('custom.component.2')).toBeNull(); }); it('should display url with the external viewer provided', async () => { @@ -182,7 +180,7 @@ describe('ViewerComponent', () => { spyOn(extensionService, 'getViewerExtensions').and.returnValue([extension]); fixture = TestBed.createComponent(ViewerRenderComponent); - element = fixture.nativeElement; + testingUtils.setDebugElement(fixture.debugElement); component = fixture.componentInstance; component.urlFile = 'http://localhost:4200/alfresco'; @@ -194,7 +192,7 @@ describe('ViewerComponent', () => { expect(component.externalExtensions.includes('*')).toBe(true); expect(component.externalViewer).toBe(extension); expect(component.viewerType).toBe('external'); - expect(element.querySelector('[data-automation-id="custom.component"]')).not.toBeNull(); + expect(testingUtils.getByDataAutomationId('custom.component')).not.toBeNull(); }); it('should extension file pdf be loaded', (done) => { @@ -204,7 +202,7 @@ describe('ViewerComponent', () => { fixture.whenStable().then(() => { fixture.detectChanges(); - expect(element.querySelector('adf-pdf-viewer')).not.toBeNull(); + expect(testingUtils.getByCSS('adf-pdf-viewer')).not.toBeNull(); done(); }); }); @@ -216,7 +214,7 @@ describe('ViewerComponent', () => { fixture.whenStable().then(() => { fixture.detectChanges(); - expect(element.querySelector('#viewer-image')).not.toBeNull(); + expect(testingUtils.getByCSS('#viewer-image')).not.toBeNull(); done(); }); }); @@ -228,7 +226,7 @@ describe('ViewerComponent', () => { fixture.whenStable().then(() => { fixture.detectChanges(); - expect(element.querySelector('adf-media-player')).not.toBeNull(); + expect(testingUtils.getByCSS('adf-media-player')).not.toBeNull(); done(); }); }); @@ -240,7 +238,7 @@ describe('ViewerComponent', () => { fixture.whenStable().then(() => { fixture.detectChanges(); - expect(element.querySelector('adf-txt-viewer')).not.toBeNull(); + expect(testingUtils.getByCSS('adf-txt-viewer')).not.toBeNull(); done(); }); }); @@ -253,15 +251,17 @@ describe('ViewerComponent', () => { fixture.whenStable().then(() => { fixture.detectChanges(); - expect(element.querySelector('adf-viewer-unknown-format')).toBeDefined(); + expect(testingUtils.getByCSS('adf-viewer-unknown-format')).toBeDefined(); done(); }); }); }); describe('Custom viewer extension template', () => { - const getCustomViewerContent = (customFixture: ComponentFixture): HTMLHeadingElement => - customFixture.debugElement.query(By.css('.adf-viewer-render-custom-content h1')).nativeElement; + const getCustomViewerContent = (customFixture: ComponentFixture): HTMLHeadingElement => { + testingUtils.setDebugElement(customFixture.debugElement); + return testingUtils.getByCSS('.adf-viewer-render-custom-content h1').nativeElement; + }; it('should render provided custom template when file type matches supported extensions', async () => { const fixtureCustom = TestBed.createComponent(DoubleViewerComponent); @@ -304,7 +304,7 @@ describe('ViewerComponent', () => { fixture.whenStable().then(() => { fixture.detectChanges(); - expect(element.querySelector('#viewer-image')).not.toBeNull(); + expect(testingUtils.getByCSS('#viewer-image')).not.toBeNull(); done(); }); }); @@ -317,7 +317,7 @@ describe('ViewerComponent', () => { fixture.whenStable().then(() => { fixture.detectChanges(); - expect(element.querySelector('#viewer-image')).not.toBeNull(); + expect(testingUtils.getByCSS('#viewer-image')).not.toBeNull(); done(); }); }); @@ -330,7 +330,7 @@ describe('ViewerComponent', () => { fixture.whenStable().then(() => { fixture.detectChanges(); - expect(element.querySelector('adf-txt-viewer')).not.toBeNull(); + expect(testingUtils.getByCSS('adf-txt-viewer')).not.toBeNull(); done(); }); }); @@ -343,7 +343,7 @@ describe('ViewerComponent', () => { fixture.whenStable().then(() => { fixture.detectChanges(); - expect(element.querySelector('adf-media-player')).not.toBeNull(); + expect(testingUtils.getByCSS('adf-media-player')).not.toBeNull(); done(); }); }, 25000); @@ -356,7 +356,7 @@ describe('ViewerComponent', () => { fixture.whenStable().then(() => { fixture.detectChanges(); - expect(element.querySelector('adf-media-player')).not.toBeNull(); + expect(testingUtils.getByCSS('adf-media-player')).not.toBeNull(); done(); }); }, 25000); @@ -369,7 +369,7 @@ describe('ViewerComponent', () => { fixture.whenStable().then(() => { fixture.detectChanges(); - expect(element.querySelector('adf-pdf-viewer')).not.toBeNull(); + expect(testingUtils.getByCSS('adf-pdf-viewer')).not.toBeNull(); done(); }); }, 25000); @@ -381,7 +381,7 @@ describe('ViewerComponent', () => { fixture.detectChanges(); fixture.whenStable().then(() => { fixture.detectChanges(); - expect(element.querySelector('adf-pdf-viewer')).not.toBeNull(); + expect(testingUtils.getByCSS('adf-pdf-viewer')).not.toBeNull(); done(); }); }, 25000); @@ -401,7 +401,7 @@ describe('ViewerComponent', () => { component.ngOnChanges(); fixture.detectChanges(); - const imgViewer = fixture.debugElement.query(By.css('adf-img-viewer')); + const imgViewer = testingUtils.getByCSS('adf-img-viewer'); imgViewer.triggerEventHandler('isSaving', true); expect(component.isSaving.emit).toHaveBeenCalledWith(true); @@ -426,7 +426,7 @@ describe('ViewerComponent', () => { fixture.detectChanges(); fixture.whenStable().then(() => { fixture.detectChanges(); - expect(element.querySelector('adf-viewer-unknown-format')).toBeDefined(); + expect(testingUtils.getByCSS('adf-viewer-unknown-format')).toBeDefined(); done(); }); }); diff --git a/lib/core/src/lib/viewer/components/viewer.component.spec.ts b/lib/core/src/lib/viewer/components/viewer.component.spec.ts index 97c93c427c..3dee4b525b 100644 --- a/lib/core/src/lib/viewer/components/viewer.component.spec.ts +++ b/lib/core/src/lib/viewer/components/viewer.component.spec.ts @@ -20,11 +20,10 @@ import { ComponentFixture, discardPeriodicTasks, fakeAsync, flush, TestBed, tick import { MatButtonModule } from '@angular/material/button'; import { MatDialog } from '@angular/material/dialog'; import { MatIconModule } from '@angular/material/icon'; -import { By } from '@angular/platform-browser'; import { of } from 'rxjs'; import { AppConfigService } from '../../app-config'; import { EventMock } from '../../mock'; -import { CoreTestingModule } from '../../testing'; +import { CoreTestingModule, UnitTestingUtils } from '../../testing'; import { DownloadPromptActions } from '../models/download-prompt.actions'; import { CloseButtonPosition } from '../models/viewer.model'; import { ViewUtilService } from '../services/view-util.service'; @@ -35,7 +34,7 @@ import { ViewerWithCustomSidebarComponent } from './mock/adf-viewer-container-si import { ViewerWithCustomToolbarActionsComponent } from './mock/adf-viewer-container-toolbar-actions.component.mock'; import { ViewerWithCustomToolbarComponent } from './mock/adf-viewer-container-toolbar.component.mock'; import { ViewerComponent } from './viewer.component'; -import { ThumbnailService } from '@alfresco/adf-core'; +import { ThumbnailService } from '../../common/services/thumbnail.service'; @Component({ selector: 'adf-dialog-dummy', @@ -46,11 +45,11 @@ class DummyDialogComponent {} describe('ViewerComponent', () => { let component: ViewerComponent; let fixture: ComponentFixture>; - let element: HTMLElement; let dialog: MatDialog; let viewUtilService: ViewUtilService; let appConfigService: AppConfigService; let thumbnailService: ThumbnailService; + let testingUtils: UnitTestingUtils; beforeEach(() => { TestBed.configureTestingModule({ @@ -68,9 +67,8 @@ describe('ViewerComponent', () => { }); fixture = TestBed.createComponent(ViewerComponent); - element = fixture.nativeElement; + testingUtils = new UnitTestingUtils(fixture.debugElement); component = fixture.componentInstance; - dialog = TestBed.inject(MatDialog); viewUtilService = TestBed.inject(ViewUtilService); appConfigService = TestBed.inject(AppConfigService); @@ -132,7 +130,7 @@ describe('ViewerComponent', () => { component.ngOnChanges(mockSimpleChanges); fixture.detectChanges(); - expect(element.querySelector('#adf-viewer-display-name').textContent).toEqual('fakeFileName.jpeg'); + expect(testingUtils.getByCSS('#adf-viewer-display-name').nativeElement.textContent).toEqual('fakeFileName.jpeg'); }); it('should set fileName providing fileName input', () => { @@ -144,65 +142,62 @@ describe('ViewerComponent', () => { fixture.detectChanges(); fixture.detectChanges(); - expect(element.querySelector('#adf-viewer-display-name').textContent).toEqual('testFileName.jpg'); + expect(testingUtils.getByCSS('#adf-viewer-display-name').nativeElement.textContent).toEqual('testFileName.jpg'); }); }); describe('Viewer Example Component Rendering', () => { it('should use custom toolbar', (done) => { const customFixture = TestBed.createComponent(ViewerWithCustomToolbarComponent); - const customElement: HTMLElement = customFixture.nativeElement; - + testingUtils.setDebugElement(customFixture.debugElement); customFixture.detectChanges(); + fixture.whenStable().then(() => { - expect(customElement.querySelector('.custom-toolbar-element')).toBeDefined(); + expect(testingUtils.getByCSS('.custom-toolbar-element')).toBeDefined(); done(); }); }); it('should use custom toolbar actions', (done) => { const customFixture = TestBed.createComponent(ViewerWithCustomToolbarActionsComponent); - const customElement: HTMLElement = customFixture.nativeElement; - + testingUtils.setDebugElement(customFixture.debugElement); customFixture.detectChanges(); + fixture.whenStable().then(() => { - expect(customElement.querySelector('#custom-button')).toBeDefined(); + expect(testingUtils.getByCSS('#custom-button')).toBeDefined(); done(); }); }); it('should use custom info drawer', (done) => { const customFixture = TestBed.createComponent(ViewerWithCustomSidebarComponent); - const customElement: HTMLElement = customFixture.nativeElement; - + testingUtils.setDebugElement(customFixture.debugElement); customFixture.detectChanges(); fixture.whenStable().then(() => { - expect(customElement.querySelector('.custom-info-drawer-element')).toBeDefined(); + expect(testingUtils.getByCSS('.custom-info-drawer-element')).toBeDefined(); done(); }); }); it('should use custom open with menu', (done) => { const customFixture = TestBed.createComponent(ViewerWithCustomOpenWithComponent); - const customElement: HTMLElement = customFixture.nativeElement; - + testingUtils.setDebugElement(customFixture.debugElement); customFixture.detectChanges(); fixture.whenStable().then(() => { - expect(customElement.querySelector('.adf-viewer-container-open-with')).toBeDefined(); + expect(testingUtils.getByCSS('.adf-viewer-container-open-with')).toBeDefined(); done(); }); }); it('should use custom more actions menu', (done) => { const customFixture = TestBed.createComponent(ViewerWithCustomMoreActionsComponent); - const customElement: HTMLElement = customFixture.nativeElement; - + testingUtils.setDebugElement(customFixture.debugElement); customFixture.detectChanges(); fixture.whenStable().then(() => { - expect(customElement.querySelector('.adf-viewer-container-more-actions')).toBeDefined(); + expect(testingUtils.getByCSS('.adf-viewer-container-more-actions')).toBeDefined(); done(); }); }); @@ -217,11 +212,8 @@ describe('ViewerComponent', () => { fixture.detectChanges(); await fixture.whenStable(); - const nextButton = element.querySelector('[data-automation-id="adf-toolbar-next-file"]'); - expect(nextButton).not.toBeNull(); - - const prevButton = element.querySelector('[data-automation-id="adf-toolbar-pref-file"]'); - expect(prevButton).toBeNull(); + expect(testingUtils.getByDataAutomationId('adf-toolbar-next-file')).not.toBeNull(); + expect(testingUtils.getByDataAutomationId('adf-toolbar-pref-file')).toBeNull(); }); it('should provide tooltip for next file button', async () => { @@ -232,8 +224,7 @@ describe('ViewerComponent', () => { fixture.detectChanges(); await fixture.whenStable(); - const nextButton = element.querySelector('[data-automation-id="adf-toolbar-next-file"]'); - expect(nextButton.title).toBe('ADF_VIEWER.ACTIONS.NEXT_FILE'); + expect(testingUtils.getByDataAutomationId('adf-toolbar-next-file').nativeElement.title).toBe('ADF_VIEWER.ACTIONS.NEXT_FILE'); }); it('should show only previous file button', async () => { @@ -244,11 +235,8 @@ describe('ViewerComponent', () => { fixture.detectChanges(); await fixture.whenStable(); - const nextButton = element.querySelector('[data-automation-id="adf-toolbar-next-file"]'); - expect(nextButton).toBeNull(); - - const prevButton = element.querySelector('[data-automation-id="adf-toolbar-pref-file"]'); - expect(prevButton).not.toBeNull(); + expect(testingUtils.getByDataAutomationId('adf-toolbar-next-file')).toBeNull(); + expect(testingUtils.getByDataAutomationId('adf-toolbar-pref-file')).not.toBeNull(); }); it('should provide tooltip for the previous file button', async () => { @@ -259,8 +247,7 @@ describe('ViewerComponent', () => { fixture.detectChanges(); await fixture.whenStable(); - const prevButton = element.querySelector('[data-automation-id="adf-toolbar-pref-file"]'); - expect(prevButton.title).toBe('ADF_VIEWER.ACTIONS.PREV_FILE'); + expect(testingUtils.getByDataAutomationId('adf-toolbar-pref-file').nativeElement.title).toBe('ADF_VIEWER.ACTIONS.PREV_FILE'); }); it('should show both file navigation buttons', async () => { @@ -271,11 +258,8 @@ describe('ViewerComponent', () => { fixture.detectChanges(); await fixture.whenStable(); - const nextButton = element.querySelector('[data-automation-id="adf-toolbar-next-file"]'); - expect(nextButton).not.toBeNull(); - - const prevButton = element.querySelector('[data-automation-id="adf-toolbar-pref-file"]'); - expect(prevButton).not.toBeNull(); + expect(testingUtils.getByDataAutomationId('adf-toolbar-next-file')).not.toBeNull(); + expect(testingUtils.getByDataAutomationId('adf-toolbar-pref-file')).not.toBeNull(); }); it('should not show navigation buttons', async () => { @@ -284,17 +268,14 @@ describe('ViewerComponent', () => { fixture.detectChanges(); await fixture.whenStable(); - const nextButton = element.querySelector('[data-automation-id="adf-toolbar-next-file"]'); - expect(nextButton).toBeNull(); - - const prevButton = element.querySelector('[data-automation-id="adf-toolbar-pref-file"]'); - expect(prevButton).toBeNull(); + expect(testingUtils.getByDataAutomationId('adf-toolbar-next-file')).toBeNull(); + expect(testingUtils.getByDataAutomationId('adf-toolbar-pref-file')).toBeNull(); }); it('should not show navigation buttons if file is saving', async () => { component.allowNavigate = true; fixture.detectChanges(); - const viewerRender = fixture.debugElement.query(By.css('adf-viewer-render')); + const viewerRender = testingUtils.getByCSS('adf-viewer-render'); viewerRender.triggerEventHandler('isSaving', true); expect(component.allowNavigate).toBeFalsy(); @@ -311,15 +292,12 @@ describe('ViewerComponent', () => { fixture.detectChanges(); await fixture.whenStable(); - const nextButton = element.querySelector('[data-automation-id="adf-toolbar-next-file"]'); - expect(nextButton).toBeNull(); - - const prevButton = element.querySelector('[data-automation-id="adf-toolbar-pref-file"]'); - expect(prevButton).toBeNull(); + expect(testingUtils.getByDataAutomationId('adf-toolbar-next-file')).toBeNull(); + expect(testingUtils.getByDataAutomationId('adf-toolbar-pref-file')).toBeNull(); }); it('should render fullscreen button', () => { - expect(element.querySelector('[data-automation-id="adf-toolbar-fullscreen"]')).toBeDefined(); + expect(testingUtils.getByDataAutomationId('adf-toolbar-fullscreen')).toBeDefined(); }); it('should render close viewer button if it is not a shared link', (done) => { @@ -327,7 +305,7 @@ describe('ViewerComponent', () => { fixture.detectChanges(); fixture.whenStable().then(() => { fixture.detectChanges(); - expect(element.querySelector('[data-automation-id="adf-toolbar-left-back"]')).not.toBeNull(); + expect(testingUtils.getByDataAutomationId('adf-toolbar-left-back')).not.toBeNull(); done(); }); }); @@ -347,8 +325,7 @@ describe('ViewerComponent', () => { fixture.detectChanges(); fixture.whenStable().then(() => { - const sidebar = element.querySelector('#adf-right-sidebar'); - expect(sidebar).toBeNull(); + expect(testingUtils.getByCSS('#adf-right-sidebar')).toBeNull(); done(); }); }); @@ -359,7 +336,7 @@ describe('ViewerComponent', () => { fixture.detectChanges(); fixture.whenStable().then(() => { - const sidebar = element.querySelector('#adf-right-sidebar'); + const sidebar = testingUtils.getByCSS('#adf-right-sidebar').nativeElement; expect(getComputedStyle(sidebar).order).toEqual('4'); done(); }); @@ -371,8 +348,7 @@ describe('ViewerComponent', () => { fixture.detectChanges(); fixture.whenStable().then(() => { - const sidebar = element.querySelector('#adf-left-sidebar'); - expect(sidebar).toBeNull(); + expect(testingUtils.getByCSS('#adf-left-sidebar')).toBeNull(); done(); }); }); @@ -383,7 +359,7 @@ describe('ViewerComponent', () => { fixture.detectChanges(); fixture.whenStable().then(() => { - const sidebar = element.querySelector('#adf-left-sidebar'); + const sidebar = testingUtils.getByCSS('#adf-left-sidebar').nativeElement; expect(getComputedStyle(sidebar).order).toEqual('1'); done(); }); @@ -391,7 +367,7 @@ describe('ViewerComponent', () => { }); describe('Info Button', () => { - const infoButton = () => element.querySelector('[data-automation-id="adf-toolbar-sidebar"]'); + const infoButton = () => testingUtils.getByDataAutomationId('adf-toolbar-sidebar'); it('should NOT display info button on the right side', () => { component.allowRightSidebar = true; @@ -419,7 +395,7 @@ describe('ViewerComponent', () => { }); it('should header be present if is overlay mode', () => { - expect(element.querySelector('.adf-viewer-toolbar')).not.toBeNull(); + expect(testingUtils.getByCSS('.adf-viewer-toolbar')).not.toBeNull(); }); it('should file name be present if is overlay mode ', async () => { @@ -427,22 +403,21 @@ describe('ViewerComponent', () => { component.ngOnChanges(mockSimpleChanges); fixture.detectChanges(); await fixture.whenStable(); - expect(element.querySelector('#adf-viewer-display-name').textContent).toEqual('fake-test-file.pdf'); + expect(testingUtils.getByCSS('#adf-viewer-display-name').nativeElement.textContent).toEqual('fake-test-file.pdf'); }); it('should Close button be present if overlay mode', async () => { fixture.detectChanges(); await fixture.whenStable(); - expect(element.querySelector('.adf-viewer-close-button')).not.toBeNull(); + expect(testingUtils.getByCSS('.adf-viewer-close-button')).not.toBeNull(); }); it('should Click on close button hide the viewer', async () => { - const closeButton: any = element.querySelector('.adf-viewer-close-button'); - closeButton.click(); + testingUtils.clickByCSS('.adf-viewer-close-button'); fixture.detectChanges(); await fixture.whenStable(); - expect(element.querySelector('.adf-viewer-content')).toBeNull(); + expect(testingUtils.getByCSS('.adf-viewer-content')).toBeNull(); }); it('should Esc button hide the viewer', async () => { @@ -451,7 +426,7 @@ describe('ViewerComponent', () => { fixture.detectChanges(); await fixture.whenStable(); - expect(element.querySelector('.adf-viewer-content')).toBeNull(); + expect(testingUtils.getByCSS('.adf-viewer-content')).toBeNull(); }); it('should not close the viewer on Escape event if dialog was opened', (done) => { @@ -465,7 +440,7 @@ describe('ViewerComponent', () => { dialogRef.afterClosed().subscribe(() => { EventMock.keyDown(27); fixture.detectChanges(); - expect(element.querySelector('.adf-viewer-content')).toBeNull(); + expect(testingUtils.getByCSS('.adf-viewer-content')).toBeNull(); done(); }); @@ -473,7 +448,7 @@ describe('ViewerComponent', () => { document.body.dispatchEvent(event); fixture.detectChanges(); - expect(element.querySelector('.adf-viewer-content')).not.toBeNull(); + expect(testingUtils.getByCSS('.adf-viewer-content')).not.toBeNull(); }); }); @@ -489,7 +464,7 @@ describe('ViewerComponent', () => { fixture.detectChanges(); fixture.whenStable().then(() => { - expect(element.querySelector('.adf-viewer-content')).not.toBeNull(); + expect(testingUtils.getByCSS('.adf-viewer-content')).not.toBeNull(); done(); }); }); @@ -505,13 +480,13 @@ describe('ViewerComponent', () => { component.showViewer = false; fixture.detectChanges(); - expect(element.querySelector('.adf-viewer-content')).toBeNull(); + expect(testingUtils.getByCSS('.adf-viewer-content')).toBeNull(); }); }); describe('Close Button', () => { - const getRightCloseButton = () => element.querySelector('[data-automation-id="adf-toolbar-right-back"]'); - const getLeftCloseButton = () => element.querySelector('[data-automation-id="adf-toolbar-left-back"]'); + const getRightCloseButton = () => testingUtils.getByDataAutomationId('adf-toolbar-right-back'); + const getLeftCloseButton = () => testingUtils.getByDataAutomationId('adf-toolbar-left-back'); it('should show close button on left side when closeButtonPosition is left and allowGoBack is true', () => { component.allowGoBack = true; @@ -543,9 +518,7 @@ describe('ViewerComponent', () => { describe('Viewer component - Full Screen Mode - Mocking fixture element', () => { beforeEach(() => { fixture = TestBed.createComponent(ViewerComponent); - element = fixture.nativeElement; component = fixture.componentInstance; - component.showToolbar = true; component.mimeType = 'application/pdf'; fixture.detectChanges();