From 2d2347c1abd0736e7b6b1d1311f66d828480c4b8 Mon Sep 17 00:00:00 2001 From: AleksanderSklorz <115619721+AleksanderSklorz@users.noreply.github.com> Date: Fri, 20 Feb 2026 15:41:40 +0100 Subject: [PATCH] [ACS-11153] remove the usage of ng reflect from the unit tests (#5057) * [ACS-11153] Removed usages of ng-reflect attribute * [ACS-11153] Added eslint rule to prevent using ng-reflect * [ACS-11153] Fixed copilot suggestio * [ACS-11153] Fixed copilot suggestio --- .eslintrc.json | 9 ++++- .../actions/rule-action.ui-component.spec.ts | 16 ++++----- ...rule-simple-condition.ui-component.spec.ts | 36 +++++++++---------- .../components/adf-info-drawer.component.ts | 6 ++-- 4 files changed, 36 insertions(+), 31 deletions(-) diff --git a/.eslintrc.json b/.eslintrc.json index 9ffa28776..200aa27c5 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -299,7 +299,14 @@ "space-before-function-paren": "off", "space-in-parens": ["off", "never"], "unicorn/filename-case": "error", - "@typescript-eslint/no-extra-semi": "error" + "@typescript-eslint/no-extra-semi": "error", + "no-restricted-syntax": [ + "error", + { + "selector": ":matches(Literal[value=/ng-reflect-/], TemplateElement[value.cooked=/ng-reflect-/])", + "message": "*ng-reflect-* attributes should not be used. Consider alternatives for proper selectors." + } + ] } }, { diff --git a/projects/aca-content/folder-rules/src/rule-details/actions/rule-action.ui-component.spec.ts b/projects/aca-content/folder-rules/src/rule-details/actions/rule-action.ui-component.spec.ts index cdfa021a2..ff5e63c77 100644 --- a/projects/aca-content/folder-rules/src/rule-details/actions/rule-action.ui-component.spec.ts +++ b/projects/aca-content/folder-rules/src/rule-details/actions/rule-action.ui-component.spec.ts @@ -69,9 +69,9 @@ describe('RuleActionUiComponent', () => { unitTestingUtils.getByCSS('.adf-textitem-action').nativeElement.click(); }; - const changeMatSelectValue = async (value: string) => { + const changeMatSelectValue = async (optionText: string) => { const matSelect = await loader.getHarness(MatSelectHarness); - await matSelect.clickOptions({ selector: `[ng-reflect-value="${value}"]` }); + await matSelect.clickOptions({ text: optionText }); fixture.detectChanges(); }; @@ -95,7 +95,7 @@ describe('RuleActionUiComponent', () => { component.parameterConstraints = dummyConstraints; fixture.detectChanges(); - await changeMatSelectValue('mock-action-1-definition'); + await changeMatSelectValue('Action 1 title'); await unitTestingUtils.fillMatInput('test'); await fixture.whenStable(); @@ -125,7 +125,7 @@ describe('RuleActionUiComponent', () => { component.parameterConstraints = dummyConstraints; fixture.detectChanges(); - await changeMatSelectValue('mock-action-1-definition'); + await changeMatSelectValue('Action 1 title'); const cardView = getPropertiesCardView(); @@ -209,7 +209,7 @@ describe('RuleActionUiComponent', () => { spyOn(tagService, 'areTagsEnabled').and.returnValue(true); fixture.detectChanges(); - await changeMatSelectValue('mock-action-1-definition'); + await changeMatSelectValue('Action 1 title'); expect(tagService.areTagsEnabled).toHaveBeenCalled(); (getPropertiesCardView().properties[2] as CardViewSelectItemModel).options$.subscribe((options) => { expect(options).toEqual( @@ -227,7 +227,7 @@ describe('RuleActionUiComponent', () => { spyOn(tagService, 'areTagsEnabled').and.returnValue(false); fixture.detectChanges(); - await changeMatSelectValue('mock-action-1-definition'); + await changeMatSelectValue('Action 1 title'); expect(tagService.areTagsEnabled).toHaveBeenCalled(); (getPropertiesCardView().properties[2] as CardViewSelectItemModel).options$.subscribe((options) => { expect(options).toEqual([ @@ -245,7 +245,7 @@ describe('RuleActionUiComponent', () => { spyOn(categoriesService, 'areCategoriesEnabled').and.returnValue(true); fixture.detectChanges(); - await changeMatSelectValue('mock-action-1-definition'); + await changeMatSelectValue('Action 1 title'); expect(categoriesService.areCategoriesEnabled).toHaveBeenCalled(); (getPropertiesCardView().properties[2] as CardViewSelectItemModel).options$.subscribe((options) => { expect(options).toEqual( @@ -263,7 +263,7 @@ describe('RuleActionUiComponent', () => { spyOn(categoryService, 'areCategoriesEnabled').and.returnValue(false); fixture.detectChanges(); - await changeMatSelectValue('mock-action-1-definition'); + await changeMatSelectValue('Action 1 title'); expect(categoryService.areCategoriesEnabled).toHaveBeenCalled(); (getPropertiesCardView().properties[2] as CardViewSelectItemModel).options$.subscribe((options) => { expect(options).toEqual([ diff --git a/projects/aca-content/folder-rules/src/rule-details/conditions/rule-simple-condition.ui-component.spec.ts b/projects/aca-content/folder-rules/src/rule-details/conditions/rule-simple-condition.ui-component.spec.ts index 8dd5da60a..766772932 100644 --- a/projects/aca-content/folder-rules/src/rule-details/conditions/rule-simple-condition.ui-component.spec.ts +++ b/projects/aca-content/folder-rules/src/rule-details/conditions/rule-simple-condition.ui-component.spec.ts @@ -53,15 +53,15 @@ describe('RuleSimpleConditionUiComponent', () => { const valueInputAutomationId = 'value-input'; const folderRulesBaseLabel = 'ACA_FOLDER_RULES.RULE_DETAILS.COMPARATORS'; - const changeMatSelectValue = async (dataAutomationId: string, value: string) => { + const changeMatSelectValue = async (dataAutomationId: string, optionText: string) => { const matSelect = await loader.getHarness(MatSelectHarness.with({ selector: `[data-automation-id="${dataAutomationId}"]` })); - await matSelect.clickOptions({ selector: `[ng-reflect-value="${value}"]` }); + await matSelect.clickOptions({ text: optionText }); fixture.detectChanges(); }; - const changeMatAutocompleteValue = async (value: string) => { + const changeMatAutocompleteValue = async (optionText: string) => { const matAutocomplete = await loader.getHarness(MatAutocompleteHarness); - await matAutocomplete.selectOption({ selector: `[ng-reflect-value="${value}"]` }); + await matAutocomplete.selectOption({ text: optionText }); fixture.detectChanges(); }; @@ -104,8 +104,7 @@ describe('RuleSimpleConditionUiComponent', () => { expect(fixture.componentInstance.isComparatorHidden).toBeFalsy(); expect(getComputedStyle(comparatorFormField).display).not.toBe('none'); - - await changeMatSelectValue(fieldSelectAutomationId, 'mimetype'); + await changeMatSelectValue(fieldSelectAutomationId, 'ACA_FOLDER_RULES.RULE_DETAILS.FIELDS.MIMETYPE'); expect(fixture.componentInstance.isComparatorHidden).toBeTruthy(); expect(getComputedStyle(comparatorFormField).display).toBe('none'); @@ -115,10 +114,10 @@ describe('RuleSimpleConditionUiComponent', () => { spyOn(fixture.componentInstance, 'onChangeField').and.callThrough(); const comparatorSelect = await loader.getHarness(MatSelectHarness.with({ selector: `[data-automation-id="${comparatorSelectAutomationId}"]` })); - await changeMatSelectValue(comparatorSelectAutomationId, 'contains'); + await changeMatSelectValue(comparatorSelectAutomationId, 'ACA_FOLDER_RULES.RULE_DETAILS.COMPARATORS.CONTAINS'); expect(await comparatorSelect.getValueText()).toBe(folderRulesBaseLabel + '.CONTAINS'); - await changeMatSelectValue(fieldSelectAutomationId, 'size'); + await changeMatSelectValue(fieldSelectAutomationId, 'ACA_FOLDER_RULES.RULE_DETAILS.FIELDS.SIZE'); expect(await comparatorSelect.getValueText()).toBe(folderRulesBaseLabel + '.EQUALS'); expect(fixture.componentInstance.onChangeField).toHaveBeenCalled(); }); @@ -138,7 +137,7 @@ describe('RuleSimpleConditionUiComponent', () => { it('should remove the option for the unknown field as soon as another option is selected', async () => { fixture.componentInstance.writeValue(simpleConditionUnknownFieldMock); fixture.detectChanges(); - await changeMatSelectValue(fieldSelectAutomationId, 'cm:name'); + await changeMatSelectValue(fieldSelectAutomationId, 'ACA_FOLDER_RULES.RULE_DETAILS.FIELDS.NAME'); const matSelect = unitTestingUtils.getByDataAutomationId(fieldSelectAutomationId).nativeElement; matSelect.click(); fixture.detectChanges(); @@ -192,7 +191,7 @@ describe('RuleSimpleConditionUiComponent', () => { it('should show loading spinner while auto-complete options are fetched, and then remove it once it is received', fakeAsync(async () => { spyOn(categoryService, 'searchCategories').and.returnValue(of(categoriesListMock).pipe(delay(1000))); fixture.detectChanges(); - await changeMatSelectValue(fieldSelectAutomationId, 'category'); + await changeMatSelectValue(fieldSelectAutomationId, 'ACA_FOLDER_RULES.RULE_DETAILS.FIELDS.HAS_CATEGORY'); tick(500); unitTestingUtils.getByDataAutomationId(autoCompleteInputFieldAutomationId)?.nativeElement?.click(); let loadingSpinner = unitTestingUtils.getByDataAutomationId(autoCompleteSpinnerAutomationId); @@ -210,14 +209,13 @@ describe('RuleSimpleConditionUiComponent', () => { }); it('should hide the comparator select box if the type of the field is autoComplete', async () => { - const autoCompleteField = 'category'; fixture.detectChanges(); const comparatorFormField = unitTestingUtils.getByDataAutomationId(comparatorFormFieldAutomationId).nativeElement; expect(fixture.componentInstance.isComparatorHidden).toBeFalsy(); expect(getComputedStyle(comparatorFormField).display).not.toBe('none'); - await changeMatSelectValue(fieldSelectAutomationId, autoCompleteField); + await changeMatSelectValue(fieldSelectAutomationId, 'ACA_FOLDER_RULES.RULE_DETAILS.FIELDS.HAS_CATEGORY'); expect(fixture.componentInstance.isComparatorHidden).toBeTruthy(); expect(getComputedStyle(comparatorFormField).display).toBe('none'); @@ -230,7 +228,7 @@ describe('RuleSimpleConditionUiComponent', () => { expect(fixture.componentInstance.isComparatorHidden).toBeFalsy(); expect(getComputedStyle(comparatorFormField).display).not.toBe('none'); - await changeMatSelectValue(fieldSelectAutomationId, 'category'); + await changeMatSelectValue(fieldSelectAutomationId, 'ACA_FOLDER_RULES.RULE_DETAILS.FIELDS.HAS_CATEGORY'); expect(fixture.componentInstance.isComparatorHidden).toBeTruthy(); expect(getComputedStyle(comparatorFormField).display).toBe('none'); @@ -238,7 +236,7 @@ describe('RuleSimpleConditionUiComponent', () => { it('should provide auto-complete option when category is selected', async () => { fixture.detectChanges(); - await changeMatSelectValue(fieldSelectAutomationId, 'category'); + await changeMatSelectValue(fieldSelectAutomationId, 'ACA_FOLDER_RULES.RULE_DETAILS.FIELDS.HAS_CATEGORY'); expect(unitTestingUtils.getByDataAutomationId(autoCompleteInputFieldAutomationId)).toBeTruthy(); expect(fixture.componentInstance.form.get('parameter').value).toEqual(''); @@ -246,7 +244,7 @@ describe('RuleSimpleConditionUiComponent', () => { it('should fetch category list when category option is selected', fakeAsync(async () => { fixture.detectChanges(); - await changeMatSelectValue(fieldSelectAutomationId, 'category'); + await changeMatSelectValue(fieldSelectAutomationId, 'ACA_FOLDER_RULES.RULE_DETAILS.FIELDS.HAS_CATEGORY'); tick(500); expect(categoryService.searchCategories).toHaveBeenCalledWith(''); @@ -256,7 +254,7 @@ describe('RuleSimpleConditionUiComponent', () => { const categoryValue = 'a new category'; fixture.detectChanges(); - await changeMatSelectValue(fieldSelectAutomationId, 'category'); + await changeMatSelectValue(fieldSelectAutomationId, 'ACA_FOLDER_RULES.RULE_DETAILS.FIELDS.HAS_CATEGORY'); tick(500); expect(categoryService.searchCategories).toHaveBeenCalledWith(''); @@ -267,10 +265,10 @@ describe('RuleSimpleConditionUiComponent', () => { it('should display correct label for category when user selects a category from auto-complete dropdown', fakeAsync(async () => { fixture.detectChanges(); - await changeMatSelectValue(fieldSelectAutomationId, 'category'); + await changeMatSelectValue(fieldSelectAutomationId, 'ACA_FOLDER_RULES.RULE_DETAILS.FIELDS.HAS_CATEGORY'); tick(500); unitTestingUtils.getByDataAutomationId(autoCompleteInputFieldAutomationId)?.nativeElement?.click(); - await changeMatAutocompleteValue(categoriesListMock.list.entries[0].entry.id); + await changeMatAutocompleteValue('category/path/1/FakeCategory1'); const displayValue = unitTestingUtils.getByDataAutomationId(autoCompleteInputFieldAutomationId)?.nativeElement?.value; expect(displayValue).toBe('category/path/1/FakeCategory1'); discardPeriodicTasks(); @@ -278,7 +276,7 @@ describe('RuleSimpleConditionUiComponent', () => { it('should automatically select first category when user focuses out of parameter form field with category option selected', fakeAsync(async () => { fixture.detectChanges(); - await changeMatSelectValue(fieldSelectAutomationId, 'category'); + await changeMatSelectValue(fieldSelectAutomationId, 'ACA_FOLDER_RULES.RULE_DETAILS.FIELDS.HAS_CATEGORY'); tick(500); const autoCompleteInputField = unitTestingUtils.getByDataAutomationId(autoCompleteInputFieldAutomationId)?.nativeElement; autoCompleteInputField.value = 'FakeCat'; diff --git a/projects/aca-playwright-shared/src/page-objects/components/adf-info-drawer.component.ts b/projects/aca-playwright-shared/src/page-objects/components/adf-info-drawer.component.ts index 8b8ec3d04..a14b3ec0c 100644 --- a/projects/aca-playwright-shared/src/page-objects/components/adf-info-drawer.component.ts +++ b/projects/aca-playwright-shared/src/page-objects/components/adf-info-drawer.component.ts @@ -23,7 +23,7 @@ */ import { BaseComponent } from './base.component'; -import { Page } from '@playwright/test'; +import { Locator, Page } from '@playwright/test'; export class AdfInfoDrawerComponent extends BaseComponent { private static rootElement = 'adf-info-drawer'; @@ -38,8 +38,8 @@ export class AdfInfoDrawerComponent extends BaseComponent { public getNameField = (labelText: string) => this.getChild(`[data-automation-id="library-name-properties-wrapper"] input[placeholder='${labelText}']`); public getIdField = (labelText: string) => this.getChild(`[data-automation-id="library-id-properties-wrapper"] input[placeholder='${labelText}']`); - public getVisibilityField = (labelText: string) => - this.getChild(`[data-automation-id="library-visibility-properties-wrapper"] [role="combobox"][ng-reflect-placeholder='${labelText}']`); + public getVisibilityField = (labelText: string): Locator => + this.getChild(`[data-automation-id="library-visibility-properties-wrapper"]`).getByLabel(labelText); public getDescriptionField = this.getChild('[data-automation-id="library-description-properties-wrapper"] textarea'); public propertiesTab = this.page.getByRole('tab', { name: 'Properties' }); public commentsTab = this.page.getByRole('tab', { name: 'Comments' });