From 80483a062837c21b240645ce7e392e20d5c4e160 Mon Sep 17 00:00:00 2001 From: "COVEO\\lvu" Date: Fri, 6 Dec 2024 16:48:45 -0500 Subject: [PATCH 01/11] SFINT-5832: Sorts e2e migrate from Cypress to Playwright --- .../default/lwc/quanticSort/e2e/fixture.ts | 112 ++++++++++++++++++ .../lwc/quanticSort/e2e/quanticSort.e2e.ts | 74 ++++++++++++ .../default/lwc/quanticSort/e2e/sortObject.ts | 76 ++++++++++++ 3 files changed, 262 insertions(+) create mode 100644 packages/quantic/force-app/main/default/lwc/quanticSort/e2e/fixture.ts create mode 100644 packages/quantic/force-app/main/default/lwc/quanticSort/e2e/quanticSort.e2e.ts create mode 100644 packages/quantic/force-app/main/default/lwc/quanticSort/e2e/sortObject.ts diff --git a/packages/quantic/force-app/main/default/lwc/quanticSort/e2e/fixture.ts b/packages/quantic/force-app/main/default/lwc/quanticSort/e2e/fixture.ts new file mode 100644 index 00000000000..35688459006 --- /dev/null +++ b/packages/quantic/force-app/main/default/lwc/quanticSort/e2e/fixture.ts @@ -0,0 +1,112 @@ +import {SortObject} from './sortObject'; +import {quanticBase} from '../../../../../../playwright/fixtures/baseFixture'; +import {SearchObject} from '../../../../../../playwright/page-object/searchObject'; +import { + searchRequestRegex, + insightSearchRequestRegex, +} from '../../../../../../playwright/utils/requests'; +import {InsightSetupObject} from '../../../../../../playwright/page-object/insightSetupObject'; +import {useCaseEnum} from '../../../../../../playwright/utils/useCase'; + +const pagerUrl = 's/quantic-sort'; + +interface SortOptions {} + +type QuanticSortE2EFixtures = { + sort: SortObject; + sortCustom: SortObject; + sortInvalid: SortObject; + search: SearchObject; + options: Partial; +}; + +type QuanticSortE2ESearchFixtures = QuanticSortE2EFixtures & { + urlHash: string; +}; + +type QuanticSortE2EInsightFixtures = QuanticSortE2ESearchFixtures & { + insightSetup: InsightSetupObject; +}; + +export const testSearch = quanticBase.extend({ + options: {}, + urlHash: '', + search: async ({page}, use) => { + await use(new SearchObject(page, searchRequestRegex)); + }, + + sort: async ({page, options, configuration, search, urlHash}, use) => { + await page.goto(urlHash ? `${pagerUrl}#${urlHash}` : pagerUrl); + configuration.configure(options); + await search.waitForSearchResponse(); + await use(new SortObject(page)); + }, + + sortCustom: async ({page, options, configuration, search, urlHash}, use) => { + await page.goto(urlHash ? `${pagerUrl}#${urlHash}` : pagerUrl); + await page.getByRole('button', {name: 'Add Custom Sort Options'}).click(); + configuration.configure(options); + await search.waitForSearchResponse(); + await use(new SortObject(page)); + }, + + sortInvalid: async ({page, options, configuration, search, urlHash}, use) => { + await page.goto(urlHash ? `${pagerUrl}#${urlHash}` : pagerUrl); + await page + .getByRole('button', {name: 'Add Invalid Custom Sort Options'}) + .click(); + configuration.configure(options); + await search.waitForSearchResponse(); + await use(new SortObject(page)); + }, +}); + +export const testInsight = quanticBase.extend({ + options: {}, + search: async ({page}, use) => { + await use(new SearchObject(page, insightSearchRequestRegex)); + }, + + insightSetup: async ({page}, use) => { + await use(new InsightSetupObject(page)); + }, + + sort: async ({page, options, search, configuration, insightSetup}, use) => { + await page.goto(pagerUrl); + configuration.configure({...options, useCase: useCaseEnum.insight}); + await insightSetup.waitForInsightInterfaceInitialization(); + await search.performSearch(); + await search.waitForSearchResponse(); + await use(new SortObject(page)); + }, + + sortCustom: async ( + {page, options, search, configuration, insightSetup}, + use + ) => { + await page.goto(pagerUrl); + await page.getByRole('button', {name: 'Add Custom Sort Options'}).click(); + configuration.configure({...options, useCase: useCaseEnum.insight}); + await insightSetup.waitForInsightInterfaceInitialization(); + await search.performSearch(); + await search.waitForSearchResponse(); + await use(new SortObject(page)); + }, + + sortInvalid: async ( + {page, options, search, configuration, insightSetup}, + use + ) => { + await page.goto(pagerUrl); + await page + .getByRole('button', {name: 'Add Invalid Custom Sort Options'}) + .click(); + configuration.configure({...options, useCase: useCaseEnum.insight}); + await insightSetup.waitForInsightInterfaceInitialization(); + await search.performSearch(); + await search.waitForSearchResponse(); + await use(new SortObject(page)); + }, +}); + +export {expect} from '@playwright/test'; diff --git a/packages/quantic/force-app/main/default/lwc/quanticSort/e2e/quanticSort.e2e.ts b/packages/quantic/force-app/main/default/lwc/quanticSort/e2e/quanticSort.e2e.ts new file mode 100644 index 00000000000..41f445dbe02 --- /dev/null +++ b/packages/quantic/force-app/main/default/lwc/quanticSort/e2e/quanticSort.e2e.ts @@ -0,0 +1,74 @@ +import {testSearch, testInsight, expect} from './fixture'; +import {useCaseTestCases} from '../../../../../../playwright/utils/useCase'; + +const newestDateSort = 'date descending'; +const viewsDescendingSort = '@ytviewcount descending'; +const defaultSortLabels = ['Relevancy', 'Newest', 'Oldest']; + +const fixtures = { + search: testSearch, + insight: testInsight, +}; + +useCaseTestCases.forEach((useCase) => { + let test = fixtures[useCase.value]; + + test.describe(`quantic sort ${useCase.label}`, () => { + test.describe(`when changing sort option to Newest`, () => { + test('should trigger a new search and log analytics', async ({ + sort, + search, + }) => { + const searchResponsePromise = search.waitForSearchResponse(); + await sort.clickSortDropDown(); + await sort.clickSortButton('Newest'); + const searchResponse = await searchResponsePromise; + const {sortCriteria} = searchResponse.request().postDataJSON(); + expect(sortCriteria).toBe(newestDateSort); + await sort.waitForSortUaAnalytics(newestDateSort); + }); + }); + + test.describe(`when changing custom sort to "Views Descending`, () => { + test('should trigger a new search and log analytics', async ({ + sortCustom, + search, + }) => { + const searchResponsePromise = search.waitForSearchResponse(); + await sortCustom.clickSortDropDown(); + await sortCustom.clickSortButton('Views Descending'); + const searchResponse = await searchResponsePromise; + const {sortCriteria} = searchResponse.request().postDataJSON(); + expect(sortCriteria).toBe(viewsDescendingSort); + await sortCustom.waitForSortUaAnalytics(viewsDescendingSort); + }); + }); + + test.describe(`when the custom option passed has an invalid property`, () => { + test('should display an error message instead of the quanticSort component', async ({ + sortInvalid, + }) => { + await sortInvalid.invalidSortMessage(); + }); + }); + + test.describe('when testing accessibility', () => { + test('should be accessible to keyboard', async ({sort}) => { + let selectedSortLabel = await sort.sortDropDown.textContent(); + expect(selectedSortLabel).toEqual(defaultSortLabels[0]); + + // Selecting the next sort using the ArrowDown, then ENTER key + await sort.focusSortDropDownEnter(); + await sort.selectSortButtonKeyboard(); + selectedSortLabel = await sort.sortDropDown.textContent(); + expect(selectedSortLabel).toEqual(defaultSortLabels[1]); + + // Selecting the next sort using the ArrowDown, then ENTER key + await sort.focusSortDropDownEnter(); + await sort.selectSortButtonKeyboard(); + selectedSortLabel = await sort.sortDropDown.textContent(); + expect(selectedSortLabel).toEqual(defaultSortLabels[2]); + }); + }); + }); +}); diff --git a/packages/quantic/force-app/main/default/lwc/quanticSort/e2e/sortObject.ts b/packages/quantic/force-app/main/default/lwc/quanticSort/e2e/sortObject.ts new file mode 100644 index 00000000000..c1e07792b4a --- /dev/null +++ b/packages/quantic/force-app/main/default/lwc/quanticSort/e2e/sortObject.ts @@ -0,0 +1,76 @@ +import {Locator, Page, Request} from '@playwright/test'; +import {isUaSearchEvent} from '../../../../../../playwright/utils/requests'; + +export class SortObject { + constructor(public page: Page) { + this.page = page; + } + + get sortDropDown(): Locator { + return this.page.getByRole('combobox', {name: 'Sort by'}); + } + + get sortPreviewHeader(): Locator { + return this.page.getByRole('button', {name: 'Preview'}); + } + + get invalidMessage(): Locator { + return this.page + .locator('p') + .filter({hasText: 'Custom sort options configuration is invalid.'}); + } + + sortButton(buttonName: string): Locator { + return this.page.getByRole('option', {name: buttonName}); + } + + async clickSortDropDown(): Promise { + await this.sortDropDown.click(); + } + + async focusSortDropDownEnter(): Promise { + await this.sortPreviewHeader.click(); + await this.page.keyboard.press('Tab'); + } + + async clickSortButton(buttonName: string): Promise { + await this.sortButton(buttonName).click(); + } + + async selectSortButtonKeyboard(): Promise { + await this.page.keyboard.press('Enter'); + await this.sortButton('Oldest').isVisible(); + await this.page.waitForTimeout(500); + await this.page.keyboard.press('ArrowDown'); + await this.page.keyboard.press('Enter'); + } + + async invalidSortMessage(): Promise { + await this.invalidMessage.isVisible(); + } + + async waitForSortUaAnalytics(eventValue: any): Promise { + const uaRequest = this.page.waitForRequest((request) => { + if (isUaSearchEvent(request)) { + const requestBody = request.postDataJSON(); + const expectedFields = { + actionCause: 'resultsSort', + customData: { + resultsSortBy: eventValue, + }, + }; + + const validateObject = (obj: any, expectedResult: any): boolean => + Object.entries(expectedResult).every(([key, value]) => + value && typeof value === 'object' + ? validateObject(obj?.[key], value) + : obj?.[key] === value + ); + + return validateObject(requestBody, expectedFields); + } + return false; + }); + return uaRequest; + } +} From 9abd2b7476c1691522a67116a0f74ec3e582930f Mon Sep 17 00:00:00 2001 From: mmitiche Date: Fri, 27 Dec 2024 14:23:05 +0100 Subject: [PATCH 02/11] unit tests added --- .../quanticSort/__tests__/quanticSort.test.js | 266 +++++++++++++++--- .../default/lwc/quanticSort/e2e/fixture.ts | 2 +- .../e2e/{sortObject.ts => pageObject.ts} | 0 .../default/lwc/quanticSort/quanticSort.js | 11 +- 4 files changed, 238 insertions(+), 41 deletions(-) rename packages/quantic/force-app/main/default/lwc/quanticSort/e2e/{sortObject.ts => pageObject.ts} (100%) diff --git a/packages/quantic/force-app/main/default/lwc/quanticSort/__tests__/quanticSort.test.js b/packages/quantic/force-app/main/default/lwc/quanticSort/__tests__/quanticSort.test.js index 06c38f3510b..c7655a5dfe6 100644 --- a/packages/quantic/force-app/main/default/lwc/quanticSort/__tests__/quanticSort.test.js +++ b/packages/quantic/force-app/main/default/lwc/quanticSort/__tests__/quanticSort.test.js @@ -5,6 +5,13 @@ import QuanticSort from 'c/quanticSort'; import {createElement} from 'lwc'; import * as mockHeadlessLoader from 'c/quanticHeadlessLoader'; +const selectors = { + lightningCombobox: 'lightning-combobox', + componentError: 'c-quantic-component-error', + sortDropdown: '[data-cy="sort-dropdown"]', + initializationError: 'c-quantic-component-error', +}; + const sortVariants = { default: { name: 'default', @@ -20,25 +27,47 @@ const sortVariants = { }, }; +const sortByLabel = 'Sort By'; + jest.mock('c/quanticHeadlessLoader'); -jest.mock('@salesforce/label/c.quantic_SortBy', () => ({default: 'Sort By'}), { - virtual: true, -}); +jest.mock( + '@salesforce/label/c.quantic_SortBy', + () => ({default: sortByLabel}), + { + virtual: true, + } +); + +let buenoMock = { + isString: jest + .fn() + .mockImplementation( + (value) => Object.prototype.toString.call(value) === '[object String]' + ), + StringValue: jest.fn(), + RecordValue: jest.fn(), + Schema: jest.fn(() => ({ + validate: jest.fn(), + })), +}; + +const successfulBuenoValidationMock = buenoMock; +const unsuccessfulBuenoValidationMock = { + ...buenoMock, + Schema: jest.fn(() => ({ + validate: () => { + throw new Error(); + }, + })), +}; function mockBueno() { - jest.spyOn(mockHeadlessLoader, 'getBueno').mockReturnValue( - new Promise(() => { - // @ts-ignore - global.Bueno = { - isString: jest - .fn() - .mockImplementation( - (value) => - Object.prototype.toString.call(value) === '[object String]' - ), - }; - }) - ); + // @ts-ignore + mockHeadlessLoader.getBueno = () => { + // @ts-ignore + global.Bueno = buenoMock; + return new Promise((resolve) => resolve()); + }; } let isInitialized = false; @@ -47,32 +76,35 @@ const exampleEngine = { id: 'exampleEngineId', }; -const mockSearchStatusState = { +const defaultSearchStatusState = { hasResults: true, }; - -const mockSearchStatus = { - state: mockSearchStatusState, - subscribe: jest.fn((callback) => { - callback(); - return jest.fn(); - }), -}; +let searchStatusState = defaultSearchStatusState; const functionsMocks = { buildSort: jest.fn(() => ({ state: {}, - subscribe: functionsMocks.subscribe, + subscribe: functionsMocks.sortStateSubscriber, + sortBy: functionsMocks.sortBy, + })), + buildSearchStatus: jest.fn(() => ({ + state: searchStatusState, + subscribe: functionsMocks.searchStatusStateSubscriber, })), buildCriterionExpression: jest.fn((criterion) => criterion), buildRelevanceSortCriterion: jest.fn(() => 'relevance'), buildDateSortCriterion: jest.fn(() => 'date'), - buildSearchStatus: jest.fn(() => mockSearchStatus), - subscribe: jest.fn((cb) => { + sortStateSubscriber: jest.fn((cb) => { cb(); - return functionsMocks.unsubscribe; + return functionsMocks.sortStateUnsubscriber; }), - unsubscribe: jest.fn(() => {}), + searchStatusStateSubscriber: jest.fn((cb) => { + cb(); + return functionsMocks.searchStatusStateUnsubscriber; + }), + sortStateUnsubscriber: jest.fn(), + searchStatusStateUnsubscriber: jest.fn(), + sortBy: jest.fn(), }; const defaultOptions = { @@ -80,10 +112,19 @@ const defaultOptions = { variant: 'default', }; -const expectedSortByLabel = 'Sort By'; +/** + * Mocks the return value of the assignedNodes method. + * @param {Array} assignedElements + */ +function mockSlotAssignedNodes(assignedElements) { + HTMLSlotElement.prototype.assignedNodes = function () { + return assignedElements; + }; +} -function createTestComponent(options = defaultOptions) { +function createTestComponent(options = defaultOptions, assignedElements = []) { prepareHeadlessState(); + mockSlotAssignedNodes(assignedElements); const element = createElement('c-quantic-sort', { is: QuanticSort, @@ -128,6 +169,15 @@ function mockSuccessfulHeadlessInitialization() { }; } +function mockErroneousHeadlessInitialization() { + // @ts-ignore + mockHeadlessLoader.initializeWithHeadless = (element) => { + if (element instanceof QuanticSort) { + element.setInitializationError(); + } + }; +} + function cleanup() { // The jsdom instance is shared across test cases in a single file so reset the DOM while (document.body.firstChild) { @@ -145,14 +195,158 @@ describe('c-quantic-sort', () => { afterEach(() => { cleanup(); + searchStatusState = defaultSearchStatusState; + }); + + describe('when an initialization error occurs', () => { + beforeEach(() => { + mockErroneousHeadlessInitialization(); + }); + + afterAll(() => { + mockSuccessfulHeadlessInitialization(); + }); + + it('should display the initialization error component', async () => { + const element = createTestComponent(); + await flushPromises(); + + const initializationError = element.shadowRoot.querySelector( + selectors.initializationError + ); + + expect(initializationError).not.toBeNull(); + }); }); describe('controller initialization', () => { - it('should subscribe to the headless state changes', async () => { + it('should subscribe to the headless sort and search status state changes', async () => { createTestComponent(); await flushPromises(); - expect(functionsMocks.subscribe).toHaveBeenCalledTimes(1); + expect(functionsMocks.sortStateSubscriber).toHaveBeenCalledTimes(1); + expect(functionsMocks.searchStatusStateSubscriber).toHaveBeenCalledTimes( + 1 + ); + }); + }); + + describe('when no results are found', () => { + beforeAll(() => { + searchStatusState = {...defaultSearchStatusState, hasResults: false}; + }); + + it('should not display the sort dropdown', async () => { + const element = createTestComponent(); + await flushPromises(); + + const sortDropdown = element.shadowRoot.querySelector( + selectors.sortDropdown + ); + + expect(sortDropdown).toBeNull(); + }); + }); + + describe('when a sort option is selected', () => { + it('should call the sortBy method of the sort controller', async () => { + const element = createTestComponent(); + await flushPromises(); + + const lightningCombobox = element.shadowRoot.querySelector( + selectors.lightningCombobox + ); + const exampleDefaultSortOptionValue = 'relevance'; + expect(lightningCombobox).not.toBeNull(); + + lightningCombobox.dispatchEvent( + new CustomEvent('change', { + detail: {value: exampleDefaultSortOptionValue}, + }) + ); + + expect(functionsMocks.sortBy).toHaveBeenCalledTimes(1); + expect(functionsMocks.sortBy).toHaveBeenCalledWith( + exampleDefaultSortOptionValue + ); + }); + }); + + describe('when custom sort options are passed', () => { + const exampleSlot = { + value: 'example value', + label: 'example label', + criterion: { + by: 'example field', + order: 'example order', + }, + }; + const exampleAssignedElements = [exampleSlot]; + + it('should build the controller with the correct sort option and display the custom sort options', async () => { + const element = createTestComponent( + defaultOptions, + exampleAssignedElements + ); + await flushPromises(); + + expect(functionsMocks.buildSort).toHaveBeenCalledTimes(1); + expect(functionsMocks.buildSort).toHaveBeenCalledWith(exampleEngine, { + initialState: { + criterion: { + by: 'example field', + order: 'example order', + }, + }, + }); + const lightningCombobox = element.shadowRoot.querySelector( + selectors.lightningCombobox + ); + + expect(lightningCombobox.options).toEqual([exampleSlot]); + }); + }); + + describe('when invalid sort options are passed', () => { + beforeEach(() => { + // @ts-ignore + buenoMock = unsuccessfulBuenoValidationMock; + }); + + afterAll(() => { + buenoMock = successfulBuenoValidationMock; + }); + const invalidExampleSlot = { + value: 'example value', + label: '', + criterion: { + by: 'example field', + order: 'example order', + }, + }; + const exampleAssignedElements = [invalidExampleSlot]; + + it('should display the component error', async () => { + const element = createTestComponent( + defaultOptions, + exampleAssignedElements + ); + await flushPromises(); + + expect(functionsMocks.buildSort).toHaveBeenCalledTimes(1); + expect(functionsMocks.buildSort).toHaveBeenCalledWith(exampleEngine, { + initialState: { + criterion: { + by: 'example field', + order: 'example order', + }, + }, + }); + const componentError = element.shadowRoot.querySelector( + selectors.componentError + ); + + expect(componentError).not.toBeNull(); }); }); @@ -187,7 +381,7 @@ describe('c-quantic-sort', () => { const sortLabel = element.shadowRoot.querySelector(variant.labelSelector); - expect(sortLabel.value).toBe(expectedSortByLabel); + expect(sortLabel.value).toBe(sortByLabel); }); }); @@ -228,7 +422,7 @@ describe('c-quantic-sort', () => { const sortLabel = element.shadowRoot.querySelector(variant.labelSelector); - expect(sortLabel.textContent).toBe(expectedSortByLabel); + expect(sortLabel.textContent).toBe(sortByLabel); expect(sortLabel.classList).toContain('slds-text-heading_small'); }); }); diff --git a/packages/quantic/force-app/main/default/lwc/quanticSort/e2e/fixture.ts b/packages/quantic/force-app/main/default/lwc/quanticSort/e2e/fixture.ts index 35688459006..c8db3232549 100644 --- a/packages/quantic/force-app/main/default/lwc/quanticSort/e2e/fixture.ts +++ b/packages/quantic/force-app/main/default/lwc/quanticSort/e2e/fixture.ts @@ -1,4 +1,4 @@ -import {SortObject} from './sortObject'; +import {SortObject} from './pageObject'; import {quanticBase} from '../../../../../../playwright/fixtures/baseFixture'; import {SearchObject} from '../../../../../../playwright/page-object/searchObject'; import { diff --git a/packages/quantic/force-app/main/default/lwc/quanticSort/e2e/sortObject.ts b/packages/quantic/force-app/main/default/lwc/quanticSort/e2e/pageObject.ts similarity index 100% rename from packages/quantic/force-app/main/default/lwc/quanticSort/e2e/sortObject.ts rename to packages/quantic/force-app/main/default/lwc/quanticSort/e2e/pageObject.ts diff --git a/packages/quantic/force-app/main/default/lwc/quanticSort/quanticSort.js b/packages/quantic/force-app/main/default/lwc/quanticSort/quanticSort.js index e7a99a42ec3..335142962c8 100644 --- a/packages/quantic/force-app/main/default/lwc/quanticSort/quanticSort.js +++ b/packages/quantic/force-app/main/default/lwc/quanticSort/quanticSort.js @@ -167,11 +167,12 @@ export default class QuanticSort extends LightningElement { } /** - * @param {CustomEvent<{value: string}>} e + * @param {CustomEvent<{value: string}>} event */ - handleChange(e) { + handleChange(event) { this.sort.sortBy( - this.options.find((option) => option.value === e.detail.value).criterion + this.options.find((option) => option.value === event.detail.value) + .criterion ); } @@ -280,8 +281,10 @@ export default class QuanticSort extends LightningElement { * @returns {SortOption[]} The specified custom sort options. */ get customSortOptions() { + /** @type {HTMLSlotElement} */ + const slot = this.template.querySelector('slot[name="sortOption"]'); /** @type {SortOption[]} */ - return Array.from(this.querySelectorAll('c-quantic-sort-option')).map( + return Array.from(slot?.assignedNodes()).map( // @ts-ignore ({label, value, criterion}) => ({label, value, criterion}) ); From e365d5516bbf420e2f229d808c72028083d5b609 Mon Sep 17 00:00:00 2001 From: "COVEO\\lvu" Date: Fri, 27 Dec 2024 17:13:21 -0500 Subject: [PATCH 03/11] SFINT-5832 Update test --- .../default/lwc/quanticSort/e2e/fixture.ts | 56 ++------------- .../default/lwc/quanticSort/e2e/pageObject.ts | 25 +++---- .../lwc/quanticSort/e2e/quanticSort.e2e.ts | 69 ++++++++++--------- 3 files changed, 50 insertions(+), 100 deletions(-) diff --git a/packages/quantic/force-app/main/default/lwc/quanticSort/e2e/fixture.ts b/packages/quantic/force-app/main/default/lwc/quanticSort/e2e/fixture.ts index c8db3232549..4d91b1b56c3 100644 --- a/packages/quantic/force-app/main/default/lwc/quanticSort/e2e/fixture.ts +++ b/packages/quantic/force-app/main/default/lwc/quanticSort/e2e/fixture.ts @@ -8,14 +8,12 @@ import { import {InsightSetupObject} from '../../../../../../playwright/page-object/insightSetupObject'; import {useCaseEnum} from '../../../../../../playwright/utils/useCase'; -const pagerUrl = 's/quantic-sort'; +const pageUrl = 's/quantic-sort'; interface SortOptions {} type QuanticSortE2EFixtures = { sort: SortObject; - sortCustom: SortObject; - sortInvalid: SortObject; search: SearchObject; options: Partial; }; @@ -24,7 +22,7 @@ type QuanticSortE2ESearchFixtures = QuanticSortE2EFixtures & { urlHash: string; }; -type QuanticSortE2EInsightFixtures = QuanticSortE2ESearchFixtures & { +type QuanticSortE2EInsightFixtures = QuanticSortE2EFixtures & { insightSetup: InsightSetupObject; }; @@ -36,25 +34,7 @@ export const testSearch = quanticBase.extend({ }, sort: async ({page, options, configuration, search, urlHash}, use) => { - await page.goto(urlHash ? `${pagerUrl}#${urlHash}` : pagerUrl); - configuration.configure(options); - await search.waitForSearchResponse(); - await use(new SortObject(page)); - }, - - sortCustom: async ({page, options, configuration, search, urlHash}, use) => { - await page.goto(urlHash ? `${pagerUrl}#${urlHash}` : pagerUrl); - await page.getByRole('button', {name: 'Add Custom Sort Options'}).click(); - configuration.configure(options); - await search.waitForSearchResponse(); - await use(new SortObject(page)); - }, - - sortInvalid: async ({page, options, configuration, search, urlHash}, use) => { - await page.goto(urlHash ? `${pagerUrl}#${urlHash}` : pagerUrl); - await page - .getByRole('button', {name: 'Add Invalid Custom Sort Options'}) - .click(); + await page.goto(urlHash ? `${pageUrl}#${urlHash}` : pageUrl); configuration.configure(options); await search.waitForSearchResponse(); await use(new SortObject(page)); @@ -72,35 +52,7 @@ export const testInsight = quanticBase.extend({ }, sort: async ({page, options, search, configuration, insightSetup}, use) => { - await page.goto(pagerUrl); - configuration.configure({...options, useCase: useCaseEnum.insight}); - await insightSetup.waitForInsightInterfaceInitialization(); - await search.performSearch(); - await search.waitForSearchResponse(); - await use(new SortObject(page)); - }, - - sortCustom: async ( - {page, options, search, configuration, insightSetup}, - use - ) => { - await page.goto(pagerUrl); - await page.getByRole('button', {name: 'Add Custom Sort Options'}).click(); - configuration.configure({...options, useCase: useCaseEnum.insight}); - await insightSetup.waitForInsightInterfaceInitialization(); - await search.performSearch(); - await search.waitForSearchResponse(); - await use(new SortObject(page)); - }, - - sortInvalid: async ( - {page, options, search, configuration, insightSetup}, - use - ) => { - await page.goto(pagerUrl); - await page - .getByRole('button', {name: 'Add Invalid Custom Sort Options'}) - .click(); + await page.goto(pageUrl); configuration.configure({...options, useCase: useCaseEnum.insight}); await insightSetup.waitForInsightInterfaceInitialization(); await search.performSearch(); diff --git a/packages/quantic/force-app/main/default/lwc/quanticSort/e2e/pageObject.ts b/packages/quantic/force-app/main/default/lwc/quanticSort/e2e/pageObject.ts index c1e07792b4a..8eb72f25bb2 100644 --- a/packages/quantic/force-app/main/default/lwc/quanticSort/e2e/pageObject.ts +++ b/packages/quantic/force-app/main/default/lwc/quanticSort/e2e/pageObject.ts @@ -1,4 +1,4 @@ -import {Locator, Page, Request} from '@playwright/test'; +import type {Locator, Page, Request} from '@playwright/test'; import {isUaSearchEvent} from '../../../../../../playwright/utils/requests'; export class SortObject { @@ -14,12 +14,6 @@ export class SortObject { return this.page.getByRole('button', {name: 'Preview'}); } - get invalidMessage(): Locator { - return this.page - .locator('p') - .filter({hasText: 'Custom sort options configuration is invalid.'}); - } - sortButton(buttonName: string): Locator { return this.page.getByRole('option', {name: buttonName}); } @@ -28,7 +22,7 @@ export class SortObject { await this.sortDropDown.click(); } - async focusSortDropDownEnter(): Promise { + async focusSortDropDown(): Promise { await this.sortPreviewHeader.click(); await this.page.keyboard.press('Tab'); } @@ -37,18 +31,21 @@ export class SortObject { await this.sortButton(buttonName).click(); } - async selectSortButtonKeyboard(): Promise { - await this.page.keyboard.press('Enter'); + async openSortDropdownUsingEnter(useEnter = true): Promise { + if (useEnter) { + await this.page.keyboard.press('Enter'); + } else { + await this.page.keyboard.press('Space'); + } + } + + async selectSortOptionUsingArrow(): Promise { await this.sortButton('Oldest').isVisible(); await this.page.waitForTimeout(500); await this.page.keyboard.press('ArrowDown'); await this.page.keyboard.press('Enter'); } - async invalidSortMessage(): Promise { - await this.invalidMessage.isVisible(); - } - async waitForSortUaAnalytics(eventValue: any): Promise { const uaRequest = this.page.waitForRequest((request) => { if (isUaSearchEvent(request)) { diff --git a/packages/quantic/force-app/main/default/lwc/quanticSort/e2e/quanticSort.e2e.ts b/packages/quantic/force-app/main/default/lwc/quanticSort/e2e/quanticSort.e2e.ts index 41f445dbe02..1463e75db5b 100644 --- a/packages/quantic/force-app/main/default/lwc/quanticSort/e2e/quanticSort.e2e.ts +++ b/packages/quantic/force-app/main/default/lwc/quanticSort/e2e/quanticSort.e2e.ts @@ -1,17 +1,24 @@ import {testSearch, testInsight, expect} from './fixture'; -import {useCaseTestCases} from '../../../../../../playwright/utils/useCase'; +import { + useCaseEnum, + useCaseTestCases, +} from '../../../../../../playwright/utils/useCase'; const newestDateSort = 'date descending'; -const viewsDescendingSort = '@ytviewcount descending'; const defaultSortLabels = ['Relevancy', 'Newest', 'Oldest']; const fixtures = { - search: testSearch, - insight: testInsight, + search: testSearch as typeof testSearch, + insight: testInsight as typeof testInsight, }; useCaseTestCases.forEach((useCase) => { - let test = fixtures[useCase.value]; + let test; + if (useCase.value === useCaseEnum.search) { + test = fixtures[useCase.value] as typeof testSearch; + } else { + test = fixtures[useCase.value] as typeof testInsight; + } test.describe(`quantic sort ${useCase.label}`, () => { test.describe(`when changing sort option to Newest`, () => { @@ -29,46 +36,40 @@ useCaseTestCases.forEach((useCase) => { }); }); - test.describe(`when changing custom sort to "Views Descending`, () => { - test('should trigger a new search and log analytics', async ({ - sortCustom, - search, - }) => { - const searchResponsePromise = search.waitForSearchResponse(); - await sortCustom.clickSortDropDown(); - await sortCustom.clickSortButton('Views Descending'); - const searchResponse = await searchResponsePromise; - const {sortCriteria} = searchResponse.request().postDataJSON(); - expect(sortCriteria).toBe(viewsDescendingSort); - await sortCustom.waitForSortUaAnalytics(viewsDescendingSort); - }); - }); - - test.describe(`when the custom option passed has an invalid property`, () => { - test('should display an error message instead of the quanticSort component', async ({ - sortInvalid, - }) => { - await sortInvalid.invalidSortMessage(); - }); - }); - test.describe('when testing accessibility', () => { test('should be accessible to keyboard', async ({sort}) => { let selectedSortLabel = await sort.sortDropDown.textContent(); expect(selectedSortLabel).toEqual(defaultSortLabels[0]); - // Selecting the next sort using the ArrowDown, then ENTER key - await sort.focusSortDropDownEnter(); - await sort.selectSortButtonKeyboard(); + // Selecting the next sort using Enter to open dropdown, the ArrowDown, then ENTER key + await sort.focusSortDropDown(); + await sort.openSortDropdownUsingEnter(); + await sort.selectSortOptionUsingArrow(); selectedSortLabel = await sort.sortDropDown.textContent(); expect(selectedSortLabel).toEqual(defaultSortLabels[1]); - // Selecting the next sort using the ArrowDown, then ENTER key - await sort.focusSortDropDownEnter(); - await sort.selectSortButtonKeyboard(); + // Selecting the next sort using Space to open dropdown, the ArrowDown, then ENTER key + await sort.focusSortDropDown(); + await sort.openSortDropdownUsingEnter(false); + await sort.selectSortOptionUsingArrow(); selectedSortLabel = await sort.sortDropDown.textContent(); expect(selectedSortLabel).toEqual(defaultSortLabels[2]); }); }); + + if (useCase.value === 'search') { + test.describe('when loading options from the url', () => { + test.use({ + urlHash: 'sortCriteria=date%20ascending', + }); + + test('should reflect the options of url in the component', async ({ + sort, + }) => { + const expectedSort = 'Oldest'; + await expect(sort.sortDropDown).toContainText(expectedSort); + }); + }); + } }); }); From 45934bc68414969f5226ee38f42205ecd2e0d11e Mon Sep 17 00:00:00 2001 From: "COVEO\\lvu" Date: Fri, 27 Dec 2024 17:31:44 -0500 Subject: [PATCH 04/11] SFINT-5832 Fix button name --- .../force-app/main/default/lwc/quanticSort/e2e/pageObject.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/quantic/force-app/main/default/lwc/quanticSort/e2e/pageObject.ts b/packages/quantic/force-app/main/default/lwc/quanticSort/e2e/pageObject.ts index 8eb72f25bb2..b95d6294f69 100644 --- a/packages/quantic/force-app/main/default/lwc/quanticSort/e2e/pageObject.ts +++ b/packages/quantic/force-app/main/default/lwc/quanticSort/e2e/pageObject.ts @@ -10,7 +10,7 @@ export class SortObject { return this.page.getByRole('combobox', {name: 'Sort by'}); } - get sortPreviewHeader(): Locator { + get sortPreviewButton(): Locator { return this.page.getByRole('button', {name: 'Preview'}); } @@ -23,7 +23,7 @@ export class SortObject { } async focusSortDropDown(): Promise { - await this.sortPreviewHeader.click(); + await this.sortPreviewButton.click(); await this.page.keyboard.press('Tab'); } From 46d133e84c338abad7801cc01199cbc1c9981742 Mon Sep 17 00:00:00 2001 From: "COVEO\\lvu" Date: Tue, 21 Jan 2025 16:17:53 -0500 Subject: [PATCH 05/11] SFINT-5832 Update path name + remove empty space --- .../main/default/lwc/quanticSort/e2e/fixture.ts | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/packages/quantic/force-app/main/default/lwc/quanticSort/e2e/fixture.ts b/packages/quantic/force-app/main/default/lwc/quanticSort/e2e/fixture.ts index 4d91b1b56c3..fb0f0d1dc4d 100644 --- a/packages/quantic/force-app/main/default/lwc/quanticSort/e2e/fixture.ts +++ b/packages/quantic/force-app/main/default/lwc/quanticSort/e2e/fixture.ts @@ -8,7 +8,7 @@ import { import {InsightSetupObject} from '../../../../../../playwright/page-object/insightSetupObject'; import {useCaseEnum} from '../../../../../../playwright/utils/useCase'; -const pageUrl = 's/quantic-sort'; +const sortUrl = 's/quantic-sort'; interface SortOptions {} @@ -32,9 +32,8 @@ export const testSearch = quanticBase.extend({ search: async ({page}, use) => { await use(new SearchObject(page, searchRequestRegex)); }, - sort: async ({page, options, configuration, search, urlHash}, use) => { - await page.goto(urlHash ? `${pageUrl}#${urlHash}` : pageUrl); + await page.goto(urlHash ? `${sortUrl}#${urlHash}` : sortUrl); configuration.configure(options); await search.waitForSearchResponse(); await use(new SortObject(page)); @@ -46,13 +45,11 @@ export const testInsight = quanticBase.extend({ search: async ({page}, use) => { await use(new SearchObject(page, insightSearchRequestRegex)); }, - insightSetup: async ({page}, use) => { await use(new InsightSetupObject(page)); }, - sort: async ({page, options, search, configuration, insightSetup}, use) => { - await page.goto(pageUrl); + await page.goto(sortUrl); configuration.configure({...options, useCase: useCaseEnum.insight}); await insightSetup.waitForInsightInterfaceInitialization(); await search.performSearch(); From 1264be9f5a5f337c9e61f0a3a8da5500880c2f0b Mon Sep 17 00:00:00 2001 From: mmitiche Date: Fri, 24 Jan 2025 09:59:35 -0500 Subject: [PATCH 06/11] feedback on unit tests added --- .../quanticSort/__tests__/quanticSort.test.js | 51 ++++++++----------- 1 file changed, 21 insertions(+), 30 deletions(-) diff --git a/packages/quantic/force-app/main/default/lwc/quanticSort/__tests__/quanticSort.test.js b/packages/quantic/force-app/main/default/lwc/quanticSort/__tests__/quanticSort.test.js index c7655a5dfe6..c218f295dbb 100644 --- a/packages/quantic/force-app/main/default/lwc/quanticSort/__tests__/quanticSort.test.js +++ b/packages/quantic/force-app/main/default/lwc/quanticSort/__tests__/quanticSort.test.js @@ -38,34 +38,27 @@ jest.mock( } ); -let buenoMock = { - isString: jest - .fn() - .mockImplementation( - (value) => Object.prototype.toString.call(value) === '[object String]' - ), - StringValue: jest.fn(), - RecordValue: jest.fn(), - Schema: jest.fn(() => ({ - validate: jest.fn(), - })), -}; - -const successfulBuenoValidationMock = buenoMock; -const unsuccessfulBuenoValidationMock = { - ...buenoMock, - Schema: jest.fn(() => ({ - validate: () => { - throw new Error(); - }, - })), -}; - -function mockBueno() { +function mockBueno(shouldError = false) { // @ts-ignore mockHeadlessLoader.getBueno = () => { // @ts-ignore - global.Bueno = buenoMock; + global.Bueno = { + isString: jest + .fn() + .mockImplementation( + (value) => Object.prototype.toString.call(value) === '[object String]' + ), + StringValue: jest.fn(), + RecordValue: jest.fn(), + Schema: jest.fn(() => ({ + validate: () => { + if (shouldError) { + throw new Error(); + } + jest.fn(); + }, + })), + }; return new Promise((resolve) => resolve()); }; } @@ -309,13 +302,10 @@ describe('c-quantic-sort', () => { describe('when invalid sort options are passed', () => { beforeEach(() => { - // @ts-ignore - buenoMock = unsuccessfulBuenoValidationMock; + mockBueno(true); + jest.spyOn(console, 'error').mockImplementation(() => {}); }); - afterAll(() => { - buenoMock = successfulBuenoValidationMock; - }); const invalidExampleSlot = { value: 'example value', label: '', @@ -347,6 +337,7 @@ describe('c-quantic-sort', () => { ); expect(componentError).not.toBeNull(); + expect(console.error).toHaveBeenCalledTimes(1); }); }); From 3a8ae439f8a8db6d684d7752cf04d79dc3c04c72 Mon Sep 17 00:00:00 2001 From: "COVEO\\lvu" Date: Wed, 29 Jan 2025 10:38:24 -0500 Subject: [PATCH 07/11] SFINT-5832 Fix comments --- .../main/default/lwc/quanticSort/e2e/pageObject.ts | 7 +------ .../default/lwc/quanticSort/e2e/quanticSort.e2e.ts | 12 +++++++----- 2 files changed, 8 insertions(+), 11 deletions(-) diff --git a/packages/quantic/force-app/main/default/lwc/quanticSort/e2e/pageObject.ts b/packages/quantic/force-app/main/default/lwc/quanticSort/e2e/pageObject.ts index b95d6294f69..6202ffc1eb7 100644 --- a/packages/quantic/force-app/main/default/lwc/quanticSort/e2e/pageObject.ts +++ b/packages/quantic/force-app/main/default/lwc/quanticSort/e2e/pageObject.ts @@ -31,19 +31,14 @@ export class SortObject { await this.sortButton(buttonName).click(); } - async openSortDropdownUsingEnter(useEnter = true): Promise { + async openSortDropdownUsingKeyboardEnter(useEnter = true): Promise { if (useEnter) { await this.page.keyboard.press('Enter'); } else { await this.page.keyboard.press('Space'); } - } - - async selectSortOptionUsingArrow(): Promise { await this.sortButton('Oldest').isVisible(); await this.page.waitForTimeout(500); - await this.page.keyboard.press('ArrowDown'); - await this.page.keyboard.press('Enter'); } async waitForSortUaAnalytics(eventValue: any): Promise { diff --git a/packages/quantic/force-app/main/default/lwc/quanticSort/e2e/quanticSort.e2e.ts b/packages/quantic/force-app/main/default/lwc/quanticSort/e2e/quanticSort.e2e.ts index 1463e75db5b..5aae060612c 100644 --- a/packages/quantic/force-app/main/default/lwc/quanticSort/e2e/quanticSort.e2e.ts +++ b/packages/quantic/force-app/main/default/lwc/quanticSort/e2e/quanticSort.e2e.ts @@ -37,21 +37,23 @@ useCaseTestCases.forEach((useCase) => { }); test.describe('when testing accessibility', () => { - test('should be accessible to keyboard', async ({sort}) => { + test('should be accessible to keyboard', async ({sort, page}) => { let selectedSortLabel = await sort.sortDropDown.textContent(); expect(selectedSortLabel).toEqual(defaultSortLabels[0]); // Selecting the next sort using Enter to open dropdown, the ArrowDown, then ENTER key await sort.focusSortDropDown(); - await sort.openSortDropdownUsingEnter(); - await sort.selectSortOptionUsingArrow(); + await sort.openSortDropdownUsingKeyboardEnter(); + await page.keyboard.press('ArrowDown'); + await page.keyboard.press('Enter'); selectedSortLabel = await sort.sortDropDown.textContent(); expect(selectedSortLabel).toEqual(defaultSortLabels[1]); // Selecting the next sort using Space to open dropdown, the ArrowDown, then ENTER key await sort.focusSortDropDown(); - await sort.openSortDropdownUsingEnter(false); - await sort.selectSortOptionUsingArrow(); + await sort.openSortDropdownUsingKeyboardEnter(false); + await page.keyboard.press('ArrowDown'); + await page.keyboard.press('Enter'); selectedSortLabel = await sort.sortDropDown.textContent(); expect(selectedSortLabel).toEqual(defaultSortLabels[2]); }); From 80cfcb5d8eae943eec25bdf3228a3f8f895be0f6 Mon Sep 17 00:00:00 2001 From: Lucille Vu Date: Thu, 6 Feb 2025 09:12:51 -0500 Subject: [PATCH 08/11] Update packages/quantic/force-app/main/default/lwc/quanticSort/e2e/quanticSort.e2e.ts Co-authored-by: Simon Milord --- .../main/default/lwc/quanticSort/e2e/quanticSort.e2e.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/quantic/force-app/main/default/lwc/quanticSort/e2e/quanticSort.e2e.ts b/packages/quantic/force-app/main/default/lwc/quanticSort/e2e/quanticSort.e2e.ts index 5aae060612c..501c9fe26b5 100644 --- a/packages/quantic/force-app/main/default/lwc/quanticSort/e2e/quanticSort.e2e.ts +++ b/packages/quantic/force-app/main/default/lwc/quanticSort/e2e/quanticSort.e2e.ts @@ -20,7 +20,7 @@ useCaseTestCases.forEach((useCase) => { test = fixtures[useCase.value] as typeof testInsight; } - test.describe(`quantic sort ${useCase.label}`, () => { + test.describe(`quantic sort ${useCase.label}`, () => { test.describe(`when changing sort option to Newest`, () => { test('should trigger a new search and log analytics', async ({ sort, From 7b00d6a16f029744023c18f5401ecd280befb6ca Mon Sep 17 00:00:00 2001 From: Lucille Vu Date: Thu, 6 Feb 2025 09:41:55 -0500 Subject: [PATCH 09/11] Update packages/quantic/force-app/main/default/lwc/quanticSort/__tests__/quanticSort.test.js Co-authored-by: Etienne Rocheleau --- .../main/default/lwc/quanticSort/__tests__/quanticSort.test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/quantic/force-app/main/default/lwc/quanticSort/__tests__/quanticSort.test.js b/packages/quantic/force-app/main/default/lwc/quanticSort/__tests__/quanticSort.test.js index c218f295dbb..bbf05b5461f 100644 --- a/packages/quantic/force-app/main/default/lwc/quanticSort/__tests__/quanticSort.test.js +++ b/packages/quantic/force-app/main/default/lwc/quanticSort/__tests__/quanticSort.test.js @@ -8,7 +8,7 @@ import * as mockHeadlessLoader from 'c/quanticHeadlessLoader'; const selectors = { lightningCombobox: 'lightning-combobox', componentError: 'c-quantic-component-error', - sortDropdown: '[data-cy="sort-dropdown"]', + sortDropdown: '[data-testid="sort-dropdown"]', initializationError: 'c-quantic-component-error', }; From 8a6676a349161bef03decaf0a6700da5bfdbdf2e Mon Sep 17 00:00:00 2001 From: "COVEO\\lvu" Date: Thu, 6 Feb 2025 09:52:41 -0500 Subject: [PATCH 10/11] SFINT-5832 Remove AfterAll --- .../default/lwc/quanticSort/__tests__/quanticSort.test.js | 4 ---- 1 file changed, 4 deletions(-) diff --git a/packages/quantic/force-app/main/default/lwc/quanticSort/__tests__/quanticSort.test.js b/packages/quantic/force-app/main/default/lwc/quanticSort/__tests__/quanticSort.test.js index bbf05b5461f..3db00e5c020 100644 --- a/packages/quantic/force-app/main/default/lwc/quanticSort/__tests__/quanticSort.test.js +++ b/packages/quantic/force-app/main/default/lwc/quanticSort/__tests__/quanticSort.test.js @@ -196,10 +196,6 @@ describe('c-quantic-sort', () => { mockErroneousHeadlessInitialization(); }); - afterAll(() => { - mockSuccessfulHeadlessInitialization(); - }); - it('should display the initialization error component', async () => { const element = createTestComponent(); await flushPromises(); From 1d4158398d5aaa6922ec336bc13a521423a4ae49 Mon Sep 17 00:00:00 2001 From: "COVEO\\lvu" Date: Fri, 7 Feb 2025 17:10:05 -0500 Subject: [PATCH 11/11] SFINT-5832 Make sort options list dynamic --- .../default/lwc/quanticSort/e2e/pageObject.ts | 21 +++++++++ .../lwc/quanticSort/e2e/quanticSort.e2e.ts | 46 ++++++++++++------- 2 files changed, 51 insertions(+), 16 deletions(-) diff --git a/packages/quantic/force-app/main/default/lwc/quanticSort/e2e/pageObject.ts b/packages/quantic/force-app/main/default/lwc/quanticSort/e2e/pageObject.ts index 6202ffc1eb7..7efd2238f3d 100644 --- a/packages/quantic/force-app/main/default/lwc/quanticSort/e2e/pageObject.ts +++ b/packages/quantic/force-app/main/default/lwc/quanticSort/e2e/pageObject.ts @@ -65,4 +65,25 @@ export class SortObject { }); return uaRequest; } + + async allSortLabelOptions() { + const options = await this.page + .locator('div[part="dropdown overlay"]') + .allInnerTexts(); + const arrSort = options[0].split('\n'); + return arrSort; + } + + async getSortLabelValue() { + const arrSort = await this.allSortLabelOptions(); + const sortLabelwithValueList = await Promise.all( + arrSort.map(async (item) => ({ + label: item, + value: await this.page + .getByRole('option', {name: item}) + .getAttribute('data-value'), + })) + ); + return sortLabelwithValueList; + } } diff --git a/packages/quantic/force-app/main/default/lwc/quanticSort/e2e/quanticSort.e2e.ts b/packages/quantic/force-app/main/default/lwc/quanticSort/e2e/quanticSort.e2e.ts index 501c9fe26b5..23403fbcd22 100644 --- a/packages/quantic/force-app/main/default/lwc/quanticSort/e2e/quanticSort.e2e.ts +++ b/packages/quantic/force-app/main/default/lwc/quanticSort/e2e/quanticSort.e2e.ts @@ -4,9 +4,6 @@ import { useCaseTestCases, } from '../../../../../../playwright/utils/useCase'; -const newestDateSort = 'date descending'; -const defaultSortLabels = ['Relevancy', 'Newest', 'Oldest']; - const fixtures = { search: testSearch as typeof testSearch, insight: testInsight as typeof testInsight, @@ -14,6 +11,8 @@ const fixtures = { useCaseTestCases.forEach((useCase) => { let test; + let sortArrOptions; + let sortLabelWithValue; if (useCase.value === useCaseEnum.search) { test = fixtures[useCase.value] as typeof testSearch; } else { @@ -21,25 +20,36 @@ useCaseTestCases.forEach((useCase) => { } test.describe(`quantic sort ${useCase.label}`, () => { - test.describe(`when changing sort option to Newest`, () => { + test.beforeEach(async ({sort}) => { + await sort.clickSortDropDown(); + sortArrOptions = await sort.allSortLabelOptions(); + sortLabelWithValue = await sort.getSortLabelValue(); + await sort.clickSortDropDown(); + }); + + test.describe(`when changing sort option to 2nd position`, () => { test('should trigger a new search and log analytics', async ({ sort, search, }) => { + const {label: expectedSortName, value: expectedSortValue} = + sortLabelWithValue[1]; // Assuming 0 is the first sort option, 1 should be the 2nd one after that. + const searchResponsePromise = search.waitForSearchResponse(); await sort.clickSortDropDown(); - await sort.clickSortButton('Newest'); + await sort.clickSortButton(expectedSortName); + const searchResponse = await searchResponsePromise; const {sortCriteria} = searchResponse.request().postDataJSON(); - expect(sortCriteria).toBe(newestDateSort); - await sort.waitForSortUaAnalytics(newestDateSort); + expect(sortCriteria).toBe(expectedSortValue); + await sort.waitForSortUaAnalytics(expectedSortValue); }); }); test.describe('when testing accessibility', () => { test('should be accessible to keyboard', async ({sort, page}) => { let selectedSortLabel = await sort.sortDropDown.textContent(); - expect(selectedSortLabel).toEqual(defaultSortLabels[0]); + expect(selectedSortLabel).toEqual(sortArrOptions[0]); // Selecting the next sort using Enter to open dropdown, the ArrowDown, then ENTER key await sort.focusSortDropDown(); @@ -47,7 +57,7 @@ useCaseTestCases.forEach((useCase) => { await page.keyboard.press('ArrowDown'); await page.keyboard.press('Enter'); selectedSortLabel = await sort.sortDropDown.textContent(); - expect(selectedSortLabel).toEqual(defaultSortLabels[1]); + expect(selectedSortLabel).toEqual(sortArrOptions[1]); // Selecting the next sort using Space to open dropdown, the ArrowDown, then ENTER key await sort.focusSortDropDown(); @@ -55,21 +65,25 @@ useCaseTestCases.forEach((useCase) => { await page.keyboard.press('ArrowDown'); await page.keyboard.press('Enter'); selectedSortLabel = await sort.sortDropDown.textContent(); - expect(selectedSortLabel).toEqual(defaultSortLabels[2]); + expect(selectedSortLabel).toEqual(sortArrOptions[2]); }); }); if (useCase.value === 'search') { test.describe('when loading options from the url', () => { - test.use({ - urlHash: 'sortCriteria=date%20ascending', - }); - test('should reflect the options of url in the component', async ({ sort, + page, }) => { - const expectedSort = 'Oldest'; - await expect(sort.sortDropDown).toContainText(expectedSort); + const {label: expectedSortName, value: expectedSortValue} = + sortLabelWithValue[2]; // Assuming 0 is the first sort option + + const currentUrl = await page.url(); + const urlHash = `#sortCriteria=${encodeURI(expectedSortValue)}`; + + await page.goto(`${currentUrl}/${urlHash}`); + await page.getByRole('button', {name: 'Try it now'}).click(); + await expect(sort.sortDropDown).toContainText(expectedSortName); }); }); }