From eb3074bfa01ef558da4fd4bed154d3bc9a01f517 Mon Sep 17 00:00:00 2001 From: Santoshkumar Nateekar Date: Thu, 26 Oct 2023 11:47:30 -0700 Subject: [PATCH 01/53] Update the Marquee and Media scripts (#193) * update the marquee and media scripts * update the delay * update the path * update retries * marquee updates * wait update * skip webkit --------- Co-authored-by: nateekar --- features/milo/marquee.block.spec.js | 20 +- features/milo/media.block.spec.js | 30 ++- libs/webutil.js | 4 +- playwright.config.js | 2 +- selectors/milo/marquee.block.page.js | 20 +- selectors/milo/media.block.page.js | 208 ++++------------- tests/milo/marquee.block.test.js | 321 ++++++++++++++++++++------- tests/milo/media.block.test.js | 168 +++++++++++++- 8 files changed, 511 insertions(+), 262 deletions(-) diff --git a/features/milo/marquee.block.spec.js b/features/milo/marquee.block.spec.js index 90b6d2d2..87b18b33 100644 --- a/features/milo/marquee.block.spec.js +++ b/features/milo/marquee.block.spec.js @@ -105,7 +105,7 @@ module.exports = { detailText: 'DETAIL L BOLD 16/20', h2Text: 'Heading XXL 44/55 Lorem', bodyText: 'Body XL Regular (22/33) Lorem ipsum dolor sit amet', - outlineButtonText: 'Call to action', + blueButtonText: 'Call to action', linkText: 'Body M 18/27', }, tags: '@marquee @marquee-split-large @smoke @regression @milo', @@ -118,7 +118,7 @@ module.exports = { detailText: 'DETAIL L BOLD 16/20', h2Text: 'Heading XXL 44/55 Lorem', bodyText: 'Body XL Regular (22/33) Lorem ipsum dolor sit amet', - outlineButtonText: 'Call to action', + blueButtonText: 'Call to action', linkText: 'Body M 18/27', }, tags: '@marquee @marquee-split-one-third-large-light @smoke @regression @milo', @@ -131,7 +131,7 @@ module.exports = { detailText: 'DETAIL M BOLD 12/15 OPTIONAL', h2Text: 'Heading XL 36/45 Lorem', bodyText: 'Body M Regular (18/27) Lorem ipsum dolor sit amet', - outlineButtonText: 'Call to action', + blueButtonText: 'Call to action', linkText: 'Body M 18/27', }, tags: '@marquee @marquee-split-one-third @smoke @regression @milo', @@ -144,7 +144,7 @@ module.exports = { detailText: 'DETAIL M BOLD 12/15 OPTIONAL', h2Text: 'Heading XL 36/45 Lorem', bodyText: 'Body M Regular (18/27) Lorem ipsum dolor sit amet', - outlineButtonText: 'Call to action', + blueButtonText: 'Call to action', }, tags: '@marquee @marquee-split-one-third-small-light @smoke @regression @milo', }, @@ -171,5 +171,17 @@ module.exports = { }, tags: '@marquee @marquee-video @smoke @regression @milo', }, + { + tcid: '14', + name: '@Marquee large (background video playsinline loop once)', + path: '/drafts/nala/blocks/marquee/video-autoplay-loop-once', + data: { + detailText: 'DETAIL L 16/20', + h2Text: 'Heading XL 36/45 Media (large, dark)', + bodyText: 'Body M 18/27 Lorem ipsum dolor sit amet', + blueButtonText: 'Learn More', + }, + tags: '@marquee @marquee-video @smoke @regression @milo', + }, ], }; diff --git a/features/milo/media.block.spec.js b/features/milo/media.block.spec.js index 29e9b7a5..015b928c 100644 --- a/features/milo/media.block.spec.js +++ b/features/milo/media.block.spec.js @@ -2,7 +2,7 @@ module.exports = { BlockName: 'Media Block', features: [ { - tcid: '1', + tcid: '0', name: '@Media (small)', path: '/drafts/nala/blocks/media/media-small', data: { @@ -15,7 +15,7 @@ module.exports = { tags: '@media @media-small @smoke @regression @milo', }, { - tcid: '2', + tcid: '1', name: '@Media', path: '/drafts/nala/blocks/media/media', data: { @@ -27,7 +27,7 @@ module.exports = { tags: '@media @smoke @regression @milo', }, { - tcid: '3', + tcid: '2', name: '@media (large, dark)', path: '/drafts/nala/blocks/media/media-large-dark', data: { @@ -38,5 +38,29 @@ module.exports = { }, tags: '@media @media-large-dark @smoke @regression @milo', }, + { + tcid: '3', + name: '@media (large, dark) video, autoplay infinite looping', + path: '/drafts/nala/blocks/media/media-video-autoplay-infinite-loop', + data: { + detailText: 'Detail L 16/20', + h2Text: 'Heading XL 36/45 Media (large, dark)', + bodyText: 'Body M 18/27 Lorem ipsum dolor sit amet,', + blueButtonText: 'Learn More', + }, + tags: '@media @media-video @smoke @regression @milo', + }, + { + tcid: '4', + name: '@media video, autoplay loop once', + path: '/drafts/nala/blocks/media/media-video-autoplay-loop-once', + data: { + detailText: 'Detail L 16/20', + h2Text: 'Heading XL 36/45 Media (large, dark)', + bodyText: 'Body M 18/27 Lorem ipsum dolor sit amet,', + blueButtonText: 'Learn More', + }, + tags: '@media @media-video @smoke @regression @milo', + }, ], }; diff --git a/libs/webutil.js b/libs/webutil.js index 99403289..c17ed981 100644 --- a/libs/webutil.js +++ b/libs/webutil.js @@ -164,14 +164,14 @@ exports.WebUtil = class WebUtil { // split the string value into individual classes const classes = expectedValue.split(' '); try { - await expect(this.locator).toHaveClass(classes.join(' ')); + await expect(await this.locator).toHaveClass(classes.join(' ')); } catch (error) { console.error('Attribute class not found:', error); result = false; } } else { try { - await expect(this.locator).toHaveAttribute(property, expectedValue); + await expect(await this.locator).toHaveAttribute(property, expectedValue); } catch (error) { console.error(`Attribute ${property} not found:`, error); result = false; diff --git a/playwright.config.js b/playwright.config.js index 6b9d8c72..99420337 100644 --- a/playwright.config.js +++ b/playwright.config.js @@ -24,7 +24,7 @@ const config = { /* Fail the build on CI if you accidentally left test.only in the source code. */ forbidOnly: !!process.env.CI, /* Retry on CI only */ - retries: process.env.CI ? 1 : 0, + retries: process.env.CI ? 2 : 0, /* Opt out of parallel tests on CI. */ workers: process.env.CI ? 4 : 3, /* Reporter to use. See https://playwright.dev/docs/test-reporters */ diff --git a/selectors/milo/marquee.block.page.js b/selectors/milo/marquee.block.page.js index 049d905b..0260f12e 100644 --- a/selectors/milo/marquee.block.page.js +++ b/selectors/milo/marquee.block.page.js @@ -6,8 +6,10 @@ export default class Marquee { this.marqueeLight = page.locator('.marquee.light'); this.marqueeSmall = page.locator('.marquee.small'); this.marqueeSmallLight = page.locator('.marquee.small.light'); + this.marqueeSmallDark = page.locator('.marquee.small.dark'); this.marqueeLarge = page.locator('.marquee.large'); this.marqueeLargeLight = page.locator('.marquee.large.light'); + this.marqueeLargeDark = page.locator('.marquee.large.dark'); this.marqueeQuiet = page.locator('.marquee.quiet'); this.marqueeInline = page.locator('.marquee'); this.marqueeSplitSmall = page.locator('.marquee.split.small'); @@ -170,12 +172,28 @@ export default class Marquee { 'loop': '', 'muted': '' }, + 'backgroundVideo.loopOnce': { + 'playsinline': '', + 'autoplay': '', + 'muted': '' + }, 'backgroundVideo.controls': { 'controls': '', 'autoplay': '', 'loop': '', 'muted': '' - }, + }, + 'analytics': { + 'marquee.daa-lh': { + 'daa-lh': /b[1-9]|marquee|default|default/, + }, + 'section.daa-lh': { + 'daa-lh': /s[1-9]/, + }, + 'content.daa-lh': { + 'daa-lh': /b[1-9]|content|default|default/, + }, + }, }; } }; diff --git a/selectors/milo/media.block.page.js b/selectors/milo/media.block.page.js index 5ae39148..246b1935 100644 --- a/selectors/milo/media.block.page.js +++ b/selectors/milo/media.block.page.js @@ -1,11 +1,8 @@ -import { expect } from '@playwright/test'; -import { WebUtil } from '../../libs/webutil.js'; - export default class Media { - constructor(page) { + constructor(page, nth = 0) { this.page = page; // media types - this.media = page.locator('.media'); + this.media = page.locator('.media').nth(nth); this.mediaSmall = page.locator('.media.small'); this.mediaLargeDark = page.locator('.media.large'); @@ -34,168 +31,55 @@ export default class Media { this.mediaImage = this.media.locator('.image'); this.mediaImg = this.mediaImage.locator('img'); - // media contents css - this.cssProperties = { - 'media': { - 'margin': /^0px(.*)/, - 'position': 'relative', - }, - 'media-large-dark': { - 'margin': /^0px(.*)/, - 'position': 'relative', - }, - 'heading-xl': { - 'font-size': '36px', - 'line-height': '45px', - }, - 'heading-m': { - 'font-size': '24px', - 'line-height': '30px', - }, - 'heading-xs': { - 'font-size': '18px', - 'line-height': '22.5px', - }, - 'detail-l': { - 'font-size': '16px', - 'line-height': '20px', - }, - 'detail-m': { - 'font-size': '12px', - 'line-height': '15px', + // background video + this.backgroundVideo = this.media.locator('div video'); + this.backgroundVideoDesktop = this.media.locator('div .desktop-only video'); + + // media attributes + this.attributes = { + 'media.small': { + 'image': { + 'loading': 'eager', + 'fetchpriority': 'high', + 'width': '400', + 'height': '300' + }, }, - 'body-m': { - 'font-size': '18px', - 'line-height': '27px', + 'media.large': { + 'image': { + 'loading': 'lazy', + 'width': '700', + 'height': '525' + }, }, - 'body-s': { - 'font-size': '16px', - 'line-height': '24px', + 'backgroundVideo.inline': { + 'playsinline': '', + 'autoplay': '', + 'loop': '', + 'muted': '' }, - 'outline': { - 'border': '2px solid rgb(44, 44, 44)', - 'color': 'rgb(44, 44, 44)', - 'border-radius': '16px', - 'display': 'block', - 'padding': '5px 14px', - 'font-size': '15px', - 'line-height': '16px', - 'font-style': 'normal', - 'font-weight': '700', + 'backgroundVideo.loopOnce': { + 'playsinline': '', + 'autoplay': '', + 'muted': '' }, - 'blue': { - 'border': '2px solid rgb(20, 115, 230)', - 'color': 'rgb(255, 255, 255)', - 'background': /^rgb\(20,\s*115,\s*230\)(.*)/, - 'border-radius': '16px', - 'display': 'block', - 'padding': '5px 14px', - 'font-size': '15px', - 'line-height': '16px', - 'font-style': 'normal', - 'font-weight': '700', + 'backgroundVideo.controls': { + 'controls': '', + 'autoplay': '', + 'loop': '', + 'muted': '' }, - }; - - // media contents attributes - this.attProperties = { - 'learn-more': { 'daa-ll': /^Learn More[-\s]\d+\|(.*)/ }, - 'watch-video': { 'daa-ll': /^Watch the Video[-\s]\d+\|(.*)/ }, - 'media-small': { - 'class': 'media small con-block media-reverse-mobile', - 'daa-lh': 'b1|media|default|default', - }, - 'media': { - 'class': 'media con-block', - 'daa-lh': 'b1|media|default|default', - }, - 'media-large-dark': { - 'class': 'media large dark con-block has-bg media-reverse-mobile', - 'daa-lh': 'b1|media|default|default', - }, - 'media-small-image': { - 'width': '400', - 'height': '300', + 'analytics': { + 'media.daa-lh': { + 'daa-lh': /b[1-9]|media|default|default/, + }, + 'section.daa-lh': { + 'daa-lh': /s[1-9]/, + }, + 'content.daa-lh': { + 'daa-lh': /b[1-9]|content|default|default/, + }, }, - }; - } - - /** - * Verifies the css, attributes, styles, of elements or - * sections of the specified Media block. - * - * @param {string} mediaType - The type of the Media block to verify. - * Possible values are 'media (small)', 'media ', and 'media (large,dark)'. - * @returns {Promise} - Returns true if the specified media block type has the expected values. - */ - async verifyMedia(mediaType, data) { - switch (mediaType) { - case 'media (small)': - // verify media (small) visibility, content, css and attributes values - await expect(this.mediaSmall).toBeVisible(); - - await expect(await this.detailM).toContainText(data.detailText); - await expect(await this.headingXS).toContainText(data.h2Text); - await expect(await this.bodyS).toContainText(data.bodyText); - await expect(await this.outlineButton).toContainText(data.outlineButtonText); - await expect(await this.blueButton).toContainText(data.blueButtonText); - - expect(await WebUtil.verifyCSS(this.mediaSmall, this.cssProperties.media)).toBeTruthy(); - expect(await WebUtil.verifyCSS(this.detailM, this.cssProperties['detail-m'])).toBeTruthy(); - expect(await WebUtil.verifyCSS(this.headingXS, this.cssProperties['heading-xs'])).toBeTruthy(); - expect(await WebUtil.verifyCSS(this.bodyTextS, this.cssProperties['body-s'])).toBeTruthy(); - expect(await WebUtil.verifyAttributes(this.media, this.attProperties['media-small'])).toBeTruthy(); - - expect(await WebUtil.verifyCSS(this.blueButton, this.cssProperties.blue)).toBeTruthy(); - expect(await WebUtil.verifyCSS(this.outlineButton, this.cssProperties.outline)).toBeTruthy(); - - expect(await WebUtil.verifyAttributes(this.blueButton, this.attProperties['learn-more'])).toBeTruthy(); - expect(await WebUtil.verifyAttributes(this.outlineButton, this.attProperties['watch-video'])).toBeTruthy(); - - return true; - - case 'media': - // verify media visibility, content, css and attributes values - await expect(this.media).toBeVisible(); - - await expect(await this.detailM).toContainText(data.detailText); - await expect(await this.headingM).toContainText(data.h2Text); - await expect(await this.bodyS).toContainText(data.bodyText); - await expect(await this.blueButton).toContainText(data.blueButtonText); - - expect(await WebUtil.verifyCSS(this.media, this.cssProperties.media)).toBeTruthy(); - expect(await WebUtil.verifyCSS(this.detailM, this.cssProperties['detail-m'])).toBeTruthy(); - expect(await WebUtil.verifyCSS(this.headingM, this.cssProperties['heading-m'])).toBeTruthy(); - expect(await WebUtil.verifyCSS(this.bodyTextS, this.cssProperties['body-s'])).toBeTruthy(); - expect(await WebUtil.verifyAttributes(this.media, this.attProperties.media)).toBeTruthy(); - - expect(await WebUtil.verifyCSS(this.blueButton, this.cssProperties.blue)).toBeTruthy(); - expect(await WebUtil.verifyAttributes(this.blueButton, this.attProperties['learn-more'])).toBeTruthy(); - - return true; - - case 'media (large, dark)': - // verify media (large, dark) visibility, content, css and attributes values - await expect(this.mediaLargeDark).toBeVisible(); - - await expect(await this.detailL).toContainText(data.detailText); - await expect(await this.headingXL).toContainText(data.h2Text); - await expect(await this.bodyM).toContainText(data.bodyText); - await expect(await this.blueButton).toContainText(data.blueButtonText); - - expect(await WebUtil.verifyCSS(this.media, this.cssProperties.media)).toBeTruthy(); - expect(await WebUtil.verifyCSS(this.detailL, this.cssProperties['detail-l'])).toBeTruthy(); - expect(await WebUtil.verifyCSS(this.headingXL, this.cssProperties['heading-xl'])).toBeTruthy(); - expect(await WebUtil.verifyCSS(this.bodyTextM, this.cssProperties['body-m'])).toBeTruthy(); - expect(await WebUtil.verifyAttributes(this.mediaLargeDark, this.attProperties['media-large-dark'])).toBeTruthy(); - - expect(await WebUtil.verifyAttributes(this.blueButton, this.attProperties['learn-more'])).toBeTruthy(); - expect(await WebUtil.verifyCSS(this.blueButton, this.cssProperties.blue)).toBeTruthy(); - - return true; - - default: - throw new Error(`Unsupported media type: ${this.mediaType}`); - } + } } }; diff --git a/tests/milo/marquee.block.test.js b/tests/milo/marquee.block.test.js index 4193cd4e..b980ff3b 100644 --- a/tests/milo/marquee.block.test.js +++ b/tests/milo/marquee.block.test.js @@ -6,6 +6,7 @@ import MarqueeBlock from '../../selectors/milo/marquee.block.page.js'; let webUtil; let marquee; let consoleErrors = []; +const knownConsoleErrors = ['Access-Control-Allow-Origin','Failed to load resource: net::ERR_FAILED']; test.describe('Milo Marquee Block test suite', () => { test.beforeEach(async ({ page }) => { @@ -13,12 +14,20 @@ test.describe('Milo Marquee Block test suite', () => { marquee = new MarqueeBlock(page); page.on('pageerror', (exception) => { - consoleErrors.push(exception); + if (exception.type() === 'error') { + consoleErrors.push(exception.text()); + } }); }); + test.afterEach(async () =>{ + consoleErrors = []; + }); + + // Test 0 : Marquee (light) test(`${features[0].name},${features[0].tags}`, async ({ page, baseURL }) => { console.info(`[Test Page]: ${baseURL}${features[0].path}`); + const { data } = features[0]; await test.step('step-1: Go to Marquee (light) block test page', async () => { await page.goto(`${baseURL}${features[0].path}`); @@ -26,9 +35,7 @@ test.describe('Milo Marquee Block test suite', () => { await expect(page).toHaveURL(`${baseURL}${features[0].path}`); }); - await test.step('step-2: Verify marquee(light) specs', async () => { - const { data } = features[0]; - + await test.step('step-2: Verify marquee(light) specs', async () => { await expect(await marquee.marqueeLight).toBeVisible(); await expect(await marquee.headingXL).toContainText(data.h2Text); @@ -40,14 +47,23 @@ test.describe('Milo Marquee Block test suite', () => { expect(await webUtil.verifyAttributes_(marquee.backgroundImage, marquee.attributes['marquee.light']['backgroundImg'])).toBeTruthy(); }); - await test.step('step-3: Verify and log if any console errors', async () => { - consoleErrors.length > 0 && console.log('[Console error]:', consoleErrors); - expect.soft(consoleErrors.length).toBe(0); + await test.step('step-3: Verify analytics attributes', async () => { + const outlineButtonDaalh = data.outlineButtonText +'-1'+ '|' + (data.h2Text).slice(0, 20) ; + + expect(await webUtil.verifyAttributes_(marquee.marqueeLight, marquee.attributes['analytics']['marquee.daa-lh'])).toBeTruthy(); + await expect(await marquee.outlineButton).toHaveAttribute('daa-ll', outlineButtonDaalh); + }); + + await test.step('step-4: Verify browser console errors', async () => { + consoleErrors.length > knownConsoleErrors.length && console.log('[Console error]:', consoleErrors); + expect.soft(consoleErrors.length).toBeLessThanOrEqual(knownConsoleErrors.length); }); }); + // Test 1 : Marquee (small) test(`${features[1].name},${features[1].tags}`, async ({ page, baseURL }) => { console.info(`[Test Page]: ${baseURL}${features[1].path}`); + const { data } = features[1]; await test.step('step-1: Go to Marquee (small) block test page', async () => { await page.goto(`${baseURL}${features[1].path}`); @@ -56,8 +72,6 @@ test.describe('Milo Marquee Block test suite', () => { }); await test.step('step-2: Verify Marquee (small) specs', async () => { - const { data } = features[1]; - await expect(await marquee.marqueeSmall).toBeVisible(); await expect(await marquee.headingXL).toContainText(data.h2Text); @@ -68,14 +82,23 @@ test.describe('Milo Marquee Block test suite', () => { expect(await webUtil.verifyAttributes_(marquee.backgroundImage, marquee.attributes['marquee.small']['backgroundImg'])).toBeTruthy(); }); - await test.step('step-3: Verify and log if any console errors', async () => { - consoleErrors.length > 0 && console.log('[Console error]:', consoleErrors); - expect.soft(consoleErrors.length).toBe(0); + await test.step('step-3: Verify analytic attributes', async () => { + const blueButtonDaalh = data.blueButtonText +'-1'+ '|' + (data.h2Text).slice(0, 20) ; + + expect(await webUtil.verifyAttributes_(marquee.marqueeSmall, marquee.attributes['analytics']['marquee.daa-lh'])).toBeTruthy(); + await expect(await marquee.blueButton).toHaveAttribute('daa-ll', blueButtonDaalh); + }); + + await test.step('step-4: Verify browser console errors', async () => { + consoleErrors.length > knownConsoleErrors.length && console.log('[Console error]:', consoleErrors); + expect.soft(consoleErrors.length).toBeLessThanOrEqual(knownConsoleErrors.length); }); }); + // Test 2 : Marquee (small,light) test(`${features[2].name},${features[2].tags}`, async ({ page, baseURL }) => { console.info(`[Test Page]: ${baseURL}${features[2].path}`); + const { data } = features[2]; await test.step('step-1: Go to Marquee (small, light ) block test page', async () => { await page.goto(`${baseURL}${features[2].path}`); @@ -84,8 +107,6 @@ test.describe('Milo Marquee Block test suite', () => { }); await test.step('step-2: Verify Marquee (small, light) specs', async () => { - const { data } = features[2]; - await expect(await marquee.marqueeSmallLight).toBeVisible(); await expect(await marquee.detailM).toContainText(data.detailText); @@ -95,18 +116,28 @@ test.describe('Milo Marquee Block test suite', () => { await expect(await marquee.blueButton).toContainText(data.blueButtonText); await expect(await marquee.backgroundImage).toBeVisible(); - expect(await webUtil.verifyAttributes_(marquee.backgroundImage, marquee.attributes['marquee.small.light']['backgroundImg'])).toBeTruthy(); - + expect(await webUtil.verifyAttributes_(marquee.backgroundImage, marquee.attributes['marquee.small.light']['backgroundImg'])).toBeTruthy(); }); - await test.step('step-3: Verify and log if any console errors', async () => { - consoleErrors.length > 0 && console.log('[Console error]:', consoleErrors); - expect.soft(consoleErrors.length).toBe(0); + await test.step('step-3: Verify analytic attributes', async () => { + const outlineButtonDaalh = data.outlineButtonText +'-1'+ '|' + (data.h2Text).slice(0, 20) ; + const blueButtonDaalh = data.blueButtonText +'-2'+ '|' + (data.h2Text).slice(0, 20) ; + + expect(await webUtil.verifyAttributes_(marquee.marqueeSmallLight, marquee.attributes['analytics']['marquee.daa-lh'])).toBeTruthy(); + await expect(await marquee.outlineButton).toHaveAttribute('daa-ll', outlineButtonDaalh); + await expect(await marquee.blueButton).toHaveAttribute('daa-ll', blueButtonDaalh); + }); + + await test.step('step-4: Verify browser console errors', async () => { + consoleErrors.length > knownConsoleErrors.length && console.log('[Console error]:', consoleErrors); + expect.soft(consoleErrors.length).toBeLessThanOrEqual(knownConsoleErrors.length); }); }); + // Test 3 : Marquee (large) test(`${features[3].name},${features[3].tags}`, async ({ page, baseURL }) => { console.info(`[Test Page]: ${baseURL}${features[3].path}`); + const { data } = features[3]; await test.step('step-1: Go to Marquee (large ) block test page', async () => { await page.goto(`${baseURL}${features[3].path}`); @@ -115,8 +146,6 @@ test.describe('Milo Marquee Block test suite', () => { }); await test.step('step-2: Verify Marquee (large) specs', async () => { - const { data } = features[3]; - await expect(await marquee.marqueeLarge).toBeVisible(); await expect(await marquee.headingXXL).toContainText(data.h2Text); @@ -128,14 +157,25 @@ test.describe('Milo Marquee Block test suite', () => { expect(await webUtil.verifyAttributes_(marquee.backgroundImage, marquee.attributes['marquee.large']['backgroundImg'])).toBeTruthy(); }); - await test.step('step-3: Verify and log if any console errors', async () => { - consoleErrors.length > 0 && console.log('[Console error]:', consoleErrors); - expect.soft(consoleErrors.length).toBe(0); + await test.step('step-3: Verify analytic attributes', async () => { + const outlineButtonDaalh = data.outlineButtonText +'-1'+ '|' + (data.h2Text).slice(0, 20) ; + const blueButtonDaalh = data.blueButtonText +'-2'+ '|' + (data.h2Text).slice(0, 20) ; + + expect(await webUtil.verifyAttributes_(marquee.marqueeLarge, marquee.attributes['analytics']['marquee.daa-lh'])).toBeTruthy(); + await expect(await marquee.outlineButtonXL).toHaveAttribute('daa-ll', outlineButtonDaalh); + await expect(await marquee.blueButtonXL).toHaveAttribute('daa-ll', blueButtonDaalh); + }); + + await test.step('step-4: Verify browser console errors', async () => { + consoleErrors.length > knownConsoleErrors.length && console.log('[Console error]:', consoleErrors); + expect.soft(consoleErrors.length).toBeLessThanOrEqual(knownConsoleErrors.length); }); }); + // Test 4 : Marquee (large,light) test(`${features[4].name},${features[4].tags}`, async ({ page, baseURL }) => { console.info(`[Test Page]: ${baseURL}${features[4].path}`); + const { data } = features[4]; await test.step('step-1: Go to Marquee (large, light ) block test page', async () => { await page.goto(`${baseURL}${features[4].path}`); @@ -144,8 +184,6 @@ test.describe('Milo Marquee Block test suite', () => { }); await test.step('step-2: Verify Marquee (large, light) specs', async () => { - const { data } = features[4]; - await expect(await marquee.marqueeLargeLight).toBeVisible(); await expect(await marquee.headingXXL).toContainText(data.h2Text); @@ -157,14 +195,25 @@ test.describe('Milo Marquee Block test suite', () => { expect(await webUtil.verifyAttributes_(marquee.backgroundImage, marquee.attributes['marquee.large.light']['backgroundImg'])).toBeTruthy(); }); - await test.step('step-3: Verify and log if any console errors', async () => { - consoleErrors.length > 0 && console.log('[Console error]:', consoleErrors); - expect.soft(consoleErrors.length).toBe(0); + await test.step('step-3: Verify analytic attributes', async () => { + const outlineButtonDaalh = data.outlineButtonText +'-1'+ '|' + (data.h2Text).slice(0, 20) ; + const blueButtonDaalh = data.blueButtonText +'-2'+ '|' + (data.h2Text).slice(0, 20) ; + + expect(await webUtil.verifyAttributes_(marquee.marqueeLargeLight, marquee.attributes['analytics']['marquee.daa-lh'])).toBeTruthy(); + await expect(await marquee.outlineButtonXL).toHaveAttribute('daa-ll', outlineButtonDaalh); + await expect(await marquee.blueButtonXL).toHaveAttribute('daa-ll', blueButtonDaalh); + }); + + await test.step('step-4: Verify and log if any console errors', async () => { + consoleErrors.length > knownConsoleErrors.length && console.log('[Console error]:', consoleErrors); + expect.soft(consoleErrors.length).toBeLessThanOrEqual(knownConsoleErrors.length); }); }); + // Test 5 : Marquee (quiet) test(`${features[5].name},${features[5].tags}`, async ({ page, baseURL }) => { console.info(`[Test Page]: ${baseURL}${features[5].path}`); + const { data } = features[5]; await test.step('step-1: Go to Marquee (quiet ) block test page', async () => { await page.goto(`${baseURL}${features[5].path}`); @@ -173,8 +222,6 @@ test.describe('Milo Marquee Block test suite', () => { }); await test.step('step-2: Verify Marquee (quiet) specs', async () => { - const { data } = features[5]; - await expect(await marquee.marqueeQuiet).toBeVisible(); await expect(await marquee.detailM).toContainText(data.detailText); @@ -185,14 +232,23 @@ test.describe('Milo Marquee Block test suite', () => { await expect(await marquee.backgroundImage).toBeHidden(); }); - await test.step('step-3: Verify and log if any console errors', async () => { - consoleErrors.length > 0 && console.log('[Console error]:', consoleErrors); - expect.soft(consoleErrors.length).toBe(0); + await test.step('step-3: Verify analytic attributes', async () => { + const blueButtonDaalh = data.blueButtonText +'-1'+ '|' + (data.h2Text).slice(0, 20) ; + + expect(await webUtil.verifyAttributes_(marquee.marqueeQuiet, marquee.attributes['analytics']['marquee.daa-lh'])).toBeTruthy(); + await expect(await marquee.blueButton).toHaveAttribute('daa-ll', blueButtonDaalh); + }); + + await test.step('step-4: Verify and log if any console errors', async () => { + consoleErrors.length > knownConsoleErrors.length && console.log('[Console error]:', consoleErrors); + expect.soft(consoleErrors.length).toBeLessThanOrEqual(knownConsoleErrors.length); }); }); + // Test 6 : Marquee (inline) test(`${features[6].name},${features[6].tags}`, async ({ page, baseURL }) => { console.info(`[Test Page]: ${baseURL}${features[6].path}`); + const { data } = features[6]; await test.step('step-1: Go to Marquee (inline ) block test page', async () => { await page.goto(`${baseURL}${features[6].path}`); @@ -201,8 +257,6 @@ test.describe('Milo Marquee Block test suite', () => { }); await test.step('step-2: Verify Marquee (inline) specs', async () => { - const { data } = features[6]; - await expect(await marquee.marqueeInline).toBeVisible(); await expect(await marquee.detailM).toContainText(data.detailText); @@ -212,14 +266,20 @@ test.describe('Milo Marquee Block test suite', () => { await expect(await marquee.backgroundImage).toBeHidden(); }); - await test.step('step-3: Verify and log if any console errors', async () => { - consoleErrors.length > 0 && console.log('[Console error]:', consoleErrors); - expect.soft(consoleErrors.length).toBe(0); + await test.step('step-3: Verify analytic attributes', async () => { + expect(await webUtil.verifyAttributes_(marquee.marqueeInline, marquee.attributes['analytics']['marquee.daa-lh'])).toBeTruthy(); + }); + + await test.step('step-4: Verify and log if any console errors', async () => { + consoleErrors.length > knownConsoleErrors.length && console.log('[Console error]:', consoleErrors); + expect.soft(consoleErrors.length).toBeLessThanOrEqual(knownConsoleErrors.length); }); }); + // Test 7 : Marquee (split,small) test(`${features[7].name},${features[7].tags}`, async ({ page, baseURL }) => { console.info(`[Test Page]: ${baseURL}${features[7].path}`); + const { data } = features[7]; await test.step('step-1: Go to Marquee (split, small ) block test page', async () => { await page.goto(`${baseURL}${features[7].path}`); @@ -228,8 +288,6 @@ test.describe('Milo Marquee Block test suite', () => { }); await test.step('step-2: Verify Marquee (split, small) specs', async () => { - const { data } = features[7]; - await expect(marquee.marqueeSplitSmall).toBeVisible(); await expect(await marquee.detailM).toContainText(data.detailText); @@ -241,14 +299,25 @@ test.describe('Milo Marquee Block test suite', () => { expect(await webUtil.verifyAttributes_(marquee.marqueeSplitSmall, marquee.attributes['marquee.split.small']['style'])).toBeTruthy(); }); - await test.step('step-3: Verify and log if any console errors', async () => { - consoleErrors.length > 0 && console.log('[Console error]:', consoleErrors); - expect.soft(consoleErrors.length).toBe(0); + await test.step('step-3: Verify analytic attributes', async () => { + const outlineButtonDaalh = data.outlineButtonText +'-1'+ '|' + (data.h2Text).slice(0, 20) ; + const blueButtonDaalh = data.blueButtonText +'-2'+ '|' + (data.h2Text).slice(0, 20) ; + + expect(await webUtil.verifyAttributes_(marquee.marqueeSplitSmall, marquee.attributes['analytics']['marquee.daa-lh'])).toBeTruthy(); + await expect(await marquee.outlineButton).toHaveAttribute('daa-ll', outlineButtonDaalh); + await expect(await marquee.blueButton).toHaveAttribute('daa-ll', blueButtonDaalh); + }); + + await test.step('step-4: Verify and log if any console errors', async () => { + consoleErrors.length > knownConsoleErrors.length && console.log('[Console error]:', consoleErrors); + expect.soft(consoleErrors.length).toBeLessThanOrEqual(knownConsoleErrors.length); }); }); + // Test 8 : Marquee (split,large) test(`${features[8].name},${features[8].tags}`, async ({ page, baseURL }) => { console.info(`[Test Page]: ${baseURL}${features[8].path}`); + const { data } = features[8]; await test.step('step-1: Go to Marquee (split, large ) block test page', async () => { await page.goto(`${baseURL}${features[8].path}`); @@ -257,14 +326,12 @@ test.describe('Milo Marquee Block test suite', () => { }); await test.step('step-2: Verify Marquee (split, large) specs ', async () => { - const { data } = features[8]; - await expect(await marquee.marqueeSplitLarge).toBeVisible(); await expect(await marquee.detailL).toContainText(data.detailText); await expect(await marquee.headingXXL).toContainText(data.h2Text); await expect(await marquee.bodyXL).toContainText(data.bodyText); - await expect(await marquee.blueButtonXL).toContainText(data.outlineButtonText); + await expect(await marquee.blueButtonXL).toContainText(data.blueButtonText); await expect(await marquee.actionLink2).toContainText(data.linkText); await expect(await marquee.iconImage).toBeVisible(); @@ -272,17 +339,27 @@ test.describe('Milo Marquee Block test suite', () => { await expect(await marquee.mediaImage).toBeVisible(); expect(await webUtil.verifyAttributes_(marquee.mediaImage, marquee.attributes['marquee.split.large']['mediaImg'])).toBeTruthy(); + }); + + await test.step('step-3: Verify analytic attributes', async () => { + const blueButtonDaalh = data.blueButtonText +'-1'+ '|' + (data.h2Text).slice(0, 20) ; + const actionLink2Daalh = data.linkText +'-2'+ '|' + (data.h2Text).slice(0, 20) ; + expect(await webUtil.verifyAttributes_(marquee.marqueeSplitLarge, marquee.attributes['analytics']['marquee.daa-lh'])).toBeTruthy(); + await expect(await marquee.blueButtonXL).toHaveAttribute('daa-ll', blueButtonDaalh); + await expect(await marquee.actionLink2).toHaveAttribute('daa-ll', actionLink2Daalh); }); - await test.step('step-3: Verify and log if any console errors', async () => { - consoleErrors.length > 0 && console.log('[Console error]:', consoleErrors); - expect.soft(consoleErrors.length).toBe(0); + await test.step('step-4: Verify and log if any console errors', async () => { + consoleErrors.length > knownConsoleErrors.length && console.log('[Console error]:', consoleErrors); + expect.soft(consoleErrors.length).toBeLessThanOrEqual(knownConsoleErrors.length); }); }); + // Test 9 : Marquee (split,one-third,large,light) test(`${features[9].name},${features[9].tags}`, async ({ page, baseURL }) => { console.info(`[Test Page]: ${baseURL}${features[9].path}`); + const { data } = features[9]; await test.step('step-1: Go to Marquee (split, one-third, large, light ) block test page', async () => { await page.goto(`${baseURL}${features[9].path}`); @@ -291,14 +368,12 @@ test.describe('Milo Marquee Block test suite', () => { }); await test.step('step-2: Verify Marquee (split, one-third, large, light) specs', async () => { - const { data } = features[9]; - await expect(marquee.marqueeSplitOneThirdLargeLight).toBeVisible(); await expect(await marquee.detailL).toContainText(data.detailText); await expect(await marquee.headingXXL).toContainText(data.h2Text); await expect(await marquee.bodyXL).toContainText(data.bodyText); - await expect(await marquee.blueButtonXL).toContainText(data.outlineButtonText); + await expect(await marquee.blueButtonXL).toContainText(data.blueButtonText); await expect(await marquee.actionLink2).toContainText(data.linkText); await expect(await marquee.iconImage).toBeVisible(); @@ -308,14 +383,25 @@ test.describe('Milo Marquee Block test suite', () => { expect(await webUtil.verifyAttributes_(marquee.mediaImage, marquee.attributes['marquee.split.one-third-large']['mediaImg'])).toBeTruthy(); }); + await test.step('step-3: Verify analytic attributes', async () => { + const blueButtonDaalh = data.blueButtonText +'-1'+ '|' + (data.h2Text).slice(0, 20) ; + const actionLink2Daalh = data.linkText +'-2'+ '|' + (data.h2Text).slice(0, 20) ; + + expect(await webUtil.verifyAttributes_(marquee.marqueeSplitLarge, marquee.attributes['analytics']['marquee.daa-lh'])).toBeTruthy(); + await expect(await marquee.blueButtonXL).toHaveAttribute('daa-ll', blueButtonDaalh); + await expect(await marquee.actionLink2).toHaveAttribute('daa-ll', actionLink2Daalh); + }); + await test.step('step-3: Verify and log if any console errors', async () => { - consoleErrors.length > 0 && console.log('[Console error]:', consoleErrors); - expect.soft(consoleErrors.length).toBe(0); + consoleErrors.length > knownConsoleErrors.length && console.log('[Console error]:', consoleErrors); + expect.soft(consoleErrors.length).toBeLessThanOrEqual(knownConsoleErrors.length); }); }); + // Test 10 : Marquee (split,one-third) test(`${features[10].name},${features[10].tags}`, async ({ page, baseURL }) => { console.info(`[Test Page]: ${baseURL}${features[10].path}`); + const { data } = features[10]; await test.step('step-1: Go to Marquee (split, one-third ) block test page', async () => { await page.goto(`${baseURL}${features[10].path}`); @@ -323,15 +409,13 @@ test.describe('Milo Marquee Block test suite', () => { await expect(page).toHaveURL(`${baseURL}${features[10].path}`); }); - await test.step('step-2: Verify Marquee (split, one-third) specs', async () => { - const { data } = features[10]; - + await test.step('step-2: Verify Marquee (split, one-third) specs', async () => { await expect(await marquee.marqueeSplitOneThird).toBeVisible(); await expect(await marquee.detailM).toContainText(data.detailText); await expect(await marquee.headingXL).toContainText(data.h2Text); await expect(await marquee.bodyM).toContainText(data.bodyText); - await expect(await marquee.blueButtonL).toContainText(data.outlineButtonText); + await expect(await marquee.blueButtonL).toContainText(data.blueButtonText); await expect(await marquee.actionLink2).toContainText(data.linkText); await expect(await marquee.iconImage).toBeVisible(); @@ -341,14 +425,23 @@ test.describe('Milo Marquee Block test suite', () => { expect(await webUtil.verifyAttributes_(marquee.mediaImage, marquee.attributes['marquee.split.one-third']['mediaImg'])).toBeTruthy(); }); - await test.step('step-3: Verify and log if any console errors', async () => { - consoleErrors.length > 0 && console.log('[Console error]:', consoleErrors); - expect.soft(consoleErrors.length).toBe(0); + await test.step('step-3: Verify analytic attributes', async () => { + const blueButtonDaalh = data.blueButtonText +'-1'+ '|' + (data.h2Text).slice(0, 20) ; + + expect(await webUtil.verifyAttributes_(marquee.marqueeSplitOneThird, marquee.attributes['analytics']['marquee.daa-lh'])).toBeTruthy(); + await expect(await marquee.blueButtonL).toHaveAttribute('daa-ll', blueButtonDaalh); + }); + + await test.step('step-4: Verify and log if any console errors', async () => { + consoleErrors.length > knownConsoleErrors.length && console.log('[Console error]:', consoleErrors); + expect.soft(consoleErrors.length).toBeLessThanOrEqual(knownConsoleErrors.length); }); }); + // Test 11 : Marquee (split,one-third,small,light) test(`${features[11].name},${features[11].tags}`, async ({ page, baseURL }) => { console.info(`[Test Page]: ${baseURL}${features[11].path}`); + const { data } = features[11]; await test.step('step-1: Go to Marquee (split,one-third,small,light ) block test page', async () => { await page.goto(`${baseURL}${features[11].path}`); @@ -357,28 +450,36 @@ test.describe('Milo Marquee Block test suite', () => { }); await test.step('step-2: Verify Marquee (split,one-third,small,light) specs', async () => { - const { data } = features[11]; - await expect(marquee.marqueeSplitOneThirdSmallLight).toBeVisible(); await expect(await marquee.detailM).toContainText(data.detailText); await expect(await marquee.headingXL).toContainText(data.h2Text); await expect(await marquee.bodyM).toContainText(data.bodyText); - await expect(await marquee.blueButtonL).toContainText(data.outlineButtonText); + await expect(await marquee.blueButtonL).toContainText(data.blueButtonText); await expect(await marquee.mediaImage).toBeVisible(); expect(await webUtil.verifyAttributes_(marquee.mediaImage, marquee.attributes['marquee.split.one-third']['mediaImg'])).toBeTruthy(); + }); + await test.step('step-3: Verify analytic attributes', async () => { + const blueButtonDaalh = data.blueButtonText +'-1'+ '|' + (data.h2Text).slice(0, 20) ; + + expect(await webUtil.verifyAttributes_(marquee.marqueeSplitOneThirdSmallLight, marquee.attributes['analytics']['marquee.daa-lh'])).toBeTruthy(); + await expect(await marquee.blueButtonL).toHaveAttribute('daa-ll', blueButtonDaalh); }); - await test.step('step-3: Verify and log if any console errors', async () => { - consoleErrors.length > 0 && console.log('[Console error]:', consoleErrors); - expect.soft(consoleErrors.length).toBe(0); + await test.step('step-4: Verify and log if any console errors', async () => { + consoleErrors.length > knownConsoleErrors.length && console.log('[Console error]:', consoleErrors); + expect.soft(consoleErrors.length).toBeLessThanOrEqual(knownConsoleErrors.length); }); }); - test(`${features[12].name},${features[12].tags}`, async ({ page, baseURL }) => { + // Test 12 : Marquee small (background video playsinline) + test(`${features[12].name},${features[12].tags}`, async ({ page, baseURL, browserName }) => { + test.slow(); + test.skip(browserName === 'webkit', 'This feature is failing on Webkit browsers') console.info(`[Test Page]: ${baseURL}${features[12].path}`); + const { data } = features[12]; await test.step('step-1: Go to Marquee (small) block test page', async () => { await page.goto(`${baseURL}${features[12].path}`); @@ -386,10 +487,8 @@ test.describe('Milo Marquee Block test suite', () => { await expect(page).toHaveURL(`${baseURL}${features[12].path}`); }); - await test.step('step-2: Verify Marquee (small) specs', async () => { - const { data } = features[12]; - - await expect(await marquee.marqueeSmall).toBeVisible(); + await test.step('step-2: Verify Marquee (small) background video playsinline specs', async () => { + await expect(await marquee.marqueeSmallDark).toBeVisible(); await expect(await marquee.headingXL).toContainText(data.h2Text); await expect(await marquee.bodyM).toContainText(data.bodyText); @@ -399,14 +498,25 @@ test.describe('Milo Marquee Block test suite', () => { expect(await webUtil.verifyAttributes_(marquee.backgroundVideo, marquee.attributes['backgroundVideo.inline'])).toBeTruthy(); }); - await test.step('step-3: Verify and log if any console errors', async () => { - consoleErrors.length > 0 && console.log('[Console error]:', consoleErrors); - expect.soft(consoleErrors.length).toBe(0); + await test.step('step-3: Verify analytic attributes', async () => { + const blueButtonDaalh = data.blueButtonText +'-1'+ '|' + (data.h2Text).slice(0, 20) ; + + expect(await webUtil.verifyAttributes_(marquee.marqueeSmallDark, marquee.attributes['analytics']['marquee.daa-lh'])).toBeTruthy(); + await expect(await marquee.blueButton).toHaveAttribute('daa-ll', blueButtonDaalh); + }); + + await test.step('step-4: Verify and log if any console errors', async () => { + consoleErrors.length > knownConsoleErrors.length && console.log('[Console error]:', consoleErrors); + expect.soft(consoleErrors.length).toBeLessThanOrEqual(knownConsoleErrors.length); }); }); - test(`${features[13].name},${features[13].tags}`, async ({ page, baseURL }) => { + // Test 13 : Marquee large (background video playsinline desktop) + test(`${features[13].name},${features[13].tags}`, async ({ page, baseURL, browserName }) => { + test.skip(browserName === 'webkit', 'This feature is failing on Webkit browsers') + test.slow(); console.info(`[Test Page]: ${baseURL}${features[13].path}`); + const { data } = features[13]; await test.step('step-1: Go to Marquee (large, light ) block test page', async () => { await page.goto(`${baseURL}${features[13].path}`); @@ -415,8 +525,6 @@ test.describe('Milo Marquee Block test suite', () => { }); await test.step('step-2: Verify Marquee (large, light) desktop background specs', async () => { - const { data } = features[13]; - await expect(await marquee.marqueeLargeLight).toBeVisible(); await expect(await marquee.headingXXL).toContainText(data.h2Text); @@ -431,9 +539,58 @@ test.describe('Milo Marquee Block test suite', () => { expect(await sourceElement.getAttribute('src')).toContain('.mp4'); }); - await test.step('step-3: Verify and log if any console errors', async () => { - consoleErrors.length > 0 && console.log('[Console error]:', consoleErrors); - expect.soft(consoleErrors.length).toBe(0); + await test.step('step-3: Verify analytic attributes', async () => { + const blueButtonDaalh = data.blueButtonText +'-1'+ '|' + (data.h2Text).slice(0, 20) ; + const actionLink2Daalh = data.linkText +'-2'+ '|' + (data.h2Text).slice(0, 20) ; + + expect(await webUtil.verifyAttributes_(marquee.marqueeLargeLight, marquee.attributes['analytics']['marquee.daa-lh'])).toBeTruthy(); + await expect(await marquee.blueButtonXL).toHaveAttribute('daa-ll', blueButtonDaalh); + await expect(await marquee.actionLink2).toHaveAttribute('daa-ll', actionLink2Daalh); + }); + + await test.step('step-4: Verify and log if any console errors', async () => { + consoleErrors.length > knownConsoleErrors.length && console.log('[Console error]:', consoleErrors); + expect.soft(consoleErrors.length).toBeLessThanOrEqual(knownConsoleErrors.length); + }); + }); + + // Test 14 : Marquee large (background video playsinline loop once) + test(`${features[14].name},${features[14].tags}`, async ({ page, baseURL }) => { + test.slow(); + console.info(`[Test Page]: ${baseURL}${features[14].path}`); + const { data } = features[14]; + + await test.step('step-1: Go to Marquee (large, dark ) block test page', async () => { + await page.goto(`${baseURL}${features[14].path}`); + await page.waitForLoadState('domcontentloaded'); + await expect(page).toHaveURL(`${baseURL}${features[14].path}`); + }); + + await test.step('step-2: Verify Marquee (large, dark) background specs', async () => { + await expect(await marquee.marqueeLargeDark).toBeVisible(); + + await expect(await marquee.headingXXL).toContainText(data.h2Text); + await expect(await marquee.bodyXL).toContainText(data.bodyText); + await expect(await marquee.blueButtonXL).toContainText(data.blueButtonText); + + await expect(await marquee.backgroundVideo).toBeVisible(); + expect(await webUtil.verifyAttributes_(marquee.backgroundVideo, marquee.attributes['backgroundVideo.loopOnce'])).toBeTruthy(); + + const sourceElement = await marquee.backgroundVideo.locator('source'); + expect(await sourceElement.getAttribute('src')).toContain('.mp4'); + expect(await sourceElement.getAttribute('type')).toContain('video/mp4'); + }); + + await test.step('step-3: Verify analytic attributes', async () => { + const blueButtonDaalh = data.blueButtonText +'-1'+ '|' + (data.h2Text).slice(0, 20) ; + + expect(await webUtil.verifyAttributes_(marquee.marqueeLargeDark, marquee.attributes['analytics']['marquee.daa-lh'])).toBeTruthy(); + await expect(await marquee.blueButtonXL).toHaveAttribute('daa-ll', blueButtonDaalh); + }); + + await test.step('step-4: Verify and log if any console errors', async () => { + consoleErrors.length > knownConsoleErrors.length && console.log('[Console error]:', consoleErrors); + expect.soft(consoleErrors.length).toBeLessThanOrEqual(knownConsoleErrors.length); }); }); }); diff --git a/tests/milo/media.block.test.js b/tests/milo/media.block.test.js index f1ef6b92..20546387 100644 --- a/tests/milo/media.block.test.js +++ b/tests/milo/media.block.test.js @@ -1,16 +1,33 @@ import { expect, test } from '@playwright/test'; +import { WebUtil } from '../../libs/webutil.js'; import { features } from '../../features/milo/media.block.spec.js'; import MediaBlock from '../../selectors/milo/media.block.page.js'; +let webUtil; let media; +let consoleErrors = []; +const knownConsoleErrors = ['Access-Control-Allow-Origin','Failed to load resource: net::ERR_FAILED']; test.describe('Milo Media Block test suite', () => { test.beforeEach(async ({ page }) => { + webUtil = new WebUtil(page); media = new MediaBlock(page); + + page.on('console', (exception) => { + if (exception.type() === 'error') { + consoleErrors.push(exception.text()); + } + }); }); + test.afterEach(async () =>{ + consoleErrors = []; + }); + + // Test 0 : Media (small) test(`${features[0].name},${features[0].tags}`, async ({ page, baseURL }) => { console.info(`[Test Page]: ${baseURL}${features[0].path}`); + const { data } = features[0]; await test.step('step-1: Go to Media (small) block test page', async () => { await page.goto(`${baseURL}${features[0].path}`); @@ -19,13 +36,35 @@ test.describe('Milo Media Block test suite', () => { }); await test.step('step-2: Verify media (small) block specs', async () => { - const { data } = features[0]; - expect(await media.verifyMedia('media (small)', data)).toBeTruthy(); + await expect(media.mediaSmall).toBeVisible(); + + await expect(await media.detailM).toContainText(data.detailText); + await expect(await media.headingXS).toContainText(data.h2Text); + await expect(await media.bodyS).toContainText(data.bodyText); + await expect(await media.outlineButton).toContainText(data.outlineButtonText); + await expect(await media.blueButton).toContainText(data.blueButtonText); + + await expect(await media.mediaImage).toBeVisible(); + expect(await webUtil.verifyAttributes_(media.mediaImg, media.attributes['media.small']['image'])).toBeTruthy(); + }); + + await test.step('step-3: Verify analytics attributes', async () => { + const blueButtonDaalh = data.blueButtonText +'-1'+ '|' + (data.h2Text).slice(0, 20) ; + + expect(await webUtil.verifyAttributes_(media.mediaSmall, media.attributes['analytics']['media.daa-lh'])).toBeTruthy(); + await expect(await media.blueButton).toHaveAttribute('daa-ll', blueButtonDaalh); + }); + + await test.step('step-4: Verify browser console errors', async () => { + consoleErrors.length > knownConsoleErrors.length && console.log('[Console error]:', consoleErrors); + expect.soft(consoleErrors.length).toBeLessThanOrEqual(knownConsoleErrors.length); }); }); + // Test 1 : Media test(`${features[1].name},${features[1].tags}`, async ({ page, baseURL }) => { console.info(`[Test Page]: ${baseURL}${features[1].path}`); + const { data } = features[1]; await test.step('step-1: Go to media block test page', async () => { await page.goto(`${baseURL}${features[1].path}`); @@ -34,13 +73,34 @@ test.describe('Milo Media Block test suite', () => { }); await test.step('step-2: Verify media block specs', async () => { - const { data } = features[1]; - expect(await media.verifyMedia('media', data)).toBeTruthy(); + await expect(media.media).toBeVisible(); + + await expect(await media.detailM).toContainText(data.detailText); + await expect(await media.headingM).toContainText(data.h2Text); + await expect(await media.bodyS).toContainText(data.bodyText); + await expect(await media.blueButton).toContainText(data.blueButtonText); + + await expect(await media.mediaImage).toBeVisible(); + expect(await webUtil.verifyAttributes_(media.mediaImg, media.attributes['media.small']['image'])).toBeTruthy(); }); + + await test.step('step-3: Verify analytics attributes', async () => { + const blueButtonDaalh = data.blueButtonText +'-1'+ '|' + (data.h2Text).slice(0, 20) ; + + expect(await webUtil.verifyAttributes_(media.media, media.attributes['analytics']['media.daa-lh'])).toBeTruthy(); + await expect(await media.blueButton).toHaveAttribute('daa-ll', blueButtonDaalh); + }); + + await test.step('step-4: Verify browser console errors', async () => { + consoleErrors.length > knownConsoleErrors.length && console.log('[Console error]:', consoleErrors); + expect.soft(consoleErrors.length).toBeLessThanOrEqual(knownConsoleErrors.length); + }); }); + // Test 2 : Media (large, dark) test(`${features[2].name},${features[2].tags}`, async ({ page, baseURL }) => { console.info(`[Test Page]: ${baseURL}${features[2].path}`); + const { data } = features[2]; await test.step('step-1: Go to media block test page', async () => { await page.goto(`${baseURL}${features[2].path}`); @@ -48,9 +108,103 @@ test.describe('Milo Media Block test suite', () => { await expect(page).toHaveURL(`${baseURL}${features[2].path}`); }); - await test.step('step-2: Verify media block specs', async () => { - const { data } = features[2]; - expect(await media.verifyMedia('media (large, dark)', data)).toBeTruthy(); + await test.step('step-2: Verify media (large, dark) block specs', async () => { + await expect(media.mediaLargeDark).toBeVisible(); + + await expect(await media.detailL).toContainText(data.detailText); + await expect(await media.headingXL).toContainText(data.h2Text); + await expect(await media.bodyM).toContainText(data.bodyText); + await expect(await media.blueButton).toContainText(data.blueButtonText); + + await expect(await media.mediaImage).toBeVisible(); + expect(await webUtil.verifyAttributes_(media.mediaImg, media.attributes['media.large']['image'])).toBeTruthy(); + }); + + await test.step('step-3: Verify analytics attributes', async () => { + const blueButtonDaalh = data.blueButtonText +'-1'+ '|' + (data.h2Text).slice(0, 20) ; + + expect(await webUtil.verifyAttributes_(media.mediaLargeDark, media.attributes['analytics']['media.daa-lh'])).toBeTruthy(); + await expect(await media.blueButton).toHaveAttribute('daa-ll', blueButtonDaalh); + }); + + await test.step('step-4: Verify browser console errors', async () => { + consoleErrors.length > knownConsoleErrors.length && console.log('[Console error]:', consoleErrors); + expect.soft(consoleErrors.length).toBeLessThanOrEqual(knownConsoleErrors.length); + }); + }); + + // Test 3 : Media (large, dark) video, autoplay infinite looping + test(`${features[3].name},${features[3].tags}`, async ({ page, baseURL, browserName }) => { + test.skip(browserName === 'webkit', 'This feature is failing on Webkit browsers') + test.slow(); + console.info(`[Test Page]: ${baseURL}${features[3].path}`); + const { data } = features[3]; + + await test.step('step-1: Go to media block test page', async () => { + await page.goto(`${baseURL}${features[3].path}`); + await page.waitForLoadState('domcontentloaded'); + await expect(page).toHaveURL(`${baseURL}${features[3].path}`); + }); + + await test.step('step-2: Verify media (large, dark) block specs', async () => { + await expect(media.mediaLargeDark).toBeVisible(); + + await expect(await media.detailL).toContainText(data.detailText); + await expect(await media.headingXL).toContainText(data.h2Text); + await expect(await media.bodyM).toContainText(data.bodyText); + await expect(await media.blueButton).toContainText(data.blueButtonText); + + await expect(await media.backgroundVideo).toBeVisible(); + expect(await webUtil.verifyAttributes_(media.backgroundVideo, media.attributes['backgroundVideo.inline'])).toBeTruthy(); }); + + await test.step('step-3: Verify analytics attributes', async () => { + const blueButtonDaalh = data.blueButtonText +'-1'+ '|' + (data.h2Text).slice(0, 20) ; + + expect(await webUtil.verifyAttributes_(media.mediaLargeDark, media.attributes['analytics']['media.daa-lh'])).toBeTruthy(); + await expect(await media.blueButton).toHaveAttribute('daa-ll', blueButtonDaalh); + }); + + await test.step('step-4: Verify browser console errors', async () => { + consoleErrors.length > knownConsoleErrors.length && console.log('[Console error]:', consoleErrors); + expect.soft(consoleErrors.length).toBeLessThanOrEqual(knownConsoleErrors.length); + }); }); + + // Test 5 : Media (large, dark) video, autoplay loop once + test(`${features[4].name},${features[4].tags}`, async ({ page, baseURL }) => { + test.slow(); + console.info(`[Test Page]: ${baseURL}${features[4].path}`); + const { data } = features[4]; + + await test.step('step-1: Go to media block test page', async () => { + await page.goto(`${baseURL}${features[4].path}`); + await page.waitForLoadState('domcontentloaded'); + await expect(page).toHaveURL(`${baseURL}${features[4].path}`); + }); + + await test.step('step-2: Verify media (large, dark) block specs', async () => { + await expect(media.mediaLargeDark).toBeVisible(); + + await expect(await media.detailL).toContainText(data.detailText); + await expect(await media.headingXL).toContainText(data.h2Text); + await expect(await media.bodyM).toContainText(data.bodyText); + await expect(await media.blueButton).toContainText(data.blueButtonText); + + await expect(await media.backgroundVideo).toBeVisible(); + expect(await webUtil.verifyAttributes_(media.backgroundVideo, media.attributes['backgroundVideo.loopOnce'])).toBeTruthy(); + }); + + await test.step('step-3: Verify analytics attributes', async () => { + const blueButtonDaalh = data.blueButtonText +'-1'+ '|' + (data.h2Text).slice(0, 20) ; + + expect(await webUtil.verifyAttributes_(media.mediaLargeDark, media.attributes['analytics']['media.daa-lh'])).toBeTruthy(); + await expect(await media.blueButton).toHaveAttribute('daa-ll', blueButtonDaalh); + }); + + await test.step('step-4: Verify browser console errors', async () => { + consoleErrors.length > knownConsoleErrors.length && console.log('[Console error]:', consoleErrors); + expect.soft(consoleErrors.length).toBeLessThanOrEqual(knownConsoleErrors.length); + }); + }); }); From c4c678371cf4e6be2e91f7c15e65e57ba73e9b07 Mon Sep 17 00:00:00 2001 From: Jacky Sun <67350368+JackySun9@users.noreply.github.com> Date: Fri, 27 Oct 2023 13:50:02 -0700 Subject: [PATCH 02/53] fix test failures (#195) * add test for quiz and result pages * add test for quiz and result pages * add test for quiz and result pages * add POC for analytics test * update analytics tests and envs * result envs * update analytics only on firefox * add dynamic tests * add dynamic test for quiz page * update quiz test * update test structure * add test for quiz and result pages * add POC for analytics test * update analytics tests and envs * result envs * update analytics only on firefox * add dynamic tests * add dynamic test for quiz page * update quiz test * update test structure * update uar tests to new format * update uar tests * move everything to uar folder * add dependency for js-yaml * update test according to latest comments * update test according to latest comments * update tests according to the latest comments * add uar config * add analytics for uar * update according to feedbacks * update tags * add @cc tag * update according to feedbacks * add dynamic tests for uar * update according to review comments * fix some typos * update according to review comments * merge console log info * add UI screenshots for UAR * move view point to test * update according to feedback * add analytics test for UAR * update validation and uar libs * update libs * update by feedback * update some config and tests * update some config and tests * update test content path to common path * update analytics tests * fix test failures caused by test code * fix test failures * fix test failures --------- Co-authored-by: xiasun Co-authored-by: Aaron Mauchley --- configs/uar.config.js | 2 +- tests/uar/quiz.dynamic.test.js | 6 +++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/configs/uar.config.js b/configs/uar.config.js index 92711477..b7f077f4 100644 --- a/configs/uar.config.js +++ b/configs/uar.config.js @@ -34,7 +34,7 @@ const config = { /* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */ use: { /* Maximum time each action such as `click()` can take. Defaults to 0 (no limit). */ - actionTimeout: 5000, + actionTimeout: 15000, /* Base URL to use in actions like `await page.goto('/')`. */ // baseURL: 'http://localhost:3000', diff --git a/tests/uar/quiz.dynamic.test.js b/tests/uar/quiz.dynamic.test.js index 0f9ebbfe..81d7ab0d 100644 --- a/tests/uar/quiz.dynamic.test.js +++ b/tests/uar/quiz.dynamic.test.js @@ -24,7 +24,11 @@ test.describe('Quiz flow test suite', () => { const originalData = await WebUtil.loadTestDataFromAPI(baseURL, feature.data); - const testdata = buildTestData(originalData, feature.name); + let testdata = buildTestData(originalData, feature.name); + + if (feature.name.includes('triple flagship')) { + testdata = testdata.sort(() => 0.5 - Math.random()).slice(0, 20); + } for (const key of testdata) { console.log(key); From 013aea432ce0a3c0c3c49fc8ad8de7c2122a91cf Mon Sep 17 00:00:00 2001 From: Santoshkumar Nateekar Date: Fri, 27 Oct 2023 13:50:18 -0700 Subject: [PATCH 03/53] MWPW-138097 : Video block automation test scripts (#194) * video and accordion test cases * update the title --------- Co-authored-by: nateekar --- features/milo/video.block.spec.js | 41 +++++++ selectors/milo/accordion.block.page.js | 164 +++---------------------- selectors/milo/video.block.page.js | 49 ++++++++ tests/milo/accordion.block.test.js | 99 +++++++++++++-- tests/milo/video.block.test.js | 144 ++++++++++++++++++++++ 5 files changed, 340 insertions(+), 157 deletions(-) create mode 100644 features/milo/video.block.spec.js create mode 100644 selectors/milo/video.block.page.js create mode 100644 tests/milo/video.block.test.js diff --git a/features/milo/video.block.spec.js b/features/milo/video.block.spec.js new file mode 100644 index 00000000..3ba4a853 --- /dev/null +++ b/features/milo/video.block.spec.js @@ -0,0 +1,41 @@ +module.exports = { + FeatureName: 'Video Block', + features: [ + { + tcid: '0', + name: '@Video Default', + path: '/drafts/nala/blocks/video/default-video', + data: { + h2Text: 'Default video', + }, + tags: '@video @smoke @regression @milo', + }, + { + tcid: '1', + name: '@Video autoplay loop', + path: '/drafts/nala/blocks/video/video-autoplay-loop', + data: { + h2Text: 'Autoplay enabled video', + }, + tags: '@video @smoke @regression @milo', + }, + { + tcid: '2', + name: '@Video autoplay loop once', + path: '/drafts/nala/blocks/video/autoplay-loop-once', + data: { + h2Text: 'Autoplay once enabled video', + }, + tags: '@video @smoke @regression @milo', + }, + { + tcid: '3', + name: '@Video hover play', + path: '/drafts/nala/blocks/video/video-hover-play', + data: { + h2Text: 'Hover play enabled video (combined with #_autoplay1 for feature to work)', + }, + tags: '@video @smoke @regression @milo', + }, + ], +}; diff --git a/selectors/milo/accordion.block.page.js b/selectors/milo/accordion.block.page.js index 392fa17b..1fb31129 100644 --- a/selectors/milo/accordion.block.page.js +++ b/selectors/milo/accordion.block.page.js @@ -1,170 +1,36 @@ -import { expect } from '@playwright/test'; -import { WebUtil } from '../../libs/webutil.js'; - export default class Accordion { - constructor(page) { + constructor(page, nth=0) { this.page = page; // accordion locators - this.accordion = this.page.locator('.accordion-container'); + this.accordion = this.page.locator('.accordion-container').nth(nth); this.accordionForeground = this.accordion.locator('.foreground'); this.accordionHeaders = this.accordion.locator('dt[role=heading]'); this.accordionButtons = this.accordion.locator('dt button'); this.accordionButtonIcons = this.accordion.locator('.accordion-icon'); - // accordion blocks css - this.cssProperties = { - '.con-block.max-width-10-desktop .foreground': { 'max-width': /^\d{2}/ }, - - '.con-block.max-width-12-desktop-large .foreground': { 'max-width': /^\d{2}/ }, - - 'accordion dd': { - 'margin': /^0.*/, - 'padding': '16px', - 'font-size': '16px', - 'line-height': '24px', - }, - - '.accordion-icon': { - 'position': 'absolute', - 'right': '16px', - 'top': /^\d{2}/, - 'margin-top': '-6px', - 'width': '12px', - 'height': '12px', - 'pointer-events': 'none', - }, - - '.accordion dt button': { - 'align-items': 'center', - 'border': '', - 'border-width': '1px 0px 0px', - 'color': 'rgb(44, 44, 44)', - 'display': 'flex', - 'font-family': '"Adobe Clean", adobe-clean, "Trebuchet MS", sans-serif', - 'font-size': '18px', - 'font-weight': '700', - 'line-height': '25px', - 'padding': '24px 32px 24px 16px', - 'position': 'relative', - 'text-align': 'left', - 'width': /^\d{4}/, - }, - - }; - // accordion blocks attributes - this.attProperties = { + this.attributes = { 'accordion-container': { 'class': 'accordion-container con-block max-width-10-desktop', - 'daa-lh': 'b1|accordion-container|default|default', }, - - 'accordion-container seo': { + 'accordion-container.seo': { 'class': 'accordion-container seo con-block max-width-10-desktop', - 'daa-lh': 'b1|accordion-container|default|default', }, - 'accordion-container-quiet-large': { 'class': 'accordion-container quiet max-width-12-desktop-large con-block', - 'daa-lh': 'b1|accordion-container|default|default', }, - - 'accordion-trigger': { 'daa-ll': /^link\|(.*)/ }, - }; - } - - /** - * Verifies the visibility, css, attributes, styles, and content of - * the Accordion block. - * - * @param {string} accordionType - The type of the Accordion block to verify. - * Possible values are 'accordion', 'accordion (seo)', and - * 'Accordion (quiet, max-width-12-desktop-large)'. - * @returns {Promise} - Returns true if the specified Quote type has the expected values. - */ - async verifyAccordion(accordionType, data) { - // verify accordion block is visible - await expect(await this.accordion).toBeVisible(); - - // verify accordion headers, buttons, and icons count - await expect(await this.accordionHeaders).toHaveCount(data.headers); - await expect(await this.accordionButtons).toHaveCount(data.headers); - await expect(await this.accordionButtonIcons).toHaveCount(data.headers); - - // verify accordion headers text content - await expect(await this.accordionHeaders.nth(0)).toContainText(data.heading0); - await expect(await this.accordionHeaders.nth(1)).toContainText(data.heading1); - await expect(await this.accordionHeaders.nth(2)).toContainText(data.heading2); - - // verify accordion button css - expect(await WebUtil.verifyCSS( - await this.accordionButtons.nth(0), - this.cssProperties['.accordion dt button'], - )).toBeTruthy(); - - // verify accordion icon css - expect(await WebUtil.verifyCSS( - await this.accordionButtonIcons.nth(0), - this.cssProperties['.accordion-icon'], - )).toBeTruthy(); - - switch (accordionType) { - case 'accordion': - // verify accordion attributes and css - expect(await WebUtil.verifyAttributes( - await this.accordion, - this.attProperties['accordion-container'], - )).toBeTruthy(); - - // verify accordion forground css - expect(await WebUtil.verifyCSS( - await this.accordionForeground.nth(0), - this.cssProperties['.con-block.max-width-10-desktop .foreground'], - )).toBeTruthy(); - - return true; - - case 'accordion (seo)': - // verify accordion attributes and css - expect(await WebUtil.verifyAttributes( - await this.accordion, - this.attProperties['accordion-container seo'], - )).toBeTruthy(); - - // verify accordion forground css - expect(await WebUtil.verifyCSS( - await this.accordionForeground.nth(0), - this.cssProperties['.con-block.max-width-10-desktop .foreground'], - )).toBeTruthy(); - - // verify seo script - // eslint-disable-next-line no-case-declarations - const scriptContent = await this.page.evaluate(() => { - const scriptElement = document.querySelector('script[type="application/ld+json"]'); - return scriptElement ? scriptElement.textContent : null; - }); - expect(scriptContent).toBeTruthy(); - console.log('Script content:', scriptContent); - - return true; - - case 'accordion (quiet, max-width-12-desktop-large)': - // verify accordion attributes and css - expect(await WebUtil.verifyAttributes( - await this.accordion, - this.attProperties['accordion-container-quiet-large'], - )).toBeTruthy(); - - // verify accordion forground css - expect(await WebUtil.verifyCSS( - await this.accordionForeground.nth(0), - this.cssProperties['.con-block.max-width-10-desktop .foreground'], - )).toBeTruthy(); - - return true; - default: - throw new Error(`Unsupported Text type: ${this.accordionType}`); + 'analytics': { + 'accordion.daa-lh': { + 'daa-lh': /b[1-9]|accordion-container|default|default/, + }, + 'section.daa-lh': { + 'daa-lh': /s[1-9]/, + }, + 'content.daa-lh': { + 'daa-lh': /b[1-9]|content|default|default/, + }, + }, } } } diff --git a/selectors/milo/video.block.page.js b/selectors/milo/video.block.page.js new file mode 100644 index 00000000..b0383361 --- /dev/null +++ b/selectors/milo/video.block.page.js @@ -0,0 +1,49 @@ +export default class Video { + constructor(page, nth=0) { + this.page = page; + + // video locators + this.section = this.page.locator('.section').nth(nth); + this.content = this.page.locator('.content').nth(nth); + this.video = this.page.locator('.content video'); + this.videoSource = this.video.locator('source'); + + // video block attributes + this.attributes = { + 'video.default': { + 'playsinline': '', + 'controls': '', + }, + 'video.source': { + 'type': 'video/mp4', + 'src': /.*.mp4/, + }, + 'video.autoplay': { + 'playsinline': '', + 'autoplay': '', + 'loop': '', + 'muted': '' + }, + 'video.autoplay.once': { + 'playsinline': '', + 'autoplay': '', + 'muted': '' + }, + 'video.hover.play': { + 'playsinline': '', + 'autoplay': '', + 'muted': '', + 'data-hoverplay': '', + 'data-mouseevent': 'true' + }, + 'analytics': { + 'section.daa-lh': { + 'daa-lh': /s[1-9]/, + }, + 'content.daa-lh': { + 'daa-lh': /b[1-9]|content|default|default/, + }, + }, + }; + } +} diff --git a/tests/milo/accordion.block.test.js b/tests/milo/accordion.block.test.js index 3b2598a1..efdda553 100644 --- a/tests/milo/accordion.block.test.js +++ b/tests/milo/accordion.block.test.js @@ -1,16 +1,33 @@ import { expect, test } from '@playwright/test'; +import { WebUtil } from '../../libs/webutil.js'; import { features } from '../../features/milo/accordion.block.spec.js'; import AccordionBlock from '../../selectors/milo/accordion.block.page.js'; +let webUtil; let accordion; +let consoleErrors = []; +const knownConsoleErrors = ['Access-Control-Allow-Origin','Failed to load resource: net::ERR_FAILED']; test.describe('Milo Accordion Block test suite', () => { test.beforeEach(async ({ page }) => { + webUtil = new WebUtil(page); accordion = new AccordionBlock(page); + + page.on('console', (exception) => { + if (exception.type() === 'error') { + consoleErrors.push(exception.text()); + } + }); }); + test.afterEach(async () =>{ + consoleErrors = []; + }); + + // Test 0 : Accordion test(`${features[0].name},${features[0].tags}`, async ({ page, baseURL }) => { console.info(`[Test Page]: ${baseURL}${features[0].path}`); + const { data } = features[0]; await test.step('step-1: Go to Accordion block test page', async () => { await page.goto(`${baseURL}${features[0].path}`); @@ -19,13 +36,40 @@ test.describe('Milo Accordion Block test suite', () => { }); await test.step('step-2: Verify Accrodion block content/specs', async () => { - const { data } = features[0]; - expect(await accordion.verifyAccordion('accordion', data)).toBeTruthy(); + await expect(await accordion.accordion).toBeVisible(); + + // verify accordion headers, buttons, and icons count + await expect(await accordion.accordionHeaders).toHaveCount(data.headers); + await expect(await accordion.accordionButtons).toHaveCount(data.headers); + await expect(await accordion.accordionButtonIcons).toHaveCount(data.headers); + + // verify accordion headers text content + await expect(await accordion.accordionHeaders.nth(0)).toContainText(data.heading0); + await expect(await accordion.accordionHeaders.nth(1)).toContainText(data.heading1); + await expect(await accordion.accordionHeaders.nth(2)).toContainText(data.heading2); + + // verify accordion buttons open close clicks + await expect(await accordion.accordionButtons.nth(0)).toHaveAttribute('aria-expanded', 'false'); + await accordion.accordionButtonIcons.nth(0).click(); + await expect(await accordion.accordionButtons.nth(0)).toHaveAttribute('aria-expanded', 'true'); + await accordion.accordionButtonIcons.nth(0).click(); + await expect(await accordion.accordionButtons.nth(0)).toHaveAttribute('aria-expanded', 'false'); + }); + + await test.step('step-3: Verify analytics attributes', async () => { + expect(await webUtil.verifyAttributes_(accordion.accordion, accordion.attributes['analytics']['accordion.daa-lh'])).toBeTruthy(); }); + + await test.step('step-4: Verify browser console errors', async () => { + consoleErrors.length > knownConsoleErrors.length && console.log('[Console error]:', consoleErrors); + expect.soft(consoleErrors.length).toBeLessThanOrEqual(knownConsoleErrors.length); + }); }); + // Test 1 : Accordion (seo) test(`${features[1].name},${features[1].tags}`, async ({ page, baseURL }) => { console.info(`[Test Page]: ${baseURL}${features[1].path}`); + const { data } = features[1]; await test.step('step-1: Go to Accordion block test page', async () => { await page.goto(`${baseURL}${features[1].path}`); @@ -33,14 +77,33 @@ test.describe('Milo Accordion Block test suite', () => { await expect(page).toHaveURL(`${baseURL}${features[1].path}`); }); - await test.step('step-2: Verify Accrodion block content/specs', async () => { - const { data } = features[1]; - expect(await accordion.verifyAccordion('accordion (seo)', data)).toBeTruthy(); + await test.step('step-2: Verify Accrodion seo block specs', async () => { + await expect(await accordion.accordion).toBeVisible(); + + const scriptContent = await page.evaluate(() => { + const scriptElement = document.querySelector('script[type="application/ld+json"]'); + return scriptElement ? scriptElement.textContent : null; + }); + expect(scriptContent).toBeTruthy(); + console.log('[SEO Script content]:', scriptContent); + + expect(await webUtil.verifyAttributes_(accordion.accordion, accordion.attributes['accordion-container.seo'])).toBeTruthy(); + }); + + await test.step('step-3: Verify analytics attributes', async () => { + expect(await webUtil.verifyAttributes_(accordion.accordion, accordion.attributes['analytics']['accordion.daa-lh'])).toBeTruthy(); + }); + + await test.step('step-4: Verify browser console errors', async () => { + consoleErrors.length > knownConsoleErrors.length && console.log('[Console error]:', consoleErrors); + expect.soft(consoleErrors.length).toBeLessThanOrEqual(knownConsoleErrors.length); }); }); +// Test 2 : Accordion (quiet, max-width-12-desktop-large) test(`${features[2].name},${features[2].tags}`, async ({ page, baseURL }) => { - console.info(`[Test Page]: ${baseURL}${features[0].path}`); + console.info(`[Test Page]: ${baseURL}${features[2].path}`); + const { data } = features[2]; await test.step('step-1: Go to Accordion block test page', async () => { await page.goto(`${baseURL}${features[2].path}`); @@ -49,8 +112,28 @@ test.describe('Milo Accordion Block test suite', () => { }); await test.step('step-2: Verify Accrodion block content/specs', async () => { - const { data } = features[2]; - expect(await accordion.verifyAccordion('accordion (quiet, max-width-12-desktop-large)', data)).toBeTruthy(); + await expect(await accordion.accordion).toBeVisible(); + + // verify accordion headers, buttons, and icons count + await expect(await accordion.accordionHeaders).toHaveCount(data.headers); + await expect(await accordion.accordionButtons).toHaveCount(data.headers); + await expect(await accordion.accordionButtonIcons).toHaveCount(data.headers); + + // verify accordion headers text content + await expect(await accordion.accordionHeaders.nth(0)).toContainText(data.heading0); + await expect(await accordion.accordionHeaders.nth(1)).toContainText(data.heading1); + await expect(await accordion.accordionHeaders.nth(2)).toContainText(data.heading2); + + expect(await webUtil.verifyAttributes_(accordion.accordion, accordion.attributes['accordion-container-quiet-large'])).toBeTruthy(); + }); + + await test.step('step-3: Verify analytics attributes', async () => { + expect(await webUtil.verifyAttributes_(accordion.accordion, accordion.attributes['analytics']['accordion.daa-lh'])).toBeTruthy(); + }); + + await test.step('step-4: Verify browser console errors', async () => { + consoleErrors.length > knownConsoleErrors.length && console.log('[Console error]:', consoleErrors); + expect.soft(consoleErrors.length).toBeLessThanOrEqual(knownConsoleErrors.length); }); }); }); diff --git a/tests/milo/video.block.test.js b/tests/milo/video.block.test.js new file mode 100644 index 00000000..a04fdd04 --- /dev/null +++ b/tests/milo/video.block.test.js @@ -0,0 +1,144 @@ +import { expect, test } from '@playwright/test'; +import { WebUtil } from '../../libs/webutil.js'; +import { features } from '../../features/milo/video.block.spec.js'; +import VideoBlock from '../../selectors/milo/video.block.page.js'; + +let webUtil; +let video; +let consoleErrors = []; +const knownConsoleErrors = ['Access-Control-Allow-Origin','Failed to load resource: net::ERR_FAILED']; + +test.describe('Milo Video Block test suite', () => { + test.beforeEach(async ({ page }) => { + webUtil = new WebUtil(page); + video = new VideoBlock(page); + + page.on('console', (exception) => { + if (exception.type() === 'error') { + consoleErrors.push(exception.text()); + } + }); + }); + + test.afterEach(async () =>{ + consoleErrors = []; + }); + + // Test 0 : Video default + test(`${features[0].name},${features[0].tags}`, async ({ page, baseURL }) => { + console.info(`[Test Page]: ${baseURL}${features[0].path}`); + const { data } = features[0]; + + await test.step('step-1: Go to video block test page', async () => { + await page.goto(`${baseURL}${features[0].path}`); + await page.waitForLoadState('domcontentloaded'); + await expect(page).toHaveURL(`${baseURL}${features[0].path}`); + }); + + await test.step('step-2: Verify video block content/specs', async () => { + await expect(await video.video).toBeVisible(); + await expect(await video.content).toContainText(data.h2Text); + + expect(await webUtil.verifyAttributes_(video.video, video.attributes['video.default'])).toBeTruthy(); + expect(await webUtil.verifyAttributes_(video.videoSource, video.attributes['video.source'])).toBeTruthy(); + }); + + await test.step('step-3: Verify analytics attributes', async () => { + expect(await webUtil.verifyAttributes_(video.content, video.attributes['analytics']['content.daa-lh'])).toBeTruthy(); + }); + + await test.step('step-4: Verify browser console errors', async () => { + consoleErrors.length > knownConsoleErrors.length && console.log('[Console error]:', consoleErrors); + expect.soft(consoleErrors.length).toBeLessThanOrEqual(knownConsoleErrors.length); + }); + }); + + // Test 1 : Video autoplay loop + test(`${features[1].name},${features[1].tags}`, async ({ page, baseURL }) => { + console.info(`[Test Page]: ${baseURL}${features[1].path}`); + const { data } = features[1]; + + await test.step('step-1: Go to video block test page', async () => { + await page.goto(`${baseURL}${features[1].path}`); + await page.waitForLoadState('domcontentloaded'); + await expect(page).toHaveURL(`${baseURL}${features[1].path}`); + }); + + await test.step('step-2: Verify video block content/specs', async () => { + await expect(await video.video).toBeVisible(); + await expect(await video.content).toContainText(data.h2Text); + + expect(await webUtil.verifyAttributes_(video.video, video.attributes['video.autoplay'])).toBeTruthy(); + expect(await webUtil.verifyAttributes_(video.videoSource, video.attributes['video.source'])).toBeTruthy(); + }); + + await test.step('step-3: Verify analytics attributes', async () => { + expect(await webUtil.verifyAttributes_(video.content, video.attributes['analytics']['content.daa-lh'])).toBeTruthy(); + }); + + await test.step('step-4: Verify browser console errors', async () => { + consoleErrors.length > knownConsoleErrors.length && console.log('[Console error]:', consoleErrors); + expect.soft(consoleErrors.length).toBeLessThanOrEqual(knownConsoleErrors.length); + }); + }); + + // Test 2 : Video autoplay loop once + test(`${features[2].name},${features[2].tags}`, async ({ page, baseURL }) => { + console.info(`[Test Page]: ${baseURL}${features[2].path}`); + const { data } = features[2]; + + await test.step('step-1: Go to video block test page', async () => { + await page.goto(`${baseURL}${features[2].path}`); + await page.waitForLoadState('domcontentloaded'); + await expect(page).toHaveURL(`${baseURL}${features[2].path}`); + }); + + await test.step('step-2: Verify video block content/specs', async () => { + await expect(await video.video).toBeVisible(); + await expect(await video.content).toContainText(data.h2Text); + + expect(await webUtil.verifyAttributes_(video.video, video.attributes['video.autoplay.once'])).toBeTruthy(); + expect(await webUtil.verifyAttributes_(video.videoSource, video.attributes['video.source'])).toBeTruthy(); + }); + + await test.step('step-3: Verify analytics attributes', async () => { + expect(await webUtil.verifyAttributes_(video.content, video.attributes['analytics']['content.daa-lh'])).toBeTruthy(); + }); + + await test.step('step-4: Verify browser console errors', async () => { + consoleErrors.length > knownConsoleErrors.length && console.log('[Console error]:', consoleErrors); + expect.soft(consoleErrors.length).toBeLessThanOrEqual(knownConsoleErrors.length); + }); + }); + + // Test 3 : Video hover play + test(`${features[3].name},${features[3].tags}`, async ({ page, baseURL }) => { + console.info(`[Test Page]: ${baseURL}${features[3].path}`); + const { data } = features[3]; + + await test.step('step-1: Go to video block test page', async () => { + await page.goto(`${baseURL}${features[3].path}`); + await page.waitForLoadState('domcontentloaded'); + await expect(page).toHaveURL(`${baseURL}${features[3].path}`); + }); + + await test.step('step-2: Verify video block content/specs', async () => { + await expect(await video.video).toBeVisible(); + await expect(await video.content).toContainText(data.h2Text); + await new Promise(resolve => setTimeout(resolve, 2000)); + await video.video.hover(); + + expect(await webUtil.verifyAttributes_(video.video, video.attributes['video.autoplay.once'])).toBeTruthy(); + expect(await webUtil.verifyAttributes_(video.videoSource, video.attributes['video.source'])).toBeTruthy(); + }); + + await test.step('step-3: Verify analytics attributes', async () => { + expect(await webUtil.verifyAttributes_(video.content, video.attributes['analytics']['content.daa-lh'])).toBeTruthy(); + }); + + await test.step('step-4: Verify browser console errors', async () => { + consoleErrors.length > knownConsoleErrors.length && console.log('[Console error]:', consoleErrors); + expect.soft(consoleErrors.length).toBeLessThanOrEqual(knownConsoleErrors.length); + }); + }); +}); From bc681fc42bb469515651a13595c37ebb9f091d88 Mon Sep 17 00:00:00 2001 From: Santoshkumar Nateekar Date: Mon, 30 Oct 2023 13:19:01 -0700 Subject: [PATCH 04/53] MWPW-138097 : Video block automation test scripts (#197) * video and accordion test cases * update the title * adding few more test scripts * update content attribute * update scripts --------- Co-authored-by: nateekar --- features/milo/video.block.spec.js | 51 +++++++++ selectors/milo/video.block.page.js | 28 ++++- tests/milo/video.block.test.js | 166 +++++++++++++++++++++++++---- 3 files changed, 226 insertions(+), 19 deletions(-) diff --git a/features/milo/video.block.spec.js b/features/milo/video.block.spec.js index 3ba4a853..e4e91cf7 100644 --- a/features/milo/video.block.spec.js +++ b/features/milo/video.block.spec.js @@ -37,5 +37,56 @@ module.exports = { }, tags: '@video @smoke @regression @milo', }, + { + tcid: '4', + name: '@MPC Video', + path: '/drafts/nala/blocks/video/mpc-video', + data: { + h1Title: '1856730_Summit_2021_Marquee_1440x1028_v1.0.mp4', + iframeTitle: 'Adobe Video Publishing Cloud Player', + source: 'https://video.tv.adobe.com/v/332632', + }, + tags: '@video @smoke @regression @milo', + }, + { + tcid: '5', + name: '@MPC Video Autoplay Looping', + path: '/drafts/nala/blocks/video/mpc-video-autoplay-looping', + data: { + iframeTitle: 'Adobe Video Publishing Cloud Player', + source: 'https://video.tv.adobe.com/v/332632?autoplay=true&end=replay', + }, + tags: '@video @smoke @regression @milo', + }, + { + tcid: '6', + name: '@Youtube Video ', + path: '/drafts/nala/blocks/video/youtube-video', + data: { + h1Text: 'YouTube video', + iframeTitle: 'Adobe MAX Keynote 2022 | Adobe Creative Cloud', + source: 'https://www.youtube.com/embed/OfQKEzgPaBA?', + }, + tags: '@video @smoke @regression @milo', + }, + { + tcid: '7', + name: '@Fragment Modal video inline', + path: '/drafts/nala/blocks/video/fragments-modal-video-autoplay', + data: { + source: 'https://main--milo--adobecom.hlx.live/libs/media_1e798d01c6ddc7e7eadc8f134d69e4f8d7193fdbb.mp4', + }, + tags: '@video @smoke @regression @milo', + }, + { + tcid: '8', + name: '@Modal video with cards', + path: '/drafts/nala/blocks/video/modal-video-with-cards', + data: { + cardsCount: 3, + source: 'https://milo.adobe.com/libs/media_1e798d01c6ddc7e7eadc8f134d69e4f8d7193fdbb.mp4', + }, + tags: '@video @smoke @regression @milo', + }, ], }; diff --git a/selectors/milo/video.block.page.js b/selectors/milo/video.block.page.js index b0383361..9fb2dde2 100644 --- a/selectors/milo/video.block.page.js +++ b/selectors/milo/video.block.page.js @@ -5,6 +5,20 @@ export default class Video { // video locators this.section = this.page.locator('.section').nth(nth); this.content = this.page.locator('.content').nth(nth); + this.fragment = this.page.locator('.fragment') + this.video = this.page.locator('.content video'); + this.videoSource = this.video.locator('source'); + this.miloVideo = this.page.locator('.milo-video'); + this.iframe = this.page.locator('iframe').first(); + this.mpcPlayerTitle = this.page.frameLocator('iframe').first().locator('.mpc-player__title'); + this.mpcPlayButton = this.page.frameLocator('iframe').first().locator('.mpc-player button[aria-label="Play"]'); + this.mpcMutedButton = this.page.frameLocator('iframe').first().locator('.mpc-player button[aria-label="Mute"]'); + this.mpcMutedLabel = this.page.frameLocator('iframe').first().locator('.mpc-player button[aria-label="Mute"] span'); + this.youtubePlayButton = this.page.frameLocator('iframe').first().locator('button[aria-label="Play"]'); + this.modalVideo = this.fragment.locator('video') + this.modalVideoSource = this.modalVideo.locator('source'); + this.consonantCardsGrid = this.page.locator('.consonant-CardsGrid'); + this.consonantCards = this.consonantCardsGrid.locator('.card.consonant-Card'); this.video = this.page.locator('.content video'); this.videoSource = this.video.locator('source'); @@ -35,7 +49,19 @@ export default class Video { 'muted': '', 'data-hoverplay': '', 'data-mouseevent': 'true' - }, + }, + 'iframe-mpc': { + 'class': 'adobetv', + 'scrolling': 'no', + 'allowfullscreen': '', + 'loading': 'lazy', + }, + 'iframe-youtube': { + 'class': 'youtube', + 'scrolling': 'no', + 'allowfullscreen': '', + 'allow': 'encrypted-media; accelerometer; gyroscope; picture-in-picture', + }, 'analytics': { 'section.daa-lh': { 'daa-lh': /s[1-9]/, diff --git a/tests/milo/video.block.test.js b/tests/milo/video.block.test.js index a04fdd04..b99976a8 100644 --- a/tests/milo/video.block.test.js +++ b/tests/milo/video.block.test.js @@ -43,11 +43,7 @@ test.describe('Milo Video Block test suite', () => { expect(await webUtil.verifyAttributes_(video.videoSource, video.attributes['video.source'])).toBeTruthy(); }); - await test.step('step-3: Verify analytics attributes', async () => { - expect(await webUtil.verifyAttributes_(video.content, video.attributes['analytics']['content.daa-lh'])).toBeTruthy(); - }); - - await test.step('step-4: Verify browser console errors', async () => { + await test.step('step-3: Verify browser console errors', async () => { consoleErrors.length > knownConsoleErrors.length && console.log('[Console error]:', consoleErrors); expect.soft(consoleErrors.length).toBeLessThanOrEqual(knownConsoleErrors.length); }); @@ -72,11 +68,7 @@ test.describe('Milo Video Block test suite', () => { expect(await webUtil.verifyAttributes_(video.videoSource, video.attributes['video.source'])).toBeTruthy(); }); - await test.step('step-3: Verify analytics attributes', async () => { - expect(await webUtil.verifyAttributes_(video.content, video.attributes['analytics']['content.daa-lh'])).toBeTruthy(); - }); - - await test.step('step-4: Verify browser console errors', async () => { + await test.step('step-3: Verify browser console errors', async () => { consoleErrors.length > knownConsoleErrors.length && console.log('[Console error]:', consoleErrors); expect.soft(consoleErrors.length).toBeLessThanOrEqual(knownConsoleErrors.length); }); @@ -101,11 +93,7 @@ test.describe('Milo Video Block test suite', () => { expect(await webUtil.verifyAttributes_(video.videoSource, video.attributes['video.source'])).toBeTruthy(); }); - await test.step('step-3: Verify analytics attributes', async () => { - expect(await webUtil.verifyAttributes_(video.content, video.attributes['analytics']['content.daa-lh'])).toBeTruthy(); - }); - - await test.step('step-4: Verify browser console errors', async () => { + await test.step('step-3: Verify browser console errors', async () => { consoleErrors.length > knownConsoleErrors.length && console.log('[Console error]:', consoleErrors); expect.soft(consoleErrors.length).toBeLessThanOrEqual(knownConsoleErrors.length); }); @@ -132,11 +120,153 @@ test.describe('Milo Video Block test suite', () => { expect(await webUtil.verifyAttributes_(video.videoSource, video.attributes['video.source'])).toBeTruthy(); }); - await test.step('step-3: Verify analytics attributes', async () => { - expect(await webUtil.verifyAttributes_(video.content, video.attributes['analytics']['content.daa-lh'])).toBeTruthy(); + await test.step('step-3: Verify browser console errors', async () => { + consoleErrors.length > knownConsoleErrors.length && console.log('[Console error]:', consoleErrors); + expect.soft(consoleErrors.length).toBeLessThanOrEqual(knownConsoleErrors.length); + }); + }); + + // Test 4 : MPC Video + test(`${features[4].name},${features[4].tags}`, async ({ page, baseURL }) => { + test.slow(); + console.info(`[Test Page]: ${baseURL}${features[4].path}`); + const { data } = features[4]; + + await test.step('step-1: Go to video block test page', async () => { + await page.goto(`${baseURL}${features[4].path}`); + await page.waitForLoadState('domcontentloaded'); + await expect(page).toHaveURL(`${baseURL}${features[4].path}`); + }); + + await test.step('step-2: Verify video block content/specs', async () => { + await expect(await video.miloVideo).toBeVisible(); + await expect(await video.iframe).toBeVisible(); + await expect(await video.mpcPlayButton).toBeVisible(); + await expect(await video.mpcPlayerTitle).toContainText(data.h1Title); + + await expect(await video.iframe).toHaveAttribute('title', data.iframeTitle); + await expect(await video.iframe).toHaveAttribute('src', data.source); + expect(await webUtil.verifyAttributes_(video.iframe, video.attributes['iframe-mpc'])).toBeTruthy(); + }); + + await test.step('step-3: Verify browser console errors', async () => { + consoleErrors.length > knownConsoleErrors.length && console.log('[Console error]:', consoleErrors); + expect.soft(consoleErrors.length).toBeLessThanOrEqual(knownConsoleErrors.length); + }); + }); + + // Test 5 : MPC Video Autoplay Looping + test(`${features[5].name},${features[5].tags}`, async ({ page, baseURL }) => { + test.slow(); + console.info(`[Test Page]: ${baseURL}${features[5].path}`); + const { data } = features[5]; + + await test.step('step-1: Go to video block test page', async () => { + await page.goto(`${baseURL}${features[5].path}`); + await page.waitForLoadState('domcontentloaded'); + await expect(page).toHaveURL(`${baseURL}${features[5].path}`); + }); + + await test.step('step-2: Verify video block content/specs', async () => { + await expect(await video.miloVideo).toBeVisible(); + await expect(await video.iframe).toBeVisible(); + await expect(await video.mpcMutedButton).toBeVisible(); + + await expect(await video.iframe).toHaveAttribute('title', data.iframeTitle); + await expect(await video.iframe).toHaveAttribute('src', data.source); + expect(await webUtil.verifyAttributes_(video.iframe, video.attributes['iframe-mpc'])).toBeTruthy(); + }); + + await test.step('step-3: Verify browser console errors', async () => { + consoleErrors.length > knownConsoleErrors.length && console.log('[Console error]:', consoleErrors); + expect.soft(consoleErrors.length).toBeLessThanOrEqual(knownConsoleErrors.length); + }); + }); + + // Test 6 : Youtube Video + test(`${features[6].name},${features[6].tags}`, async ({ page, baseURL }) => { + test.slow(); + console.info(`[Test Page]: ${baseURL}${features[6].path}`); + const { data } = features[6]; + + await test.step('step-1: Go to video block test page', async () => { + await page.goto(`${baseURL}${features[6].path}`); + await page.waitForLoadState('domcontentloaded'); + await expect(page).toHaveURL(`${baseURL}${features[6].path}`); + }); + + await test.step('step-2: Verify video block content/specs', async () => { + await expect(await video.miloVideo).toBeVisible(); + await expect(await video.iframe).toBeVisible(); + await expect(await video.youtubePlayButton).toBeVisible(); + await expect(await video.youtubePlayButton).toHaveAttribute('title', 'Play'); + + await expect(await video.iframe).toHaveAttribute('title', data.iframeTitle); + await expect(await video.iframe).toHaveAttribute('src', data.source); + expect(await webUtil.verifyAttributes_(video.iframe, video.attributes['iframe-youtube'])).toBeTruthy(); + }); + + await test.step('step-3: Verify browser console errors', async () => { + consoleErrors.length > knownConsoleErrors.length && console.log('[Console error]:', consoleErrors); + }); + }); + + // Test 7 : Modal Video default + test(`${features[7].name},${features[7].tags}`, async ({ page, baseURL }) => { + test.slow(); + console.info(`[Test Page]: ${baseURL}${features[7].path}`); + const { data } = features[7]; + + await test.step('step-1: Go to video block test page', async () => { + await page.goto(`${baseURL}${features[7].path}`); + await page.waitForLoadState('domcontentloaded'); + await expect(page).toHaveURL(`${baseURL}${features[7].path}`); + }); + + await test.step('step-2: Verify video block content/specs', async () => { + await expect(await video.modalVideo).toBeVisible(); + + expect(await webUtil.verifyAttributes_(video.modalVideo, video.attributes['video.autoplay'])).toBeTruthy(); + expect(await webUtil.verifyAttributes_(video.modalVideoSource, video.attributes['video.source'])).toBeTruthy(); + + const srcAttributeValue = await video.modalVideoSource.getAttribute('src'); + console.log('[video source]:', srcAttributeValue); + expect(srcAttributeValue).not.toBe(''); + }); + + await test.step('step-3: Verify browser console errors', async () => { + consoleErrors.length > knownConsoleErrors.length && console.log('[Console error]:', consoleErrors); + expect.soft(consoleErrors.length).toBeLessThanOrEqual(knownConsoleErrors.length); + }); + }); + + // Test 8 : Modal video with cards + test(`${features[8].name},${features[8].tags}`, async ({ page, baseURL,browserName }) => { + test.slow(); + console.info(`[Test Page]: ${baseURL}${features[8].path}`); + const { data } = features[8]; + + await test.step('step-1: Go to video block test page', async () => { + await page.goto(`${baseURL}${features[8].path}`); + await page.waitForLoadState('domcontentloaded'); + await expect(page).toHaveURL(`${baseURL}${features[8].path}`); + }); + + await test.step('step-2: Verify consonant cards with modal video block content/specs', async () => { + await expect(await video.consonantCardsGrid).toBeVisible(); + await expect(await video.consonantCards.nth(0)).toBeVisible(); + await expect(await video.consonantCards).toHaveCount(data.cardsCount); + + await expect(await video.modalVideo).toBeVisible(); + expect(await webUtil.verifyAttributes_(video.modalVideo, video.attributes['video.autoplay'])).toBeTruthy(); + expect(await webUtil.verifyAttributes_(video.modalVideoSource, video.attributes['video.source'])).toBeTruthy(); + + const srcAttributeValue = await video.modalVideoSource.getAttribute('src'); + console.log('[video source]:', srcAttributeValue); + expect(srcAttributeValue).not.toBe(''); }); - await test.step('step-4: Verify browser console errors', async () => { + await test.step('step-3: Verify browser console errors', async () => { consoleErrors.length > knownConsoleErrors.length && console.log('[Console error]:', consoleErrors); expect.soft(consoleErrors.length).toBeLessThanOrEqual(knownConsoleErrors.length); }); From 5ca9f73c5300632029b4a730650ec3e45571147f Mon Sep 17 00:00:00 2001 From: Dan Chivescu Date: Mon, 30 Oct 2023 23:03:20 +0200 Subject: [PATCH 05/53] [MWPW-136596] FEDS Visual Comparison Checks (#192) * [MWPW-136596] Added FEDS VC checks * [MWPW-136596] Added VC config file * [MWPW-136596] Updated VC checks * [MWPW-136596] Updated FEDS VC checks --------- Co-authored-by: Aaron Mauchley --- .gitignore | 1 + configs/feds.vc.config.js | 92 +++++++++++++++++++ .../visual-compare/feds/footer.block.spec.js | 12 +++ .../visual-compare/feds/header.block.spec.js | 12 +++ .../feds/footer.block.vc.test.js | 43 +++++++++ .../feds/header.block.vc.test.js | 52 +++++++++++ 6 files changed, 212 insertions(+) create mode 100644 configs/feds.vc.config.js create mode 100644 features/visual-compare/feds/footer.block.spec.js create mode 100644 features/visual-compare/feds/header.block.spec.js create mode 100644 visual-compare-tests/feds/footer.block.vc.test.js create mode 100644 visual-compare-tests/feds/header.block.vc.test.js diff --git a/.gitignore b/.gitignore index 3ffb04ea..199e0b4e 100644 --- a/.gitignore +++ b/.gitignore @@ -125,4 +125,5 @@ axe-reports /playwright/.cache/ Test.pptx nala-results.json +configs/screenshots/ configs/test-html-results/ diff --git a/configs/feds.vc.config.js b/configs/feds.vc.config.js new file mode 100644 index 00000000..64f53220 --- /dev/null +++ b/configs/feds.vc.config.js @@ -0,0 +1,92 @@ +// @ts-check +const { devices } = require('@playwright/test'); + +/** + * @see https://playwright.dev/docs/test-configuration + * @type {import('@playwright/test').PlaywrightTestConfig} + */ +const config = { + testDir: '../visual-compare-tests/feds/', // TODO: Switch to ./tests once baseURL conditional checks have been made on individual tests + outputDir: '../test-results', + /* Maximum time one test can run for. */ + timeout: 30 * 1000, + /** + * Location of snapshots generated by expect(page).toHaveScreenshot() + * and expect(snapshot).toMatchSnapshot(). + */ + snapshotPathTemplate: 'screenshots/{testFilePath}/{arg}{ext}', + expect: { + /** + * Maximum time expect() should wait for the condition to be met. + * For example in `await expect(locator).toHaveText();` + */ + timeout: 5000, + toHaveScreenshot: { maxDiffPixelRatio: 0.3 }, + }, + /* Run tests in files in parallel */ + fullyParallel: true, + /* Fail the build on CI if you accidentally left test.only in the source code. */ + forbidOnly: !!process.env.CI, + /* Retry on CI only */ + retries: process.env.CI ? 2 : 0, + /* Opt out of parallel tests on CI. */ + workers: process.env.CI ? 2 : undefined, + /* Reporter to use. See https://playwright.dev/docs/test-reporters */ + reporter: process.env.CI + ? [['github'], ['./utils/reporters/json-reporter.js'], ['./utils/reporters/api-reporter.js']] + : [['html', { outputFolder: 'test-html-results' }]], + /* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */ + use: { + /* Maximum time each action such as `click()` can take. Defaults to 0 (no limit). */ + actionTimeout: 60000, + /* Base URL to use in actions like `await page.goto('/')`. */ + // baseURL: 'http://localhost:3000', + + /* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */ + trace: 'on-first-retry', + baseURL: 'https://main--milo--adobecom.hlx.live', // TODO: Remove once baseURL checks have been made on individual tests + }, + + /* Configure projects for major browsers */ + projects: [ + { + name: 'chromium', + use: { + ...devices['Desktop Chrome'], + viewport: { width: 1280, height: 720 }, + }, + }, + + { + name: 'firefox', + use: { + ...devices['Desktop Firefox'], + viewport: { width: 1280, height: 720 }, + }, + }, + + { + name: 'webkit', + use: { + ...devices['Desktop Safari'], + viewport: { width: 1280, height: 720 }, + }, + }, + + /* Test visually against mobile viewports. */ + // { + // name: 'android', + // use: { ...devices['Pixel 5'] }, + // }, + // { + // name: 'iphone', + // use: { ...devices['iPhone SE'] }, + // }, + // { + // name: 'ipad', + // use: { ...devices['iPad Mini'] }, + // }, + ], +}; + +module.exports = config; diff --git a/features/visual-compare/feds/footer.block.spec.js b/features/visual-compare/feds/footer.block.spec.js new file mode 100644 index 00000000..105cf1ed --- /dev/null +++ b/features/visual-compare/feds/footer.block.spec.js @@ -0,0 +1,12 @@ +module.exports = { + name: 'Footer VC Suite', + features: [ + { + tcid: '0', + name: '@Footer-VC-Checks', + path: '/libs/feds/drafts/qa/footer/feds-default-footer', + tags: '@footer-visual, @feds-visual, @visual, @visual-smoke, @visual-regression', + browserParams: '?georouting=off', + }, + ], +}; diff --git a/features/visual-compare/feds/header.block.spec.js b/features/visual-compare/feds/header.block.spec.js new file mode 100644 index 00000000..521b46d9 --- /dev/null +++ b/features/visual-compare/feds/header.block.spec.js @@ -0,0 +1,12 @@ +module.exports = { + name: 'Header VC Suite', + features: [ + { + tcid: '0', + name: '@Header-VC-Checks', + path: '/libs/feds/drafts/qa/header/feds-header-page', + tags: '@header-visual, @feds-heaver, @visual, @visual-smoke, @visual-regression', + browserParams: '?georouting=off', + }, + ], +}; diff --git a/visual-compare-tests/feds/footer.block.vc.test.js b/visual-compare-tests/feds/footer.block.vc.test.js new file mode 100644 index 00000000..e966fb70 --- /dev/null +++ b/visual-compare-tests/feds/footer.block.vc.test.js @@ -0,0 +1,43 @@ +/* eslint-disable import/named */ +import { expect, test } from '@playwright/test'; +import { features } from '../../features/visual-compare/feds/footer.block.spec.js'; +import FedsConsent from '../../selectors/feds/feds.consent.page.js'; +import { WebUtil } from '../../libs/webutil.js'; + +// Globals: +let webUtil; +let Consent; + +test.describe('FEDS Footer Block Visual Comparison Test Suite', () => { + test.beforeEach(async ({ page }) => { + webUtil = new WebUtil(page); + Consent = new FedsConsent(page); + }); + + test(`${features[0].name}, ${features[0].tags}`, async ({ page, baseURL }) => { + console.info(`[Test Page]: ${baseURL}${features[0].path}`); + + await test.step('Navigate to FEDS FOOTER page', async () => { + await page.goto(`${baseURL}${features[0].path}${features[0].browserParams}`); + // Wait for page to load & stabilize: + await page.waitForLoadState('domcontentloaded'); + await expect(page).toHaveURL(`${baseURL}${features[0].path}${features[0].browserParams}`); + }); + + await test.step('Check consent persistence (post-consent)', async () => { + // Accept the OneTrust consent banner: + await Consent.acceptOneTrustConsentBar(); + // Check consent persistence: + await Consent.assertOneTrustAcceptState(); + }); + + await test.step('Compare base screenshot against current screenshot', async () => { + // Scroll to initiate lazy loaded images: + await webUtil.scrollPage('down', 'slow'); + await webUtil.scrollPage('up', 'fast'); + // Compare the base screenshot against a newly taken screenshot for equality + // If no base screenshot image is available for comparison create one. + await expect(page).toHaveScreenshot(`footer_${baseURL}${features[0].path}.png`, { fullPage: true, timeout: 30000 }); + }); + }); +}); diff --git a/visual-compare-tests/feds/header.block.vc.test.js b/visual-compare-tests/feds/header.block.vc.test.js new file mode 100644 index 00000000..2535a77b --- /dev/null +++ b/visual-compare-tests/feds/header.block.vc.test.js @@ -0,0 +1,52 @@ +/* eslint-disable import/named */ +import { expect, test } from '@playwright/test'; +import { features } from '../../features/visual-compare/feds/header.block.spec.js'; +import FedsConsent from '../../selectors/feds/feds.consent.page.js'; +import FedsHeader from '../../selectors/feds/feds.header.page.js'; +import { WebUtil } from '../../libs/webutil.js'; + +// Globals: +let Header; +let Consent; +let webUtil; + +test.describe('FEDS Header Block Visual Comparison Test Suite', () => { + test.beforeEach(async ({ page }) => { + webUtil = new WebUtil(page); + Header = new FedsHeader(page); + Consent = new FedsConsent(page); + }); + + test(`${features[0].name}, ${features[0].tags}`, async ({ page, baseURL }) => { + console.info(`[Test Page]: ${baseURL}${features[0].path}`); + + await test.step('Navigate to FEDS HEADER page', async () => { + await page.goto(`${baseURL}${features[0].path}${features[0].browserParams}`); + // Wait for page to load & stabilize: + await page.waitForLoadState('domcontentloaded'); + await expect(page).toHaveURL(`${baseURL}${features[0].path}${features[0].browserParams}`); + }); + + await test.step('Check consent persistence (post-consent)', async () => { + // Accept the OneTrust consent banner: + await Consent.acceptOneTrustConsentBar(); + // Check consent persistence: + await Consent.assertOneTrustAcceptState(); + }); + + await test.step('Open HEADER mega-menu prior to VC check', async () => { + await Header.megaMenuToggle.waitFor({ state: 'visible', timeout: 5000 }); + await Header.megaMenuToggle.click(); + await expect(Header.megaMenuContainer).toBeVisible(); + }); + + await test.step('Compare base screenshot against current screenshot', async () => { + // Scroll to initiate lazy loaded images: + await webUtil.scrollPage('down', 'slow'); + await webUtil.scrollPage('up', 'fast'); + // Compare the base screenshot against a newly taken screenshot for equality + // If no base screenshot image is available for comparison create one. + await expect(page).toHaveScreenshot(`header_${baseURL}${features[0].path}.png`, { fullPage: true, timeout: 30000 }); + }); + }); +}); From fae9e2c7b6dc7e0ab46440c1b47e7bbc122f8891 Mon Sep 17 00:00:00 2001 From: Santoshkumar Nateekar Date: Wed, 1 Nov 2023 11:37:35 -0700 Subject: [PATCH 06/53] commenting linux-webkit project (#198) * commenting linux-webkit project * commenting the project --------- Co-authored-by: nateekar --- playwright.config.js | 5 +++-- run.sh | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/playwright.config.js b/playwright.config.js index 99420337..e9c73701 100644 --- a/playwright.config.js +++ b/playwright.config.js @@ -58,13 +58,14 @@ const config = { ...devices['Desktop Firefox'], }, }, - + /** { name: 'milo-live-webkit', use: { ...devices['Desktop Safari'], }, - }, + }, + */ ], }; diff --git a/run.sh b/run.sh index 272ee464..e3c763e3 100755 --- a/run.sh +++ b/run.sh @@ -84,7 +84,7 @@ if [[ -n "$APPS" ]];then echo "*** npx playwright test --config=./configs/${conf_name}.config.js ${TAGS} --project=${app_name} ***" npx playwright test --config=./configs/${conf_name}.config.js ${TAGS} --project=${app_name}-chrome ${REPORTER} npx playwright test --config=./configs/${conf_name}.config.js ${TAGS} --project=${app_name}-firefox ${REPORTER} - npx playwright test --config=./configs/${conf_name}.config.js ${TAGS} --project=${app_name}-webkit ${REPORTER} + # npx playwright test --config=./configs/${conf_name}.config.js ${TAGS} --project=${app_name}-webkit ${REPORTER} else # Run all the projects from config file for all projects echo "*** npx playwright test --config="$config_file" ${TAGS} ${REPORTER} ***" From b8dd0e239368e70b4a5fae7c9ad64a001b68556b Mon Sep 17 00:00:00 2001 From: ancysr <127083004+ancysr@users.noreply.github.com> Date: Thu, 2 Nov 2023 11:51:23 +0530 Subject: [PATCH 07/53] CodeBlock and Draft (#196) * commit helpx internal procedure component * Incorporating review comments * commit beforeAfter changes * handled scenario if auth token not set in env variable * CodeBlock and Draft cases * Reviews * Committing config changes * Update helpx.config.js --------- Co-authored-by: Santoshkumar Nateekar --- configs/helpx.config.js | 80 ++++++++++++++++++ envs/envs.js | 2 +- features/helpx/beforeAfter.spec.js | 1 - features/helpx/codeBlock.spec.js | 11 +++ features/helpx/draft.spec.js | 11 +++ features/helpx/procedure.spec.js | 1 - selectors/helpx/beforeafter.page.js | 15 ++++ selectors/helpx/beforeafter.selectors.js | 11 --- selectors/helpx/codeBlock.page.js | 55 ++++++++++++ selectors/helpx/draft.page.js | 38 +++++++++ selectors/helpx/procedure.page.js | 14 +++ selectors/helpx/procedure.selectors.js | 12 --- tests/helpx/beforeafter.test.js | 42 ++++----- tests/helpx/codeBlock.test.js | 103 +++++++++++++++++++++++ tests/helpx/draft.test.js | 98 +++++++++++++++++++++ tests/helpx/procedure.test.js | 41 +++++---- 16 files changed, 468 insertions(+), 67 deletions(-) create mode 100644 configs/helpx.config.js create mode 100644 features/helpx/codeBlock.spec.js create mode 100644 features/helpx/draft.spec.js create mode 100644 selectors/helpx/beforeafter.page.js delete mode 100644 selectors/helpx/beforeafter.selectors.js create mode 100644 selectors/helpx/codeBlock.page.js create mode 100644 selectors/helpx/draft.page.js create mode 100644 selectors/helpx/procedure.page.js delete mode 100644 selectors/helpx/procedure.selectors.js create mode 100644 tests/helpx/codeBlock.test.js create mode 100644 tests/helpx/draft.test.js diff --git a/configs/helpx.config.js b/configs/helpx.config.js new file mode 100644 index 00000000..abc49c66 --- /dev/null +++ b/configs/helpx.config.js @@ -0,0 +1,80 @@ +// @ts-check +const { devices } = require('@playwright/test'); + +const envs = require('../envs/envs.js'); + +/** + * @see https://playwright.dev/docs/test-configuration + * @type {import('@playwright/test').PlaywrightTestConfig} + */ +const config = { + testDir: '../tests/helpx', + outputDir: '../test-results', + /* Maximum time one test can run for. */ + timeout: 30 * 1000, + /** + * Location of snapshots generated by expect(page).toHaveScreenshot() + * and expect(snapshot).toMatchSnapshot(). + */ + snapshotPathTemplate: 'screenshots/{testFilePath}/{arg}{ext}', + expect: { + /** + * Maximum time expect() should wait for the condition to be met. + * For example in `await expect(locator).toHaveText();` + */ + timeout: 5000, + toHaveScreenshot: { maxDiffPixelRatio: 0.2 }, + }, + /* Run tests in files in parallel */ + fullyParallel: true, + /* Fail the build on CI if you accidentally left test.only in the source code. */ + forbidOnly: !!process.env.CI, + /* Retry on CI only */ + retries: process.env.CI ? 2 : 0, + /* Opt out of parallel tests on CI. */ + workers: process.env.CI ? 2 : undefined, + /* Reporter to use. See https://playwright.dev/docs/test-reporters */ + reporter: process.env.CI + ? [['github'], ['list'], ['../utils/reporters/base-reporter.js']] + : [ + ['html', { outputFolder: 'test-html-results' }], + ['list'], + ['./utils/reporters/base-reporter.js'], + ], + /* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */ + use: { + /* Maximum time each action such as `click()` can take. Defaults to 0 (no limit). */ + actionTimeout: 60000, + /* Base URL to use in actions like `await page.goto('/')`. */ + // baseURL: 'http://localhost:3000', + + /* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */ + trace: 'on-first-retry', + baseURL: process.env.PR_BRANCH_LIVE_URL || ( process.env.LOCAL_TEST_LIVE_URL ||'https://helpx-internal.stage.adobe.com'), + }, + + /* Configure projects for major browsers */ + projects: [ + { + name: 'helpx-live-chrome', + use: { + ...devices['Desktop Chrome'], + }, + }, + + { + name: 'helpx-live-firefox', + use: { + ...devices['Desktop Firefox'], + }, + }, + + { + name: 'helpx-live-webkit', + use: { + ...devices['Desktop Safari'], + }, + }, + ], +}; +export default config; diff --git a/envs/envs.js b/envs/envs.js index 970b2a91..27bba2ca 100644 --- a/envs/envs.js +++ b/envs/envs.js @@ -17,5 +17,5 @@ module.exports = { '@uar_live': 'https://uar-integration--milo--adobecom.hlx.live', '@local3000': 'http://localhost:3000', '@local6456': 'http://localhost:6456', - '@helpxInternal_live':'https://helpx-internal.stage.adobe.com', + '@helpx_live':'https://helpx-internal.stage.adobe.com', }; diff --git a/features/helpx/beforeAfter.spec.js b/features/helpx/beforeAfter.spec.js index 098cebc4..c2aaa04e 100644 --- a/features/helpx/beforeAfter.spec.js +++ b/features/helpx/beforeAfter.spec.js @@ -5,7 +5,6 @@ module.exports = { tcid: '0', name: '@beforeAfter', path: '/automation/blocks/before-after-component', - envs: '@helpxInternal_live', tags: '@beforeafter @regression @helpx', }, ], diff --git a/features/helpx/codeBlock.spec.js b/features/helpx/codeBlock.spec.js new file mode 100644 index 00000000..33471b2e --- /dev/null +++ b/features/helpx/codeBlock.spec.js @@ -0,0 +1,11 @@ +module.exports = { + name: 'CodeBlock', + features: [ + { + tcid: '0', + name: '@codeBlock', + path: '/automation/blocks/code-block', + tags: '@codeBlk @regression @helpx', + }, + ], +}; diff --git a/features/helpx/draft.spec.js b/features/helpx/draft.spec.js new file mode 100644 index 00000000..f49a8d04 --- /dev/null +++ b/features/helpx/draft.spec.js @@ -0,0 +1,11 @@ +module.exports = { + name: 'Draft', + features: [ + { + tcid: '0', + name: '@draft', + path: '/automation/blocks/Drafts/draft-test', + tags: '@draft @regression @helpx', + }, + ], +}; diff --git a/features/helpx/procedure.spec.js b/features/helpx/procedure.spec.js index 103e6ab8..f1346432 100644 --- a/features/helpx/procedure.spec.js +++ b/features/helpx/procedure.spec.js @@ -5,7 +5,6 @@ module.exports = { tcid: '0', name: '@procedureValidation', path: '/automation/blocks/procedure', - envs: '@helpxInternal_live', tags: '@procedure @regression @helpx', }, ], diff --git a/selectors/helpx/beforeafter.page.js b/selectors/helpx/beforeafter.page.js new file mode 100644 index 00000000..207b33e1 --- /dev/null +++ b/selectors/helpx/beforeafter.page.js @@ -0,0 +1,15 @@ +import { expect } from '@playwright/test'; +import { WebUtil } from '../../libs/webutil.js'; + +export default class BeforeAfter { + constructor(page) { + this.page = page; + + // BeforeAfter Selectors: + this.beforeAftr = page.locator('.beforeafter'); + this.beforeafterVertical = page.locator(selectors['@beforeafter-vertical']); + this.beforeafterVerticalmoved = page.locator( + selectors['@beforeafter-vertical-moved'] + ); + } +} diff --git a/selectors/helpx/beforeafter.selectors.js b/selectors/helpx/beforeafter.selectors.js deleted file mode 100644 index aac745f5..00000000 --- a/selectors/helpx/beforeafter.selectors.js +++ /dev/null @@ -1,11 +0,0 @@ -exports.BeforeAfter = class BeforeAfter { - constructor(page) { - this.page = page; - - // BeforeAfter Selectors: - this.beforeAftr = page.locator('.beforeafter'); - this.beforeafterVertical = page.locator(selectors['@beforeafter-vertical']); - this.beforeafterVerticalmoved = page.locator(selectors['@beforeafter-vertical-moved']); - } - -}; \ No newline at end of file diff --git a/selectors/helpx/codeBlock.page.js b/selectors/helpx/codeBlock.page.js new file mode 100644 index 00000000..9f863e0d --- /dev/null +++ b/selectors/helpx/codeBlock.page.js @@ -0,0 +1,55 @@ +import { expect } from '@playwright/test'; +import { WebUtil } from '../../libs/webutil.js'; + +export default class CodeBlock { + constructor(page) { + this.page = page; + + // CodeBlock Selectors: + this.codeA3 = page.locator('div.language-as3'); + this.codeFusion = page.locator('div.language-coldfusion'); + this.codeC = page.locator('div.language-c'); + this.codeCss = page.locator('div.language-css'); + this.codeJava = page.locator('div.language-java'); + this.codeJS = page.locator('div.language-javascript'); + this.codePhp = page.locator('div.language-php'); + this.codePlain = page.locator('div.language-plain'); + this.codeSql = page.locator('div.language-sql'); + this.codeXml = page.locator('div.language-xml'); + this.codeMxml = page.locator('div.language-mxml'); + this.codeA3Num = page.locator('.language-as3.line-numbers'); + this.codeFusionNum = page.locator('.language-coldfusion.line-numbers'); + this.codeCNum = page.locator('.language-c.line-numbers'); + this.codeCssNum = page.locator('.language-css.line-numbers'); + this.codeJavaNum = page.locator('.language-java.line-numbers'); + this.codeJSNum = page.locator('.language-javascript.line-numbers'); + this.codePhpNum = page.locator('.language-php.line-numbers'); + this.codePlainNum = page.locator('.language-plain.line-numbers'); + this.codeSqlNum = page.locator('.language-sql.line-numbers'); + this.codeXmlNum = page.locator('.language-xml.line-numbers'); + this.codeMxmlNum = page.locator('.language-mxml.line-numbers'); + this.codeHideDsktop = page.locator('.hidden-desktop'); + this.codeHideTablet = page.locator('.hidden-tablet'); + this.codeHideMobile = page.locator('.hidden-mobile'); + + // quote blocks css + this.cssProperties = { + 'codeHideDsktop': { + 'display': 'none', + }, + 'codeHideTablet': { + 'display': 'block', + }, + 'codeHideMobile': { + 'display': 'block', + }, + }; + + // quote blocks attributes + this.attProperties = { + 'codeHideDsktop': { 'class': 'code language-javascript line-numbers hidden-desktop' }, + 'codeHideTablet': { 'class': 'code language-php line-numbers hidden-tablet' }, + 'codeHideMobile': { 'class': 'code language-sql line-numbers hidden-mobile' }, + }; + } +}; diff --git a/selectors/helpx/draft.page.js b/selectors/helpx/draft.page.js new file mode 100644 index 00000000..2d8e70c2 --- /dev/null +++ b/selectors/helpx/draft.page.js @@ -0,0 +1,38 @@ +import { expect } from '@playwright/test'; +import { WebUtil } from '../../libs/webutil.js'; + +export default class Draft { + constructor(page) { + this.page = page; + + // Draft Selectors: + this.beforeAftr = page.locator('.before-after-slider'); + this.procedure = page.locator('.procedure'); + this.codeBlock = page.locator('.code'); + this.generic = page.locator('.generic'); + + // draft blocks css + this.cssProperties = { + 'beforeAftr': { + 'display': 'none', + }, + 'procedure': { + 'display': 'none', + }, + 'codeBlock': { + 'display': 'none', + }, + 'generic': { + 'display': 'none', + }, + }; + + // draft blocks attributes + this.attProperties = { + 'beforeAftr': { 'class': 'before-after-slider vertical draft' }, + 'procedure': { 'class': 'procedure draft' }, + 'codeBlock': { 'class': 'code language-as3 line-numbers draft' }, + 'generic': { 'class': 'generic draft class1 class2' }, + }; + } +}; diff --git a/selectors/helpx/procedure.page.js b/selectors/helpx/procedure.page.js new file mode 100644 index 00000000..011e0a21 --- /dev/null +++ b/selectors/helpx/procedure.page.js @@ -0,0 +1,14 @@ +import { expect } from '@playwright/test'; +import { WebUtil } from '../../libs/webutil.js'; + +export default class Procedure { + constructor(page) { + this.page = page; + + // Procedure Selectors: + this.procedure = page.locator('.procedure'); + this.procedureStep = page.locator('li[class=step]'); + this.procedureImage = page.locator('hli[class=step] img'); + this.procedureTxtBold = page.locator('li[class=step] strong'); + } +} diff --git a/selectors/helpx/procedure.selectors.js b/selectors/helpx/procedure.selectors.js deleted file mode 100644 index b30bf0d9..00000000 --- a/selectors/helpx/procedure.selectors.js +++ /dev/null @@ -1,12 +0,0 @@ -exports.Procedure = class Procedure { - constructor(page) { - this.page = page; - - // Procedure Selectors: - this.procedure = page.locator('.procedure'); - this.procedureStep = page.locator('li[class=step]'); - this.procedureImage = page.locator('hli[class=step] img'); - this.procedureTxtBold = page.locator('li[class=step] strong'); - } - - }; \ No newline at end of file diff --git a/tests/helpx/beforeafter.test.js b/tests/helpx/beforeafter.test.js index f253d1a4..65a9ffbf 100644 --- a/tests/helpx/beforeafter.test.js +++ b/tests/helpx/beforeafter.test.js @@ -1,44 +1,46 @@ import { expect, test } from '@playwright/test'; import { features } from '../../features/helpx/procedure.spec.js'; -import { BeforeAfter } from '../../selectors/helpx/procedure.selectors.js'; +import { BeforeAfter } from '../../selectors/helpx/procedure.page.js'; let beforeAftr; -test.beforeAll(async({browser})=>{ - if (process.env.HLX_TKN !== undefined && process.env.HLX_TKN !== "") { +test.beforeAll(async ({ browser }) => { + if (process.env.HLX_TKN !== undefined && process.env.HLX_TKN !== '') { // The environment variable is set and has a non-blank value - console.log("Environment variable is set and not blank"); + console.log('Environment variable is set and not blank'); } else { // The environment variable is either not set or has a blank value - const errorMessage = "Environment variable 'HLX_TKN' is not set or blank. Please ensure it is properly configured."; + const errorMessage = + "Environment variable 'HLX_TKN' is not set or blank. Please ensure it is properly configured."; throw new Error(errorMessage); } const authToken = process.env.HLX_TKN; const context = await browser.newContext(); - // Set the authorization token in the header - await context.setExtraHTTPHeaders({ 'authorization': `token ${authToken}` }); - const page = await context.newPage(); - beforeAftr = new BeforeAfter(page); - await page.goto(`${baseURL}${features[0].path}`); - await page.waitForLoadState('networkidle'); -}) + // Set the authorization token in the header + await context.setExtraHTTPHeaders({ authorization: `token ${authToken}` }); + const page = await context.newPage(); + beforeAftr = new BeforeAfter(page); + await page.goto(`${baseURL}${features[0].path}`); + await page.waitForLoadState('networkidle'); +}); test.describe('BeforeAfter sanity test suite', () => { - // Procedure Sanity Checks: - test(`${features[0].name}, ${features[0].tags}`, async ({ page, baseURL }) => { - console.info(`[BeforeAfter] Checking page: ${baseURL}${features[0].path}`); + test(`${features[0].name}, ${features[0].tags}`, async ({ + page, + baseURL, + }) => { + console.info(`[Test Page]: ${baseURL}${features[0].path}`); await test.step('Navigate to BeforeAfter page', async () => { - await expect(page).toHaveURL(`${baseURL}${features[0].path}`); + await expect(page).toHaveURL(`${baseURL}${features[0].path}`); }); // Check beforeAfter await expect(beforeAftr.beforeafterVertical).toBeVisible(); - + // Check beforeAfter after vertical movement beforeafterVertical.scrollTop -= 40; await expect(beforeAftr.beforeafterVerticalmoved).toBeVisible(); - - }); - }); \ No newline at end of file + }); +}); diff --git a/tests/helpx/codeBlock.test.js b/tests/helpx/codeBlock.test.js new file mode 100644 index 00000000..1e29adac --- /dev/null +++ b/tests/helpx/codeBlock.test.js @@ -0,0 +1,103 @@ +import { expect, test } from '@playwright/test'; +import { features } from '../../features/helpx/codeBlock.spec.js'; +import { CodeBlock } from '../../selectors/helpx/codeBlock.page.js'; + +let codeBlk; + +test.beforeAll(async ({ browser }) => { + if (process.env.HLX_TKN !== undefined && process.env.HLX_TKN !== '') { + // The environment variable is set and has a non-blank value + console.log('Environment variable is set and not blank'); + } else { + // The environment variable is either not set or has a blank value + const errorMessage = + "Environment variable 'HLX_TKN' is not set or blank. Please ensure it is properly configured."; + throw new Error(errorMessage); + } + + const authToken = process.env.HLX_TKN; + const context = await browser.newContext(); + // Set the authorization token in the header + await context.setExtraHTTPHeaders({ authorization: `token ${authToken}` }); + const page = await context.newPage(); + codeBlk = new CodeBlock(page); + await page.goto(`${baseURL}${features[0].path}`); + await page.waitForLoadState('networkidle'); +}); + +test.describe('CodeBlock sanity test suite', () => { + // CodeBlock Sanity Checks: + test(`${features[0].name}, ${features[0].tags}`, async ({ + page, + baseURL, + }) => { + console.info(`[Test Page]: ${baseURL}${features[0].path}`); + await test.step('Navigate to CodeBlock page', async () => { + await expect(page).toHaveURL(`${baseURL}${features[0].path}`); + }); + + // Check for different codeBlock formats present + await expect(codeBlk.codeBlockA3).toBeVisible(); + await expect(codeBlk.codeFusion).toBeVisible(); + await expect(codeBlk.codeC).toBeVisible(); + await expect(codeBlk.codeCss).toBeVisible(); + await expect(codeBlk.codeJava).toBeVisible(); + await expect(codeBlk.codeJS).toBeVisible(); + await expect(codeBlk.codePhp).toBeVisible(); + await expect(codeBlk.codePlain).toBeVisible(); + await expect(codeBlk.codeSql).toBeVisible(); + await expect(codeBlk.codeXml).toBeVisible(); + await expect(codeBlk.codeMxml).toBeVisible(); + + // Check different InLineNumber codeBlock formats present + await expect(codeBlk.codeBlockA3Num).toBeVisible(); + await expect(codeBlk.codeFusionNum).toBeVisible(); + await expect(codeBlk.codeCNum).toBeVisible(); + await expect(codeBlk.codeCssNum).toBeVisible(); + await expect(codeBlk.codeJavaNum).toBeVisible(); + await expect(codeBlk.codeJSNum).toBeVisible(); + await expect(codeBlk.codePhpNum).toBeVisible(); + await expect(codeBlk.codePlainNum).toBeVisible(); + await expect(codeBlk.codeSqlNum).toBeVisible(); + await expect(codeBlk.codeXmlNum).toBeVisible(); + await expect(codeBlk.codeMxmlNum).toBeVisible(); + + expect( + await WebUtil.verifyCSS( + await this.codeHideDsktop, + this.cssProperties['codeHideDsktop'] + ) + ).toBeTruthy(); + expect( + await WebUtil.verifyCSS( + await this.codeHideTablet, + this.cssProperties['codeHideTablet'] + ) + ).toBeTruthy(); + expect( + await WebUtil.verifyCSS( + await this.codeHideMobile, + this.cssProperties['codeHideMobile'] + ) + ).toBeTruthy(); + + expect( + await WebUtil.verifyAttributes( + await this.codeHideDsktop, + this.attProperties['codeHideDsktop'] + ) + ).toBeTruthy(); + expect( + await WebUtil.verifyAttributes( + await this.codeHideTablet, + this.attProperties['codeHideTablet'] + ) + ).toBeTruthy(); + expect( + await WebUtil.verifyAttributes( + await this.codeHideMobile, + this.attProperties['codeHideMobile'] + ) + ).toBeTruthy(); + }); +}); diff --git a/tests/helpx/draft.test.js b/tests/helpx/draft.test.js new file mode 100644 index 00000000..bd8c61d1 --- /dev/null +++ b/tests/helpx/draft.test.js @@ -0,0 +1,98 @@ +import { expect, test } from '@playwright/test'; +import { features } from '../../features/helpx/draft.spec.js'; +import { Draft } from '../../selectors/helpx/draft.page.js'; + +let draft; + +test.beforeAll(async ({ browser }) => { + if (process.env.HLX_TKN !== undefined && process.env.HLX_TKN !== '') { + // The environment variable is set and has a non-blank value + console.log('Environment variable is set and not blank'); + } else { + // The environment variable is either not set or has a blank value + const errorMessage = + "Environment variable 'HLX_TKN' is not set or blank. Please ensure it is properly configured."; + throw new Error(errorMessage); + } + + const authToken = process.env.HLX_TKN; + const context = await browser.newContext(); + // Set the authorization token in the header + await context.setExtraHTTPHeaders({ authorization: `token ${authToken}` }); + const page = await context.newPage(); + draft = new Draft(page); + await page.goto(`${baseURL}${features[0].path}`); + await page.waitForLoadState('networkidle'); +}); + +test.describe('Draft sanity test suite', () => { + // Draft Sanity Checks: + test(`${features[0].name}, ${features[0].tags}`, async ({ + page, + baseURL, + }) => { + console.info(`[Test Page]: ${baseURL}${features[0].path}`); + await test.step('Navigate to Draft page', async () => { + await expect(page).toHaveURL(`${baseURL}${features[0].path}`); + }); + + // Check procedure present + await expect(draft.procedure).toBeVisible(); + + // Check beforeAftr present + await expect(draft.beforeAftr).toBeVisible(); + + // Check codeBlock present + await expect(draft.codeBlock).toBeVisible(); + + // Check generic present + await expect(draft.generic).toBeVisible(); + + expect( + await WebUtil.verifyCSS( + await this.procedure, + this.cssProperties['procedure'] + ) + ).toBeTruthy(); + expect( + await WebUtil.verifyCSS( + await this.beforeAftr, + this.cssProperties['beforeAftr'] + ) + ).toBeTruthy(); + expect( + await WebUtil.verifyCSS( + await this.codeBlock, + this.cssProperties['codeBlock'] + ) + ).toBeTruthy(); + expect( + await WebUtil.verifyCSS(await this.generic, this.cssProperties['generic']) + ).toBeTruthy(); + + expect( + await WebUtil.verifyAttributes( + await this.procedure, + this.attProperties['procedure'] + ) + ).toBeTruthy(); + expect( + await WebUtil.verifyAttributes( + await this.beforeAftr, + this.attProperties['beforeAftr'] + ) + ).toBeTruthy(); + expect( + await WebUtil.verifyAttributes( + await this.codeBlock, + this.attProperties['codeBlock'] + ) + ).toBeTruthy(); + expect( + await WebUtil.verifyAttributes( + await this.generic, + this.attProperties['generic'] + ) + ).toBeTruthy(); + }); +}); diff --git a/tests/helpx/procedure.test.js b/tests/helpx/procedure.test.js index 1f11b7b3..cb96ceee 100644 --- a/tests/helpx/procedure.test.js +++ b/tests/helpx/procedure.test.js @@ -1,39 +1,39 @@ import { expect, test } from '@playwright/test'; import { features } from '../../features/helpx/procedure.spec.js'; -import { Procedure} from '../../selectors/helpx/procedure.selectors.js'; - +import { Procedure } from '../../selectors/helpx/procedure.page.js'; let procedure; -test.beforeAll(async({browser})=>{ - - if (process.env.HLX_TKN !== undefined && process.env.HLX_TKN !== "") { +test.beforeAll(async ({ browser }) => { + if (process.env.HLX_TKN !== undefined && process.env.HLX_TKN !== '') { // The environment variable is set and has a non-blank value - console.log("Environment variable is set and not blank"); + console.log('Environment variable is set and not blank'); } else { // The environment variable is either not set or has a blank value - const errorMessage = "Environment variable 'HLX_TKN' is not set or blank. Please ensure it is properly configured."; + const errorMessage = + "Environment variable 'HLX_TKN' is not set or blank. Please ensure it is properly configured."; throw new Error(errorMessage); } const authToken = process.env.HLX_TKN; const context = await browser.newContext(); - // Set the authorization token in the header - await context.setExtraHTTPHeaders({ 'authorization': `token ${authToken}` }); - const page = await context.newPage(); - procedure = new Procedure(page); - await page.goto(`${baseURL}${features[0].path}`); - await page.waitForLoadState('networkidle'); -}) - + // Set the authorization token in the header + await context.setExtraHTTPHeaders({ authorization: `token ${authToken}` }); + const page = await context.newPage(); + procedure = new Procedure(page); + await page.goto(`${baseURL}${features[0].path}`); + await page.waitForLoadState('networkidle'); +}); test.describe('Procedure Sanity test suite', () => { - // Procedure Sanity Checks: - test(`${features[0].name}, ${features[0].tags}`, async ({ page, baseURL }) => { - console.info(`[Procedure] Checking page: ${baseURL}${features[0].path}`); + test(`${features[0].name}, ${features[0].tags}`, async ({ + page, + baseURL, + }) => { + console.info(`[Test Page]: ${baseURL}${features[0].path}`); await test.step('Navigate to Procedure page', async () => { - await expect(page).toHaveURL(`${baseURL}${features[0].path}`); + await expect(page).toHaveURL(`${baseURL}${features[0].path}`); }); await test.step('Check Procedure page content', async () => { @@ -48,7 +48,6 @@ test.describe('Procedure Sanity test suite', () => { // Check bold text in procedure: await expect(procedure.procedureTxtBold).toBeVisible(); - }); }); -}); \ No newline at end of file +}); From 4a4590af1ece7601b5088a84349d30ed061a64f5 Mon Sep 17 00:00:00 2001 From: Santoshkumar Nateekar Date: Thu, 2 Nov 2023 16:46:39 -0700 Subject: [PATCH 08/53] Add video test script to Modal feature test suite (#199) * add video test to modal and update marquee console fn * testing token * update the console log --------- Co-authored-by: nateekar --- features/milo/modal.block.spec.js | 16 ++++- selectors/milo/modal.block.page.js | 111 ++++++++++------------------- tests/milo/marquee.block.test.js | 2 +- tests/milo/modal.block.test.js | 82 +++++++++++++++++++-- 4 files changed, 131 insertions(+), 80 deletions(-) diff --git a/features/milo/modal.block.spec.js b/features/milo/modal.block.spec.js index d766d5ff..48ae69c7 100644 --- a/features/milo/modal.block.spec.js +++ b/features/milo/modal.block.spec.js @@ -20,7 +20,7 @@ module.exports = { path: '/drafts/nala/blocks/modal/modal-media', data: { modalId: 'modal-media', - detailText: 'DETAIL M 12/15', + detailText: 'Detail M 12/15', fragment: 'media', contentType: 'media', h2Text: 'Heading M 24/30 Media', @@ -28,5 +28,19 @@ module.exports = { }, tags: '@modal @smoke @regression @milo', }, + { + tcid: '2', + name: '@Modal Autoplay Video', + path: '/drafts/nala/blocks/modal/modal-autoplay-video', + data: { + modalId: 'modal-video-autoplay', + detailText: 'Detail M 12/15', + fragment: 'media', + contentType: 'media', + h2Text: 'Heading M 24/30 Media', + bodyText: 'Body S 16/24 Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed', + }, + tags: '@modal @smoke @regression @milo', + }, ], }; diff --git a/selectors/milo/modal.block.page.js b/selectors/milo/modal.block.page.js index a67c355b..b5683564 100644 --- a/selectors/milo/modal.block.page.js +++ b/selectors/milo/modal.block.page.js @@ -1,99 +1,64 @@ -import { expect } from '@playwright/test'; -import { WebUtil } from '../../libs/webutil.js'; - export default class Modal { constructor(page) { this.page = page; // modal locators + this.dialog = this.page.locator('.dialog-modal'); this.modal = this.page.locator('.dialog-modal'); this.fragment = this.modal.locator('.fragment'); this.headingXL = this.page.locator('.heading-xl'); this.bodyM = this.page.locator('.body-m').nth(2); this.modalCloseButton = this.modal.locator('.dialog-close'); - this.marqueeLight = this.page.locator('.marquee.light'); + this.dialogCloseButton = this.modal.locator('.dialog-close'); + this.marqueeLight = this.dialog.locator('.marquee.light'); this.modelSelector = '.dialog-modal'; - + // text block - this.text = this.modal.locator('.text'); - this.textHeading = this.text.locator('h2'); - this.textBodyM = this.text.locator('.body-m'); + this.textBlock = this.modal.locator('.text'); + this.textBlockHeading = this.textBlock.locator('h2'); + this.textBlockBodyM = this.textBlock.locator('.body-m'); // media block - this.media = this.modal.locator('.media'); - this.detailM = this.media.locator('.detail-m'); - this.textHeadingMedia = this.media.locator('h2'); - this.textBodySMedia = this.media.locator('.body-s').first(); + this.mediaBlock = this.modal.locator('.media'); + this.mediaBlockdetailM = this.mediaBlock.locator('.detail-m'); + this.mediaBlockTextHeading = this.mediaBlock.locator('h2'); + this.mediaBlockTextBodyS = this.mediaBlock.locator('.body-s').first(); + + // video block + this.video = this.modal.locator('video'); // modal contents attributes - this.attProperties = { + this.attributes = { 'modal-link': { - class: 'modal link-block ', + 'class': 'modal link-block ', + }, + 'video.inline': { + 'playsinline': '', + 'autoplay': '', + 'loop': '', + 'muted': '' }, }; } /** - * Verifies that a modal with the specified ID can be opened and closed. - * @param {string} modalData - Modal data required to verify modal. - * @returns {Promise} - A Promise that resolves to true if the verification - * is successful, or false if an error occurs. - */ - async verifyModal(modalData) { + * Gets the modal link based on the modal id. + * Waits for the link to be visible before returning the locator. + * @param {Object} data - The data object containing modalId. + * @param {number} [timeout=3000] - Optional timeout for waiting. + * @returns {Promise} - The locator for the modal link. + * @throws Will throw an error if the link is not found within the timeout. + */ + async getModalLink(modalId, timeout = 1000) { + if (!modalId) { + throw new Error('Invalid data, "modalId" property is required.'); + } + const selector = `a[href="#${modalId}"]`; + const modalLink = this.page.locator(selector); try { - // verify modal link attributes and then click - const modalLink = await this.page.locator(`a[href="#${modalData.modalId}"]`); - await expect(await modalLink).toBeVisible(); - expect(await WebUtil.verifyAttributes( - modalLink, - this.attProperties['modal-link'], - )).toBeTruthy(); - - await modalLink.click(); - - // validate modal content - switch (modalData.fragment) { - case 'text': - await expect(await this.modal).toContainText(modalData.bodyText); - await expect(await this.modalCloseButton).toBeVisible(); - expect(await WebUtil.isModalInViewport( - this.page, - this.modalSelector, - )).toBeTruthy(); - - // verify modal content (text fragment) - await expect(await this.text).toBeVisible(); - await expect(await this.textHeading).toContainText(modalData.h2Text); - await expect(await this.textBodyM).toContainText(modalData.bodyText); - - // close the modal - await this.modalCloseButton.click(); - - return true; - - case 'media': - await expect(await this.modal).toContainText(modalData.bodyText); - await expect(await this.modalCloseButton).toBeVisible(); - expect(await WebUtil.isModalInViewport( - this.page, - this.modalSelector, - )).toBeTruthy(); - - // verify modal content (media fragment) - await expect(await this.media).toBeVisible(); - await expect(await this.textHeadingMedia).toContainText(modalData.h2Text); - await expect(await this.textBodySMedia).toContainText(modalData.bodyText); - - // close the modal using escape key press. - await this.page.keyboard.press('Escape'); - - return true; - - default: - throw new Error(`Unsupported Text type: ${this.textType}`); - } + await modalLink.waitFor({ state: 'visible', timeout }); + return modalLink; } catch (error) { - console.error(`Error verifying modal: ${error}`); - return false; + throw new Error(`The modal link with selector "${selector}" could not be found within ${timeout}ms.`); } } } diff --git a/tests/milo/marquee.block.test.js b/tests/milo/marquee.block.test.js index b980ff3b..8aea29b5 100644 --- a/tests/milo/marquee.block.test.js +++ b/tests/milo/marquee.block.test.js @@ -13,7 +13,7 @@ test.describe('Milo Marquee Block test suite', () => { webUtil = new WebUtil(page); marquee = new MarqueeBlock(page); - page.on('pageerror', (exception) => { + page.on('console', (exception) => { if (exception.type() === 'error') { consoleErrors.push(exception.text()); } diff --git a/tests/milo/modal.block.test.js b/tests/milo/modal.block.test.js index 6bb2fea7..ba972b6f 100644 --- a/tests/milo/modal.block.test.js +++ b/tests/milo/modal.block.test.js @@ -1,29 +1,51 @@ import { expect, test } from '@playwright/test'; +import { WebUtil } from '../../libs/webutil.js'; import { features } from '../../features/milo/modal.block.spec.js'; import ModalBlock from '../../selectors/milo/modal.block.page.js'; let modal; +let webUtil; test.describe('Milo Modal feature test suite', () => { test.beforeEach(async ({ page }) => { modal = new ModalBlock(page); + webUtil = new WebUtil(page); }); + // Test 0 : Modal with Text block test(`${features[0].name},${features[0].tags}`, async ({ page, baseURL }) => { console.info(`[Test Page]: ${baseURL}${features[0].path}`); await test.step('step-1: Go to Modal feature test page', async () => { await page.goto(`${baseURL}${features[0].path}`); await page.waitForLoadState('domcontentloaded'); - await expect(page).toHaveURL(`${baseURL}${features[0].path}`); + await expect(page).toHaveURL(`${baseURL}${features[0].path}`); }); await test.step('step-2: Verify Modal text fragment content/specs', async () => { - const modalData = features[0].data; - expect(await modal.verifyModal(modalData)).toBeTruthy(); + const data = features[0].data; + const modalLink = await modal.getModalLink(data.modalId); + await expect(await modalLink).toBeVisible(); + await expect(await modalLink).toHaveAttribute('class', modal.attributes['modal-link']['class']); + + //click the modal link + await modalLink.click(); + await expect(await modal.dialog).toBeVisible(); + + await expect(await modal.textBlock).toBeVisible(); + await expect(await modal.textBlockHeading).toContainText(data.h2Text); + await expect(await modal.textBlockBodyM).toContainText(data.bodyText); + + expect(await WebUtil.isModalInViewport(modal.page, modal.modalSelector)).toBeTruthy(); + + // click the modal close button + await expect(await modal.dialogCloseButton).toBeVisible(); + await modal.dialogCloseButton.click(); + }); }); + // Test 1 : Modal with Media block test(`${features[1].name}, ${features[1].tags}`, async ({ page, baseURL }) => { console.info(`[Test Page]: ${baseURL}${features[1].path}`); @@ -34,8 +56,58 @@ test.describe('Milo Modal feature test suite', () => { }); await test.step('step-2: Verify Modal media fragement content/specs', async () => { - const modalData = features[1].data; - expect(await modal.verifyModal(modalData)).toBeTruthy(); + const data = features[1].data; + //expect(await modal.verifyModal(modalData)).toBeTruthy(); + + const modalLink = await modal.getModalLink(data.modalId); + await expect(await modalLink).toBeVisible(); + await expect(await modalLink).toHaveAttribute('class', modal.attributes['modal-link']['class']); + + //click the modal link + await modalLink.click(); + await expect(await modal.dialog).toBeVisible(); + + await expect(await modal.mediaBlock).toBeVisible(); + await expect(await modal.mediaBlockdetailM).toContainText(data.detailText); + await expect(await modal.mediaBlockTextHeading).toContainText(data.h2Text); + await expect(await modal.mediaBlockTextBodyS).toContainText(data.bodyText); + + expect(await WebUtil.isModalInViewport(modal.page, modal.modalSelector)).toBeTruthy(); + + // close the modal using escape key press + await expect(await modal.dialogCloseButton).toBeVisible(); + await modal.page.keyboard.press('Escape'); }); }); + + // Test 2 : Modal with Video Autoplay + test(`${features[2].name}, ${features[2].tags}`, async ({ page, baseURL }) => { + console.info(`[Test Page]: ${baseURL}${features[2].path}`); + + await test.step('step-1: Go to Modal feature test page', async () => { + await page.goto(`${baseURL}${features[2].path}`); + await page.waitForLoadState('domcontentloaded'); + await expect(page).toHaveURL(`${baseURL}${features[2].path}`); + }); + + await test.step('step-2: Verify Modal media fragement content/specs', async () => { + const data = features[2].data; + + const modalLink = await modal.getModalLink(data.modalId); + await expect(await modalLink).toBeVisible(); + await expect(await modalLink).toHaveAttribute('class', modal.attributes['modal-link']['class']); + + //click the modal link and verify video autoplay + await modalLink.click(); + await expect(await modal.dialog).toBeVisible(); + expect(await WebUtil.isModalInViewport(modal.page, modal.modalSelector)).toBeTruthy(); + + await expect(await modal.video).toBeVisible(); + expect(await webUtil.verifyAttributes_(await modal.video, modal.attributes['video.inline'])).toBeTruthy(); + + // close the modal using escape key press + await expect(await modal.dialogCloseButton).toBeVisible(); + await modal.page.keyboard.press('Escape'); + }); + }); }); From 35806375ccfc820ed69d82247014b3bdff58c709 Mon Sep 17 00:00:00 2001 From: Santoshkumar Nateekar Date: Tue, 7 Nov 2023 13:49:46 -0800 Subject: [PATCH 09/53] [MWPW-138844] : Merch-card block tests scripts (#201) * merch-cards test scripts * remove webhook url * update the url * updated eof space * updated the locator --------- Co-authored-by: nateekar --- features/milo/merchcard.block.spec.js | 133 +++++++++++ libs/slack.js | 27 +++ selectors/milo/merchcard.block.page.js | 81 +++++++ tests/milo/merchcard.block.test.js | 303 +++++++++++++++++++++++++ utils/reporters/base-reporter.js | 25 +- 5 files changed, 560 insertions(+), 9 deletions(-) create mode 100644 features/milo/merchcard.block.spec.js create mode 100644 libs/slack.js create mode 100644 selectors/milo/merchcard.block.page.js create mode 100644 tests/milo/merchcard.block.test.js diff --git a/features/milo/merchcard.block.spec.js b/features/milo/merchcard.block.spec.js new file mode 100644 index 00000000..37603425 --- /dev/null +++ b/features/milo/merchcard.block.spec.js @@ -0,0 +1,133 @@ +module.exports = { + FeatureName: 'Merch Card Block', + features: [ + { + tcid: '0', + name: '@Merch-card (Segment)', + path: '/drafts/nala/blocks/merch-card/merch-card-segment', + data: { + title: 'Individuals', + price: 'US$59.99/mo', + strikethroughPrice: 'US$89.99/mo', + description: 'Save over 25% on 20+ apps, including Photoshop, Illustrator, and more. First year only. Ends 27', + link1Text: "See what's included", + link2Text: 'Learn more', + footerOutlineButtonText: 'Learn More', + footerBlueButtonText: 'Save now', + }, + tags: '@merch-card @smoke @regression @milo', + }, + { + tcid: '1', + name: '@Merch-card (Segment) with Badge', + path: '/drafts/nala/blocks/merch-card/merch-card-segment-with-badge', + data: { + title: 'Individuals', + badgeText: 'Best value', + price: 'US$59.99/mo', + strikethroughPrice: 'US$89.99/mo', + description: 'Save over 25% on 20+ apps, including Photoshop, Illustrator, and more. First year only. Ends 27', + link1Text: "See what's included", + link2Text: 'Learn more', + footerOutlineButtonText: 'Learn More', + footerBlueButtonText: 'Save now', + }, + tags: '@merch-card @smoke @regression @milo', + }, + { + tcid: '2', + name: '@Merch-card (special-offers) ', + path: '/drafts/nala/blocks/merch-card/merch-card-special-offers', + data: { + titleH4: 'INDIVIDUALS', + titleH3: 'Save over 30% on Creative Cloud All Apps.', + description1: 'Get 20+ creative apps and save big when you choose a yearly plan instead of a monthly plan.', + description2: 'Create gorgeous images, rich graphics, and incredible art. Save 10% for the first year. Ends Mar 20.', + footerBlueButtonText: 'Save now', + }, + tags: '@merch-card @smoke @regression @milo', + }, + { + tcid: '3', + name: '@Merch-card (special-offers) with badge', + path: '/drafts/nala/blocks/merch-card/merch-card-special-offers-with-badge', + data: { + titleH4: 'INDIVIDUALS', + titleH3: 'Get 10% off Photoshop.', + badgeText: 'LIMITED TIME WEEKLY OFFER', + price: 'US$383.88/yr', + strikethroughPrice: 'US$32.99/mo', + description: 'Create gorgeous images, rich graphics, and incredible art. Save 10% for the first year. Ends Mar 20.', + link1Text: "See terms", + footerOutlineButtonText: 'Learn More', + footerBlueButtonText: 'Save now', + }, + tags: '@merch-card @smoke @regression @milo', + }, + { + tcid: '4', + name: '@Merch-card (plans)', + path: '/drafts/nala/blocks/merch-card/merch-cards-plans', + data: { + titleH3: 'Creative Cloud All Apps', + titleH5: 'Desktop', + price: 'US$79.99/mo', + description: 'Get 20+ Creative Cloud apps including Photoshop, Illustrator, Adobe Express, Premiere Pro, and Acrobat Pro. (Substance 3D apps are not included.)', + link1Text: "See plan & pricing details", + footerBlueButtonText: 'Buy now', + }, + tags: '@merch-card @smoke @regression @milo', + }, + { + tcid: '5', + name: '@Merch-card (plans) with badge', + path: '/drafts/nala/blocks/merch-card/merch-card-plans-with-badge', + data: { + titleH3: 'Creative Cloud All Apps', + titleH5: 'Desktop', + badgeText: 'Best value', + price: 'US$79.99/mo', + description: 'Get 20+ Creative Cloud apps including Photoshop, Illustrator, Adobe Express, Premiere Pro, and Acrobat Pro. (Substance 3D apps are not included.)', + link1Text: "See plan & pricing details", + footerBlueButtonText: 'Buy now', + }, + tags: '@merch-card @smoke @regression @milo', + }, + { + tcid: '6', + name: '@Merch-card (plans, secure)', + path: '/drafts/nala/blocks/merch-card/merch-card-plans-secure', + data: { + titleH3: 'Acrobat', + titleH5: 'Desktop + mobile', + price: 'US$79.99/mo', + description: 'The complete PDF solution for working anywhere (includes desktop, web, and mobile access).', + link1Text: "See plan & pricing details", + checkboxLabel: "Add a 30-day free trial of Adobe Stock.*", + secureLabel: "Secure transaction", + footerBlueButton1Text: 'Buy now', + footerBlueButton2Text: 'Buy now', + footerOutlineButtonText: 'Free trial', + }, + tags: '@merch-card @smoke @regression @milo', + }, + { + tcid: '7', + name: '@Merch-card (plans, secure) with badge', + path: '/drafts/nala/blocks/merch-card/merch-cards-plans-secure-with-badge', + data: { + titleH3: 'Creative Cloud All Apps', + titleH5: 'Desktop', + badgeText: 'Best value', + price: 'US$79.99/mo', + description: 'Get 20+ Creative Cloud apps including Photoshop, Illustrator, Adobe Express, Premiere Pro, and Acrobat Pro. (Substance 3D apps are not included.)', + link1Text: "See plan & pricing details", + checkboxLabel: "Add a 30-day free trial of Adobe Stock.*", + secureLabel: "Secure transaction", + footerBlueButton1Text: 'Buy now', + footerOutlineButtonText: 'Free trial', + }, + tags: '@merch-card @smoke @regression @milo', + }, + ], +}; diff --git a/libs/slack.js b/libs/slack.js new file mode 100644 index 00000000..08a7e8e5 --- /dev/null +++ b/libs/slack.js @@ -0,0 +1,27 @@ +import axios from 'axios'; + +/** + * Sends a message to Slack using a webhook URL. + * @param {string} webhookUrl - The Slack channel webhook. + * @param {Object} messageContent - The content of the message to send. + */ +async function sendSlackMessage(webhookUrl, messageContent) { + try { + const response = await axios.post(webhookUrl, messageContent, { + headers: { + 'Content-Type': 'application/json' + } + }); + + if (response.status !== 200) { + throw new Error(`Error sending message to Slack. Status: ${response.status}. Message: ${response.data}`); + } + console.log('---Result summary is sent to slack---'); + } catch (error) { + console.error('Axios error:', error); + } +} + +export { + sendSlackMessage, +}; diff --git a/selectors/milo/merchcard.block.page.js b/selectors/milo/merchcard.block.page.js new file mode 100644 index 00000000..68ea6360 --- /dev/null +++ b/selectors/milo/merchcard.block.page.js @@ -0,0 +1,81 @@ +export default class Merchcard { + constructor(page, nth = 0) { + this.page = page; + // modal locators + this.merchCard = this.page.locator('.merch-card').nth(nth); + this.segment = this.page.locator('.merch-card.segment').nth(nth); + this.sepcialOffers = this.page.locator('.merch-card.special-offers').nth(nth); + this.plans = this.page.locator('.merch-card.plans').nth(nth); + + // inline price and strikethrough price + this.inlinePrice1 = this.merchCard.locator('span.placeholder-resolved').nth(0); + this.inlinePrice2 = this.merchCard.locator('span.placeholder-resolved').nth(1); + this.price = this.inlinePrice1.locator('.price'); + this.priceCurrencySymbol = this.inlinePrice1.locator('.price-currency-symbol'); + this.priceInteger = this.inlinePrice1.locator('.price-integer'); + this.priceDecimalDelimiter = this.inlinePrice1.locator('.price-decimals-delimiter'); + this.priceDecimals = this.inlinePrice1.locator('.price-decimals'); + this.priceRecurrence = this.inlinePrice1.locator('.price-recurrence'); + + this.strikethroughPrice = this.inlinePrice2.locator('.price'); + this.strikethroughPriceCurrencySymbol = this.inlinePrice2.locator('.price-currency-symbol'); + this.strikethroughPriceInteger = this.inlinePrice2.locator('.price-integer'); + this.strikethroughPriceDecimalDelimiter = this.inlinePrice2.locator('.price-decimals-delimiter'); + this.strikethroughPriceDecimals = this.inlinePrice2.locator('.price-decimals'); + this.strikethroughPriceRecurrence = this.inlinePrice2.locator('.price-recurrence'); + + // merch-card segment locators + this.segmentRibbon = this.merchCard.locator('.consonant-SegmentBlade-ribbon'); + this.segmentTitle = this.segment.locator('.consonant-SegmentBlade-title').nth(0); + this.segmentDescription1 = this.segment.locator('.consonant-SegmentBlade-description').nth(0); + this.segmentDescription2 = this.segment.locator('.consonant-SegmentBlade-description').nth(1); + + this.linkText1 = this.segmentDescription2.locator('a').nth(0); + this.linkText2 = this.segmentDescription2.locator('a').nth(1); + + // merch-card special offers + this.sepcialOffersImage = this.sepcialOffers.locator('.consonant-SpecialOffers-img'); + this.sepcialOffersRibbon = this.merchCard.locator('.consonant-SpecialOffers-ribbon'); + this.sepcialOffersTitleH4 = this.sepcialOffers.locator('h4.consonant-SpecialOffers-title'); + this.sepcialOffersTitleH3 = this.sepcialOffers.locator('h3.consonant-SpecialOffers-title'); + + this.sepcialOffersDescription1 = this.sepcialOffers.locator('.consonant-SpecialOffers-description').nth(0); + this.sepcialOffersDescription2 = this.sepcialOffers.locator('.consonant-SpecialOffers-description').nth(1); + + this.sepcialOffersDescription3 = this.sepcialOffers.locator('.consonant-SpecialOffers-description').nth(2); + this.sepcialOffersLinkText3 = this.sepcialOffersDescription3.locator('a').nth(0); + + this.seeTermsTextLink = this.merchCard.locator('a:has-text("See terms")'); + + // merch-card plans locators + this.productIcon = this.plans.locator('.consonant-MerchCard-ProductIcon'); + this.plansRibbon = this.plans.locator('.consonant-PlansCard-ribbon'); + this.plansCardTitleH3 = this.plans.locator('h3.consonant-PlansCard-title'); + this.plansCardTitleH5 = this.plans.locator('h5.consonant-PlansCard-title'); + this.plansCardDescription2 = this.plans.locator('.consonant-PlansCard-description').nth(1); + this.seePlansTextLink = this.merchCard.locator('a:has-text("See plan & pricing details")'); + + // merch-card footer sections + this.footer = this.merchCard.locator('.consonant-CardFooter') + this.footerCheckbox = this.merchCard.locator('.checkbox-container .checkmark') + this.footerCheckboxLabel = this.merchCard.locator('.checkbox-container .checkbox-label') + this.secureTransactionIcon = this.merchCard.locator('.secure-transaction-icon') + this.secureTransactionLabel = this.merchCard.locator('.secure-transaction-label') + this.footerOutlineButton = this.merchCard.locator('a.con-button.outline'); + this.footerBlueButton = this.merchCard.locator('a.con-button.blue').nth(0); + this.footerBlueButton2 = this.merchCard.locator('a.con-button.blue').nth(1); + + // merch-card attributes + this.attributes = { + 'segmentRibbon': { + 'style': 'background-color: rgb(237, 204, 45); color: rgb(0, 0, 0);', + }, + 'specialOfferRibbon': { + 'style': 'background-color: rgb(246, 141, 46); color: rgb(0, 0, 0);', + }, + 'plansRibbon': { + 'style': 'background-color: rgb(246, 141, 46); color: rgb(0, 0, 0);', + }, + }; + } +} diff --git a/tests/milo/merchcard.block.test.js b/tests/milo/merchcard.block.test.js new file mode 100644 index 00000000..a78283de --- /dev/null +++ b/tests/milo/merchcard.block.test.js @@ -0,0 +1,303 @@ +import { expect, test } from '@playwright/test'; +import { WebUtil } from '../../libs/webutil.js'; +import { features } from '../../features/milo/merchcard.block.spec.js'; +import MerchCard from '../../selectors/milo/merchcard.block.page.js'; + +let merchCard; +let webUtil; + +test.describe('Milo Modal feature test suite', () => { + test.beforeEach(async ({ page }) => { + merchCard = new MerchCard(page); + webUtil = new WebUtil(page); + }); + + // Test 0 : Merch Card (Segment) + test(`${features[0].name},${features[0].tags}`, async ({ page, baseURL }) => { + console.info(`[Test Page]: ${baseURL}${features[0].path}`); + const data = features[0].data; + + await test.step('step-1: Go to Merch Card feature test page', async () => { + await page.goto(`${baseURL}${features[0].path}`); + await page.waitForLoadState('domcontentloaded'); + await expect(page).toHaveURL(`${baseURL}${features[0].path}`); + }); + + await test.step('step-2: Verify Merch Card content/specs', async () => { + await expect(await merchCard.segment).toBeVisible(); + await expect(await merchCard.segmentTitle).toContainText(data.title); + + await expect(await merchCard.price).toContainText(data.price); + await expect(await merchCard.strikethroughPrice).toContainText(data.strikethroughPrice); + + await expect(await merchCard.segmentDescription1).toContainText(data.description); + await expect(await merchCard.linkText1).toContainText(data.link1Text); + await expect(await merchCard.linkText2).toContainText(data.link2Text); + + await expect(await merchCard.footer).toBeVisible(); + await expect(await merchCard.footerOutlineButton).toBeVisible(); + await expect(await merchCard.footerOutlineButton).toContainText(data.footerOutlineButtonText); + + await expect(await merchCard.footerBlueButton).toBeVisible(); + await expect(await merchCard.footerBlueButton).toContainText(data.footerBlueButtonText); + + }); + }); + + // Test 1 : Merch Card (Segment) with Badge + test(`${features[1].name},${features[1].tags}`, async ({ page, baseURL }) => { + console.info(`[Test Page]: ${baseURL}${features[1].path}`); + const data = features[1].data; + + await test.step('step-1: Go to Merch Card feature test page', async () => { + await page.goto(`${baseURL}${features[1].path}`); + await page.waitForLoadState('domcontentloaded'); + await expect(page).toHaveURL(`${baseURL}${features[1].path}`); + }); + + await test.step('step-2: Verify Merch Card with Badge content/specs', async () => { + await expect(await merchCard.segment).toBeVisible(); + await expect(await merchCard.segmentTitle).toContainText(data.title); + + await expect(await merchCard.segmentRibbon).toBeVisible(); + await expect(await merchCard.segmentRibbon).toContainText(data.badgeText); + + await expect(await merchCard.price).toContainText(data.price); + await expect(await merchCard.strikethroughPrice).toContainText(data.strikethroughPrice); + + await expect(await merchCard.segmentDescription1).toContainText(data.description); + await expect(await merchCard.linkText1).toContainText(data.link1Text); + await expect(await merchCard.linkText2).toContainText(data.link2Text); + + await expect(await merchCard.footer).toBeVisible(); + await expect(await merchCard.footerOutlineButton).toBeVisible(); + await expect(await merchCard.footerOutlineButton).toContainText(data.footerOutlineButtonText); + + await expect(await merchCard.footerBlueButton).toBeVisible(); + await expect(await merchCard.footerBlueButton).toContainText(data.footerBlueButtonText); + }); + + await test.step('step-3: Verify Merch Card attributes', async () => { + await expect(await merchCard.segmentRibbon).toHaveAttribute('style', merchCard.attributes['segmentRibbon']['style']); + + }); + }); + + // Test 2 : Merch Card (Special Offers) + test(`${features[2].name},${features[2].tags}`, async ({ page, baseURL }) => { + console.info(`[Test Page]: ${baseURL}${features[2].path}`); + const data = features[2].data; + + await test.step('step-1: Go to Merch Card feature test page', async () => { + await page.goto(`${baseURL}${features[2].path}`); + await page.waitForLoadState('domcontentloaded'); + await expect(page).toHaveURL(`${baseURL}${features[2].path}`); + }); + + await test.step('step-2: Verify Merch Card special offers content/specs', async () => { + await expect(await merchCard.sepcialOffers).toBeVisible(); + await expect(await merchCard.sepcialOffersImage).toBeVisible(); + + await expect(await merchCard.sepcialOffersTitleH4).toContainText(data.titleH4); + await expect(await merchCard.sepcialOffersTitleH3).toContainText(data.titleH3); + + await expect(await merchCard.sepcialOffersDescription1).toContainText(data.description1); + await expect(await merchCard.sepcialOffersDescription2).toContainText(data.description2); + + await expect(await merchCard.footer).toBeVisible(); + await expect(await merchCard.footerBlueButton).toBeVisible(); + await expect(await merchCard.footerBlueButton).toContainText(data.footerBlueButtonText); + }); + }); + + // Test 3 : Merch Card (Special Offers) with badge + test(`${features[3].name},${features[3].tags}`, async ({ page, baseURL }) => { + console.info(`[Test Page]: ${baseURL}${features[3].path}`); + const data = features[3].data; + + await test.step('step-1: Go to Merch Card feature test page', async () => { + await page.goto(`${baseURL}${features[3].path}`); + await page.waitForLoadState('domcontentloaded'); + await expect(page).toHaveURL(`${baseURL}${features[3].path}`); + }); + + await test.step('step-2: Verify Merch Card special offers content/specs', async () => { + await expect(await merchCard.sepcialOffers).toBeVisible(); + await expect(await merchCard.sepcialOffersImage).toBeVisible(); + + await expect(await merchCard.sepcialOffersRibbon).toBeVisible(); + await expect(await merchCard.sepcialOffersRibbon).toContainText(data.badgeText); + + await expect(await merchCard.sepcialOffersTitleH4).toContainText(data.titleH4); + await expect(await merchCard.sepcialOffersTitleH3).toContainText(data.titleH3); + + await expect(await merchCard.sepcialOffersDescription2).toContainText(data.description); + await expect(await merchCard.seeTermsTextLink).toContainText(data.link1Text); + + await expect(await merchCard.footer).toBeVisible(); + await expect(await merchCard.footerOutlineButton).toBeVisible(); + await expect(await merchCard.footerOutlineButton).toContainText(data.footerOutlineButtonText); + + await expect(await merchCard.footerBlueButton).toBeVisible(); + await expect(await merchCard.footerBlueButton).toContainText(data.footerBlueButtonText); + }); + + await test.step('step-3: Verify Merch Card attributes', async () => { + await expect(await merchCard.sepcialOffersRibbon).toHaveAttribute('style', merchCard.attributes['specialOfferRibbon']['style']); + + }); + }); + + // Test 4 : Merch Card (plans) + test(`${features[4].name},${features[4].tags}`, async ({ page, baseURL }) => { + console.info(`[Test Page]: ${baseURL}${features[4].path}`); + const data = features[4].data; + + await test.step('step-1: Go to Merch Card feature test page', async () => { + await page.goto(`${baseURL}${features[4].path}`); + await page.waitForLoadState('domcontentloaded'); + await expect(page).toHaveURL(`${baseURL}${features[4].path}`); + }); + + await test.step('step-2: Verify Merch Card special offers content/specs', async () => { + await expect(await merchCard.plans).toBeVisible(); + await expect(await merchCard.productIcon).toBeVisible(); + + await expect(await merchCard.plansCardTitleH3).toContainText(data.titleH3); + await expect(await merchCard.plansCardTitleH5).toContainText(data.titleH5); + + await expect(await merchCard.price).toContainText(data.price); + await expect(await merchCard.plansCardDescription2).toContainText(data.description); + await expect(await merchCard.seePlansTextLink).toContainText(data.link1Text); + + await expect(await merchCard.footer).toBeVisible(); + + await expect(await merchCard.footerBlueButton).toBeVisible(); + await expect(await merchCard.footerBlueButton).toContainText(data.footerBlueButtonText); + }); + }); + + // Test 5 : Merch Card (plans) with badge + test(`${features[5].name},${features[5].tags}`, async ({ page, baseURL }) => { + console.info(`[Test Page]: ${baseURL}${features[5].path}`); + const data = features[5].data; + + await test.step('step-1: Go to Merch Card feature test page', async () => { + await page.goto(`${baseURL}${features[5].path}`); + await page.waitForLoadState('domcontentloaded'); + await expect(page).toHaveURL(`${baseURL}${features[5].path}`); + }); + + await test.step('step-2: Verify Merch Card special offers content/specs', async () => { + await expect(await merchCard.plans).toBeVisible(); + await expect(await merchCard.productIcon).toBeVisible(); + + await expect(await merchCard.plansRibbon).toBeVisible(); + await expect(await merchCard.plansRibbon).toContainText(data.badgeText); + + await expect(await merchCard.plansCardTitleH3).toContainText(data.titleH3); + await expect(await merchCard.plansCardTitleH5).toContainText(data.titleH5); + + await expect(await merchCard.price).toContainText(data.price); + await expect(await merchCard.plansCardDescription2).toContainText(data.description); + await expect(await merchCard.seePlansTextLink).toContainText(data.link1Text); + + await expect(await merchCard.footer).toBeVisible(); + + await expect(await merchCard.footerBlueButton).toBeVisible(); + await expect(await merchCard.footerBlueButton).toContainText(data.footerBlueButtonText); + }); + }); + + // Test 6 : Merch Card (plans) with secure + test(`${features[6].name},${features[6].tags}`, async ({ page, baseURL }) => { + console.info(`[Test Page]: ${baseURL}${features[6].path}`); + const data = features[6].data; + + await test.step('step-1: Go to Merch Card feature test page', async () => { + await page.goto(`${baseURL}${features[6].path}`); + await page.waitForLoadState('domcontentloaded'); + await expect(page).toHaveURL(`${baseURL}${features[6].path}`); + }); + + await test.step('step-2: Verify Merch Card special offers content/specs', async () => { + await expect(await merchCard.plans).toBeVisible(); + await expect(await merchCard.productIcon).toBeVisible(); + + await expect(await merchCard.plansCardTitleH3).toContainText(data.titleH3); + await expect(await merchCard.plansCardTitleH5).toContainText(data.titleH5); + + await expect(await merchCard.price).toContainText(data.price); + await expect(await merchCard.plansCardDescription2).toContainText(data.description); + await expect(await merchCard.seePlansTextLink).toContainText(data.link1Text); + + await expect(await merchCard.footer).toBeVisible(); + + await expect(await merchCard.footerBlueButton).toBeVisible(); + await expect(await merchCard.footerBlueButton).toContainText(data.footerBlueButton1Text); + + await expect(await merchCard.footerBlueButton2).toBeVisible(); + await expect(await merchCard.footerBlueButton).toContainText(data.footerBlueButton2Text); + + await expect(await merchCard.footerCheckbox).toBeVisible(); + await expect(await merchCard.footerCheckboxLabel).toContainText(data.checkboxLabel); + + await expect(await merchCard.secureTransactionIcon).toBeVisible(); + await expect(await merchCard.secureTransactionLabel).toContainText(data.secureLabel); + }); + + await test.step('step-3: Click the check box and verify the free trial button', async () => { + await merchCard.footerCheckbox.click(); + + await expect(await merchCard.footerOutlineButton).toBeVisible(); + await expect(await merchCard.footerOutlineButton).toContainText(data.footerOutlineButtonText); + }); + + }); + + // Test 6 : Merch Card (plans, secure) with badge + test(`${features[7].name},${features[7].tags}`, async ({ page, baseURL }) => { + console.info(`[Test Page]: ${baseURL}${features[7].path}`); + const data = features[7].data; + + await test.step('step-1: Go to Merch Card feature test page', async () => { + await page.goto(`${baseURL}${features[7].path}`); + await page.waitForLoadState('domcontentloaded'); + await expect(page).toHaveURL(`${baseURL}${features[7].path}`); + }); + + await test.step('step-2: Verify Merch Card special offers content/specs', async () => { + await expect(await merchCard.plans).toBeVisible(); + await expect(await merchCard.productIcon).toBeVisible(); + + await expect(await merchCard.plansRibbon).toBeVisible(); + await expect(await merchCard.plansRibbon).toContainText(data.badgeText); + + await expect(await merchCard.plansCardTitleH3).toContainText(data.titleH3); + await expect(await merchCard.plansCardTitleH5).toContainText(data.titleH5); + + await expect(await merchCard.price).toContainText(data.price); + await expect(await merchCard.plansCardDescription2).toContainText(data.description); + await expect(await merchCard.seePlansTextLink).toContainText(data.link1Text); + + await expect(await merchCard.footer).toBeVisible(); + + await expect(await merchCard.footerBlueButton).toBeVisible(); + await expect(await merchCard.footerBlueButton).toContainText(data.footerBlueButton1Text); + + await expect(await merchCard.footerCheckbox).toBeVisible(); + await expect(await merchCard.footerCheckboxLabel).toContainText(data.checkboxLabel); + + await expect(await merchCard.secureTransactionIcon).toBeVisible(); + await expect(await merchCard.secureTransactionLabel).toContainText(data.secureLabel); + }); + + await test.step('step-3: Click the check box and verify the free trial button', async () => { + await merchCard.footerCheckbox.click(); + + await expect(await merchCard.footerOutlineButton).toBeVisible(); + await expect(await merchCard.footerOutlineButton).toContainText(data.footerOutlineButtonText); + }); + + }); +}); diff --git a/utils/reporters/base-reporter.js b/utils/reporters/base-reporter.js index 703dbbdf..785994f8 100644 --- a/utils/reporters/base-reporter.js +++ b/utils/reporters/base-reporter.js @@ -1,3 +1,5 @@ +import { sendSlackMessage } from '../../libs/slack.js'; +const envs = require('../../envs/envs.js'); // Playwright will include ANSI color characters and regex from below // https://github.com/microsoft/playwright/issues/13522 // https://github.com/chalk/ansi-regex/blob/main/index.js#L3 @@ -75,8 +77,9 @@ class BaseReporter { async onEnd() { //this.printPersistingOption(); //await this.persistData(); - this.printResultSummary(); - + const summary = this.printResultSummary(); + const resultSummary = { summary }; + //await sendSlackMessage(envs['@webhook_url'], resultSummary); } printResultSummary() { @@ -94,13 +97,16 @@ class BaseReporter { exeEnv = 'Local Environment'; } - console.log('--------Test run summary------------'); - console.log('Total Test executed : ', totalTests); - console.log('# Test Pass : ', this.passedTests, `(${passPercentage}%)`); - console.log('# Test Fail : ', this.failedTests, `(${failPercentage}%)`); - console.log('# Test Skipped : ', this.skippedTests); - console.log('** Application URL : ', envURL); - console.log('** Executed on : ', exeEnv); + const summary = ` + --------Test run summary------------ + # Total Test executed: ${totalTests} + # Test Pass : ${this.passedTests} (${passPercentage}%) + # Test Fail : ${this.failedTests} (${failPercentage}%) + # Test Skipped : ${this.skippedTests} + ** Application URL : ${envURL} + ** Executed on : ${exeEnv}`; + + console.log(summary); if (this.failedTests > 0) { console.log('-------- Test Failures --------'); @@ -113,6 +119,7 @@ class BaseReporter { console.log('-------------------------'); }); } + return summary; } /** From 48aece8d80331d2d11e7d0c9c38952e948e0cf92 Mon Sep 17 00:00:00 2001 From: Santoshkumar Nateekar Date: Thu, 9 Nov 2023 11:50:18 -0800 Subject: [PATCH 10/53] [MWPW-139022] : Card block tests scripts (#202) card-block-scripts Co-authored-by: nateekar --- features/milo/card.block.spec.js | 85 +++++++++++++ selectors/milo/card.block.page.js | 60 +++++++++ tests/milo/card.block.test.js | 198 ++++++++++++++++++++++++++++++ 3 files changed, 343 insertions(+) create mode 100644 features/milo/card.block.spec.js create mode 100644 selectors/milo/card.block.page.js create mode 100644 tests/milo/card.block.test.js diff --git a/features/milo/card.block.spec.js b/features/milo/card.block.spec.js new file mode 100644 index 00000000..5ac989f5 --- /dev/null +++ b/features/milo/card.block.spec.js @@ -0,0 +1,85 @@ +module.exports = { + FeatureName: 'Consonant Card Block', + features: [ + { + tcid: '0', + name: '@Card', + path: '/drafts/nala/blocks/card/card', + data: { + titleH3: 'Lorem ipsum dolor sit amet', + text: 'Maecenas porttitor congue massa. Fusce posuere, magna sed pulvinar ultricies, purus lectus malesuada libero, sit amet commodo magna eros quis', + footerOutlineButtonText: 'Sign up', + footerBlueButtonText: 'Learn more', + }, + tags: '@card @smoke @regression @milo', + }, + { + tcid: '1', + name: '@Card (half-card, border)', + path: '/drafts/nala/blocks/card/half-card-border', + data: { + titleH3: 'Lorem ipsum dolor sit amet', + text: 'Maecenas porttitor congue massa. Fusce posuere, magna sed pulvinar ultricies, purus lectus malesuada libero, sit amet commodo magna eros quis', + footerOutlineButtonText: 'Sign up', + footerBlueButtonText: 'Learn more', + }, + tags: '@card @smoke @regression @milo', + }, + { + tcid: '2', + name: '@Card (double-width-card, border)', + path: '/drafts/nala/blocks/card/double-width-card-border', + data: { + titleH3: 'Lorem ipsum dolor sit amet', + text: 'Maecenas porttitor congue massa. Fusce posuere, magna sed pulvinar ultricies, purus lectus malesuada libero, sit amet commodo magna eros quis', + }, + tags: '@card @smoke @regression @milo', + }, + { + tcid: '3', + name: '@Card (product-card, border) ', + path: '/drafts/nala/blocks/card/product-card-border', + data: { + titleH3: 'Lorem ipsum dolor sit amet', + text: 'Maecenas porttitor congue massa. Fusce posuere, magna sed pulvinar ultricies, purus lectus malesuada libero, sit amet commodo magna eros quis', + footerOutlineButtonText: 'Learn more', + footerBlueButtonText: 'Sign up', + }, + tags: '@card @smoke @regression @milo', + }, + { + tcid: '4', + name: '@Card (half-height-card, border)', + path: '/drafts/nala/blocks/card/half-height-card-border', + data: { + titleH3: 'Lorem ipsum dolor sit amet', + }, + tags: '@card @smoke @regression @milo', + }, + { + tcid: '5', + name: '@Card-horizontal', + path: '/drafts/nala/blocks/card/card-horizontal', + data: { + bodyXS: 'Body XS Regular', + headingXS: 'Heading XS Bold Lorem ipsum dolo sit amet, consectetur adipis cing elit.', + imgWidth: '180', + imgHeight: '132', + }, + tags: '@card @smoke @regression @milo', + }, + { + tcid: '6', + name: '@Card-horizontal (tile)', + path: '/drafts/nala/blocks/card/card-horizontal-tile', + data: { + bodyXS: 'Body XS Regular', + headingXS: 'Heading XS Bold Lorem ipsum dolo sit amet, consectetur adipis cing elit.', + imgWidth: '80', + imgHeight: '78', + }, + tags: '@card @smoke @regression @milo', + }, + ], +}; + diff --git a/selectors/milo/card.block.page.js b/selectors/milo/card.block.page.js new file mode 100644 index 00000000..238ceafc --- /dev/null +++ b/selectors/milo/card.block.page.js @@ -0,0 +1,60 @@ +export default class Card { + constructor(page, nth = 0) { + this.page = page; + // card locators + this.card = this.page.locator('.card').nth(nth); + + // One half card locators + this.oneHalfCard = this.page.locator('.consonant-OneHalfCard').nth(nth); + this.oneHalfCardImage = this.oneHalfCard.locator('.consonant-OneHalfCard-img'); + this.oneHalfCardInner = this.oneHalfCard.locator('.consonant-OneHalfCard-inner'); + this.oneHalfCardTitleH3 = this.oneHalfCard.locator('h3.consonant-OneHalfCard-title'); + this.oneHalfCardText = this.oneHalfCard.locator('.consonant-OneHalfCard-text'); + // Double width card locators + this.doubleWidthCard = this.page.locator('.double-width-card').nth(nth); + this.doubleWidthCardImage = this.doubleWidthCard.locator('.consonant-DoubleWideCard-img'); + this.doubleWidthCardInner = this.doubleWidthCard.locator('.consonant-DoubleWideCard-inner'); + this.doubleWidthCardTitleH3 = this.doubleWidthCard.locator('h3.consonant-DoubleWideCard-title'); + this.doubleWidthCardText = this.doubleWidthCard.locator('.consonant-DoubleWideCard-text'); + // Product card locators + this.productCard = this.page.locator('.product-card').nth(nth); + this.productCardImage = this.productCard.locator('.consonant-ProductCard-img'); + this.productCardInner = this.productCard.locator('.consonant-ProductCard-inner'); + this.productCardTitleH3 = this.productCard.locator('h3.consonant-ProductCard-title'); + this.productCardText = this.productCard.locator('.consonant-ProductCard-text'); + // Half height card locators + this.halfHeightCard = this.page.locator('.half-height-card').nth(nth); + this.halfHeightCardImage = this.halfHeightCard.locator('.consonant-HalfHeightCard-img'); + this.halfHeightCardLink = this.halfHeightCard.locator('a.consonant-HalfHeightCard'); + this.halfHeightCardInner = this.halfHeightCard.locator('.consonant-HalfHeightCard-inner'); + this.halfHeightCardTitleH3 = this.halfHeightCard.locator('h3.consonant-HalfHeightCard-title'); + this.halfHeightCardText = this.halfHeightCard.locator('.consonant-HalfHeightCard-text'); + // Horizontal card locators + this.horizontalCard = this.page.locator('.card-horizontal').nth(nth); + this.horizontalCardImage = this.horizontalCard.locator('.card-image'); + this.horizontalCardImg = this.horizontalCard.locator('img'); + this.horizontalCardContent = this.horizontalCard.locator('card-content'); + this.horizontalCardBodyXS = this.horizontalCard.locator('.body-xs'); + this.horizontalCardHeadingXS = this.horizontalCard.locator('h2.heading-xs'); + this.horizontalCardHeadingXSLink = this.horizontalCardHeadingXS.locator('a'); + + // card footer sections + this.footer = this.card.locator('.consonant-CardFooter') + this.footerOutlineButton = this.card.locator('a.con-button.outline').nth(0); + this.footerOutlineButton2 = this.card.locator('a.con-button.outline').nth(1); + this.footerBlueButton = this.card.locator('a.con-button.blue').nth(0); + this.footerBlueButton2 = this.card.locator('a.con-button.blue').nth(1); + + // card attributes + this.attributes = { + 'oneHalfCardImage': { + 'style': 'background-image: url', + }, + 'card-image': { + 'loading': 'eager', + 'fetchpriority': 'hight', + }, + }; + } +} + diff --git a/tests/milo/card.block.test.js b/tests/milo/card.block.test.js new file mode 100644 index 00000000..87ed4e1a --- /dev/null +++ b/tests/milo/card.block.test.js @@ -0,0 +1,198 @@ +import { expect, test } from '@playwright/test'; +import { WebUtil } from '../../libs/webutil.js'; +import { features } from '../../features/milo/card.block.spec.js'; +import ConsonantCard from '../../selectors/milo/card.block.page.js'; + +let card; +let webUtil; + +test.describe('Milo Consonant card feature test suite', () => { + test.beforeEach(async ({ page }) => { + card = new ConsonantCard(page); + webUtil = new WebUtil(page); + }); + + // Test 0 : Card + test(`${features[0].name},${features[0].tags}`, async ({ page, baseURL }) => { + console.info(`[Test Page]: ${baseURL}${features[0].path}`); + const data = features[0].data; + + await test.step('step-1: Go to Consonant Card feature test page', async () => { + await page.goto(`${baseURL}${features[0].path}`); + await page.waitForLoadState('domcontentloaded'); + await expect(page).toHaveURL(`${baseURL}${features[0].path}`); + }); + + await test.step('step-2: Verify Card content/specs', async () => { + await expect(await card.oneHalfCard).toBeVisible(); + await expect(await card.oneHalfCardImage).toBeVisible(); + + await expect(await card.oneHalfCardTitleH3).toContainText(data.titleH3); + await expect(await card.oneHalfCardText).toContainText(data.text); + + await expect(await card.footer).toBeVisible(); + await expect(await card.footerOutlineButton).toBeVisible(); + await expect(await card.footerOutlineButton).toContainText(data.footerOutlineButtonText); + + await expect(await card.footerBlueButton).toBeVisible(); + await expect(await card.footerBlueButton).toContainText(data.footerBlueButtonText); + + }); + }); + + // Test 1 : Card (half-card, border) + test(`${features[1].name},${features[1].tags}`, async ({ page, baseURL }) => { + console.info(`[Test Page]: ${baseURL}${features[1].path}`); + const data = features[1].data; + + await test.step('step-1: Go to Consonant Card feature test page', async () => { + await page.goto(`${baseURL}${features[1].path}`); + await page.waitForLoadState('domcontentloaded'); + await expect(page).toHaveURL(`${baseURL}${features[1].path}`); + }); + + await test.step('step-2: Verify Half Card with Boarder content/specs', async () => { + await expect(await card.oneHalfCard).toBeVisible(); + + expect(await card.oneHalfCard.getAttribute('class')).toContain('border') + + await expect(await card.oneHalfCardImage).toBeVisible(); + await expect(await card.oneHalfCardTitleH3).toContainText(data.titleH3); + await expect(await card.oneHalfCardText).toContainText(data.text); + + await expect(await card.footer).toBeVisible(); + await expect(await card.footerOutlineButton).toBeVisible(); + await expect(await card.footerOutlineButton).toContainText(data.footerOutlineButtonText); + + await expect(await card.footerBlueButton).toBeVisible(); + await expect(await card.footerBlueButton).toContainText(data.footerBlueButtonText); + + }); + }); + + // Test 2 : card (double-width-card, border) + test(`${features[2].name},${features[2].tags}`, async ({ page, baseURL }) => { + console.info(`[Test Page]: ${baseURL}${features[2].path}`); + const data = features[2].data; + + await test.step('step-2: Go to Consonant Card feature test page', async () => { + await page.goto(`${baseURL}${features[2].path}`); + await page.waitForLoadState('domcontentloaded'); + await expect(page).toHaveURL(`${baseURL}${features[2].path}`); + }); + + await test.step('step-2: Verify card (double-width-card, border) content/specs', async () => { + await expect(await card.doubleWidthCard).toBeVisible(); + + expect(await card.doubleWidthCard.getAttribute('class')).toContain('border') + + await expect(await card.doubleWidthCardImage).toBeVisible(); + await expect(await card.doubleWidthCardTitleH3).toContainText(data.titleH3); + await expect(await card.doubleWidthCardText).toContainText(data.text); + + }); + }); + + // Test 3 : Card (product-card, border) + test(`${features[3].name},${features[3].tags}`, async ({ page, baseURL }) => { + console.info(`[Test Page]: ${baseURL}${features[3].path}`); + const data = features[3].data; + + await test.step('step-2: Go to Consonant Card feature test page', async () => { + await page.goto(`${baseURL}${features[3].path}`); + await page.waitForLoadState('domcontentloaded'); + await expect(page).toHaveURL(`${baseURL}${features[3].path}`); + }); + + await test.step('step-2: Verify Card (product-card, border) content/specs', async () => { + await expect(await card.productCard).toBeVisible(); + + expect(await card.productCard.getAttribute('class')).toContain('border') + + await expect(await card.productCardTitleH3).toContainText(data.titleH3); + await expect(await card.productCardText).toContainText(data.text); + + await expect(await card.footer).toBeVisible(); + await expect(await card.footerOutlineButton).toBeVisible(); + await expect(await card.footerOutlineButton).toContainText(data.footerOutlineButtonText); + + await expect(await card.footerBlueButton).toBeVisible(); + await expect(await card.footerBlueButton).toContainText(data.footerBlueButtonText); + + }); + }); + + // Test 4 : Card (half-height-card, border) + test(`${features[4].name},${features[4].tags}`, async ({ page, baseURL }) => { + console.info(`[Test Page]: ${baseURL}${features[4].path}`); + const data = features[4].data; + + await test.step('step-2: Go to Consonant Card feature test page', async () => { + await page.goto(`${baseURL}${features[4].path}`); + await page.waitForLoadState('domcontentloaded'); + await expect(page).toHaveURL(`${baseURL}${features[4].path}`); + }); + + await test.step('step-2: Verify Card (half-height-card, border) content/specs', async () => { + await expect(await card.halfHeightCard).toBeVisible(); + + expect(await card.halfHeightCard.getAttribute('class')).toContain('border') + + await expect(await card.halfHeightCardImage).toBeVisible(); + await expect(await card.halfHeightCardLink).toBeVisible(); + + await expect(await card.halfHeightCardTitleH3).toContainText(data.titleH3); + }); + }); + + // Test 5 : Card-horizontal + test(`${features[5].name},${features[5].tags}`, async ({ page, baseURL }) => { + console.info(`[Test Page]: ${baseURL}${features[5].path}`); + const data = features[5].data; + + await test.step('step-2: Go to Consonant Card feature test page', async () => { + await page.goto(`${baseURL}${features[5].path}`); + await page.waitForLoadState('domcontentloaded'); + await expect(page).toHaveURL(`${baseURL}${features[5].path}`); + }); + + await test.step('step-2: Verify Card-horizontal content/specs', async () => { + await expect(await card.horizontalCard).toBeVisible(); + await expect(await card.horizontalCardImage).toBeVisible(); + + expect(await card.horizontalCardImg.getAttribute('width')).toContain(data.imgWidth); + expect(await card.horizontalCardImg.getAttribute('height')).toContain(data.imgHeight); + + await expect(await card.horizontalCardBodyXS).toContainText(data.bodyXS); + await expect(await card.horizontalCardHeadingXS).toContainText(data.headingXS); + await expect(await card.horizontalCardHeadingXSLink).toContainText(data.headingXS); + }); + }); + + // Test 6 : Card-horizontal (tile) + test(`${features[6].name},${features[6].tags}`, async ({ page, baseURL }) => { + console.info(`[Test Page]: ${baseURL}${features[6].path}`); + const data = features[6].data; + + await test.step('step-2: Go to Consonant Card feature test page', async () => { + await page.goto(`${baseURL}${features[6].path}`); + await page.waitForLoadState('domcontentloaded'); + await expect(page).toHaveURL(`${baseURL}${features[6].path}`); + }); + + await test.step('step-2: Verify Card-horizontal (tile) content/specs', async () => { + await expect(await card.horizontalCard).toBeVisible(); + expect(await card.horizontalCard.getAttribute('class')).toContain('tile') + + await expect(await card.horizontalCardImage).toBeVisible(); + + expect(await card.horizontalCardImg.getAttribute('width')).toContain(data.imgWidth); + expect(await card.horizontalCardImg.getAttribute('height')).toContain(data.imgHeight); + + await expect(await card.horizontalCardBodyXS).toContainText(data.bodyXS); + await expect(await card.horizontalCardHeadingXS).toContainText(data.headingXS); + await expect(await card.horizontalCardHeadingXSLink).toContainText(data.headingXS); + }); + }); +}); + From 3150823f5f1bb331dcf0646265b57d5f9fd81243 Mon Sep 17 00:00:00 2001 From: Santoshkumar Nateekar Date: Sat, 11 Nov 2023 12:13:09 -0800 Subject: [PATCH 11/53] [MWPW-139085] : Chart block tests scripts (#203) chart test scripts Co-authored-by: nateekar --- features/milo/chart.block.spec.js | 93 ++++++++++++++ selectors/milo/chart.block.page.js | 55 ++++++++ tests/milo/chart.block.test.js | 200 +++++++++++++++++++++++++++++ 3 files changed, 348 insertions(+) create mode 100644 features/milo/chart.block.spec.js create mode 100644 selectors/milo/chart.block.page.js create mode 100644 tests/milo/chart.block.test.js diff --git a/features/milo/chart.block.spec.js b/features/milo/chart.block.spec.js new file mode 100644 index 00000000..85734280 --- /dev/null +++ b/features/milo/chart.block.spec.js @@ -0,0 +1,93 @@ +module.exports = { + FeatureName: 'Chart Block', + features: [ + { + tcid: '0', + name: '@Chart (area, green, border)', + path: '/drafts/nala/blocks/chart/chart-area-green-border', + data: { + chartType: 'area green border', + titleH3: 'Lorem ipsum dolor sit amet, consectetuer adipiscing elit.', + subTitle: 'Revenue dollars: 2020 vs 2021 forecasted vs 2021 actuals.', + footNote: 'Footnote lorem ipsum dolor sit amet, consectetuer adipiscing elit.', + }, + tags: '@chart @smoke @regression @milo', + }, + { + tcid: '1', + name: '@Chart (bar, border)', + path: '/drafts/nala/blocks/chart/chart-bar-border', + data: { + chartType: 'bar border large', + titleH3: 'Lorem ipsum dolor sit amet, consectetuer adipiscing elit.', + subTitle: 'Revenue dollars: 2020 vs 2021 forecasted vs 2021 actuals.', + footNote: 'Footnote lorem ipsum dolor sit amet, consectetuer adipiscing elit.', + }, + tags: '@chart @smoke @regression @milo', + }, + { + tcid: '2', + name: '@Chart (column, border)', + path: '/drafts/nala/blocks/chart/chart-column-border', + data: { + chartType: 'column border large', + titleH3: 'Lorem ipsum dolor sit amet, consectetuer adipiscing elit.', + subTitle: 'Revenue dollars: 2020 vs 2021 forecasted vs 2021 actuals.', + footNote: 'Footnote lorem ipsum dolor sit amet, consectetuer adipiscing elit.', + }, + tags: '@chart @smoke @regression @milo', + }, + { + tcid: '3', + name: '@Chart (donut, border)', + path: '/drafts/nala/blocks/chart/chart-donut-border', + data: { + chartType: 'donut border large', + titleH3: 'Lorem ipsum dolor sit amet, consectetuer adipiscing elit.', + subTitle: 'Revenue dollars: 2020 vs 2021 forecasted vs 2021 actuals.', + footNote: 'Footnote lorem ipsum dolor sit amet, consectetuer adipiscing elit.', + }, + tags: '@chart @smoke @regression @milo', + }, + { + tcid: '4', + name: '@Chart (line, border)', + path: '/drafts/nala/blocks/chart/chart-line-border', + data: { + chartType: 'line border large', + titleH3: 'Lorem ipsum dolor sit amet, consectetuer adipiscing elit.', + subTitle: 'Revenue dollars: 2020 vs 2021 forecasted vs 2021 actuals.', + footNote: 'Footnote lorem ipsum dolor sit amet, consectetuer adipiscing elit.', + }, + tags: '@chart @smoke @regression @milo', + }, + { + tcid: '5', + name: '@Chart (oversized-number, border)', + path: '/drafts/nala/blocks/chart/chart-oversized-number-border', + data: { + chartType: 'oversized-number border large', + titleH3: 'Lorem ipsum dolor sit amet, consectetuer adipiscing elit.', + subTitle: 'Revenue dollars: 2020 vs 2021 forecasted vs 2021 actuals.', + circleNumber: '25', + circleSubTitle: 'Out of 60 days', + footNote: 'Footnote lorem ipsum dolor sit amet, consectetuer adipiscing elit.', + }, + tags: '@chart @smoke @regression @milo', + }, + { + tcid: '6', + name: '@Chart (pie, border)', + path: '/drafts/nala/blocks/chart/chart-pie-border', + data: { + chartType: 'pie border large', + titleH3: 'Lorem ipsum dolor sit amet, consectetuer adipiscing elit.', + subTitle: 'Revenue dollars: 2020 vs 2021 forecasted vs 2021 actuals.', + footNote: 'Footnote lorem ipsum dolor sit amet, consectetuer adipiscing elit.', + }, + tags: '@chart @smoke @regression @milo', + }, + ], +}; + + diff --git a/selectors/milo/chart.block.page.js b/selectors/milo/chart.block.page.js new file mode 100644 index 00000000..f5df8450 --- /dev/null +++ b/selectors/milo/chart.block.page.js @@ -0,0 +1,55 @@ +export default class Chart { + constructor(page, nth = 0) { + this.page = page; + // chart locators + this.chart = this.page.locator('.chart').nth(nth); + this.type = this.page.locator('.chart').nth(nth); + + this.title = this.chart.locator('.title'); + this.subTitle= this.chart.locator('.subtitle').nth(0); + this.container = this.chart.locator('.chart-container'); + this.svgImg = this.container.locator('svg'); + this.svgImgCircle = this.container.locator('circle'); + this.svgImgCircleNumber = this.container.locator('text.number') + this.svgImgCircleSubTitle = this.container.locator('text.subtitle') + + this.legendChrome = page.locator('text[dominant-baseline="central"]').filter({ hasText: 'Chrome' }); + this.legendFirefox = page.locator('text[dominant-baseline="central"]').filter({ hasText: 'Firefox' }); + this.legendEdge = page.locator('text[dominant-baseline="central"]').filter({ hasText: 'Edge' }); + this.legendSafari = page.locator('text[dominant-baseline="central"]').filter({ hasText: 'Safari' }); + this.legendOpera = page.locator('text[dominant-baseline="central"]').filter({ hasText: 'Opera' }); + this.legendChromeAndroid = page.locator('text[dominant-baseline="central"]').filter({ hasText: 'Chrome Android' }); + this.legendFirefoxAndroid= page.locator('text[dominant-baseline="central"]').filter({ hasText: 'Firefox Android' }); + this.legendSafariIos = page.locator('text[dominant-baseline="central"]').filter({ hasText: 'Safari iOS' }); + this.legendOperaAndroid = page.locator('text[dominant-baseline="central"]').filter({ hasText: 'Opera Android' }); + this.legendSamsungInternet = page.locator('text[dominant-baseline="central"]').filter({ hasText: 'Samsung Internet' }); + this.legendAdobeAcrobat = page.locator('text[dominant-baseline="central"][fill="#333"]').filter({ hasText: 'Adobe Acrobat' }); + this.legendAdobeExperienceManager = page.locator('text[dominant-baseline="central"][fill="#333"]').filter({ hasText: 'Adobe Experience Manager' }); + + this.x_axisMonday = page.locator('text[dominant-baseline="central"]').filter({ hasText: 'Monday' }); + this.x_axisTuesday = page.locator('text[dominant-baseline="central"]').filter({ hasText: 'Tuesday' }); + this.x_axisSunday = page.locator('text[dominant-baseline="central"]').filter({ hasText: 'Sunday' }); + this.y_axis50K = page.locator('text[dominant-baseline="central"]').filter({ hasText: '50K', exact: true }); + this.y_axis100K = page.locator('text[dominant-baseline="central"]').filter({ hasText: '100K', exact: true }); + this.y_axis250K = page.locator('text[dominant-baseline="central"]').filter({ hasText: '250K', exact: true }); + this.y_axis300K = page.locator('text[dominant-baseline="central"]').filter({ hasText: '300K', exact: true }); + + this.donutTitle = page.locator('text[dominant-baseline="central"]').filter({ hasText: 'Hello World', exact: true }); + + this.pieChartLabelAdobeSign = page.locator('text[dominant-baseline="central"][text-anchor="end"]').filter({ hasText: 'Adobe Sign' }); + this.pieChartLabelAdobePhotoshop = page.locator('text[dominant-baseline="central"][text-anchor="end"]').filter({ hasText: 'Adobe Photoshop' }); + this.pieChartLabelAdobePremier = page.locator('text[dominant-baseline="central"][text-anchor="end"]').filter({ hasText: 'Adobe Premier' }); + + // chart footer + this.footNote = this.chart.locator('.footnote') + + // chart attributes + this.attributes = { + 'svgViewBox': { + viewBox: '0 0 430 430', + }, + }; + } +} + + diff --git a/tests/milo/chart.block.test.js b/tests/milo/chart.block.test.js new file mode 100644 index 00000000..3c108ca2 --- /dev/null +++ b/tests/milo/chart.block.test.js @@ -0,0 +1,200 @@ +import { expect, test } from '@playwright/test'; +import { features } from '../../features/milo/chart.block.spec.js'; +import ChartBlock from '../../selectors/milo/chart.block.page.js'; + +let chart; + +test.describe('Milo Chart feature test suite', () => { + test.beforeEach(async ({ page }) => { + chart = new ChartBlock(page); + }); + + // Test 0 : Chart (area, green, border) + test(`${features[0].name},${features[0].tags}`, async ({ page, baseURL }) => { + console.info(`[Test Page]: ${baseURL}${features[0].path}`); + const data = features[0].data; + + await test.step('step-1: Go to Chart feature test page', async () => { + await page.goto(`${baseURL}${features[0].path}`); + await page.waitForLoadState('domcontentloaded'); + await expect(page).toHaveURL(`${baseURL}${features[0].path}`); + }); + + await test.step('step-2: Verify chart content/specs', async () => { + await expect(await chart.chart).toBeVisible(); + await expect(await chart.title).toContainText(data.titleH3); + await expect(await chart.subTitle).toContainText(data.subTitle); + expect(await chart.type.getAttribute('class')).toContain(data.chartType); + await expect(await chart.footNote).toContainText(data.footNote); + + }); + }); + + // Test 1 : Chart (bar, border) + test(`${features[1].name},${features[1].tags}`, async ({ page, baseURL }) => { + console.info(`[Test Page]: ${baseURL}${features[1].path}`); + const data = features[1].data; + + await test.step('step-1: Go to Chart feature test page', async () => { + await page.goto(`${baseURL}${features[1].path}`); + await page.waitForLoadState('domcontentloaded'); + await expect(page).toHaveURL(`${baseURL}${features[1].path}`); + }); + + await test.step('step-2: Verify chart content/specs', async () => { + await expect(await chart.chart).toBeVisible(); + await expect(await chart.title).toContainText(data.titleH3); + await expect(await chart.subTitle).toContainText(data.subTitle); + expect(await chart.type.getAttribute('class')).toContain(data.chartType); + await expect(await chart.legendChrome).toBeVisible(); + await expect(await chart.legendFirefox).toBeVisible(); + await expect(await chart.legendEdge).toBeVisible(); + + await expect(await chart.footNote).toContainText(data.footNote); + }); + }); + + // Test 2 : Chart (column, border) + test(`${features[2].name},${features[2].tags}`, async ({ page, baseURL }) => { + console.info(`[Test Page]: ${baseURL}${features[2].path}`); + const data = features[2].data; + + await test.step('step-1: Go to Chart feature test page', async () => { + await page.goto(`${baseURL}${features[2].path}`); + await page.waitForLoadState('domcontentloaded'); + await expect(page).toHaveURL(`${baseURL}${features[2].path}`); + }); + + await test.step('step-2: Verify chart content/specs', async () => { + await expect(await chart.chart).toBeVisible(); + await expect(await chart.title).toContainText(data.titleH3); + await expect(await chart.subTitle).toContainText(data.subTitle); + expect(await chart.type.getAttribute('class')).toContain(data.chartType); + + await expect(await chart.x_axisMonday).toBeVisible(); + await expect(await chart.x_axisTuesday).toBeVisible(); + await expect(await chart.x_axisSunday).toBeVisible(); + + await expect(await chart.y_axis100K).toBeVisible(); + await expect(await chart.y_axis250K).toBeVisible(); + await expect(await chart.y_axis300K).toBeVisible(); + + await expect(await chart.legendChrome).toBeVisible(); + await expect(await chart.legendFirefox).toBeVisible(); + await expect(await chart.legendSafari).toBeVisible(); + + await expect(await chart.footNote).toContainText(data.footNote); + }); + }); + + // Test 3 : Chart (donut, border) + test(`${features[3].name},${features[3].tags}`, async ({ page, baseURL }) => { + console.info(`[Test Page]: ${baseURL}${features[3].path}`); + const data = features[3].data; + + await test.step('step-1: Go to Chart feature test page', async () => { + await page.goto(`${baseURL}${features[3].path}`); + await page.waitForLoadState('domcontentloaded'); + await expect(page).toHaveURL(`${baseURL}${features[3].path}`); + }); + + await test.step('step-2: Verify chart content/specs', async () => { + await expect(await chart.chart).toBeVisible(); + await expect(await chart.title).toContainText(data.titleH3); + await expect(await chart.subTitle).toContainText(data.subTitle); + expect(await chart.type.getAttribute('class')).toContain(data.chartType); + + await expect(await chart.donutTitle).toBeVisible(); + await expect(await chart.x_axisMonday).toBeVisible(); + await expect(await chart.x_axisTuesday).toBeVisible(); + await expect(await chart.x_axisSunday).toBeVisible(); + + await expect(await chart.footNote).toContainText(data.footNote); + }); + }); + + // Test 4 : Chart (line, border) + test(`${features[4].name},${features[4].tags}`, async ({ page, baseURL }) => { + console.info(`[Test Page]: ${baseURL}${features[4].path}`); + const data = features[4].data; + + await test.step('step-1: Go to Chart feature test page', async () => { + await page.goto(`${baseURL}${features[4].path}`); + await page.waitForLoadState('domcontentloaded'); + await expect(page).toHaveURL(`${baseURL}${features[4].path}`); + }); + + await test.step('step-2: Verify chart content/specs', async () => { + await expect(await chart.chart).toBeVisible(); + await expect(await chart.title).toContainText(data.titleH3); + await expect(await chart.subTitle).toContainText(data.subTitle); + expect(await chart.type.getAttribute('class')).toContain(data.chartType); + + await expect(await chart.x_axisMonday).toBeVisible(); + await expect(await chart.x_axisTuesday).toBeVisible(); + await expect(await chart.x_axisSunday).toBeVisible(); + + await expect(await chart.legendChromeAndroid).toBeVisible(); + await expect(await chart.legendFirefoxAndroid).toBeVisible(); + await expect(await chart.legendSafariIos).toBeVisible(); + + await expect(await chart.footNote).toContainText(data.footNote); + }); + }); + + // Test 5 : Chart (oversized-number, border) + test(`${features[5].name},${features[5].tags}`, async ({ page, baseURL }) => { + console.info(`[Test Page]: ${baseURL}${features[5].path}`); + const data = features[5].data; + + await test.step('step-1: Go to Chart feature test page', async () => { + await page.goto(`${baseURL}${features[5].path}`); + await page.waitForLoadState('domcontentloaded'); + await expect(page).toHaveURL(`${baseURL}${features[5].path}`); + }); + + await test.step('step-2: Verify chart content/specs', async () => { + await expect(await chart.chart).toBeVisible(); + await expect(await chart.title).toContainText(data.titleH3); + await expect(await chart.subTitle).toContainText(data.subTitle); + + expect(await chart.type.getAttribute('class')).toContain(data.chartType); + expect(await chart.svgImg.getAttribute('viewBox')).toContain(chart.attributes['svgViewBox']['viewBox']); + + await expect(await chart.svgImgCircleNumber).toContainText(data.circleNumber); + await expect(await chart.svgImgCircleSubTitle).toContainText(data.circleSubTitle); + + await expect(await chart.footNote).toContainText(data.footNote); + }); + }); + + // Test 6 : Chart (pie, border) + test(`${features[6].name},${features[6].tags}`, async ({ page, baseURL }) => { + console.info(`[Test Page]: ${baseURL}${features[6].path}`); + const data = features[6].data; + + await test.step('step-1: Go to Chart feature test page', async () => { + await page.goto(`${baseURL}${features[6].path}`); + await page.waitForLoadState('domcontentloaded'); + await expect(page).toHaveURL(`${baseURL}${features[6].path}`); + }); + + await test.step('step-2: Verify chart content/specs', async () => { + await expect(await chart.chart).toBeVisible(); + await expect(await chart.title).toContainText(data.titleH3); + await expect(await chart.subTitle).toContainText(data.subTitle); + + await expect(await chart.pieChartLabelAdobeSign).toBeVisible(); + await expect(await chart.pieChartLabelAdobePhotoshop).toBeVisible(); + await expect(await chart.pieChartLabelAdobePremier).toBeVisible(); + + await expect(await chart.legendAdobeAcrobat).toBeVisible(); + await expect(await chart.legendAdobeExperienceManager).toBeVisible(); + + await expect(await chart.footNote).toContainText(data.footNote); + }); + }); + +}); + + From b7e31e5a68b8353a8c5c569da214fa60ba38e29f Mon Sep 17 00:00:00 2001 From: Santoshkumar Nateekar Date: Mon, 13 Nov 2023 13:30:28 -0800 Subject: [PATCH 12/53] [MWPW-139139] : Tabs block tests scripts (#205) * tabs-block-scripts * disable price validation from merch cards --------- Co-authored-by: nateekar --- features/milo/tabs.block.spec.js | 33 +++++++++++++ selectors/milo/tabs.block.page.js | 23 +++++++++ tests/milo/merchcard.block.test.js | 16 +++--- tests/milo/tab.block.test.js | 79 ++++++++++++++++++++++++++++++ 4 files changed, 143 insertions(+), 8 deletions(-) create mode 100644 features/milo/tabs.block.spec.js create mode 100644 selectors/milo/tabs.block.page.js create mode 100644 tests/milo/tab.block.test.js diff --git a/features/milo/tabs.block.spec.js b/features/milo/tabs.block.spec.js new file mode 100644 index 00000000..ad521fa4 --- /dev/null +++ b/features/milo/tabs.block.spec.js @@ -0,0 +1,33 @@ +module.exports = { + FeatureName: 'Tabs Block', + features: [ + { + tcid: '0', + name: '@Tabs (xl-spacing)', + path: '/drafts/nala/blocks/tabs/tabs-xl-spacing', + data: { + tabsCount: 3, + activeTab: 2, + tab1Text: 'Here is tab 1 content', + tab2Text: 'Here is tab 2 content and it is active tab', + tab3Text: 'Here is tab 3 content', + }, + tags: '@tabs @smoke @regression @milo', + }, + { + tcid: '1', + name: '@Tabs (Quiet, Dark, Center)', + path: '/drafts/nala/blocks/tabs/tabs-quiet-dark-center', + data: { + tabsCount: 3, + activeTab: 2, + tab1Text: 'Here is tab 1 content', + tab2Text: 'Here is tab 2 content and it is active tab', + tab3Text: 'Here is tab 3 content', + }, + tags: '@tabs @smoke @t1 @regression @milo', + }, + ], +}; + + diff --git a/selectors/milo/tabs.block.page.js b/selectors/milo/tabs.block.page.js new file mode 100644 index 00000000..117b6903 --- /dev/null +++ b/selectors/milo/tabs.block.page.js @@ -0,0 +1,23 @@ +export default class Tabs { + constructor(page, nth = 0) { + this.page = page; + // tabs locators + this.tab = this.page.locator('.tabs').nth(nth); + this.xlTab = this.page.locator('.tabs.xl-spacing').nth(nth); + this.queitDarkTab = this.page.locator('.tabs.quiet.dark.center').nth(nth); + // tabs list + this.tabList = this.tab.locator('.tablist'); + this.tabListContainer = this.tab.locator('.tab-list-container'); + this.tabsCount = this.tabListContainer.locator('button[role="tab"]'); + this.tab1 = this.tabListContainer.locator('button[role="tab"]').nth(0) + this.tab2 = this.tabListContainer.locator('button[role="tab"]').nth(1) + this.tab3 = this.tabListContainer.locator('button[role="tab"]').nth(2) + // tabs panel and content + this.tabContent = this.tab.locator('.tab-content'); + this.tab1Panel = this.tabContent.locator('div[role="tabpanel"]').nth(0) + this.tab2Panel = this.tabContent.locator('div[role="tabpanel"]').nth(1) + this.tab3Panel = this.tabContent.locator('div[role="tabpanel"]').nth(2) + } +} + + diff --git a/tests/milo/merchcard.block.test.js b/tests/milo/merchcard.block.test.js index a78283de..5778b5bb 100644 --- a/tests/milo/merchcard.block.test.js +++ b/tests/milo/merchcard.block.test.js @@ -27,8 +27,8 @@ test.describe('Milo Modal feature test suite', () => { await expect(await merchCard.segment).toBeVisible(); await expect(await merchCard.segmentTitle).toContainText(data.title); - await expect(await merchCard.price).toContainText(data.price); - await expect(await merchCard.strikethroughPrice).toContainText(data.strikethroughPrice); + //await expect(await merchCard.price).toContainText(data.price); + //await expect(await merchCard.strikethroughPrice).toContainText(data.strikethroughPrice); await expect(await merchCard.segmentDescription1).toContainText(data.description); await expect(await merchCard.linkText1).toContainText(data.link1Text); @@ -62,8 +62,8 @@ test.describe('Milo Modal feature test suite', () => { await expect(await merchCard.segmentRibbon).toBeVisible(); await expect(await merchCard.segmentRibbon).toContainText(data.badgeText); - await expect(await merchCard.price).toContainText(data.price); - await expect(await merchCard.strikethroughPrice).toContainText(data.strikethroughPrice); + //await expect(await merchCard.price).toContainText(data.price); + //await expect(await merchCard.strikethroughPrice).toContainText(data.strikethroughPrice); await expect(await merchCard.segmentDescription1).toContainText(data.description); await expect(await merchCard.linkText1).toContainText(data.link1Text); @@ -166,7 +166,7 @@ test.describe('Milo Modal feature test suite', () => { await expect(await merchCard.plansCardTitleH3).toContainText(data.titleH3); await expect(await merchCard.plansCardTitleH5).toContainText(data.titleH5); - await expect(await merchCard.price).toContainText(data.price); + //await expect(await merchCard.price).toContainText(data.price); await expect(await merchCard.plansCardDescription2).toContainText(data.description); await expect(await merchCard.seePlansTextLink).toContainText(data.link1Text); @@ -198,7 +198,7 @@ test.describe('Milo Modal feature test suite', () => { await expect(await merchCard.plansCardTitleH3).toContainText(data.titleH3); await expect(await merchCard.plansCardTitleH5).toContainText(data.titleH5); - await expect(await merchCard.price).toContainText(data.price); + //await expect(await merchCard.price).toContainText(data.price); await expect(await merchCard.plansCardDescription2).toContainText(data.description); await expect(await merchCard.seePlansTextLink).toContainText(data.link1Text); @@ -227,7 +227,7 @@ test.describe('Milo Modal feature test suite', () => { await expect(await merchCard.plansCardTitleH3).toContainText(data.titleH3); await expect(await merchCard.plansCardTitleH5).toContainText(data.titleH5); - await expect(await merchCard.price).toContainText(data.price); + //await expect(await merchCard.price).toContainText(data.price); await expect(await merchCard.plansCardDescription2).toContainText(data.description); await expect(await merchCard.seePlansTextLink).toContainText(data.link1Text); @@ -276,7 +276,7 @@ test.describe('Milo Modal feature test suite', () => { await expect(await merchCard.plansCardTitleH3).toContainText(data.titleH3); await expect(await merchCard.plansCardTitleH5).toContainText(data.titleH5); - await expect(await merchCard.price).toContainText(data.price); + //await expect(await merchCard.price).toContainText(data.price); await expect(await merchCard.plansCardDescription2).toContainText(data.description); await expect(await merchCard.seePlansTextLink).toContainText(data.link1Text); diff --git a/tests/milo/tab.block.test.js b/tests/milo/tab.block.test.js new file mode 100644 index 00000000..93db25cf --- /dev/null +++ b/tests/milo/tab.block.test.js @@ -0,0 +1,79 @@ +import { expect, test } from '@playwright/test'; +import { features } from '../../features/milo/tabs.block.spec.js'; +import TabBlock from '../../selectors/milo/tabs.block.page.js'; + +let tab; + +test.describe('Milo Tab block feature test suite', () => { + test.beforeEach(async ({ page }) => { + tab = new TabBlock(page); + }); + + // Test 0 : Tabs (xl-spacing) + test(`${features[0].name},${features[0].tags}`, async ({ page, baseURL }) => { + console.info(`[Test Page]: ${baseURL}${features[0].path}`); + const data = features[0].data; + + await test.step('step-1: Go to Tabs block feature test page', async () => { + await page.goto(`${baseURL}${features[0].path}`); + await page.waitForLoadState('domcontentloaded'); + await expect(page).toHaveURL(`${baseURL}${features[0].path}`); + }); + + await test.step('step-2: Verify tabs content/specs', async () => { + await expect(await tab.xlTab).toBeVisible(); + await expect(await tab.tabsCount).toHaveCount(data.tabsCount); + //verify default tab contents + await expect(await tab.tab2).toHaveAttribute('aria-selected', 'true') + await expect(await tab.tab2Panel).toBeVisible(); + await expect(await tab.tab2Panel).toContainText(data.tab2Text) + + //click tabs and verify contents + await expect(await tab.tab1).toHaveAttribute('aria-selected', 'false') + await tab.tab1.click() + await expect(await tab.tab1Panel).toBeVisible(); + await expect(await tab.tab1Panel).toContainText(data.tab1Text); + + await expect(await tab.tab3).toHaveAttribute('aria-selected', 'false') + await tab.tab3.click() + await expect(await tab.tab3Panel).toBeVisible(); + await expect(await tab.tab3Panel).toContainText(data.tab3Text); + }); + }); + + // Test 1 : Tabs (Quiet, Dark, Center) + test(`${features[1].name},${features[1].tags}`, async ({ page, baseURL }) => { + console.info(`[Test Page]: ${baseURL}${features[1].path}`); + const data = features[1].data; + + await test.step('step-1: Go to Tabs block feature test page', async () => { + await page.goto(`${baseURL}${features[1].path}`); + await page.waitForLoadState('domcontentloaded'); + await expect(page).toHaveURL(`${baseURL}${features[1].path}`); + }); + + await test.step('step-2: Verify tabs content/specs', async () => { + await expect(await tab.queitDarkTab).toBeVisible(); + await expect(await tab.tabsCount).toHaveCount(data.tabsCount); + //verify default tab contents + await expect(await tab.tab2).toHaveAttribute('aria-selected', 'true') + await expect(await tab.tab2Panel).toBeVisible(); + await expect(await tab.tab2Panel).toContainText(data.tab2Text) + + //click tabs and verify contents + await expect(await tab.tab1).toHaveAttribute('aria-selected', 'false') + await tab.tab1.click() + await expect(await tab.tab1Panel).toBeVisible(); + await expect(await tab.tab1Panel).toContainText(data.tab1Text); + + await expect(await tab.tab3).toHaveAttribute('aria-selected', 'false') + await tab.tab3.click() + await expect(await tab.tab3Panel).toBeVisible(); + await expect(await tab.tab3Panel).toContainText(data.tab3Text); + }); + }); + +}); + + + From f95162e0608462b52098caf90a266383a78b43b5 Mon Sep 17 00:00:00 2001 From: Dan Chivescu Date: Tue, 14 Nov 2023 11:08:13 +0200 Subject: [PATCH 13/53] [MWPW-138268] FEDS Promo bar component (#204) * [MWPW-138268] Added Promobar logic & selectors * [MWPW-138268] Added Promobar test file & PO * [MWPW-13868] Removed unnecessary spec config * [MWPW-138268] Adressing PR reviews --------- Co-authored-by: Aaron Mauchley --- features/feds/promobar.spec.js | 18 ++++++++++++++ selectors/feds/feds.header.page.js | 14 +++++++++++ tests/feds/promobar.test.js | 40 ++++++++++++++++++++++++++++++ 3 files changed, 72 insertions(+) create mode 100644 features/feds/promobar.spec.js create mode 100644 tests/feds/promobar.test.js diff --git a/features/feds/promobar.spec.js b/features/feds/promobar.spec.js new file mode 100644 index 00000000..47583be4 --- /dev/null +++ b/features/feds/promobar.spec.js @@ -0,0 +1,18 @@ +module.exports = { + name: 'Promobar Block', + features: [ + { + name: '@FEDS-Promo-Checks', + path: [ + '/libs/feds/drafts/qa/promo/feds-promo-bar', + ], + data: { + promoBarBtn: 'See offers', + promoBarText: 'Black Friday 2023 is here! Check out the HOT NEW basketball jerseys from our shop!', + promoBarBtnLink: 'https://adobe.com/', + }, + browserParams: '?georouting=off', + tags: '@milo @feds @promobar @smoke @regression', + }, + ], +}; diff --git a/selectors/feds/feds.header.page.js b/selectors/feds/feds.header.page.js index cf0ea798..df43a702 100644 --- a/selectors/feds/feds.header.page.js +++ b/selectors/feds/feds.header.page.js @@ -34,6 +34,20 @@ export default class FedsHeader { this.breadcrumbList = page.locator('nav.feds-breadcrumbs ul'); this.breadcrumbElems = page.locator('nav.feds-breadcrumbs li'); this.breadcrumbContainer = page.locator('nav.feds-breadcrumbs'); + + // Promo-bar selectors: + this.promoBarContainer = page.locator('div.aside.promobar'); + this.promoBarBackground = this.promoBarContainer.locator('div.background'); + this.promoBarForeground = this.promoBarContainer.locator('div.foreground'); + this.promoBarContent = this.promoBarContainer.locator('div.desktop-up'); + this.promoBarText = this.promoBarContainer.locator('div.desktop-up p.content-area'); + this.promoBarBtn = this.promoBarContainer.locator('div.desktop-up p.action-area a'); + this.promoBarMobileContent = this.promoBarContainer.locator('div.mobile-up'); + this.promoBarMobileText = this.promoBarContainer.locator('div.mobile-up p.content-area'); + this.promoBarMobileBtn = this.promoBarContainer.locator('div.mobile-up p.action-area a'); + this.promoBarTabletContent = this.promoBarContainer.locator('div.tablet-up'); + this.promoBarTabletText = this.promoBarContainer.locator('div.tablet-up p.content-area'); + this.promoBarTabletBtn = this.promoBarContainer.locator('div.tablet-up p.action-area a'); } /** diff --git a/tests/feds/promobar.test.js b/tests/feds/promobar.test.js new file mode 100644 index 00000000..a4ce953a --- /dev/null +++ b/tests/feds/promobar.test.js @@ -0,0 +1,40 @@ +/* eslint-disable import/named */ +/* eslint-disable no-await-in-loop */ +/* eslint-disable import/extensions */ +import { expect, test } from '@playwright/test'; +import { features } from '../../features/feds/promobar.spec.js'; +import FedsHeader from '../../selectors/feds/feds.header.page.js'; + +test.describe('Promobar Block Test Suite', () => { + // FEDS Default Header Checks: + test(`${features[0].name}, ${features[0].tags}`, async ({ page, baseURL }) => { + const Header = new FedsHeader(page); + const { data } = features[0]; + console.info(`[FEDSInfo] Checking page: ${baseURL}${features[0].path}`); + + await test.step('Navigate to FEDS Promobar page', async () => { + await page.goto(`${baseURL}${features[0].path}${features[0].browserParams}`); + await page.waitForLoadState('domcontentloaded'); + await expect(page).toHaveURL(`${baseURL}${features[0].path}${features[0].browserParams}`); + }); + + await test.step('Check Promobar block content', async () => { + // Wait for promobar to be visible: + await Header.promoBarContainer.waitFor({ state: 'visible', timeout: 5000 }); + // Check promobar content: + await expect(Header.promoBarBackground).toBeVisible(); + await expect(Header.promoBarForeground).toBeVisible(); + await expect(Header.promoBarContent).toBeVisible(); + await expect(Header.promoBarText).toBeVisible(); + await expect(Header.promoBarBtn).toBeVisible(); + await expect(Header.promoBarBtn).toHaveText(data.promoBarBtn); + await expect(Header.promoBarText).toHaveText(data.promoBarText); + // Check promobar action button: + expect(await Header.promoBarBtn).toHaveAttribute('href', data.promoBarBtnLink); + await Header.promoBarBtn.click(); + await page.waitForLoadState('domcontentloaded'); + await Header.mainNavContainer.waitFor({ state: 'visible', timeout: 5000 }); + await expect(page).toHaveURL('https://www.adobe.com/'); + }); + }); +}); From 20a2934c8a98b60f85f96d3199ae515259ccb541 Mon Sep 17 00:00:00 2001 From: Santoshkumar Nateekar Date: Tue, 14 Nov 2023 11:41:35 -0800 Subject: [PATCH 14/53] [MWPW-139138] : Table block tests scripts (#206) * table block test scripts * spell correct * remove comments * remove additional spaces and comments --------- Co-authored-by: nateekar --- features/milo/table.block.spec.js | 123 ++++++++++++++++++ selectors/milo/table.block.page.js | 74 +++++++++++ tests/milo/table.block.test.js | 200 +++++++++++++++++++++++++++++ utils/reporters/base-reporter.js | 11 +- 4 files changed, 406 insertions(+), 2 deletions(-) create mode 100644 features/milo/table.block.spec.js create mode 100644 selectors/milo/table.block.page.js create mode 100644 tests/milo/table.block.test.js diff --git a/features/milo/table.block.spec.js b/features/milo/table.block.spec.js new file mode 100644 index 00000000..7525f8d6 --- /dev/null +++ b/features/milo/table.block.spec.js @@ -0,0 +1,123 @@ +module.exports = { + FeatureName: 'Table Block', + features: [ + { + tcid: '0', + name: '@Table (default)', + path: '/drafts/nala/blocks/table/table', + data: { + rowsCount: 9, + headerRowColCount: 5, + sectionRowCount: 8, + headerCell2: { + heading: 'Heading Title-2', + pricingText: 'Pricing-2', + outlineButtonText: 'Free trial', + blueButtonText: 'Buy now', + }, + sectionRow2: { + sectionRowTitle: 'Row-1.1, Title', + cell22: 'Content', + }, + }, + tags: '@table @smoke @regression @milo', + }, + { + tcid: '1', + name: '@Table (highlight)', + path: '/drafts/nala/blocks/table/table-hightlight', + data: { + rowsCount: 10, + headerRowColCount: 5, + sectionRowCount: 8, + hightlightRow: { + cell12: 'Highlight-2', + cell13: 'Highlight-3', + cell14: 'Highlight-4', + }, + headerCell3: { + heading: 'Heading Title-3', + pricingText: 'Pricing-3', + outlineButtonText: 'Free trial', + blueButtonText: 'Buy now', + }, + sectionRow2: { + sectionRowTitle: 'Row-1.1, Title', + cell22: 'Content', + }, + }, + tags: '@table @smoke @regression @milo', + }, + { + tcid: '2', + name: '@Table (sticky)', + path: '/drafts/nala/blocks/table/table-sticky', + data: { + rowsCount: 9, + headerRowColCount: 5, + sectionRowCount: 8, + headerCell4: { + heading: 'Heading Title-4', + pricingText: 'Pricing-4', + outlineButtonText: 'Free trial', + blueButtonText: 'Buy now', + }, + sectionRow2: { + sectionRowTitle: 'Row-1.1, Title', + cell22: 'Content', + }, + }, + tags: '@table @smoke @regression @milo', + }, + { + tcid: '3', + name: '@Table (highlight, collapse, sticky)', + path: '/drafts/nala/blocks/table/table-highlight-collapse-sticky', + data: { + rowsCount: 10, + headerRowColCount: 5, + sectionRowCount: 8, + hightlightRow: { + cell12: 'Highlight-2', + cell13: 'Highlight-3', + cell14: 'Highlight-4', + }, + headerCell5: { + heading: 'Heading Title-5', + pricingText: 'Pricing-5', + outlineButtonText: 'Free trial', + blueButtonText: 'Buy now', + }, + sectionRow2: { + sectionRowTitle: 'Row-1.1, Title', + cell22: 'Content', + }, + }, + tags: '@table @smoke @regression @milo', + }, + { + tcid: '4', + name: '@Table (merch)', + path: '/drafts/nala/blocks/table/table-merch', + data: { + rowsCount: 9, + headerRowColCount: 3, + sectionRowCount: 8, + headerCell1: { + heading: 'Heading Title-1', + pricingText: 'Pricing-1', + AdditionalText: 'Additional Text-1', + outlineButtonText: 'Free trial', + blueButtonText: 'Buy now', + }, + sectionRow2: { + merchContent: 'Section Content-1.1', + image: 'yes', + }, + }, + tags: '@table @smoke @regression @milo', + }, + ], +}; + + diff --git a/selectors/milo/table.block.page.js b/selectors/milo/table.block.page.js new file mode 100644 index 00000000..08352b3e --- /dev/null +++ b/selectors/milo/table.block.page.js @@ -0,0 +1,74 @@ +export default class Table { + constructor(page, nth = 0) { + this.page = page; + // tabel locators + this.table = this.page.locator('.table').nth(nth); + this.highlightTable = this.page.locator('.table.highlight').nth(nth); + this.stickyTable = this.page.locator('.table.sticky').nth(nth); + this.collapseStickyTable = this.page.locator('.table.highlight.collapse.sticky').nth(nth); + this.merchTable = this.page.locator('.table.merch').nth(nth); + this.merchHighlightStickyTable = this.page.locator('.table.merch.highlight.sticky').nth(nth); + + this.highlightRow = this.table.locator('.row-highlight'); + this.headingRow = this.table.locator('.row-heading'); + this.stickyRow = this.table.locator('.row-heading'); + + this.headingRowColumns = this.headingRow.locator('.col'); + this.rows = this.table.locator('.row'); + this.sectionRows = this.table.locator('.section-row'); + } + + async getHighlightRowColumnTitle(colIndex) { + return await this.highlightRow.locator(`.col-highlight`).nth(colIndex); + } + + async getHeaderColumnTitle(colIndex) { + const headerColumn = await this.headingRow.locator(`.col-${colIndex}`); + return headerColumn.locator(`.tracking-header`); + } + + async getHeaderColumnPricing(colIndex) { + const headerColumn = await this.headingRow.locator(`.col-${colIndex}`); + return headerColumn.locator(`.pricing`); + } + + async getHeaderColumnImg(colIndex) { + const headerColumn = await this.headingRow.locator(`.col-${colIndex}`); + return headerColumn.locator(`img`); + } + + async getHeaderColumnAdditionalText(colIndex) { + const headerColumn = await this.headingRow.locator(`.col-${colIndex}`); + return headerColumn.locator(`p`).nth(3); + } + + async getHeaderColumnOutlineButton(colIndex) { + const headerColumn = await this.headingRow.locator(`.col-${colIndex}`); + return headerColumn.locator(`.con-button.outline`); + } + + async getHeaderColumnBlueButton(colIndex) { + const headerColumn = await this.headingRow.locator(`.col-${colIndex}`); + return headerColumn.locator(`.con-button.blue`); + } + + async getSectionRowTitle(index) { + const sectionRow = await this.table.locator(`.section-row`).nth(index); + return sectionRow.locator(`.section-row-title`); + } + + async getSectionRowMerchContent(index) { + const sectionRow = await this.table.locator(`.section-row`).nth(index); + return sectionRow.locator(`.col-merch-content`).nth(0); + } + + async getSectionRowMerchContentImg(index) { + const sectionRow = await this.table.locator(`.section-row`).nth(index); + return sectionRow.locator(`.col-merch-content img`); + } + + async getSectionRowCell(rowIndex, colIndex) { + const sectionRow = await this.table.locator(`.section-row`).nth(rowIndex); + return sectionRow.locator(`.col-${colIndex}`) + } +} diff --git a/tests/milo/table.block.test.js b/tests/milo/table.block.test.js new file mode 100644 index 00000000..08bb26b4 --- /dev/null +++ b/tests/milo/table.block.test.js @@ -0,0 +1,200 @@ +import { expect, test } from '@playwright/test'; +import { features } from '../../features/milo/table.block.spec'; +import TableBlock from '../../selectors/milo/table.block.page'; + +let table; + +test.describe('Milo Table block feature test suite', () => { + test.beforeEach(async ({ page }) => { + table = new TableBlock(page); + }); + + // Test 0 : Table block (default) + test(`${features[0].name},${features[0].tags}`, async ({ page, baseURL }) => { + console.info(`[Test Page]: ${baseURL}${features[0].path}`); + const data = features[0].data; + + await test.step('step-1: Go to Table block test page', async () => { + await page.goto(`${baseURL}${features[0].path}`); + await page.waitForLoadState('domcontentloaded'); + await expect(page).toHaveURL(`${baseURL}${features[0].path}`); + }); + + await test.step('step-2: Verify table content/specs', async () => { + await expect(await table.table).toBeVisible(); + await expect(await table.rows).toHaveCount(data.rowsCount); + await expect(await table.headingRowColumns).toHaveCount(data.headerRowColCount); + await expect(await table.sectionRows).toHaveCount(data.sectionRowCount); + + //verify header row cell + const headerCell = data.headerCell2; + await expect(await table.getHeaderColumnTitle(2)).toContainText(headerCell.heading); + await expect(await table.getHeaderColumnPricing(2)).toContainText(headerCell.pricingText); + await expect(await table.getHeaderColumnOutlineButton(2)).toContainText(headerCell.outlineButtonText); + await expect(await table.getHeaderColumnBlueButton(2)).toContainText(headerCell.blueButtonText); + + //verify section row cell + const sectionCell = data.sectionRow2; + await expect(await table.getSectionRowTitle(2)).toContainText(sectionCell.sectionRowTitle); + await expect(await table.getSectionRowCell(2, 2)).toContainText(sectionCell.cell22); + + }); + }); + + // Test 1 : Table (highlight) + test(`${features[1].name},${features[1].tags}`, async ({ page, baseURL }) => { + console.info(`[Test Page]: ${baseURL}${features[1].path}`); + const data = features[1].data; + + await test.step('step-1: Go to Table block test page', async () => { + await page.goto(`${baseURL}${features[1].path}`); + await page.waitForLoadState('domcontentloaded'); + await expect(page).toHaveURL(`${baseURL}${features[1].path}`); + }); + + await test.step('step-2: Verify table content/specs', async () => { + await expect(await table.highlightTable).toBeVisible(); + await expect(await table.highlightRow).toBeVisible(); + + await expect(await table.rows).toHaveCount(data.rowsCount); + await expect(await table.headingRowColumns).toHaveCount(data.headerRowColCount); + await expect(await table.sectionRows).toHaveCount(data.sectionRowCount); + + //verify highlighter row + const highlighter = data.hightlightRow; + await expect(await table.getHighlightRowColumnTitle(1)).toContainText(highlighter.cell12); + await expect(await table.getHighlightRowColumnTitle(2)).toContainText(highlighter.cell13); + await expect(await table.getHighlightRowColumnTitle(3)).toContainText(highlighter.cell14); + + //verify header row cell + const headerCell = data.headerCell3; + await expect(await table.getHeaderColumnTitle(3)).toContainText(headerCell.heading); + await expect(await table.getHeaderColumnPricing(3)).toContainText(headerCell.pricingText); + await expect(await table.getHeaderColumnOutlineButton(3)).toContainText(headerCell.outlineButtonText); + await expect(await table.getHeaderColumnBlueButton(3)).toContainText(headerCell.blueButtonText); + + //verify section row cell + const sectionCell = data.sectionRow2; + await expect(await table.getSectionRowTitle(2)).toContainText(sectionCell.sectionRowTitle); + await expect(await table.getSectionRowCell(2, 2)).toContainText(sectionCell.cell22); + + }); + }); + + // Test 2 : Table (sticky) + test(`${features[2].name},${features[2].tags}`, async ({ page, baseURL }) => { + console.info(`[Test Page]: ${baseURL}${features[2].path}`); + const data = features[2].data; + + await test.step('step-1: Go to Table block test page', async () => { + await page.goto(`${baseURL}${features[2].path}`); + await page.waitForLoadState('domcontentloaded'); + await expect(page).toHaveURL(`${baseURL}${features[2].path}`); + }); + + await test.step('step-2: Verify table content/specs', async () => { + //verify sticky table header and attributes + await expect(await table.stickyTable).toBeVisible(); + await expect(await table.stickyRow).toHaveAttribute('style', 'top: 64px;'); + await expect(await table.stickyRow).toHaveAttribute('class', 'row row-1 row-heading top-border-transparent'); + + //verify table row, column count + await expect(await table.rows).toHaveCount(data.rowsCount); + await expect(await table.headingRowColumns).toHaveCount(data.headerRowColCount); + await expect(await table.sectionRows).toHaveCount(data.sectionRowCount); + + //verify header row cell + const headerCell = data.headerCell4; + await expect(await table.getHeaderColumnTitle(4)).toContainText(headerCell.heading); + await expect(await table.getHeaderColumnPricing(4)).toContainText(headerCell.pricingText); + await expect(await table.getHeaderColumnOutlineButton(4)).toContainText(headerCell.outlineButtonText); + await expect(await table.getHeaderColumnBlueButton(4)).toContainText(headerCell.blueButtonText); + + //verify section row cell + const sectionCell = data.sectionRow2; + await expect(await table.getSectionRowTitle(2)).toContainText(sectionCell.sectionRowTitle); + await expect(await table.getSectionRowCell(2, 2)).toContainText(sectionCell.cell22); + }); + }); + + // Test 3 : Table (highlight, collapse, sticky) + test(`${features[3].name},${features[3].tags}`, async ({ page, baseURL }) => { + console.info(`[Test Page]: ${baseURL}${features[3].path}`); + const data = features[3].data; + + await test.step('step-1: Go to Table block test page', async () => { + await page.goto(`${baseURL}${features[3].path}`); + await page.waitForLoadState('domcontentloaded'); + await expect(page).toHaveURL(`${baseURL}${features[3].path}`); + }); + + await test.step('step-2: Verify table content/specs', async () => { + //verify sticky table header and attributes + await expect(await table.collapseStickyTable).toBeVisible(); + + expect(await table.highlightRow).toHaveAttribute('style', 'top: 64px;'); + expect(await table.highlightRow).toHaveAttribute('class', 'row row-1 row-highlight top-border-transparent'); + + expect(await table.stickyRow).toHaveAttribute('style', 'top: 114px;'); + expect(await table.stickyRow.getAttribute('class')).toContain('row row-2 row-heading') + + //verify table row, column count + await expect(await table.rows).toHaveCount(data.rowsCount); + await expect(await table.headingRowColumns).toHaveCount(data.headerRowColCount); + await expect(await table.sectionRows).toHaveCount(data.sectionRowCount); + + //verify highlighter row + const highlighter = data.hightlightRow; + await expect(await table.getHighlightRowColumnTitle(1)).toContainText(highlighter.cell12); + await expect(await table.getHighlightRowColumnTitle(2)).toContainText(highlighter.cell13); + await expect(await table.getHighlightRowColumnTitle(3)).toContainText(highlighter.cell14); + + //verify header row cell + const headerCell = data.headerCell5; + await expect(await table.getHeaderColumnTitle(5)).toContainText(headerCell.heading); + await expect(await table.getHeaderColumnPricing(5)).toContainText(headerCell.pricingText); + await expect(await table.getHeaderColumnOutlineButton(5)).toContainText(headerCell.outlineButtonText); + await expect(await table.getHeaderColumnBlueButton(5)).toContainText(headerCell.blueButtonText); + + //verify section row cell + const sectionCell = data.sectionRow2; + await expect(await table.getSectionRowTitle(2)).toContainText(sectionCell.sectionRowTitle); + await expect(await table.getSectionRowCell(2, 2)).toContainText(sectionCell.cell22); + }); + }); + + // Test 4 : Table (merch) + test(`${features[4].name},${features[4].tags}`, async ({ page, baseURL }) => { + console.info(`[Test Page]: ${baseURL}${features[4].path}`); + const data = features[4].data; + + await test.step('step-1: Go to Table block test page', async () => { + await page.goto(`${baseURL}${features[4].path}`); + await page.waitForLoadState('domcontentloaded'); + await expect(page).toHaveURL(`${baseURL}${features[4].path}`); + }); + + await test.step('step-2: Verify table content/specs', async () => { + //verify merch table + await expect(await table.merchTable).toBeVisible(); + + //verify table row, column count + await expect(await table.rows).toHaveCount(data.rowsCount); + await expect(await table.headingRowColumns).toHaveCount(data.headerRowColCount); + await expect(await table.sectionRows).toHaveCount(data.sectionRowCount); + + //verify merch table header row cell + const headerCell = data.headerCell1; + await expect(await table.getHeaderColumnTitle(1)).toContainText(headerCell.heading); + await expect(await table.getHeaderColumnPricing(1)).toContainText(headerCell.pricingText); + await expect(await table.getHeaderColumnAdditionalText(1)).toContainText(headerCell.AdditionalText); + await expect(await table.getHeaderColumnOutlineButton(1)).toContainText(headerCell.outlineButtonText); + await expect(await table.getHeaderColumnBlueButton(1)).toContainText(headerCell.blueButtonText); + + //verify merch table section row cell + const sectionCell = data.sectionRow2; + await expect(await table.getSectionRowMerchContent(2)).toContainText(sectionCell.merchContent); + await expect(await table.getSectionRowMerchContentImg(2)).toBeVisible(); + }); + }); +}); diff --git a/utils/reporters/base-reporter.js b/utils/reporters/base-reporter.js index 785994f8..97eb622b 100644 --- a/utils/reporters/base-reporter.js +++ b/utils/reporters/base-reporter.js @@ -1,5 +1,5 @@ import { sendSlackMessage } from '../../libs/slack.js'; -const envs = require('../../envs/envs.js'); + // Playwright will include ANSI color characters and regex from below // https://github.com/microsoft/playwright/issues/13522 // https://github.com/chalk/ansi-regex/blob/main/index.js#L3 @@ -79,7 +79,14 @@ class BaseReporter { //await this.persistData(); const summary = this.printResultSummary(); const resultSummary = { summary }; - //await sendSlackMessage(envs['@webhook_url'], resultSummary); + + if (process.env.SLACK_WH) { + try { + await sendSlackMessage(process.env.SLACK_WH, resultSummary); + } catch (error){ + console.log('----Failed to publish result to slack channel----'); + } + } } printResultSummary() { From b0fae9274ad8f0422659a81dd0b5637946b57239 Mon Sep 17 00:00:00 2001 From: Santoshkumar Nateekar Date: Tue, 14 Nov 2023 14:52:16 -0800 Subject: [PATCH 15/53] Run nala tests on stage env (#207) * update to run on circleci * update comment --------- Co-authored-by: nateekar --- global.setup.js | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/global.setup.js b/global.setup.js index 5cca8fe6..f67bd24c 100644 --- a/global.setup.js +++ b/global.setup.js @@ -63,6 +63,15 @@ async function globalSetup() { } + } else if (process.env.CIRCLECI) { + console.info('----Executing Tests in CircleCI environment ---------'); + + prBranchLiveUrl = 'https://milo.stage.adobe.com'; + + if (await isBranchURLValid(prBranchLiveUrl)) { + process.env.PR_BRANCH_LIVE_URL = prBranchLiveUrl; + } + } else { console.info('----Executing Tests in Local environment ---------'); From f3622d005d93b058a399937b49a37833ff923144 Mon Sep 17 00:00:00 2001 From: Santoshkumar Nateekar Date: Thu, 16 Nov 2023 00:54:48 -0800 Subject: [PATCH 16/53] [MWPW-139314] : Action-item Block tests scripts (#208) * action-item-scripts * comment update * remove extra space * update the review comment * update the action-item-count * update type * updated circleci url --------- Co-authored-by: nateekar --- .github/workflows/daily.yml | 1 + .github/workflows/debug.yml | 1 + .github/workflows/manual.yml | 1 + .github/workflows/self.yml | 1 + features/milo/actionitem.block.spec.js | 89 +++++++++++ global.setup.js | 17 ++- selectors/milo/actionitem.block.page.js | 35 +++++ tests/milo/actionitem.block.test.js | 189 ++++++++++++++++++++++++ utils/reporters/base-reporter.js | 17 ++- 9 files changed, 340 insertions(+), 11 deletions(-) create mode 100644 features/milo/actionitem.block.spec.js create mode 100644 selectors/milo/actionitem.block.page.js create mode 100644 tests/milo/actionitem.block.test.js diff --git a/.github/workflows/daily.yml b/.github/workflows/daily.yml index 75b15b2b..e5c1f770 100644 --- a/.github/workflows/daily.yml +++ b/.github/workflows/daily.yml @@ -22,6 +22,7 @@ jobs: IMS_EMAIL: ${{ secrets.IMS_EMAIL }} IMS_PASS: ${{ secrets.IMS_PASS }} HLX_TKN: ${{ secrets.HLX_TKN }} + SLACK_WH: ${{ secrets.SLACK_WH }} - name: Persist JSON Artifact uses: actions/upload-artifact@v3 if: always() diff --git a/.github/workflows/debug.yml b/.github/workflows/debug.yml index 89d86a52..71d29dc8 100644 --- a/.github/workflows/debug.yml +++ b/.github/workflows/debug.yml @@ -28,6 +28,7 @@ jobs: IMS_EMAIL: ${{ secrets.IMS_EMAIL }} IMS_PASS: ${{ secrets.IMS_PASS }} HLX_TKN: ${{ secrets.HLX_TKN }} + SLACK_WH: ${{ secrets.SLACK_WH }} - name: Nala Reporting uses: actions/upload-artifact@v3 if: always() diff --git a/.github/workflows/manual.yml b/.github/workflows/manual.yml index 75d94649..98b3e29c 100644 --- a/.github/workflows/manual.yml +++ b/.github/workflows/manual.yml @@ -29,6 +29,7 @@ jobs: IMS_EMAIL: ${{ secrets.IMS_EMAIL }} IMS_PASS: ${{ secrets.IMS_PASS }} HLX_TKN: ${{ secrets.HLX_TKN }} + SLACK_WH: ${{ secrets.SLACK_WH }} - name: Persist JSON Artifact uses: actions/upload-artifact@v3 if: always() diff --git a/.github/workflows/self.yml b/.github/workflows/self.yml index 2a869005..e4861f67 100644 --- a/.github/workflows/self.yml +++ b/.github/workflows/self.yml @@ -26,6 +26,7 @@ jobs: IMS_EMAIL: ${{ secrets.IMS_EMAIL }} IMS_PASS: ${{ secrets.IMS_PASS }} HLX_TKN: ${{ secrets.HLX_TKN }} + SLACK_WH: ${{ secrets.SLACK_WH }} - name: Persist JSON Artifact uses: actions/upload-artifact@v3 if: always() diff --git a/features/milo/actionitem.block.spec.js b/features/milo/actionitem.block.spec.js new file mode 100644 index 00000000..29d7a25e --- /dev/null +++ b/features/milo/actionitem.block.spec.js @@ -0,0 +1,89 @@ +module.exports = { + FeatureName: 'Action Item Block', + features: [ + { + tcid: '0', + name: '@Action-item (small) ', + path: '/drafts/nala/blocks/action-item/action-item-small', + data: { + bodyText: 'Body XS Regular - Image min-height 56px', + imgMinHeight: '56px', + }, + tags: '@action-item @smoke @regression @milo', + }, + { + tcid: '1', + name: '@Action-item (medium) ', + path: '/drafts/nala/blocks/action-item/action-item-medium', + data: { + bodyText: 'Body S Regular - Image min-height 80px', + imgMinHeight: '80px', + }, + tags: '@action-item @smoke @regression @milo', + }, + { + tcid: '2', + name: '@Action-item (large) ', + path: '/drafts/nala/blocks/action-item/action-item-large', + data: { + bodyText: 'Body M Regular - Image min-height 104px', + imgMinHeight: '104px', + }, + tags: '@action-item @smoke @regression @milo', + }, + { + tcid: '3', + name: '@Action-item (center) ', + path: '/drafts/nala/blocks/action-item/action-item-center', + data: { + bodyText: 'Center content', + margin: '0 auto', + }, + tags: '@action-item @smoke @regression @milo', + }, + { + tcid: '4', + name: '@Action-item (rounded) ', + path: '/drafts/nala/blocks/action-item/action-item-rounded', + data: { + bodyText: 'Border radius 4px', + borderRadius: '4px', + }, + tags: '@action-item @smoke @regression @milo', + }, + { + tcid: '5', + name: '@Action-item (float-button) ', + path: '/drafts/nala/blocks/action-item/action-item-float-button', + data: { + bodyText: 'Float button', + floatButtonText: 'Edit', + }, + tags: '@action-item @smoke @regression @milo', + }, + { + tcid: '6', + name: '@Action-item (scroller) ', + path: '/drafts/nala/blocks/action-item/action-scroller', + data: { + bodyText: 'content', + floatButtonText: 'Edit', + actionItemsCount: 6, + }, + tags: '@action-item @smoke @regression @milo', + }, + { + tcid: '7', + name: '@Action-item (scroller with navigation) ', + path: '/drafts/nala/blocks/action-item/action-scroller-navigation', + data: { + bodyText: 'content', + floatButtonText: 'Edit', + actionItemsCount: 8, + }, + tags: '@action-item @smoke @regression @milo', + } + ], +}; + + diff --git a/global.setup.js b/global.setup.js index f67bd24c..daa18cff 100644 --- a/global.setup.js +++ b/global.setup.js @@ -8,6 +8,7 @@ async function globalSetup() { console.info('----Executing Global setup---------'); let prBranchLiveUrl; + let stageBranchLiveUrl; let localTestLiveUrl; let localOrg; let localRepo; @@ -15,7 +16,7 @@ async function globalSetup() { // Check if the code is running in a GitHub CI/CD environment if (process.env.GITHUB_ACTIONS === 'true') { - console.info('----Executing Tests in GitHub ---------'); + console.info('---- Running Tests in the GitHub environment ---------'); // get the pr number const prReference = process.env.GITHUB_REF; @@ -60,21 +61,21 @@ async function globalSetup() { console.error(`Error => Error in setting PR Branch test URL : ${prBranchLiveUrl}`); console.info(`Note : PR branch test url ${prBranchLiveUrl} is not valid, Exiting test execution.`); process.exit(1); - } - - + } } else if (process.env.CIRCLECI) { - console.info('----Executing Tests in CircleCI environment ---------'); + console.info('---- Running Tests in the CircleCI environment ---------'); - prBranchLiveUrl = 'https://milo.stage.adobe.com'; + stageBranchLiveUrl = 'https://milo.stage.adobe.com'; + // Validate the stage URL by making an HTTP request if (await isBranchURLValid(prBranchLiveUrl)) { - process.env.PR_BRANCH_LIVE_URL = prBranchLiveUrl; + process.env.PR_BRANCH_LIVE_URL = stageBranchLiveUrl; } + console.info('Stage Branch Live URL : ', stageBranchLiveUrl); } else { - console.info('----Executing Tests in Local environment ---------'); + console.info('---- Running Tests in the Local environment ---------'); try { // Run 'git rev-parse --show-toplevel' to get the root directory of the Git repository diff --git a/selectors/milo/actionitem.block.page.js b/selectors/milo/actionitem.block.page.js new file mode 100644 index 00000000..8bd97ecf --- /dev/null +++ b/selectors/milo/actionitem.block.page.js @@ -0,0 +1,35 @@ +export default class ActionItem { + constructor(page, nth = 0) { + this.page = page; + + this.actionItem = this.page.locator('.action-item').nth(nth); + this.small = this.page.locator('.action-item.small').nth(nth); + this.medium = this.page.locator('.action-item.medium').nth(nth); + this.large = this.page.locator('.action-item.large').nth(nth); + this.center = this.page.locator('.action-item.center').nth(nth); + this.rounded = this.page.locator('.action-item.rounded').nth(nth); + this.floatIcon = this.page.locator('.action-item.float-icon').nth(nth); + this.floatButton = this.page.locator('.action-item.float-button').nth(nth); + this.libraryContainerStart = this.page.locator('.library-container-start').nth(nth); + this.libraryContainerEnd = this.page.locator('.library-container-end').nth(nth); + this.actionScroller = this.page.locator('.action-scroller').nth(nth); + this.scroller = this.page.locator('.scroller ').nth(nth); + this.scrollerActionItems = this.scroller.locator('.action-item'); + + this.navigationPrevious = this.actionScroller.locator('.nav-grad.previous'); + this.navigationNext = this.actionScroller.locator('.nav-grad.next'); + this.nextButton = this.navigationNext.locator('.nav-button.next-button'); + this.previousButton = this.navigationPrevious.locator('.nav-button.previous-button'); + + this.scrollerActionItems = this.scroller.locator('.action-item'); + + this.mainImage = this.actionItem.locator('.main-image').nth(nth); + this.mainImageDark = this.actionItem.locator('.main-image.dark').nth(nth); + this.image = this.mainImage.locator('img').nth(0); + this.bodyText = this.actionItem.locator('p').nth(1); + this.bodyTextLink = this.actionItem.locator('a').nth(0); + this.floatOutlineButton = this.mainImage.locator('a') + } +} + + diff --git a/tests/milo/actionitem.block.test.js b/tests/milo/actionitem.block.test.js new file mode 100644 index 00000000..8989b278 --- /dev/null +++ b/tests/milo/actionitem.block.test.js @@ -0,0 +1,189 @@ +import { expect, test } from '@playwright/test'; +import { WebUtil } from '../../libs/webutil.js'; +import { features } from '../../features/milo/actionitem.block.spec.js'; +import ActionItem from '../../selectors/milo/actionitem.block.page.js'; + +let actionItem; +let webUtil; + +test.describe('Milo Action-Item block test suite', () => { + test.beforeEach(async ({ page }) => { + actionItem = new ActionItem(page); + webUtil = new WebUtil(page); + }); + + // Test 0 : Action-Item (Small) + test(`${features[0].name},${features[0].tags}`, async ({ page, baseURL }) => { + console.info(`[Test Page]: ${baseURL}${features[0].path}`); + const data = features[0].data; + + await test.step('step-1: Go to Action item block test page', async () => { + await page.goto(`${baseURL}${features[0].path}`); + await page.waitForLoadState('domcontentloaded'); + await expect(page).toHaveURL(`${baseURL}${features[0].path}`); + }); + + await test.step('step-2: Verify Action item content/specs', async () => { + await expect(await actionItem.small).toBeVisible(); + await expect(await actionItem.image).toBeVisible(); + await expect(await actionItem.image).toHaveCSS('min-height', data.imgMinHeight); + + await expect(await actionItem.bodyTextLink).toBeVisible(); + await expect(await actionItem.bodyText).toContainText(data.bodyText); + }); + }); + + // Test 1 : Action-Item (Medium) + test(`${features[1].name},${features[1].tags}`, async ({ page, baseURL }) => { + console.info(`[Test Page]: ${baseURL}${features[1].path}`); + const data = features[1].data; + + await test.step('step-1: Go to Action item block test page', async () => { + await page.goto(`${baseURL}${features[1].path}`); + await page.waitForLoadState('domcontentloaded'); + await expect(page).toHaveURL(`${baseURL}${features[1].path}`); + }); + + await test.step('step-2: Verify Action item content/specs', async () => { + await expect(await actionItem.medium).toBeVisible(); + await expect(await actionItem.image).toBeVisible(); + await expect(await actionItem.image).toHaveCSS('min-height', data.imgMinHeight); + + await expect(await actionItem.bodyTextLink).toBeVisible(); + await expect(await actionItem.bodyText).toContainText(data.bodyText); + }); + }); + + // Test 2 : Action-Item (Large) + test(`${features[2].name},${features[2].tags}`, async ({ page, baseURL }) => { + console.info(`[Test Page]: ${baseURL}${features[2].path}`); + const data = features[2].data; + + await test.step('step-1: Go to Action item block test page', async () => { + await page.goto(`${baseURL}${features[2].path}`); + await page.waitForLoadState('domcontentloaded'); + await expect(page).toHaveURL(`${baseURL}${features[2].path}`); + }); + + await test.step('step-2: Verify Action item content/specs', async () => { + await expect(await actionItem.large).toBeVisible(); + await expect(await actionItem.image).toBeVisible(); + await expect(await actionItem.image).toHaveCSS('min-height', data.imgMinHeight); + + await expect(await actionItem.bodyTextLink).toBeVisible(); + await expect(await actionItem.bodyText).toContainText(data.bodyText); + }); + }); + + // Test 3 : Action-Item (Center) + test(`${features[3].name},${features[3].tags}`, async ({ page, baseURL }) => { + console.info(`[Test Page]: ${baseURL}${features[3].path}`); + const data = features[3].data; + + await test.step('step-1: Go to Action item block test page', async () => { + await page.goto(`${baseURL}${features[3].path}`); + await page.waitForLoadState('domcontentloaded'); + await expect(page).toHaveURL(`${baseURL}${features[3].path}`); + }); + + await test.step('step-2: Verify Action item content/specs', async () => { + await expect(await actionItem.center).toBeVisible(); + await expect(await actionItem.image).toBeVisible(); + + await expect(await actionItem.bodyTextLink).toBeVisible(); + await expect(await actionItem.bodyText).toContainText(data.bodyText); + }); + }); + + // Test 4 : Action-Item (Rounded) + test(`${features[4].name},${features[4].tags}`, async ({ page, baseURL }) => { + console.info(`[Test Page]: ${baseURL}${features[4].path}`); + const data = features[4].data; + + await test.step('step-1: Go to Action item block test page', async () => { + await page.goto(`${baseURL}${features[4].path}`); + await page.waitForLoadState('domcontentloaded'); + await expect(page).toHaveURL(`${baseURL}${features[4].path}`); + }); + + await test.step('step-2: Verify Action item content/specs', async () => { + await expect(await actionItem.rounded).toBeVisible(); + await expect(await actionItem.image).toBeVisible(); + await expect(await actionItem.image).toHaveCSS('border-radius', data.borderRadius); + + await expect(await actionItem.bodyTextLink).toBeVisible(); + await expect(await actionItem.bodyText).toContainText(data.bodyText); + }); + }); + + // Test 5 : Action-Item (Float Button) + test(`${features[5].name},${features[5].tags}`, async ({ page, baseURL }) => { + console.info(`[Test Page]: ${baseURL}${features[5].path}`); + const data = features[5].data; + + await test.step('step-1: Go to Action item block test page', async () => { + await page.goto(`${baseURL}${features[5].path}`); + await page.waitForLoadState('domcontentloaded'); + await expect(page).toHaveURL(`${baseURL}${features[5].path}`); + }); + + await test.step('step-2: Verify Action item content/specs', async () => { + await expect(await actionItem.floatButton).toBeVisible(); + await expect(await actionItem.image).toBeVisible(); + await expect(await actionItem.floatOutlineButton).toBeVisible(); + await expect(await actionItem.floatOutlineButton).toContainText(data.floatButtonText); + }); + }); + + // Test 6 : Action-Item (scroller) + test(`${features[6].name},${features[6].tags}`, async ({ page, baseURL }) => { + console.info(`[Test Page]: ${baseURL}${features[6].path}`); + const data = features[6].data; + + await test.step('step-1: Go to Action item block test page', async () => { + await page.goto(`${baseURL}${features[6].path}`); + await page.waitForLoadState('domcontentloaded'); + await expect(page).toHaveURL(`${baseURL}${features[6].path}`); + }); + + await test.step('step-2: Verify Action item content/specs', async () => { + await expect(await actionItem.libraryContainerStart).toBeVisible(); + await expect(await actionItem.actionScroller).toBeVisible(); + await expect(await actionItem.scroller).toBeVisible(); + await expect(await actionItem.scrollerActionItems).toHaveCount(data.actionItemsCount); + + await expect(await actionItem.image).toBeVisible(); + await expect(await actionItem.bodyText).toContainText(data.bodyText); + await expect(await actionItem.libraryContainerEnd).toBeVisible(); + }); + }); + + // Test 7 : Action-Item (scroller) + test(`${features[7].name},${features[7].tags}`, async ({ page, baseURL }) => { + console.info(`[Test Page]: ${baseURL}${features[7].path}`); + const data = features[7].data; + + await test.step('step-1: Go to Action item block test page', async () => { + await page.goto(`${baseURL}${features[7].path}`); + await page.waitForLoadState('domcontentloaded'); + await expect(page).toHaveURL(`${baseURL}${features[7].path}`); + }); + + await test.step('step-2: Verify Action item content/specs', async () => { + await expect(await actionItem.libraryContainerStart).toBeVisible(); + await expect(await actionItem.actionScroller).toBeVisible(); + await expect(await actionItem.scroller).toBeVisible(); + await expect(await actionItem.scrollerActionItems).toHaveCount(data.actionItemsCount); + + await expect(await actionItem.image).toBeVisible(); + await expect(await actionItem.bodyText).toContainText(data.bodyText); + await expect(await actionItem.libraryContainerEnd).toBeVisible(); + + await expect(await actionItem.nextButton).toBeVisible({timeout: 1000}); + await actionItem.nextButton.click(); + await expect(await actionItem.previousButton).toBeVisible({timeout: 1000}); + await expect(await actionItem.navigationNext).toHaveAttribute('hide-btn','false'); + }); + }); +}); + diff --git a/utils/reporters/base-reporter.js b/utils/reporters/base-reporter.js index 97eb622b..c7f29bd9 100644 --- a/utils/reporters/base-reporter.js +++ b/utils/reporters/base-reporter.js @@ -91,7 +91,8 @@ class BaseReporter { printResultSummary() { let envURL; - let exeEnv + let exeEnv; + let runUrl; const totalTests = this.results.length; const passPercentage = ((this.passedTests / totalTests) * 100).toFixed(2); const failPercentage = ((this.failedTests / totalTests) * 100).toFixed(2); @@ -99,7 +100,16 @@ class BaseReporter { if (process.env.GITHUB_ACTIONS === 'true') { envURL = process.env.PR_BRANCH_LIVE_URL || 'N/A'; exeEnv = 'GitHub Actions Environment'; - } else { + const repo = process.env.GITHUB_REPOSITORY; + const runId = process.env.GITHUB_RUN_ID; + runUrl = `https://github.com/${repo}/actions/runs/${runId}`; + }else if (process.env.CIRCLECI) { + envURL = process.env.PR_BRANCH_LIVE_URL || 'N/A'; + exeEnv = 'CircleCI Environment'; + const workflowId = process.env.CIRCLE_WORKFLOW_ID; + const jobNumber = process.env.CIRCLE_BUILD_NUM; + runUrl = `https://app.circleci.adobe.com/pipelines/github/wcms/nala/10/workflows/${workflowId}/jobs/${jobNumber}`; + }else { envURL = process.env.LOCAL_TEST_LIVE_URL || 'N/A'; exeEnv = 'Local Environment'; } @@ -111,7 +121,8 @@ class BaseReporter { # Test Fail : ${this.failedTests} (${failPercentage}%) # Test Skipped : ${this.skippedTests} ** Application URL : ${envURL} - ** Executed on : ${exeEnv}`; + ** Executed on : ${exeEnv} + ** Execution details : ${runUrl}`; console.log(summary); From 7326b2b3e4956aadf07716c0dbc200783c52c481 Mon Sep 17 00:00:00 2001 From: Santoshkumar Nateekar Date: Thu, 16 Nov 2023 01:20:06 -0800 Subject: [PATCH 17/53] Fix circle-ci url (#209) fix circle-ci url Co-authored-by: nateekar --- global.setup.js | 2 +- utils/reporters/base-reporter.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/global.setup.js b/global.setup.js index daa18cff..13c9352c 100644 --- a/global.setup.js +++ b/global.setup.js @@ -68,7 +68,7 @@ async function globalSetup() { stageBranchLiveUrl = 'https://milo.stage.adobe.com'; // Validate the stage URL by making an HTTP request - if (await isBranchURLValid(prBranchLiveUrl)) { + if (await isBranchURLValid(stageBranchLiveUrl)) { process.env.PR_BRANCH_LIVE_URL = stageBranchLiveUrl; } console.info('Stage Branch Live URL : ', stageBranchLiveUrl); diff --git a/utils/reporters/base-reporter.js b/utils/reporters/base-reporter.js index c7f29bd9..fde0d44e 100644 --- a/utils/reporters/base-reporter.js +++ b/utils/reporters/base-reporter.js @@ -108,7 +108,7 @@ class BaseReporter { exeEnv = 'CircleCI Environment'; const workflowId = process.env.CIRCLE_WORKFLOW_ID; const jobNumber = process.env.CIRCLE_BUILD_NUM; - runUrl = `https://app.circleci.adobe.com/pipelines/github/wcms/nala/10/workflows/${workflowId}/jobs/${jobNumber}`; + runUrl = `https://app.circleci.adobe.com/pipelines/github/wcms/nala/${jobNumber}/workflows/${workflowId}/jobs/${jobNumber}`; }else { envURL = process.env.LOCAL_TEST_LIVE_URL || 'N/A'; exeEnv = 'Local Environment'; From 9c7bad6e2acbd05727094d7a7ba555b1c0a3d00e Mon Sep 17 00:00:00 2001 From: Santoshkumar Nateekar Date: Thu, 16 Nov 2023 01:35:29 -0800 Subject: [PATCH 18/53] Update CircleCI URL (#210) * fix circle-ci url * update the circle url --------- Co-authored-by: nateekar --- utils/reporters/base-reporter.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/utils/reporters/base-reporter.js b/utils/reporters/base-reporter.js index fde0d44e..e6ddd63e 100644 --- a/utils/reporters/base-reporter.js +++ b/utils/reporters/base-reporter.js @@ -108,7 +108,7 @@ class BaseReporter { exeEnv = 'CircleCI Environment'; const workflowId = process.env.CIRCLE_WORKFLOW_ID; const jobNumber = process.env.CIRCLE_BUILD_NUM; - runUrl = `https://app.circleci.adobe.com/pipelines/github/wcms/nala/${jobNumber}/workflows/${workflowId}/jobs/${jobNumber}`; + runUrl = `https://app.circle.ci.adobe.com/pipelines/github/wcms/nala/${jobNumber}/workflows/${workflowId}/jobs/${jobNumber}`; }else { envURL = process.env.LOCAL_TEST_LIVE_URL || 'N/A'; exeEnv = 'Local Environment'; From 2d5c8baf03988ec163676cd89f70a5ec3126b20d Mon Sep 17 00:00:00 2001 From: Santoshkumar Nateekar Date: Fri, 17 Nov 2023 17:48:53 -0800 Subject: [PATCH 19/53] Update Merch card test scripts as per the changes : MWPW-138882: Commerce v3 Merch Card (#212) * fix circle-ci url * update merch cards scripts --------- Co-authored-by: nateekar --- selectors/milo/merchcard.block.page.js | 50 +++++++++++++------------- tests/milo/merchcard.block.test.js | 9 +++-- 2 files changed, 32 insertions(+), 27 deletions(-) diff --git a/selectors/milo/merchcard.block.page.js b/selectors/milo/merchcard.block.page.js index 68ea6360..10a8b724 100644 --- a/selectors/milo/merchcard.block.page.js +++ b/selectors/milo/merchcard.block.page.js @@ -25,42 +25,44 @@ export default class Merchcard { this.strikethroughPriceRecurrence = this.inlinePrice2.locator('.price-recurrence'); // merch-card segment locators - this.segmentRibbon = this.merchCard.locator('.consonant-SegmentBlade-ribbon'); - this.segmentTitle = this.segment.locator('.consonant-SegmentBlade-title').nth(0); - this.segmentDescription1 = this.segment.locator('.consonant-SegmentBlade-description').nth(0); - this.segmentDescription2 = this.segment.locator('.consonant-SegmentBlade-description').nth(1); + this.segmentRibbon = this.merchCard.locator('.segment-ribbon'); + this.segmentTitle = this.segment.locator('h3[slot="heading-xs"]').nth(0); + this.segmentDescription1 = this.segment.locator('div[slot="body-xs"] p').nth(0); + this.segmentDescription2 = this.segment.locator('div[slot="body-xs"] p').nth(1); this.linkText1 = this.segmentDescription2.locator('a').nth(0); this.linkText2 = this.segmentDescription2.locator('a').nth(1); // merch-card special offers - this.sepcialOffersImage = this.sepcialOffers.locator('.consonant-SpecialOffers-img'); - this.sepcialOffersRibbon = this.merchCard.locator('.consonant-SpecialOffers-ribbon'); - this.sepcialOffersTitleH4 = this.sepcialOffers.locator('h4.consonant-SpecialOffers-title'); - this.sepcialOffersTitleH3 = this.sepcialOffers.locator('h3.consonant-SpecialOffers-title'); + this.sepcialOffersImage = this.sepcialOffers.locator('div[slot="bg-image"] img'); + this.sepcialOffersRibbon = this.merchCard.locator('.special-offers-ribbon'); + this.sepcialOffersTitleH4 = this.sepcialOffers.locator('h5[slot="detail-m"]'); + this.sepcialOffersTitleH5 = this.sepcialOffers.locator('h4[slot="body-xss"]'); + this.sepcialOffersTitleH3 = this.sepcialOffers.locator('h3[slot="heading-xs"]'); - this.sepcialOffersDescription1 = this.sepcialOffers.locator('.consonant-SpecialOffers-description').nth(0); - this.sepcialOffersDescription2 = this.sepcialOffers.locator('.consonant-SpecialOffers-description').nth(1); + this.sepcialOffersDescription1 = this.sepcialOffers.locator('div[slot="body-xs"] p').nth(1); + this.sepcialOffersDescription2 = this.sepcialOffers.locator('div[slot="body-xs"] p').nth(2); - this.sepcialOffersDescription3 = this.sepcialOffers.locator('.consonant-SpecialOffers-description').nth(2); + this.sepcialOffersDescription3 = this.sepcialOffers.locator('div[slot="body-xs"] p').nth(3); this.sepcialOffersLinkText3 = this.sepcialOffersDescription3.locator('a').nth(0); this.seeTermsTextLink = this.merchCard.locator('a:has-text("See terms")'); // merch-card plans locators - this.productIcon = this.plans.locator('.consonant-MerchCard-ProductIcon'); - this.plansRibbon = this.plans.locator('.consonant-PlansCard-ribbon'); - this.plansCardTitleH3 = this.plans.locator('h3.consonant-PlansCard-title'); - this.plansCardTitleH5 = this.plans.locator('h5.consonant-PlansCard-title'); - this.plansCardDescription2 = this.plans.locator('.consonant-PlansCard-description').nth(1); + //this.productIcon = this.plans.locator('#shadow-root div.icons'); + this.productIcon = this.plans.locator('img'); + this.plansRibbon = this.plans.locator('.plans-ribbon'); + this.plansCardTitleH3 = this.plans.locator('h3[slot="heading-xs"]'); + this.plansCardTitleH5 = this.plans.locator('h5[slot="detail-m"]'); + this.plansCardDescription2 = this.plans.locator('div[slot="body-xs"] p').nth(2); this.seePlansTextLink = this.merchCard.locator('a:has-text("See plan & pricing details")'); // merch-card footer sections - this.footer = this.merchCard.locator('.consonant-CardFooter') - this.footerCheckbox = this.merchCard.locator('.checkbox-container .checkmark') - this.footerCheckboxLabel = this.merchCard.locator('.checkbox-container .checkbox-label') - this.secureTransactionIcon = this.merchCard.locator('.secure-transaction-icon') - this.secureTransactionLabel = this.merchCard.locator('.secure-transaction-label') + this.footer = this.merchCard.locator('div[slot="footer"]'); + this.footerCheckbox = this.page.locator('#stock-checkbox input[type="checkbox"]'); + this.footerCheckboxLabel = this.merchCard.locator('#stock-checkbox'); + this.secureTransactionIcon = this.merchCard.locator('.secure-transaction-icon'); + this.secureTransactionLabel = this.merchCard.locator('.secure-transaction-label'); this.footerOutlineButton = this.merchCard.locator('a.con-button.outline'); this.footerBlueButton = this.merchCard.locator('a.con-button.blue').nth(0); this.footerBlueButton2 = this.merchCard.locator('a.con-button.blue').nth(1); @@ -68,13 +70,13 @@ export default class Merchcard { // merch-card attributes this.attributes = { 'segmentRibbon': { - 'style': 'background-color: rgb(237, 204, 45); color: rgb(0, 0, 0);', + 'style': 'background-color: #EDCC2D; color: #000000; ', }, 'specialOfferRibbon': { - 'style': 'background-color: rgb(246, 141, 46); color: rgb(0, 0, 0);', + 'style': 'background-color: #F68D2E; color: #000000; ', }, 'plansRibbon': { - 'style': 'background-color: rgb(246, 141, 46); color: rgb(0, 0, 0);', + 'style': 'background-color: #EDCC2D; color: #000000; ', }, }; } diff --git a/tests/milo/merchcard.block.test.js b/tests/milo/merchcard.block.test.js index 5778b5bb..2fe1739c 100644 --- a/tests/milo/merchcard.block.test.js +++ b/tests/milo/merchcard.block.test.js @@ -98,6 +98,7 @@ test.describe('Milo Modal feature test suite', () => { await expect(await merchCard.sepcialOffers).toBeVisible(); await expect(await merchCard.sepcialOffersImage).toBeVisible(); + //await expect(await merchCard.sepcialOffersTitleH4).toBeVisible(); await expect(await merchCard.sepcialOffersTitleH4).toContainText(data.titleH4); await expect(await merchCard.sepcialOffersTitleH3).toContainText(data.titleH3); @@ -128,7 +129,7 @@ test.describe('Milo Modal feature test suite', () => { await expect(await merchCard.sepcialOffersRibbon).toBeVisible(); await expect(await merchCard.sepcialOffersRibbon).toContainText(data.badgeText); - await expect(await merchCard.sepcialOffersTitleH4).toContainText(data.titleH4); + //await expect(await merchCard.sepcialOffersTitleH4).toContainText(data.titleH4); await expect(await merchCard.sepcialOffersTitleH3).toContainText(data.titleH3); await expect(await merchCard.sepcialOffersDescription2).toContainText(data.description); @@ -210,7 +211,8 @@ test.describe('Milo Modal feature test suite', () => { }); // Test 6 : Merch Card (plans) with secure - test(`${features[6].name},${features[6].tags}`, async ({ page, baseURL }) => { + // Note: skipping the test as there were failures, informed the team + test.skip(`${features[6].name},${features[6].tags}`, async ({ page, baseURL }) => { console.info(`[Test Page]: ${baseURL}${features[6].path}`); const data = features[6].data; @@ -256,7 +258,8 @@ test.describe('Milo Modal feature test suite', () => { }); // Test 6 : Merch Card (plans, secure) with badge - test(`${features[7].name},${features[7].tags}`, async ({ page, baseURL }) => { + // Note: skipping the test as there were failures, informed the team + test.skip(`${features[7].name},${features[7].tags}`, async ({ page, baseURL }) => { console.info(`[Test Page]: ${baseURL}${features[7].path}`); const data = features[7].data; From 7cb650df907133db48331a36ee0addc76b0ce2d6 Mon Sep 17 00:00:00 2001 From: Dan Chivescu Date: Tue, 28 Nov 2023 18:03:27 +0200 Subject: [PATCH 20/53] [MWPW-139561] FEDS to Milo: Run FEDS tests for every Milo PR when label is added (#215) [MWPW-139561] FEDS to Milo - critical components checks --- features/milo/breadcrumbs.block.spec.js | 33 ++++++ features/milo/footer.block.spec.js | 26 +++++ features/milo/header.block.spec.js | 12 +++ tests/milo/breadcrumbs.block.test.js | 104 +++++++++++++++++++ tests/milo/footer.block.test.js | 132 ++++++++++++++++++++++++ tests/milo/header.block.test.js | 42 ++++++++ 6 files changed, 349 insertions(+) create mode 100644 features/milo/breadcrumbs.block.spec.js create mode 100644 features/milo/footer.block.spec.js create mode 100644 features/milo/header.block.spec.js create mode 100644 tests/milo/breadcrumbs.block.test.js create mode 100644 tests/milo/footer.block.test.js create mode 100644 tests/milo/header.block.test.js diff --git a/features/milo/breadcrumbs.block.spec.js b/features/milo/breadcrumbs.block.spec.js new file mode 100644 index 00000000..4a3f6b3d --- /dev/null +++ b/features/milo/breadcrumbs.block.spec.js @@ -0,0 +1,33 @@ +module.exports = { + name: 'Breadcrumbs Component', + features: [ + { + name: '@FEDS-Breadcrumbs-With-Base', + path: [ + '/drafts/nala/blocks/breadcrumbs/feds-breadcrumbs-with-base', + ], + tags: '@milo @feds @breadcrumbs @smoke @regression', + }, + { + name: '@FEDS-Breadcrumbs-From-Document', + path: [ + '/drafts/nala/blocks/breadcrumbs/feds-breadcrumbs-from-document', + ], + tags: '@milo @feds @breadcrumbs @smoke @regression', + }, + { + name: '@FEDS-Breadcrumbs-Hidden-Links', + path: [ + '/drafts/nala/blocks/breadcrumbs/feds-breadcrumbs-hidden-links', + ], + tags: '@milo @feds @breadcrumbs @smoke @regression', + }, + { + name: '@FEDS-Breadcrumbs-No-Hidden-Links', + path: [ + '/drafts/nala/blocks/breadcrumbs/feds-breadcrumbs-no-hidden-links', + ], + tags: '@milo @feds @breadcrumbs @smoke @regression', + }, + ], +}; diff --git a/features/milo/footer.block.spec.js b/features/milo/footer.block.spec.js new file mode 100644 index 00000000..47db4828 --- /dev/null +++ b/features/milo/footer.block.spec.js @@ -0,0 +1,26 @@ +module.exports = { + name: 'Footer Block', + features: [ + { + name: '@FEDS-Default-Footer', + path: [ + '/drafts/nala/blocks/footer/feds-default-footer', + ], + tags: '@milo @feds @footer @smoke @regression', + }, + { + name: '@FEDS-Skinny-Footer', + path: [ + '/drafts/nala/blocks/footer/feds-skinny-footer', + ], + tags: '@milo @feds @footer @smoke @regression', + }, + { + name: '@FEDS-Privacy-Footer', + path: [ + '/drafts/nala/blocks/footer/feds-privacy-footer', + ], + tags: '@milo @feds @footer @smoke @regression', + }, + ], +}; diff --git a/features/milo/header.block.spec.js b/features/milo/header.block.spec.js new file mode 100644 index 00000000..e1682be6 --- /dev/null +++ b/features/milo/header.block.spec.js @@ -0,0 +1,12 @@ +module.exports = { + name: 'Header Block', + features: [ + { + name: '@FEDS-Header-Checks', + path: [ + '/drafts/nala/blocks/header/feds-header-page', + ], + tags: '@milo @feds @header @smoke @regression', + }, + ], +}; diff --git a/tests/milo/breadcrumbs.block.test.js b/tests/milo/breadcrumbs.block.test.js new file mode 100644 index 00000000..bb55cf2f --- /dev/null +++ b/tests/milo/breadcrumbs.block.test.js @@ -0,0 +1,104 @@ +/* eslint-disable import/named */ +/* eslint-disable no-await-in-loop */ +/* eslint-disable import/extensions */ +import { expect, test } from '@playwright/test'; +import { features } from '../../features/milo/breadcrumbs.block.spec.js'; +import FedsHeader from '../../selectors/feds/feds.header.page.js'; + +test.describe('Breadcrumbs Component Test Suite', () => { + // FEDS Breadcrumbs-With-Base Checks: + test(`${features[0].name}, ${features[0].tags}`, async ({ page, baseURL }) => { + const Header = new FedsHeader(page); + console.info(`[FEDSInfo] Checking page: ${baseURL}${features[0].path}`); + + await test.step('Navigate to FEDS Breadcrumbs-With-Base page', async () => { + await page.goto(`${baseURL}${features[0].path}`); + await page.waitForLoadState('domcontentloaded'); + await expect(page).toHaveURL(`${baseURL}${features[0].path}`); + }); + + await test.step('Check breadcrumbs structure on current page', async () => { + // Wait for FEDS GNAV to be visible: + await Header.mainNavContainer.waitFor({ state: 'visible', timeout: 10000 }); + // Check breadcrumbs is displayed: + await expect(Header.breadcrumbContainer).toBeVisible(); + // Check breadcrumbs structure & content: + await expect(Header.breadcrumbElems).toHaveCount(5); + let breadcrumbs = await Header.breadcrumbContainer.textContent(); + breadcrumbs = breadcrumbs.replace(/ /g, '').replace(/(\r\n|\n|\r)/gm, ''); + expect(breadcrumbs).toEqual('HomeProductsPhotoshopEducationBreadcrumbsWithBase'); + }); + }); + + // FEDS Breadcrumbs-From-Document checks: + test(`${features[1].name}, ${features[1].tags}`, async ({ page, baseURL }) => { + const Header = new FedsHeader(page); + console.info(`[FEDSInfo] Checking page: ${baseURL}${features[1].path}`); + + await test.step('Navigate to FEDS Breadcrumbs-From-Document page', async () => { + await page.goto(`${baseURL}${features[1].path}`); + await page.waitForLoadState('domcontentloaded'); + await expect(page).toHaveURL(`${baseURL}${features[1].path}`); + }); + + await test.step('Check breadcrumbs structure on current page', async () => { + // Wait for FEDS GNAV to be visible: + await Header.mainNavContainer.waitFor({ state: 'visible', timeout: 10000 }); + // Check breadcrumbs is displayed: + await expect(Header.breadcrumbContainer).toBeVisible(); + // Check breadcrumbs structure & content: + await expect(Header.breadcrumbElems).toHaveCount(5); + let breadcrumbs = await Header.breadcrumbContainer.textContent(); + breadcrumbs = breadcrumbs.replace(/ /g, '').replace(/(\r\n|\n|\r)/gm, ''); + expect(breadcrumbs).toEqual('HomeProductsPhotoshopEducationBreadcrumbsFromDocument'); + }); + }); + + // FEDS Breadcrumbs-Hidden-Links checks: + test(`${features[2].name}, ${features[2].tags}`, async ({ page, baseURL }) => { + const Header = new FedsHeader(page); + console.info(`[FEDSInfo] Checking page: ${baseURL}${features[2].path}`); + + await test.step('Navigate to FEDS Breadcrumbs-Hidden-Links page', async () => { + await page.goto(`${baseURL}${features[2].path}`); + await page.waitForLoadState('domcontentloaded'); + await expect(page).toHaveURL(`${baseURL}${features[2].path}`); + }); + + await test.step('Check breadcrumbs structure on current page', async () => { + // Wait for FEDS GNAV to be visible: + await Header.mainNavContainer.waitFor({ state: 'visible', timeout: 10000 }); + // Check breadcrumbs is displayed: + await expect(Header.breadcrumbContainer).toBeVisible(); + // Check breadcrumbs structure & content: + await expect(Header.breadcrumbElems).toHaveCount(4); + let breadcrumbs = await Header.breadcrumbContainer.textContent(); + breadcrumbs = breadcrumbs.replace(/ /g, '').replace(/(\r\n|\n|\r)/gm, ''); + expect(breadcrumbs).toEqual('nalablocksbreadcrumbsfedsbreadcrumbshiddenlinks'); + }); + }); + + // FEDS Breadcrumbs-No-Hidden-Links checks: + test(`${features[3].name}, ${features[3].tags}`, async ({ page, baseURL }) => { + const Header = new FedsHeader(page); + console.info(`[FEDSInfo] Checking page: ${baseURL}${features[3].path}`); + + await test.step('Navigate to FEDS Breadcrumbs-No-Hidden-Links page', async () => { + await page.goto(`${baseURL}${features[3].path}`); + await page.waitForLoadState('domcontentloaded'); + await expect(page).toHaveURL(`${baseURL}${features[3].path}`); + }); + + await test.step('Check breadcrumbs structure on current page', async () => { + // Wait for FEDS GNAV to be visible: + await Header.mainNavContainer.waitFor({ state: 'visible', timeout: 10000 }); + // Check breadcrumbs is displayed: + await expect(Header.breadcrumbContainer).toBeVisible(); + // Check breadcrumbs structure & content: + await expect(Header.breadcrumbElems).toHaveCount(5); + let breadcrumbs = await Header.breadcrumbContainer.textContent(); + breadcrumbs = breadcrumbs.replace(/ /g, '').replace(/(\r\n|\n|\r)/gm, ''); + expect(breadcrumbs).toEqual('draftsnalablocksbreadcrumbsfedsbreadcrumbsnohiddenlinks'); + }); + }); +}); diff --git a/tests/milo/footer.block.test.js b/tests/milo/footer.block.test.js new file mode 100644 index 00000000..7c22019e --- /dev/null +++ b/tests/milo/footer.block.test.js @@ -0,0 +1,132 @@ +/* eslint-disable import/named */ +/* eslint-disable no-await-in-loop */ +/* eslint-disable import/extensions */ +import { expect, test } from '@playwright/test'; +import { features } from '../../features/milo/footer.block.spec.js'; +import FedsFooter from '../../selectors/feds/feds.footer.page.js'; + +test.describe('Footer Block Test Suite', () => { + // FEDS Default Footer Checks: + test(`${features[0].name}, ${features[0].tags}`, async ({ page, baseURL }) => { + const Footer = new FedsFooter(page); + console.info(`[FEDSInfo] Checking page: ${baseURL}${features[0].path}`); + + await test.step('Navigate to FEDS Default Footer page', async () => { + await page.goto(`${baseURL}${features[0].path}`); + await page.waitForLoadState('domcontentloaded'); + await expect(page).toHaveURL(`${baseURL}${features[0].path}`); + }); + + await test.step('Check FEDS Default Footer critical elements', async () => { + // Scroll FEDS Footer into viewport: + await Footer.legalContainer.scrollIntoViewIfNeeded(); + // Wait for FEDS Footer to be visible: + await Footer.footerContainer.waitFor({ state: 'visible', timeout: 5000 }); + // Check FEDS Footer critical elements: + await expect(Footer.legalContainer).toBeVisible(); + await expect(Footer.socialContainer).toBeVisible(); + await expect(Footer.footerContainer).toBeVisible(); + await expect(Footer.changeRegionContainer).toBeVisible(); + // !Note: Footer featuredProducts not appearing in NALA. Possible BUG! + // await expect(Footer.featuredProductsContainer).toBeVisible(); + await expect(Footer.footerColumns).toHaveCount(5); + await expect(Footer.footerSections).toHaveCount(6); + await expect(Footer.footerHeadings).toHaveCount(6); + await expect(Footer.socialIcons).toHaveCount(4); + await expect(Footer.legalLinks).toHaveCount(5); + }); + + await test.step('Check ChangeRegion functionality', async () => { + await Footer.changeRegionButton.click(); + await expect(Footer.changeRegionModal).toBeVisible(); + await Footer.changeRegionCloseButton.click(); + await expect(Footer.changeRegionModal).not.toBeVisible(); + }); + }); + + // FEDS Skinny Footer Checks: + test(`${features[1].name}, ${features[1].tags}`, async ({ page, baseURL }) => { + const Footer = new FedsFooter(page); + console.info(`[FEDSInfo] Checking page: ${baseURL}${features[1].path}`); + + await test.step('Navigate to FEDS Skinny Footer page', async () => { + await page.goto(`${baseURL}${features[1].path}`); + await page.waitForLoadState('domcontentloaded'); + await expect(page).toHaveURL(`${baseURL}${features[1].path}`); + }); + + await test.step('Check FEDS Skinny Footer critical elements', async () => { + // Scroll FEDS Footer into viewport: + await Footer.legalContainer.scrollIntoViewIfNeeded(); + // Wait for FEDS Footer to be visible: + await Footer.footerContainer.waitFor({ state: 'visible', timeout: 5000 }); + // Check FEDS Footer critical elements: + await expect(Footer.legalContainer).toBeVisible(); + await expect(Footer.socialContainer).toBeVisible(); + await expect(Footer.footerContainer).toBeVisible(); + await expect(Footer.changeRegionContainer).toBeVisible(); + + await expect(Footer.featuredProducts).toHaveCount(0); + await expect(Footer.featuredProductsContainer).not.toBeVisible(); + + await expect(Footer.legalLinks).toHaveCount(5); + await expect(Footer.socialIcons).toHaveCount(4); + + await expect(Footer.footerColumns).toHaveCount(0); + await expect(Footer.footerSections).toHaveCount(0); + await expect(Footer.footerHeadings).toHaveCount(0); + await expect(Footer.footerColumns).not.toBeVisible(); + await expect(Footer.footerSections).not.toBeVisible(); + await expect(Footer.footerHeadings).not.toBeVisible(); + }); + + await test.step('Check ChangeRegion functionality', async () => { + await Footer.changeRegionButton.click(); + await expect(Footer.changeRegionModal).toBeVisible(); + await Footer.changeRegionCloseButton.click(); + await expect(Footer.changeRegionModal).not.toBeVisible(); + }); + }); + + // FEDS Privacy Footer Checks: + test(`${features[2].name}, ${features[2].tags}`, async ({ page, baseURL }) => { + const Footer = new FedsFooter(page); + console.info(`[FEDSInfo] Checking page: ${baseURL}${features[2].path}`); + + await test.step('Navigate to FEDS Privacy Footer page', async () => { + await page.goto(`${baseURL}${features[2].path}`); + await page.waitForLoadState('domcontentloaded'); + await expect(page).toHaveURL(`${baseURL}${features[2].path}`); + }); + + await test.step('Check FEDS Privacy Footer critical elements', async () => { + // Scroll FEDS Footer into viewport: + await Footer.legalContainer.scrollIntoViewIfNeeded(); + // Wait for FEDS Footer to be visible: + await Footer.footerContainer.waitFor({ state: 'visible', timeout: 5000 }); + // Check FEDS Footer critical elements: + await expect(Footer.legalContainer).toBeVisible(); + await expect(Footer.socialContainer).toBeVisible(); + await expect(Footer.footerContainer).toBeVisible(); + await expect(Footer.changeRegionContainer).toBeVisible(); + await expect(Footer.featuredProductsContainer).toBeVisible(); + + await expect(Footer.footerColumns).toHaveCount(5); + await expect(Footer.footerSections).toHaveCount(6); + await expect(Footer.footerHeadings).toHaveCount(6); + await expect(Footer.featuredProducts).toHaveCount(3); + + await expect(Footer.legalSections).toHaveCount(2); + await expect(Footer.socialIcons).toHaveCount(4); + await expect(Footer.legalLinks).toHaveCount(5); + }); + + await test.step('Check ChangeRegion functionality', async () => { + await Footer.changeRegionButton.click(); + await expect(Footer.changeRegionDropDown).toBeVisible(); + await expect(Footer.changeRegionModal).not.toBeVisible(); + await Footer.changeRegionButton.click(); + await expect(Footer.changeRegionDropDown).not.toBeVisible(); + }); + }); +}); diff --git a/tests/milo/header.block.test.js b/tests/milo/header.block.test.js new file mode 100644 index 00000000..c72f4b78 --- /dev/null +++ b/tests/milo/header.block.test.js @@ -0,0 +1,42 @@ +/* eslint-disable import/named */ +/* eslint-disable no-await-in-loop */ +/* eslint-disable import/extensions */ +import { expect, test } from '@playwright/test'; +import { features } from '../../features/milo/header.block.spec.js'; +import FedsHeader from '../../selectors/feds/feds.header.page.js'; + +test.describe('Header Block Test Suite', () => { + // FEDS Default Header Checks: + test(`${features[0].name}, ${features[0].tags}`, async ({ page, baseURL }) => { + const Header = new FedsHeader(page); + console.info(`[FEDSInfo] Checking page: ${baseURL}${features[0].path}`); + + await test.step('Navigate to FEDS HEADER page', async () => { + await page.goto(`${baseURL}${features[0].path}`); + await page.waitForLoadState('domcontentloaded'); + await expect(page).toHaveURL(`${baseURL}${features[0].path}`); + }); + + await test.step('Check HEADER block content', async () => { + // Wait for FEDS GNAV to be visible: + await Header.mainNavContainer.waitFor({ state: 'visible', timeout: 5000 }); + // Check HEADER block content: + await expect(Header.mainNavLogo).toBeVisible(); + await expect(Header.searchIcon).toBeVisible(); + await expect(Header.signInButton).toBeVisible(); + }); + + await test.step('Check HEADER search component', async () => { + await Header.openSearchBar(); + await Header.closeSearchBar(); + }); + + await test.step('Check HEADER block mega menu component', async () => { + await Header.megaMenuToggle.waitFor({ state: 'visible', timeout: 5000 }); + await Header.megaMenuToggle.click(); + await expect(Header.megaMenuContainer).toBeVisible(); + await Header.megaMenuToggle.click(); + await expect(Header.megaMenuContainer).not.toBeVisible(); + }); + }); +}); From 8e01f496f541eaa4cd443c895b36c88ccf1dd375 Mon Sep 17 00:00:00 2001 From: Jacky Sun <67350368+JackySun9@users.noreply.github.com> Date: Tue, 28 Nov 2023 11:31:21 -0800 Subject: [PATCH 21/53] Add visual test for CAAS (#213) * add test for quiz and result pages * add test for quiz and result pages * add test for quiz and result pages * add POC for analytics test * update analytics tests and envs * result envs * update analytics only on firefox * add dynamic tests * add dynamic test for quiz page * update quiz test * update test structure * add test for quiz and result pages * add POC for analytics test * update analytics tests and envs * result envs * update analytics only on firefox * add dynamic tests * add dynamic test for quiz page * update quiz test * update test structure * update uar tests to new format * update uar tests * move everything to uar folder * add dependency for js-yaml * update test according to latest comments * update test according to latest comments * update tests according to the latest comments * add uar config * add analytics for uar * update according to feedbacks * update tags * add @cc tag * update according to feedbacks * add dynamic tests for uar * update according to review comments * fix some typos * update according to review comments * merge console log info * add UI screenshots for UAR * move view point to test * update according to feedback * add analytics test for UAR * update validation and uar libs * update libs * update by feedback * update some config and tests * update some config and tests * update test content path to common path * update analytics tests * fix test failures caused by test code * fix test failures * fix test failures * add visual test for CAAS with two pages * update according to feedbacks * update report in config file --------- Co-authored-by: xiasun Co-authored-by: Aaron Mauchley --- configs/visual.config.js | 9 +- .../visual-compare/caas/cards.block.spec.js | 89 +++++++++++++++++++ libs/webutil.js | 24 +++++ visual-compare-tests/caas/cards.vc.test.js | 25 ++++++ 4 files changed, 143 insertions(+), 4 deletions(-) create mode 100644 features/visual-compare/caas/cards.block.spec.js create mode 100644 visual-compare-tests/caas/cards.vc.test.js diff --git a/configs/visual.config.js b/configs/visual.config.js index 82c29426..70fc3a37 100644 --- a/configs/visual.config.js +++ b/configs/visual.config.js @@ -6,8 +6,9 @@ const { devices } = require('@playwright/test'); * @type {import('@playwright/test').PlaywrightTestConfig} */ const config = { - testDir: './tests/milo', // TODO: Switch to ./tests once baseURL conditional checks have been made on individual tests - outputDir: './test-results', + testDir: '../visual-compare-tests', // TODO: Switch to ./tests once baseURL conditional checks have been made on individual tests + outputDir: '../test-results', + globalSetup: '../global.setup.js', /* Maximum time one test can run for. */ timeout: 30 * 1000, /** @@ -33,8 +34,8 @@ const config = { workers: process.env.CI ? 2 : undefined, /* Reporter to use. See https://playwright.dev/docs/test-reporters */ reporter: process.env.CI - ? [['github'], ['./utils/reporters/json-reporter.js'], ['./utils/reporters/api-reporter.js']] - : [['html', { outputFolder: 'test-html-results' }]], + ? [['github'], ['list'], ['../utils/reporters/base-reporter.js']] + : [['html', { outputFolder: 'test-html-results' }], ['list'], ['../utils/reporters/base-reporter.js']], /* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */ use: { /* Maximum time each action such as `click()` can take. Defaults to 0 (no limit). */ diff --git a/features/visual-compare/caas/cards.block.spec.js b/features/visual-compare/caas/cards.block.spec.js new file mode 100644 index 00000000..fa6ba7a6 --- /dev/null +++ b/features/visual-compare/caas/cards.block.spec.js @@ -0,0 +1,89 @@ +module.exports = { + name: 'Caas Visual Comparison', + features: [ + { + tcid: '0', + name: '@caas-visual-onehalfcollection-desktop', + stable: '/fragments/caas/test-pages/onehalfcollection', + beta: '/fragments/caas/test-pages/onehalfcollection?caasver=beta', + tags: '@caas-visual-onehalfcollection-desktop, @caas-visual-desktop, @visual, @visual-smoke, @visual-regression', + }, + { + tcid: '1', + name: '@caas-visual-threefourthscollection-desktop', + stable: '/fragments/caas/test-pages/threefourthscollection', + beta: '/fragments/caas/test-pages/threefourthscollection?caasver=beta', + tags: '@caas-visual-threefourthscollection-desktop, @caas-visual-desktop, @visual, @visual-smoke, @visual-regression', + }, + { + tcid: '2', + name: '@caas-visual-halfheightcollection-desktop', + stable: '/fragments/caas/test-pages/halfheightcollection', + beta: '/fragments/caas/test-pages/halfheightcollection?caasver=beta', + tags: '@caas-visual-halfheightcollection-desktop, @caas-visual-desktop, @visual, @visual-smoke, @visual-regression', + }, + { + tcid: '3', + name: '@caas-visual-fullwidthcollection-desktop', + stable: '/fragments/caas/test-pages/textcardcollection', + beta: '/fragments/caas/test-pages/textcardcollection?caasver=beta', + tags: '@caas-visual-fullwidthcollection-desktop, @caas-visual-desktop, @visual, @visual-smoke, @visual-regression', + }, + { + tcid: '4', + name: '@caas-visual-onehalfcollection-tablet', + stable: '/fragments/caas/test-pages/onehalfcollection', + beta: '/fragments/caas/test-pages/onehalfcollection?caasver=beta', + tags: '@caas-visual-onehalfcollection-tablet, @caas-visual-tablet, @visual, @visual-smoke, @visual-regression', + }, + { + tcid: '5', + name: '@caas-visual-threefourthscollection-tablet', + stable: '/fragments/caas/test-pages/threefourthscollection', + beta: '/fragments/caas/test-pages/threefourthscollection?caasver=beta', + tags: '@caas-visual-threefourthscollection-tablet, @caas-visual-tablet, @visual, @visual-smoke, @visual-regression', + }, + { + tcid: '6', + name: '@caas-visual-halfheightcollection-tablet', + stable: '/fragments/caas/test-pages/halfheightcollection', + beta: '/fragments/caas/test-pages/halfheightcollection?caasver=beta', + tags: '@caas-visual-halfheightcollection-tablet, @caas-visual-tablet, @visual, @visual-smoke, @visual-regression', + }, + { + tcid: '7', + name: '@caas-visual-fullwidthcollection-tablet', + stable: '/fragments/caas/test-pages/textcardcollection', + beta: '/fragments/caas/test-pages/textcardcollection?caasver=beta', + tags: '@caas-visual-fullwidthcollection-tablet, @caas-visual-tablet, @visual, @visual-smoke, @visual-regression', + }, + { + tcid: '8', + name: '@caas-visual-onehalfcollection-phone', + stable: '/fragments/caas/test-pages/onehalfcollection', + beta: '/fragments/caas/test-pages/onehalfcollection?caasver=beta', + tags: '@caas-visual-onehalfcollection-phone, @caas-visual-phone, @visual, @visual-smoke, @visual-regression', + }, + { + tcid: '9', + name: '@caas-visual-threefourthscollection-phone', + stable: '/fragments/caas/test-pages/threefourthscollection', + beta: '/fragments/caas/test-pages/threefourthscollection?caasver=beta', + tags: '@caas-visual-threefourthscollection-phone, @caas-visual-phone, @visual, @visual-smoke, @visual-regression', + }, + { + tcid: '10', + name: '@caas-visual-halfheightcollection-phone', + stable: '/fragments/caas/test-pages/halfheightcollection', + beta: '/fragments/caas/test-pages/halfheightcollection?caasver=beta', + tags: '@caas-visual-halfheightcollection-phone, @caas-visual-phone, @visual, @visual-smoke, @visual-regression', + }, + { + tcid: '11', + name: '@caas-visual-fullwidthcollection-phone', + stable: '/fragments/caas/test-pages/textcardcollection', + beta: '/fragments/caas/test-pages/textcardcollection?caasver=beta', + tags: '@caas-visual-fullwidthcollection-phone, @caas-visual-phone, @visual, @visual-smoke, @visual-regression', + }, + ], +}; diff --git a/libs/webutil.js b/libs/webutil.js index c17ed981..c451441a 100644 --- a/libs/webutil.js +++ b/libs/webutil.js @@ -3,6 +3,7 @@ /* eslint-disable max-len */ // eslint-disable-next-line import/no-import-module-exports import { expect } from '@playwright/test'; +import { getComparator } from 'playwright-core/lib/utils'; const fs = require('fs'); // eslint-disable-next-line import/no-extraneous-dependencies @@ -290,4 +291,27 @@ exports.WebUtil = class WebUtil { await this.page.setViewportSize({ width, height }); await this.page.screenshot({ path: `${folderPath}/${fileName}`, fullPage: true }); } + + async takeScreenshotAndCompare(urlA, urlB, folderPath, fileName) { + console.info(`[Test Page]: ${urlA}`); + await this.page.goto(urlA); + await this.page.waitForTimeout(3000); + await this.page.screenshot({ path: `${folderPath}/${fileName}-a.png`, fullPage: true }); + const baseImage = fs.readFileSync(`${folderPath}/${fileName}-a.png`); + + console.info(`[Test Page]: ${urlB}`); + await this.page.goto(urlB); + await this.page.waitForTimeout(3000); + await this.page.waitForSelector('.feds-footer-privacyLink'); + await this.page.screenshot({ path: `${folderPath}/${fileName}-b.png`, fullPage: true }); + const currImage = fs.readFileSync(`${folderPath}/${fileName}-b.png`); + + const comparator = getComparator('image/png'); + const diffImage = comparator(baseImage, currImage); + + if (diffImage) { + fs.writeFileSync(`${folderPath}/${fileName}-diff.png`, diffImage.diff); + console.info('Differences found'); + } + } }; diff --git a/visual-compare-tests/caas/cards.vc.test.js b/visual-compare-tests/caas/cards.vc.test.js new file mode 100644 index 00000000..29a2a253 --- /dev/null +++ b/visual-compare-tests/caas/cards.vc.test.js @@ -0,0 +1,25 @@ +/* eslint-disable import/named */ +import { features } from '../../features/visual-compare/caas/cards.block.spec.js'; +import { WebUtil } from '../../libs/webutil.js'; + +const { test } = require('@playwright/test'); + +// Global declarations +let webUtil; + +test.describe('Milo Caas block visual comparison test suite', () => { + // before each test block + test.beforeEach(async ({ page }) => { + webUtil = new WebUtil(page); + }); + + // eslint-disable-next-line no-restricted-syntax + for (const feature of features) { + // eslint-disable-next-line no-loop-func + test(`${feature.name},${feature.tags}`, async ({ baseURL }) => { + const folderPath = 'screenshots/caas'; + // eslint-disable-next-line max-len + await webUtil.takeScreenshotAndCompare(baseURL + feature.stable, baseURL + feature.beta, folderPath, feature.name); + }); + } +}); From 1eb713226da1ca9d3a4db3ab01a6a7eef581a6fb Mon Sep 17 00:00:00 2001 From: sigadamramesh <130433161+sigadamvenkata@users.noreply.github.com> Date: Fri, 1 Dec 2023 21:36:46 +0530 Subject: [PATCH 22/53] PR for Offer selector Tool test cases which cover given use cases (#214) * config, env, folder structure setup for CC config, env, folder structure setup for CC onboarding * PR 126 - Review comments changes PR 126 - Review comments changes * PR 126 asked changes PR 126 asked changes * Update febpub.sanity.js * Update fedpub.sanity.js * Update febpub.selectors.js * Update febpub.test.js * Text block legal, link-farm variations automation Text block legal, link-farm variations automation * removed unwanted comma as per comments removed unwanted comma as per comments * moved the new case details to new line as per review comments moved the new case details to new line as per review comments * Jarvis feature Automated test cases MWPW-122175 : jarvis feature automation test cases * OST Price formats (single license, month/year subscriptions, strikethrough preice, student license, Ucv3 checkout cases automation OST Price formats (single license, month/year subscriptions, strikethrough price, student license, Ucv3 (email, segmentation, upsell etc) checkout flows automation. Jira: https://jira.corp.adobe.com/browse/MWPW-135460 * javis feature file removed * spec javis removed * test javis removed * Update ostprices.spec.js * Update ostprices.page.js updated file with given changes * Update ostprices.test.js added required changes --------- Co-authored-by: Dan Chivescu <106924778+chadsunvice@users.noreply.github.com> Co-authored-by: Santoshkumar Nateekar Co-authored-by: Aaron Mauchley --- features/cc/ostprices.spec.js | 65 ++++++++++ selectors/cc/ostprices.page.js | 55 +++++++++ tests/cc/ostprices.test.js | 220 +++++++++++++++++++++++++++++++++ 3 files changed, 340 insertions(+) create mode 100644 features/cc/ostprices.spec.js create mode 100644 selectors/cc/ostprices.page.js create mode 100644 tests/cc/ostprices.test.js diff --git a/features/cc/ostprices.spec.js b/features/cc/ostprices.spec.js new file mode 100644 index 00000000..e9295fd4 --- /dev/null +++ b/features/cc/ostprices.spec.js @@ -0,0 +1,65 @@ +module.exports = { + name: 'ostprices', + features: [ + { + tcid: '0', + name: '@ost-currencyformat-price-buyemailcta', + path: '/drafts/Automation-PW/OST-prices/marquee-price?georouting=off', + tags: '@cc @cc-ost @cc-pricewithcta', + }, + { + tcid: '1', + name: '@ost-ccallapps-price-buysegmentcta', + path: '/drafts/Automation-PW/OST-prices/cc-monty-year-ucv3?georouting=off', + tags: '@cc @cc-ost @cc-allappswithcta', + }, + { + tcid: '2', + name: '@ost-student-price-buycta', + path: '/drafts/Automation-PW/OST-prices/ste-prices?georouting=off', + tags: '@cc @cc-ost @cc-steprices', + }, + { + tcid: '3', + name: '@ost-strike-throughprice-buycta', + path: '/drafts/Automation-PW/OST-prices/strike-through-prices?georouting=off', + tags: '@cc @cc-ost @cc-strikethroughprice', + }, + { + tcid: '4', + name: '@ost-month-year-prices-buycta', + path: '/drafts/Automation-PW/OST-prices/photoshop-prices?georouting=off', + tags: '@cc @cc-ost @cc-montandyearprices', + }, + { + tcid: '5', + name: '@ost-jp-currencyformat-price-buyemailcta', + path: '/jp/drafts/Automation-PW/OST-prices/marquee-price?georouting=off', + tags: '@cc @cc-ost @cc-jp-pricewithcta', + }, + { + tcid: '6', + name: '@ost-jp-ccallapps-price-buysegmentcta', + path: '/jp/drafts/Automation-PW/OST-prices/cc-monty-year-ucv3?georouting=off', + tags: '@cc @cc-ost @cc-jp-allappswithcta', + }, + { + tcid: '7', + name: '@ost-jp-student-price-buycta', + path: '/jp/drafts/Automation-PW/OST-prices/ste-prices?georouting=off', + tags: '@cc @cc-ost @cc-jp-steprices', + }, + { + tcid: '8', + name: '@ost-jp-strike-throughprice-buycta', + path: '/jp/drafts/Automation-PW/OST-prices/strike-through-prices?georouting=off', + tags: '@cc @cc-ost @cc-jp-strikethroughprice', + }, + { + tcid: '9', + name: '@ost-jp-month-year-prices-buycta', + path: '/jp/drafts/Automation-PW/OST-prices/photoshop-prices?georouting=off', + tags: '@cc @cc-ost @cc-jp-monthyearprices', + }, + ], +}; diff --git a/selectors/cc/ostprices.page.js b/selectors/cc/ostprices.page.js new file mode 100644 index 00000000..4f156347 --- /dev/null +++ b/selectors/cc/ostprices.page.js @@ -0,0 +1,55 @@ +import { expect } from '@playwright/test'; +import { WebUtil } from '../../libs/webutil.js'; + +export default class ostprices { + constructor(page) { + this.page = page; + // ccsubsciton currency format, price and buynow email CTA check out flows in US and Jp pages + this.productname = page.locator('//em[contains(text(),"Creative cloud all apps :")]'); + this.uscountrycurrencysymbol = page.locator('.price-currency-symbol'); + this.pricebeforedelimiter = page.locator('.price-integer'); + this.priceafterdelimiter = page.locator('.price-decimals'); + this.licensecommitment = page.locator('.price-recurrence'); + this.numberoflicenses = page.locator('.price-unit-type'); + this.buynowcta = page.locator('//a[@daa-ll="Buy now-1|Make Create Amazing"]'); + this.price = page.locator('//span[@class="price"]'); + this.jpproductprice = page.locator('//span[@aria-label="10,280 円 毎月 ライセンスごと"]'); + this.jpcountrycurrencysymbol = page.locator('.price-currency-symbol'); + // cc all apps price with segment CTA checkout + this.productname_1 = page.locator('//p[contains(text(),"CC Starting from(month) : ")]'); + this.cc_pricebeforedelimiter = page.locator('.price-integer').first(); + this.cc_priceafterdelimiter = page.locator('.price-decimals').first(); + this.cc_licensecommitment = page.locator('.price-recurrence').first(); + this.cc_numberoflicenses = page.locator('.price-unit-type').first(); + this.productname_2 = page.locator('//p[contains(text(),"PS Purchase (year) : ")]'); + this.ps_pricebeforedelimiter = page.locator('.price-integer').last(); + this.ps_priceafterdelimiter = page.locator('.price-decimals').last(); + this.ps_licensecommitment = page.locator('.price-recurrence').last(); + this.ps_numberoflicenses = page.locator('.price-unit-type').last(); + this.cc_buynowcta = page.locator('//a[@daa-ll="Buy now-1|Generative AI.This c"]'); + this.cc_pricemonth_jp = page.locator('//span[@aria-label="5,891 円 毎月 ライセンスごと"]'); + this.ps_priceyear_jp = page.locator('//span[@aria-label="28,776 円 毎年 ライセンスごと"]'); + // Student teacher edition price checks + this.STEProductname = page.locator('h2#adobe-light-room'); + this.STE_LR_price = page.locator('//span[@aria-label="US$4.44 per month per license"]'); + this.STE_LR_JP_price = page.locator('//span[@aria-label="980 円 毎月 ライセンスごと"]'); + this.STEgetstarted_CTA = page.locator('//a[@daa-ll="Get started-1|Adobe Light room"]'); + // display of strike through prince, slection of bundle price for commerce store + this.producatname_3 = page.locator('h3#creative-cloud'); + this.pricelabel_actual = page.locator('//p[contains(text(),"Actual price : ")]'); + this.strikethroughproperty = page.locator('//span[@data-template="priceStrikethrough"]'); + this.strikethrouthprice = page.locator('//span[@aria-label="US$89.99 per month per license"]').first(); + this.strikethroughprice_jp_1 = page.locator('//span[@aria-label="9,346 円 毎月 ライセンスごと"]').first(); + this.pricelabel_now = page.locator('//p[contains(text(),"Now its: ")]'); + this.purchaseCTAbandle = page.locator('//a[@daa-ll="choose a plan-1|Actual price"]'); + this.strikethroughproductprice_jp = page.locator('//span[@aria-label="9,346 円 per month per license"]'); + // page has card layout with month , year prices and CTAs + this.headingdiscription = page.locator('//h3[@slot="heading-xs"]').first(); + this.headingdiscription2 = page.locator('//h3[@slot="heading-xs"]').last(); + this.firstcardheading = page.locator('//h3[contains(text(),"Individuals PS year subscription")]'); + this.individualPSpricemonth = page.locator('//span[@aria-label="US$22.99 per month per license"]'); + this.individualPSpriceyear = page.locator('//span[@aria-label="US$263.88 per year per license"]'); + this.individualPSpricemonth_jp = page.locator('//span[@aria-label="2,480 円 毎月 ライセンスごと"]'); + this.individualPSpriceyear_jp = page.locator('//span[@aria-label="26,160 円 毎年 ライセンスごと"]'); +} +}; diff --git a/tests/cc/ostprices.test.js b/tests/cc/ostprices.test.js new file mode 100644 index 00000000..423618a5 --- /dev/null +++ b/tests/cc/ostprices.test.js @@ -0,0 +1,220 @@ +import { expect, test } from '@playwright/test'; +import { features } from '../../features/cc/ostprices.spec.js'; +import Ostprices from '../../selectors/cc/ostprices.page.js'; + +let ost; +test.describe('test Offer selector tool price formats and checkout flows in US & Jp locale pages' , () => { + test.beforeEach(async ({ page }) => { + ost = new Ostprices(page); + }); + + test(`${features[0].name},${features[0].tags}`, async ({ page, baseURL }) => { + console.info(`[Test Page]: ${baseURL}${features[0].path}`); + await test.step('page marquee shows the CC price and CTA US locale', async () => { + await page.goto(`${baseURL}${features[0].path}`); + await page.waitForLoadState('domcontentloaded'); + await expect(page).toHaveURL(`${baseURL}${features[0].path}`); + }); + + await test.step('Test CC all apps price and UCv3 email checkout, buy button checks in marquee', async () => { + await page.waitForLoadState(); + await expect(await ost.productname).toBeTruthy(); + await expect(ost.uscountrycurrencysymbol).toBeTruthy(); + await expect(ost.price).toBeVisible(); + await expect(ost.buynowcta).toBeVisible(); + await expect(ost.pricebeforedelimiter).toBeVisible(); + await page.locator('//a[@daa-ll="Buy now-1|Make Create Amazing"]').click(); + await expect(page).toHaveURL(new RegExp('^https://commerce.adobe.com/store/')); + }); +}); + + test(`${features[1].name},${features[1].tags}`, async ({ page, baseURL }) => { + console.info(`[Test Page]: ${baseURL}${features[1].path}`); + await test.step('page checks with month and year CC subscription, checkout', async () => { + await page.goto(`${baseURL}${features[1].path}`); + await page.waitForLoadState('domcontentloaded'); + await expect(page).toHaveURL(`${baseURL}${features[1].path}`); + }); + + await test.step('Verify the month and year price display , CTA for UCv3 segment checkout destination', async () => { + await page.waitForLoadState(); + await expect(ost.productname_1).toBeTruthy(); + await expect(ost.uscountrycurrencysymbol).toBeTruthy(); + await expect(ost.cc_pricebeforedelimiter).toBeVisible(); + await expect(ost.cc_priceafterdelimiter).toBeVisible(); + await expect(ost.cc_licensecommitment).toBeVisible(); + await expect(ost.cc_numberoflicenses).toBeVisible(); + await expect(ost.productname_2).toBeTruthy(); + await expect(ost.uscountrycurrencysymbol).toBeTruthy(); + await expect(ost.ps_pricebeforedelimiter).toBeVisible(); + await expect(ost.ps_priceafterdelimiter).toBeVisible(); + await expect(ost.ps_licensecommitment).toBeVisible(); + await expect(ost.ps_numberoflicenses).toBeVisible(); + await page.locator('//a[@daa-ll="Buy now-1|Generative AI.This c"]').click(); + await expect(page).toHaveURL(new RegExp('^https://commerce.adobe.com/store/segmentation')); + }); +}); + + test(`${features[2].name},${features[2].tags}`, async ({ page, baseURL }) => { + console.info(`[Test Page]: ${baseURL}${features[2].path}`); + await test.step('Light room STE edition price display with email checkout cta destination', async () => { + await page.goto(`${baseURL}${features[2].path}`); + await page.waitForLoadState('domcontentloaded'); + await expect(page).toHaveURL(`${baseURL}${features[2].path}`); + }); + + await test.step('step-2: verify LR STU price and email CTA', async () => { + await page.waitForLoadState(); + await expect(ost.STEProductname).toBeTruthy(); + await expect(ost.uscountrycurrencysymbol).toBeTruthy(); + await expect(ost.STE_LR_price).toBeVisible(); + await page.locator('//a[@daa-ll="Get started-1|Adobe Light room"]').click(); + await expect(page).toHaveURL(new RegExp('^https://commerce.adobe.com/store/email')); + }); +}); + + test(`${features[3].name},${features[3].tags}`, async ({ page, baseURL }) => { + console.info(`[Test Page]: ${baseURL}${features[3].path}`); + await test.step('page authored with CC product strike through price', async () => { + await page.goto(`${baseURL}${features[3].path}`); + await page.waitForLoadState('domcontentloaded'); + await expect(page).toHaveURL(`${baseURL}${features[3].path}`); + }); + + await test.step('step-2: verify CC strike through prices are showup correctly with valid store bundle CTA destination', async () => { + await page.waitForLoadState(); + await expect(ost.producatname_3).toBeVisible(); + await expect(ost.uscountrycurrencysymbol).toBeTruthy(); + await expect(ost.pricelabel_actual).toBeVisible(); + await expect(ost.strikethroughproperty).toBeTruthy(); + await expect(ost.strikethrouthprice).toBeVisible(); + await expect(ost.pricelabel_now).toBeVisible(); + await expect(ost.purchaseCTAbandle).toBeVisible(); + await page.locator('//a[@daa-ll="choose a plan-1|Actual price"]').click(); + await expect(page).toHaveURL(new RegExp('^https://commerce.adobe.com/store/bundle')); + }); +}); + + test(`${features[4].name},${features[4].tags}`, async ({ page, baseURL }) => { + console.info(`[Test Page]: ${baseURL}${features[4].path}`); + await test.step('Product - photoshop month, year price with CTAs', async () => { + await page.goto(`${baseURL}${features[4].path}`); + await page.waitForLoadState('domcontentloaded'); + await expect(page).toHaveURL(`${baseURL}${features[4].path}`); + }); + + await test.step('step-2: Photoshop product month, year price with CTAs', async () => { + await page.waitForLoadState(); + await expect(ost.headingdiscription).toBeTruthy(); + await expect(ost.headingdiscription2).toBeTruthy(); + await expect(ost.firstcardheading).toBeVisible(); + await expect(ost.individualPSpricemonth).toBeVisible(); + await expect(ost.individualPSpriceyear).toBeVisible(); + await page.locator('//a[@class="con-button placeholder-resolved"]').first().click(); + await expect(page).toHaveURL(new RegExp('^https://commerce.adobe.com/store/')); + }); +}); + + test(`${features[5].name},${features[5].tags}`, async ({ page, baseURL }) => { + console.info(`[Test Page]: ${baseURL}${features[5].path}`); + await test.step('page marquee shows the CC price and CTA for JP', async () => { + await page.goto(`${baseURL}${features[5].path}`); + await page.waitForLoadState('domcontentloaded'); + await expect(page).toHaveURL(`${baseURL}${features[5].path}`); + }); + + await test.step('Test CC all apps price and UCv3 email checkout, buy button checks in marquee for JP', async () => { + await page.waitForLoadState(); + await expect(ost.productname).toBeVisible(); + await expect(ost.jpcountrycurrencysymbol).toBeVisible(); + await expect(ost.jpproductprice).toBeVisible(); + await page.locator('//a[@daa-ll="Buy now-1|Make Create Amazing"]').click(); + await expect(page).toHaveURL(new RegExp('^https://commerce.adobe.com/store/')); + await expect(page).toHaveURL(new RegExp('co=JP&lang=ja')); + }); +}); + + test(`${features[6].name},${features[6].tags}`, async ({ page, baseURL }) => { + console.info(`[Test Page]: ${baseURL}${features[6].path}`); + await test.step('product with month, year subscriptions in JP', async () => { + await page.goto(`${baseURL}${features[6].path}`); + await page.waitForLoadState('domcontentloaded'); + await expect(page).toHaveURL(`${baseURL}${features[6].path}`); + }); + + await test.step('JP locale monthly, year subscriptions', async () => { + await page.waitForLoadState(); + await expect(ost.productname_1).toBeVisible(); + await expect(ost.productname_2).toBeVisible(); + await expect(ost.cc_pricemonth_jp).toBeVisible(); + await expect(ost.ps_priceyear_jp).toBeVisible(); + await expect(ost.jpcountrycurrencysymbol).toBeTruthy(); + await page.locator('//a[@daa-ll="Buy now-1|Generative AI.This c"]').click(); + await expect(page).toHaveURL(new RegExp('^https://commerce.adobe.com/store/')); + await expect(page).toHaveURL(new RegExp('co=JP&lang=ja')); + }); +}); + + test(`${features[7].name},${features[7].tags}`, async ({ page, baseURL }) => { + console.info(`[Test Page]: ${baseURL}${features[7].path}`); + await test.step('page has JP STE prices for LR product', async () => { + await page.goto(`${baseURL}${features[7].path}`); + await page.waitForLoadState('domcontentloaded'); + await expect(page).toHaveURL(`${baseURL}${features[7].path}`); + }); + + await test.step('step-2: Verify STE price for Lighthouse in JP currency', async () => { + await page.waitForLoadState(); + await expect(ost.STEProductname).toBeTruthy(); + await expect(ost.jpcountrycurrencysymbol).toBeTruthy(); + await expect(ost.STE_LR_JP_price).toBeVisible(); + await page.locator('//a[@daa-ll="Get started-1|Adobe Light room"]').click(); + await expect(page).toHaveURL(new RegExp('^https://commerce.adobe.com/store/email')); + await expect(page).toHaveURL(new RegExp('co=JP&lang=ja')); + }); +}); + + test(`${features[8].name},${features[8].tags}`, async ({ page, baseURL }) => { + console.info(`[Test Page]: ${baseURL}${features[8].path}`); + await test.step('product with month, year subscriptions in JP', async () => { + await page.goto(`${baseURL}${features[8].path}`); + await page.waitForLoadState('domcontentloaded'); + await expect(page).toHaveURL(`${baseURL}${features[8].path}`); + }); + + await test.step('JP locale monthly, year subscriptions', async () => { + await page.waitForLoadState(); + await expect(ost.producatname_3).toBeVisible(); + await expect(ost.jpcountrycurrencysymbol).toBeTruthy(); + await expect(ost.pricelabel_actual).toBeVisible(); + await expect(ost.strikethroughproperty).toBeTruthy(); + await expect(ost.strikethroughprice_jp_1).toBeVisible(); + await expect(ost.pricelabel_now).toBeVisible(); + await expect(ost.purchaseCTAbandle).toBeVisible(); + await page.locator('//a[@daa-ll="choose a plan-1|Actual price"]').click(); + await expect(page).toHaveURL(new RegExp('^https://commerce.adobe.com/store/bundle')); + await expect(page).toHaveURL(new RegExp('co=JP&lang=ja')); + }); +}); + + test(`${features[9].name},${features[9].tags}`, async ({ page, baseURL }) => { + console.info(`[Test Page]: ${baseURL}${features[9].path}`); + await test.step('product with month, year subscriptions in JP', async () => { + await page.goto(`${baseURL}${features[9].path}`); + await page.waitForLoadState('domcontentloaded'); + await expect(page).toHaveURL(`${baseURL}${features[9].path}`); + }); + + await test.step('JP locale monthly, year subscriptions', async () => { + await page.waitForLoadState(); + await expect(ost.headingdiscription).toBeTruthy(); + await expect(ost.headingdiscription2).toBeTruthy(); + await expect(ost.firstcardheading).toBeVisible(); + await expect(ost.individualPSpricemonth_jp).toBeVisible(); + await expect(ost.individualPSpriceyear_jp).toBeVisible(); + await page.locator('//a[@class="con-button placeholder-resolved"]').first().click(); + await expect(page).toHaveURL(new RegExp('^https://commerce.adobe.com/store/')); + await expect(page).toHaveURL(new RegExp('co=JP&lang=ja')); + }); +}); +}); From bbbcec7cfb22a0050506fdc1c19013d1f580381e Mon Sep 17 00:00:00 2001 From: Jacky Sun <67350368+JackySun9@users.noreply.github.com> Date: Fri, 1 Dec 2023 08:07:43 -0800 Subject: [PATCH 23/53] add screenshot for UAR stable and beta (#216) * add test for quiz and result pages * add test for quiz and result pages * add test for quiz and result pages * add POC for analytics test * update analytics tests and envs * result envs * update analytics only on firefox * add dynamic tests * add dynamic test for quiz page * update quiz test * update test structure * add test for quiz and result pages * add POC for analytics test * update analytics tests and envs * result envs * update analytics only on firefox * add dynamic tests * add dynamic test for quiz page * update quiz test * update test structure * update uar tests to new format * update uar tests * move everything to uar folder * add dependency for js-yaml * update test according to latest comments * update test according to latest comments * update tests according to the latest comments * add uar config * add analytics for uar * update according to feedbacks * update tags * add @cc tag * update according to feedbacks * add dynamic tests for uar * update according to review comments * fix some typos * update according to review comments * merge console log info * add UI screenshots for UAR * move view point to test * update according to feedback * add analytics test for UAR * update validation and uar libs * update libs * update by feedback * update some config and tests * update some config and tests * update test content path to common path * update analytics tests * fix test failures caused by test code * fix test failures * fix test failures * add visual test for CAAS with two pages * update according to feedbacks * update report in config file * add screenshot for milo main live vs uar-integration live * add timestamp js for time stampe recording * add screenshot diff for uar stable and beta * move uar screenshots into visual compare folder --------- Co-authored-by: xiasun Co-authored-by: Aaron Mauchley --- features/visual-compare/uar/quiz.spec.js | 14 ++++ libs/timestamp.js | 6 ++ libs/webutil.js | 77 ++++++++++++++-------- selectors/uar/quiz.page.js | 29 ++++---- tests/uar/quiz.screenshots.test.js | 4 +- visual-compare-tests/caas/cards.vc.test.js | 4 +- visual-compare-tests/uar/quiz.vc.test.js | 66 +++++++++++++++++++ 7 files changed, 156 insertions(+), 44 deletions(-) create mode 100644 features/visual-compare/uar/quiz.spec.js create mode 100644 libs/timestamp.js create mode 100644 visual-compare-tests/uar/quiz.vc.test.js diff --git a/features/visual-compare/uar/quiz.spec.js b/features/visual-compare/uar/quiz.spec.js new file mode 100644 index 00000000..52e2a806 --- /dev/null +++ b/features/visual-compare/uar/quiz.spec.js @@ -0,0 +1,14 @@ +module.exports = { + name: 'UAR Visual Comparison', + features: [ + { + tcid: '0', + name: '@quiz screenshots', + path: '/drafts/quiz/quiz-2/', + stable: '@milo_live', + beta: '@uar_live', + tags: '@cc @uar-quiz-stable-vs-beta @uar-quiz-static', + data: 'data/uar/quiz/quiz-basic.yml', + }, + ], +}; diff --git a/libs/timestamp.js b/libs/timestamp.js new file mode 100644 index 00000000..10f332a5 --- /dev/null +++ b/libs/timestamp.js @@ -0,0 +1,6 @@ +const fs = require('fs'); + +fs.writeFileSync( + 'timestamp.json', + JSON.stringify([(new Date()).toLocaleString()], null, 2), +); diff --git a/libs/webutil.js b/libs/webutil.js index c451441a..ee2f703a 100644 --- a/libs/webutil.js +++ b/libs/webutil.js @@ -155,33 +155,33 @@ exports.WebUtil = class WebUtil { * @param {Object} attProps - The attribute properties and expected values to verify. * @returns {Boolean} - True if all attribute properties match the expected values, false otherwise. */ - async verifyAttributes_(locator, attProps) { - this.locator = locator; - let result = true; - await Promise.allSettled( - Object.entries(attProps).map(async ([property, expectedValue]) => { - if (property === 'class' && typeof expectedValue === 'string') { - // If the property is 'class' and the expected value is an string, - // split the string value into individual classes - const classes = expectedValue.split(' '); - try { - await expect(await this.locator).toHaveClass(classes.join(' ')); - } catch (error) { - console.error('Attribute class not found:', error); - result = false; - } - } else { - try { - await expect(await this.locator).toHaveAttribute(property, expectedValue); - } catch (error) { - console.error(`Attribute ${property} not found:`, error); - result = false; - } + async verifyAttributes_(locator, attProps) { + this.locator = locator; + let result = true; + await Promise.allSettled( + Object.entries(attProps).map(async ([property, expectedValue]) => { + if (property === 'class' && typeof expectedValue === 'string') { + // If the property is 'class' and the expected value is an string, + // split the string value into individual classes + const classes = expectedValue.split(' '); + try { + await expect(await this.locator).toHaveClass(classes.join(' ')); + } catch (error) { + console.error('Attribute class not found:', error); + result = false; } - }), - ); - return result; - } + } else { + try { + await expect(await this.locator).toHaveAttribute(property, expectedValue); + } catch (error) { + console.error(`Attribute ${property} not found:`, error); + result = false; + } + } + }), + ); + return result; + } /** * Slow/fast scroll of entire page JS evaluation method, aides with lazy loaded content. @@ -292,16 +292,16 @@ exports.WebUtil = class WebUtil { await this.page.screenshot({ path: `${folderPath}/${fileName}`, fullPage: true }); } - async takeScreenshotAndCompare(urlA, urlB, folderPath, fileName) { + async takeScreenshotAndCompare(urlA, callbackA, urlB, callbackB, folderPath, fileName) { console.info(`[Test Page]: ${urlA}`); await this.page.goto(urlA); - await this.page.waitForTimeout(3000); + await callbackA(); await this.page.screenshot({ path: `${folderPath}/${fileName}-a.png`, fullPage: true }); const baseImage = fs.readFileSync(`${folderPath}/${fileName}-a.png`); console.info(`[Test Page]: ${urlB}`); await this.page.goto(urlB); - await this.page.waitForTimeout(3000); + await callbackB(); await this.page.waitForSelector('.feds-footer-privacyLink'); await this.page.screenshot({ path: `${folderPath}/${fileName}-b.png`, fullPage: true }); const currImage = fs.readFileSync(`${folderPath}/${fileName}-b.png`); @@ -314,4 +314,23 @@ exports.WebUtil = class WebUtil { console.info('Differences found'); } } + + static compareScreenshots(stableArray, betaArray, folderPath) { + const comparator = getComparator('image/png'); + for (let i = 0; i < stableArray.length; i += 1) { + if (betaArray[i].slice(-10) === stableArray[i].slice(-10)) { + const stableImage = fs.readFileSync(`${folderPath}/${stableArray[i]}`); + const betaImage = fs.readFileSync(`${folderPath}/${betaArray[i]}`); + const diffImage = comparator(stableImage, betaImage); + + if (diffImage) { + fs.writeFileSync(`${folderPath}/${stableArray[i]}-diff.png`, diffImage.diff); + console.info('Differences found'); + } + } else { + console.info('Screenshots are not matched'); + console.info(`${stableArray[i]} vs ${betaArray[i]}`); + } + } + } }; diff --git a/selectors/uar/quiz.page.js b/selectors/uar/quiz.page.js index 9a759670..218bac1f 100644 --- a/selectors/uar/quiz.page.js +++ b/selectors/uar/quiz.page.js @@ -11,6 +11,7 @@ export default class Quiz { this.uarResult = page.locator('.quiz-results h1'); this.uarResult2 = page.locator('//div[contains(@data-path,"marquee-product")]//strong | //div[contains(@data-path,"check-bullet")]//h1 | //div[contains(@data-path,"express-product")]//h1'); this.uarResult3 = page.locator('//div[contains(@data-path,"card")]//strong'); + this.screenshots = []; } /** @@ -41,7 +42,7 @@ export default class Quiz { * @param {string} url * @param {string} originalAnswer */ - async clickEachAnswer(url, originalAnswer, keyNumber, isScreenshot = false) { + async clickEachAnswer(url, originalAnswer, keyNumber, version, isScreenshot = false) { await this.page.goto(url); const answers = originalAnswer.split('>').map((x) => x.trim()); @@ -64,13 +65,15 @@ export default class Quiz { const index = answers.indexOf(answer); const folderPath = 'screenshots/uar'; - const desktopName = `${keyNumber} - new - desktop - ${index} - ${answer.replace('/', '')}.png`; - const tabletName = `${keyNumber} - new - tablet - ${index} - ${answer.replace('/', '')}.png`; - const mobileName = `${keyNumber} - new - mobile - ${index} - ${answer.replace('/', '')}.png`; + const desktopName = `${keyNumber} - ${version} - desktop - ${index} - ${answer.replace('/', '')}.png`; + const tabletName = `${keyNumber} - ${version} - tablet - ${index} - ${answer.replace('/', '')}.png`; + const mobileName = `${keyNumber} - ${version} - mobile - ${index} - ${answer.replace('/', '')}.png`; await this.webUtil.takeScreenshot(folderPath, desktopName, 1920, 1080); await this.webUtil.takeScreenshot(folderPath, tabletName, 768, 1024); await this.webUtil.takeScreenshot(folderPath, mobileName, 375, 812); + + this.screenshots.push(desktopName, tabletName, mobileName); } // click next button @@ -79,13 +82,15 @@ export default class Quiz { await this.page.waitForTimeout(500); const index = answers.length - 1; const folderPath = 'screenshots/uar'; - const desktopName = `${keyNumber} - new - desktop - ${index} - ${answer.replace('/', '')}.png`; - const tabletName = `${keyNumber} - new - tablet - ${index} - ${answer.replace('/', '')}.png`; - const mobileName = `${keyNumber} - new - mobile - ${index} - ${answer.replace('/', '')}.png`; + const desktopName = `${keyNumber} - ${version} - desktop - ${index} - ${answer.replace('/', '')}.png`; + const tabletName = `${keyNumber} - ${version} - tablet - ${index} - ${answer.replace('/', '')}.png`; + const mobileName = `${keyNumber} - ${version} - mobile - ${index} - ${answer.replace('/', '')}.png`; await this.webUtil.takeScreenshot(folderPath, desktopName, 1920, 1080); await this.webUtil.takeScreenshot(folderPath, tabletName, 768, 1024); await this.webUtil.takeScreenshot(folderPath, mobileName, 375, 812); + + this.screenshots.push(desktopName, tabletName, mobileName); } } @@ -97,7 +102,7 @@ export default class Quiz { * Validate products on result page to match with expect products * @param {string} name */ - async checkResultPage(name, originalAnswer, keyNumber, isScreenshot = false) { + async checkResultPage(name, originalAnswer, keyNumber, version, isScreenshot = false) { const newProduct = []; const actualProduct = await this.uarResult.nth(0); @@ -163,13 +168,15 @@ export default class Quiz { await this.page.waitForTimeout(1000); const folderPath = 'screenshots/uar'; - const desktopName = `${keyNumber} - new - desktop - result.png`; - const tabletName = `${keyNumber} - new - tablet - result.png`; - const mobileName = `${keyNumber} - new - mobile - result.png`; + const desktopName = `${keyNumber} - ${version} - desktop - result.png`; + const tabletName = `${keyNumber} - ${version} - tablet - result.png`; + const mobileName = `${keyNumber} - ${version} - mobile - result.png`; await this.webUtil.takeScreenshot(folderPath, desktopName, 1920, 1080); await this.webUtil.takeScreenshot(folderPath, tabletName, 768, 1024); await this.webUtil.takeScreenshot(folderPath, mobileName, 375, 812); + + this.screenshots.push(desktopName, tabletName, mobileName); } console.info(`==========new============\n${newProduct.sort().join('')}`); diff --git a/tests/uar/quiz.screenshots.test.js b/tests/uar/quiz.screenshots.test.js index ca21cbf9..67fa75dc 100644 --- a/tests/uar/quiz.screenshots.test.js +++ b/tests/uar/quiz.screenshots.test.js @@ -41,11 +41,11 @@ test.describe('Quiz flow test suite', () => { }); await test.step(`New: Select each answer on test page according to ${key}`, async () => { - await quiz.clickEachAnswer(url, key, keyNumber, true); + await quiz.clickEachAnswer(url, key, keyNumber, 'new', true); }); await test.step('New: Check results on test page', async () => { - newProduct = await quiz.checkResultPage(testdata[key], key, keyNumber, true); + newProduct = await quiz.checkResultPage(testdata[key], key, keyNumber, 'new', true); }); expect.soft(newProduct).toContain(oldProduct); diff --git a/visual-compare-tests/caas/cards.vc.test.js b/visual-compare-tests/caas/cards.vc.test.js index 29a2a253..98ab3ed9 100644 --- a/visual-compare-tests/caas/cards.vc.test.js +++ b/visual-compare-tests/caas/cards.vc.test.js @@ -16,10 +16,10 @@ test.describe('Milo Caas block visual comparison test suite', () => { // eslint-disable-next-line no-restricted-syntax for (const feature of features) { // eslint-disable-next-line no-loop-func - test(`${feature.name},${feature.tags}`, async ({ baseURL }) => { + test(`${feature.name},${feature.tags}`, async ({ page, baseURL }) => { const folderPath = 'screenshots/caas'; // eslint-disable-next-line max-len - await webUtil.takeScreenshotAndCompare(baseURL + feature.stable, baseURL + feature.beta, folderPath, feature.name); + await webUtil.takeScreenshotAndCompare(baseURL + feature.stable, async () => { await page.waitForTimeout(3000); }, baseURL + feature.beta, async () => { await page.waitForTimeout(3000); }, folderPath, feature.name); }); } }); diff --git a/visual-compare-tests/uar/quiz.vc.test.js b/visual-compare-tests/uar/quiz.vc.test.js new file mode 100644 index 00000000..028e5920 --- /dev/null +++ b/visual-compare-tests/uar/quiz.vc.test.js @@ -0,0 +1,66 @@ +/* eslint-disable no-await-in-loop */ +/* eslint-disable no-loop-func */ +/* eslint-disable no-restricted-syntax */ +import { expect, test } from '@playwright/test'; +import Quiz from '../../selectors/uar/quiz.page.js'; + +const { features } = require('../../features/visual-compare/uar/quiz.spec.js'); +const { WebUtil } = require('../../libs/webutil.js'); +const envs = require('../../envs/envs.js'); + +test.describe('Quiz flow test suite', () => { + // reset timeout because we use this to run all test data + test.setTimeout(10 * 60 * 1000); + for (const feature of features) { + test( + `${feature.name}, ${feature.tags}`, + async ({ page }) => { + const stablePage = new Quiz(page); + const betaPage = new Quiz(page); + const stableURL = `${envs[feature.stable]}${feature.path}`; + console.info(stableURL); + const betaURL = `${envs[feature.beta]}${feature.path}`; + console.info(betaURL); + + // load test data from static files + const testdata = await WebUtil.loadTestData(`${feature.data}`); + + let keyNumber = 0; + + for (const key of Object.keys(testdata)) { + console.log(key); + let stableProduct = ''; + let betaProduct = ''; + let stableProductScreenshots = []; + let betaProductScreenshots = []; + keyNumber += 1; + await test.step(`Old: Select each answer on test page according to ${key}`, async () => { + await stablePage.clickEachAnswer(stableURL, key, keyNumber, 'stable', true); + }); + + await test.step('Old: Check results on test page', async () => { + stableProduct = await stablePage.checkResultPage(testdata[key], key, keyNumber, 'stable', true); + }); + + stableProductScreenshots = stablePage.screenshots.slice(); + stablePage.screenshots = []; + + await test.step(`New: Select each answer on test page according to ${key}`, async () => { + await betaPage.clickEachAnswer(betaURL, key, keyNumber, 'beta', true); + }); + + await test.step('New: Check results on test page', async () => { + betaProduct = await betaPage.checkResultPage(testdata[key], key, keyNumber, 'beta', true); + }); + + betaProductScreenshots = betaPage.screenshots.slice(); + betaPage.screenshots = []; + + WebUtil.compareScreenshots(stableProductScreenshots, betaProductScreenshots, 'screenshots/uar'); + + expect.soft(betaProduct).toContain(stableProduct); + } + }, + ); + } +}); From 54e3c3e59d5f23e0e8f1014ff2d4479cd55e8f6d Mon Sep 17 00:00:00 2001 From: Santoshkumar Nateekar Date: Mon, 4 Dec 2023 13:35:46 -0800 Subject: [PATCH 24/53] [MWPW-139389] : Update Nala test scripts as per Analytics 2.1 changes (#211) * fix circle-ci url * analytics update 2_1 * update text.block.spec * fix circle-ci url * update circle ci --------- Co-authored-by: nateekar --- libs/webutil.js | 96 +++++++++++++ selectors/milo/marquee.block.page.js | 13 +- selectors/milo/text.block.page.js | 198 ++++----------------------- tests/milo/marquee.block.test.js | 109 +++++---------- tests/milo/media.block.test.js | 31 ++--- tests/milo/text.block.test.js | 143 ++++++++++++++++--- utils/reporters/base-reporter.js | 2 +- 7 files changed, 302 insertions(+), 290 deletions(-) diff --git a/libs/webutil.js b/libs/webutil.js index ee2f703a..ecaf86d5 100644 --- a/libs/webutil.js +++ b/libs/webutil.js @@ -115,6 +115,50 @@ exports.WebUtil = class WebUtil { return result; } + /** + * Verifies that the specified CSS properties of the given locator match the expected values. + * @param {Object} locator - The locator to verify CSS properties for. + * @param {Object} cssProps - The CSS properties and expected values to verify. + * @returns {Boolean} - True if all CSS properties match the expected values, false otherwise. + */ + async verifyCSS_(locator, cssProps) { + this.locator = locator; + let result = true; + await Promise.allSettled( + Object.entries(cssProps).map(async ([property, expectedValue]) => { + try { + await expect(this.locator).toHaveCSS(property, expectedValue); + } catch (error) { + console.error(`CSS property ${property} not found:`, error); + result = false; + } + }), + ); + return result; + } + + /** + * Verifies that the specified CSS properties of the given locator match the expected values. + * @param {Object} locator - The locator to verify CSS properties for. + * @param {Object} cssProps - The CSS properties and expected values to verify. + * @returns {Boolean} - True if all CSS properties match the expected values, false otherwise. + */ + async verifyCSS_(locator, cssProps) { + this.locator = locator; + let result = true; + await Promise.allSettled( + Object.entries(cssProps).map(async ([property, expectedValue]) => { + try { + await expect(this.locator).toHaveCSS(property, expectedValue); + } catch (error) { + console.error(`CSS property ${property} not found:`, error); + result = false; + } + }), + ); + return result; + } + /** * Verifies that the specified attribute properties of the given locator match the expected values. * @param {Object} locator - The locator to verify attributes. @@ -292,6 +336,58 @@ exports.WebUtil = class WebUtil { await this.page.screenshot({ path: `${folderPath}/${fileName}`, fullPage: true }); } +/** + * Generates analytic string for a given project. + * @param {string} project - The project identifier, defaulting to 'milo' if not provided. + * @returns {string} - A string formatted as 'gnav||nopzn|nopzn'. + */ + async getGnavDaalh(project=milo) { + return 'gnav'+ '|' + project + '|'+ 'nopzn' + '|' + 'nopzn' ; + } + +/** + * Generates analytic string for a section based on a given counter value. + * @param {number|string} counter - A counter value used to generate the section identifier. + * @returns {string} - A string formatted as 's'. + */ + async getSectionDaalh(counter) { + return 's'+ counter; + } + +/** + * Generates analytic string for a given block name and a counter. + * @param {string} blockName - The name of the block, which is sliced to its first 20 characters. + * @param {number|string} counter - A counter value i.e. block number. + * @returns {string} - A string formatted as 'b||nopzn|nopzn'. + */ + async getBlockDaalh(blockName, counter) { + const slicedBlockName = blockName.slice(0, 20); + return 'b'+ counter + '|' + slicedBlockName + '|'+ 'nopzn' + '|' + 'nopzn' ; + } + +/** + * Generates analytic string for link or button based on link/button text , a counter, and the last header text. + * @param {string} linkText - The text of the link, which is cleaned and sliced to its first 20 characters. + * @param {number|string} counter - A counter value used in the identifier. + * @param {string} lastHeaderText - The last header text, which is cleaned and sliced to its first 20 characters. + * @param {boolean} [pzn=false] - boolean parameter, defaulting to false.(for personalization) + * @returns {string} - A string formatted as '---'. + */ + async getLinkDaall(linkText, counter, lastHeaderText, pzn = false) { + const cleanAndSliceText = (text) => { + return text + ?.replace(/[^\w\s]+/g, ' ') + .replace(/\s+/g, ' ') + .replace(/^_+|_+$/g, '') + .trim() + .slice(0, 20); + } + const slicedLinkText = cleanAndSliceText(linkText); + const slicedLastHeaderText = cleanAndSliceText(lastHeaderText); + return `${slicedLinkText}-${counter}--${slicedLastHeaderText}`; + } + + async takeScreenshotAndCompare(urlA, callbackA, urlB, callbackB, folderPath, fileName) { console.info(`[Test Page]: ${urlA}`); await this.page.goto(urlA); diff --git a/selectors/milo/marquee.block.page.js b/selectors/milo/marquee.block.page.js index 0260f12e..27895730 100644 --- a/selectors/milo/marquee.block.page.js +++ b/selectors/milo/marquee.block.page.js @@ -182,18 +182,7 @@ export default class Marquee { 'autoplay': '', 'loop': '', 'muted': '' - }, - 'analytics': { - 'marquee.daa-lh': { - 'daa-lh': /b[1-9]|marquee|default|default/, - }, - 'section.daa-lh': { - 'daa-lh': /s[1-9]/, - }, - 'content.daa-lh': { - 'daa-lh': /b[1-9]|content|default|default/, - }, - }, + }, }; } }; diff --git a/selectors/milo/text.block.page.js b/selectors/milo/text.block.page.js index 4b3ecb70..4985b357 100644 --- a/selectors/milo/text.block.page.js +++ b/selectors/milo/text.block.page.js @@ -14,38 +14,38 @@ export default class Text { this.textlegal = this.page.locator('.text.legal.text-block.con-block.has-bg'); this.textLinkFarm = this.page.locator('.text.link-farm.text-block.con-block.has-bg'); - this.textDetailM = page.locator('.detail-m'); - this.textIntroDetailM = page.locator('.detail-m'); - this.textLongFormDetailL = page.locator('.detail-l'); - this.textLegalDetail = page.locator('.foreground'); - - this.textHeadline = this.text.locator('#text'); - this.textIntroHeadline = this.text.locator('#text-intro'); - this.textFullWidthHeadline = this.text.locator('#text-full-width'); - this.textFullWidthLargeHeadline = this.text.locator('#text-full-width-large'); - this.textLongFormLargeHeadline = this.text.locator('#text-long-form-large'); - this.textInsetLargeMSpacingHeadline = this.text.locator('#text-inset-large-m-spacing'); - this.textLinkFarmHeadline = this.text.locator('#text-link-farm-title'); - this.textLinkFarmcolumnheading = this.text.locator('#heading-1'); - this.textLinkFarmcolumns = this.text.locator('h3'); - this.textLinkColumnOne = this.text.locator('div div:nth-child(1) a'); + this.detailM = page.locator('.detail-m'); + this.introDetailM = page.locator('.detail-m'); + this.longFormDetailL = page.locator('.detail-l'); + this.legalDetail = page.locator('.foreground'); + + this.headline = this.text.locator('#text'); + this.introHeadline = this.text.locator('#text-intro'); + this.fullWidthHeadline = this.text.locator('#text-full-width'); + this.fullWidthLargeHeadline = this.text.locator('#text-full-width-large'); + this.longFormLargeHeadline = this.text.locator('#text-long-form-large'); + this.insetLargeMSpacingHeadline = this.text.locator('#text-inset-large-m-spacing'); + this.linkFarmHeadline = this.text.locator('#text-link-farm-title'); + this.linkFarmcolumnheading = this.text.locator('#heading-1'); + + this.linkFarmcolumns = this.text.locator('h3'); + this.linkColumnOne = this.text.locator('div div:nth-child(1) a'); this.linkFormText = this.text.locator('p').nth(1); - this.textBodyXSS = this.text.locator('.body-xxs').first(); - this.textBodyM = this.text.locator('.body-m').first(); - this.textBodyL = this.text.locator('.body-l').first(); - - this.textPropertiesHeadingM = this.text.locator('#properties-h3').first(); + this.bodyXSS = this.text.locator('.body-xxs').first(); + this.bodyM = this.text.locator('.body-m').first(); + this.bodyL = this.text.locator('.body-l').first(); + this.propertiesHeadingM = this.text.locator('#properties-h3').first(); - this.textBodyLink = this.page.locator('.body-m a'); - this.textActionAreaLink = this.page.locator('.body-m.action-area a').nth(1); this.outlineButton = this.text.locator('.con-button.outline'); + this.actionAreaLink = this.page.locator('.body-m.action-area a').nth(1); + this.bodyLink = this.page.locator('.body-m a'); + + this.insetLargeMSpacingList1 = this.page.locator('.text.inset.medium.m-spacing ul').nth(0); + this.listOneItems = this.insetLargeMSpacingList1.locator('li') - this.textInsetLargeMSpacingList1 = this.page.locator('.text.inset.medium.m-spacing ul').nth(0); - this.listOneItems = this.textInsetLargeMSpacingList1.locator('li') - - this.textInsetLargeMSpacingList2 = this.page.locator('.text.inset.medium.m-spacing ul').nth(1); - this.listTwoItems = this.textInsetLargeMSpacingList2.locator('li') + this.insetLargeMSpacingList2 = this.page.locator('.text.inset.medium.m-spacing ul').nth(1); + this.listTwoItems = this.insetLargeMSpacingList2.locator('li') this.generalTermsOfUse = this.textlegal.locator('.body-xxs').nth(1); this.publishText = this.textlegal.locator('.body-xxs').nth(2); @@ -98,41 +98,30 @@ export default class Text { // text block contents attributes this.attProperties = { - 'outline': { 'daa-ll': /^outline\|(.*)/ }, - 'filled': { 'daa-ll': /^filled\|(.*)/ }, - 'learn-more': { 'daa-ll': /^Learn more[-\s]\d+\|(.*)/ }, - 'text-link': { 'daa-ll': /^Explore the premium collection[-\s]\d+|(.*)/ }, 'text': { 'class': 'text text-block con-block', - 'daa-lh': 'b1|text|default|default', }, 'text-intro': { 'class': 'text intro text-block con-block has-bg max-width-8-desktop xxl-spacing-top xl-spacing-bottom', - 'daa-lh': 'b1|text|default|default', 'style': 'background: rgb(255, 255, 255);', }, 'text-full-width': { 'class': 'text full-width text-block con-block max-width-8-desktop center xxl-spacing', - 'daa-lh': 'b1|text|default|default', }, 'text-full-width-large': { 'class': 'text full-width large text-block con-block max-width-8-desktop center xxl-spacing', - 'daa-lh': 'b1|text|default|default', }, 'text-long-form-large': { 'class': 'text long-form large text-block con-block max-width-8-desktop', - 'daa-lh': 'b1|text|default|default', }, 'text-inset-medium-m-spacing': { 'class': 'text inset medium m-spacing text-block con-block max-width-8-desktop', - 'daa-lh': 'b1|text|default|default', }, 'text-legal': { 'class': 'text legal text-block con-block has-bg', }, 'text-Link-farm': { 'class': 'text link-farm text-block con-block has-bg', - 'daa-lh' : 'b1|text|default|default', 'style': 'background: rgb(255, 255, 255);', }, 'headingprops': { @@ -141,136 +130,5 @@ export default class Text { }; } - /** - * Verifies the css, attributes, styles, of elements or sections of the specified Text block. - * - * @param {string} textType - The type of the Text block to verify. - * Possible values are 'text', 'text (Intro)', 'Text (full width)'. - * text (full-width, large), text (long form, large), and text (inset, large, m spacing). - * text (legal), text (link-farm). - * @returns {Promise} - Returns true if the specified Text type has the expected values. - */ - async verifyText(textType, data) { - switch (textType) { - case 'text': - // verify text visibility, content, css and attribute values - await expect(await this.text).toBeVisible(); - - await expect(await this.textHeadline).toContainText(data.h3Text); - await expect(await this.textBodyM).toContainText(data.bodyText); - await expect(await this.outlineButton).toContainText(data.outlineButtonText); - - expect(await WebUtil.verifyAttributes(await this.text, this.attProperties.text)).toBeTruthy(); - expect(await WebUtil.verifyCSS(await this.textHeadline, this.cssProperties['heading-l'])).toBeTruthy(); - expect(await WebUtil.verifyCSS(await this.textBodyM, this.cssProperties['body-m'])).toBeTruthy(); - expect(await WebUtil.verifyCSS(await this.textActionAreaLink, this.cssProperties['body-m'])).toBeTruthy(); - expect(await WebUtil.verifyAttributes(await this.textActionAreaLink, this.attProperties['text-link'])).toBeTruthy(); - expect(await WebUtil.verifyAttributes(await this.outlineButton, this.attProperties['learn-more'])).toBeTruthy(); - - return true; - case 'text (intro)': - // verify text (intro) visibility, css and attribute values - await expect(this.textIntro).toBeVisible(); - await expect(await this.textIntroHeadline).toContainText(data.h2Text); - await expect(await this.textBodyM).toContainText(data.bodyText); - - expect(await WebUtil.verifyAttributes(await this.textIntro, this.attProperties['text-intro'])).toBeTruthy(); - expect(await WebUtil.verifyCSS(await this.textIntroDetailM, this.cssProperties['detail-m'])).toBeTruthy(); - expect(await WebUtil.verifyCSS(await this.textIntroHeadline, this.cssProperties['heading-l'])).toBeTruthy(); - expect(await WebUtil.verifyCSS(await this.textBodyM, this.cssProperties['body-m'])).toBeTruthy(); - - return true; - - case 'text (full width)': - // verify text (full width) visibility, content, css and attribute values - await expect(this.textFullWidth).toBeVisible(); - - await expect(await this.textFullWidthHeadline).toContainText(data.h3Text); - await expect(await this.textBodyM).toContainText(data.bodyText); - await expect(await this.textBodyLink).toContainText(data.linkText); - - expect(await WebUtil.verifyAttributes(await this.textFullWidth, this.attProperties['text-full-width'])).toBeTruthy(); - expect(await WebUtil.verifyCSS(await this.textFullWidthHeadline, this.cssProperties['heading-l'])).toBeTruthy(); - expect(await WebUtil.verifyCSS(await this.textBodyM, this.cssProperties['body-m'])).toBeTruthy(); - expect(await WebUtil.verifyAttributes(await this.textBodyLink, this.attProperties['text-link'])).toBeTruthy(); - - return true; - - case 'text (full-width, large)': - // verify text (full-width, large) visibility, content, css and attribute values - await expect(this.textFullWidthLarge).toBeVisible(); - - await expect(await this.textFullWidthLargeHeadline).toContainText(data.h2Text); - await expect(await this.textBodyM).toContainText(data.bodyText); - await expect(await this.textBodyLink).toContainText(data.linkText); - - expect(await WebUtil.verifyAttributes(await this.textFullWidthLarge, this.attProperties['text-full-width-large'])).toBeTruthy(); - expect(await WebUtil.verifyCSS(await this.textFullWidthLargeHeadline, this.cssProperties['heading-xl'])).toBeTruthy(); - expect(await WebUtil.verifyCSS(await this.textBodyM, this.cssProperties['body-m'])).toBeTruthy(); - expect(await WebUtil.verifyAttributes(await this.textBodyLink, this.attProperties['text-link'])).toBeTruthy(); - - return true; - - case 'text (long form, large)': - // verify text (long-form, large) visibility, content, css and attribute values - await expect(await this.textLongFormLarge).toBeVisible(); - - await expect(await this.textLongFormDetailL).toContainText(data.detailText); - await expect(await this.textLongFormLargeHeadline).toContainText(data.h2Text); - await expect(await this.textBodyL).toContainText(data.bodyText); - - expect(await WebUtil.verifyAttributes(await this.textLongFormLarge, this.attProperties['text-long-form-large'])).toBeTruthy(); - expect(await WebUtil.verifyCSS(await this.textLongFormDetailL, this.cssProperties['detail-l'])).toBeTruthy(); - expect(await WebUtil.verifyCSS(await this.textLongFormLargeHeadline, this.cssProperties['heading-l'])).toBeTruthy(); - expect(await WebUtil.verifyCSS(await this.textBodyL, this.cssProperties['body-l'])).toBeTruthy(); - - return true; - - case 'text (inset, large, m spacing)': - // verify text (inset, large, m spacing) visibility, content, css and attribute values - await expect(await this.textInsetLargeMSpacing).toBeVisible(); - - await expect(await this.textInsetLargeMSpacingHeadline).toContainText(data.h3Text); - await expect(await this.textBodyL).toContainText(data.bodyText); - await expect(await this.listOneItems).toHaveCount(data.listCount1); - - expect(await WebUtil.verifyAttributes(await this.textInsetLargeMSpacing, this.attProperties['text-inset-medium-m-spacing'])).toBeTruthy(); - expect(await WebUtil.verifyCSS(await this.textInsetLargeMSpacingHeadline, this.cssProperties['heading-m'])).toBeTruthy(); - expect(await WebUtil.verifyCSS(await this.textBodyL, this.cssProperties['body-l'])).toBeTruthy(); - expect(await WebUtil.verifyCSS(await this.textPropertiesHeadingM, this.cssProperties['heading-m'])).toBeTruthy(); - - return true; - - case 'text (legal)': - // verify text (legal) visibility, content, css and attribute values - await expect(await this.textlegal).toBeVisible(); - - await expect(await this.generalTermsOfUse).toContainText(data.termsOfUseText); - await expect(await this.publishText).toContainText(data.publishText); - await expect(await this.generalTerms).toContainText(data.generalTermsText); - await expect(await this.legalInfoLink).toContainText(data.linkText); - - expect(await WebUtil.verifyAttributes(await this.textlegal, this.attProperties['text-legal'])).toBeTruthy(); - expect(await WebUtil.verifyCSS(await this.textBodyXSS, this.cssProperties['body-xss'])).toBeTruthy(); - - return true; - - case 'text (link-farm)': - // verify text (link-farm) visibility, content, css and attribute values - await expect(await this.textLinkFarm).toBeVisible(); - - await expect(await this.textLinkFarmcolumns).toHaveCount(data.headingColumns); - await expect(await this.textLinkColumnOne).toHaveCount(data.linksCount); - await expect(await this.linkFormText).toContainText(data.linkText); - - expect(await WebUtil.verifyAttributes(await this.textLinkFarm, this.attProperties['text-Link-farm'])).toBeTruthy(); - expect(await WebUtil.verifyCSS(await this.textLinkFarmHeadline, this.cssProperties['heading-l'])).toBeTruthy(); - expect(await WebUtil.verifyAttributes(await this.textLinkFarmcolumnheading, this.attProperties['headingprops'])).toBeTruthy(); - - return true; - - default: - throw new Error(`Unsupported Text type: ${this.textType}`); - } - } }; + diff --git a/tests/milo/marquee.block.test.js b/tests/milo/marquee.block.test.js index 8aea29b5..f16802e8 100644 --- a/tests/milo/marquee.block.test.js +++ b/tests/milo/marquee.block.test.js @@ -48,10 +48,9 @@ test.describe('Milo Marquee Block test suite', () => { }); await test.step('step-3: Verify analytics attributes', async () => { - const outlineButtonDaalh = data.outlineButtonText +'-1'+ '|' + (data.h2Text).slice(0, 20) ; - - expect(await webUtil.verifyAttributes_(marquee.marqueeLight, marquee.attributes['analytics']['marquee.daa-lh'])).toBeTruthy(); - await expect(await marquee.outlineButton).toHaveAttribute('daa-ll', outlineButtonDaalh); + await expect(await marquee.marqueeLight).toHaveAttribute('daa-lh', await webUtil.getBlockDaalh('marquee', 1)); + await expect(await marquee.outlineButton).toHaveAttribute('daa-ll', await webUtil.getLinkDaall(data.outlineButtonText, 1, data.h2Text)); + await expect(await marquee.blueButton).toHaveAttribute('daa-ll', await webUtil.getLinkDaall(data.blueButtonText, 2, data.h2Text)); }); await test.step('step-4: Verify browser console errors', async () => { @@ -83,10 +82,8 @@ test.describe('Milo Marquee Block test suite', () => { }); await test.step('step-3: Verify analytic attributes', async () => { - const blueButtonDaalh = data.blueButtonText +'-1'+ '|' + (data.h2Text).slice(0, 20) ; - - expect(await webUtil.verifyAttributes_(marquee.marqueeSmall, marquee.attributes['analytics']['marquee.daa-lh'])).toBeTruthy(); - await expect(await marquee.blueButton).toHaveAttribute('daa-ll', blueButtonDaalh); + await expect(await marquee.marqueeSmall).toHaveAttribute('daa-lh', await webUtil.getBlockDaalh('marquee', 1)); + await expect(await marquee.blueButton).toHaveAttribute('daa-ll', await webUtil.getLinkDaall(data.blueButtonText, 1, data.h2Text)); }); await test.step('step-4: Verify browser console errors', async () => { @@ -120,12 +117,9 @@ test.describe('Milo Marquee Block test suite', () => { }); await test.step('step-3: Verify analytic attributes', async () => { - const outlineButtonDaalh = data.outlineButtonText +'-1'+ '|' + (data.h2Text).slice(0, 20) ; - const blueButtonDaalh = data.blueButtonText +'-2'+ '|' + (data.h2Text).slice(0, 20) ; - - expect(await webUtil.verifyAttributes_(marquee.marqueeSmallLight, marquee.attributes['analytics']['marquee.daa-lh'])).toBeTruthy(); - await expect(await marquee.outlineButton).toHaveAttribute('daa-ll', outlineButtonDaalh); - await expect(await marquee.blueButton).toHaveAttribute('daa-ll', blueButtonDaalh); + await expect(await marquee.marqueeSmallLight).toHaveAttribute('daa-lh', await webUtil.getBlockDaalh('marquee', 1)); + await expect(await marquee.outlineButton).toHaveAttribute('daa-ll', await webUtil.getLinkDaall(data.outlineButtonText, 1, data.h2Text)); + await expect(await marquee.blueButton).toHaveAttribute('daa-ll', await webUtil.getLinkDaall(data.blueButtonText, 2, data.h2Text)); }); await test.step('step-4: Verify browser console errors', async () => { @@ -158,12 +152,9 @@ test.describe('Milo Marquee Block test suite', () => { }); await test.step('step-3: Verify analytic attributes', async () => { - const outlineButtonDaalh = data.outlineButtonText +'-1'+ '|' + (data.h2Text).slice(0, 20) ; - const blueButtonDaalh = data.blueButtonText +'-2'+ '|' + (data.h2Text).slice(0, 20) ; - - expect(await webUtil.verifyAttributes_(marquee.marqueeLarge, marquee.attributes['analytics']['marquee.daa-lh'])).toBeTruthy(); - await expect(await marquee.outlineButtonXL).toHaveAttribute('daa-ll', outlineButtonDaalh); - await expect(await marquee.blueButtonXL).toHaveAttribute('daa-ll', blueButtonDaalh); + await expect(await marquee.marqueeLarge).toHaveAttribute('daa-lh', await webUtil.getBlockDaalh('marquee', 1)); + await expect(await marquee.outlineButtonXL).toHaveAttribute('daa-ll', await webUtil.getLinkDaall(data.outlineButtonText, 1, data.h2Text)); + await expect(await marquee.blueButtonXL).toHaveAttribute('daa-ll', await webUtil.getLinkDaall(data.blueButtonText, 2, data.h2Text)); }); await test.step('step-4: Verify browser console errors', async () => { @@ -196,12 +187,9 @@ test.describe('Milo Marquee Block test suite', () => { }); await test.step('step-3: Verify analytic attributes', async () => { - const outlineButtonDaalh = data.outlineButtonText +'-1'+ '|' + (data.h2Text).slice(0, 20) ; - const blueButtonDaalh = data.blueButtonText +'-2'+ '|' + (data.h2Text).slice(0, 20) ; - - expect(await webUtil.verifyAttributes_(marquee.marqueeLargeLight, marquee.attributes['analytics']['marquee.daa-lh'])).toBeTruthy(); - await expect(await marquee.outlineButtonXL).toHaveAttribute('daa-ll', outlineButtonDaalh); - await expect(await marquee.blueButtonXL).toHaveAttribute('daa-ll', blueButtonDaalh); + await expect(await marquee.marqueeLargeLight).toHaveAttribute('daa-lh', await webUtil.getBlockDaalh('marquee', 1)); + await expect(await marquee.outlineButtonXL).toHaveAttribute('daa-ll', await webUtil.getLinkDaall(data.outlineButtonText, 1, data.h2Text)); + await expect(await marquee.blueButtonXL).toHaveAttribute('daa-ll', await webUtil.getLinkDaall(data.blueButtonText, 2, data.h2Text)); }); await test.step('step-4: Verify and log if any console errors', async () => { @@ -233,10 +221,8 @@ test.describe('Milo Marquee Block test suite', () => { }); await test.step('step-3: Verify analytic attributes', async () => { - const blueButtonDaalh = data.blueButtonText +'-1'+ '|' + (data.h2Text).slice(0, 20) ; - - expect(await webUtil.verifyAttributes_(marquee.marqueeQuiet, marquee.attributes['analytics']['marquee.daa-lh'])).toBeTruthy(); - await expect(await marquee.blueButton).toHaveAttribute('daa-ll', blueButtonDaalh); + await expect(await marquee.marqueeQuiet).toHaveAttribute('daa-lh', await webUtil.getBlockDaalh('marquee', 1)); + await expect(await marquee.blueButton).toHaveAttribute('daa-ll', await webUtil.getLinkDaall(data.blueButtonText, 1, data.h2Text)); }); await test.step('step-4: Verify and log if any console errors', async () => { @@ -267,7 +253,7 @@ test.describe('Milo Marquee Block test suite', () => { }); await test.step('step-3: Verify analytic attributes', async () => { - expect(await webUtil.verifyAttributes_(marquee.marqueeInline, marquee.attributes['analytics']['marquee.daa-lh'])).toBeTruthy(); + await expect(await marquee.marqueeInline).toHaveAttribute('daa-lh', await webUtil.getBlockDaalh('marquee', 1)); }); await test.step('step-4: Verify and log if any console errors', async () => { @@ -300,12 +286,9 @@ test.describe('Milo Marquee Block test suite', () => { }); await test.step('step-3: Verify analytic attributes', async () => { - const outlineButtonDaalh = data.outlineButtonText +'-1'+ '|' + (data.h2Text).slice(0, 20) ; - const blueButtonDaalh = data.blueButtonText +'-2'+ '|' + (data.h2Text).slice(0, 20) ; - - expect(await webUtil.verifyAttributes_(marquee.marqueeSplitSmall, marquee.attributes['analytics']['marquee.daa-lh'])).toBeTruthy(); - await expect(await marquee.outlineButton).toHaveAttribute('daa-ll', outlineButtonDaalh); - await expect(await marquee.blueButton).toHaveAttribute('daa-ll', blueButtonDaalh); + await expect(await marquee.marqueeSplitSmall).toHaveAttribute('daa-lh', await webUtil.getBlockDaalh('marquee', 1)); + await expect(await marquee.outlineButton).toHaveAttribute('daa-ll', await webUtil.getLinkDaall(data.outlineButtonText, 1, data.h2Text)); + await expect(await marquee.blueButton).toHaveAttribute('daa-ll', await webUtil.getLinkDaall(data.blueButtonText, 2, data.h2Text)); }); await test.step('step-4: Verify and log if any console errors', async () => { @@ -342,12 +325,9 @@ test.describe('Milo Marquee Block test suite', () => { }); await test.step('step-3: Verify analytic attributes', async () => { - const blueButtonDaalh = data.blueButtonText +'-1'+ '|' + (data.h2Text).slice(0, 20) ; - const actionLink2Daalh = data.linkText +'-2'+ '|' + (data.h2Text).slice(0, 20) ; - - expect(await webUtil.verifyAttributes_(marquee.marqueeSplitLarge, marquee.attributes['analytics']['marquee.daa-lh'])).toBeTruthy(); - await expect(await marquee.blueButtonXL).toHaveAttribute('daa-ll', blueButtonDaalh); - await expect(await marquee.actionLink2).toHaveAttribute('daa-ll', actionLink2Daalh); + await expect(await marquee.marqueeSplitLarge).toHaveAttribute('daa-lh', await webUtil.getBlockDaalh('marquee', 1)); + await expect(await marquee.blueButtonXL).toHaveAttribute('daa-ll', await webUtil.getLinkDaall(data.blueButtonText, 1, data.h2Text)); + await expect(await marquee.actionLink2).toHaveAttribute('daa-ll', await webUtil.getLinkDaall(data.linkText, 2, data.h2Text)); }); await test.step('step-4: Verify and log if any console errors', async () => { @@ -384,12 +364,9 @@ test.describe('Milo Marquee Block test suite', () => { }); await test.step('step-3: Verify analytic attributes', async () => { - const blueButtonDaalh = data.blueButtonText +'-1'+ '|' + (data.h2Text).slice(0, 20) ; - const actionLink2Daalh = data.linkText +'-2'+ '|' + (data.h2Text).slice(0, 20) ; - - expect(await webUtil.verifyAttributes_(marquee.marqueeSplitLarge, marquee.attributes['analytics']['marquee.daa-lh'])).toBeTruthy(); - await expect(await marquee.blueButtonXL).toHaveAttribute('daa-ll', blueButtonDaalh); - await expect(await marquee.actionLink2).toHaveAttribute('daa-ll', actionLink2Daalh); + await expect(await marquee.marqueeSplitOneThirdLargeLight).toHaveAttribute('daa-lh', await webUtil.getBlockDaalh('marquee', 1)); + await expect(await marquee.blueButtonXL).toHaveAttribute('daa-ll', await webUtil.getLinkDaall(data.blueButtonText, 1, data.h2Text)); + await expect(await marquee.actionLink2).toHaveAttribute('daa-ll', await webUtil.getLinkDaall(data.linkText, 2, data.h2Text)); }); await test.step('step-3: Verify and log if any console errors', async () => { @@ -426,10 +403,9 @@ test.describe('Milo Marquee Block test suite', () => { }); await test.step('step-3: Verify analytic attributes', async () => { - const blueButtonDaalh = data.blueButtonText +'-1'+ '|' + (data.h2Text).slice(0, 20) ; - - expect(await webUtil.verifyAttributes_(marquee.marqueeSplitOneThird, marquee.attributes['analytics']['marquee.daa-lh'])).toBeTruthy(); - await expect(await marquee.blueButtonL).toHaveAttribute('daa-ll', blueButtonDaalh); + await expect(await marquee.marqueeSplitOneThird).toHaveAttribute('daa-lh', await webUtil.getBlockDaalh('marquee', 1)); + await expect(await marquee.blueButtonL).toHaveAttribute('daa-ll', await webUtil.getLinkDaall(data.blueButtonText, 1, data.h2Text)); + await expect(await marquee.actionLink2).toHaveAttribute('daa-ll', await webUtil.getLinkDaall(data.linkText, 2, data.h2Text)); }); await test.step('step-4: Verify and log if any console errors', async () => { @@ -462,10 +438,8 @@ test.describe('Milo Marquee Block test suite', () => { }); await test.step('step-3: Verify analytic attributes', async () => { - const blueButtonDaalh = data.blueButtonText +'-1'+ '|' + (data.h2Text).slice(0, 20) ; - - expect(await webUtil.verifyAttributes_(marquee.marqueeSplitOneThirdSmallLight, marquee.attributes['analytics']['marquee.daa-lh'])).toBeTruthy(); - await expect(await marquee.blueButtonL).toHaveAttribute('daa-ll', blueButtonDaalh); + await expect(await marquee.marqueeSplitOneThirdSmallLight).toHaveAttribute('daa-lh', await webUtil.getBlockDaalh('marquee', 1)); + await expect(await marquee.blueButtonL).toHaveAttribute('daa-ll', await webUtil.getLinkDaall(data.blueButtonText, 1, data.h2Text)); }); await test.step('step-4: Verify and log if any console errors', async () => { @@ -499,10 +473,8 @@ test.describe('Milo Marquee Block test suite', () => { }); await test.step('step-3: Verify analytic attributes', async () => { - const blueButtonDaalh = data.blueButtonText +'-1'+ '|' + (data.h2Text).slice(0, 20) ; - - expect(await webUtil.verifyAttributes_(marquee.marqueeSmallDark, marquee.attributes['analytics']['marquee.daa-lh'])).toBeTruthy(); - await expect(await marquee.blueButton).toHaveAttribute('daa-ll', blueButtonDaalh); + await expect(await marquee.marqueeSmallDark).toHaveAttribute('daa-lh', await webUtil.getBlockDaalh('marquee', 1)); + await expect(await marquee.blueButtonL).toHaveAttribute('daa-ll', await webUtil.getLinkDaall(data.blueButtonText, 1, data.h2Text)); }); await test.step('step-4: Verify and log if any console errors', async () => { @@ -540,12 +512,9 @@ test.describe('Milo Marquee Block test suite', () => { }); await test.step('step-3: Verify analytic attributes', async () => { - const blueButtonDaalh = data.blueButtonText +'-1'+ '|' + (data.h2Text).slice(0, 20) ; - const actionLink2Daalh = data.linkText +'-2'+ '|' + (data.h2Text).slice(0, 20) ; - - expect(await webUtil.verifyAttributes_(marquee.marqueeLargeLight, marquee.attributes['analytics']['marquee.daa-lh'])).toBeTruthy(); - await expect(await marquee.blueButtonXL).toHaveAttribute('daa-ll', blueButtonDaalh); - await expect(await marquee.actionLink2).toHaveAttribute('daa-ll', actionLink2Daalh); + await expect(await marquee.marqueeLargeLight).toHaveAttribute('daa-lh', await webUtil.getBlockDaalh('marquee', 1)); + await expect(await marquee.blueButtonXL).toHaveAttribute('daa-ll', await webUtil.getLinkDaall(data.blueButtonText, 1, data.h2Text)); + await expect(await marquee.actionLink2).toHaveAttribute('daa-ll', await webUtil.getLinkDaall(data.linkText, 2, data.h2Text)); }); await test.step('step-4: Verify and log if any console errors', async () => { @@ -582,10 +551,8 @@ test.describe('Milo Marquee Block test suite', () => { }); await test.step('step-3: Verify analytic attributes', async () => { - const blueButtonDaalh = data.blueButtonText +'-1'+ '|' + (data.h2Text).slice(0, 20) ; - - expect(await webUtil.verifyAttributes_(marquee.marqueeLargeDark, marquee.attributes['analytics']['marquee.daa-lh'])).toBeTruthy(); - await expect(await marquee.blueButtonXL).toHaveAttribute('daa-ll', blueButtonDaalh); + await expect(await marquee.marqueeLargeDark).toHaveAttribute('daa-lh', await webUtil.getBlockDaalh('marquee', 2)); + await expect(await marquee.blueButtonXL).toHaveAttribute('daa-ll', await webUtil.getLinkDaall(data.blueButtonText, 1, data.h2Text)); }); await test.step('step-4: Verify and log if any console errors', async () => { diff --git a/tests/milo/media.block.test.js b/tests/milo/media.block.test.js index 20546387..04b4b936 100644 --- a/tests/milo/media.block.test.js +++ b/tests/milo/media.block.test.js @@ -49,10 +49,8 @@ test.describe('Milo Media Block test suite', () => { }); await test.step('step-3: Verify analytics attributes', async () => { - const blueButtonDaalh = data.blueButtonText +'-1'+ '|' + (data.h2Text).slice(0, 20) ; - - expect(await webUtil.verifyAttributes_(media.mediaSmall, media.attributes['analytics']['media.daa-lh'])).toBeTruthy(); - await expect(await media.blueButton).toHaveAttribute('daa-ll', blueButtonDaalh); + await expect(await media.mediaSmall).toHaveAttribute('daa-lh', await webUtil.getBlockDaalh('media', 1)); + await expect(await media.blueButton).toHaveAttribute('daa-ll', await webUtil.getLinkDaall(data.blueButtonText, 1, data.h2Text)); }); await test.step('step-4: Verify browser console errors', async () => { @@ -85,10 +83,8 @@ test.describe('Milo Media Block test suite', () => { }); await test.step('step-3: Verify analytics attributes', async () => { - const blueButtonDaalh = data.blueButtonText +'-1'+ '|' + (data.h2Text).slice(0, 20) ; - - expect(await webUtil.verifyAttributes_(media.media, media.attributes['analytics']['media.daa-lh'])).toBeTruthy(); - await expect(await media.blueButton).toHaveAttribute('daa-ll', blueButtonDaalh); + await expect(await media.media).toHaveAttribute('daa-lh', await webUtil.getBlockDaalh('media', 1)); + await expect(await media.blueButton).toHaveAttribute('daa-ll', await webUtil.getLinkDaall(data.blueButtonText, 1, data.h2Text)); }); await test.step('step-4: Verify browser console errors', async () => { @@ -121,10 +117,8 @@ test.describe('Milo Media Block test suite', () => { }); await test.step('step-3: Verify analytics attributes', async () => { - const blueButtonDaalh = data.blueButtonText +'-1'+ '|' + (data.h2Text).slice(0, 20) ; - - expect(await webUtil.verifyAttributes_(media.mediaLargeDark, media.attributes['analytics']['media.daa-lh'])).toBeTruthy(); - await expect(await media.blueButton).toHaveAttribute('daa-ll', blueButtonDaalh); + await expect(await media.mediaLargeDark).toHaveAttribute('daa-lh', await webUtil.getBlockDaalh('media', 1)); + await expect(await media.blueButton).toHaveAttribute('daa-ll', await webUtil.getLinkDaall(data.blueButtonText, 1, data.h2Text)); }); await test.step('step-4: Verify browser console errors', async () => { @@ -159,10 +153,8 @@ test.describe('Milo Media Block test suite', () => { }); await test.step('step-3: Verify analytics attributes', async () => { - const blueButtonDaalh = data.blueButtonText +'-1'+ '|' + (data.h2Text).slice(0, 20) ; - - expect(await webUtil.verifyAttributes_(media.mediaLargeDark, media.attributes['analytics']['media.daa-lh'])).toBeTruthy(); - await expect(await media.blueButton).toHaveAttribute('daa-ll', blueButtonDaalh); + await expect(await media.mediaLargeDark).toHaveAttribute('daa-lh', await webUtil.getBlockDaalh('media', 2)); + await expect(await media.blueButton).toHaveAttribute('daa-ll', await webUtil.getLinkDaall(data.blueButtonText, 1, data.h2Text)); }); await test.step('step-4: Verify browser console errors', async () => { @@ -196,10 +188,8 @@ test.describe('Milo Media Block test suite', () => { }); await test.step('step-3: Verify analytics attributes', async () => { - const blueButtonDaalh = data.blueButtonText +'-1'+ '|' + (data.h2Text).slice(0, 20) ; - - expect(await webUtil.verifyAttributes_(media.mediaLargeDark, media.attributes['analytics']['media.daa-lh'])).toBeTruthy(); - await expect(await media.blueButton).toHaveAttribute('daa-ll', blueButtonDaalh); + await expect(await media.mediaLargeDark).toHaveAttribute('daa-lh', await webUtil.getBlockDaalh('media', 2)); + await expect(await media.blueButton).toHaveAttribute('daa-ll', await webUtil.getLinkDaall(data.blueButtonText, 1, data.h2Text)); }); await test.step('step-4: Verify browser console errors', async () => { @@ -208,3 +198,4 @@ test.describe('Milo Media Block test suite', () => { }); }); }); + diff --git a/tests/milo/text.block.test.js b/tests/milo/text.block.test.js index 12537909..98bdd25c 100644 --- a/tests/milo/text.block.test.js +++ b/tests/milo/text.block.test.js @@ -1,16 +1,21 @@ import { expect, test } from '@playwright/test'; +import { WebUtil } from '../../libs/webutil.js'; import { features } from '../../features/milo/text.block.spec.js'; import TextBlock from '../../selectors/milo/text.block.page.js'; let text; +let webUtil; test.describe('Milo Text Block test suite', () => { test.beforeEach(async ({ page }) => { text = new TextBlock(page); + webUtil = new WebUtil(page); }); + // Test 0 : Text test(`${features[0].name},${features[0].tags}`, async ({ page, baseURL }) => { console.info(`[Test Page]: ${baseURL}${features[0].path}`); + const { data } = features[0]; await test.step('step-1: Go to Text block test page', async () => { await page.goto(`${baseURL}${features[0].path}`); @@ -19,13 +24,27 @@ test.describe('Milo Text Block test suite', () => { }); await test.step('step-2: Verify Text specs', async () => { - const { data } = features[0]; - expect(await text.verifyText('text', data)).toBeTruthy(); + await expect(await text.text).toBeVisible(); + await expect(await text.headline).toContainText(data.h3Text); + await expect(await text.bodyM).toContainText(data.bodyText); + await expect(await text.outlineButton).toContainText(data.outlineButtonText); + + expect(await webUtil.verifyCSS_(text.headline, text.cssProperties['heading-l'])).toBeTruthy(); + expect(await webUtil.verifyCSS_(text.bodyM, text.cssProperties['body-m'])).toBeTruthy(); + expect(await webUtil.verifyCSS_(text.actionAreaLink, text.cssProperties['body-m'])).toBeTruthy(); + }); + + await test.step('step-3: Verify analytics attributes', async () => { + await expect(await text.text).toHaveAttribute('daa-lh', await webUtil.getBlockDaalh('text', 1)); + await expect(await text.outlineButton).toHaveAttribute('daa-ll', await webUtil.getLinkDaall(data.outlineButtonText, 1, data.h3Text)); + await expect(await text.actionAreaLink).toHaveAttribute('daa-ll', await webUtil.getLinkDaall(data.linkText, 2, data.h3Text)); }); }); + // Test 1 : Text (intro) test(`${features[1].name},${features[1].tags}`, async ({ page, baseURL }) => { console.info(`[Test Page]: ${baseURL}${features[1].path}`); + const { data } = features[1]; await test.step('step-1: Go to Text (intro) block test page', async () => { await page.goto(`${baseURL}${features[1].path}`); @@ -34,13 +53,25 @@ test.describe('Milo Text Block test suite', () => { }); await test.step('step-2: Verify Text (intro) specs', async () => { - const { data } = features[1]; - expect(await text.verifyText('text (intro)', data)).toBeTruthy(); + await expect(text.textIntro).toBeVisible(); + await expect(await text.introHeadline).toContainText(data.h2Text); + await expect(await text.bodyM).toContainText(data.bodyText); + + expect(await webUtil.verifyAttributes_(text.textIntro, text.attProperties['text-intro'])).toBeTruthy(); + expect(await webUtil.verifyCSS_(text.introDetailM, text.cssProperties['detail-m'])).toBeTruthy(); + expect(await webUtil.verifyCSS_(text.introHeadline, text.cssProperties['heading-l'])).toBeTruthy(); + expect(await webUtil.verifyCSS_(text.bodyM, text.cssProperties['body-m'])).toBeTruthy(); }); + + await test.step('step-3: Verify analytics attributes', async () => { + await expect(await text.textIntro).toHaveAttribute('daa-lh', await webUtil.getBlockDaalh('text', 1)); + }); }); + // Test 2 : Text (full-width) test(`${features[2].name},${features[2].tags}`, async ({ page, baseURL }) => { console.info(`[Test Page]: ${baseURL}${features[2].path}`); + const { data } = features[2]; await test.step('step-1: Go to Text (full width) block test page', async () => { await page.goto(`${baseURL}${features[2].path}`); @@ -49,13 +80,28 @@ test.describe('Milo Text Block test suite', () => { }); await test.step('step-2: Verify Text (full width) specs', async () => { - const { data } = features[2]; - expect(await text.verifyText('text (full width)', data)).toBeTruthy(); + await expect(text.textFullWidth).toBeVisible(); + + await expect(await text.fullWidthHeadline).toContainText(data.h3Text); + await expect(await text.bodyM).toContainText(data.bodyText); + await expect(await text.bodyLink).toContainText(data.linkText); + + expect(await webUtil.verifyAttributes_(await text.textFullWidth, text.attProperties['text-full-width'])).toBeTruthy(); + expect(await webUtil.verifyCSS_(await text.fullWidthHeadline, text.cssProperties['heading-l'])).toBeTruthy(); + expect(await webUtil.verifyCSS_(await text.bodyM, text.cssProperties['body-m'])).toBeTruthy(); }); + + await test.step('step-3: Verify analytics attributes', async () => { + await expect(await text.textFullWidth).toHaveAttribute('daa-lh', await webUtil.getBlockDaalh('text', 1)); + await expect(await text.bodyLink).toHaveAttribute('daa-ll', await webUtil.getLinkDaall(data.linkText, 1, data.h3Text)); + }); + }); + // Test 3 : Text (full-width, large) test(`${features[3].name},${features[3].tags}`, async ({ page, baseURL }) => { console.info(`[Test Page]: ${baseURL}${features[3].path}`); + const { data } = features[3]; await test.step('step-1: Go to text (full-width, large) block test page', async () => { await page.goto(`${baseURL}${features[3].path}`); @@ -64,13 +110,27 @@ test.describe('Milo Text Block test suite', () => { }); await test.step('step-2: Verify Text (full-width, large) specs', async () => { - const { data } = features[3]; - expect(await text.verifyText('text (full-width, large)', data)).toBeTruthy(); + await expect(text.textFullWidthLarge).toBeVisible(); + + await expect(await text.fullWidthLargeHeadline).toContainText(data.h2Text); + await expect(await text.bodyM).toContainText(data.bodyText); + await expect(await text.bodyLink).toContainText(data.linkText); + + expect(await webUtil.verifyAttributes_(text.textFullWidthLarge, text.attProperties['text-full-width-large'])).toBeTruthy(); + expect(await webUtil.verifyCSS_(text.fullWidthLargeHeadline, text.cssProperties['heading-xl'])).toBeTruthy(); + expect(await webUtil.verifyCSS_(text.bodyM, text.cssProperties['body-m'])).toBeTruthy(); }); + + await test.step('step-3: Verify analytics attributes', async () => { + await expect(await text.textFullWidthLarge).toHaveAttribute('daa-lh', await webUtil.getBlockDaalh('text', 1)); + await expect(await text.bodyLink).toHaveAttribute('daa-ll', await webUtil.getLinkDaall(data.linkText, 1, data.h2Text)); + }); }); + // Test 4 : Text (long-form, large) test(`${features[4].name},${features[4].tags}`, async ({ page, baseURL }) => { console.info(`[Test Page]: ${baseURL}${features[4].path}`); + const { data } = features[4]; await test.step('step-1: Go to Text (long form, large) block test page', async () => { await page.goto(`${baseURL}${features[4].path}`); @@ -79,13 +139,27 @@ test.describe('Milo Text Block test suite', () => { }); await test.step('step-2: Verify Text (long form, large) specs', async () => { - const { data } = features[4]; - expect(await text.verifyText('text (long form, large)', data)).toBeTruthy(); + await expect(await text.textLongFormLarge).toBeVisible(); + + await expect(await text.longFormDetailL).toContainText(data.detailText); + await expect(await text.longFormLargeHeadline).toContainText(data.h2Text); + await expect(await text.bodyL).toContainText(data.bodyText); + + expect(await webUtil.verifyAttributes_(text.textLongFormLarge, text.attProperties['text-long-form-large'])).toBeTruthy(); + expect(await webUtil.verifyCSS_(text.longFormDetailL, text.cssProperties['detail-l'])).toBeTruthy(); + expect(await webUtil.verifyCSS_(text.longFormLargeHeadline, text.cssProperties['heading-l'])).toBeTruthy(); + expect(await webUtil.verifyCSS_(text.bodyL, text.cssProperties['body-l'])).toBeTruthy(); }); + + await test.step('step-3: Verify analytics attributes', async () => { + await expect(await text.textLongFormLarge).toHaveAttribute('daa-lh', await webUtil.getBlockDaalh('text', 1)); + }); }); + // Test 5 : Text (inset, medium, m-spacing) test(`${features[5].name},${features[5].tags}`, async ({ page, baseURL }) => { console.info(`[Test Page]: ${baseURL}${features[5].path}`); + const { data } = features[5]; await test.step('step-1: Go to Text (inset, medium, m-spacing ) block test page', async () => { await page.goto(`${baseURL}${features[5].path}`); @@ -94,13 +168,27 @@ test.describe('Milo Text Block test suite', () => { }); await test.step('step-2: Verify Text (inset, large, m spacing) specs', async () => { - const { data } = features[5]; - expect(await text.verifyText('text (inset, large, m spacing)', data)).toBeTruthy(); + await expect(await text.textInsetLargeMSpacing).toBeVisible(); + + await expect(await text.insetLargeMSpacingHeadline).toContainText(data.h3Text); + await expect(await text.bodyL).toContainText(data.bodyText); + await expect(await text.listOneItems).toHaveCount(data.listCount1); + + expect(await webUtil.verifyAttributes_(text.textInsetLargeMSpacing, text.attProperties['text-inset-medium-m-spacing'])).toBeTruthy(); + expect(await webUtil.verifyCSS_(text.insetLargeMSpacingHeadline, text.cssProperties['heading-m'])).toBeTruthy(); + expect(await webUtil.verifyCSS_(text.bodyL, text.cssProperties['body-l'])).toBeTruthy(); + expect(await webUtil.verifyCSS_(text.propertiesHeadingM, text.cssProperties['heading-m'])).toBeTruthy(); }); + + await test.step('step-3: Verify analytics attributes', async () => { + await expect(await text.textInsetLargeMSpacing).toHaveAttribute('daa-lh', await webUtil.getBlockDaalh('text', 1)); + }); }); + // Test 6 : Text (legal) test(`${features[6].name},${features[6].tags}`, async ({ page, baseURL }) => { console.info(`[Test Page]: ${baseURL}${features[6].path}`); + const { data } = features[6]; await test.step('step-1: Go to Text (legal) block test page', async () => { await page.goto(`${baseURL}${features[6].path}`); @@ -109,13 +197,25 @@ test.describe('Milo Text Block test suite', () => { }); await test.step('step-2: Verify Text (legal) specs', async () => { - const { data } = features[6]; - expect(await text.verifyText('text (legal)', data)).toBeTruthy(); + await expect(await text.textlegal).toBeVisible(); + + await expect(await text.generalTermsOfUse).toContainText(data.termsOfUseText); + await expect(await text.publishText).toContainText(data.publishText); + await expect(await text.generalTerms).toContainText(data.generalTermsText); + await expect(await text.legalInfoLink).toContainText(data.linkText); + + expect(await webUtil.verifyAttributes_(text.textlegal, text.attProperties['text-legal'])).toBeTruthy(); + expect(await webUtil.verifyCSS_(text.bodyXSS, text.cssProperties['body-xss'])).toBeTruthy(); }); + + await test.step('step-3: Verify analytics attributes', async () => { + await expect(await text.textlegal).toHaveAttribute('daa-lh', await webUtil.getBlockDaalh('text', 1)); + }); }); test(`${features[7].name},${features[7].tags}`, async ({ page, baseURL }) => { console.info(`[Test Page]: ${baseURL}${features[7].path}`); + const { data } = features[7]; await test.step('step-1: Go to Text (link-farm) block test page', async () => { await page.goto(`${baseURL}${features[7].path}`); @@ -124,9 +224,20 @@ test.describe('Milo Text Block test suite', () => { }); await test.step('step-2: Verify Text (link-farm) specs', async () => { - const { data } = features[7]; - expect(await text.verifyText('text (link-farm)', data)).toBeTruthy(); + await expect(await text.textLinkFarm).toBeVisible(); + + await expect(await text.linkFarmcolumns).toHaveCount(data.headingColumns); + await expect(await text.linkColumnOne).toHaveCount(data.linksCount); + await expect(await text.linkFormText).toContainText(data.linkText); + + expect(await webUtil.verifyAttributes_(text.textLinkFarm, text.attProperties['text-Link-farm'])).toBeTruthy(); + expect(await webUtil.verifyCSS_(text.linkFarmHeadline, text.cssProperties['heading-l'])).toBeTruthy(); + expect(await webUtil.verifyAttributes_(text.linkFarmcolumnheading, text.attProperties['headingprops'])).toBeTruthy(); }); + + await test.step('step-3: Verify analytics attributes', async () => { + await expect(await text.textLinkFarm).toHaveAttribute('daa-lh', await webUtil.getBlockDaalh('text', 1)); + }); }); }); diff --git a/utils/reporters/base-reporter.js b/utils/reporters/base-reporter.js index e6ddd63e..fde0d44e 100644 --- a/utils/reporters/base-reporter.js +++ b/utils/reporters/base-reporter.js @@ -108,7 +108,7 @@ class BaseReporter { exeEnv = 'CircleCI Environment'; const workflowId = process.env.CIRCLE_WORKFLOW_ID; const jobNumber = process.env.CIRCLE_BUILD_NUM; - runUrl = `https://app.circle.ci.adobe.com/pipelines/github/wcms/nala/${jobNumber}/workflows/${workflowId}/jobs/${jobNumber}`; + runUrl = `https://app.circleci.adobe.com/pipelines/github/wcms/nala/${jobNumber}/workflows/${workflowId}/jobs/${jobNumber}`; }else { envURL = process.env.LOCAL_TEST_LIVE_URL || 'N/A'; exeEnv = 'Local Environment'; From ca496c0519204f1ccb1afbe5d24d9f79a129b672 Mon Sep 17 00:00:00 2001 From: Santoshkumar Nateekar Date: Wed, 6 Dec 2023 13:44:11 -0800 Subject: [PATCH 25/53] [MWPW-140157] Personalization Test Scripts (#217) * fix circle-ci url * personalization test cases * update review comments * update the merch cards changes * update pzn test case --------- Co-authored-by: nateekar --- features/milo/personalization.spec.js | 44 +++++++ libs/webutil.js | 49 +++++++- selectors/milo/merchcard.block.page.js | 12 +- selectors/milo/text.block.page.js | 4 +- tests/milo/personalization.feature.test.js | 129 +++++++++++++++++++++ 5 files changed, 229 insertions(+), 9 deletions(-) create mode 100644 features/milo/personalization.spec.js create mode 100644 tests/milo/personalization.feature.test.js diff --git a/features/milo/personalization.spec.js b/features/milo/personalization.spec.js new file mode 100644 index 00000000..93b9be4c --- /dev/null +++ b/features/milo/personalization.spec.js @@ -0,0 +1,44 @@ +module.exports = { + name: 'Personalization Feature', + features: [ + { + tcid: '0', + name: '@Replace content', + desc: 'Personalization with action=replaceContent', + path: '/drafts/nala/features/personalization/pzn-replacecontent', + data: { + target: 'textpersonlization', + pznExpName:'param-target=textpersonlization', + pznFileName:'pzn1', + h3Text: 'Text' + }, + tags: '@pzn @smoke @regression @milo ', + }, + { + tcid: '1', + name: '@Insert Content Before', + desc: 'Personalization with action=insertContentBefore', + path: '/drafts/nala/features/personalization/pzn-insertcontent-before', + data: { + target: 'textpersonlization', + pznExpName:'param-target=textpersonlization', + pznFileName:'insert-content-before', + h3Text: 'Text' + }, + tags: '@pzn @smoke @regression @milo ', + }, + { + tcid: '2', + name: '@Insert Content After', + desc: 'Personalization with action=insertContentAfter', + path: '/drafts/nala/features/personalization/pzn-insertcontent-after', + data: { + target: 'textpersonlization', + pznExpName:'param-target=textpersonlization', + pznFileName:'insert-content-before', + h3Text: 'Text' + }, + tags: '@pzn @smoke @regression @milo ', + }, + ], +}; diff --git a/libs/webutil.js b/libs/webutil.js index ecaf86d5..08f61a63 100644 --- a/libs/webutil.js +++ b/libs/webutil.js @@ -345,6 +345,19 @@ exports.WebUtil = class WebUtil { return 'gnav'+ '|' + project + '|'+ 'nopzn' + '|' + 'nopzn' ; } +/** + * Generates analytic string for a given project. + * @param {string} project - The project identifier, defaulting to 'milo' if not provided. + * @param {string} pznExpName - Personalized experience name, which is sliced to its first 15 characters. + * @param {string} pznFileName - Manifest filename, which is sliced to its first 20 characters. + * @returns {string} - A string formatted as 'gnav|||'. + */ +async getPznGnavDaalh(project=milo, pznExpName, pznFileName) { + const slicedExpName = pznExpName.slice(0, 15); + const slicedFileName = pznFileName.slice(0, 15); + return 'gnav'+ '|' + project + '|'+ slicedExpName + '|' + slicedFileName ; +} + /** * Generates analytic string for a section based on a given counter value. * @param {number|string} counter - A counter value used to generate the section identifier. @@ -365,6 +378,40 @@ exports.WebUtil = class WebUtil { return 'b'+ counter + '|' + slicedBlockName + '|'+ 'nopzn' + '|' + 'nopzn' ; } +/** + * Generates personalization analytic string for a given block name and a counter. + * @param {string} blockName - The name of the block, which is sliced to its first 20 characters. + * @param {number|string} counter - A counter value i.e. block number. + * @param {string} pznExpName - Personalized experience name, which is sliced to its first 15 characters. + * @param {string} pznExpName - Manifest filename, which is sliced to its first 20 characters. + * @returns {string} - A string formatted as 'b|||'. + */ +async getPznBlockDaalh(blockName, counter, pznExpName, pznFileName) { + const slicedBlockName = blockName.slice(0, 20); + const slicedExpName = pznExpName.slice(0, 15); + const slicedFileName = pznFileName.slice(0, 15); + return 'b'+ counter + '|' + slicedBlockName + '|'+ slicedExpName + '|' + slicedFileName ; +} + +/** + * Generates an analytic string for a given block name and a counter. + * @param {string} blockName - The name of the block, which is sliced to its first 20 characters. + * @param {number|string} counter - A counter value, i.e., block number. + * @param {boolean} [pzn=false] - A boolean flag indicating whether to use pzntext. + * @param {string} [pzntext='nopzn'] - The pzntext to use when pzn is true, sliced to its first 15 characters. + * @returns {string} - A formatted string. + */ +async getBlockDaalh(blockName, counter, pzn = false, pzntext = 'nopzn') { + const slicedBlockName = blockName.slice(0, 20); + const slicedPzntext = pzntext.slice(0, 15); + if (pzn) { + return 'b' + counter + '|' + slicedBlockName + '|' + slicedPzntext + '|' + 'nopzn'; + } else { + return 'b' + counter + '|' + slicedBlockName + '|' + 'nopzn' + '|' + 'nopzn'; + } +} + + /** * Generates analytic string for link or button based on link/button text , a counter, and the last header text. * @param {string} linkText - The text of the link, which is cleaned and sliced to its first 20 characters. @@ -429,4 +476,4 @@ exports.WebUtil = class WebUtil { } } } -}; +}; \ No newline at end of file diff --git a/selectors/milo/merchcard.block.page.js b/selectors/milo/merchcard.block.page.js index 10a8b724..7113ee41 100644 --- a/selectors/milo/merchcard.block.page.js +++ b/selectors/milo/merchcard.block.page.js @@ -25,7 +25,7 @@ export default class Merchcard { this.strikethroughPriceRecurrence = this.inlinePrice2.locator('.price-recurrence'); // merch-card segment locators - this.segmentRibbon = this.merchCard.locator('.segment-ribbon'); + this.segmentRibbon = this.merchCard.locator('.segment-badge'); this.segmentTitle = this.segment.locator('h3[slot="heading-xs"]').nth(0); this.segmentDescription1 = this.segment.locator('div[slot="body-xs"] p').nth(0); this.segmentDescription2 = this.segment.locator('div[slot="body-xs"] p').nth(1); @@ -35,7 +35,7 @@ export default class Merchcard { // merch-card special offers this.sepcialOffersImage = this.sepcialOffers.locator('div[slot="bg-image"] img'); - this.sepcialOffersRibbon = this.merchCard.locator('.special-offers-ribbon'); + this.sepcialOffersRibbon = this.merchCard.locator('.special-offers-badge'); this.sepcialOffersTitleH4 = this.sepcialOffers.locator('h5[slot="detail-m"]'); this.sepcialOffersTitleH5 = this.sepcialOffers.locator('h4[slot="body-xss"]'); this.sepcialOffersTitleH3 = this.sepcialOffers.locator('h3[slot="heading-xs"]'); @@ -51,7 +51,7 @@ export default class Merchcard { // merch-card plans locators //this.productIcon = this.plans.locator('#shadow-root div.icons'); this.productIcon = this.plans.locator('img'); - this.plansRibbon = this.plans.locator('.plans-ribbon'); + this.plansRibbon = this.plans.locator('.plans-badge'); this.plansCardTitleH3 = this.plans.locator('h3[slot="heading-xs"]'); this.plansCardTitleH5 = this.plans.locator('h5[slot="detail-m"]'); this.plansCardDescription2 = this.plans.locator('div[slot="body-xs"] p').nth(2); @@ -70,13 +70,13 @@ export default class Merchcard { // merch-card attributes this.attributes = { 'segmentRibbon': { - 'style': 'background-color: #EDCC2D; color: #000000; ', + 'style': /background-color:\s*#EDCC2D;\s*color:\s*#000000;\s*/, }, 'specialOfferRibbon': { - 'style': 'background-color: #F68D2E; color: #000000; ', + 'style': /background-color:\s* #F68D2E;\s*color:\s*#000000;\s*/, }, 'plansRibbon': { - 'style': 'background-color: #EDCC2D; color: #000000; ', + 'style': /background-color:\s*#EDCC2D;\s*color:\s*#000000;\s*/, }, }; } diff --git a/selectors/milo/text.block.page.js b/selectors/milo/text.block.page.js index 4985b357..29060904 100644 --- a/selectors/milo/text.block.page.js +++ b/selectors/milo/text.block.page.js @@ -2,10 +2,10 @@ import { expect } from '@playwright/test'; import { WebUtil } from '../../libs/webutil.js'; export default class Text { - constructor(page) { + constructor(page, nth = 0) { this.page = page; // text locators - this.text = page.locator('.text'); + this.text = page.locator('.text').nth(nth); this.textIntro = this.page.locator('.text.intro'); this.textFullWidth = this.page.locator('.text.full-width'); this.textFullWidthLarge = this.page.locator('.text.full-width.large'); diff --git a/tests/milo/personalization.feature.test.js b/tests/milo/personalization.feature.test.js new file mode 100644 index 00000000..8b01fccd --- /dev/null +++ b/tests/milo/personalization.feature.test.js @@ -0,0 +1,129 @@ +import { expect, test } from '@playwright/test'; +import { WebUtil } from '../../libs/webutil.js'; +import { features } from '../../features/milo/personalization.spec.js'; +import MarqueeBlock from '../../selectors/milo/marquee.block.page.js'; +import TextBlock from '../../selectors/milo/text.block.page.js'; +import Howto from '../../selectors/milo/howto.block.page.js'; + +let webUtil; +let howto; +let marquee; +let text; +let pznUrl; + +test.describe('Milo Personalization feature test suite', () => { + test.beforeEach(async ({ page }) => { + webUtil = new WebUtil(page); + }); + + // Test 0 : Personalization (Replace content) + test(`${features[0].name},${features[0].tags}`, async ({ page, baseURL }) => { + console.info(`[Test Page]: ${baseURL}${features[0].path}`); + const data = features[0].data; + text = new TextBlock(page); + marquee = new MarqueeBlock(page); + pznUrl = `${baseURL}${features[0].path}${'?target='}${data.target}` + + await test.step('step-1: Go to default test page', async () => { + await page.goto(`${baseURL}${features[0].path}`); + await page.waitForLoadState('domcontentloaded'); + await expect(page).toHaveURL(`${baseURL}${features[0].path}`); + }); + + await test.step('step-2: Verify default test page content/specs', async () => { + await expect(await marquee.marquee).toBeVisible(); + }); + + await test.step('step-3: Navigate to personlized page and verify content/specs', async () => { + await page.goto(pznUrl); + await page.waitForLoadState('domcontentloaded'); + await expect(page).toHaveURL(pznUrl); + console.info(`[Pzn Page]: ${pznUrl}`); + + await expect(await text.text).toBeVisible(); + await expect(await text.headline).toContainText(data.h3Text); + + const blockDll = await webUtil.getPznBlockDaalh('text', 1, data.pznExpName, data.pznFileName) + await expect(await text.text).toHaveAttribute('daa-lh', blockDll); + }); + + }); + + // Test 1 : Personalization (Insert Content Before) + test(`${features[1].name},${features[1].tags}`, async ({ page, baseURL }) => { + console.info(`[Test Page]: ${baseURL}${features[1].path}`); + const data = features[1].data; + text = new TextBlock(page); + marquee = new MarqueeBlock(page); + pznUrl = `${baseURL}${features[1].path}${'?target='}${data.target}` + + await test.step('step-1: Go to default test page', async () => { + await page.goto(`${baseURL}${features[1].path}`); + await page.waitForLoadState('domcontentloaded'); + await expect(page).toHaveURL(`${baseURL}${features[1].path}`); + }); + + await test.step('step-2: Verify default test page content/specs', async () => { + await expect(await marquee.marquee).toBeVisible(); + }); + + await test.step('step-3: Navigate to personlized page and verify content/specs', async () => { + await page.goto(pznUrl); + await page.waitForLoadState('domcontentloaded'); + await expect(page).toHaveURL(pznUrl); + console.info(`[Pzn Page]: ${pznUrl}`); + + await expect(await text.text).toBeVisible(); + await expect(await text.headline).toContainText(data.h3Text); + + // text block Dll analytics + const textBlockDll = await webUtil.getPznBlockDaalh('text', 1, data.pznExpName, data.pznFileName) + await expect(await text.text).toHaveAttribute('daa-lh', textBlockDll); + + // Marquee block Dll analytics + await expect(await marquee.marquee).toBeVisible(); + const marqueeBlockDll = await webUtil.getPznBlockDaalh('marquee', 2, data.pznExpName, data.pznFileName) + await expect(await marquee.marquee).toHaveAttribute('daa-lh', marqueeBlockDll); + }); + + }); + + // Test 2 : Personalization (Insert Content After) + test(`${features[2].name},${features[2].tags}`, async ({ page, baseURL }) => { + console.info(`[Test Page]: ${baseURL}${features[2].path}`); + const data = features[2].data; + text = new TextBlock(page); + howto = new Howto(page); + pznUrl = `${baseURL}${features[2].path}${'?target='}${data.target}` + + await test.step('step-1: Go to default test page', async () => { + await page.goto(`${baseURL}${features[2].path}`); + await page.waitForLoadState('domcontentloaded'); + await expect(page).toHaveURL(`${baseURL}${features[2].path}`); + }); + + await test.step('step-2: Verify default test page content/specs', async () => { + await expect(await howto.howTo).toBeVisible(); + }); + + await test.step('step-3: Navigate to personlized page and verify content/specs', async () => { + await page.goto(pznUrl); + await page.waitForLoadState('domcontentloaded'); + await expect(page).toHaveURL(pznUrl); + console.info(`[Pzn Page]: ${pznUrl}`); + + await expect(await text.text).toBeVisible(); + await expect(await text.headline).toContainText(data.h3Text); + + // HowTo block Dll analytics + await expect(await howto.howTo).toBeVisible(); + const howtoBlockDll = await webUtil.getPznBlockDaalh('how-to', 1, data.pznExpName, data.pznFileName) + await expect(await howto.howTo).toHaveAttribute('daa-lh', howtoBlockDll); + + // text block Dll analytics + const textBlockDll = await webUtil.getPznBlockDaalh('text', 2, data.pznExpName, data.pznFileName) + await expect(await text.text).toHaveAttribute('daa-lh', textBlockDll); + }); + }); + +}); From 60279e05ed7086243e913cf6ccf1650730a77c10 Mon Sep 17 00:00:00 2001 From: Santoshkumar Nateekar Date: Thu, 7 Dec 2023 02:53:29 -0800 Subject: [PATCH 26/53] MWPW-140218 : Refactor CC automation test scripts and introduce daily runs (#218) * update cc tests and add daily run * testing the scheduler --------- Co-authored-by: nateekar --- .github/workflows/cc.daily.yml | 44 ++++++ .github/workflows/daily.yml | 2 +- configs/cc.config.js | 1 + dailyrun.sh | 19 +++ features/cc/fedpub.spec.js | 9 +- selectors/cc/fedpub.page.js | 15 +++ selectors/cc/fedpub.selectors.js | 19 --- selectors/cc/ostprices.page.js | 85 ++++++------ tests/cc/fedpub.test.js | 29 ++-- tests/cc/ostprices.test.js | 225 +++++++++++++++++++------------ 10 files changed, 288 insertions(+), 160 deletions(-) create mode 100644 .github/workflows/cc.daily.yml create mode 100644 dailyrun.sh create mode 100644 selectors/cc/fedpub.page.js delete mode 100644 selectors/cc/fedpub.selectors.js diff --git a/.github/workflows/cc.daily.yml b/.github/workflows/cc.daily.yml new file mode 100644 index 00000000..69c7ff1a --- /dev/null +++ b/.github/workflows/cc.daily.yml @@ -0,0 +1,44 @@ +name: CC Nala Daily Run + +on: + schedule: + - cron: '*/10 * * * *' + +jobs: + platform_matrix: + strategy: + fail-fast: false + matrix: + os: [ubuntu-latest, windows-latest, macos-latest] + name: Running tests + runs-on: ${{ matrix.os }} + env: + WORKFLOW_NAME: 'CC Nala Daily Run' + + steps: + - name: Check out repository + uses: actions/checkout@v3 + + - name: Set up Node.js + uses: actions/setup-node@v3 + with: + node-version: lts/* + + - name: Run Nala ${{ matrix.os }} + uses: bash dailyrun.sh cc + env: + IMS_EMAIL: ${{ secrets.IMS_EMAIL }} + IMS_PASS: ${{ secrets.IMS_PASS }} + HLX_TKN: ${{ secrets.HLX_TKN }} + SLACK_WH: ${{ secrets.SLACK_WH }} + + - name: Display workflow name + run: echo "The workflow name is $WORKFLOW_NAME" + + - name: Persist JSON Artifact + uses: actions/upload-artifact@v3 + if: always() + with: + name: nala-results + path: nala-results.json + retention-days: 30 diff --git a/.github/workflows/daily.yml b/.github/workflows/daily.yml index e5c1f770..167c80b6 100644 --- a/.github/workflows/daily.yml +++ b/.github/workflows/daily.yml @@ -1,4 +1,4 @@ -name: Run Nala Daily +name: Milo Nala Daily Run on: schedule: diff --git a/configs/cc.config.js b/configs/cc.config.js index c65a8b3b..5f61bca3 100644 --- a/configs/cc.config.js +++ b/configs/cc.config.js @@ -10,6 +10,7 @@ const envs = require('../envs/envs.js'); const config = { testDir: '../tests/cc', outputDir: '../test-results', + globalSetup: '../global.setup.js', /* Maximum time one test can run for. */ timeout: 30 * 1000, expect: { diff --git a/dailyrun.sh b/dailyrun.sh new file mode 100644 index 00000000..0dbd1d9a --- /dev/null +++ b/dailyrun.sh @@ -0,0 +1,19 @@ +#!/bin/bash + +# get the input argument i.e. config.js file name +PROJECT_NAME=$1 + +# Construct the full path to the config.js file +CONFIG_FILE_PATH="./configs/${PROJECT_NAME}.config.js" + +# Check if the config.js file exists +if [ -f "${CONFIG_FILE_PATH}" ]; then + echo "*** Running Playwright tests with config: ${CONFIG_FILE_PATH} ***" + npx playwright test --config="${CONFIG_FILE_PATH}" --project="${PROJECT_NAME}-live-chrome" + npx playwright test --config="${CONFIG_FILE_PATH}" --project="${PROJECT_NAME}-live-firefox" +else + echo "Config file: ${CONFIG_FILE_PATH} not found, running default tests" + exit 1 +fi + + diff --git a/features/cc/fedpub.spec.js b/features/cc/fedpub.spec.js index 794f9a4a..c646c3b6 100644 --- a/features/cc/fedpub.spec.js +++ b/features/cc/fedpub.spec.js @@ -5,8 +5,13 @@ module.exports = { tcid: '0', name: '@FedPub-Sanity-Check', path: '/creativecloud/photography/hub/guides/camera-settings-for-rain-photography', - envs: '@cc_live @adobe_stage', - tags: '@cc @cc-fedpub', + data: { + title: 'The best camera settings for rain photography.', + subTitle1: 'Choose the right camera settings for a rainy day.', + subTitle2: 'Use Adobe photo editing software.', + tryForFreeHref: 'https://www.adobe.com/creativecloud/photography.html#mini-plans-web-cta-photoshop-lightroom-card', + }, + tags: '@cc @cc-fedpub @smoke @regression', }, ], }; diff --git a/selectors/cc/fedpub.page.js b/selectors/cc/fedpub.page.js new file mode 100644 index 00000000..325a67eb --- /dev/null +++ b/selectors/cc/fedpub.page.js @@ -0,0 +1,15 @@ +export default class FedPub { + constructor(page, nth=0) { + this.page = page; + + this.section = this.page.locator('.section').nth(nth); + this.readingWith = this.page.locator('.reading-with').nth(nth); + + // FedPub locators + this.fedPubTitle = this.page.locator('h1#the-best-camera-settings-for-rain-photography'); + this.fedPubSubtitle1 = this.page.locator('h2#choose-the-right-camera-settings-for-a-rainy-day'); + this.fedPubSubtitle2 = this.page.locator('h2#use-adobe-photo-editing-software'); + this.tryForFreeButton = this.page.locator('a.feds-cta').nth(0); + this.rainPhotographyTextLink = this.page.locator('a[href*="rain-photography"]'); +} +}; diff --git a/selectors/cc/fedpub.selectors.js b/selectors/cc/fedpub.selectors.js deleted file mode 100644 index e34a15d7..00000000 --- a/selectors/cc/fedpub.selectors.js +++ /dev/null @@ -1,19 +0,0 @@ -exports.FedPub = class FedPub { - constructor(page) { - this.page = page; - this.props = { - fedPubTitle: 'The best camera settings for rain photography.', - fedPubSubtitle1: 'Choose the right camera settings for a rainy day.', - fedPubSubtitle2: 'Use Adobe photo editing software.', - tryForFreeHref: 'https://www.adobe.com/creativecloud/photography.html#mini-plans-web-cta-photoshop-lightroom-card', - }; - - // FedPub Selectors: - this.fedPubTitle = page.locator('h1#the-best-camera-settings-for-rain-photography'); - this.fedPubSubtitle1 = page.locator('h2#choose-the-right-camera-settings-for-a-rainy-day'); - this.fedPubSubtitle2 = page.locator('h2#use-adobe-photo-editing-software'); - this.tryForFreeButton = page.locator('a.con-button.button-m'); - } - - // >> FedPub methods declared below << -}; diff --git a/selectors/cc/ostprices.page.js b/selectors/cc/ostprices.page.js index 4f156347..9c9d1f4e 100644 --- a/selectors/cc/ostprices.page.js +++ b/selectors/cc/ostprices.page.js @@ -1,55 +1,60 @@ -import { expect } from '@playwright/test'; -import { WebUtil } from '../../libs/webutil.js'; - export default class ostprices { constructor(page) { this.page = page; // ccsubsciton currency format, price and buynow email CTA check out flows in US and Jp pages - this.productname = page.locator('//em[contains(text(),"Creative cloud all apps :")]'); - this.uscountrycurrencysymbol = page.locator('.price-currency-symbol'); - this.pricebeforedelimiter = page.locator('.price-integer'); - this.priceafterdelimiter = page.locator('.price-decimals'); - this.licensecommitment = page.locator('.price-recurrence'); - this.numberoflicenses = page.locator('.price-unit-type'); - this.buynowcta = page.locator('//a[@daa-ll="Buy now-1|Make Create Amazing"]'); + this.productName = page.locator('//em[contains(text(),"Creative cloud all apps :")]'); + this.usCurrencySymbol = page.locator('.price-currency-symbol'); + this.priceBeforeDelimiter = page.locator('.price-integer'); + this.priceAfterDelimiter = page.locator('.price-decimals'); + this.licenseCommitment = page.locator('.price-recurrence'); + this.numberofLicenses = page.locator('.price-unit-type'); + + this.emailBuynowCta = page.locator('a.con-button[data-checkout-workflow-step="email"]').nth(0); + this.emailBuynowCta2 = page.locator('a.con-button[data-checkout-workflow-step="email"]').nth(1); + this.segmentationBuynowCta = page.locator('a[data-checkout-workflow-step="segmentation"]'); + this.bundleBuynowCta = page.locator('a[data-checkout-workflow-step="bundle"]'); + this.price = page.locator('//span[@class="price"]'); - this.jpproductprice = page.locator('//span[@aria-label="10,280 円 毎月 ライセンスごと"]'); - this.jpcountrycurrencysymbol = page.locator('.price-currency-symbol'); + this.jpProductPrice = page.locator('//span[@aria-label="10,280 円 毎月 ライセンスごと"]'); + this.jpCurrencySymbol = page.locator('.price-currency-symbol'); + // cc all apps price with segment CTA checkout - this.productname_1 = page.locator('//p[contains(text(),"CC Starting from(month) : ")]'); - this.cc_pricebeforedelimiter = page.locator('.price-integer').first(); - this.cc_priceafterdelimiter = page.locator('.price-decimals').first(); - this.cc_licensecommitment = page.locator('.price-recurrence').first(); - this.cc_numberoflicenses = page.locator('.price-unit-type').first(); - this.productname_2 = page.locator('//p[contains(text(),"PS Purchase (year) : ")]'); - this.ps_pricebeforedelimiter = page.locator('.price-integer').last(); - this.ps_priceafterdelimiter = page.locator('.price-decimals').last(); - this.ps_licensecommitment = page.locator('.price-recurrence').last(); - this.ps_numberoflicenses = page.locator('.price-unit-type').last(); - this.cc_buynowcta = page.locator('//a[@daa-ll="Buy now-1|Generative AI.This c"]'); + this.productName1 = page.locator('//p[contains(text(),"CC Starting from(month) : ")]'); + this.ccPriceBeforeDelimiter = page.locator('.price-integer').first(); + this.ccPriceAfterDelimiter = page.locator('.price-decimals').first(); + this.ccLicenseCommitment = page.locator('.price-recurrence').first(); + this.ccNumberOfLicenses = page.locator('.price-unit-type').first(); + this.productName2 = page.locator('//p[contains(text(),"PS Purchase (year) : ")]'); + this.psPriceBeforeDelimiter = page.locator('.price-integer').last(); + this.psPriceAfterDelimiter = page.locator('.price-decimals').last(); + this.psLicenseCommitment = page.locator('.price-recurrence').last(); + this.psNumberOfLicenses = page.locator('.price-unit-type').last(); + this.cc_pricemonth_jp = page.locator('//span[@aria-label="5,891 円 毎月 ライセンスごと"]'); this.ps_priceyear_jp = page.locator('//span[@aria-label="28,776 円 毎年 ライセンスごと"]'); + // Student teacher edition price checks - this.STEProductname = page.locator('h2#adobe-light-room'); - this.STE_LR_price = page.locator('//span[@aria-label="US$4.44 per month per license"]'); - this.STE_LR_JP_price = page.locator('//span[@aria-label="980 円 毎月 ライセンスごと"]'); + this.SteProductName = page.locator('h2#adobe-light-room'); + this.SteLrPrice = page.locator('//span[@aria-label="US$4.44 per month per license"]'); + this.SteLrJpPrice = page.locator('//span[@aria-label="980 円 毎月 ライセンスごと"]'); this.STEgetstarted_CTA = page.locator('//a[@daa-ll="Get started-1|Adobe Light room"]'); + // display of strike through prince, slection of bundle price for commerce store - this.producatname_3 = page.locator('h3#creative-cloud'); - this.pricelabel_actual = page.locator('//p[contains(text(),"Actual price : ")]'); - this.strikethroughproperty = page.locator('//span[@data-template="priceStrikethrough"]'); - this.strikethrouthprice = page.locator('//span[@aria-label="US$89.99 per month per license"]').first(); - this.strikethroughprice_jp_1 = page.locator('//span[@aria-label="9,346 円 毎月 ライセンスごと"]').first(); - this.pricelabel_now = page.locator('//p[contains(text(),"Now its: ")]'); + this.productName3 = page.locator('h3#creative-cloud'); + this.priceLabelActual = page.locator('//p[contains(text(),"Actual price : ")]'); + this.strikeThroughProperty = page.locator('//span[@data-template="priceStrikethrough"]'); + this.strikeThroughPrice = page.locator('//span[@aria-label="US$89.99 per month per license"]').first(); + this.strikeThroughPriceJp1 = page.locator('//span[@aria-label="9,346 円 毎月 ライセンスごと"]').first(); + this.priceLabelNow = page.locator('//p[contains(text(),"Now its: ")]'); this.purchaseCTAbandle = page.locator('//a[@daa-ll="choose a plan-1|Actual price"]'); - this.strikethroughproductprice_jp = page.locator('//span[@aria-label="9,346 円 per month per license"]'); + // page has card layout with month , year prices and CTAs - this.headingdiscription = page.locator('//h3[@slot="heading-xs"]').first(); - this.headingdiscription2 = page.locator('//h3[@slot="heading-xs"]').last(); - this.firstcardheading = page.locator('//h3[contains(text(),"Individuals PS year subscription")]'); - this.individualPSpricemonth = page.locator('//span[@aria-label="US$22.99 per month per license"]'); - this.individualPSpriceyear = page.locator('//span[@aria-label="US$263.88 per year per license"]'); - this.individualPSpricemonth_jp = page.locator('//span[@aria-label="2,480 円 毎月 ライセンスごと"]'); - this.individualPSpriceyear_jp = page.locator('//span[@aria-label="26,160 円 毎年 ライセンスごと"]'); + this.headingDiscription = page.locator('//h3[@slot="heading-xs"]').first(); + this.headingDiscription2 = page.locator('//h3[@slot="heading-xs"]').last(); + this.firstCardHeading = page.locator('//h3[contains(text(),"Individuals PS year subscription")]'); + this.individualPsPriceMonth = page.locator('//span[@aria-label="US$22.99 per month per license"]'); + this.individualPsPriceYear = page.locator('//span[@aria-label="US$263.88 per year per license"]'); + this.individualPsPriceMonthJP = page.locator('.price').nth(0); + this.individualPsPriceYearJP = page.locator('.price').nth(1); } }; diff --git a/tests/cc/fedpub.test.js b/tests/cc/fedpub.test.js index 771f8db7..7f785525 100644 --- a/tests/cc/fedpub.test.js +++ b/tests/cc/fedpub.test.js @@ -1,37 +1,38 @@ -/* eslint-disable import/named */ -/* eslint-disable no-await-in-loop */ -/* eslint-disable import/extensions */ import { expect, test } from '@playwright/test'; -import { FedPub } from '../../selectors/cc/fedpub.selectors.js'; -import * as FedPubSpec from '../../features/cc/fedpub.spec.js'; +import { features } from '../../features/cc/fedpub.spec.js'; +import FedPub from '../../selectors/cc/fedpub.page.js'; -const { features } = FedPubSpec; test.describe('FedPub Sanity test suite', () => { - // FedPub Sanity Checks: + + //Test 0 : FedPub-Sanity-Check test(`${features[0].name}, ${features[0].tags}`, async ({ page, baseURL }) => { + console.info(`[Test Page]: ${baseURL}${features[0].path}`); const fedpub = new FedPub(page); - console.info(`[FedPub] Checking page: ${baseURL}${features[0].path}`); + const { data } = features[0]; - await test.step('Navigate to FedPub page', async () => { + await test.step('step-1: Navigate to FedPub page', async () => { await page.goto(`${baseURL}${features[0].path}`); await page.waitForLoadState('networkidle'); await expect(page).toHaveURL(`${baseURL}${features[0].path}`); }); - await test.step('Check FedPub page content', async () => { + await test.step('step-2: Check FedPub page content', async () => { // Check page title: await expect(fedpub.fedPubTitle).toBeVisible(); - await expect(fedpub.fedPubTitle).toHaveText(fedpub.props.fedPubTitle); + await expect(fedpub.fedPubTitle).toHaveText(data.title); + // Check page first subtitle: await expect(fedpub.fedPubSubtitle1).toBeVisible(); - await expect(fedpub.fedPubSubtitle1).toHaveText(fedpub.props.fedPubSubtitle1); + await expect(fedpub.fedPubSubtitle1).toHaveText(data.subTitle1); + // Check page second subtitle: await expect(fedpub.fedPubSubtitle2).toBeVisible(); - await expect(fedpub.fedPubSubtitle2).toHaveText(fedpub.props.fedPubSubtitle2); + await expect(fedpub.fedPubSubtitle2).toHaveText(data.subTitle2); + // Check page 'Try for free' button: await expect(fedpub.tryForFreeButton).toBeVisible(); - await expect(fedpub.tryForFreeButton).toHaveAttribute('href', fedpub.props.tryForFreeHref); + await expect(fedpub.tryForFreeButton).toHaveAttribute('href', data.tryForFreeHref); }); }); }); diff --git a/tests/cc/ostprices.test.js b/tests/cc/ostprices.test.js index 423618a5..26c76ac4 100644 --- a/tests/cc/ostprices.test.js +++ b/tests/cc/ostprices.test.js @@ -8,56 +8,73 @@ test.describe('test Offer selector tool price formats and checkout flows in US & ost = new Ostprices(page); }); + // Test 0 : OST Currency Format price buy emailcta test(`${features[0].name},${features[0].tags}`, async ({ page, baseURL }) => { console.info(`[Test Page]: ${baseURL}${features[0].path}`); - await test.step('page marquee shows the CC price and CTA US locale', async () => { + + await test.step('step-1: page marquee shows the CC price and CTA US locale', async () => { await page.goto(`${baseURL}${features[0].path}`); await page.waitForLoadState('domcontentloaded'); await expect(page).toHaveURL(`${baseURL}${features[0].path}`); - }); + }); - await test.step('Test CC all apps price and UCv3 email checkout, buy button checks in marquee', async () => { - await page.waitForLoadState(); - await expect(await ost.productname).toBeTruthy(); - await expect(ost.uscountrycurrencysymbol).toBeTruthy(); - await expect(ost.price).toBeVisible(); - await expect(ost.buynowcta).toBeVisible(); - await expect(ost.pricebeforedelimiter).toBeVisible(); - await page.locator('//a[@daa-ll="Buy now-1|Make Create Amazing"]').click(); - await expect(page).toHaveURL(new RegExp('^https://commerce.adobe.com/store/')); + await test.step('step-2: Test CC all apps price and UCv3 email checkout, buy button checks in marquee', async () => { + await page.waitForLoadState(); + + expect(await ost.productName).toBeTruthy(); + expect(await ost.usCurrencySymbol).toBeTruthy(); + + await expect(await ost.price).toBeVisible(); + await expect(await ost.emailBuynowCta).toBeVisible(); + await expect(await ost.priceBeforeDelimiter).toBeVisible(); + + // click 'Buy now' (ucv3 checkout) button and verify the checkout page. + await ost.emailBuynowCta.click() + await page.waitForTimeout(1000); + await expect(page).toHaveURL(new RegExp('^https://commerce.adobe.com/store/')); + }); }); -}); + // Test 1 : OST CC all apps price buy segment cta test(`${features[1].name},${features[1].tags}`, async ({ page, baseURL }) => { console.info(`[Test Page]: ${baseURL}${features[1].path}`); - await test.step('page checks with month and year CC subscription, checkout', async () => { + + await test.step('step-1: page checks with month and year CC subscription, checkout', async () => { await page.goto(`${baseURL}${features[1].path}`); await page.waitForLoadState('domcontentloaded'); await expect(page).toHaveURL(`${baseURL}${features[1].path}`); }); - await test.step('Verify the month and year price display , CTA for UCv3 segment checkout destination', async () => { + await test.step('step-2: Verify the month and year price display , CTA for UCv3 segment checkout destination', async () => { await page.waitForLoadState(); - await expect(ost.productname_1).toBeTruthy(); - await expect(ost.uscountrycurrencysymbol).toBeTruthy(); - await expect(ost.cc_pricebeforedelimiter).toBeVisible(); - await expect(ost.cc_priceafterdelimiter).toBeVisible(); - await expect(ost.cc_licensecommitment).toBeVisible(); - await expect(ost.cc_numberoflicenses).toBeVisible(); - await expect(ost.productname_2).toBeTruthy(); - await expect(ost.uscountrycurrencysymbol).toBeTruthy(); - await expect(ost.ps_pricebeforedelimiter).toBeVisible(); - await expect(ost.ps_priceafterdelimiter).toBeVisible(); - await expect(ost.ps_licensecommitment).toBeVisible(); - await expect(ost.ps_numberoflicenses).toBeVisible(); - await page.locator('//a[@daa-ll="Buy now-1|Generative AI.This c"]').click(); + expect(ost.productName1).toBeTruthy(); + expect(ost.usCurrencySymbol).toBeTruthy(); + + await expect(ost.ccPriceBeforeDelimiter).toBeVisible(); + await expect(ost.ccPriceAfterDelimiter).toBeVisible(); + await expect(ost.ccLicenseCommitment).toBeVisible(); + await expect(ost.ccNumberOfLicenses).toBeVisible(); + + await expect(ost.productName2).toBeTruthy(); + await expect(ost.usCurrencySymbol).toBeTruthy(); + + await expect(ost.psPriceBeforeDelimiter).toBeVisible(); + await expect(ost.psPriceAfterDelimiter).toBeVisible(); + await expect(ost.psLicenseCommitment).toBeVisible(); + await expect(ost.psNumberOfLicenses).toBeVisible(); + + // click 'Buy now' (ucv3 checkout, checkout workflow = email ) button and verify the checkout page. + await ost.segmentationBuynowCta.click() + await page.waitForTimeout(1000); await expect(page).toHaveURL(new RegExp('^https://commerce.adobe.com/store/segmentation')); }); }); + // Test 2 : OST student price buy cta test(`${features[2].name},${features[2].tags}`, async ({ page, baseURL }) => { console.info(`[Test Page]: ${baseURL}${features[2].path}`); - await test.step('Light room STE edition price display with email checkout cta destination', async () => { + + await test.step('step-1: Light room STE edition price display with email checkout cta destination', async () => { await page.goto(`${baseURL}${features[2].path}`); await page.waitForLoadState('domcontentloaded'); await expect(page).toHaveURL(`${baseURL}${features[2].path}`); @@ -65,17 +82,21 @@ test.describe('test Offer selector tool price formats and checkout flows in US & await test.step('step-2: verify LR STU price and email CTA', async () => { await page.waitForLoadState(); - await expect(ost.STEProductname).toBeTruthy(); - await expect(ost.uscountrycurrencysymbol).toBeTruthy(); - await expect(ost.STE_LR_price).toBeVisible(); - await page.locator('//a[@daa-ll="Get started-1|Adobe Light room"]').click(); + await expect(ost.SteProductName).toBeTruthy(); + await expect(ost.usCurrencySymbol).toBeTruthy(); + await expect(ost.SteLrPrice).toBeVisible(); + + await ost.emailBuynowCta.click(); + await page.waitForTimeout(1000); await expect(page).toHaveURL(new RegExp('^https://commerce.adobe.com/store/email')); }); }); + // Test 3 : OST strike-through price buy cta test(`${features[3].name},${features[3].tags}`, async ({ page, baseURL }) => { console.info(`[Test Page]: ${baseURL}${features[3].path}`); - await test.step('page authored with CC product strike through price', async () => { + + await test.step('step-1: page authored with CC product strike through price', async () => { await page.goto(`${baseURL}${features[3].path}`); await page.waitForLoadState('domcontentloaded'); await expect(page).toHaveURL(`${baseURL}${features[3].path}`); @@ -83,21 +104,26 @@ test.describe('test Offer selector tool price formats and checkout flows in US & await test.step('step-2: verify CC strike through prices are showup correctly with valid store bundle CTA destination', async () => { await page.waitForLoadState(); - await expect(ost.producatname_3).toBeVisible(); - await expect(ost.uscountrycurrencysymbol).toBeTruthy(); - await expect(ost.pricelabel_actual).toBeVisible(); - await expect(ost.strikethroughproperty).toBeTruthy(); - await expect(ost.strikethrouthprice).toBeVisible(); - await expect(ost.pricelabel_now).toBeVisible(); - await expect(ost.purchaseCTAbandle).toBeVisible(); - await page.locator('//a[@daa-ll="choose a plan-1|Actual price"]').click(); - await expect(page).toHaveURL(new RegExp('^https://commerce.adobe.com/store/bundle')); + await expect(ost.productName3).toBeVisible(); + await expect(ost.usCurrencySymbol).toBeTruthy(); + await expect(ost.priceLabelActual).toBeVisible(); + await expect(ost.strikeThroughProperty).toBeTruthy(); + await expect(ost.strikeThroughPrice).toBeVisible(); + await expect(ost.priceLabelNow).toBeVisible(); + + // click 'Choose a plan' (ucv3 checkout, checkout workflow = bundle ) button and verify the checkout page. + await expect(ost.bundleBuynowCta).toBeVisible(); + await ost.bundleBuynowCta.click(); + await page.waitForTimeout(1000); + await expect(page).toHaveURL(new RegExp('^https://commerce.adobe.com/store/')); }); }); + // Test 4 : OST month-year-prices buy cta test(`${features[4].name},${features[4].tags}`, async ({ page, baseURL }) => { console.info(`[Test Page]: ${baseURL}${features[4].path}`); - await test.step('Product - photoshop month, year price with CTAs', async () => { + + await test.step('step-1: Product - photoshop month, year price with CTAs', async () => { await page.goto(`${baseURL}${features[4].path}`); await page.waitForLoadState('domcontentloaded'); await expect(page).toHaveURL(`${baseURL}${features[4].path}`); @@ -105,59 +131,76 @@ test.describe('test Offer selector tool price formats and checkout flows in US & await test.step('step-2: Photoshop product month, year price with CTAs', async () => { await page.waitForLoadState(); - await expect(ost.headingdiscription).toBeTruthy(); - await expect(ost.headingdiscription2).toBeTruthy(); - await expect(ost.firstcardheading).toBeVisible(); - await expect(ost.individualPSpricemonth).toBeVisible(); - await expect(ost.individualPSpriceyear).toBeVisible(); - await page.locator('//a[@class="con-button placeholder-resolved"]').first().click(); + await expect(ost.headingDiscription).toBeTruthy(); + await expect(ost.headingDiscription2).toBeTruthy(); + await expect(ost.firstCardHeading).toBeVisible(); + await expect(ost.individualPsPriceMonth).toBeVisible(); + await expect(ost.individualPsPriceYear).toBeVisible(); + + await ost.emailBuynowCta.click(); + await page.waitForTimeout(1000); await expect(page).toHaveURL(new RegExp('^https://commerce.adobe.com/store/')); }); }); + // Test 5 : OST JP currency format-price buy email cta test(`${features[5].name},${features[5].tags}`, async ({ page, baseURL }) => { console.info(`[Test Page]: ${baseURL}${features[5].path}`); - await test.step('page marquee shows the CC price and CTA for JP', async () => { + + await test.step('step-1: page marquee shows the CC price and CTA for JP', async () => { await page.goto(`${baseURL}${features[5].path}`); await page.waitForLoadState('domcontentloaded'); await expect(page).toHaveURL(`${baseURL}${features[5].path}`); }); - await test.step('Test CC all apps price and UCv3 email checkout, buy button checks in marquee for JP', async () => { + await test.step('step-2: Test CC all apps price and UCv3 email checkout, buy button checks in marquee for JP', async () => { await page.waitForLoadState(); - await expect(ost.productname).toBeVisible(); - await expect(ost.jpcountrycurrencysymbol).toBeVisible(); - await expect(ost.jpproductprice).toBeVisible(); - await page.locator('//a[@daa-ll="Buy now-1|Make Create Amazing"]').click(); + await expect(ost.productName).toBeVisible(); + await expect(ost.jpCurrencySymbol).toBeVisible(); + await expect(ost.jpProductPrice).toBeVisible(); + + // click 'Buy now' (ucv3 checkout, checkout workflow = email ) button and verify the checkout page. + await expect(ost.emailBuynowCta).toBeVisible(); + await ost.emailBuynowCta.click(); + await page.waitForTimeout(1000); await expect(page).toHaveURL(new RegExp('^https://commerce.adobe.com/store/')); await expect(page).toHaveURL(new RegExp('co=JP&lang=ja')); }); }); + // Test 6 : OST JP currency format-price buy email cta test(`${features[6].name},${features[6].tags}`, async ({ page, baseURL }) => { console.info(`[Test Page]: ${baseURL}${features[6].path}`); - await test.step('product with month, year subscriptions in JP', async () => { + + await test.step('step-1: product with month, year subscriptions in JP', async () => { await page.goto(`${baseURL}${features[6].path}`); await page.waitForLoadState('domcontentloaded'); await expect(page).toHaveURL(`${baseURL}${features[6].path}`); }); - await test.step('JP locale monthly, year subscriptions', async () => { + await test.step('step-2: JP locale monthly, year subscriptions', async () => { await page.waitForLoadState(); - await expect(ost.productname_1).toBeVisible(); - await expect(ost.productname_2).toBeVisible(); + await expect(ost.productName1).toBeVisible(); + await expect(ost.productName2).toBeVisible(); await expect(ost.cc_pricemonth_jp).toBeVisible(); await expect(ost.ps_priceyear_jp).toBeVisible(); - await expect(ost.jpcountrycurrencysymbol).toBeTruthy(); - await page.locator('//a[@daa-ll="Buy now-1|Generative AI.This c"]').click(); + await expect(ost.jpCurrencySymbol).toBeTruthy(); + + + // click 'Buy now' (ucv3 checkout, checkout workflow = segmentation ) button and verify the checkout page. + await expect(ost.segmentationBuynowCta).toBeVisible(); + await ost.segmentationBuynowCta.click(); + await page.waitForTimeout(1000); await expect(page).toHaveURL(new RegExp('^https://commerce.adobe.com/store/')); await expect(page).toHaveURL(new RegExp('co=JP&lang=ja')); }); }); + // Test 7 : OST JP CC all apps price buy segment cta test(`${features[7].name},${features[7].tags}`, async ({ page, baseURL }) => { console.info(`[Test Page]: ${baseURL}${features[7].path}`); - await test.step('page has JP STE prices for LR product', async () => { + + await test.step('step-1: page has JP STE prices for LR product', async () => { await page.goto(`${baseURL}${features[7].path}`); await page.waitForLoadState('domcontentloaded'); await expect(page).toHaveURL(`${baseURL}${features[7].path}`); @@ -165,54 +208,68 @@ test.describe('test Offer selector tool price formats and checkout flows in US & await test.step('step-2: Verify STE price for Lighthouse in JP currency', async () => { await page.waitForLoadState(); - await expect(ost.STEProductname).toBeTruthy(); - await expect(ost.jpcountrycurrencysymbol).toBeTruthy(); - await expect(ost.STE_LR_JP_price).toBeVisible(); - await page.locator('//a[@daa-ll="Get started-1|Adobe Light room"]').click(); + await expect(ost.SteProductName).toBeTruthy(); + await expect(ost.jpCurrencySymbol).toBeTruthy(); + await expect(ost.SteLrJpPrice).toBeVisible(); + + // click 'Get started' (ucv3 checkout, checkout workflow = email ) button and verify the checkout page. + await expect(ost.emailBuynowCta).toBeVisible(); + await ost.emailBuynowCta.click(); + await page.waitForTimeout(1000); await expect(page).toHaveURL(new RegExp('^https://commerce.adobe.com/store/email')); await expect(page).toHaveURL(new RegExp('co=JP&lang=ja')); }); }); + // Test 8 : OST JP CC student-price buy cta test(`${features[8].name},${features[8].tags}`, async ({ page, baseURL }) => { console.info(`[Test Page]: ${baseURL}${features[8].path}`); - await test.step('product with month, year subscriptions in JP', async () => { + + await test.step('step-1: product with month, year subscriptions in JP', async () => { await page.goto(`${baseURL}${features[8].path}`); await page.waitForLoadState('domcontentloaded'); await expect(page).toHaveURL(`${baseURL}${features[8].path}`); }); - await test.step('JP locale monthly, year subscriptions', async () => { + await test.step('step-2: JP locale monthly, year subscriptions', async () => { await page.waitForLoadState(); - await expect(ost.producatname_3).toBeVisible(); - await expect(ost.jpcountrycurrencysymbol).toBeTruthy(); - await expect(ost.pricelabel_actual).toBeVisible(); - await expect(ost.strikethroughproperty).toBeTruthy(); - await expect(ost.strikethroughprice_jp_1).toBeVisible(); - await expect(ost.pricelabel_now).toBeVisible(); - await expect(ost.purchaseCTAbandle).toBeVisible(); - await page.locator('//a[@daa-ll="choose a plan-1|Actual price"]').click(); + await expect(ost.productName3).toBeVisible(); + await expect(ost.jpCurrencySymbol).toBeTruthy(); + await expect(ost.priceLabelActual).toBeVisible(); + await expect(ost.strikeThroughProperty).toBeTruthy(); + await expect(ost.strikeThroughPriceJp1).toBeVisible(); + await expect(ost.priceLabelNow).toBeVisible(); + + // click 'Choose a plan' (ucv3 checkout, checkout workflow = bundle ) button and verify the checkout page. + await expect(ost.bundleBuynowCta).toBeVisible(); + await ost.bundleBuynowCta.click(); + await page.waitForTimeout(1000); await expect(page).toHaveURL(new RegExp('^https://commerce.adobe.com/store/bundle')); await expect(page).toHaveURL(new RegExp('co=JP&lang=ja')); }); }); + // Test 9 : OST JP CC student-price buy cta test(`${features[9].name},${features[9].tags}`, async ({ page, baseURL }) => { console.info(`[Test Page]: ${baseURL}${features[9].path}`); - await test.step('product with month, year subscriptions in JP', async () => { + + await test.step('step-1: product with month, year subscriptions in JP', async () => { await page.goto(`${baseURL}${features[9].path}`); await page.waitForLoadState('domcontentloaded'); await expect(page).toHaveURL(`${baseURL}${features[9].path}`); }); - await test.step('JP locale monthly, year subscriptions', async () => { + await test.step('step-2: JP locale monthly, year subscriptions', async () => { await page.waitForLoadState(); - await expect(ost.headingdiscription).toBeTruthy(); - await expect(ost.headingdiscription2).toBeTruthy(); - await expect(ost.firstcardheading).toBeVisible(); - await expect(ost.individualPSpricemonth_jp).toBeVisible(); - await expect(ost.individualPSpriceyear_jp).toBeVisible(); - await page.locator('//a[@class="con-button placeholder-resolved"]').first().click(); + await expect(ost.headingDiscription).toBeTruthy(); + await expect(ost.headingDiscription2).toBeTruthy(); + await expect(ost.firstCardHeading).toBeVisible(); + await expect(ost.individualPsPriceMonthJP).toBeVisible(); + await expect(ost.individualPsPriceYearJP).toBeVisible(); + + await expect(ost.emailBuynowCta).toBeVisible(); + await ost.emailBuynowCta.click(); + await page.waitForTimeout(1000); await expect(page).toHaveURL(new RegExp('^https://commerce.adobe.com/store/')); await expect(page).toHaveURL(new RegExp('co=JP&lang=ja')); }); From 45a5fe359e2f5bdd66c56b3e8f914e095299b31f Mon Sep 17 00:00:00 2001 From: Santoshkumar Nateekar Date: Thu, 7 Dec 2023 02:56:43 -0800 Subject: [PATCH 27/53] Update cc.daily.yml1 --- .github/workflows/cc.daily.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/cc.daily.yml b/.github/workflows/cc.daily.yml index 69c7ff1a..0f2a5c10 100644 --- a/.github/workflows/cc.daily.yml +++ b/.github/workflows/cc.daily.yml @@ -25,7 +25,7 @@ jobs: node-version: lts/* - name: Run Nala ${{ matrix.os }} - uses: bash dailyrun.sh cc + run: bash dailyrun.sh cc env: IMS_EMAIL: ${{ secrets.IMS_EMAIL }} IMS_PASS: ${{ secrets.IMS_PASS }} From f2c56cd364469f6e70fb5bfaf7289e7904a07bb5 Mon Sep 17 00:00:00 2001 From: Santoshkumar Nateekar Date: Thu, 7 Dec 2023 03:15:56 -0800 Subject: [PATCH 28/53] Update cc.daily.yml2 --- .github/workflows/cc.daily.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/cc.daily.yml b/.github/workflows/cc.daily.yml index 0f2a5c10..bcf10865 100644 --- a/.github/workflows/cc.daily.yml +++ b/.github/workflows/cc.daily.yml @@ -3,6 +3,7 @@ name: CC Nala Daily Run on: schedule: - cron: '*/10 * * * *' + workflow_dispatch: jobs: platform_matrix: From bdbebe714a3da935e349922d905c046ae043520e Mon Sep 17 00:00:00 2001 From: Santoshkumar Nateekar Date: Thu, 7 Dec 2023 03:25:35 -0800 Subject: [PATCH 29/53] Update dailyrun.sh 1 --- dailyrun.sh | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/dailyrun.sh b/dailyrun.sh index 0dbd1d9a..e69525b2 100644 --- a/dailyrun.sh +++ b/dailyrun.sh @@ -8,6 +8,10 @@ CONFIG_FILE_PATH="./configs/${PROJECT_NAME}.config.js" # Check if the config.js file exists if [ -f "${CONFIG_FILE_PATH}" ]; then + echo "*** Installing playwright dependencies ***" + cd "$GITHUB_ACTION_PATH" || exit + npm ci + npx playwright install --with-deps echo "*** Running Playwright tests with config: ${CONFIG_FILE_PATH} ***" npx playwright test --config="${CONFIG_FILE_PATH}" --project="${PROJECT_NAME}-live-chrome" npx playwright test --config="${CONFIG_FILE_PATH}" --project="${PROJECT_NAME}-live-firefox" From 65fafe13bca685b90a6620ee31c68579236aa291 Mon Sep 17 00:00:00 2001 From: Santoshkumar Nateekar Date: Thu, 7 Dec 2023 03:40:12 -0800 Subject: [PATCH 30/53] Update cc.daily.yml3 --- .github/workflows/cc.daily.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/cc.daily.yml b/.github/workflows/cc.daily.yml index bcf10865..17f3abee 100644 --- a/.github/workflows/cc.daily.yml +++ b/.github/workflows/cc.daily.yml @@ -2,7 +2,7 @@ name: CC Nala Daily Run on: schedule: - - cron: '*/10 * * * *' + - cron: "0 15 * * *" workflow_dispatch: jobs: From cbd1168598aa4a3e4054435d425ed918cc86fb58 Mon Sep 17 00:00:00 2001 From: Jacky Sun <67350368+JackySun9@users.noreply.github.com> Date: Thu, 7 Dec 2023 14:58:41 -0800 Subject: [PATCH 31/53] add UI screenshots for DX Quiz (#219) * add test for quiz and result pages * add test for quiz and result pages * add test for quiz and result pages * add POC for analytics test * update analytics tests and envs * result envs * update analytics only on firefox * add dynamic tests * add dynamic test for quiz page * update quiz test * update test structure * add test for quiz and result pages * add POC for analytics test * update analytics tests and envs * result envs * update analytics only on firefox * add dynamic tests * add dynamic test for quiz page * update quiz test * update test structure * update uar tests to new format * update uar tests * move everything to uar folder * add dependency for js-yaml * update test according to latest comments * update test according to latest comments * update tests according to the latest comments * add uar config * add analytics for uar * update according to feedbacks * update tags * add @cc tag * update according to feedbacks * add dynamic tests for uar * update according to review comments * fix some typos * update according to review comments * merge console log info * add UI screenshots for UAR * move view point to test * update according to feedback * add analytics test for UAR * update validation and uar libs * update libs * update by feedback * update some config and tests * update some config and tests * update test content path to common path * update analytics tests * fix test failures caused by test code * fix test failures * fix test failures * add visual test for CAAS with two pages * update according to feedbacks * update report in config file * add screenshot for milo main live vs uar-integration live * add timestamp js for time stampe recording * add screenshot diff for uar stable and beta * move uar screenshots into visual compare folder * add UI screenshots for DX Quiz * build a function to get screenshots --------- Co-authored-by: xiasun Co-authored-by: Aaron Mauchley Co-authored-by: xiasun --- data/dx/quiz/quiz-basic.yml | 12 ++++ features/visual-compare/dx/quiz.spec.js | 14 ++++ selectors/uar/quiz.page.js | 94 ++++++++++++++++--------- visual-compare-tests/dx/quiz.vc.test.js | 62 ++++++++++++++++ 4 files changed, 150 insertions(+), 32 deletions(-) create mode 100644 data/dx/quiz/quiz-basic.yml create mode 100644 features/visual-compare/dx/quiz.spec.js create mode 100644 visual-compare-tests/dx/quiz.vc.test.js diff --git a/data/dx/quiz/quiz-basic.yml b/data/dx/quiz/quiz-basic.yml new file mode 100644 index 00000000..694c0d8b --- /dev/null +++ b/data/dx/quiz/quiz-basic.yml @@ -0,0 +1,12 @@ +--- +'Commerce': 'adobe-commerce' +'Analytics > Web analytics': 'adobe-analytics' +'Analytics > Omnichannel analytics (online and offline)': 'adobe-customer-journey-analytics' +'Analytics > Product analytics': 'adobe-product-analytics' +'Content management > Content management system (CMS)': 'experience-manager-sites' +'Content management > Digital assets management (DAM)': 'experience-manager-assets' +'Customer data management': 'real-time-cdp' +'Marketing and campaign management > B2C customer journey management': 'adobe-journey-optimizer' +'Marketing and campaign management > B2B marketing automation': 'marketo-engage' +'Project management': 'workfront' + diff --git a/features/visual-compare/dx/quiz.spec.js b/features/visual-compare/dx/quiz.spec.js new file mode 100644 index 00000000..f95c4ba4 --- /dev/null +++ b/features/visual-compare/dx/quiz.spec.js @@ -0,0 +1,14 @@ +module.exports = { + name: 'UAR Visual Comparison', + features: [ + { + tcid: '0', + name: '@dx quiz screenshots', + path: '/drafts/quiz/solution-finder/', + stable: '@milo_live', + beta: '@uar_live', + tags: '@bacom @dx-quiz-stable-vs-beta @dx-quiz-static', + data: 'data/dx/quiz/quiz-basic.yml', + }, + ], +}; diff --git a/selectors/uar/quiz.page.js b/selectors/uar/quiz.page.js index 218bac1f..b5557583 100644 --- a/selectors/uar/quiz.page.js +++ b/selectors/uar/quiz.page.js @@ -1,5 +1,7 @@ /* eslint-disable no-await-in-loop */ /* eslint-disable no-restricted-syntax */ +import { expect } from '@playwright/test'; + const { WebUtil } = require('../../libs/webutil.js'); export default class Quiz { @@ -42,7 +44,7 @@ export default class Quiz { * @param {string} url * @param {string} originalAnswer */ - async clickEachAnswer(url, originalAnswer, keyNumber, version, isScreenshot = false) { + async clickEachAnswer(url, originalAnswer, keyNumber, version, isScreenshot = false, folderPath = 'screenshots/uar') { await this.page.goto(url); const answers = originalAnswer.split('>').map((x) => x.trim()); @@ -64,16 +66,13 @@ export default class Quiz { await this.page.waitForTimeout(500); const index = answers.indexOf(answer); - const folderPath = 'screenshots/uar'; - const desktopName = `${keyNumber} - ${version} - desktop - ${index} - ${answer.replace('/', '')}.png`; - const tabletName = `${keyNumber} - ${version} - tablet - ${index} - ${answer.replace('/', '')}.png`; - const mobileName = `${keyNumber} - ${version} - mobile - ${index} - ${answer.replace('/', '')}.png`; - - await this.webUtil.takeScreenshot(folderPath, desktopName, 1920, 1080); - await this.webUtil.takeScreenshot(folderPath, tabletName, 768, 1024); - await this.webUtil.takeScreenshot(folderPath, mobileName, 375, 812); - - this.screenshots.push(desktopName, tabletName, mobileName); + await this.takeScreenshotsOnThreeDimensions( + keyNumber, + version, + index, + answer, + folderPath, + ); } // click next button @@ -81,16 +80,13 @@ export default class Quiz { } else if (isScreenshot) { await this.page.waitForTimeout(500); const index = answers.length - 1; - const folderPath = 'screenshots/uar'; - const desktopName = `${keyNumber} - ${version} - desktop - ${index} - ${answer.replace('/', '')}.png`; - const tabletName = `${keyNumber} - ${version} - tablet - ${index} - ${answer.replace('/', '')}.png`; - const mobileName = `${keyNumber} - ${version} - mobile - ${index} - ${answer.replace('/', '')}.png`; - - await this.webUtil.takeScreenshot(folderPath, desktopName, 1920, 1080); - await this.webUtil.takeScreenshot(folderPath, tabletName, 768, 1024); - await this.webUtil.takeScreenshot(folderPath, mobileName, 375, 812); - - this.screenshots.push(desktopName, tabletName, mobileName); + await this.takeScreenshotsOnThreeDimensions( + keyNumber, + version, + index, + answer, + folderPath, + ); } } @@ -98,11 +94,33 @@ export default class Quiz { await this.clickResultButton(); } + async takeScreenshotsOnThreeDimensions(keyNumber, version, index, answer, folderPath) { + let desktopName; + let tabletName; + let mobileName; + + if (answer === 'result') { + desktopName = `${keyNumber} - ${version} - desktop - result.png`; + tabletName = `${keyNumber} - ${version} - tablet - result.png`; + mobileName = `${keyNumber} - ${version} - mobile - result.png`; + } else { + desktopName = `${keyNumber} - ${version} - desktop - ${index} - ${answer.replace('/', '')}.png`; + tabletName = `${keyNumber} - ${version} - tablet - ${index} - ${answer.replace('/', '')}.png`; + mobileName = `${keyNumber} - ${version} - mobile - ${index} - ${answer.replace('/', '')}.png`; + } + + await this.webUtil.takeScreenshot(folderPath, desktopName, 1920, 1080); + await this.webUtil.takeScreenshot(folderPath, tabletName, 768, 1024); + await this.webUtil.takeScreenshot(folderPath, mobileName, 375, 812); + + this.screenshots.push(desktopName, tabletName, mobileName); + } + /** * Validate products on result page to match with expect products * @param {string} name */ - async checkResultPage(name, originalAnswer, keyNumber, version, isScreenshot = false) { + async checkResultPage(name, originalAnswer, keyNumber, version, isScreenshot = false, folderPath = 'screenshots/uar') { const newProduct = []; const actualProduct = await this.uarResult.nth(0); @@ -167,19 +185,31 @@ export default class Quiz { if (isScreenshot) { await this.page.waitForTimeout(1000); - const folderPath = 'screenshots/uar'; - const desktopName = `${keyNumber} - ${version} - desktop - result.png`; - const tabletName = `${keyNumber} - ${version} - tablet - result.png`; - const mobileName = `${keyNumber} - ${version} - mobile - result.png`; - - await this.webUtil.takeScreenshot(folderPath, desktopName, 1920, 1080); - await this.webUtil.takeScreenshot(folderPath, tabletName, 768, 1024); - await this.webUtil.takeScreenshot(folderPath, mobileName, 375, 812); - - this.screenshots.push(desktopName, tabletName, mobileName); + await this.takeScreenshotsOnThreeDimensions( + keyNumber, + version, + 0, + 'result', + folderPath, + ); } console.info(`==========new============\n${newProduct.sort().join('')}`); return newProduct.sort().join(''); } + + async checkResultPageDX(value, keyNumber, version, isScreenshot = false, folderPath = 'screenshots/dx') { + expect.soft(await this.page.url()).toContain(value); + if (isScreenshot) { + await this.page.waitForTimeout(1000); + + await this.takeScreenshotsOnThreeDimensions( + keyNumber, + version, + 0, + 'result', + folderPath, + ); + } + } } diff --git a/visual-compare-tests/dx/quiz.vc.test.js b/visual-compare-tests/dx/quiz.vc.test.js new file mode 100644 index 00000000..eda9d56b --- /dev/null +++ b/visual-compare-tests/dx/quiz.vc.test.js @@ -0,0 +1,62 @@ +/* eslint-disable no-await-in-loop */ +/* eslint-disable no-loop-func */ +/* eslint-disable no-restricted-syntax */ +import { expect, test } from '@playwright/test'; +import Quiz from '../../selectors/uar/quiz.page.js'; + +const { features } = require('../../features/visual-compare/dx/quiz.spec.js'); +const { WebUtil } = require('../../libs/webutil.js'); +const envs = require('../../envs/envs.js'); + +test.describe('Quiz flow test suite', () => { + // reset timeout because we use this to run all test data + test.setTimeout(10 * 60 * 1000); + for (const feature of features) { + test( + `${feature.name}, ${feature.tags}`, + async ({ page }) => { + const stablePage = new Quiz(page); + const betaPage = new Quiz(page); + const stableURL = `${envs[feature.stable]}${feature.path}`; + console.info(stableURL); + const betaURL = `${envs[feature.beta]}${feature.path}`; + console.info(betaURL); + + // load test data from static files + const testdata = await WebUtil.loadTestData(`${feature.data}`); + + let keyNumber = 0; + + for (const key of Object.keys(testdata)) { + console.log(key); + let stableProductScreenshots = []; + let betaProductScreenshots = []; + keyNumber += 1; + await test.step(`Stable: Select each answer on test page according to ${key}`, async () => { + await stablePage.clickEachAnswer(stableURL, key, keyNumber, 'stable', true, 'screenshots/dx'); + }); + + await test.step('Stable: Check results on test page', async () => { + await stablePage.checkResultPageDX(testdata[key], keyNumber, 'stable', true, 'screenshots/dx'); + }); + + stableProductScreenshots = stablePage.screenshots.slice(); + stablePage.screenshots = []; + + await test.step(`Beta: Select each answer on test page according to ${key}`, async () => { + await betaPage.clickEachAnswer(betaURL, key, keyNumber, 'beta', true, 'screenshots/dx'); + }); + + await test.step('Beta: Check results on test page', async () => { + await betaPage.checkResultPageDX(testdata[key], keyNumber, 'beta', true, 'screenshots/dx'); + }); + + betaProductScreenshots = betaPage.screenshots.slice(); + betaPage.screenshots = []; + + WebUtil.compareScreenshots(stableProductScreenshots, betaProductScreenshots, 'screenshots/dx'); + } + }, + ); + } +}); From 5e4d75591e4ee18c927577f574998fbad12d1ce2 Mon Sep 17 00:00:00 2001 From: Santoshkumar Nateekar Date: Thu, 7 Dec 2023 15:43:28 -0800 Subject: [PATCH 32/53] MWPW-140218 : Update CC Daily run workflow (#220) update cc workflow Co-authored-by: nateekar --- .github/workflows/cc.daily.yml | 1 + configs/cc.config.js | 5 +---- utils/reporters/base-reporter.js | 8 +++++++- 3 files changed, 9 insertions(+), 5 deletions(-) diff --git a/.github/workflows/cc.daily.yml b/.github/workflows/cc.daily.yml index 17f3abee..af2ddb5a 100644 --- a/.github/workflows/cc.daily.yml +++ b/.github/workflows/cc.daily.yml @@ -15,6 +15,7 @@ jobs: runs-on: ${{ matrix.os }} env: WORKFLOW_NAME: 'CC Nala Daily Run' + DAILY_RUN: 'true' steps: - name: Check out repository diff --git a/configs/cc.config.js b/configs/cc.config.js index 5f61bca3..e1cd29f3 100644 --- a/configs/cc.config.js +++ b/configs/cc.config.js @@ -31,7 +31,7 @@ const config = { /* Reporter to use. See https://playwright.dev/docs/test-reporters */ reporter: process.env.CI ? [['github'], ['../utils/reporters/json-reporter.js'], ['../utils/reporters/json-reporter.js']] - : [['html', { outputFolder: 'test-html-results' }]], + : [['html', { outputFolder: 'test-html-results' }],['list'],['../utils/reporters/base-reporter.js']], /* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */ use: { /* Maximum time each action such as `click()` can take. Defaults to 0 (no limit). */ @@ -50,7 +50,6 @@ const config = { name: 'cc-live-chrome', use: { ...devices['Desktop Chrome'], - baseURL: envs['@cc-live'], }, }, @@ -58,7 +57,6 @@ const config = { name: 'cc-live-firefox', use: { ...devices['Desktop Firefox'], - baseURL: envs['@cc-live'], }, }, @@ -66,7 +64,6 @@ const config = { name: 'cc-live-webkit', use: { ...devices['Desktop Safari'], - baseURL: envs['@cc-live'], }, }, diff --git a/utils/reporters/base-reporter.js b/utils/reporters/base-reporter.js index fde0d44e..68b980e3 100644 --- a/utils/reporters/base-reporter.js +++ b/utils/reporters/base-reporter.js @@ -98,7 +98,11 @@ class BaseReporter { const failPercentage = ((this.failedTests / totalTests) * 100).toFixed(2); if (process.env.GITHUB_ACTIONS === 'true') { - envURL = process.env.PR_BRANCH_LIVE_URL || 'N/A'; + if(process.env.DAILY_RUN === 'true'){ + envURL = this.config.projects[0].use.baseURL; + }else{ + envURL = process.env.PR_BRANCH_LIVE_URL || 'N/A'; + } exeEnv = 'GitHub Actions Environment'; const repo = process.env.GITHUB_REPOSITORY; const runId = process.env.GITHUB_RUN_ID; @@ -112,6 +116,8 @@ class BaseReporter { }else { envURL = process.env.LOCAL_TEST_LIVE_URL || 'N/A'; exeEnv = 'Local Environment'; + envURL = this.config.projects[0].use.baseURL; + runUrl = 'Local Environment' } const summary = ` From 83aadf130d13a80c37198c095e68b2020d8b38a6 Mon Sep 17 00:00:00 2001 From: Santoshkumar Nateekar Date: Thu, 7 Dec 2023 15:57:26 -0800 Subject: [PATCH 33/53] [CC Daily Run ] : Update to cc-workflow (#221) * updat to cc-workflow * also update the headerblock script --------- Co-authored-by: nateekar --- configs/cc.config.js | 24 ------------------------ dailyrun.sh | 3 +-- tests/milo/header.block.test.js | 6 +++++- 3 files changed, 6 insertions(+), 27 deletions(-) diff --git a/configs/cc.config.js b/configs/cc.config.js index e1cd29f3..d5e858b2 100644 --- a/configs/cc.config.js +++ b/configs/cc.config.js @@ -66,30 +66,6 @@ const config = { ...devices['Desktop Safari'], }, }, - - { - name: 'cc-prod-chrome', - use: { - ...devices['Desktop Chrome'], - baseURL: envs['@cc_prod'], - }, - }, - - { - name: 'cc-prod-firefox', - use: { - ...devices['Desktop Firefox'], - baseURL: envs['@cc_prod'], - }, - }, - - { - name: 'cc-prod-webkit', - use: { - ...devices['Desktop Safari'], - baseURL: envs['@cc_prod'], - }, - }, ], }; export default config; diff --git a/dailyrun.sh b/dailyrun.sh index e69525b2..4c013fe0 100644 --- a/dailyrun.sh +++ b/dailyrun.sh @@ -13,8 +13,7 @@ if [ -f "${CONFIG_FILE_PATH}" ]; then npm ci npx playwright install --with-deps echo "*** Running Playwright tests with config: ${CONFIG_FILE_PATH} ***" - npx playwright test --config="${CONFIG_FILE_PATH}" --project="${PROJECT_NAME}-live-chrome" - npx playwright test --config="${CONFIG_FILE_PATH}" --project="${PROJECT_NAME}-live-firefox" + npx playwright test --config="${CONFIG_FILE_PATH}" else echo "Config file: ${CONFIG_FILE_PATH} not found, running default tests" exit 1 diff --git a/tests/milo/header.block.test.js b/tests/milo/header.block.test.js index c72f4b78..946d7866 100644 --- a/tests/milo/header.block.test.js +++ b/tests/milo/header.block.test.js @@ -23,7 +23,11 @@ test.describe('Header Block Test Suite', () => { // Check HEADER block content: await expect(Header.mainNavLogo).toBeVisible(); await expect(Header.searchIcon).toBeVisible(); - await expect(Header.signInButton).toBeVisible(); + + //skipping the step for PR branch runs + // working on better workaround soloution + + // await expect(Header.signInButton).toBeVisible(); }); await test.step('Check HEADER search component', async () => { From 3cf10dee0ea95c656957000ac9c70125e1c6db42 Mon Sep 17 00:00:00 2001 From: Jacky Sun <67350368+JackySun9@users.noreply.github.com> Date: Fri, 8 Dec 2023 10:33:31 -0800 Subject: [PATCH 34/53] update locator for new content (#225) * add test for quiz and result pages * add test for quiz and result pages * add test for quiz and result pages * add POC for analytics test * update analytics tests and envs * result envs * update analytics only on firefox * add dynamic tests * add dynamic test for quiz page * update quiz test * update test structure * add test for quiz and result pages * add POC for analytics test * update analytics tests and envs * result envs * update analytics only on firefox * add dynamic tests * add dynamic test for quiz page * update quiz test * update test structure * update uar tests to new format * update uar tests * move everything to uar folder * add dependency for js-yaml * update test according to latest comments * update test according to latest comments * update tests according to the latest comments * add uar config * add analytics for uar * update according to feedbacks * update tags * add @cc tag * update according to feedbacks * add dynamic tests for uar * update according to review comments * fix some typos * update according to review comments * merge console log info * add UI screenshots for UAR * move view point to test * update according to feedback * add analytics test for UAR * update validation and uar libs * update libs * update by feedback * update some config and tests * update some config and tests * update test content path to common path * update analytics tests * fix test failures caused by test code * fix test failures * fix test failures * add visual test for CAAS with two pages * update according to feedbacks * update report in config file * add screenshot for milo main live vs uar-integration live * add timestamp js for time stampe recording * add screenshot diff for uar stable and beta * move uar screenshots into visual compare folder * add UI screenshots for DX Quiz * build a function to get screenshots * update locator --------- Co-authored-by: xiasun Co-authored-by: Aaron Mauchley Co-authored-by: xiasun --- selectors/uar/quiz.page.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/selectors/uar/quiz.page.js b/selectors/uar/quiz.page.js index b5557583..40504d5a 100644 --- a/selectors/uar/quiz.page.js +++ b/selectors/uar/quiz.page.js @@ -12,7 +12,7 @@ export default class Quiz { this.resultButton = page.locator('div.quiz-button-container > button'); this.uarResult = page.locator('.quiz-results h1'); this.uarResult2 = page.locator('//div[contains(@data-path,"marquee-product")]//strong | //div[contains(@data-path,"check-bullet")]//h1 | //div[contains(@data-path,"express-product")]//h1'); - this.uarResult3 = page.locator('//div[contains(@data-path,"card")]//strong'); + this.uarResult3 = page.locator('//div[contains(@data-path,"card")]//h3'); this.screenshots = []; } From 06efc03015364748d84643e5f5e8969e6f779e2b Mon Sep 17 00:00:00 2001 From: Santoshkumar Nateekar Date: Fri, 8 Dec 2023 13:50:37 -0800 Subject: [PATCH 35/53] [MWPW-140301] Introduce Daily runs for Nala Blog Automation scripts (#227) * blog daily run * remove skips * update daily run time to 7-30 am pst --------- Co-authored-by: nateekar --- .github/workflows/daily/blog.daily.yml | 46 ++++++++++++++++++++++ .github/workflows/{ => daily}/cc.daily.yml | 0 .github/workflows/{ => daily}/daily.yml | 3 +- configs/blog.config.js | 3 +- selectors/blog/home.page.js | 29 ++++++++++++-- tests/blog/homepage.test.js | 35 ++++++++++++---- 6 files changed, 103 insertions(+), 13 deletions(-) create mode 100644 .github/workflows/daily/blog.daily.yml rename .github/workflows/{ => daily}/cc.daily.yml (100%) rename .github/workflows/{ => daily}/daily.yml (95%) diff --git a/.github/workflows/daily/blog.daily.yml b/.github/workflows/daily/blog.daily.yml new file mode 100644 index 00000000..bcecf924 --- /dev/null +++ b/.github/workflows/daily/blog.daily.yml @@ -0,0 +1,46 @@ +name: Blog Nala Daily Run + +on: + schedule: + - cron: "30 15 * * *" + workflow_dispatch: + +jobs: + platform_matrix: + strategy: + fail-fast: false + matrix: + os: [ubuntu-latest, windows-latest, macos-latest] + name: Running tests + runs-on: ${{ matrix.os }} + env: + WORKFLOW_NAME: 'CC Nala Daily Run' + DAILY_RUN: 'true' + + steps: + - name: Check out repository + uses: actions/checkout@v3 + + - name: Set up Node.js + uses: actions/setup-node@v3 + with: + node-version: lts/* + + - name: Run Nala ${{ matrix.os }} + run: bash dailyrun.sh blog + env: + IMS_EMAIL: ${{ secrets.IMS_EMAIL }} + IMS_PASS: ${{ secrets.IMS_PASS }} + HLX_TKN: ${{ secrets.HLX_TKN }} + SLACK_WH: ${{ secrets.SLACK_WH }} + + - name: Display workflow name + run: echo "The workflow name is $WORKFLOW_NAME" + + - name: Persist JSON Artifact + uses: actions/upload-artifact@v3 + if: always() + with: + name: nala-results + path: nala-results.json + retention-days: 30 diff --git a/.github/workflows/cc.daily.yml b/.github/workflows/daily/cc.daily.yml similarity index 100% rename from .github/workflows/cc.daily.yml rename to .github/workflows/daily/cc.daily.yml diff --git a/.github/workflows/daily.yml b/.github/workflows/daily/daily.yml similarity index 95% rename from .github/workflows/daily.yml rename to .github/workflows/daily/daily.yml index 167c80b6..a2a2489d 100644 --- a/.github/workflows/daily.yml +++ b/.github/workflows/daily/daily.yml @@ -3,6 +3,7 @@ name: Milo Nala Daily Run on: schedule: - cron: "0 16 * * *" + workflow_dispatch: jobs: platform_matrix: @@ -17,7 +18,7 @@ jobs: - name: Check out repository uses: actions/checkout@v3 - name: Run Nala ${{ matrix.os }} - uses: ./ + uses: ../ env: IMS_EMAIL: ${{ secrets.IMS_EMAIL }} IMS_PASS: ${{ secrets.IMS_PASS }} diff --git a/configs/blog.config.js b/configs/blog.config.js index 977b6696..94661565 100644 --- a/configs/blog.config.js +++ b/configs/blog.config.js @@ -10,6 +10,7 @@ const envs = require('../envs/envs.js'); const config = { testDir: '../tests/blog', outputDir: '../test-results', + globalSetup: '../global.setup.js', /* Maximum time one test can run for. */ timeout: 30 * 1000, expect: { @@ -30,7 +31,7 @@ const config = { /* Reporter to use. See https://playwright.dev/docs/test-reporters */ reporter: process.env.CI ? [['github'], ['../utils/reporters/json-reporter.js'], ['../utils/reporters/json-reporter.js']] - : [['html', { outputFolder: 'test-html-results' }]], + : [['html', { outputFolder: 'test-html-results' }],['list'],['../utils/reporters/base-reporter.js']], /* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */ use: { /* Maximum time each action such as `click()` can take. Defaults to 0 (no limit). */ diff --git a/selectors/blog/home.page.js b/selectors/blog/home.page.js index 0240fcd9..4674c2ee 100644 --- a/selectors/blog/home.page.js +++ b/selectors/blog/home.page.js @@ -29,15 +29,38 @@ export default class BlogHomePage { this.gnavProfile = this.page.locator('.gnav-profile'); this.signIn = this.gnavProfile.locator('.gnav-signin'); + // Marquee block locators + this.marquee = this.page.locator('.marquee.dark').nth(0); + this.marqueeTextH1 = this.marquee.locator('h1').nth(0); + this.marqueeActionBlueButton = this.marquee.locator('a').nth(0); + // Featured article block locators this.featuredArticleBlock = this.page.locator('.featured-article'); this.featuredArticleCard = this.featuredArticleBlock.locator('.featured-article-card'); this.featuredArticleImage = this.featuredArticleBlock.locator('.featured-article-card-image'); // Text block locators - this.textBlock = this.page.locator('.text.text-block.con-block'); - this.textBlockHeader = this.textBlock.locator('#the-latest-news'); - this.readMoreNewsButton = this.textBlock.locator('.con-button.outline'); + this.textBlock1 = this.page.locator('.text.text-block.con-block').nth(0); + this.textBlock1Header = this.textBlock1.locator('h3'); + this.textBlock1OutlineButton = this.textBlock1.locator('.con-button.outline'); + this.readMoreNewsButton = this.textBlock1.locator('.con-button.outline'); + + // Consonant Card locators + this.consonantCard1 = this.page.locator('.card.consonant-Card').nth(0); + this.consonantCard1Image = this.consonantCard1.locator('.consonant-OneHalfCard-img').nth(0); + this.consonantCard1H3Text = this.consonantCard1.locator('.consonant-OneHalfCard-inner h3'); + this.consonantCard1Text = this.consonantCard1.locator('.consonant-OneHalfCard-text'); + + this.consonantCard2 = this.page.locator('.card.consonant-Card').nth(1); + this.consonantCard2Image = this.consonantCard2.locator('.consonant-OneHalfCard-img').nth(0); + this.consonantCard2H3Text = this.consonantCard2.locator('.consonant-OneHalfCard-inner h3'); + this.consonantCard2Text = this.consonantCard2.locator('.consonant-OneHalfCard-text'); + + this.consonantCard3 = this.page.locator('.card.consonant-Card').nth(2); + this.consonantCard3Image = this.consonantCard3.locator('.consonant-OneHalfCard-img').nth(0); + this.consonantCard3H3Text = this.consonantCard3.locator('.consonant-OneHalfCard-inner h3'); + this.consonantCard3Text = this.consonantCard3.locator('.consonant-OneHalfCard-text'); + // Article feed block locators this.articleFeedBlock = this.page.locator('.article-feed.appear'); diff --git a/tests/blog/homepage.test.js b/tests/blog/homepage.test.js index f29ee7a2..55aff089 100644 --- a/tests/blog/homepage.test.js +++ b/tests/blog/homepage.test.js @@ -48,14 +48,33 @@ test.describe('Blog Home page test suite', () => { }); await test.step('step-3: Verify Articles', async () => { - // Featured article section - await expect(homePage.featuredArticleBlock).toBeVisible(); - await expect(homePage.featuredArticleCard).toBeVisible(); - await expect(homePage.featuredArticleImage).toBeVisible(); - // Latest news text section - await expect(homePage.textBlock).toBeVisible(); - await expect(homePage.textBlockHeader).toBeVisible(); - await expect(homePage.readMoreNewsButton).toBeVisible(); + // article section (Text Block) + await expect(homePage.marquee).toBeVisible(); + await expect(homePage.marqueeTextH1).toBeVisible(); + await expect(homePage.marqueeActionBlueButton).toBeVisible(); + + // article section (Text Block) + await expect(homePage.textBlock1).toBeVisible(); + await expect(homePage.textBlock1Header).toBeVisible(); + await expect(homePage.textBlock1OutlineButton).toBeVisible(); + + // consonant cards section + await expect(homePage.consonantCard1).toBeVisible(); + await expect(homePage.consonantCard1Image).toBeVisible(); + await expect(homePage.consonantCard1H3Text).toBeVisible(); + await expect(homePage.consonantCard1Text).toBeVisible(); + + await expect(homePage.consonantCard2).toBeVisible(); + await expect(homePage.consonantCard2Image).toBeVisible(); + await expect(homePage.consonantCard2H3Text).toBeVisible(); + await expect(homePage.consonantCard2Text).toBeVisible(); + + await expect(homePage.consonantCard3).toBeVisible(); + await expect(homePage.consonantCard3Image).toBeVisible(); + await expect(homePage.consonantCard3H3Text).toBeVisible(); + await expect(homePage.consonantCard3Text).toBeVisible(); + + // Article feeds section await webUtil.scrollPage('down', 'slow'); await page.waitForLoadState('networkidle'); From 8a5e90e4cc28b47cd03ad5af3a7e618e869aeb92 Mon Sep 17 00:00:00 2001 From: Santoshkumar Nateekar Date: Fri, 8 Dec 2023 14:08:51 -0800 Subject: [PATCH 36/53] MWPW-140266 : Update PR branch console errors (#226) update cors ims annotation Co-authored-by: nateekar --- features/milo/header.block.spec.js | 2 +- tests/milo/marquee.block.test.js | 2 +- tests/milo/media.block.test.js | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/features/milo/header.block.spec.js b/features/milo/header.block.spec.js index e1682be6..d0e754d3 100644 --- a/features/milo/header.block.spec.js +++ b/features/milo/header.block.spec.js @@ -6,7 +6,7 @@ module.exports = { path: [ '/drafts/nala/blocks/header/feds-header-page', ], - tags: '@milo @feds @header @smoke @regression', + tags: '@milo @feds @header @nopr @smoke @regression', }, ], }; diff --git a/tests/milo/marquee.block.test.js b/tests/milo/marquee.block.test.js index f16802e8..7439fe65 100644 --- a/tests/milo/marquee.block.test.js +++ b/tests/milo/marquee.block.test.js @@ -6,7 +6,7 @@ import MarqueeBlock from '../../selectors/milo/marquee.block.page.js'; let webUtil; let marquee; let consoleErrors = []; -const knownConsoleErrors = ['Access-Control-Allow-Origin','Failed to load resource: net::ERR_FAILED']; +const knownConsoleErrors = ['Access-Control-Allow-Origin','Failed to load resource: net::ERR_FAILED','adobeid-na1-stg1.services']; test.describe('Milo Marquee Block test suite', () => { test.beforeEach(async ({ page }) => { diff --git a/tests/milo/media.block.test.js b/tests/milo/media.block.test.js index 04b4b936..a049a5f5 100644 --- a/tests/milo/media.block.test.js +++ b/tests/milo/media.block.test.js @@ -6,7 +6,7 @@ import MediaBlock from '../../selectors/milo/media.block.page.js'; let webUtil; let media; let consoleErrors = []; -const knownConsoleErrors = ['Access-Control-Allow-Origin','Failed to load resource: net::ERR_FAILED']; +const knownConsoleErrors = ['Access-Control-Allow-Origin','Failed to load resource: net::ERR_FAILED','adobeid-na1-stg1.services']; test.describe('Milo Media Block test suite', () => { test.beforeEach(async ({ page }) => { From fede581e80a6e1c1d2917301e89ec2a837b511eb Mon Sep 17 00:00:00 2001 From: Santoshkumar Nateekar Date: Fri, 8 Dec 2023 14:26:45 -0800 Subject: [PATCH 37/53] [MWPW-140301] Adjust the yaml files folder (#228) * moving daily works flows from daily to workflows folder for visibility * update the workflow name --------- Co-authored-by: nateekar --- .github/workflows/{daily => }/blog.daily.yml | 2 +- .github/workflows/{daily => }/cc.daily.yml | 0 .github/workflows/{daily => }/daily.yml | 0 3 files changed, 1 insertion(+), 1 deletion(-) rename .github/workflows/{daily => }/blog.daily.yml (92%) rename .github/workflows/{daily => }/cc.daily.yml (100%) rename .github/workflows/{daily => }/daily.yml (100%) diff --git a/.github/workflows/daily/blog.daily.yml b/.github/workflows/blog.daily.yml similarity index 92% rename from .github/workflows/daily/blog.daily.yml rename to .github/workflows/blog.daily.yml index bcecf924..72416e38 100644 --- a/.github/workflows/daily/blog.daily.yml +++ b/.github/workflows/blog.daily.yml @@ -14,7 +14,7 @@ jobs: name: Running tests runs-on: ${{ matrix.os }} env: - WORKFLOW_NAME: 'CC Nala Daily Run' + WORKFLOW_NAME: 'Blog Nala Daily Run' DAILY_RUN: 'true' steps: diff --git a/.github/workflows/daily/cc.daily.yml b/.github/workflows/cc.daily.yml similarity index 100% rename from .github/workflows/daily/cc.daily.yml rename to .github/workflows/cc.daily.yml diff --git a/.github/workflows/daily/daily.yml b/.github/workflows/daily.yml similarity index 100% rename from .github/workflows/daily/daily.yml rename to .github/workflows/daily.yml From c4367f1d3240e52884f23390183555d92fb9dae7 Mon Sep 17 00:00:00 2001 From: Santoshkumar Nateekar Date: Sat, 9 Dec 2023 12:55:06 -0800 Subject: [PATCH 38/53] [MWPW-140301] Create automated daily test run workflows for 'Feds' and 'Blog' in NALA (#229) * feds daily run setup * add feds daily run and update base * update workflow name * default value * update the pr number in the summary * update the pr number * update the pr number1 * pr run id update --------- Co-authored-by: nateekar --- .github/workflows/blog.daily.yml | 2 +- .github/workflows/cc.daily.yml | 2 +- .github/workflows/feds.daily.yml | 46 +++++++++++++++++++ .../workflows/{daily.yml => milo.daily.yml} | 5 +- configs/feds.config.js | 4 +- run.sh | 1 + utils/reporters/base-reporter.js | 15 ++++-- 7 files changed, 66 insertions(+), 9 deletions(-) create mode 100644 .github/workflows/feds.daily.yml rename .github/workflows/{daily.yml => milo.daily.yml} (89%) diff --git a/.github/workflows/blog.daily.yml b/.github/workflows/blog.daily.yml index 72416e38..43147a62 100644 --- a/.github/workflows/blog.daily.yml +++ b/.github/workflows/blog.daily.yml @@ -2,7 +2,7 @@ name: Blog Nala Daily Run on: schedule: - - cron: "30 15 * * *" + - cron: "0 15 * * *" workflow_dispatch: jobs: diff --git a/.github/workflows/cc.daily.yml b/.github/workflows/cc.daily.yml index af2ddb5a..6b25b72d 100644 --- a/.github/workflows/cc.daily.yml +++ b/.github/workflows/cc.daily.yml @@ -2,7 +2,7 @@ name: CC Nala Daily Run on: schedule: - - cron: "0 15 * * *" + - cron: "30 15 * * *" workflow_dispatch: jobs: diff --git a/.github/workflows/feds.daily.yml b/.github/workflows/feds.daily.yml new file mode 100644 index 00000000..58ac91ad --- /dev/null +++ b/.github/workflows/feds.daily.yml @@ -0,0 +1,46 @@ +name: Feds Nala Daily Run + +on: + schedule: + - cron: "30 16 * * *" + workflow_dispatch: + +jobs: + platform_matrix: + strategy: + fail-fast: false + matrix: + os: [ubuntu-latest, windows-latest, macos-latest] + name: Running tests + runs-on: ${{ matrix.os }} + env: + WORKFLOW_NAME: 'Feds Nala Daily Run' + DAILY_RUN: 'true' + + steps: + - name: Check out repository + uses: actions/checkout@v3 + + - name: Set up Node.js + uses: actions/setup-node@v3 + with: + node-version: lts/* + + - name: Run Nala ${{ matrix.os }} + run: bash dailyrun.sh feds + env: + IMS_EMAIL: ${{ secrets.IMS_EMAIL }} + IMS_PASS: ${{ secrets.IMS_PASS }} + HLX_TKN: ${{ secrets.HLX_TKN }} + SLACK_WH: ${{ secrets.SLACK_WH }} + + - name: Display workflow name + run: echo "The workflow name is $WORKFLOW_NAME" + + - name: Persist JSON Artifact + uses: actions/upload-artifact@v3 + if: always() + with: + name: nala-results + path: nala-results.json + retention-days: 30 diff --git a/.github/workflows/daily.yml b/.github/workflows/milo.daily.yml similarity index 89% rename from .github/workflows/daily.yml rename to .github/workflows/milo.daily.yml index a2a2489d..cd818022 100644 --- a/.github/workflows/daily.yml +++ b/.github/workflows/milo.daily.yml @@ -13,12 +13,15 @@ jobs: os: [ubuntu-latest, windows-latest, macos-latest] name: Running tests runs-on: ${{ matrix.os }} + env: + WORKFLOW_NAME: 'Milo Nala Daily Run' + DAILY_RUN: 'true' steps: - name: Check out repository uses: actions/checkout@v3 - name: Run Nala ${{ matrix.os }} - uses: ../ + uses: ./ env: IMS_EMAIL: ${{ secrets.IMS_EMAIL }} IMS_PASS: ${{ secrets.IMS_PASS }} diff --git a/configs/feds.config.js b/configs/feds.config.js index 7e2d024c..5a62cab6 100644 --- a/configs/feds.config.js +++ b/configs/feds.config.js @@ -29,8 +29,8 @@ const config = { workers: process.env.CI ? 2 : undefined, /* Reporter to use. See https://playwright.dev/docs/test-reporters */ reporter: process.env.CI - ? [['github'], ['../utils/reporters/json-reporter.js'], ['../utils/reporters/json-reporter.js']] - : [['html', { outputFolder: 'test-html-results' }]], + ? [['github'], ['list'], ['../utils/reporters/base-reporter.js']] + : [['html', { outputFolder: 'test-html-results' }],['list'],['../utils/reporters/base-reporter.js']], /* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */ use: { /* Maximum time each action such as `click()` can take. Defaults to 0 (no limit). */ diff --git a/run.sh b/run.sh index e3c763e3..07037bcd 100755 --- a/run.sh +++ b/run.sh @@ -16,6 +16,7 @@ echo "Feature Branch Name: $FEATURE_BRANCH" PR_BRANCH_LIVE_URL_GH="https://$FEATURE_BRANCH--$prRepo--$prOrg.hlx.live" # set pr branch url as env export PR_BRANCH_LIVE_URL_GH +export PR_NUMBER echo "PR Branch live URL: $PR_BRANCH_LIVE_URL_GH" echo "*******************************" diff --git a/utils/reporters/base-reporter.js b/utils/reporters/base-reporter.js index 68b980e3..03ec47ed 100644 --- a/utils/reporters/base-reporter.js +++ b/utils/reporters/base-reporter.js @@ -93,6 +93,7 @@ class BaseReporter { let envURL; let exeEnv; let runUrl; + let runName = 'Nala PR Run'; const totalTests = this.results.length; const passPercentage = ((this.passedTests / totalTests) * 100).toFixed(2); const failPercentage = ((this.failedTests / totalTests) * 100).toFixed(2); @@ -100,35 +101,41 @@ class BaseReporter { if (process.env.GITHUB_ACTIONS === 'true') { if(process.env.DAILY_RUN === 'true'){ envURL = this.config.projects[0].use.baseURL; + runName = process.env.WORKFLOW_NAME || 'Nala Daily Run' }else{ envURL = process.env.PR_BRANCH_LIVE_URL || 'N/A'; } exeEnv = 'GitHub Actions Environment'; const repo = process.env.GITHUB_REPOSITORY; const runId = process.env.GITHUB_RUN_ID; - runUrl = `https://github.com/${repo}/actions/runs/${runId}`; + const prNumber = process.env.GITHUB_REF.split('/')[2]; + runUrl = `https://github.com/${repo}/actions/runs/${runId}`; + runName = 'Nala PR Run' + ` (${prNumber}) `; }else if (process.env.CIRCLECI) { envURL = process.env.PR_BRANCH_LIVE_URL || 'N/A'; exeEnv = 'CircleCI Environment'; const workflowId = process.env.CIRCLE_WORKFLOW_ID; const jobNumber = process.env.CIRCLE_BUILD_NUM; runUrl = `https://app.circleci.adobe.com/pipelines/github/wcms/nala/${jobNumber}/workflows/${workflowId}/jobs/${jobNumber}`; + runName = 'Nala CirclCI/Stage Run'; }else { envURL = process.env.LOCAL_TEST_LIVE_URL || 'N/A'; exeEnv = 'Local Environment'; envURL = this.config.projects[0].use.baseURL; - runUrl = 'Local Environment' + runUrl = 'Local Environment'; + runName = 'Nala Local Run'; } const summary = ` - --------Test run summary------------ + ---------Nala Test Run Summary------------ # Total Test executed: ${totalTests} # Test Pass : ${this.passedTests} (${passPercentage}%) # Test Fail : ${this.failedTests} (${failPercentage}%) # Test Skipped : ${this.skippedTests} ** Application URL : ${envURL} ** Executed on : ${exeEnv} - ** Execution details : ${runUrl}`; + ** Execution details : ${runUrl} + ** Workflow name : ${runName}` ; console.log(summary); From 4439f836c0725f278723b2d564ca112c2b810e25 Mon Sep 17 00:00:00 2001 From: Santoshkumar Nateekar Date: Sun, 10 Dec 2023 13:16:11 -0800 Subject: [PATCH 39/53] [MWPW-140301] Create automated daily test run workflows for 'Feds', 'UAR', and 'Blog' in NALA (#230) * uar-daily run * update the pr name * update the print summary * update uar config.js * update the run name --------- Co-authored-by: nateekar --- .github/workflows/uar.daily.yml | 46 ++++++++++++++++++++++++ configs/uar.config.js | 62 +++----------------------------- playwright.config.js | 7 ++-- utils/reporters/base-reporter.js | 31 +++++----------- 4 files changed, 62 insertions(+), 84 deletions(-) create mode 100644 .github/workflows/uar.daily.yml diff --git a/.github/workflows/uar.daily.yml b/.github/workflows/uar.daily.yml new file mode 100644 index 00000000..0e17be58 --- /dev/null +++ b/.github/workflows/uar.daily.yml @@ -0,0 +1,46 @@ +name: UAR Nala Daily Run + +on: + schedule: + - cron: "0 9 * * *" + workflow_dispatch: + +jobs: + platform_matrix: + strategy: + fail-fast: false + matrix: + os: [ubuntu-latest, windows-latest, macos-latest] + name: Running tests + runs-on: ${{ matrix.os }} + env: + WORKFLOW_NAME: 'UAR Nala Daily Run' + DAILY_RUN: 'true' + + steps: + - name: Check out repository + uses: actions/checkout@v3 + + - name: Set up Node.js + uses: actions/setup-node@v3 + with: + node-version: lts/* + + - name: Run Nala ${{ matrix.os }} + run: bash dailyrun.sh uar + env: + IMS_EMAIL: ${{ secrets.IMS_EMAIL }} + IMS_PASS: ${{ secrets.IMS_PASS }} + HLX_TKN: ${{ secrets.HLX_TKN }} + SLACK_WH: ${{ secrets.SLACK_WH }} + + - name: Display workflow name + run: echo "The workflow name is $WORKFLOW_NAME" + + - name: Persist JSON Artifact + uses: actions/upload-artifact@v3 + if: always() + with: + name: nala-results + path: nala-results.json + retention-days: 30 diff --git a/configs/uar.config.js b/configs/uar.config.js index b7f077f4..6dfbeb1b 100644 --- a/configs/uar.config.js +++ b/configs/uar.config.js @@ -27,72 +27,22 @@ const config = { retries: process.env.CI ? 2 : 0, /* Opt out of parallel tests on CI. */ workers: process.env.CI ? 2 : undefined, - /* Reporter to use. See https://playwright.dev/docs/test-reporters */ + /* Reporter to use.*/ reporter: process.env.CI - ? [['github'], ['../utils/reporters/json-reporter.js'], ['../utils/reporters/json-reporter.js']] - : [['list']], - /* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */ + ? [['github'], ['list'], ['../utils/reporters/base-reporter.js']] + : [['list'],['./utils/reporters/base-reporter.js']], + /* Shared settings for all the projects below*/ use: { /* Maximum time each action such as `click()` can take. Defaults to 0 (no limit). */ actionTimeout: 15000, - /* Base URL to use in actions like `await page.goto('/')`. */ - // baseURL: 'http://localhost:3000', - /* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */ + /* Collect trace when retrying the failed test*/ trace: 'on-first-retry', baseURL: process.env.BASE_URL || envs['@adobe_stage'] || 'https://www.stage.adobe.com', }, /* Configure projects for major browsers */ projects: [ - { - name: 'adobe-stage-chrome', - use: { - ...devices['Desktop Chrome'], - baseURL: envs['@adobe_stage'], - }, - }, - - { - name: 'adobe-stage-firefox', - use: { - ...devices['Desktop Firefox'], - baseURL: envs['@adobe_stage'], - }, - }, - - { - name: 'adobe-stage-webkit', - use: { - ...devices['Desktop Safari'], - baseURL: envs['@adobe_stage'], - }, - }, - - { - name: 'adobe-prod-chrome', - use: { - ...devices['Desktop Chrome'], - baseURL: envs['@adobe_prod'], - }, - }, - - { - name: 'adobe-prod-firefox', - use: { - ...devices['Desktop Firefox'], - baseURL: envs['@adobe_prod'], - }, - }, - - { - name: 'adobe-prod-webkit', - use: { - ...devices['Desktop Safari'], - baseURL: envs['@adobe_prod'], - }, - }, - { name: 'uar-live-chrome', use: { @@ -100,7 +50,6 @@ const config = { baseURL: envs['@uar_live'], }, }, - { name: 'uar-live-firefox', use: { @@ -108,7 +57,6 @@ const config = { baseURL: envs['@uar_live'], }, }, - { name: 'uar-live-webkit', use: { diff --git a/playwright.config.js b/playwright.config.js index e9c73701..0f656c10 100644 --- a/playwright.config.js +++ b/playwright.config.js @@ -27,18 +27,15 @@ const config = { retries: process.env.CI ? 2 : 0, /* Opt out of parallel tests on CI. */ workers: process.env.CI ? 4 : 3, - /* Reporter to use. See https://playwright.dev/docs/test-reporters */ + /* Reporter to use.*/ reporter: process.env.CI ? [['github'], ['list'], ['./utils/reporters/base-reporter.js']] : [['html', { outputFolder: 'test-html-results' }],['list'],['./utils/reporters/base-reporter.js']], - /* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */ + /* Shared settings for all the projects below */ use: { /* Maximum time each action such as `click()` can take. Defaults to 0 (no limit). */ actionTimeout: 60000, - /* Base URL to use in actions like `await page.goto('/')`. */ - // baseURL: 'http://localhost:3000', - /* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */ trace: 'on-first-retry', baseURL: process.env.PR_BRANCH_LIVE_URL || ( process.env.LOCAL_TEST_LIVE_URL || 'https://main--milo--adobecom.hlx.live'), }, diff --git a/utils/reporters/base-reporter.js b/utils/reporters/base-reporter.js index 03ec47ed..4a14057a 100644 --- a/utils/reporters/base-reporter.js +++ b/utils/reporters/base-reporter.js @@ -90,40 +90,27 @@ class BaseReporter { } printResultSummary() { - let envURL; - let exeEnv; - let runUrl; - let runName = 'Nala PR Run'; const totalTests = this.results.length; const passPercentage = ((this.passedTests / totalTests) * 100).toFixed(2); const failPercentage = ((this.failedTests / totalTests) * 100).toFixed(2); - + let envURL = process.env.PR_BRANCH_LIVE_URL || this.config.projects[0].use.baseURL; + let exeEnv = 'Local Environment'; + let runUrl = 'Local Environment'; + let runName = 'Nala Local Run'; + if (process.env.GITHUB_ACTIONS === 'true') { - if(process.env.DAILY_RUN === 'true'){ - envURL = this.config.projects[0].use.baseURL; - runName = process.env.WORKFLOW_NAME || 'Nala Daily Run' - }else{ - envURL = process.env.PR_BRANCH_LIVE_URL || 'N/A'; - } exeEnv = 'GitHub Actions Environment'; const repo = process.env.GITHUB_REPOSITORY; const runId = process.env.GITHUB_RUN_ID; const prNumber = process.env.GITHUB_REF.split('/')[2]; - runUrl = `https://github.com/${repo}/actions/runs/${runId}`; - runName = 'Nala PR Run' + ` (${prNumber}) `; - }else if (process.env.CIRCLECI) { - envURL = process.env.PR_BRANCH_LIVE_URL || 'N/A'; + runUrl = `https://github.com/${repo}/actions/runs/${runId}`; + runName = `${process.env.WORKFLOW_NAME ? (process.env.WORKFLOW_NAME || 'Nala Daily Run') : 'Nala PR Run'} (${prNumber})`; + } else if (process.env.CIRCLECI) { exeEnv = 'CircleCI Environment'; const workflowId = process.env.CIRCLE_WORKFLOW_ID; const jobNumber = process.env.CIRCLE_BUILD_NUM; runUrl = `https://app.circleci.adobe.com/pipelines/github/wcms/nala/${jobNumber}/workflows/${workflowId}/jobs/${jobNumber}`; - runName = 'Nala CirclCI/Stage Run'; - }else { - envURL = process.env.LOCAL_TEST_LIVE_URL || 'N/A'; - exeEnv = 'Local Environment'; - envURL = this.config.projects[0].use.baseURL; - runUrl = 'Local Environment'; - runName = 'Nala Local Run'; + runName = 'Nala CircleCI/Stage Run'; } const summary = ` From a06f090c719ca9431bee68b42b0c35b4793f4abc Mon Sep 17 00:00:00 2001 From: Santoshkumar Nateekar Date: Tue, 12 Dec 2023 09:22:18 -0800 Subject: [PATCH 40/53] MWPW-140359 : Nala automation scripts for Merch card (catalog) variant (#231) * nala scripts for merch card - catalog variable * update basereporter path * update readme * readme * readme1 --------- Co-authored-by: nateekar --- .github/workflows/uar.daily.yml | 2 +- README.md | 102 ++++++++++---------- configs/uar.config.js | 2 +- features/milo/merchcard.block.spec.js | 61 +++++++++++- selectors/milo/merchcard.block.page.js | 23 ++++- tests/milo/merchcard.block.test.js | 123 ++++++++++++++++++++++++- 6 files changed, 257 insertions(+), 56 deletions(-) diff --git a/.github/workflows/uar.daily.yml b/.github/workflows/uar.daily.yml index 0e17be58..ec1c413f 100644 --- a/.github/workflows/uar.daily.yml +++ b/.github/workflows/uar.daily.yml @@ -10,7 +10,7 @@ jobs: strategy: fail-fast: false matrix: - os: [ubuntu-latest, windows-latest, macos-latest] + os: [ubuntu-latest] name: Running tests runs-on: ${{ matrix.os }} env: diff --git a/README.md b/README.md index 42aacfff..0c2e61b5 100644 --- a/README.md +++ b/README.md @@ -4,33 +4,36 @@ Automated E2E and integration testing of Milo-based projects. -## Get started - -### 1. GitHub repositoy -- Scenario A : I / We want to use existing Nala repo, learn, explore and contribute to Nala test automation - - step-1 : Fork [Nala](https://github.com/adobecom/nala) repository - - step-2 : Clone, and set the remote URLs (Upstream and Origin) - -- Scenario B : I / We want to onboard to Nala for our application test automation - - step-1 : Follow Scenario A - - step-2 : Your first PR should include adding your project folder(s) under features, selectors and test folders. - - step-3 : Create your project `.config.js` under `configs` folder, and add your application url's in `.env.js`, thats it you are ready to go!! - - - Note: The folder structure in Nala is designed to make it easy to migrate your tests to your repository seamlessly when Nala becomes a consuming tool, -### 2. Nala Dry run test : -- Run following command in your IDE or VSCode terminal +## Getting started + +## Scenario : I wanto to contribute to Nala framework and Milo Test Automation + +### 1. Nala repositoy + + - step-1 : Fork the Nala repository + - Begin by forking the [Nala](https://github.com/adobecom/nala) repository + - step-2 : Clone and Set Remote URLs + - After forking, clone the repository to your local machine + - Configure the remote URLs for both Upstream (original repository) and Origin (your fork). + +### 2. Performing a Dry Run Test + + - Open the Nala codebase in Visual Studio Code (VSCode). + - Execute the following sample command in the terminal to run the 'Quote' block tests ```bash npx playwright test -g@quote ``` -- If any errors, then run following commands to install dependencies defined in the [`package.json`](https://github.com/adobecom/nala/blob/main/package.json) and then re run above command, now it should run the Quote block test scripts +- If you encounter any errors, install the necessary dependencies as defined in the [`package.json`](https://github.com/adobecom/nala/blob/main/package.json), use the following commands: ```bash - npm install - npm fund ``` +- After installing the dependencies, re-run the above command to execute the Quote block test scripts. The tests should now run successfully. + ### 3. Start Nala automation test script creation Nala automation script creation involves following three simple steps. -- #### Step-1 : Create [`feature.spec.js`](https://github.com/adobecom/nala/tree/main/features) under the `features` folder and add test cases and data - - Please refer sample template for creating test cases +- #### Step-1 : Create [`.spec.js`](https://github.com/adobecom/nala/tree/main/features) under the `features` folder and add test cases and data + - Please refer below sample template for creating a test case. ```bash module.exports = { FeatureName: 'Quote Block', @@ -52,8 +55,8 @@ module.exports = { nala spec ---- -- #### Step-2 : Create [`selector.page.js`](https://github.com/adobecom/nala/tree/main/selectors) under the `selectors` folder and add selectors - - Please refer sample template for creating selector page object +- #### Step-2 : Create [`.page.js`](https://github.com/adobecom/nala/tree/main/selectors) page object under the `selectors` folder and add locators + - Please refer to the sample template for creating a selector page object ```bash export default class Quote { constructor(page) { @@ -71,7 +74,7 @@ export default class Quote { nala pom --- -- #### Step-3 : Create [`.test.js`](https://github.com/adobecom/nala-template/blob/main/tests/quote.block.test.js) under the `tests` folder, and add tests +- #### Step-3 : Create [`.test.js`](https://github.com/adobecom/nala-template/blob/main/tests/quote.block.test.js) under the `tests` folder, and add tests - Please refer sample template for creating tests. Also please refer [Nala onboarding wiki](https://github.com/adobecom/nala/wiki/Onboarding#tests) ```bash // Quote block tests @@ -115,7 +118,7 @@ test.describe('Milo Quote block test suite', () => { nala pom --- -### 4. Running Nala tests +## 4 Running Nala tests - Nala offers a range of flexible options to suit your testing needs. Please refer to the following choices for running your tests: - By default Nala is configured to runs all tests in parallel in headless mode on following browsers - Chrome @@ -175,63 +178,64 @@ npx playwright test -g@quote|@marquee|@accordion --project=milo-live-chrome ``` - Note : To run tests using tags, make sure in `.spec.js` file `@tags` are specified -#### 4.4 : Run Tests on my localhost (ex: @local3000': 'http://localhost:3000',) -##### To run Nala tests on your local host, please make sure you have following configs set - - Add your local host url parameter in[`.env.js`](https://github.com/adobecom/nala/blob/main/envs/envs.js) - - `'@local3000': 'http://localhost:3000',` - - Please add a local project and local baseURL in [`playwright.config.js`](https://github.com/adobecom/nala/blob/main/playwright.config.js) + +### 5 : Run Tests on my localhost (i.e. 'http://localhost:3000',) + + - To run Nala tests on your local host server, make sure you add or have following project object in [`playwright.config.js`](https://github.com/adobecom/nala/blob/main/playwright.config.js) ```bash - { - name: 'local-chrome', - use: { - ...devices['Desktop Chrome'], - baseURL: envs['@local3000'], + { + name: 'local-chrome', + use: { + ...devices['Desktop Chrome'], + baseURL: envs['@local3000'], + }, }, - }, ``` ##### Now, you are all set to run Nala tests on your local host - - Example-1 : I want to run all tests on my local environments or projects (i.e [local-chrome]('http://localhost:3000')) on chrome browser in headless mode + - Example-1 : I want to run all tests on my local server or on project name = local-chrome on chrome browser in headless mode ```bash npx playwright test --project=local-chrome ``` - - Example-2: I want to run all smoke test suite on my local all environment or projects on chrome browser in headless mode + - Example-2: I want to run all smoke test suite on my local server or on project name = local-chrome on chrome browser in headless mode ```bash npx playwright test -g@smoke --project=local-chrome ``` -- Note: Please refer other options of section-4, for various run methods +- Note: Please refer above section-4, for various run options. -#### 4.4 : Run Tests on GitHub using using GitHub actions. -##### To run nala tests on GitHub upon Pull Requests (PR), PR should follow below labeling options - - Example-1 : This PR affects Quote block functionality so i want to test Quote block tests on Milo environments +## 6 : Run tests on PRs +##### To run nala tests on pull requests (PRs) please following below labeling options, + + - Example-1 : This PR affects Quote block functionality so i want to test Quote block tests on Milo ```bash - PR Label = @quote @run-on-milo + PR Label = @quote @run-nala ``` - Example-2 : As part of this PR i want to verify all smoke tests on Milo ```bash - PR Label = @smoke @run-on-milo + PR Label = @smoke @run-nala ``` -Example-2 : As part of this PR i want to verify all regression tests on Milo +Example-3 : As part of this PR i want to verify all regression tests on Milo ```bash - PR Label = @regression @run-on-milo + PR Label = @regression @run-nala ``` -- Example-3 : As part of this PR i want to verify accordion, marquee block tests on Milo +- Example-4 : As part of this PR i want to verify accordion and marquee block tests on Milo ```bash PR Label = @accordion @marquee @run-on-milo ``` -Example-4 : As part of this PR i want to verify smokes tests on Milo and Bcom applications / urls - - Note : For this requirement please make sure tests pages with correct paths are available and published in both the application sharepoint directories +Example-5 : As part of this PR i want to verify smokes tests on Milo and Bcom applications ```bash PR Label = @smoke @run-on-milo @run-on-bcom ``` - Note: PR should have label of the format : `@tag(s) @run-on-` -##### All nala tests are schedule to run daily at 9:30 am PST - - Please refer [`daily.yml`](https://github.com/adobecom/nala/blob/main/.github/workflows/daily.yml) for daily run workflow + +## 7 : Daily Runs +##### All Milo and Consuming applications tests are scheduled to run between 6:00 to 9:30 AM PST + - Please refer [` { }); - // Test 6 : Merch Card (plans, secure) with badge + // Test 7 : Merch Card (plans, secure) with badge // Note: skipping the test as there were failures, informed the team test.skip(`${features[7].name},${features[7].tags}`, async ({ page, baseURL }) => { console.info(`[Test Page]: ${baseURL}${features[7].path}`); @@ -300,7 +300,124 @@ test.describe('Milo Modal feature test suite', () => { await expect(await merchCard.footerOutlineButton).toBeVisible(); await expect(await merchCard.footerOutlineButton).toContainText(data.footerOutlineButtonText); - }); + }); + }); + + // Test 8 : Merch Card (catalog) + test(`${features[8].name},${features[8].tags}`, async ({ page, baseURL }) => { + console.info(`[Test Page]: ${baseURL}${features[8].path}`); + const data = features[8].data; + + await test.step('step-1: Go to Merch Card feature test page', async () => { + await page.goto(`${baseURL}${features[8].path}`); + await page.waitForLoadState('domcontentloaded'); + await expect(page).toHaveURL(`${baseURL}${features[8].path}`); + }); + + await test.step('step-2: Verify Merch Card catalog content/specs', async () => { + await expect(await merchCard.catalog).toBeVisible(); + await expect(await merchCard.catalogCardTitleH3).toContainText(data.titleH3); + await expect(await merchCard.catalogCardTitleH4).toContainText(data.titleH4); + + //await expect(await merchCard.price).toContainText(data.price); + + await expect(await merchCard.catalogCardDescription2).toContainText(data.description); + await expect(await merchCard.seeWhatsIncludedTextLink).toContainText(data.link1Text); + await expect(await merchCard.learnMoreTextLink).toContainText(data.link2Text); + + await expect(await merchCard.footer).toBeVisible(); + + await expect(await merchCard.footerBlueButton).toBeVisible(); + await expect(await merchCard.footerBlueButton).toContainText(data.footerBlueButton1Text); + + await expect(await merchCard.footerOutlineButton).toBeVisible(); + await expect(await merchCard.footerOutlineButton).toContainText(data.footerOutlineButtonText); + }); + }); + + // Test 9 : Merch Card (catalog) with badge + test(`${features[9].name},${features[9].tags}`, async ({ page, baseURL }) => { + console.info(`[Test Page]: ${baseURL}${features[9].path}`); + const data = features[9].data; + + await test.step('step-1: Go to Merch Card feature test page', async () => { + await page.goto(`${baseURL}${features[9].path}`); + await page.waitForLoadState('domcontentloaded'); + await expect(page).toHaveURL(`${baseURL}${features[9].path}`); + }); + + await test.step('step-2: Verify Merch Card catalog with badge content/specs', async () => { + await expect(await merchCard.catalog).toBeVisible(); + + await expect(await merchCard.catalog).toHaveAttribute('badge-background-color', data.badgeBgColor); + await expect(await merchCard.catalog).toHaveAttribute('badge-color', data.badgeColor);; + await expect(await merchCard.catalog).toHaveAttribute('badge-text', data.badgeText); + + await expect(await merchCard.catalogCardTitleH3).toContainText(data.titleH3); + await expect(await merchCard.catalogCardTitleH4).toContainText(data.titleH4); + + //await expect(await merchCard.price).toContainText(data.price); + + await expect(await merchCard.catalogCardDescription2).toContainText(data.description); + await expect(await merchCard.seeWhatsIncludedTextLink).toContainText(data.link1Text); + await expect(await merchCard.learnMoreTextLink).toContainText(data.link2Text); + + await expect(await merchCard.footer).toBeVisible(); + + await expect(await merchCard.footerBlueButton).toBeVisible(); + await expect(await merchCard.footerBlueButton).toContainText(data.footerBlueButton1Text); + + await expect(await merchCard.footerOutlineButton).toBeVisible(); + await expect(await merchCard.footerOutlineButton).toContainText(data.footerOutlineButtonText); + }); + }); + + // Test 10 : Merch Card (catalog) with more info and badge + test(`${features[10].name},${features[10].tags}`, async ({ page, baseURL }) => { + console.info(`[Test Page]: ${baseURL}${features[10].path}`); + const data = features[10].data; + + await test.step('step-1: Go to Merch Card feature test page', async () => { + await page.goto(`${baseURL}${features[10].path}`); + await page.waitForLoadState('domcontentloaded'); + await expect(page).toHaveURL(`${baseURL}${features[10].path}`); + }); + + await test.step('step-2: Verify Merch Card catalog with badge content/specs', async () => { + await expect(await merchCard.catalog).toBeVisible(); + + await expect(await merchCard.catalog).toHaveAttribute('badge-background-color', data.badgeBgColor); + await expect(await merchCard.catalog).toHaveAttribute('badge-color', data.badgeColor);; + await expect(await merchCard.catalog).toHaveAttribute('badge-text', data.badgeText); + + await expect(await merchCard.catalogCardTitleH3).toContainText(data.titleH3); + await expect(await merchCard.catalogCardTitleH4).toContainText(data.titleH4); + + //await expect(await merchCard.price).toContainText(data.price); + + await expect(await merchCard.catalogCardDescription2).toContainText(data.description); + await expect(await merchCard.seeWhatsIncludedTextLink).toContainText(data.link1Text); + await expect(await merchCard.learnMoreTextLink).toContainText(data.link2Text); + + await expect(await merchCard.footer).toBeVisible(); + + await expect(await merchCard.footerBlueButton).toBeVisible(); + await expect(await merchCard.footerBlueButton).toContainText(data.footerBlueButton1Text); + + await expect(await merchCard.footerOutlineButton).toBeVisible(); + await expect(await merchCard.footerOutlineButton).toContainText(data.footerOutlineButtonText); + }); + + await test.step('step-3: click more info link and verify action menu list', async () => { + await merchCard.catalog.hover(); + await merchCard.catalog.click(); + await page.waitForTimeout(1000); + + await expect(await merchCard.catalogActionMenuList).toHaveCount(data.actionMenuListCount); + await expect(await merchCard.catalogActionMenuPText1).toContainText(data.actionMenuText1); + await expect(await merchCard.catalogActionMenuPText2).toContainText(data.actionMenuText2); + await expect(await merchCard.catalogActionMenuPText3).toContainText(data.actionMenuText3); + }); + }); - }); }); From cdddfaa74d5a9d74035545db9ec8ff8a85edaeb2 Mon Sep 17 00:00:00 2001 From: Jacky Sun <67350368+JackySun9@users.noreply.github.com> Date: Wed, 13 Dec 2023 11:19:30 -0800 Subject: [PATCH 41/53] Update UAR to run basic tests (#232) * add test for quiz and result pages * add test for quiz and result pages * add test for quiz and result pages * add POC for analytics test * update analytics tests and envs * result envs * update analytics only on firefox * add dynamic tests * add dynamic test for quiz page * update quiz test * update test structure * add test for quiz and result pages * add POC for analytics test * update analytics tests and envs * result envs * update analytics only on firefox * add dynamic tests * add dynamic test for quiz page * update quiz test * update test structure * update uar tests to new format * update uar tests * move everything to uar folder * add dependency for js-yaml * update test according to latest comments * update test according to latest comments * update tests according to the latest comments * add uar config * add analytics for uar * update according to feedbacks * update tags * add @cc tag * update according to feedbacks * add dynamic tests for uar * update according to review comments * fix some typos * update according to review comments * merge console log info * add UI screenshots for UAR * move view point to test * update according to feedback * add analytics test for UAR * update validation and uar libs * update libs * update by feedback * update some config and tests * update some config and tests * update test content path to common path * update analytics tests * fix test failures caused by test code * fix test failures * fix test failures * add visual test for CAAS with two pages * update according to feedbacks * update report in config file * add screenshot for milo main live vs uar-integration live * add timestamp js for time stampe recording * add screenshot diff for uar stable and beta * move uar screenshots into visual compare folder * add UI screenshots for DX Quiz * build a function to get screenshots * update locator * udate uar to only run basic tests * update according to feedback --------- Co-authored-by: xiasun Co-authored-by: Aaron Mauchley Co-authored-by: xiasun --- .github/workflows/uar.daily.yml | 92 ++++++++++++++++----------------- dailyrun.sh | 12 ++++- 2 files changed, 56 insertions(+), 48 deletions(-) diff --git a/.github/workflows/uar.daily.yml b/.github/workflows/uar.daily.yml index ec1c413f..6f77255a 100644 --- a/.github/workflows/uar.daily.yml +++ b/.github/workflows/uar.daily.yml @@ -1,46 +1,46 @@ -name: UAR Nala Daily Run - -on: - schedule: - - cron: "0 9 * * *" - workflow_dispatch: - -jobs: - platform_matrix: - strategy: - fail-fast: false - matrix: - os: [ubuntu-latest] - name: Running tests - runs-on: ${{ matrix.os }} - env: - WORKFLOW_NAME: 'UAR Nala Daily Run' - DAILY_RUN: 'true' - - steps: - - name: Check out repository - uses: actions/checkout@v3 - - - name: Set up Node.js - uses: actions/setup-node@v3 - with: - node-version: lts/* - - - name: Run Nala ${{ matrix.os }} - run: bash dailyrun.sh uar - env: - IMS_EMAIL: ${{ secrets.IMS_EMAIL }} - IMS_PASS: ${{ secrets.IMS_PASS }} - HLX_TKN: ${{ secrets.HLX_TKN }} - SLACK_WH: ${{ secrets.SLACK_WH }} - - - name: Display workflow name - run: echo "The workflow name is $WORKFLOW_NAME" - - - name: Persist JSON Artifact - uses: actions/upload-artifact@v3 - if: always() - with: - name: nala-results - path: nala-results.json - retention-days: 30 +name: UAR Nala Daily Run + +on: + schedule: + - cron: "0 9 * * *" + workflow_dispatch: + +jobs: + platform_matrix: + strategy: + fail-fast: false + matrix: + os: [ubuntu-latest] + name: Running tests + runs-on: ${{ matrix.os }} + env: + WORKFLOW_NAME: 'UAR Nala Daily Run' + DAILY_RUN: 'true' + + steps: + - name: Check out repository + uses: actions/checkout@v3 + + - name: Set up Node.js + uses: actions/setup-node@v3 + with: + node-version: lts/* + + - name: Run Nala ${{ matrix.os }} + run: bash dailyrun.sh uar @uar-quiz-basic + env: + IMS_EMAIL: ${{ secrets.IMS_EMAIL }} + IMS_PASS: ${{ secrets.IMS_PASS }} + HLX_TKN: ${{ secrets.HLX_TKN }} + SLACK_WH: ${{ secrets.SLACK_WH }} + + - name: Display workflow name + run: echo "The workflow name is $WORKFLOW_NAME" + + - name: Persist JSON Artifact + uses: actions/upload-artifact@v3 + if: always() + with: + name: nala-results + path: nala-results.json + retention-days: 30 diff --git a/dailyrun.sh b/dailyrun.sh index 4c013fe0..567e5cf1 100644 --- a/dailyrun.sh +++ b/dailyrun.sh @@ -1,7 +1,8 @@ #!/bin/bash # get the input argument i.e. config.js file name -PROJECT_NAME=$1 +PROJECT_NAME=$1 +TAG=$2 # Construct the full path to the config.js file CONFIG_FILE_PATH="./configs/${PROJECT_NAME}.config.js" @@ -13,7 +14,14 @@ if [ -f "${CONFIG_FILE_PATH}" ]; then npm ci npx playwright install --with-deps echo "*** Running Playwright tests with config: ${CONFIG_FILE_PATH} ***" - npx playwright test --config="${CONFIG_FILE_PATH}" + if [ -n "$TAG" ]; then + echo "Running with TAG: ${TAG}" + npx playwright test --config="${CONFIG_FILE_PATH}" --grep="${TAG}" + exit 0 + else + npx playwright test --config="${CONFIG_FILE_PATH}" + exit 0 + fi else echo "Config file: ${CONFIG_FILE_PATH} not found, running default tests" exit 1 From 1e257a72b24df28b7418b5984e24c2c7b701a364 Mon Sep 17 00:00:00 2001 From: Santoshkumar Nateekar Date: Wed, 3 Jan 2024 11:09:14 -0800 Subject: [PATCH 42/53] [MWPW-140873] Refactor automation test scripts (#233) * update quote block * update * column blocks refactor * howto blocks refactor * rm space * zpattern block test * update html extn --------- Co-authored-by: nateekar --- features/milo/htmlextn.spec.js | 8 +- features/milo/zpattern.block.spec.js | 104 +++++++++++- selectors/milo/columns.block.page.js | 124 +-------------- selectors/milo/howto.block.page.js | 63 ++------ selectors/milo/quote.block.page.js | 116 +------------- selectors/milo/zpattern.block.page.js | 217 +------------------------- tests/milo/columns.block.test.js | 92 +++++++++-- tests/milo/howto.block.test.js | 23 ++- tests/milo/htmlextn.feature.test.js | 126 +++++---------- tests/milo/quote.block.test.js | 75 +++++++-- tests/milo/zpattern.block.test.js | 117 +++++++++++++- 11 files changed, 437 insertions(+), 628 deletions(-) diff --git a/features/milo/htmlextn.spec.js b/features/milo/htmlextn.spec.js index eef54622..b5f372e9 100644 --- a/features/milo/htmlextn.spec.js +++ b/features/milo/htmlextn.spec.js @@ -2,21 +2,21 @@ module.exports = { name: 'HTML Extension', features: [ { - name: '@Html Extn', + name: '@Html Extn for bcom', path: [ '/customer-success-stories', '/customer-success-stories/jaguar-land-rover-case-study', '/customer-success-stories/abb-case-study', '/customer-success-stories/dentsu-isobar-case-study', - '/blog/', '/jp/customer-success-stories/adobe-experience-cloud-case-study', ], envs: '@bacom_prod', tags: '@htmlextn', }, { - name: '@Html Extn', - path: '/en/publish/2023/02/01/see-you-in-vegas-adobe-summit-2023-reg-open', + name: '@Html Extn for Blog', + path: [ + '/en/publish/2023/02/01/see-you-in-vegas-adobe-summit-2023-reg-open'], envs: '@blog_prod', tags: '@htmlextn', }, diff --git a/features/milo/zpattern.block.spec.js b/features/milo/zpattern.block.spec.js index c80bf143..2827a529 100644 --- a/features/milo/zpattern.block.spec.js +++ b/features/milo/zpattern.block.spec.js @@ -6,11 +6,29 @@ module.exports = { name: '@ZPattern', path: '/drafts/nala/blocks/zpattern/z-pattern', data: { - detailText: 'Detail M 12/15', - h2Text: 'Heading XS 18/22 Media (small)', - bodyText: 'Body S 16/24 Lorem ipsum dolor sit amet', - blueButtonText: 'Learn More', - outlineButtonText: 'Watch the Video', + headingText: 'Medium Intro Text (optional)', + introText: 'Perspiciatis unde omnis iste natus error', + mediaBlockCount: 3, + mediaBlocks: [ + { + detailText: 'Detail M 12/15', + h2Text: 'Heading M 24/30 z-pattern medium', + bodyText: 'Body S 16/24 Lorem ipsum dolor sit amet', + blueButtonText: 'learn more', + }, + { + detailText: 'Detail M 12/15', + h2Text: 'Heading M 24/30 z-pattern medium', + bodyText: 'Body S 16/24 Lorem ipsum dolor sit amet', + blueButtonText: 'learn more', + }, + { + detailText: 'Detail M 12/15', + h2Text: 'Heading M 24/30 z-pattern medium', + bodyText: 'Body S 16/24 Lorem ipsum dolor sit amet', + blueButtonText: 'learn more', + }, + ], }, tags: '@zpattern @smoke @regression @milo', }, @@ -18,6 +36,31 @@ module.exports = { tcid: '1', name: '@ZPattern (small)', path: '/drafts/nala/blocks/zpattern/z-pattern-small', + data: { + headingText: 'Small (default) Intro Text (optional)', + introText: 'Media blocks may use one of three background colors', + mediaBlockCount: 3, + mediaBlocks: [ + { + detailText: 'Detail M 12/15', + h2Text: 'Heading XS 18/22 z-pattern small', + bodyText: 'Body S 16/24 Lorem ipsum dolor sit amet', + blueButtonText: 'learn more', + }, + { + detailText: 'Detail M 12/15', + h2Text: 'Heading XS 18/22 z-pattern small', + bodyText: 'Body S 16/24 Lorem ipsum dolor sit amet', + blueButtonText: 'learn more', + }, + { + detailText: 'Detail M 12/15', + h2Text: 'Heading XS 18/22 z-pattern small', + bodyText: 'Body S 16/24 Lorem ipsum dolor sit amet', + blueButtonText: 'learn more', + }, + ], + }, tags: '@zpattern @zpattern-small @smoke @regression @milo', }, @@ -25,12 +68,63 @@ module.exports = { tcid: '2', name: '@Zpattern (large)', path: '/drafts/nala/blocks/zpattern/z-pattern-large', + data: { + headingText: 'Large Intro Text (optional)', + introText: 'Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium', + mediaBlockCount: 3, + mediaBlocks: [ + { + detailText: 'Detail L 16/20', + h2Text: 'Heading XL 36/45 z-pattern large', + bodyText: 'Body M 18/27 Lorem ipsum dolor sit amet', + blueButtonText: 'learn more', + }, + { + detailText: 'Detail L 16/20', + h2Text: 'Heading XL 36/45 z-pattern large', + bodyText: 'Body M 18/27 Lorem ipsum dolor sit amet', + blueButtonText: 'learn more', + }, + { + detailText: 'Detail L 16/20', + h2Text: 'Heading XL 36/45 z-pattern large', + bodyText: 'Body M 18/27 Lorem ipsum dolor sit amet', + blueButtonText: 'learn more', + }, + ], + }, tags: '@zpattern @zpattern-large @smoke @regression @milo', }, + { tcid: '3', name: '@Zpattern (dark)', path: '/drafts/nala/blocks/zpattern/z-pattern-dark', + data: { + headingText: 'Intuitive block authoring', + introText: 'Supports alternating or inline authoring preferences', + mediaBlockCount: 3, + mediaBlocks: [ + { + detailText: 'Detail M 12/15', + h2Text: 'Heading M 24/30 z-pattern medium', + bodyText: 'Body S 16/24 Lorem ipsum dolor sit amet', + blueButtonText: 'Learn More', + }, + { + detailText: 'Detail M 12/15', + h2Text: 'Heading M 24/30 z-pattern medium', + bodyText: 'Body S 16/24 Lorem ipsum dolor sit amet', + blueButtonText: 'Learn More', + }, + { + detailText: 'Detail M 12/15', + h2Text: 'Heading M 24/30 z-pattern medium', + bodyText: 'Body S 16/24 Lorem ipsum dolor sit amet', + blueButtonText: 'Learn More', + }, + ], + }, tags: '@zpattern @zpattern-dark @smoke @regression @milo', }, ], diff --git a/selectors/milo/columns.block.page.js b/selectors/milo/columns.block.page.js index 4c4994d3..6c9f4de5 100644 --- a/selectors/milo/columns.block.page.js +++ b/selectors/milo/columns.block.page.js @@ -2,10 +2,10 @@ import { expect } from '@playwright/test'; import { WebUtil } from '../../libs/webutil.js'; export default class Columns { - constructor(page) { + constructor(page, nth = 0) { this.page = page; // columns locators - this.column = this.page.locator('.columns'); + this.column = this.page.locator('.columns').nth(nth); this.rows = this.column.locator('.row'); this.columns = this.column.locator('.col'); @@ -52,124 +52,4 @@ export default class Columns { 'columns-contained-table': { 'class': 'columns contained columns-table' }, }; } - - /** - * Verifies the visibility, css, attributes, styles, of elements or sections of - * the specified Columns block. - * @param {string} columnType - The type of the Columns block to verify. - * Possible values are 'columns', 'columns (contained)', 'columns (contained,middle)',and - * columns (table),columns (contained,table), - * @returns {Promise} - Returns true if the specified Column type has the expected values. - */ - async verifyColumns(columnType, data) { - // verify column block is visible - await expect(await this.column).toBeVisible(); - - // verify rows and columns count - await expect(await this.rows).toHaveCount(data.rows); - await expect(await this.columns).toHaveCount(data.columns); - - // verify columns text - await expect(await this.columns.nth(0)).toContainText(data.col0); - await expect(await this.columns.nth(1)).toContainText(data.col1); - - // verify the css of columns row - if (!columnType.includes('table')) { - expect(await WebUtil.verifyCSS( - await this.rows.nth(0), - this.cssProperties['.columns > .row'], - )).toBeTruthy(); - } - - switch (columnType) { - case 'columns': - // verify the attributes of columns type block - expect(await WebUtil.verifyAttributes( - await this.column, - this.attProperties.columns, - )).toBeTruthy(); - // verify third column content - await expect(await this.columns.nth(2)).toContainText(data.col2); - return true; - - case 'columns(contained)': - // verify the attributes of columns type block - expect(await WebUtil.verifyAttributes( - await this.column, - this.attProperties['columns-contained'], - )).toBeTruthy(); - - // verify the css of columns row - expect(await WebUtil.verifyCSS( - await this.column.nth(0), - this.cssProperties['.columns.contained'], - )).toBeTruthy(); - - return true; - - case 'columns(contained,middle)': - // verify the attributes of columns type block - expect(await WebUtil.verifyAttributes( - await this.column, - this.attProperties['columns-contained-middle'], - )).toBeTruthy(); - - // verify the css of columns row - expect(await WebUtil.verifyCSS( - await this.column.nth(0), - this.cssProperties['.columns.contained'], - )).toBeTruthy(); - return true; - - case 'columns(table)': - // verify the attributes of columns type block - expect(await WebUtil.verifyAttributes( - await this.column, - this.attProperties['columns-table'], - )).toBeTruthy(); - - // verify the css of columns first row - expect(await WebUtil.verifyCSS( - await this.rows.nth(0), - this.cssProperties['.columns.table > .row:first-child'], - )).toBeTruthy(); - - expect(await WebUtil.verifyCSS( - await this.rows.nth(1), - this.cssProperties['.columns.table > .row'], - )).toBeTruthy(); - - // verify columns text - await expect(await this.columns.nth(2)).toContainText(data.col2); - await expect(await this.columns.nth(3)).toContainText(data.col3); - - return true; - - case 'columns(contained,table)': - // verify the attributes of columns type block - expect(await WebUtil.verifyAttributes( - await this.column, - this.attProperties['columns-contained-table'], - )).toBeTruthy(); - - // verify the css of columns first row - expect(await WebUtil.verifyCSS( - await this.rows.nth(0), - this.cssProperties['.columns.table > .row:first-child'], - )).toBeTruthy(); - - expect(await WebUtil.verifyCSS( - await this.rows.nth(1), - this.cssProperties['.columns.table > .row'], - )).toBeTruthy(); - - // verify columns text - await expect(await this.columns.nth(2)).toContainText(data.col2); - await expect(await this.columns.nth(3)).toContainText(data.col3); - - return true; - default: - throw new Error(`Unsupported Text type: ${this.columnsType}`); - } - } } diff --git a/selectors/milo/howto.block.page.js b/selectors/milo/howto.block.page.js index 5c6fdfd4..310bd2a9 100644 --- a/selectors/milo/howto.block.page.js +++ b/selectors/milo/howto.block.page.js @@ -1,18 +1,15 @@ -import { expect } from '@playwright/test'; -import { WebUtil } from '../../libs/webutil.js'; - export default class HowTo { - constructor(page) { + constructor(page, nth = 0) { this.page = page; // how-to locators - this.howTo = page.locator('.how-to'); - this.howToForeground = this.howTo.locator('.foreground'); - this.howToLarge = this.page.locator('.how-to.large-image'); - this.howToSeo = this.page.locator('.how-to.seo'); - this.howToHeading = this.howTo.locator('.how-to-heading'); - this.howToImage = this.howTo.locator('.how-to-image'); - this.howToList = this.howTo.locator('li'); - this.howToLargeImage = page.locator('.how-to-image img'); + this.howTo = page.locator('.how-to').nth(nth); + this.foreground = this.howTo.locator('.foreground'); + this.howToLarge = this.page.locator('.how-to.large-image').nth(nth); + this.howToSeo = this.page.locator('.how-to.seo').nth(nth); + this.heading = this.howTo.locator('.how-to-heading'); + this.image = this.howTo.locator('.how-to-image'); + this.list = this.howTo.locator('li'); + this.largeImage = page.locator('.how-to-image img'); // howto contents css this.cssProperties = { @@ -50,48 +47,6 @@ export default class HowTo { 'width': '600', 'height': '300', }, - }; } - - /** - * Verifies the css, attributes, styles, of elements or sections of the specified HowTo block. - * - * @param {string} howToType - The type of the HowTo to verify. - * Possible values are 'how-to', 'how-to (large-image)', and 'how-to (seo)'. - * @param {Integer} howToListCount - Howto block list count (ex: 3, 4, 5 etc..). - * @returns {Promise} - Returns true if the specified HowTo type has the expected values. - */ - async verifyHowTo(howToType, howToListCount) { - switch (howToType) { - case 'how-to': - // verify howto visibility and css values - await expect(this.howTo).toBeVisible(); - expect(await WebUtil.verifyCSS(this.howToForeground, this.cssProperties['.how-to .foreground'])).toBeTruthy(); - expect(await WebUtil.verifyCSS(this.howToHeading, this.cssProperties['body-m'])).toBeTruthy(); - expect(await WebUtil.verifyCSS(this.howToImage, this.cssProperties['how-to-image'])).toBeTruthy(); - // verify howto list count - await expect(await this.howToList).toHaveCount(howToListCount); - return true; - case 'how-to (large)': - // verify howto large visibility and css values - await expect(this.howToLarge).toBeVisible(); - expect(await WebUtil.verifyCSS(this.howToHeading, this.cssProperties['body-m'])).toBeTruthy(); - expect(await WebUtil.verifyCSS(this.howToLarge, this.cssProperties['how-to-large-image'])).toBeTruthy(); - expect(await WebUtil.verifyAttributes(await this.howToLargeImage, this.attProperties['how-to-large-image'])).toBeTruthy(); - // verify howto list count - await expect(await this.howToList).toHaveCount(howToListCount); - return true; - case 'how-to (seo)': - // verify howto seo visibility and css values - await expect(this.howToSeo).toBeVisible(); - expect(await WebUtil.verifyCSS(this.howToHeading, this.cssProperties['body-m'])).toBeTruthy(); - expect(await WebUtil.verifyCSS(this.howToSeo, this.cssProperties['how-to-seo'])).toBeTruthy(); - // verify howto list count - await expect(await this.howToList).toHaveCount(howToListCount); - return true; - default: - throw new Error(`Unsupported howto type: ${this.howToList}`); - } - } }; diff --git a/selectors/milo/quote.block.page.js b/selectors/milo/quote.block.page.js index c47204ad..ed65fd36 100644 --- a/selectors/milo/quote.block.page.js +++ b/selectors/milo/quote.block.page.js @@ -1,11 +1,8 @@ -import { expect } from '@playwright/test'; -import { WebUtil } from '../../libs/webutil.js'; - export default class Quote { - constructor(page) { + constructor(page, nth = 0) { this.page = page; // quote locators - this.quote = this.page.locator('.quote'); + this.quote = this.page.locator('.quote').nth(nth); this.quoteImage = this.quote.locator('.quote-image'); this.quoteCopy = this.quote.locator('p.quote-copy'); this.quoteFigCaption = this.quote.locator('p.figcaption'); @@ -62,115 +59,6 @@ export default class Quote { 'quote-align-right': { 'class': 'quote contained align-right con-block' }, 'quote-xl-spacing': { 'class': 'quote contained xl-spacing con-block' }, 'section-dark': { 'style': 'background: rgb(102, 102, 102);' }, - }; } - - /** - * Verifies the visibility, css, attributes, styles, of elements or sections of - * the specified Quote block. - * - * @param {string} quoteType - The type of the Quote block to verify. - * Possible values are 'quote', 'quote (contained)', 'quote (inline)'. - * quote (borders), quote (align-right), and quote (xl-spaced) - * @returns {Promise} - Returns true if the specified Quote type has the expected values. - */ - async verifyQuote(quoteType, data) { - await expect(await this.quote).toBeVisible(); - - switch (quoteType) { - case 'quote': - // verify quote block image visibility, attributes, css and different contents - await expect(await this.quoteImage).toBeVisible(); - expect(await WebUtil.verifyAttributes( - await this.quote, - this.attProperties.quote, - )).toBeTruthy(); - expect(await WebUtil.verifyCSS(await this.quote, this.cssProperties.quote)).toBeTruthy(); - await expect(await this.quoteCopy).toContainText(data.quoteCopy); - await expect(await this.quoteFigCaption).toContainText(data.figCaption); - await expect(await this.quoteFigCaptionCite).toContainText(data.cite); - - return true; - case 'quote (contained)': - // verify quote (contained) block image visibility, attributes, css and different contents - await expect(await this.quoteImage).toBeVisible(); - expect(await WebUtil.verifyAttributes( - await this.quote, - this.attProperties['quote-contained'], - )).toBeTruthy(); - expect(await WebUtil.verifyCSS(await this.quote, this.cssProperties['quote-contained'])).toBeTruthy(); - await expect(await this.quoteCopy).toContainText(data.quoteCopy); - await expect(await this.quoteFigCaption).toContainText(data.figCaption); - await expect(await this.quoteFigCaptionCite).toContainText(data.cite); - - return true; - - case 'quote (inline)': - // verify quote (inline) block image visibility, attributes, css and different contents - await expect(await this.quoteImage).toBeVisible(); - expect(await WebUtil.verifyAttributes( - await this.quote, - this.attProperties['quote-inline'], - )).toBeTruthy(); - expect(await WebUtil.verifyCSS(await this.quote, this.cssProperties.quote)).toBeTruthy(); - expect(await WebUtil.verifyCSS(await this.quoteImage, this.cssProperties['quote-inline-figure'])).toBeTruthy(); - await expect(await this.quoteCopy).toContainText(data.quoteCopy); - await expect(await this.quoteFigCaption).toContainText(data.figCaption); - await expect(await this.quoteFigCaptionCite).toContainText(data.cite); - - return true; - - case 'quote (borders)': - // verify quote (borders) block image not visibility, attributes, css and different contents - await expect(await this.quoteImage).not.toBeVisible(); - expect(await WebUtil.verifyAttributes( - await this.quote, - this.attProperties['quote-borders'], - )).toBeTruthy(); - expect(await WebUtil.verifyCSS(await this.quote, this.cssProperties.quote)).toBeTruthy(); - await expect(await this.quoteCopy).toContainText(data.quoteCopy); - await expect(await this.quoteFigCaption).toContainText(data.figCaption); - await expect(await this.quoteFigCaptionCite).toContainText(data.cite); - - return true; - - case 'quote (align-right)': - // verify quote (align-right) block image visibility, attributes, css and different content - await expect(await this.quoteImage).toBeVisible(); - expect(await WebUtil.verifyAttributes( - await this.quote, - this.attProperties['quote-align-right'], - )).toBeTruthy(); - expect(await WebUtil.verifyCSS(await this.quote, this.cssProperties['quote-align-right'])).toBeTruthy(); - await expect(await this.quoteCopy).toContainText(data.quoteCopy); - await expect(await this.quoteFigCaption).toContainText(data.figCaption); - await expect(await this.quoteFigCaptionCite).toContainText(data.cite); - - return true; - - case 'quote (xl-spaced)': - // verify quote (xl-spaced) block image visibility, attributes, css and different content - await expect(await this.sectionDark).toBeVisible(); - expect(await WebUtil.verifyAttributes( - await this.sectionDark, - this.attProperties['section-dark'], - )).toBeTruthy(); - - await expect(await this.quoteImage).not.toBeVisible(); - expect(await WebUtil.verifyAttributes( - await this.quote, - this.attProperties['quote-xl-spacing'], - )).toBeTruthy(); - - expect(await WebUtil.verifyCSS(await this.quote, this.cssProperties.quote)).toBeTruthy(); - await expect(await this.quoteCopy).toContainText(data.quoteCopy); - await expect(await this.quoteFigCaption).toContainText(data.figCaption); - await expect(await this.quoteFigCaptionCite).toContainText(data.cite); - - return true; - default: - throw new Error(`Unsupported Text type: ${this.quoteType}`); - } - } } diff --git a/selectors/milo/zpattern.block.page.js b/selectors/milo/zpattern.block.page.js index 2ade4ea4..372de7c5 100644 --- a/selectors/milo/zpattern.block.page.js +++ b/selectors/milo/zpattern.block.page.js @@ -1,100 +1,20 @@ -import { expect } from '@playwright/test'; -import { WebUtil } from '../../libs/webutil.js'; - export default class ZPattern { - constructor(page) { + constructor(page, nth = 0) { this.page = page; // z-pattern locators - this.zPattern = page.locator('.z-pattern').first(); + this.zPattern = page.locator('.z-pattern').nth(nth); // zpatter header this.zPatternHeader = this.zPattern.locator('.heading-row'); + this.zPatternPText = this.zPatternHeader.locator('p'); + this.smallIntroHeadingText = this.zPattern.locator('#small-default-intro-text-optional'); this.mediumIntroHeadingText = this.zPattern.locator('#medium-intro-text-optional'); this.largeIntroHeadingText = this.zPattern.locator('#large-intro-text-optional'); this.darkIntroHeadingText = this.zPattern.locator('#intuitive-block-authoring'); this.zPatternMediaBlocks = this.zPattern.locator('.media'); - - // zpattern contents css - this.cssProperties = { - 'media': { - 'margin': /^0px(.*)/, - 'position': 'relative', - }, - 'media-large-dark': { - 'margin': /^0px(.*)/, - 'position': 'relative', - }, - 'heading-xl': { - 'font-size': '36px', - 'line-height': '45px', - }, - 'heading-l': { - 'font-size': '28px', - 'line-height': '35px', - }, - 'heading-m': { - 'font-size': '24px', - 'line-height': '30px', - }, - 'heading-xs': { - 'font-size': '18px', - 'line-height': '22.5px', - }, - 'detail-l': { - 'font-size': '16px', - 'line-height': '20px', - }, - 'detail-m': { - 'font-size': '12px', - 'line-height': '15px', - }, - 'body-m': { - 'font-size': '18px', - 'line-height': '27px', - }, - 'body-s': { - 'font-size': '16px', - 'line-height': '24px', - }, - 'outline-button': { - 'border': '2px solid rgb(44, 44, 44)', - 'color': 'rgb(44, 44, 44)', - 'border-radius': '16px', - 'display': 'block', - 'padding': '5px 14px', - 'font-size': '15px', - 'line-height': '16px', - 'font-style': 'normal', - 'font-weight': '700', - }, - 'con-button-blue': { - 'border': '2px solid rgb(20, 115, 230)', - 'color': 'rgb(255, 255, 255)', - 'background': /^rgb\(20,\s*115,\s*230\)(.*)/, - 'border-radius': '16px', - 'display': 'block', - 'padding': '5px 14px', - 'font-size': '15px', - 'line-height': '16px', - 'font-style': 'normal', - 'font-weight': '700', - }, - 'body-text': { - 'border': '0px none rgb(44, 44, 44)', - 'color': 'rgb(44, 44, 44)', - 'background': /^rgba\(0,\s*0,\s*0,\s*0\)(.*)/, - 'border-radius': '0px', - 'display': 'block', - 'padding': '0px', - 'font-size': '16px', - 'line-height': '24px', - 'font-style': 'normal', - 'font-weight': '400', - }, - - }; + this.mediaBlocks = this.zPattern.locator('.media'); // zpattern contents attributes this.attProperties = { @@ -126,130 +46,5 @@ export default class ZPattern { }; } - - /** - * Verifies the css, attributes & styles, of elements of the specified Z Pattern block. - * - * @param {string} howToType - The type of the Z Pattern to verify. - * Possible values are 'zpattern', z-pattern (small), z-pattern (large) and z-pattern (dark) - * @returns {Promise} - Returns true if the specified Z Pattern type has the expected values. - */ - async verifyZPattern(zPatternType) { - const mediaBlocks = await this.zPatternMediaBlocks.all(); - const mediaBlocksArray = await Promise.all(mediaBlocks.map(async (block) => block)); - - switch (zPatternType) { - case 'z-pattern': - // verify z-pattern style background - expect(await WebUtil.verifyAttributes(this.zPattern, this.attProperties['z-pattern'])).toBeTruthy(); - - // verify Z pattern intro text css and attributes - expect(await WebUtil.verifyCSS(this.mediumIntroHeadingText, this.cssProperties['heading-l'])).toBeTruthy(); - expect(await WebUtil.verifyAttributes(this.mediumIntroHeadingText, this.attProperties['medium-intro-text-optional'])).toBeTruthy(); - - // verify Z pattern elements css and attributes - for (const mediaBlock of mediaBlocksArray) { - const classAttribute = await mediaBlock.getAttribute('class'); - const hasReversedClass = classAttribute.includes('media-reversed'); - if (hasReversedClass) { - expect(await WebUtil.verifyAttributes(mediaBlock, this.attProperties['medium-media-reversed'])).toBeTruthy(); - } - - const detailText = await mediaBlock.locator('.detail-m'); - const headerText = await mediaBlock.locator('.heading-m'); - const bodyText = await mediaBlock.locator('.body-s').nth(0); - const blueButton = await mediaBlock.locator('.blue').nth(0); - const image = await mediaBlock.locator('.image img').nth(0); - expect(await WebUtil.verifyCSS(detailText, this.cssProperties['detail-m'])).toBeTruthy(); - expect(await WebUtil.verifyCSS(headerText, this.cssProperties['heading-m'])).toBeTruthy(); - expect(await WebUtil.verifyCSS(bodyText, this.cssProperties['body-s'])).toBeTruthy(); - expect(await WebUtil.verifyCSS(blueButton, this.cssProperties['con-button-blue'])).toBeTruthy(); - - expect(await WebUtil.verifyAttributes(image, this.attProperties['media-image'])).toBeTruthy(); - } - return true; - - case 'z-pattern (small)': - // verify Z pattern (small) intro text css and attributes - expect(await WebUtil.verifyCSS(this.smallIntroHeadingText, this.cssProperties['heading-l'])).toBeTruthy(); - expect(await WebUtil.verifyAttributes(this.smallIntroHeadingText, this.attProperties['small-default-intro-text-optional'])).toBeTruthy(); - - // verify Z pattern (small) elements css and attributes - for (const mediaBlock of mediaBlocksArray) { - const classAttribute = await mediaBlock.getAttribute('class'); - const hasReversedClass = classAttribute.includes('media-reversed'); - if (hasReversedClass) { - expect(await WebUtil.verifyAttributes(mediaBlock, this.attProperties['small-media-reversed'])).toBeTruthy(); - } - const detailText = await mediaBlock.locator('.detail-m'); - const headerText = await mediaBlock.locator('.heading-xs'); - const bodyText = await mediaBlock.locator('.body-s').nth(0); - const blueButton = await mediaBlock.locator('.blue').nth(0); - const image = await mediaBlock.locator('.image img').nth(0); - expect(await WebUtil.verifyCSS(detailText, this.cssProperties['detail-m'])).toBeTruthy(); - expect(await WebUtil.verifyCSS(headerText, this.cssProperties['heading-xs'])).toBeTruthy(); - expect(await WebUtil.verifyCSS(bodyText, this.cssProperties['body-s'])).toBeTruthy(); - expect(await WebUtil.verifyCSS(blueButton, this.cssProperties['con-button-blue'])).toBeTruthy(); - - expect(await WebUtil.verifyAttributes(image, this.attProperties['media-image'])).toBeTruthy(); - } - return true; - - case 'z-pattern (large)': - - // verify Z pattern (large) intro text css and attributes - expect(await WebUtil.verifyCSS(this.largeIntroHeadingText, this.cssProperties['heading-xl'])).toBeTruthy(); - expect(await WebUtil.verifyAttributes(this.largeIntroHeadingText, this.attProperties['large-intro-text-optional'])).toBeTruthy(); - - // verify Z pattern (large) elements css and attributes - for (const mediaBlock of mediaBlocksArray) { - const classAttribute = await mediaBlock.getAttribute('class'); - const hasReversedClass = classAttribute.includes('media-reversed'); - if (hasReversedClass) { - expect(await WebUtil.verifyAttributes(mediaBlock, this.attProperties['large-media-reversed'])).toBeTruthy(); - } - const detailText = await mediaBlock.locator('.detail-l'); - const headerText = await mediaBlock.locator('.heading-xl'); - const bodyText = await mediaBlock.locator('.body-m').nth(0); - const blueButton = await mediaBlock.locator('.blue').nth(0); - const image = await mediaBlock.locator('.image img').nth(0); - expect(await WebUtil.verifyCSS(detailText, this.cssProperties['detail-l'])).toBeTruthy(); - expect(await WebUtil.verifyCSS(headerText, this.cssProperties['heading-xl'])).toBeTruthy(); - expect(await WebUtil.verifyCSS(bodyText, this.cssProperties['body-m'])).toBeTruthy(); - expect(await WebUtil.verifyCSS(blueButton, this.cssProperties['con-button-blue'])).toBeTruthy(); - expect(await WebUtil.verifyAttributes(image, this.attProperties['media-image'])).toBeTruthy(); - } - return true; - - case 'z-pattern (dark)': - // verify z-pattern (dark) style background - expect(await WebUtil.verifyAttributes(this.zPattern, this.attProperties['z-pattern-dark'])).toBeTruthy(); - - // verify Z pattern (dark) intro text css and attributes - expect(await WebUtil.verifyCSS(this.darkIntroHeadingText, this.cssProperties['heading-l'])).toBeTruthy(); - expect(await WebUtil.verifyAttributes(this.darkIntroHeadingText, this.attProperties['dark-intro-text-optional'])).toBeTruthy(); - - // verify Z pattern (dark) elements css and attributes - for (const mediaBlock of mediaBlocksArray) { - const classAttribute = await mediaBlock.getAttribute('class'); - const hasReversedClass = classAttribute.includes('media-reversed'); - if (hasReversedClass) { - expect(await WebUtil.verifyAttributes(mediaBlock, this.attProperties['medium-media-reverse-mobile'])).toBeTruthy(); - } - const detailText = await mediaBlock.locator('.detail-m'); - const headerText = await mediaBlock.locator('.heading-m'); - const bodyText = await mediaBlock.locator('.body-s').nth(0); - const blueButton = await mediaBlock.locator('.blue').nth(0); - const image = await mediaBlock.locator('.image img').nth(0); - expect(await WebUtil.verifyCSS(detailText, this.cssProperties['detail-m'])).toBeTruthy(); - expect(await WebUtil.verifyCSS(headerText, this.cssProperties['heading-m'])).toBeTruthy(); - expect(await WebUtil.verifyCSS(bodyText, this.cssProperties['body-s'])).toBeTruthy(); - expect(await WebUtil.verifyCSS(blueButton, this.cssProperties['con-button-blue'])).toBeTruthy(); - expect(await WebUtil.verifyAttributes(image, this.attProperties['media-image'])).toBeTruthy(); - } - return true; - default: - throw new Error(`Unsupported Z Pattern type: ${this.zPatternType}`); - } - } }; + diff --git a/tests/milo/columns.block.test.js b/tests/milo/columns.block.test.js index 6557fa8b..6e6d035c 100644 --- a/tests/milo/columns.block.test.js +++ b/tests/milo/columns.block.test.js @@ -1,17 +1,22 @@ /* eslint-disable import/named */ import { expect, test } from '@playwright/test'; +import { WebUtil } from '../../libs/webutil.js'; import { features } from '../../features/milo/columns.block.spec.js'; import ColumnsBlock from '../../selectors/milo/columns.block.page.js'; let column; +let webUtil; test.describe('Milo Columns Block test suite', () => { test.beforeEach(async ({ page }) => { column = new ColumnsBlock(page); + webUtil = new WebUtil(page); }); + // Test 0 : Column default block test(`${features[0].name},${features[0].tags}`, async ({ page, baseURL }) => { console.info(`[Test Page]: ${baseURL}${features[0].path}`); + const { data } = features[0]; await test.step('step-1: Go to Columns block test page', async () => { await page.goto(`${baseURL}${features[0].path}`); @@ -20,13 +25,26 @@ test.describe('Milo Columns Block test suite', () => { }); await test.step('step-2: Verify Columns block content/specs', async () => { - const { data } = features[0]; - expect(await column.verifyColumns('columns', data)).toBeTruthy(); + // verify colums visibility, rows count, columns count and text content + await expect(await column.column).toBeVisible(); + + await expect(await column.rows).toHaveCount(data.rows); + await expect(await column.columns).toHaveCount(data.columns); + + await expect(await column.columns.nth(0)).toContainText(data.col0); + await expect(await column.columns.nth(1)).toContainText(data.col1); + await expect(await column.columns.nth(2)).toContainText(data.col2); + + // verify the css and attributes + expect(await webUtil.verifyCSS_(await column.rows.nth(0), column.cssProperties['.columns > .row'])).toBeTruthy(); + expect(await webUtil.verifyAttributes_(await column.column, column.attProperties.columns)).toBeTruthy(); }); }); + // Test 1 : Columns (contained) block test(`${features[1].name},${features[1].tags}`, async ({ page, baseURL }) => { console.info(`[Test Page]: ${baseURL}${features[1].path}`); + const { data } = features[1]; await test.step('step-1: Go to Columns block test page', async () => { await page.goto(`${baseURL}${features[1].path}`); @@ -35,13 +53,25 @@ test.describe('Milo Columns Block test suite', () => { }); await test.step('step-2: Verify Columns(contained) block content/specs', async () => { - const { data } = features[1]; - expect(await column.verifyColumns('columns(contained)', data)).toBeTruthy(); + // verify colums visibility, rows count, columns count and text content + await expect(await column.column).toBeVisible(); + + await expect(await column.rows).toHaveCount(data.rows); + await expect(await column.columns).toHaveCount(data.columns); + + await expect(await column.columns.nth(0)).toContainText(data.col0); + await expect(await column.columns.nth(1)).toContainText(data.col1); + + // verify the css and attributes + expect(await webUtil.verifyCSS_(await column.column, column.cssProperties['.columns.contained'])).toBeTruthy(); + expect(await webUtil.verifyAttributes_(await column.column, column.attProperties['columns-contained'])).toBeTruthy(); }); }); + // Test 2 : Columns (contained,middle) block test(`${features[2].name},${features[2].tags}`, async ({ page, baseURL }) => { console.info(`[Test Page]: ${baseURL}${features[2].path}`); + const { data } = features[2]; await test.step('step-1: Go to Columns block test page', async () => { await page.goto(`${baseURL}${features[2].path}`); @@ -50,13 +80,25 @@ test.describe('Milo Columns Block test suite', () => { }); await test.step('step-2: Verify Columns(contained,middle) block content/specs', async () => { - const { data } = features[2]; - expect(await column.verifyColumns('columns(contained,middle)', data)).toBeTruthy(); + // verify colums visibility, rows count, columns count and text content + await expect(await column.column).toBeVisible(); + + await expect(await column.rows).toHaveCount(data.rows); + await expect(await column.columns).toHaveCount(data.columns); + + await expect(await column.columns.nth(0)).toContainText(data.col0); + await expect(await column.columns.nth(1)).toContainText(data.col1); + + // verify the css and attributes + expect(await webUtil.verifyCSS_(await column.column, column.cssProperties['.columns.contained'])).toBeTruthy(); + expect(await webUtil.verifyAttributes_(await column.column, column.attProperties['columns-contained-middle'])).toBeTruthy(); }); }); + // Test 3 : Columns (table) block test(`${features[3].name},${features[3].tags}`, async ({ page, baseURL }) => { console.info(`[Test Page]: ${baseURL}${features[3].path}`); + const { data } = features[3]; await test.step('step-1: Go to Columns block test page', async () => { await page.goto(`${baseURL}${features[3].path}`); @@ -65,13 +107,29 @@ test.describe('Milo Columns Block test suite', () => { }); await test.step('step-2: Verify Columns(table) block content/specs', async () => { - const { data } = features[3]; - expect(await column.verifyColumns('columns(table)', data)).toBeTruthy(); + // verify colums visibility, rows count, columns count and text content + await expect(await column.column).toBeVisible(); + + await expect(await column.rows).toHaveCount(data.rows); + await expect(await column.columns).toHaveCount(data.columns); + + await expect(await column.columns.nth(0)).toContainText(data.col0); + await expect(await column.columns.nth(1)).toContainText(data.col1); + await expect(await column.columns.nth(2)).toContainText(data.col2); + await expect(await column.columns.nth(3)).toContainText(data.col3); + + // verify the css and attributes + expect(await webUtil.verifyCSS_(await column.rows.nth(0), column.cssProperties['.columns.table > .row:first-child'])).toBeTruthy(); + expect(await webUtil.verifyCSS_(await column.rows.nth(1), column.cssProperties['.columns.table > .row'])).toBeTruthy(); + + expect(await webUtil.verifyAttributes_(await column.column, column.attProperties['columns-table'])).toBeTruthy(); }); }); + // Test 4 : Columns (contained,table) block test(`${features[4].name},${features[4].tags}`, async ({ page, baseURL }) => { console.info(`[Test Page]: ${baseURL}${features[4].path}`); + const { data } = features[4]; await test.step('step-1: Go to Columns block test page', async () => { await page.goto(`${baseURL}${features[4].path}`); @@ -80,8 +138,22 @@ test.describe('Milo Columns Block test suite', () => { }); await test.step('step-2: Verify Columns(contained,table) block content/specs', async () => { - const { data } = features[4]; - expect(await column.verifyColumns('columns(contained,table)', data)).toBeTruthy(); + // verify colums visibility, rows count, columns count and text content + await expect(await column.column).toBeVisible(); + + await expect(await column.rows).toHaveCount(data.rows); + await expect(await column.columns).toHaveCount(data.columns); + + await expect(await column.columns.nth(0)).toContainText(data.col0); + await expect(await column.columns.nth(1)).toContainText(data.col1); + await expect(await column.columns.nth(2)).toContainText(data.col2); + await expect(await column.columns.nth(3)).toContainText(data.col3); + + // verify the css and attributes + expect(await webUtil.verifyCSS_(await column.rows.nth(0), column.cssProperties['.columns.table > .row:first-child'])).toBeTruthy(); + expect(await webUtil.verifyCSS_(await column.rows.nth(1), column.cssProperties['.columns.table > .row'])).toBeTruthy(); + + expect(await webUtil.verifyAttributes_(await column.column, column.attProperties['columns-contained-table'])).toBeTruthy(); }); }); }); diff --git a/tests/milo/howto.block.test.js b/tests/milo/howto.block.test.js index 3e04efb4..4bf36f0f 100644 --- a/tests/milo/howto.block.test.js +++ b/tests/milo/howto.block.test.js @@ -12,6 +12,7 @@ test.describe('Milo HowTo block test suite', () => { howTo = new HowToBlock(page); }); +// Test 0 : HowTo default block test(`${features[0].name},${features[0].tags}`, async ({ page, baseURL }) => { console.info(`[Test Page]: ${baseURL}${features[0].path}`); @@ -22,10 +23,16 @@ test.describe('Milo HowTo block test suite', () => { }); await test.step('step-2: Verify HowTo specs', async () => { - expect(await howTo.verifyHowTo('how-to', 4)).toBeTruthy(); + await expect(howTo.howTo).toBeVisible(); + await expect(await howTo.list).toHaveCount(4); + + expect(await webUtil.verifyCSS_(howTo.foreground, howTo.cssProperties['.how-to .foreground'])).toBeTruthy(); + expect(await webUtil.verifyCSS_(howTo.heading, howTo.cssProperties['body-m'])).toBeTruthy(); + expect(await webUtil.verifyCSS_(howTo.image, howTo.cssProperties['how-to-image'])).toBeTruthy(); }); }); +// Test 1 : how-to (large) block test(`${features[1].name},${features[1].tags}`, async ({ page, baseURL }) => { console.info(`[Test Page]: ${baseURL}${features[1].path}`); @@ -36,10 +43,16 @@ test.describe('Milo HowTo block test suite', () => { }); await test.step('step-2: Verify HowTo large specs', async () => { - expect(await howTo.verifyHowTo('how-to (large)', 4)).toBeTruthy(); + await expect(howTo.howToLarge).toBeVisible(); + await expect(await howTo.list).toHaveCount(4); + + expect(await webUtil.verifyCSS_(howTo.heading, howTo.cssProperties['body-m'])).toBeTruthy(); + expect(await webUtil.verifyCSS_(howTo.howToLarge, howTo.cssProperties['how-to-large-image'])).toBeTruthy(); + expect(await webUtil.verifyAttributes_(await howTo.largeImage, howTo.attProperties['how-to-large-image'])).toBeTruthy(); }); }); +// Test 2 : how-to (seo) block test(`${features[2].name},${features[2].tags}`, async ({ page, baseURL }) => { console.info(`[Test Page]: ${baseURL}${features[2].path}`); @@ -50,7 +63,11 @@ test.describe('Milo HowTo block test suite', () => { }); await test.step('step-2: Verify HowTo SEO specs', async () => { - expect(await howTo.verifyHowTo('how-to (seo)', 4)).toBeTruthy(); + await expect(howTo.howToSeo).toBeVisible(); + await expect(await howTo.list).toHaveCount(4); + + expect(await webUtil.verifyCSS_(howTo.heading, howTo.cssProperties['body-m'])).toBeTruthy(); + expect(await webUtil.verifyCSS_(howTo.howToSeo, howTo.cssProperties['how-to-seo'])).toBeTruthy(); }); }); }); diff --git a/tests/milo/htmlextn.feature.test.js b/tests/milo/htmlextn.feature.test.js index 9f641cac..1669d2e2 100644 --- a/tests/milo/htmlextn.feature.test.js +++ b/tests/milo/htmlextn.feature.test.js @@ -1,92 +1,48 @@ import { expect, test } from '@playwright/test'; -import { WebUtil } from '../../libs/webutil.js'; - -const parse = require('../../libs/parse.js'); -const htmlExtn = require('../../features/milo/htmlextn.spec.js'); -const selectors = require('../../selectors/milo/htmlextn.feature.page.js'); - -// Parse the feature file into something flat that can be tested separately -const { name, features } = parse(htmlExtn); - -let webUtil; - -test.describe(`${name} test suite`, () => { - test.beforeEach(async ({ page }) => { - webUtil = new WebUtil(page); +import { features } from '../../features/milo/htmlextn.spec.js' + +const envList = require('../../envs/envs.js'); + +test.describe('Milo Html Extension feature test suite', () => { + + // Test 0 : Html Extension validation for bacom + test(`${features[0].name},${features[0].tags}`, async ({ page }) => { + const paths = features[0].path; + const env = features[0].envs; + + await test.step('step-1: Go to test page urls and verify .html', async () => { + for (const path of paths) { + console.info('[Test Page]\n:', envList[env]+`${path}`); + const url = envList[env]+ path; + await page.goto(url); + + if (!page.url().match(/@blog/) && (page.url().match(/customer-success-stories/))) { + expect(page.url()).toContain('.html'); + } else { + await expect(page).toHaveURL(url); + } + } + }); }); - features.forEach((props) => { - test(props.title, async ({ page, browserName }) => { - test.skip(); - await page.goto(props.url); - await page.waitForLoadState('domcontentloaded'); - - if (!props.title.match(/@blog/) && (props.url.match(/customer-success-stories/))) { - expect(page.url()).toContain('.html'); - - /* Added scrolling for CaaS to load. - * Without it, test provides false count for validation checking. - * */ - await webUtil.scrollPage('down', 'slow'); - await webUtil.scrollPage('up', 'fast'); - - /* Check - * CaaS fragments urls are not converted by verifying the cards render and are visible - * Issue with CaaS cards loading when using WebKit/Chromium browsers - * outside of internal network. Firefox works though. - * */ - if (browserName === 'firefox') { - const caasCards = page.locator(selectors['@caas_cards']); - await expect(caasCards).toBeVisible(); + // Test 1 : Html Extension validation for blog + test(`${features[1].name},${features[1].tags}`, async ({ page }) => { + const paths = features[1].path; + const env = features[1].envs; + + await test.step('step-1: Go to test page urls and verify .html', async () => { + for (const path of paths) { + console.info('[Test Page]\n:', envList[env]+`${path}`); + const url = envList[env]+ path; + await page.goto(url); + + if (!page.url().match(/@blog/) && (page.url().match(/customer-success-stories/))) { + expect(page.url()).toContain('.html'); + } else { + await expect(page).toHaveURL(url); } - } else { - await expect(page).toHaveURL(props.url); - } - - /* Check all links for: - * They have .html on them within the same domain, subdomain. - * Domains without a '/', like www.adobe.com shouldn't have .html added. - * They don't have .html on urls ending in '/'. - * Links with .html already on them shouldn't have .html added again. - * */ - if (!props.title.match(/@blog/)) { - const hrefs = await page.evaluate(async () => { - await new Promise(resolve => setTimeout(resolve, 2000)); - return Array.from(document.links).map((item) => item.href); - }); - - hrefs.forEach(async (linkUrl) => { - if (!linkUrl.includes('/fragments/')) { - if (!linkUrl.match(/business.adobe.com\/blog|business.adobe.com\/.*\/blog/)) { - if (linkUrl.charAt(linkUrl.length - 1) === '/') { - expect(linkUrl).not.toContain('.html'); - } else { - if (linkUrl.includes('business.adobe.com') && !linkUrl.includes('/blog/')) { - expect(linkUrl).toContain('.html'); - } - if (linkUrl.match(/business.adobe.com\/blog\/|business.adobe.com\/.*\/blog\//)) { - expect(linkUrl).not.toContain('.html'); - } - if (linkUrl.includes('.html')) { - expect(linkUrl).not.toMatch(/.html.html/); - } - if (!linkUrl.includes('/')) { - expect(linkUrl).not.toContain('.html'); - } - } - } - } - }); - } - - if (props.title.match(/@blog/)) { - const link = page.getByRole('link', { name: selectors['@dif_subdomain_link'] }); - expect(await link.getAttribute('href')).not.toContain('.html'); - await link.click(); - await page.waitForLoadState(); - await expect(page).toHaveURL(/business.adobe.com\/blog/); - await page.getByRole('heading', { name: selectors['@dif_subdomain_heading'] }).first().waitFor(); - } + } }); }); + }); diff --git a/tests/milo/quote.block.test.js b/tests/milo/quote.block.test.js index 6e3425ee..bcecd2a5 100644 --- a/tests/milo/quote.block.test.js +++ b/tests/milo/quote.block.test.js @@ -1,16 +1,21 @@ import { expect, test } from '@playwright/test'; +import { WebUtil } from '../../libs/webutil.js'; import { features } from '../../features/milo/quote.block.spec.js'; import QuoteBlock from '../../selectors/milo/quote.block.page.js'; let quote; +let webUtil test.describe('Milo Quote Block test suite', () => { test.beforeEach(async ({ page }) => { + webUtil = new WebUtil(page); quote = new QuoteBlock(page); }); + // Test 0 : Quote default block test(`${features[0].name},${features[0].tags}`, async ({ page, baseURL }) => { console.info(`[Test Page]: ${baseURL}${features[0].path}`); + const { data } = features[0]; await test.step('step-1: Go to Quote block test page', async () => { await page.goto(`${baseURL}${features[0].path}`); @@ -19,13 +24,21 @@ test.describe('Milo Quote Block test suite', () => { }); await test.step('step-2: Verify Quote block content/specs', async () => { - const { data } = features[0]; - expect(await quote.verifyQuote('quote', data)).toBeTruthy(); + await expect(await quote.quoteImage).toBeVisible(); + await expect(await quote.quoteCopy).toContainText(data.quoteCopy); + await expect(await quote.quoteFigCaption).toContainText(data.figCaption); + await expect(await quote.quoteFigCaptionCite).toContainText(data.cite); + + expect(await webUtil.verifyAttributes_(await quote.quote, quote.attProperties.quote)).toBeTruthy(); + expect(await webUtil.verifyCSS_(await quote.quote, quote.cssProperties.quote)).toBeTruthy(); + }); }); + // Test 1 : quote (contained) test(`${features[1].name},${features[1].tags}`, async ({ page, baseURL }) => { console.info(`[Test Page]: ${baseURL}${features[1].path}`); + const { data } = features[1]; await test.step('step-1: Go to Quote block test page', async () => { await page.goto(`${baseURL}${features[1].path}`); @@ -34,13 +47,20 @@ test.describe('Milo Quote Block test suite', () => { }); await test.step('step-2: Verify Quote (contained) block content/specs', async () => { - const { data } = features[1]; - expect(await quote.verifyQuote('quote (contained)', data)).toBeTruthy(); + await expect(await quote.quoteImage).toBeVisible(); + await expect(await quote.quoteCopy).toContainText(data.quoteCopy); + await expect(await quote.quoteFigCaption).toContainText(data.figCaption); + await expect(await quote.quoteFigCaptionCite).toContainText(data.cite); + + expect(await webUtil.verifyAttributes_(await quote.quote, quote.attProperties['quote-contained'], )).toBeTruthy(); + expect(await webUtil.verifyCSS_(await quote.quote, quote.cssProperties['quote-contained'])).toBeTruthy(); }); }); + // Test 2 : Quote (inline,contained) test(`${features[2].name},${features[2].tags}`, async ({ page, baseURL }) => { console.info(`[Test Page]: ${baseURL}${features[2].path}`); + const { data } = features[2]; await test.step('step-1: Go to Quote (inline) block test page', async () => { await page.goto(`${baseURL}${features[2].path}`); @@ -49,13 +69,21 @@ test.describe('Milo Quote Block test suite', () => { }); await test.step('step-2: Verify Quote (inline) block content/specs', async () => { - const { data } = features[2]; - expect(await quote.verifyQuote('quote (inline)', data)).toBeTruthy(); + await expect(await quote.quoteImage).toBeVisible(); + await expect(await quote.quoteCopy).toContainText(data.quoteCopy); + await expect(await quote.quoteFigCaption).toContainText(data.figCaption); + await expect(await quote.quoteFigCaptionCite).toContainText(data.cite); + + expect(await webUtil.verifyAttributes_(await quote.quote, quote.attProperties['quote-inline'])).toBeTruthy(); + expect(await webUtil.verifyCSS_(await quote.quote, quote.cssProperties.quote)).toBeTruthy(); + expect(await webUtil.verifyCSS_(await quote.quoteImage, quote.cssProperties['quote-inline-figure'])).toBeTruthy(); }); }); + // Test 3 : quote (borders) test(`${features[3].name},${features[3].tags}`, async ({ page, baseURL }) => { console.info(`[MiloInfo] Checking page: ${baseURL}${features[3].path}`); + const { data } = features[3]; await test.step('step-1: Go to Quote (borders) block test page', async () => { await page.goto(`${baseURL}${features[3].path}`); @@ -64,13 +92,20 @@ test.describe('Milo Quote Block test suite', () => { }); await test.step('step-2: Verify Quote (borders) block content/specs', async () => { - const { data } = features[3]; - expect(await quote.verifyQuote('quote (borders)', data)).toBeTruthy(); + await expect(await quote.quoteImage).not.toBeVisible(); + await expect(await quote.quoteCopy).toContainText(data.quoteCopy); + await expect(await quote.quoteFigCaption).toContainText(data.figCaption); + await expect(await quote.quoteFigCaptionCite).toContainText(data.cite); + + expect(await webUtil.verifyAttributes_(await quote.quote, quote.attProperties['quote-borders'])).toBeTruthy(); + expect(await webUtil.verifyCSS_(await quote.quote, quote.cssProperties.quote)).toBeTruthy(); }); }); + // Test 4 : quote (align-right) test(`${features[4].name},${features[4].tags}`, async ({ page, baseURL }) => { console.info(`[Test Page]: ${baseURL}${features[4].path}`); + const { data } = features[4]; await test.step('step-1: Go to Quote (align-right) block test page', async () => { await page.goto(`${baseURL}${features[4].path}`); @@ -79,13 +114,20 @@ test.describe('Milo Quote Block test suite', () => { }); await test.step('step-2: Verify Quote (align-right) block content/specs', async () => { - const { data } = features[4]; - expect(await quote.verifyQuote('quote (align-right)', data)).toBeTruthy(); + await expect(await quote.quoteImage).toBeVisible(); + await expect(await quote.quoteCopy).toContainText(data.quoteCopy); + await expect(await quote.quoteFigCaption).toContainText(data.figCaption); + await expect(await quote.quoteFigCaptionCite).toContainText(data.cite); + + expect(await webUtil.verifyAttributes_(await quote.quote, quote.attProperties['quote-align-right'])).toBeTruthy(); + expect(await webUtil.verifyCSS_(await quote.quote, quote.cssProperties['quote-align-right'])).toBeTruthy(); }); }); + // Test 5 : quote (xl-spaced) test(`${features[5].name},${features[5].tags}`, async ({ page, baseURL }) => { console.info(`[Test Page]: ${baseURL}${features[5].path}`); + const { data } = features[5]; await test.step('step-1: Go to Quote (xl-spaced) block test page', async () => { await page.goto(`${baseURL}${features[5].path}`); @@ -94,8 +136,15 @@ test.describe('Milo Quote Block test suite', () => { }); await test.step('step-2: Verify Quote (xl-spaced) block content/specs', async () => { - const { data } = features[5]; - expect(await quote.verifyQuote('quote (xl-spaced)', data)).toBeTruthy(); + await expect(await quote.sectionDark).toBeVisible(); + await expect(await quote.quoteImage).not.toBeVisible(); + await expect(await quote.quoteCopy).toContainText(data.quoteCopy); + await expect(await quote.quoteFigCaption).toContainText(data.figCaption); + await expect(await quote.quoteFigCaptionCite).toContainText(data.cite); + + expect(await webUtil.verifyAttributes_(await quote.sectionDark, quote.attProperties['section-dark'])).toBeTruthy(); + expect(await webUtil.verifyAttributes_(await quote.quote, quote.attProperties['quote-xl-spacing'])).toBeTruthy(); + expect(await webUtil.verifyCSS_(await quote.quote, quote.cssProperties.quote)).toBeTruthy(); }); }); -}); +}); \ No newline at end of file diff --git a/tests/milo/zpattern.block.test.js b/tests/milo/zpattern.block.test.js index ca2b45d6..2930397e 100644 --- a/tests/milo/zpattern.block.test.js +++ b/tests/milo/zpattern.block.test.js @@ -1,16 +1,21 @@ import { expect, test } from '@playwright/test'; +import { WebUtil } from '../../libs/webutil.js'; import { features } from '../../features/milo/zpattern.block.spec.js'; import ZPatternBlock from '../../selectors/milo/zpattern.block.page.js'; +let webUtil; let zpattern; test.describe('Milo Z Pattern Block test suite', () => { test.beforeEach(async ({ page }) => { + webUtil = new WebUtil(page); zpattern = new ZPatternBlock(page); }); +// Test 0 : ZPattern default block test(`${features[0].name},${features[0].tags}`, async ({ page, baseURL }) => { console.info(`[Test Page]: ${baseURL}${features[0].path}`); + const { data } = features[0]; await test.step('step-1: Go to Z Pattern block test page', async () => { await page.goto(`${baseURL}${features[0].path}`); @@ -19,12 +24,37 @@ test.describe('Milo Z Pattern Block test suite', () => { }); await test.step('step-2: Verify Z Pattern block specs', async () => { - expect(await zpattern.verifyZPattern('z-pattern')).toBeTruthy(); - }); + await expect(await zpattern.zPatternHeader).toContainText(data.headingText); + await expect(await zpattern.zPatternPText).toContainText(data.introText); + await expect(await zpattern.mediaBlocks).toHaveCount(data.mediaBlockCount); + + const mediaBlocks = await zpattern.mediaBlocks.all(); + const mediaBlocksArray = await Promise.all(mediaBlocks.map(async (block) => block)); + + for (let i = 0; i < mediaBlocksArray.length; i++) { + const mediaBlock = mediaBlocksArray[i]; + await expect(await mediaBlock.locator('.detail-m')).toContainText(data.mediaBlocks[i]['detailText']); + await expect(await mediaBlock.locator('.heading-m')).toContainText(data.mediaBlocks[i]['h2Text']); + await expect(await mediaBlock.locator('.body-s').nth(0)).toContainText(data.mediaBlocks[i]['bodyText']); + await expect(await mediaBlock.locator('.blue')).toContainText(data.mediaBlocks[i]['blueButtonText']); + + const image = await mediaBlock.locator('.image img').nth(0); + const classAttribute = await mediaBlock.getAttribute('class'); + const hasReversedClass = classAttribute.includes('media-reversed'); + + if (hasReversedClass) { + expect(await webUtil.verifyAttributes_(mediaBlock, zpattern.attProperties['medium-media-reversed'])).toBeTruthy(); + } + expect(await webUtil.verifyAttributes_(image, zpattern.attProperties['media-image'])).toBeTruthy(); + } + + }); }); + // Test 1 :ZPattern (small) block test(`${features[1].name},${features[1].tags}`, async ({ page, baseURL }) => { console.info(`[Test Page]: ${baseURL}${features[1].path}`); + const { data } = features[1]; await test.step('step-1: Go to z-pattern (small) block test page', async () => { await page.goto(`${baseURL}${features[1].path}`); @@ -33,12 +63,37 @@ test.describe('Milo Z Pattern Block test suite', () => { }); await test.step('step-2: Verify z-pattern (small) block specs', async () => { - expect(await zpattern.verifyZPattern('z-pattern (small)')).toBeTruthy(); + await expect(await zpattern.zPatternHeader).toContainText(data.headingText); + await expect(await zpattern.zPatternPText).toContainText(data.introText); + await expect(await zpattern.mediaBlocks).toHaveCount(data.mediaBlockCount); + + const mediaBlocks = await zpattern.mediaBlocks.all(); + const mediaBlocksArray = await Promise.all(mediaBlocks.map(async (block) => block)); + + for (let i = 0; i < mediaBlocksArray.length; i++) { + const mediaBlock = mediaBlocksArray[i]; + await expect(await mediaBlock.locator('.detail-m')).toContainText(data.mediaBlocks[i]['detailText']); + await expect(await mediaBlock.locator('.heading-xs')).toContainText(data.mediaBlocks[i]['h2Text']); + await expect(await mediaBlock.locator('.body-s').nth(0)).toContainText(data.mediaBlocks[i]['bodyText']); + await expect(await mediaBlock.locator('.blue')).toContainText(data.mediaBlocks[i]['blueButtonText']); + + const image = await mediaBlock.locator('.image img').nth(0); + const classAttribute = await mediaBlock.getAttribute('class'); + const hasReversedClass = classAttribute.includes('media-reversed'); + + if (hasReversedClass) { + expect(await webUtil.verifyAttributes_(mediaBlock, zpattern.attProperties['small-media-reversed'])).toBeTruthy(); + } + expect(await webUtil.verifyAttributes_(image, zpattern.attProperties['media-image'])).toBeTruthy(); + } + }); }); + // Test 2 :Zpattern (large) block test(`${features[2].name},${features[2].tags}`, async ({ page, baseURL }) => { console.info(`[Test Page]: ${baseURL}${features[2].path}`); + const { data } = features[2]; await test.step('step-1: Go to z-pattern (large) block test page', async () => { await page.goto(`${baseURL}${features[2].path}`); @@ -47,12 +102,37 @@ test.describe('Milo Z Pattern Block test suite', () => { }); await test.step('step-2: Verify z-pattern (large) block specs', async () => { - expect(await zpattern.verifyZPattern('z-pattern (large)')).toBeTruthy(); - }); - }); + await expect(await zpattern.zPatternHeader).toContainText(data.headingText); + await expect(await zpattern.zPatternPText).toContainText(data.introText); + await expect(await zpattern.mediaBlocks).toHaveCount(data.mediaBlockCount); + + const mediaBlocks = await zpattern.mediaBlocks.all(); + const mediaBlocksArray = await Promise.all(mediaBlocks.map(async (block) => block)); + + for (let i = 0; i < mediaBlocksArray.length; i++) { + const mediaBlock = mediaBlocksArray[i]; + await expect(await mediaBlock.locator('.detail-l')).toContainText(data.mediaBlocks[i]['detailText']); + await expect(await mediaBlock.locator('.heading-xl')).toContainText(data.mediaBlocks[i]['h2Text']); + await expect(await mediaBlock.locator('.body-m').nth(0)).toContainText(data.mediaBlocks[i]['bodyText']); + await expect(await mediaBlock.locator('.blue')).toContainText(data.mediaBlocks[i]['blueButtonText']); + + const image = await mediaBlock.locator('.image img').nth(0); + const classAttribute = await mediaBlock.getAttribute('class'); + const hasReversedClass = classAttribute.includes('media-reversed'); + + if (hasReversedClass) { + expect(await webUtil.verifyAttributes_(mediaBlock, zpattern.attProperties['large-media-reversed'])).toBeTruthy(); + } + expect(await webUtil.verifyAttributes_(image, zpattern.attProperties['media-image'])).toBeTruthy(); + } + + }); + }); + // Test 3 :Zpattern (dark) block test(`${features[3].name},${features[3].tags}`, async ({ page, baseURL }) => { console.info(`[Test Page]: ${baseURL}${features[3].path}`); + const { data } = features[3]; await test.step('step-1: Go to z-pattern (large) block test page', async () => { await page.goto(`${baseURL}${features[3].path}`); @@ -61,7 +141,30 @@ test.describe('Milo Z Pattern Block test suite', () => { }); await test.step('step-2: Verify z-pattern (dark) block specs', async () => { - expect(await zpattern.verifyZPattern('z-pattern (dark)')).toBeTruthy(); + await expect(await zpattern.zPatternHeader).toContainText(data.headingText); + await expect(await zpattern.zPatternPText).toContainText(data.introText); + await expect(await zpattern.mediaBlocks).toHaveCount(data.mediaBlockCount); + + const mediaBlocks = await zpattern.mediaBlocks.all(); + const mediaBlocksArray = await Promise.all(mediaBlocks.map(async (block) => block)); + + for (let i = 0; i < mediaBlocksArray.length; i++) { + const mediaBlock = mediaBlocksArray[i]; + await expect(await mediaBlock.locator('.detail-m')).toContainText(data.mediaBlocks[i]['detailText']); + await expect(await mediaBlock.locator('.heading-m')).toContainText(data.mediaBlocks[i]['h2Text']); + await expect(await mediaBlock.locator('.body-s').nth(0)).toContainText(data.mediaBlocks[i]['bodyText']); + await expect(await mediaBlock.locator('.blue')).toContainText(data.mediaBlocks[i]['blueButtonText']); + + const image = await mediaBlock.locator('.image img').nth(0); + const classAttribute = await mediaBlock.getAttribute('class'); + const hasReversedClass = classAttribute.includes('media-reversed'); + + if (hasReversedClass) { + expect(await webUtil.verifyAttributes_(mediaBlock, zpattern.attProperties['dark-media-reversed'])).toBeTruthy(); + } + expect(await webUtil.verifyAttributes_(image, zpattern.attProperties['media-image'])).toBeTruthy(); + } }); }); }); + From be63bf9a462a7b3633da20f5ef21f75746e5fc53 Mon Sep 17 00:00:00 2001 From: Santoshkumar Nateekar Date: Sun, 7 Jan 2024 21:04:06 -0800 Subject: [PATCH 43/53] Milo Libs runs (#237) * Milo Libs runs * milo libs run test * add empty striting * update base reporter * update global setup * update manul yml --------- Co-authored-by: nateekar --- .github/workflows/manual.yml | 3 +- .github/workflows/milolib.yml | 54 +++++++++++ global.setup_1.js | 151 +++++++++++++++++++++++++++++ playwright.config.js | 2 +- tests/milo/accordion.block.test.js | 20 ++-- utils/reporters/base-reporter.js | 4 +- 6 files changed, 221 insertions(+), 13 deletions(-) create mode 100644 .github/workflows/milolib.yml create mode 100644 global.setup_1.js diff --git a/.github/workflows/manual.yml b/.github/workflows/manual.yml index 98b3e29c..6238f969 100644 --- a/.github/workflows/manual.yml +++ b/.github/workflows/manual.yml @@ -20,8 +20,7 @@ jobs: steps: - name: Check out repository uses: actions/checkout@v3 - - name: Set permissions - run: chmod +x ./path/to/run.sh + - name: Run Nala ${{ inputs.platform }} uses: ./ env: diff --git a/.github/workflows/milolib.yml b/.github/workflows/milolib.yml new file mode 100644 index 00000000..8e8d0392 --- /dev/null +++ b/.github/workflows/milolib.yml @@ -0,0 +1,54 @@ +name: Run Nala on Milo Libs Manually + +on: + workflow_dispatch: + inputs: + branch: + description: 'Provide the branch url' + required: false + type: string + milolibs: + description: 'Provide MiloLibs param' + required: false + type: string + tags: + description: 'Test scenario tags, if empty all tests will run. i.e., @marquee' + required: false + type: string + platform: + description: 'Platform to run tests on; select one, options: [ubuntu-latest, windows-latest, macos-latest]' + required: true + type: string + +jobs: + action: + name: Running tests + runs-on: ${{ inputs.platform }} + env: + WORKFLOW_NAME: 'Milo Libs Run' + MILO_LIBS_RUN: 'true' + + steps: + - name: Check out repository + uses: actions/checkout@v3 + + - name: Set environment variables + run: | + echo "PR_BRANCH_MILOLIBS_LIVE_URL=${{ github.event.inputs.branch }}" >> $GITHUB_ENV + echo "MILO_LIBS=${{ github.event.inputs.milolibs }}" >> $GITHUB_ENV + + - name: Run Nala ${{ inputs.platform }} + uses: ./ + env: + labels: ${{ inputs.tags }} + IMS_EMAIL: ${{ secrets.IMS_EMAIL }} + IMS_PASS: ${{ secrets.IMS_PASS }} + HLX_TKN: ${{ secrets.HLX_TKN }} + SLACK_WH: ${{ secrets.SLACK_WH }} + - name: Persist JSON Artifact + uses: actions/upload-artifact@v3 + if: always() + with: + name: nala-results + path: nala-results.json + retention-days: 30 diff --git a/global.setup_1.js b/global.setup_1.js new file mode 100644 index 00000000..c1faaf0f --- /dev/null +++ b/global.setup_1.js @@ -0,0 +1,151 @@ +import { exit } from 'process'; +const { execSync } = require('child_process'); +const { isBranchURLValid } = require('./libs/baseurl.js'); +const axios = require('axios'); + +const MAIN_BRANCH_LIVE_URL = 'https://main--milo--adobecom.hlx.live'; +const STAGE_BRANCH_URL = 'https://milo.stage.adobe.com'; +const LOCALHOST_URL = 'http://localhost:3000'; + +async function getGitHubPRBranchLiveUrl() { + // get the pr number + const prReference = process.env.GITHUB_REF; + const prNumber = prReference.split('/')[2]; + + // get the pr branch name + const branch = process.env.GITHUB_HEAD_REF; + const prBranch = branch.replace(/\//g, '-'); + + // get the org and repo + const repository = process.env.GITHUB_REPOSITORY; + const repoParts = repository.split('/'); + const toRepoOrg = repoParts[0]; + const toRepoName = repoParts[1]; + + // Get the org and repo from the environment variables + const prFromOrg = process.env.prOrg; + const prFromRepoName = process.env.prRepo; + + + let prBranchLiveUrl; + + if (toRepoName === 'nala' || toRepoName === 'janus') { + prBranchLiveUrl = MAIN_BRANCH_LIVE_URL; + } else { + prBranchLiveUrl = `https://${prBranch}--${prFromRepoName}--${prFromOrg}.hlx.live`; + } + + try { + if (await isBranchURLValid(prBranchLiveUrl)) { + process.env.PR_BRANCH_LIVE_URL = prBranchLiveUrl; + } + console.info('PR Repository : ', repository); + console.info('PR TO ORG : ', toRepoOrg); + console.info('PR TO REPO : ', toRepoName); + console.info('PR From ORG : ', prFromOrg); + console.info('PR From REPO : ', prFromRepoName); + console.info('PR Branch : ', branch); + console.info('PR Branch(U) : ', prBranch); + console.info('PR Number : ', prNumber); + console.info('PR From Branch live url : ', prBranchLiveUrl); + } catch (err) { + console.error(`Error => Error in setting PR Branch test URL : ${prBranchLiveUrl}`); + console.info(`Note: PR branch test url ${prBranchLiveUrl} is not valid, Exiting test execution.`); + process.exit(1); + } +} + +async function getGitHubMiloLibsBranchLiveUrl() { + const repository = process.env.GITHUB_REPOSITORY; + + let prBranchLiveUrl; + let miloLibs; + + prBranchLiveUrl = process.env.PR_BRANCH_MILOLIBS_LIVE_URL; + miloLibs = process.env.MILO_LIBS; + + try { + if (await isBranchURLValid(prBranchLiveUrl)) { + process.env.PR_BRANCH_LIVE_URL = prBranchLiveUrl; + } + console.info('PR Repository : ', repository); + console.info('PR Branch live url : ', prBranchLiveUrl); + console.info('Milo Libs : ', miloLibs); + } catch (err) { + console.error(`Error => Error in setting PR Branch test URL : ${prBranchLiveUrl}`); + console.info(`Note: PR branch test url ${prBranchLiveUrl} is not valid, Exiting test execution.`); + process.exit(1); + } +} + +async function getCircleCIBranchLiveUrl() { + const stageBranchLiveUrl = STAGE_BRANCH_URL; + + try { + if (await isBranchURLValid(stageBranchLiveUrl)) { + process.env.PR_BRANCH_LIVE_URL = stageBranchLiveUrl; + } + console.info('Stage Branch Live URL : ', stageBranchLiveUrl); + } catch (err) { + console.error('Error => Error in setting Stage Branch test URL : ', stageBranchLiveUrl); + console.info('Note: Stage branch test url is not valid, Exiting test execution.'); + process.exit(1); + } +} + +async function getLocalBranchLiveUrl() { + try { + const localGitRootDir = execSync('git rev-parse --show-toplevel', { encoding: 'utf-8' }).trim(); + + if (localGitRootDir) { + const gitRemoteOriginUrl = execSync('git config --get remote.origin.url', { cwd: localGitRootDir, encoding: 'utf-8' }).trim(); + const match = gitRemoteOriginUrl.match(/github\.com\/(.*?)\/(.*?)\.git/); + + if (match) { + const [localOrg, localRepo] = match.slice(1, 3); + const localBranch = execSync('git rev-parse --abbrev-ref HEAD', { cwd: localGitRootDir, encoding: 'utf-8' }).trim(); + let localTestLiveUrl; + + if (localRepo === 'nala' || localRepo === 'janus') { + localTestLiveUrl = MAIN_BRANCH_LIVE_URL; + } else { + localTestLiveUrl = LOCALHOST_URL; + } + + if (await isBranchURLValid(localTestLiveUrl)) { + process.env.LOCAL_TEST_LIVE_URL = localTestLiveUrl; + } + console.info('Git ORG : ', localOrg); + console.info('Git REPO : ', localRepo); + console.info('Local Branch : ', localBranch); + console.info('Local Test Live URL : ', process.env.LOCAL_TEST_LIVE_URL); + } + } + } catch (error) { + console.error(`Error => Error in setting local test URL : ${localTestLiveUrl}`); + console.info(`Note: Local or branch test url is not valid, Exiting test execution.`); + process.exit(1); + } +} + +async function globalSetup() { + console.info('----Executing Global setup---------'); + + if (process.env.GITHUB_ACTIONS === 'true') { + console.info('---- Running Tests in the GitHub environment ---------'); + + if (process.env.MILO_LIBS_RUN === 'true') { + await getGitHubMiloLibsBranchLiveUrl(); + } else { + await getGitHubPRBranchLiveUrl(); + } + } else if (process.env.CIRCLECI) { + console.info('---- Running Tests in the CircleCI environment ---------'); + await getCircleCIBranchLiveUrl(); + } else { + console.info('---- Running Tests in the Local environment ---------'); + await getLocalBranchLiveUrl(); + } +} + +export default globalSetup; diff --git a/playwright.config.js b/playwright.config.js index 0f656c10..6f89ad59 100644 --- a/playwright.config.js +++ b/playwright.config.js @@ -9,7 +9,7 @@ const envs = require('./envs/envs.js'); const config = { testDir: './tests/milo', outputDir: './test-results', - globalSetup: './global.setup.js', + globalSetup: './global.setup_1.js', /* Maximum time one test can run for. */ timeout: 30 * 1000, expect: { diff --git a/tests/milo/accordion.block.test.js b/tests/milo/accordion.block.test.js index efdda553..4c9e83e0 100644 --- a/tests/milo/accordion.block.test.js +++ b/tests/milo/accordion.block.test.js @@ -6,6 +6,8 @@ import AccordionBlock from '../../selectors/milo/accordion.block.page.js'; let webUtil; let accordion; let consoleErrors = []; + +const miloLibs = process.env.MILO_LIBS || ''; const knownConsoleErrors = ['Access-Control-Allow-Origin','Failed to load resource: net::ERR_FAILED']; test.describe('Milo Accordion Block test suite', () => { @@ -26,13 +28,13 @@ test.describe('Milo Accordion Block test suite', () => { // Test 0 : Accordion test(`${features[0].name},${features[0].tags}`, async ({ page, baseURL }) => { - console.info(`[Test Page]: ${baseURL}${features[0].path}`); + console.info(`[Test Page]: ${baseURL}${features[0].path}${miloLibs}`); const { data } = features[0]; await test.step('step-1: Go to Accordion block test page', async () => { - await page.goto(`${baseURL}${features[0].path}`); + await page.goto(`${baseURL}${features[0].path}${miloLibs}`); await page.waitForLoadState('domcontentloaded'); - await expect(page).toHaveURL(`${baseURL}${features[0].path}`); + await expect(page).toHaveURL(`${baseURL}${features[0].path}${miloLibs}`); }); await test.step('step-2: Verify Accrodion block content/specs', async () => { @@ -68,13 +70,13 @@ test.describe('Milo Accordion Block test suite', () => { // Test 1 : Accordion (seo) test(`${features[1].name},${features[1].tags}`, async ({ page, baseURL }) => { - console.info(`[Test Page]: ${baseURL}${features[1].path}`); + console.info(`[Test Page]: ${baseURL}${features[1].path}${miloLibs}`); const { data } = features[1]; await test.step('step-1: Go to Accordion block test page', async () => { - await page.goto(`${baseURL}${features[1].path}`); + await page.goto(`${baseURL}${features[1].path}${miloLibs}`); await page.waitForLoadState('domcontentloaded'); - await expect(page).toHaveURL(`${baseURL}${features[1].path}`); + await expect(page).toHaveURL(`${baseURL}${features[1].path}${miloLibs}`); }); await test.step('step-2: Verify Accrodion seo block specs', async () => { @@ -102,13 +104,13 @@ test.describe('Milo Accordion Block test suite', () => { // Test 2 : Accordion (quiet, max-width-12-desktop-large) test(`${features[2].name},${features[2].tags}`, async ({ page, baseURL }) => { - console.info(`[Test Page]: ${baseURL}${features[2].path}`); + console.info(`[Test Page]: ${baseURL}${features[2].path}${miloLibs}`); const { data } = features[2]; await test.step('step-1: Go to Accordion block test page', async () => { - await page.goto(`${baseURL}${features[2].path}`); + await page.goto(`${baseURL}${features[2].path}${miloLibs}`); await page.waitForLoadState('domcontentloaded'); - await expect(page).toHaveURL(`${baseURL}${features[2].path}`); + await expect(page).toHaveURL(`${baseURL}${features[2].path}${miloLibs}`); }); await test.step('step-2: Verify Accrodion block content/specs', async () => { diff --git a/utils/reporters/base-reporter.js b/utils/reporters/base-reporter.js index 4a14057a..25543840 100644 --- a/utils/reporters/base-reporter.js +++ b/utils/reporters/base-reporter.js @@ -93,7 +93,9 @@ class BaseReporter { const totalTests = this.results.length; const passPercentage = ((this.passedTests / totalTests) * 100).toFixed(2); const failPercentage = ((this.failedTests / totalTests) * 100).toFixed(2); - let envURL = process.env.PR_BRANCH_LIVE_URL || this.config.projects[0].use.baseURL; + const miloLibs = process.env.MILO_LIBS || ''; + const prBranchUrl = process.env.PR_BRANCH_LIVE_URL + miloLibs + let envURL = prBranchUrl || this.config.projects[0].use.baseURL; let exeEnv = 'Local Environment'; let runUrl = 'Local Environment'; let runName = 'Nala Local Run'; From 79451391c53bee1b550a650df178799560625acd Mon Sep 17 00:00:00 2001 From: kirupacommit <94790097+kirupacommit@users.noreply.github.com> Date: Mon, 8 Jan 2024 11:23:08 +0530 Subject: [PATCH 44/53] Helpx_Milo Components Script Fixes (#235) * Helpx_Milo Components Script Fixes * removed Base reporter from helpx * Added Base reporter to the helpx Config File * Added daily Run yml file and additional test cases on draft page * Draftpgae_MinorChanges on spec.js and test.js file * Helpx_Test cases Name changes and Added more test cases for Procedure component * Helpx Config variable changed to config * procedure_test case name changes --------- Co-authored-by: Kirupaagar R M --- .github/workflows/helpx.daily.yml | 46 +++++++ configs/helpx.config.js | 7 +- features/helpx/draft.spec.js | 20 ++- features/helpx/procedure.spec.js | 72 ++++++++++ selectors/helpx/beforeafter.page.js | 11 +- selectors/helpx/codeBlock.page.js | 7 +- selectors/helpx/draft.page.js | 30 ++++- selectors/helpx/procedure.page.js | 83 +++++++++++- tests/helpx/beforeafter.test.js | 41 +++--- tests/helpx/codeBlock.test.js | 89 +++++-------- tests/helpx/draft.test.js | 158 +++++++++++++--------- tests/helpx/procedure.test.js | 197 +++++++++++++++++++++++++--- 12 files changed, 586 insertions(+), 175 deletions(-) create mode 100644 .github/workflows/helpx.daily.yml diff --git a/.github/workflows/helpx.daily.yml b/.github/workflows/helpx.daily.yml new file mode 100644 index 00000000..5fe70061 --- /dev/null +++ b/.github/workflows/helpx.daily.yml @@ -0,0 +1,46 @@ +name: Helpx Nala Daily Run + +on: + schedule: + - cron: "30 15 * * *" + workflow_dispatch: + +jobs: + platform_matrix: + strategy: + fail-fast: false + matrix: + os: [ubuntu-latest, windows-latest, macos-latest] + name: Running tests + runs-on: ${{ matrix.os }} + env: + WORKFLOW_NAME: 'Helpx Nala Daily Run' + DAILY_RUN: 'true' + + steps: + - name: Check out repository + uses: actions/checkout@v3 + + - name: Set up Node.js + uses: actions/setup-node@v3 + with: + node-version: lts/* + + - name: Run Nala ${{ matrix.os }} + run: bash dailyrun.sh helpx + env: + IMS_EMAIL: ${{ secrets.IMS_EMAIL }} + IMS_PASS: ${{ secrets.IMS_PASS }} + HLX_TKN: ${{ secrets.HLX_TKN }} + SLACK_WH: ${{ secrets.SLACK_WH }} + + - name: Display workflow name + run: echo "The workflow name is $WORKFLOW_NAME" + + - name: Persist JSON Artifact + uses: actions/upload-artifact@v3 + if: always() + with: + name: nala-results + path: nala-results.json + retention-days: 30 diff --git a/configs/helpx.config.js b/configs/helpx.config.js index abc49c66..5aabb260 100644 --- a/configs/helpx.config.js +++ b/configs/helpx.config.js @@ -1,6 +1,5 @@ // @ts-check const { devices } = require('@playwright/test'); - const envs = require('../envs/envs.js'); /** @@ -39,7 +38,7 @@ const config = { : [ ['html', { outputFolder: 'test-html-results' }], ['list'], - ['./utils/reporters/base-reporter.js'], + ['../utils/reporters/base-reporter.js'] ], /* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */ use: { @@ -59,6 +58,10 @@ const config = { name: 'helpx-live-chrome', use: { ...devices['Desktop Chrome'], + channel: 'chrome', + launchOptions: { + args: ['--disable-web-security', '--disable-gpu'], + }, }, }, diff --git a/features/helpx/draft.spec.js b/features/helpx/draft.spec.js index f49a8d04..0b38e773 100644 --- a/features/helpx/draft.spec.js +++ b/features/helpx/draft.spec.js @@ -4,8 +4,26 @@ module.exports = { { tcid: '0', name: '@draft', - path: '/automation/blocks/Drafts/draft-test', + path: '/automation/blocks/Draft/draft-test.html', tags: '@draft @regression @helpx', }, + { + tcid: '1', + name: '@draftforBeforeAfter', + path: '/automation/blocks/Draft/draft-before-after.html', + tags: '@draft @regression @helpx', + }, + { + tcid: '2', + name: '@draftforCodeBlock', + path: '/automation/blocks/Draft/draft-code-block.html', + tags: '@draft @regression @helpx', + }, + { + tcid: '3', + name: '@draftforGeneric', + path: '/automation/blocks/Draft/draft-generic.html', + tags: '@draft @regression @helpx', + } ], }; diff --git a/features/helpx/procedure.spec.js b/features/helpx/procedure.spec.js index f1346432..a75df1f4 100644 --- a/features/helpx/procedure.spec.js +++ b/features/helpx/procedure.spec.js @@ -7,6 +7,78 @@ module.exports = { path: '/automation/blocks/procedure', tags: '@procedure @regression @helpx', }, + { + tcid: '1', + name: '@procedureComponentTitleValidation', + path: '/automation/blocks/procedure/procedure-step-component', + tags: '@procedure @regression @helpx', + }, + { + tcid: '2', + name: '@procedureComponentCaseSensitive', + path: '/automation/blocks/procedure/procedure-step-component', + tags: '@procedure @regression @helpx', + }, + { + tcid: '3', + name: '@procedureComponentWrongProcedureClassName', + path: '/automation/blocks/procedure/procedure-step-component', + tags: '@procedure @regression @helpx', + }, + { + tcid: '4', + name: '@procedureComponentDraftFunctionality', + path: '/automation/blocks/procedure/procedure-step-component', + tags: '@procedure @regression @helpx', + }, + { + tcid: '5', + name: '@procedureComponentTextProperties', + path: '/automation/blocks/procedure/procedure-step-component', + tags: '@procedure @regression @helpx', + }, + { + tcid: '6', + name: '@procedureComponentVideo', + path: '/automation/blocks/procedure/procedure-step-component', + tags: '@procedure @regression @helpx', + }, + { + tcid: '1', + name: '@procedureAndStepValidation', + path: '/automation/blocks/procedure/procedure-step-component', + tags: '@procedure @regression @helpx', + }, + { + tcid: '7', + name: '@procedureComponentFileDownload', + path: '/automation/blocks/procedure/procedure-step-component', + tags: '@procedure @regression @helpx', + }, + { + tcid: '8', + name: '@procedureComponentBeforeAfter', + path: '/automation/blocks/procedure/procedure-step-component', + tags: '@procedure @regression @helpx', + }, + { + tcid: '9', + name: '@procedureComponentCodeBlock', + path: '/automation/blocks/procedure/procedure-step-component', + tags: '@procedure @regression @helpx', + }, + { + tcid: '10', + name: '@procedureComponentAllComponents', + path: '/automation/blocks/procedure/procedure-step-component', + tags: '@procedure @regression @helpx', + }, + { + tcid: '11', + name: '@procedureComponentImageComponent', + path: '/automation/blocks/procedure/procedure-step-component', + tags: '@procedure @regression @helpx', + } ], }; \ No newline at end of file diff --git a/selectors/helpx/beforeafter.page.js b/selectors/helpx/beforeafter.page.js index 207b33e1..cadcd659 100644 --- a/selectors/helpx/beforeafter.page.js +++ b/selectors/helpx/beforeafter.page.js @@ -1,15 +1,10 @@ -import { expect } from '@playwright/test'; -import { WebUtil } from '../../libs/webutil.js'; - export default class BeforeAfter { constructor(page) { this.page = page; // BeforeAfter Selectors: - this.beforeAftr = page.locator('.beforeafter'); - this.beforeafterVertical = page.locator(selectors['@beforeafter-vertical']); - this.beforeafterVerticalmoved = page.locator( - selectors['@beforeafter-vertical-moved'] - ); + this.beforeAftr = page.locator("(//div[@class='before-after-slider vertical'])[1]"); + this.beforeafterVertical = page.locator(['@beforeafter-vertical']); + this.beforeafterVerticalmoved = page.locator(['@beforeafter-vertical-moved']); } } diff --git a/selectors/helpx/codeBlock.page.js b/selectors/helpx/codeBlock.page.js index 9f863e0d..1feb0d0a 100644 --- a/selectors/helpx/codeBlock.page.js +++ b/selectors/helpx/codeBlock.page.js @@ -1,12 +1,9 @@ -import { expect } from '@playwright/test'; -import { WebUtil } from '../../libs/webutil.js'; - export default class CodeBlock { constructor(page) { this.page = page; // CodeBlock Selectors: - this.codeA3 = page.locator('div.language-as3'); + this.codeA3 = page.locator("//div[@class='code language-as3']"); this.codeFusion = page.locator('div.language-coldfusion'); this.codeC = page.locator('div.language-c'); this.codeCss = page.locator('div.language-css'); @@ -17,6 +14,7 @@ export default class CodeBlock { this.codeSql = page.locator('div.language-sql'); this.codeXml = page.locator('div.language-xml'); this.codeMxml = page.locator('div.language-mxml'); + //language Selectors this.codeA3Num = page.locator('.language-as3.line-numbers'); this.codeFusionNum = page.locator('.language-coldfusion.line-numbers'); this.codeCNum = page.locator('.language-c.line-numbers'); @@ -28,6 +26,7 @@ export default class CodeBlock { this.codeSqlNum = page.locator('.language-sql.line-numbers'); this.codeXmlNum = page.locator('.language-xml.line-numbers'); this.codeMxmlNum = page.locator('.language-mxml.line-numbers'); + //Hidden Value Selectors this.codeHideDsktop = page.locator('.hidden-desktop'); this.codeHideTablet = page.locator('.hidden-tablet'); this.codeHideMobile = page.locator('.hidden-mobile'); diff --git a/selectors/helpx/draft.page.js b/selectors/helpx/draft.page.js index 2d8e70c2..b4911387 100644 --- a/selectors/helpx/draft.page.js +++ b/selectors/helpx/draft.page.js @@ -1,6 +1,3 @@ -import { expect } from '@playwright/test'; -import { WebUtil } from '../../libs/webutil.js'; - export default class Draft { constructor(page) { this.page = page; @@ -34,5 +31,32 @@ export default class Draft { 'codeBlock': { 'class': 'code language-as3 line-numbers draft' }, 'generic': { 'class': 'generic draft class1 class2' }, }; + + //draftPage for before after + this.codeAs3LineNumbersDraft = page.locator("//div[@class='code language-as3 line-numbers draft']"); + this.beforeAfterSlider = page.locator("//div[@class='before-after-slider draft']").first(); + this.horizontalBeforeAfterSlider = page.locator("//div[@class='before-after-slider horizontal draft']"); + this.beforeAfterSliderDraft = page.locator("//div[@class='before-after-slider draft'][2]"); + this.beforeAfterSliderDraftHorizontal = page.locator("//div[@class='before-after-slider draft horizontal']"); + this.as3CodeSnippet = page.locator("//div[@class='code language-as3 line-numbers draft']"); + + //draft page for codeblock + this.codeColdFusionDraft = page.locator("//div[@class='code language-coldfusion draft']"); + this.codeCPlusPlusDraft = page.locator("//div[@class='code language-c draft']"); + this.codeCSSLineNumbersDraft = page.locator("//div[@class='code language-css draft line-number']"); + this.codeJavaLineNumbersDraft = page.locator("//div[@class='code draft language-java line-numbers']"); + this.codeJavaScriptDraft = page.locator("//div[@class='code language-javascript draft']"); + this.codePHPDraft = page.locator("//div[@class='code draft language-php']"); + this.codeSQLDraft = page.locator("//div[@class='code language-sql darft']"); + this.codeXMLDraft = page.locator("//div[@class='code language-xml draft']"); + this.codeShellDraft = page.locator("//div[@class='code draft language-shell']"); + this.codePlainDraft = page.locator("//div[@class='code language-plain draft']"); + + //Draft Page for Generic + this.genericComponentsDraft = page.locator("//h1[@id='generic-components-draft']"); + this.genericImageDraft1 = page.locator("//div[@class='generic draft'][1]"); + this.genericImageDraft2 = page.locator("//div[@class='generic draft'][2]"); + this.genericTextDraft = page.locator("//div[@class='generic draft'][3]"); + } }; diff --git a/selectors/helpx/procedure.page.js b/selectors/helpx/procedure.page.js index 011e0a21..852e34e1 100644 --- a/selectors/helpx/procedure.page.js +++ b/selectors/helpx/procedure.page.js @@ -1,14 +1,87 @@ -import { expect } from '@playwright/test'; -import { WebUtil } from '../../libs/webutil.js'; - export default class Procedure { constructor(page) { this.page = page; // Procedure Selectors: this.procedure = page.locator('.procedure'); - this.procedureStep = page.locator('li[class=step]'); - this.procedureImage = page.locator('hli[class=step] img'); + this.procedureStep = page.locator("//li[contains(@class,'step')]"); + this.procedureImage = page.locator("//li[@class='step']//descendant::picture/img"); this.procedureTxtBold = page.locator('li[class=step] strong'); + + //Procedure and Step Component + //Title + this.procedureTitle = page.locator("//h1[@id='procedure-and-step-component']"); + //First procedure Component + this.procedureforb2 = page.locator("//div[contains(@daa-lh,'b2|procedure|nopzn|nopzn')]"); + this.procedureforb2Ol = page.locator("//div[@daa-lh='b2|procedure|nopzn|nopzn']/child::ol"); + this.procedureforb2liFirst = page.locator("//div[@daa-lh='b2|procedure|nopzn|nopzn']/child::ol/li[contains(@class,'step')][1]"); + + + //procedure is not case sensitive + const xpathWithDaaLh = "//div[contains(@daa-lh, 'b4|procedure|nopzn|nopzn')]/ol[@class='stepList']/li[@class='step']/div[contains(text(), 'PROCEDURE-Capital letter')]"; + this.procedurecapitalLetter = page.locator(xpathWithDaaLh).first(); + const xpathForSecondElement = "//div[contains(@daa-lh, 'b5|procedure|nopzn|nopzn')]/ol[@class='stepList']/li[@class='step']/div[contains(.,'PROCEDURE- Capital Letter - Bold -Italic')]"; + this.secondProcedureElement = page.locator(xpathForSecondElement).first(); + + const xpathForThirdElement = "//div[contains(@daa-lh, 'b6|procedure|nopzn|nopzn')]/ol[@class='stepList']/li[@class='step']//div[contains(.,'PROCEDURE-Capital Letter - Bold -Italic-Underline')]"; + this.thirdProcedureElement = page.locator(xpathForThirdElement).first(); + + //Incorrect Procedure Name + const xpathForFailedProcedure = "//div[contains(@class,'proedure')][contains(@data-failed,'true')][contains(@data-reason,'Failed loading proedure block.')]"; + this.failedProcedureElement = page.locator(xpathForFailedProcedure).first(); + + //verify Draft Procedure + const procedureDraft = "//li[contains(.,'Procedure Component with Draft Option')]/following-sibling::li[1][contains(.,'In Procedure Component, adding Text in the Step')]"; + this.draftProcedure = page.locator(procedureDraft).first(); + + //Text in procedure + this.textInProcedureComponent = page.locator("//div[contains(@daa-lh,'b11|procedure|nopzn|nopzn')]/ol/li[1]/div/p[contains(.,'Some copy-paste features that you can try out with this latest updated workflow are given here.')]"); + this.StrongtextInProcedureComponent = page.locator("//div[contains(@daa-lh,'b11|procedure|nopzn|nopzn')]/ol/li[2]/div/strong[contains(text(),'Continue')]"); + this.thirdStepLink = page.locator("//div[contains(@daa-lh,'b11|procedure|nopzn|nopzn')]/ol/li[3]/div/strong/a[contains(@href,'https://account.adobe.com/plans')]"); + this.iconinprocedureComponet = page.locator("//div[contains(@daa-lh,'b11|procedure|nopzn|nopzn')]/ol/li[6]/div/ol/li/span[contains(@class,'icon icon-objectives margin-left margin-right')]"); + this.notealertinprocedure = page.locator("//div[contains(@daa-lh,'b11|procedure|nopzn|nopzn')]/ol/li[6]/child::div/child::div[contains(@class,'note alert')]"); + this.noteiconinprocedure = page.locator("//div[contains(@daa-lh,'b11|procedure|nopzn|nopzn')]/ol/li[6]/child::div/child::div[contains(@class,'note alert')]/span[contains(@class,'note-icon')]"); + this.notecautionInprocedure = page.locator("//div[contains(@daa-lh,'b11|procedure|nopzn|nopzn')]/ol/li[8]/div/div[contains(@class,'note caution')]"); + this.notetipinProcedure = page.locator("//div[contains(@daa-lh,'b11|procedure|nopzn|nopzn')]/ol/li[8]/div/div[contains(@class,'note tip')]"); + + //Images in procedure + this.webpImageinProcedure = page.locator("//div[@class='procedure']/ol[@class='stepList']/li[@class='step'][1]//img[@title='attach_email_mfa']"); + this.pngImageInprocedure = page.locator("(//img[@loading='lazy'])[1]"); + const xpathLocator = "//div[contains(@daa-lh,'b13|procedure|nopzn|nopzn')]/ol/li[3]/div/p/em[contains(text(),'Great. I will process this for you now')]"; + this.textBeforeImageInProcedure = page.locator(xpathLocator); + this.imageafterTextInProcedure = page.locator(`${xpathLocator}/following::p[1]`); + this.urlBasedURLInProcedure = page.locator("//div[contains(@daa-lh,'b13|procedure|nopzn|nopzn')]/ol/li[4]/descendant::a[contains(@href,'/automation/blocks/procedure/')]"); + + + //Videos In Procedure + this.videoinprocedure = page.locator("//div[@class='procedure']//li[@class='step'][1]//video[@controls]"); + this.youtubevideoinprocedure = page.locator("//div[@class='procedure']//li[@class='step'][2]//iframe[contains(@src, 'youtube.com')]"); + + //Download Component + this.pdfforprocedure = page.locator("//div[@class='procedure']//li[@class='step'][1]//div[@class='download']//a[@class='download-button' and contains(@href, 'SKU%20search%20in%20Hendrix.pdf')]"); + this.xlsxforprocedure = page.locator("//div[@class='procedure']//li[@class='step'][2]//div[@class='download']//a[@class='download-button' and contains(@href, 'All%20Products_080213.xls')]"); + this.pptforprocedure = page.locator("//div[@class='procedure']//li[@class='step'][3]//div[@class='download']//a[@class='download-button' and contains(@href, 'cct_save_tagging-hendrix.pptx')]"); + + //BeforeAfter component + this.beforeafterfirst = page.locator("//input[@orient='vertical']"); + this.beforeaftersecond = page.locator("//div[@class='procedure']//li[@class='step'][2]//div[@class='before-after-slider hidden-tablet']"); + this.beforeafterthird = page.locator("//div[@class='procedure']//li[@class='step'][3]//div[@class='before-after-slider draft hidden-desktop hidden-mobile']"); + + //code block component + this.as3Inprocedure = page.locator("//div[@class='procedure']//li[@class='step'][1]//div[@class='code language-as3']").first(); + this.cplusplusInprocedure = page.locator("//div[@class='procedure']//li[@class='step'][2]//div[@class='code language-c++ line-numbers']").first(); + this.sqlInprocedure = page.locator("//div[@class='procedure']//li[@class='step'][3]//div[@class='code language-sql draft']").first(); + + //All components + this.codeBlock = page.locator("//div[@class='procedure']//li[@class='step'][1]//div[@class='code language-as3']").first(); + this.imageWithinProcedure = page.locator("//div[@class='procedure']//li[@class='step'][2]//h1[@id='image-within-procedure']/following-sibling::p/picture"); + this.ambientVideo = page.locator("//div[@class='procedure']//li[@class='step'][3]//p[contains(text(),'Ambient video')]").first(); + this.downloadSection = page.locator("//div[@class='procedure']//li[@class='step'][4]//div[@class='download']"); + this.miloVideo = page.locator("//div[@class='procedure']//li[@class='step'][5]//div[@class='milo-video']/iframe"); + this.beforeAfterSlider = page.locator("//div[@class='procedure']//li[@class='step'][6]//div[@class='before-after-slider hidden-mobile']"); + this.listWithLinks = page.locator("//div[@class='procedure']//li[@class='step'][7]//ul"); + this.noteUpdate = page.locator("//div[@class='procedure']//li[@class='step'][8]//div[@class='note alert']"); + this.noteAddReason = page.locator("//div[@class='procedure']//li[@class='step'][9]//div[@class='note caution']"); + } } diff --git a/tests/helpx/beforeafter.test.js b/tests/helpx/beforeafter.test.js index 65a9ffbf..5a934079 100644 --- a/tests/helpx/beforeafter.test.js +++ b/tests/helpx/beforeafter.test.js @@ -1,8 +1,10 @@ import { expect, test } from '@playwright/test'; -import { features } from '../../features/helpx/procedure.spec.js'; -import { BeforeAfter } from '../../selectors/helpx/procedure.page.js'; +import { features } from '../../features/helpx/beforeAfter.spec.js'; +import BeforeAfter from '../../selectors/helpx/beforeafter.page.js'; +import config from '../../configs/helpx.config.js'; let beforeAftr; +let page; test.beforeAll(async ({ browser }) => { if (process.env.HLX_TKN !== undefined && process.env.HLX_TKN !== '') { @@ -19,28 +21,29 @@ test.beforeAll(async ({ browser }) => { const context = await browser.newContext(); // Set the authorization token in the header await context.setExtraHTTPHeaders({ authorization: `token ${authToken}` }); - const page = await context.newPage(); + page = await context.newPage(); beforeAftr = new BeforeAfter(page); - await page.goto(`${baseURL}${features[0].path}`); - await page.waitForLoadState('networkidle'); + }); -test.describe('BeforeAfter sanity test suite', () => { - // Procedure Sanity Checks: - test(`${features[0].name}, ${features[0].tags}`, async ({ - page, - baseURL, - }) => { - console.info(`[Test Page]: ${baseURL}${features[0].path}`); - await test.step('Navigate to BeforeAfter page', async () => { - await expect(page).toHaveURL(`${baseURL}${features[0].path}`); + +test.describe('BeforeAfter Sanity test suite', () => { + + // Before After Sanity Checks: + test(`${features[0].name}, ${features[0].tags}`, async ({ baseURL }) => { + const BeforeAfterTag = features[0].path; + await page.goto(`${config.use?.baseURL}${BeforeAfterTag}`); + await page.waitForLoadState('networkidle'); + console.log(`[Test Page]: ${baseURL}${BeforeAfterTag}`); + //I verify url of the page + await test.step('Navigate to beforeAfter page', async () => { + await expect(page).toHaveURL(`${baseURL}${BeforeAfterTag}.html`); }); - // Check beforeAfter - await expect(beforeAftr.beforeafterVertical).toBeVisible(); - // Check beforeAfter after vertical movement - beforeafterVertical.scrollTop -= 40; - await expect(beforeAftr.beforeafterVerticalmoved).toBeVisible(); + await test.step('Check Before After page content', async () => { + // Check Before After Page component is visible + await expect(beforeAftr.beforeAftr).toBeVisible(); + }); }); }); diff --git a/tests/helpx/codeBlock.test.js b/tests/helpx/codeBlock.test.js index 1e29adac..3facc7c1 100644 --- a/tests/helpx/codeBlock.test.js +++ b/tests/helpx/codeBlock.test.js @@ -1,8 +1,14 @@ import { expect, test } from '@playwright/test'; import { features } from '../../features/helpx/codeBlock.spec.js'; -import { CodeBlock } from '../../selectors/helpx/codeBlock.page.js'; +import CodeBlock from '../../selectors/helpx/codeBlock.page.js'; +import config from '../../configs/helpx.config.js'; +import { WebUtil } from '../../libs/webutil.js'; + let codeBlk; +let page; +let codeblocktag = features[0].path; + test.beforeAll(async ({ browser }) => { if (process.env.HLX_TKN !== undefined && process.env.HLX_TKN !== '') { @@ -19,38 +25,49 @@ test.beforeAll(async ({ browser }) => { const context = await browser.newContext(); // Set the authorization token in the header await context.setExtraHTTPHeaders({ authorization: `token ${authToken}` }); - const page = await context.newPage(); + page = await context.newPage(); codeBlk = new CodeBlock(page); - await page.goto(`${baseURL}${features[0].path}`); - await page.waitForLoadState('networkidle'); }); test.describe('CodeBlock sanity test suite', () => { // CodeBlock Sanity Checks: - test(`${features[0].name}, ${features[0].tags}`, async ({ - page, - baseURL, - }) => { - console.info(`[Test Page]: ${baseURL}${features[0].path}`); + test(`${features[0].name}, ${features[0].tags}`, async ({}) => { + //Go to CodeBlock Page + await page.goto(`${config.use?.baseURL}${codeblocktag}`); + await page.waitForLoadState('networkidle'); + console.info(`[Test Page]: ${config.use?.baseURL}${codeblocktag}`); + + //verify its navigating to code block page only await test.step('Navigate to CodeBlock page', async () => { - await expect(page).toHaveURL(`${baseURL}${features[0].path}`); + await expect(page).toHaveURL(`${config.use?.baseURL}${codeblocktag}.html`); }); // Check for different codeBlock formats present - await expect(codeBlk.codeBlockA3).toBeVisible(); + await expect(codeBlk.codeA3).toBeVisible(); await expect(codeBlk.codeFusion).toBeVisible(); await expect(codeBlk.codeC).toBeVisible(); await expect(codeBlk.codeCss).toBeVisible(); await expect(codeBlk.codeJava).toBeVisible(); - await expect(codeBlk.codeJS).toBeVisible(); - await expect(codeBlk.codePhp).toBeVisible(); + await expect(codeBlk.codeJS).toHaveCount(4); + await expect(codeBlk.codePhp).toHaveCount(5); await expect(codeBlk.codePlain).toBeVisible(); - await expect(codeBlk.codeSql).toBeVisible(); - await expect(codeBlk.codeXml).toBeVisible(); + await expect(codeBlk.codeSql).toHaveCount(3); + await expect(codeBlk.codeXml).toHaveCount(2); await expect(codeBlk.codeMxml).toBeVisible(); - // Check different InLineNumber codeBlock formats present - await expect(codeBlk.codeBlockA3Num).toBeVisible(); + //verify Code block css Properties + expect(await WebUtil.verifyCSS(await codeBlk.codeHideDsktop.first(), codeBlk.cssProperties['codeHideDsktop'])).toBeTruthy(); + expect(await WebUtil.verifyCSS(await codeBlk.codeHideTablet.first(), codeBlk.cssProperties['codeHideTablet'])).toBeTruthy(); + expect(await WebUtil.verifyCSS(await codeBlk.codeHideMobile.first(), codeBlk.cssProperties['codeHideMobile'])).toBeTruthy(); + + //Verify code Block Attribute Properties + expect(await WebUtil.verifyAttributes(await codeBlk.codeHideDsktop.first(), codeBlk.attProperties['codeHideDsktop'])).toBeTruthy(); + expect(await WebUtil.verifyAttributes(await codeBlk.codeHideTablet.first(), codeBlk.attProperties['codeHideTablet'])).toBeTruthy(); + expect(await WebUtil.verifyAttributes(await codeBlk.codeHideMobile.first(), codeBlk.attProperties['codeHideMobile'])).toBeTruthy(); + + + //Check different InLineNumber codeBlock formats present + await expect(codeBlk.codeA3Num).toBeVisible(); await expect(codeBlk.codeFusionNum).toBeVisible(); await expect(codeBlk.codeCNum).toBeVisible(); await expect(codeBlk.codeCssNum).toBeVisible(); @@ -61,43 +78,5 @@ test.describe('CodeBlock sanity test suite', () => { await expect(codeBlk.codeSqlNum).toBeVisible(); await expect(codeBlk.codeXmlNum).toBeVisible(); await expect(codeBlk.codeMxmlNum).toBeVisible(); - - expect( - await WebUtil.verifyCSS( - await this.codeHideDsktop, - this.cssProperties['codeHideDsktop'] - ) - ).toBeTruthy(); - expect( - await WebUtil.verifyCSS( - await this.codeHideTablet, - this.cssProperties['codeHideTablet'] - ) - ).toBeTruthy(); - expect( - await WebUtil.verifyCSS( - await this.codeHideMobile, - this.cssProperties['codeHideMobile'] - ) - ).toBeTruthy(); - - expect( - await WebUtil.verifyAttributes( - await this.codeHideDsktop, - this.attProperties['codeHideDsktop'] - ) - ).toBeTruthy(); - expect( - await WebUtil.verifyAttributes( - await this.codeHideTablet, - this.attProperties['codeHideTablet'] - ) - ).toBeTruthy(); - expect( - await WebUtil.verifyAttributes( - await this.codeHideMobile, - this.attProperties['codeHideMobile'] - ) - ).toBeTruthy(); }); }); diff --git a/tests/helpx/draft.test.js b/tests/helpx/draft.test.js index bd8c61d1..d398c742 100644 --- a/tests/helpx/draft.test.js +++ b/tests/helpx/draft.test.js @@ -1,8 +1,15 @@ import { expect, test } from '@playwright/test'; import { features } from '../../features/helpx/draft.spec.js'; -import { Draft } from '../../selectors/helpx/draft.page.js'; +import Draft from '../../selectors/helpx/draft.page.js'; +import config from '../../configs/helpx.config.js'; +import { WebUtil } from '../../libs/webutil.js'; + let draft; +let page; +let draftTag= features[0].path; +let cssProps; +const helpxbaseURL = config.use?.baseURL; test.beforeAll(async ({ browser }) => { if (process.env.HLX_TKN !== undefined && process.env.HLX_TKN !== '') { @@ -19,80 +26,109 @@ test.beforeAll(async ({ browser }) => { const context = await browser.newContext(); // Set the authorization token in the header await context.setExtraHTTPHeaders({ authorization: `token ${authToken}` }); - const page = await context.newPage(); + page = await context.newPage(); draft = new Draft(page); - await page.goto(`${baseURL}${features[0].path}`); - await page.waitForLoadState('networkidle'); + cssProps = new WebUtil(page); + }); test.describe('Draft sanity test suite', () => { // Draft Sanity Checks: - test(`${features[0].name}, ${features[0].tags}`, async ({ - page, - baseURL, - }) => { - console.info(`[Test Page]: ${baseURL}${features[0].path}`); + test(`${features[0].name}, ${features[0].tags}`, async ({baseURL}) => { + await page.goto(`${helpxbaseURL}${draftTag}`); + await page.waitForLoadState('networkidle'); + console.log(`[Test Page]: ${baseURL}${draftTag}`); await test.step('Navigate to Draft page', async () => { - await expect(page).toHaveURL(`${baseURL}${features[0].path}`); + await expect(page).toHaveURL(`${baseURL}${draftTag}`); }); // Check procedure present - await expect(draft.procedure).toBeVisible(); + await expect(draft.procedure).not.toBeVisible(); // Check beforeAftr present - await expect(draft.beforeAftr).toBeVisible(); + await expect(draft.beforeAftr).not.toBeVisible(); // Check codeBlock present - await expect(draft.codeBlock).toBeVisible(); + await expect(draft.codeBlock).not.toBeVisible(); // Check generic present - await expect(draft.generic).toBeVisible(); - - expect( - await WebUtil.verifyCSS( - await this.procedure, - this.cssProperties['procedure'] - ) - ).toBeTruthy(); - expect( - await WebUtil.verifyCSS( - await this.beforeAftr, - this.cssProperties['beforeAftr'] - ) - ).toBeTruthy(); - expect( - await WebUtil.verifyCSS( - await this.codeBlock, - this.cssProperties['codeBlock'] - ) - ).toBeTruthy(); - expect( - await WebUtil.verifyCSS(await this.generic, this.cssProperties['generic']) - ).toBeTruthy(); - - expect( - await WebUtil.verifyAttributes( - await this.procedure, - this.attProperties['procedure'] - ) - ).toBeTruthy(); - expect( - await WebUtil.verifyAttributes( - await this.beforeAftr, - this.attProperties['beforeAftr'] - ) - ).toBeTruthy(); - expect( - await WebUtil.verifyAttributes( - await this.codeBlock, - this.attProperties['codeBlock'] - ) - ).toBeTruthy(); - expect( - await WebUtil.verifyAttributes( - await this.generic, - this.attProperties['generic'] - ) - ).toBeTruthy(); + await expect(draft.generic).not.toBeVisible(); + + //verify CSS property of a Draft page + expect(await cssProps.verifyCSS_(await draft.procedure, draft.cssProperties['procedure'])).toBeTruthy(); + expect(await cssProps.verifyCSS_(await draft.beforeAftr, draft.cssProperties['beforeAftr'])).toBeTruthy(); + expect(await cssProps.verifyCSS_(await draft.codeBlock, draft.cssProperties['codeBlock'])).toBeTruthy(); + expect(await cssProps.verifyCSS_(await draft.generic, draft.cssProperties['generic'])).toBeTruthy(); + + //Verify Attribute of a Draft Page + expect(await cssProps.verifyAttributes_(await draft.procedure, draft.attProperties['procedure'])).toBeTruthy(); + expect(await cssProps.verifyAttributes_(await draft.beforeAftr, draft.attProperties['beforeAftr'])).toBeTruthy(); + expect(await cssProps.verifyAttributes_(await draft.codeBlock, draft.attProperties['codeBlock'])).toBeTruthy(); + expect(await cssProps.verifyAttributes_(await draft.generic, draft.attProperties['generic'])).toBeTruthy(); + + }); +}); + + +test.describe('Draft on Before After Component',()=>{ + + + test(`${features[1].name}, ${features[1].tags}`, async () => { + const BeforeAfterurl = `${helpxbaseURL}${features[1].path}`; + await page.goto(BeforeAfterurl); + await page.waitForLoadState('networkidle'); + await console.log("BeforeAfterurl: "+BeforeAfterurl); + + //verify components are not visible + await expect(draft.codeAs3LineNumbersDraft).not.toBeVisible(); + await expect(draft.beforeAfterSlider).not.toBeVisible(); + await expect(draft.horizontalBeforeAfterSlider).not.toBeVisible(); + await expect(draft.beforeAfterSliderDraft).not.toBeVisible(); + await expect(draft.beforeAfterSliderDraftHorizontal).not.toBeVisible(); + await expect(draft.as3CodeSnippet).not.toBeVisible(); + + + }); +}); + +test.describe('Draft on Code Block Component',()=>{ + + + test(`${features[2].name}, ${features[2].tags}`, async () => { + const codeblockdrafturl = `${helpxbaseURL}${features[2].path}`; + await page.goto(codeblockdrafturl); + await page.waitForLoadState('networkidle'); + await console.log("CodeBlockDrafturl: "+codeblockdrafturl); + + //verify components are not visible + await expect(draft.codeAs3LineNumbersDraft).not.toBeVisible(); + await expect(draft.codeColdFusionDraft).not.toBeVisible(); + await expect(draft.codeCPlusPlusDraft).not.toBeVisible(); + await expect(draft.codeCSSLineNumbersDraft).not.toBeVisible(); + await expect(draft.codeJavaLineNumbersDraft).not.toBeVisible(); + await expect(draft.codeJavaScriptDraft).not.toBeVisible(); + await expect(draft.codePHPDraft).not.toBeVisible(); + await expect(draft.codeSQLDraft).toBeVisible(); + await expect(draft.codeXMLDraft).not.toBeVisible(); + await expect(draft.codeShellDraft).not.toBeVisible(); + await expect(draft.codePlainDraft).not.toBeVisible(); + }); +}); + +test.describe('Draft Component on Generic',()=>{ + + + test(`${features[3].name}, ${features[3].tags}`, async () => { + const genericDraftURl = `${helpxbaseURL}${features[3].path}`; + await page.goto(genericDraftURl); + await page.waitForLoadState('networkidle'); + await console.log("genericDraftURl: "+genericDraftURl); + + await expect(draft.genericComponentsDraft).toBeVisible(); + await expect(draft.genericImageDraft1).not.toBeVisible(); + await expect(draft.genericImageDraft2).not.toBeVisible(); + await expect(draft.genericTextDraft).not.toBeVisible(); + }); }); + diff --git a/tests/helpx/procedure.test.js b/tests/helpx/procedure.test.js index cb96ceee..106c628f 100644 --- a/tests/helpx/procedure.test.js +++ b/tests/helpx/procedure.test.js @@ -1,10 +1,13 @@ import { expect, test } from '@playwright/test'; import { features } from '../../features/helpx/procedure.spec.js'; -import { Procedure } from '../../selectors/helpx/procedure.page.js'; +import Procedure from '../../selectors/helpx/procedure.page.js'; +import helpxconfig from '../../configs/helpx.config.js'; let procedure; +let page; test.beforeAll(async ({ browser }) => { + //Verify TOKEN is set at environment variables if (process.env.HLX_TKN !== undefined && process.env.HLX_TKN !== '') { // The environment variable is set and has a non-blank value console.log('Environment variable is set and not blank'); @@ -19,35 +22,195 @@ test.beforeAll(async ({ browser }) => { const context = await browser.newContext(); // Set the authorization token in the header await context.setExtraHTTPHeaders({ authorization: `token ${authToken}` }); - const page = await context.newPage(); - procedure = new Procedure(page); - await page.goto(`${baseURL}${features[0].path}`); - await page.waitForLoadState('networkidle'); + //create a new page + page = await context.newPage(); + procedure = new Procedure(page); //Attached Xpaths procedure page to playwright page }); test.describe('Procedure Sanity test suite', () => { - // Procedure Sanity Checks: - test(`${features[0].name}, ${features[0].tags}`, async ({ - page, - baseURL, - }) => { - console.info(`[Test Page]: ${baseURL}${features[0].path}`); + //Procedure Sanity Checks: + test(`${features[0].name}, ${features[0].tags}`, async ({ baseURL }) => { + let procedureTag = features[0].path; + await page.goto(`${helpxconfig.use?.baseURL}${procedureTag}`); + await page.waitForLoadState('networkidle'); + console.log(`[Test Page]: ${baseURL}${procedureTag}`); + //I verify url of the page await test.step('Navigate to Procedure page', async () => { - await expect(page).toHaveURL(`${baseURL}${features[0].path}`); + await expect(page).toHaveURL(`${baseURL}${procedureTag}.html`); }); + //I verify procedure component is present with step,image,TextBold await test.step('Check Procedure page content', async () => { // Check procedure: await expect(procedure.procedure).toBeVisible(); - - // Check procedure step: - await expect(procedure.procedureStep).toBeVisible(); - + //check Step count + await expect(procedure.procedureStep).toHaveCount(3); // Check image in procedure: await expect(procedure.procedureImage).toBeVisible(); - // Check bold text in procedure: await expect(procedure.procedureTxtBold).toBeVisible(); }); }); + }); + +async function launchprocedurepage(){ + //All Components page + let procedureTag = features[1].path; + await page.goto(`${helpxconfig.use?.baseURL}${procedureTag}`); + await page.waitForLoadState('networkidle'); + console.log(`[All component procedure Page]: ${helpxconfig.use?.baseURL}${procedureTag}`); +} + + +test.describe("All Components in Procedure component",()=>{ + + //Procedure and Step Component + test(`${features[1].name}, ${features[1].tags}`, async () => { + await launchprocedurepage(); + const procedureTitle = procedure.procedureTitle; + //verify Title Text and CSS values + await expect(procedureTitle).toBeVisible(); + await expect(procedureTitle).toHaveCSS('max-width', '1050px'); + await expect(procedureTitle).toHaveCSS('line-height', '41.4px'); + await expect(procedureTitle).toHaveCSS('font-size', '36px'); + await expect(procedureTitle).toHaveCSS('font-weight', '500'); + await expect(procedureTitle).toHaveCSS('text-align', 'left'); + await expect(procedureTitle).toHaveCSS('word-break', 'break-word'); + await expect(procedureTitle).toHaveCSS('padding', '0px 40px'); + await expect(procedureTitle).toHaveCSS('min-height', '72px'); + await expect(procedureTitle).toHaveCSS('display', 'flex'); + await expect(procedureTitle).toHaveCSS('flex-direction', 'column'); + await expect(procedureTitle).toHaveCSS('justify-content', 'center'); + await expect(procedureTitle).toHaveText("Procedure and Step Component") + }); + + test(`${features[2].name}, ${features[2].tags}`, async()=>{ + await launchprocedurepage(); + await expect(procedure.procedurecapitalLetter).toBeVisible(); + await expect(procedure.secondProcedureElement).toBeVisible(); + await expect(procedure.thirdProcedureElement).toBeVisible(); + }) + + test(`${features[3].name}, ${features[3].tags}`, async()=>{ + await launchprocedurepage(); + await expect(procedure.failedProcedureElement).toBeVisible(); + }) + + test(`${features[4].name}, ${features[4].tags}`, async () => { + await launchprocedurepage(); + await expect(procedure.draftProcedure).toBeVisible(); + }); + + test(`${features[5].name}, ${features[5].tags}`, async()=>{ + await launchprocedurepage(); + // Verifying visibility for each element + await expect(procedure.textInProcedureComponent).toBeVisible(); + await expect(procedure.StrongtextInProcedureComponent).toBeVisible(); + await expect(procedure.thirdStepLink).toBeVisible(); + await expect(procedure.iconinprocedureComponet).toBeVisible(); + await expect(procedure.notealertinprocedure).toBeVisible(); + await expect(procedure.noteiconinprocedure).toBeVisible(); + await expect(procedure.notecautionInprocedure).toBeVisible(); + await expect(procedure.notetipinProcedure).toBeVisible(); + }) + + + test(`${features[6].name}, ${features[6].tags}`, async()=>{ + await launchprocedurepage(); + const scrollToHeight = 4500; + + await page.evaluate((scrollToHeight) => { + window.scrollTo(0, scrollToHeight); + }, scrollToHeight); + + await page.waitForTimeout(1000); + await expect(procedure.videoinprocedure).toBeVisible(); + await expect(procedure.youtubevideoinprocedure).toBeVisible(); + }) + + test(`${features[7].name}, ${features[7].tags}`, async()=>{ + await launchprocedurepage(); + const scrollToHeight = 4700; + + await page.evaluate((scrollToHeight) => { + window.scrollTo(0, scrollToHeight); + }, scrollToHeight); + await page.waitForTimeout(1000); + + await expect(procedure.pdfforprocedure).toBeVisible(); + await expect(procedure.xlsxforprocedure).toBeVisible(); + await expect(procedure.pptforprocedure).toBeVisible(); + + }) + + test(`${features[8].name}, ${features[8].tags}`,async()=>{ + await launchprocedurepage(); + const scrollToHeight = 5000; + + await page.evaluate((scrollToHeight) => { + window.scrollTo(0, scrollToHeight); + }, scrollToHeight); + + await page.waitForTimeout(1000); + await expect(procedure.beforeafterfirst).toBeVisible(); + await expect(procedure.beforeaftersecond).toBeVisible(); + + + }) + + + test(`${features[9].name}, ${features[9].tags}`,async()=>{ + await launchprocedurepage(); + const scrollToHeight = 6000; + + await page.evaluate((scrollToHeight) => { + window.scrollTo(0, scrollToHeight); + }, scrollToHeight); + + await page.waitForTimeout(1000); + await expect(procedure.as3Inprocedure).toBeVisible(); + await expect(procedure.cplusplusInprocedure).toBeVisible(); + expect(procedure.sqlInprocedure).toBe.length==2; + + }) + + + test(`${features[10].name}, ${features[10].tags}`,async()=>{ + await launchprocedurepage(); + const scrollToHeight = 7500; + + await page.evaluate((scrollToHeight) => { + window.scrollTo(0, scrollToHeight); + }, scrollToHeight); + + await page.waitForTimeout(5000); + await expect(procedure.codeBlock).toBeVisible(); + await expect(procedure.imageWithinProcedure).toBeVisible(); + await expect(procedure.ambientVideo).toBeVisible(); + await expect(procedure.downloadSection).toBeVisible(); + await expect(procedure.miloVideo).toBeVisible(); + await expect(procedure.beforeAfterSlider).toBeVisible(); + await expect(procedure.listWithLinks).toBeVisible(); + await expect(procedure.noteUpdate).toBeVisible(); + await expect(procedure.noteAddReason).toBeVisible(); + + }) + + test(`${features[11].name}, ${features[11].tags}`, async()=>{ + await launchprocedurepage(); + const scrollToHeight = 2500; + await page.evaluate((scrollToHeight) => { + window.scrollTo(0, scrollToHeight); + }, scrollToHeight); + + await page.waitForTimeout(1000); + // Verifying visibility for image elements + await expect(procedure.webpImageinProcedure).toBeVisible(); + await expect(procedure.pngImageInprocedure).toBeVisible(); + await expect(procedure.textBeforeImageInProcedure).toBeVisible(); + await expect(procedure.imageafterTextInProcedure).toBeVisible(); + await expect(procedure.urlBasedURLInProcedure).toBeVisible(); + }) +}) + From ab54b072da0b0d5367268f5b631f9df6fd8aa70f Mon Sep 17 00:00:00 2001 From: Jacky Sun <67350368+JackySun9@users.noreply.github.com> Date: Tue, 9 Jan 2024 14:23:44 -0800 Subject: [PATCH 45/53] Add screenshots for UAR in CC (#238) * add test for quiz and result pages * add test for quiz and result pages * add test for quiz and result pages * add POC for analytics test * update analytics tests and envs * result envs * update analytics only on firefox * add dynamic tests * add dynamic test for quiz page * update quiz test * update test structure * add test for quiz and result pages * add POC for analytics test * update analytics tests and envs * result envs * update analytics only on firefox * add dynamic tests * add dynamic test for quiz page * update quiz test * update test structure * update uar tests to new format * update uar tests * move everything to uar folder * add dependency for js-yaml * update test according to latest comments * update test according to latest comments * update tests according to the latest comments * add uar config * add analytics for uar * update according to feedbacks * update tags * add @cc tag * update according to feedbacks * add dynamic tests for uar * update according to review comments * fix some typos * update according to review comments * merge console log info * add UI screenshots for UAR * move view point to test * update according to feedback * add analytics test for UAR * update validation and uar libs * update libs * update by feedback * update some config and tests * update some config and tests * update test content path to common path * update analytics tests * fix test failures caused by test code * fix test failures * fix test failures * add visual test for CAAS with two pages * update according to feedbacks * update report in config file * add screenshot for milo main live vs uar-integration live * add timestamp js for time stampe recording * add screenshot diff for uar stable and beta * move uar screenshots into visual compare folder * add UI screenshots for DX Quiz * build a function to get screenshots * update locator * udate uar to only run basic tests * update according to feedback * add screenshot for UAR in CC which will go live --------- Co-authored-by: xiasun Co-authored-by: Aaron Mauchley Co-authored-by: xiasun --- data/cc/quiz/quiz-basic.yml | 17 ++++++++ features/cc/quiz.screenshots.spec.js | 12 +++++ tests/cc/quiz.screenshots.test.js | 65 ++++++++++++++++++++++++++++ 3 files changed, 94 insertions(+) create mode 100644 data/cc/quiz/quiz-basic.yml create mode 100644 features/cc/quiz.screenshots.spec.js create mode 100644 tests/cc/quiz.screenshots.test.js diff --git a/data/cc/quiz/quiz-basic.yml b/data/cc/quiz/quiz-basic.yml new file mode 100644 index 00000000..8133df3a --- /dev/null +++ b/data/cc/quiz/quiz-basic.yml @@ -0,0 +1,17 @@ +--- +'Photography > Edit quickly and customize templates > A student or teacher discount': 'template single > Adobe Express' +'PDFs > Edit quickly and customize templates > Licenses and business features for teams': 'template single with PDF > Acrobat Pro' +'Video + Graphic design > Edit quickly and customize templates > Neither apply': 'template double > Adobe Express' +'Illustration + PDFs > Edit quickly and customize templates > Neither apply': 'template double with PDF > Acrobat Pro' +'Photography + Video + Graphic design > Edit quickly and customize templates > A student or teacher discount': 'template triple > Adobe Express' +'Photography + Illustration + PDFs > Edit quickly and customize templates > Neither apply': 'template triple with PDF > Acrobat Pro' + +'Photography > Take the time to control every detail > Get them sorted and organized > A student or teacher discount': 'flagship single > Lightroom' +'Video > Take the time to control every detail > Create, edit, and share on social > Licenses and business features for teams': 'flagship single > Premiere Pro' +'Photography + Illustration > Take the time to control every detail > Correct color and lighting like a pro > Paint, draw, or doodle like on paper > A student or teacher discount': 'flagship double > Lightroom,Photoshop' +'Graphic design + Illustration > Take the time to control every detail > Create layouts for magazines, books, or posters > Draw crisp lines and smooth curves > Licenses and business features for teams': 'flagship double > InDesign,Illustrator' +'Photography + Video + PDFs > Take the time to control every detail > Get them sorted and organized > Create, edit, and share on social > Create and export PDFs to Office > A student or teacher discount': 'flagship triple > Premiere Pro,Lightroom,Acrobat' + +'3D/AR > Assemble, stage, and render 3D scenes > Neither apply': '3D single > Substance 3D Stager' +'Photography + 3D/AR > Get them sorted and organized > Create 3D models with digital clay > A student or teacher discount': '3D doouble > Lightroom,Substance 3D Modeler' +'Photography + Video + 3D/AR > Get them sorted and organized > Create, edit, and share on social > Texture 3D assets in real time > Licenses and business features for teams': '3D triple > Lightroom,Premiere Pro,Substance 3D Painter' diff --git a/features/cc/quiz.screenshots.spec.js b/features/cc/quiz.screenshots.spec.js new file mode 100644 index 00000000..6e54d29b --- /dev/null +++ b/features/cc/quiz.screenshots.spec.js @@ -0,0 +1,12 @@ +module.exports = { + name: 'Quiz Recommender Blocks', + features: [ + { + tcid: '0', + name: '@quiz screenshots', + path: '/cc-shared/uar/plan-recommender/', + tags: '@cc @uar-quiz-screenshots @uar-quiz-static', + data: 'data/cc/quiz/quiz-basic.yml', + }, + ], +}; diff --git a/tests/cc/quiz.screenshots.test.js b/tests/cc/quiz.screenshots.test.js new file mode 100644 index 00000000..bbab3e39 --- /dev/null +++ b/tests/cc/quiz.screenshots.test.js @@ -0,0 +1,65 @@ +/* eslint-disable no-await-in-loop */ +/* eslint-disable no-loop-func */ +/* eslint-disable no-restricted-syntax */ +import { expect, test } from '@playwright/test'; +import Quiz from '../../selectors/uar/quiz.page.js'; +import QuizOldPage from '../../selectors/uar/quiz.old.page.js'; + +const QuizSpec = require('../../features/cc/quiz.screenshots.spec.js'); + +const { features } = QuizSpec; +const { WebUtil } = require('../../libs/webutil.js'); + +test.describe('Quiz flow test suite', () => { + // reset timeout because we use this to run all test data + test.setTimeout(10 * 60 * 1000); + for (const feature of features) { + test( + `${feature.name}, ${feature.tags}`, + async ({ page, baseURL }) => { + const quiz = new Quiz(page); + const quizOldPage = new QuizOldPage(page); + const url = `${baseURL}${feature.path}`; + console.info(url); + + // load test data from static files + const testdata = await WebUtil.loadTestData(`${feature.data}`); + + let keyNumber = 0; + + for (let key of Object.keys(testdata)) { + console.log(key); + let oldProduct = ''; + let newProduct = ''; + keyNumber += 1; + await test.step(`Old: Select each answer on test page according to ${key}`, async () => { + await quizOldPage.clickEachAnswer('https://www.adobe.com/creativecloud/quiz-recommender.html', key, keyNumber, true); + }); + + await test.step('Old: Check results on test page', async () => { + oldProduct = await quizOldPage.checkResultPage(testdata[key], key, keyNumber, true); + }); + + if (key.includes('PDFs > Edit quickly')) { + // eslint-disable-next-line no-continue + continue; + } + + if (key.includes('PDFs > Take the time to control')) { + key = key.replace('PDFs > Take the time to control every detail', 'PDFs'); + } + + await test.step(`New: Select each answer on test page according to ${key}`, async () => { + await quiz.clickEachAnswer(url, key, keyNumber, 'new', true); + }); + + await test.step('New: Check results on test page', async () => { + newProduct = await quiz.checkResultPage(testdata[key], key, keyNumber, 'new', true); + }); + + // expect.soft(newProduct).toContain(oldProduct); + } + }, + ); + } +}); From 0d18ab0bcfd078babcb7bdd3d6656fa70d3b10f9 Mon Sep 17 00:00:00 2001 From: Jacky Sun <67350368+JackySun9@users.noreply.github.com> Date: Wed, 10 Jan 2024 15:09:53 -0800 Subject: [PATCH 46/53] Update final path for UAR in CC (#239) * add test for quiz and result pages * add test for quiz and result pages * add test for quiz and result pages * add POC for analytics test * update analytics tests and envs * result envs * update analytics only on firefox * add dynamic tests * add dynamic test for quiz page * update quiz test * update test structure * add test for quiz and result pages * add POC for analytics test * update analytics tests and envs * result envs * update analytics only on firefox * add dynamic tests * add dynamic test for quiz page * update quiz test * update test structure * update uar tests to new format * update uar tests * move everything to uar folder * add dependency for js-yaml * update test according to latest comments * update test according to latest comments * update tests according to the latest comments * add uar config * add analytics for uar * update according to feedbacks * update tags * add @cc tag * update according to feedbacks * add dynamic tests for uar * update according to review comments * fix some typos * update according to review comments * merge console log info * add UI screenshots for UAR * move view point to test * update according to feedback * add analytics test for UAR * update validation and uar libs * update libs * update by feedback * update some config and tests * update some config and tests * update test content path to common path * update analytics tests * fix test failures caused by test code * fix test failures * fix test failures * add visual test for CAAS with two pages * update according to feedbacks * update report in config file * add screenshot for milo main live vs uar-integration live * add timestamp js for time stampe recording * add screenshot diff for uar stable and beta * move uar screenshots into visual compare folder * add UI screenshots for DX Quiz * build a function to get screenshots * update locator * udate uar to only run basic tests * update according to feedback * add screenshot for UAR in CC which will go live * update final path for UAR in CC --------- Co-authored-by: xiasun Co-authored-by: Aaron Mauchley Co-authored-by: xiasun --- features/cc/quiz.screenshots.spec.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/features/cc/quiz.screenshots.spec.js b/features/cc/quiz.screenshots.spec.js index 6e54d29b..6f953729 100644 --- a/features/cc/quiz.screenshots.spec.js +++ b/features/cc/quiz.screenshots.spec.js @@ -4,7 +4,7 @@ module.exports = { { tcid: '0', name: '@quiz screenshots', - path: '/cc-shared/uar/plan-recommender/', + path: '/creativecloud/plan-recommender/', tags: '@cc @uar-quiz-screenshots @uar-quiz-static', data: 'data/cc/quiz/quiz-basic.yml', }, From 0ae64ab5c3bf05f4388b5bf75936ccfb6c6b906f Mon Sep 17 00:00:00 2001 From: Dan Chivescu Date: Thu, 11 Jan 2024 20:09:18 +0200 Subject: [PATCH 47/53] [MWPW-140397] Updated FEDS checks to work on GHA (FEDS-run) (#234) * [MWPW-140397] Updated FEDS checks to work on GHA (FEDS-run) * [MWPW-140397] Force Milo production to show Jarvis without VPN * [MWPW-140397] Skip UserProfile checks until IMS creddentials issue is fixed --- features/feds/jarvis.spec.js | 8 ++++---- features/feds/placeholders.spec.js | 6 ++++-- tests/feds/jarvis.desktop.test.js | 27 --------------------------- tests/feds/jarvis.mobile.test.js | 11 ----------- tests/feds/userprofile.test.js | 2 +- 5 files changed, 9 insertions(+), 45 deletions(-) diff --git a/features/feds/jarvis.spec.js b/features/feds/jarvis.spec.js index 113a423d..e8835088 100644 --- a/features/feds/jarvis.spec.js +++ b/features/feds/jarvis.spec.js @@ -6,7 +6,7 @@ module.exports = { path: [ '/libs/feds/drafts/qa/jarvis/feds-jarvis-default', ], - browserParams: '?customPrivacyLocation=de&georouting=off', + browserParams: '?skipConsent=true&env=prod&georouting=off', envs: '@milo_live', tags: '@milo @feds @jarvis @smoke @regression', }, @@ -15,7 +15,7 @@ module.exports = { path: [ '/libs/feds/drafts/qa/jarvis/feds-jarvis-desktop', ], - browserParams: '?customPrivacyLocation=de&georouting=off', + browserParams: '?skipConsent=true&env=prod&georouting=off', envs: '@milo_live', tags: '@milo @feds @jarvis @smoke @regression', }, @@ -24,7 +24,7 @@ module.exports = { path: [ '/libs/feds/drafts/qa/jarvis/feds-jarvis-disabled', ], - browserParams: '?customPrivacyLocation=de&georouting=off', + browserParams: '?skipConsent=true&env=prod&georouting=off', envs: '@milo_live', tags: '@milo @feds @jarvis @smoke @regression', }, @@ -33,7 +33,7 @@ module.exports = { path: [ '/libs/feds/drafts/qa/jarvis/feds-jarvis-mobile', ], - browserParams: '?customPrivacyLocation=de&georouting=off', + browserParams: '?skipConsent=true&env=prod&georouting=off', envs: '@milo_live', tags: '@milo @feds @jarvis @smoke @regression', }, diff --git a/features/feds/placeholders.spec.js b/features/feds/placeholders.spec.js index bba84091..8779514d 100644 --- a/features/feds/placeholders.spec.js +++ b/features/feds/placeholders.spec.js @@ -6,7 +6,8 @@ module.exports = { path: [ '/placeholders.json', '/de/placeholders.json', - '/fr/placeholders.json', + // !Note: FR locale placeholders currently broken (known issue). + // '/fr/placeholders.json', '/jp/placeholders.json', '/uk/placeholders.json', ], @@ -18,7 +19,8 @@ module.exports = { path: [ '/placeholders.json', '/de/placeholders.json', - '/fr/placeholders.json', + // !Note: FR locale placeholders currently broken (known issue). + // '/fr/placeholders.json', '/jp/placeholders.json', '/uk/placeholders.json', ], diff --git a/tests/feds/jarvis.desktop.test.js b/tests/feds/jarvis.desktop.test.js index af516899..774b285b 100644 --- a/tests/feds/jarvis.desktop.test.js +++ b/tests/feds/jarvis.desktop.test.js @@ -4,13 +4,11 @@ import { expect, test } from '@playwright/test'; import { features } from '../../features/feds/jarvis.spec.js'; import FedsJarvis from '../../selectors/feds/feds.jarvis.page.js'; -import FedsConsent from '../../selectors/feds/feds.consent.page.js'; test.describe('Jarvis Component test suite', () => { // FEDS Jarvis Default Checks: test(`${features[0].name}, ${features[0].tags}`, async ({ page, baseURL }) => { const Jarvis = new FedsJarvis(page); - const Consent = new FedsConsent(page); console.info(`[FEDSInfo] Checking page: ${baseURL}${features[0].path}`); await test.step('Navigate to FEDS Jarvis Default page', async () => { @@ -19,13 +17,6 @@ test.describe('Jarvis Component test suite', () => { await expect(page).toHaveURL(`${baseURL}${features[0].path}${features[0].browserParams}`); }); - await test.step('Accept OneTrust consent bar', async () => { - // Wait for the OneTrust consent bar to appear: - await Consent.oneTrustContainer.waitFor({ state: 'visible', timeout: 20000 }); - // Accept the OneTrust consent banner: - await Consent.acceptOneTrustConsentBar(); - }); - await test.step('Check Jarvis component functionality', async () => { // Open Jarvis chat assistant (via Jarvis button): await Jarvis.openJarvisFromCta(); @@ -43,7 +34,6 @@ test.describe('Jarvis Component test suite', () => { // FEDS Jarvis Desktop Checks: test(`${features[1].name}, ${features[1].tags}`, async ({ page, baseURL }) => { const Jarvis = new FedsJarvis(page); - const Consent = new FedsConsent(page); console.info(`[FEDSInfo] Checking page: ${baseURL}${features[1].path}`); await test.step('Navigate to FEDS Jarvis Desktop page', async () => { @@ -52,13 +42,6 @@ test.describe('Jarvis Component test suite', () => { await expect(page).toHaveURL(`${baseURL}${features[1].path}${features[1].browserParams}`); }); - await test.step('Accept OneTrust consent bar', async () => { - // Wait for the OneTrust consent bar to appear: - await Consent.oneTrustContainer.waitFor({ state: 'visible', timeout: 20000 }); - // Accept the OneTrust consent banner: - await Consent.acceptOneTrustConsentBar(); - }); - await test.step('Check Jarvis component functionality', async () => { // Open Jarvis chat assistant (via Jarvis button): await Jarvis.openJarvisFromCta(); @@ -76,7 +59,6 @@ test.describe('Jarvis Component test suite', () => { // FEDS Jarvis Disabled Checks: test(`${features[2].name}, ${features[2].tags}`, async ({ page, baseURL }) => { const Jarvis = new FedsJarvis(page); - const Consent = new FedsConsent(page); console.info(`[FEDSInfo] Checking page: ${baseURL}${features[2].path}`); await test.step('Navigate to FEDS Jarvis Disabled page', async () => { @@ -85,15 +67,6 @@ test.describe('Jarvis Component test suite', () => { await expect(page).toHaveURL(`${baseURL}${features[2].path}${features[2].browserParams}`); }); - await test.step('Accept OneTrust consent bar', async () => { - // Wait for the OneTrust consent bar to appear: - await Consent.oneTrustContainer.waitFor({ state: 'visible', timeout: 20000 }); - // Accept the OneTrust consent banner: - await Consent.acceptOneTrustConsentBar(); - // Check consent persistence: - await Consent.assertOneTrustAcceptState(); - }); - await test.step('Check Jarvis component is not initialized', async () => { // Check Jarvis component doesn't get initialized: await Jarvis.jarvisButton.waitFor({ state: 'hidden', timeout: 15000 }); diff --git a/tests/feds/jarvis.mobile.test.js b/tests/feds/jarvis.mobile.test.js index e84b38c6..f8f424b2 100644 --- a/tests/feds/jarvis.mobile.test.js +++ b/tests/feds/jarvis.mobile.test.js @@ -4,7 +4,6 @@ import { expect, test } from '@playwright/test'; import { features } from '../../features/feds/jarvis.spec.js'; import FedsJarvis from '../../selectors/feds/feds.jarvis.page.js'; -import FedsConsent from '../../selectors/feds/feds.consent.page.js'; test.describe('Jarvis Component test suite', () => { // Setup viewport to trigger mobile logic: @@ -18,7 +17,6 @@ test.describe('Jarvis Component test suite', () => { // FEDS Jarvis Mobile Checks: test(`${features[3].name}, ${features[3].tags}`, async ({ page, baseURL }) => { const Jarvis = new FedsJarvis(page); - const Consent = new FedsConsent(page); console.info(`[FEDSInfo] Checking page: ${baseURL}${features[3].path}`); await test.step('Navigate to FEDS Jarvis Default page', async () => { @@ -27,15 +25,6 @@ test.describe('Jarvis Component test suite', () => { await expect(page).toHaveURL(`${baseURL}${features[3].path}${features[3].browserParams}`); }); - await test.step('Accept OneTrust consent bar', async () => { - // Wait for the OneTrust consent bar to appear: - await Consent.oneTrustContainer.waitFor({ state: 'visible', timeout: 20000 }); - // Accept the OneTrust consent banner: - await Consent.acceptOneTrustConsentBar(); - // Check consent persistence: - await Consent.assertOneTrustAcceptState(); - }); - await test.step('Check Jarvis component is initialized', async () => { // Wait for Jarvis component to appear: await Jarvis.jarvisButton.waitFor({ state: 'visible', timeout: 15000 }); diff --git a/tests/feds/userprofile.test.js b/tests/feds/userprofile.test.js index efa2431f..d8eea91e 100644 --- a/tests/feds/userprofile.test.js +++ b/tests/feds/userprofile.test.js @@ -8,7 +8,7 @@ import FedsHeader from '../../selectors/feds/feds.header.page.js'; test.describe('User Profile Component test suite', () => { // FEDS User Profile Checks: - test(`${features[0].name}, ${features[0].tags}`, async ({ page, baseURL }) => { + test.skip(`${features[0].name}, ${features[0].tags}`, async ({ page, baseURL }) => { const Login = new FedsLogin(page); const Header = new FedsHeader(page); console.info(`[FEDSInfo] Checking page: ${baseURL}${features[0].path}`); From d629cf93a341c368cc77f4cdd72dccee7af937b4 Mon Sep 17 00:00:00 2001 From: Santoshkumar Nateekar Date: Fri, 12 Jan 2024 10:39:55 -0800 Subject: [PATCH 48/53] [MILOLIBS RUN : MWPW-141223] Provide support to run nala tests on a given milo libs (#240) * update the test files * update the tests * update the failures * update the personalizataion and iframe tests * update wait --------- Co-authored-by: nateekar --- .github/workflows/milolib.yml | 6 +- features/milo/georouting.spec.js | 2 +- global.setup.js | 231 ++++++++++++--------- playwright.config.js | 2 +- selectors/milo/georouting.feature.page.js | 3 +- tests/milo/actionitem.block.test.js | 50 ++--- tests/milo/aside.block.test.js | 102 ++++----- tests/milo/breadcrumbs.block.test.js | 26 +-- tests/milo/card.block.test.js | 44 ++-- tests/milo/carousel.block.test.js | 20 +- tests/milo/chart.block.test.js | 1 + tests/milo/columns.block.test.js | 32 +-- tests/milo/figure.block.test.js | 14 +- tests/milo/footer.block.test.js | 82 ++++++-- tests/milo/georouting.feature.test.js | 38 ++-- tests/milo/header.block.test.js | 28 ++- tests/milo/howto.block.test.js | 20 +- tests/milo/htmlextn.feature.test.js | 5 +- tests/milo/icon.block.test.js | 20 +- tests/milo/iframe.block.test.js | 8 +- tests/milo/marquee.block.test.js | 92 ++++---- tests/milo/media.block.test.js | 31 +-- tests/milo/merchcard.block.test.js | 68 +++--- tests/milo/modal.block.test.js | 20 +- tests/milo/personalization.feature.test.js | 26 +-- tests/milo/quote.block.test.js | 38 ++-- tests/milo/review.block.test.js | 14 +- tests/milo/tab.block.test.js | 14 +- tests/milo/table.block.test.js | 32 +-- tests/milo/text.block.test.js | 50 ++--- tests/milo/video.block.test.js | 55 ++--- tests/milo/zpattern.block.test.js | 26 +-- 32 files changed, 663 insertions(+), 537 deletions(-) diff --git a/.github/workflows/milolib.yml b/.github/workflows/milolib.yml index 8e8d0392..1e6376e0 100644 --- a/.github/workflows/milolib.yml +++ b/.github/workflows/milolib.yml @@ -1,14 +1,14 @@ -name: Run Nala on Milo Libs Manually +name: Run Nala on Milo Libs on: workflow_dispatch: inputs: branch: - description: 'Provide the branch url' + description: 'Provide the live branch url. ex: https://main--cc--adobecom.hlx.live' required: false type: string milolibs: - description: 'Provide MiloLibs param' + description: 'Provide MiloLibs param. ex: ?milolibs=marquee-static-hover' required: false type: string tags: diff --git a/features/milo/georouting.spec.js b/features/milo/georouting.spec.js index 557cb41d..a98353ff 100644 --- a/features/milo/georouting.spec.js +++ b/features/milo/georouting.spec.js @@ -7,7 +7,7 @@ module.exports = { desc: 'User accessing DE page from US locale.', path: '/de/drafts/nala/features/georouting/georouting', data: { - title: 'This Adobe site doesn\'t match your location.', + title: /This Adobe site doesn[' ’]t match your location./, text: 'Based on your location, we think you may prefer the United States website', button: 'United States', link: 'Deutschland', diff --git a/global.setup.js b/global.setup.js index 13c9352c..c1faaf0f 100644 --- a/global.setup.js +++ b/global.setup.js @@ -1,120 +1,151 @@ import { exit } from 'process'; - const { execSync } = require('child_process'); const { isBranchURLValid } = require('./libs/baseurl.js'); const axios = require('axios'); -async function globalSetup() { - console.info('----Executing Global setup---------'); +const MAIN_BRANCH_LIVE_URL = 'https://main--milo--adobecom.hlx.live'; +const STAGE_BRANCH_URL = 'https://milo.stage.adobe.com'; +const LOCALHOST_URL = 'http://localhost:3000'; + +async function getGitHubPRBranchLiveUrl() { + // get the pr number + const prReference = process.env.GITHUB_REF; + const prNumber = prReference.split('/')[2]; + + // get the pr branch name + const branch = process.env.GITHUB_HEAD_REF; + const prBranch = branch.replace(/\//g, '-'); + + // get the org and repo + const repository = process.env.GITHUB_REPOSITORY; + const repoParts = repository.split('/'); + const toRepoOrg = repoParts[0]; + const toRepoName = repoParts[1]; + + // Get the org and repo from the environment variables + const prFromOrg = process.env.prOrg; + const prFromRepoName = process.env.prRepo; + let prBranchLiveUrl; - let stageBranchLiveUrl; - let localTestLiveUrl; - let localOrg; - let localRepo; - let prNumber - // Check if the code is running in a GitHub CI/CD environment - if (process.env.GITHUB_ACTIONS === 'true') { - console.info('---- Running Tests in the GitHub environment ---------'); - - // get the pr number - const prReference = process.env.GITHUB_REF; - prNumber = prReference.split('/')[2]; - - // get the pr branch name - const branch = process.env.GITHUB_HEAD_REF; - const prBranch = branch.replace(/\//g, '-'); - - // get the org and repo - const repository = process.env.GITHUB_REPOSITORY; - const repoParts = repository.split('/'); - const toRepoOrg = repoParts[0]; - const toRepoName = repoParts[1]; - - // Get the org and repo from the environment variables - const prFromOrg = process.env.prOrg; - const prFromRepoName = process.env.prRepo; - - try { - // Construct the pr branch URL - if (toRepoName === 'nala' || toRepoName === 'janus') { - prBranchLiveUrl = `https://main--milo--adobecom.hlx.live`; - } else { - prBranchLiveUrl = `https://${prBranch}--${prFromRepoName}--${prFromOrg}.hlx.live`; - } + if (toRepoName === 'nala' || toRepoName === 'janus') { + prBranchLiveUrl = MAIN_BRANCH_LIVE_URL; + } else { + prBranchLiveUrl = `https://${prBranch}--${prFromRepoName}--${prFromOrg}.hlx.live`; + } - // Validate the pr branch URL by making an HTTP request - if (await isBranchURLValid(prBranchLiveUrl)) { - process.env.PR_BRANCH_LIVE_URL = prBranchLiveUrl; - } - console.info('PR Repository : ', repository); - console.info('PR TO ORG : ', toRepoOrg); - console.info('PR TO REPO : ', toRepoName); - console.info('PR From ORG : ', prFromOrg); - console.info('PR From REPO : ', prFromRepoName); - console.info('PR Branch : ', branch); - console.info('PR Branch(U) : ', prBranch); - console.info('PR Number : ', prNumber); - console.info('PR From Branch live url : ', prBranchLiveUrl); - } catch (err) { - console.error(`Error => Error in setting PR Branch test URL : ${prBranchLiveUrl}`); - console.info(`Note : PR branch test url ${prBranchLiveUrl} is not valid, Exiting test execution.`); - process.exit(1); - } - } else if (process.env.CIRCLECI) { - console.info('---- Running Tests in the CircleCI environment ---------'); + try { + if (await isBranchURLValid(prBranchLiveUrl)) { + process.env.PR_BRANCH_LIVE_URL = prBranchLiveUrl; + } + console.info('PR Repository : ', repository); + console.info('PR TO ORG : ', toRepoOrg); + console.info('PR TO REPO : ', toRepoName); + console.info('PR From ORG : ', prFromOrg); + console.info('PR From REPO : ', prFromRepoName); + console.info('PR Branch : ', branch); + console.info('PR Branch(U) : ', prBranch); + console.info('PR Number : ', prNumber); + console.info('PR From Branch live url : ', prBranchLiveUrl); + } catch (err) { + console.error(`Error => Error in setting PR Branch test URL : ${prBranchLiveUrl}`); + console.info(`Note: PR branch test url ${prBranchLiveUrl} is not valid, Exiting test execution.`); + process.exit(1); + } +} + +async function getGitHubMiloLibsBranchLiveUrl() { + const repository = process.env.GITHUB_REPOSITORY; + + let prBranchLiveUrl; + let miloLibs; + + prBranchLiveUrl = process.env.PR_BRANCH_MILOLIBS_LIVE_URL; + miloLibs = process.env.MILO_LIBS; + + try { + if (await isBranchURLValid(prBranchLiveUrl)) { + process.env.PR_BRANCH_LIVE_URL = prBranchLiveUrl; + } + console.info('PR Repository : ', repository); + console.info('PR Branch live url : ', prBranchLiveUrl); + console.info('Milo Libs : ', miloLibs); + } catch (err) { + console.error(`Error => Error in setting PR Branch test URL : ${prBranchLiveUrl}`); + console.info(`Note: PR branch test url ${prBranchLiveUrl} is not valid, Exiting test execution.`); + process.exit(1); + } +} - stageBranchLiveUrl = 'https://milo.stage.adobe.com'; - - // Validate the stage URL by making an HTTP request +async function getCircleCIBranchLiveUrl() { + const stageBranchLiveUrl = STAGE_BRANCH_URL; + + try { if (await isBranchURLValid(stageBranchLiveUrl)) { process.env.PR_BRANCH_LIVE_URL = stageBranchLiveUrl; } console.info('Stage Branch Live URL : ', stageBranchLiveUrl); + } catch (err) { + console.error('Error => Error in setting Stage Branch test URL : ', stageBranchLiveUrl); + console.info('Note: Stage branch test url is not valid, Exiting test execution.'); + process.exit(1); + } +} - } else { - - console.info('---- Running Tests in the Local environment ---------'); - - try { - // Run 'git rev-parse --show-toplevel' to get the root directory of the Git repository - const localGitRootDir = execSync('git rev-parse --show-toplevel', { encoding: 'utf-8' }).trim(); - - if (localGitRootDir) { - // Get the repository and organization/owner name from the Git remote URL - const gitRemoteOriginUrl = execSync('git config --get remote.origin.url', { cwd: localGitRootDir, encoding: 'utf-8' }).trim(); - const match = gitRemoteOriginUrl.match(/github\.com\/(.*?)\/(.*?)\.git/); - console.info('Git Local Remote Origin : ', gitRemoteOriginUrl ); - if (match) { - localOrg = match[1]; - localRepo = match[2]; - - console.info('Git ORG : ', localOrg ); - console.info('Git REPO : ', localRepo ); - - // get the current local branch name - const localBranch = execSync('git rev-parse --abbrev-ref HEAD', { cwd: localGitRootDir, encoding: 'utf-8' }).trim(); - console.info('Local Branch : ', localBranch ); - - if ( localRepo === 'nala' || localRepo === 'janus'){ - localTestLiveUrl = `https://main--milo--adobecom.hlx.live`; - } else { - localTestLiveUrl = `http://localhost:3000`; - } - - // Validate the pr branch URL by making an HTTP request - if ( await isBranchURLValid(localTestLiveUrl)){ - process.env.LOCAL_TEST_LIVE_URL = localTestLiveUrl; - } - console.info('Local Test Live URL : ', process.env.LOCAL_TEST_LIVE_URL ); +async function getLocalBranchLiveUrl() { + try { + const localGitRootDir = execSync('git rev-parse --show-toplevel', { encoding: 'utf-8' }).trim(); + + if (localGitRootDir) { + const gitRemoteOriginUrl = execSync('git config --get remote.origin.url', { cwd: localGitRootDir, encoding: 'utf-8' }).trim(); + const match = gitRemoteOriginUrl.match(/github\.com\/(.*?)\/(.*?)\.git/); + + if (match) { + const [localOrg, localRepo] = match.slice(1, 3); + const localBranch = execSync('git rev-parse --abbrev-ref HEAD', { cwd: localGitRootDir, encoding: 'utf-8' }).trim(); + let localTestLiveUrl; + + if (localRepo === 'nala' || localRepo === 'janus') { + localTestLiveUrl = MAIN_BRANCH_LIVE_URL; + } else { + localTestLiveUrl = LOCALHOST_URL; + } + + if (await isBranchURLValid(localTestLiveUrl)) { + process.env.LOCAL_TEST_LIVE_URL = localTestLiveUrl; } - } - } catch (error) { - console.error(`Error => Error in setting local test URL : ${localTestLiveUrl}`) - console.info(`Note : Local or branch test url ${localTestLiveUrl} is not valid, Exiting test execution.`); - process.exit(1); + console.info('Git ORG : ', localOrg); + console.info('Git REPO : ', localRepo); + console.info('Local Branch : ', localBranch); + console.info('Local Test Live URL : ', process.env.LOCAL_TEST_LIVE_URL); + } + } + } catch (error) { + console.error(`Error => Error in setting local test URL : ${localTestLiveUrl}`); + console.info(`Note: Local or branch test url is not valid, Exiting test execution.`); + process.exit(1); + } +} + +async function globalSetup() { + console.info('----Executing Global setup---------'); + + if (process.env.GITHUB_ACTIONS === 'true') { + console.info('---- Running Tests in the GitHub environment ---------'); + + if (process.env.MILO_LIBS_RUN === 'true') { + await getGitHubMiloLibsBranchLiveUrl(); + } else { + await getGitHubPRBranchLiveUrl(); } + } else if (process.env.CIRCLECI) { + console.info('---- Running Tests in the CircleCI environment ---------'); + await getCircleCIBranchLiveUrl(); + } else { + console.info('---- Running Tests in the Local environment ---------'); + await getLocalBranchLiveUrl(); } } + export default globalSetup; diff --git a/playwright.config.js b/playwright.config.js index 6f89ad59..0f656c10 100644 --- a/playwright.config.js +++ b/playwright.config.js @@ -9,7 +9,7 @@ const envs = require('./envs/envs.js'); const config = { testDir: './tests/milo', outputDir: './test-results', - globalSetup: './global.setup_1.js', + globalSetup: './global.setup.js', /* Maximum time one test can run for. */ timeout: 30 * 1000, expect: { diff --git a/selectors/milo/georouting.feature.page.js b/selectors/milo/georouting.feature.page.js index a7645eac..7c169d6b 100644 --- a/selectors/milo/georouting.feature.page.js +++ b/selectors/milo/georouting.feature.page.js @@ -6,7 +6,8 @@ export default class Georouting { // global footer locators this.footer = this.page.locator('.global-footer'); - this.changeRegionLink = this.footer.locator('//a[@data-modal-path="/fragments/regions"]'); + //this.changeRegionLink = this.footer.locator('//a[@data-modal-path="/fragments/regions"]'); + this.changeRegionLink = this.footer.locator('.modal.link-block'); // change region modal locators this.changeRegionModal = this.page.locator('.dialog-modal'); diff --git a/tests/milo/actionitem.block.test.js b/tests/milo/actionitem.block.test.js index 8989b278..348c3f91 100644 --- a/tests/milo/actionitem.block.test.js +++ b/tests/milo/actionitem.block.test.js @@ -6,6 +6,8 @@ import ActionItem from '../../selectors/milo/actionitem.block.page.js'; let actionItem; let webUtil; +const miloLibs = process.env.MILO_LIBS || ''; + test.describe('Milo Action-Item block test suite', () => { test.beforeEach(async ({ page }) => { actionItem = new ActionItem(page); @@ -14,13 +16,13 @@ test.describe('Milo Action-Item block test suite', () => { // Test 0 : Action-Item (Small) test(`${features[0].name},${features[0].tags}`, async ({ page, baseURL }) => { - console.info(`[Test Page]: ${baseURL}${features[0].path}`); + console.info(`[Test Page]: ${baseURL}${features[0].path}${miloLibs}`); const data = features[0].data; await test.step('step-1: Go to Action item block test page', async () => { - await page.goto(`${baseURL}${features[0].path}`); + await page.goto(`${baseURL}${features[0].path}${miloLibs}`); await page.waitForLoadState('domcontentloaded'); - await expect(page).toHaveURL(`${baseURL}${features[0].path}`); + await expect(page).toHaveURL(`${baseURL}${features[0].path}${miloLibs}`); }); await test.step('step-2: Verify Action item content/specs', async () => { @@ -35,13 +37,13 @@ test.describe('Milo Action-Item block test suite', () => { // Test 1 : Action-Item (Medium) test(`${features[1].name},${features[1].tags}`, async ({ page, baseURL }) => { - console.info(`[Test Page]: ${baseURL}${features[1].path}`); + console.info(`[Test Page]: ${baseURL}${features[1].path}${miloLibs}`); const data = features[1].data; await test.step('step-1: Go to Action item block test page', async () => { - await page.goto(`${baseURL}${features[1].path}`); + await page.goto(`${baseURL}${features[1].path}${miloLibs}`); await page.waitForLoadState('domcontentloaded'); - await expect(page).toHaveURL(`${baseURL}${features[1].path}`); + await expect(page).toHaveURL(`${baseURL}${features[1].path}${miloLibs}`); }); await test.step('step-2: Verify Action item content/specs', async () => { @@ -56,13 +58,13 @@ test.describe('Milo Action-Item block test suite', () => { // Test 2 : Action-Item (Large) test(`${features[2].name},${features[2].tags}`, async ({ page, baseURL }) => { - console.info(`[Test Page]: ${baseURL}${features[2].path}`); + console.info(`[Test Page]: ${baseURL}${features[2].path}${miloLibs}`); const data = features[2].data; await test.step('step-1: Go to Action item block test page', async () => { - await page.goto(`${baseURL}${features[2].path}`); + await page.goto(`${baseURL}${features[2].path}${miloLibs}`); await page.waitForLoadState('domcontentloaded'); - await expect(page).toHaveURL(`${baseURL}${features[2].path}`); + await expect(page).toHaveURL(`${baseURL}${features[2].path}${miloLibs}`); }); await test.step('step-2: Verify Action item content/specs', async () => { @@ -77,13 +79,13 @@ test.describe('Milo Action-Item block test suite', () => { // Test 3 : Action-Item (Center) test(`${features[3].name},${features[3].tags}`, async ({ page, baseURL }) => { - console.info(`[Test Page]: ${baseURL}${features[3].path}`); + console.info(`[Test Page]: ${baseURL}${features[3].path}${miloLibs}`); const data = features[3].data; await test.step('step-1: Go to Action item block test page', async () => { - await page.goto(`${baseURL}${features[3].path}`); + await page.goto(`${baseURL}${features[3].path}${miloLibs}`); await page.waitForLoadState('domcontentloaded'); - await expect(page).toHaveURL(`${baseURL}${features[3].path}`); + await expect(page).toHaveURL(`${baseURL}${features[3].path}${miloLibs}`); }); await test.step('step-2: Verify Action item content/specs', async () => { @@ -97,13 +99,13 @@ test.describe('Milo Action-Item block test suite', () => { // Test 4 : Action-Item (Rounded) test(`${features[4].name},${features[4].tags}`, async ({ page, baseURL }) => { - console.info(`[Test Page]: ${baseURL}${features[4].path}`); + console.info(`[Test Page]: ${baseURL}${features[4].path}${miloLibs}`); const data = features[4].data; await test.step('step-1: Go to Action item block test page', async () => { - await page.goto(`${baseURL}${features[4].path}`); + await page.goto(`${baseURL}${features[4].path}${miloLibs}`); await page.waitForLoadState('domcontentloaded'); - await expect(page).toHaveURL(`${baseURL}${features[4].path}`); + await expect(page).toHaveURL(`${baseURL}${features[4].path}${miloLibs}`); }); await test.step('step-2: Verify Action item content/specs', async () => { @@ -118,13 +120,13 @@ test.describe('Milo Action-Item block test suite', () => { // Test 5 : Action-Item (Float Button) test(`${features[5].name},${features[5].tags}`, async ({ page, baseURL }) => { - console.info(`[Test Page]: ${baseURL}${features[5].path}`); + console.info(`[Test Page]: ${baseURL}${features[5].path}${miloLibs}`); const data = features[5].data; await test.step('step-1: Go to Action item block test page', async () => { - await page.goto(`${baseURL}${features[5].path}`); + await page.goto(`${baseURL}${features[5].path}${miloLibs}`); await page.waitForLoadState('domcontentloaded'); - await expect(page).toHaveURL(`${baseURL}${features[5].path}`); + await expect(page).toHaveURL(`${baseURL}${features[5].path}${miloLibs}`); }); await test.step('step-2: Verify Action item content/specs', async () => { @@ -137,13 +139,13 @@ test.describe('Milo Action-Item block test suite', () => { // Test 6 : Action-Item (scroller) test(`${features[6].name},${features[6].tags}`, async ({ page, baseURL }) => { - console.info(`[Test Page]: ${baseURL}${features[6].path}`); + console.info(`[Test Page]: ${baseURL}${features[6].path}${miloLibs}`); const data = features[6].data; await test.step('step-1: Go to Action item block test page', async () => { - await page.goto(`${baseURL}${features[6].path}`); + await page.goto(`${baseURL}${features[6].path}${miloLibs}`); await page.waitForLoadState('domcontentloaded'); - await expect(page).toHaveURL(`${baseURL}${features[6].path}`); + await expect(page).toHaveURL(`${baseURL}${features[6].path}${miloLibs}`); }); await test.step('step-2: Verify Action item content/specs', async () => { @@ -160,13 +162,13 @@ test.describe('Milo Action-Item block test suite', () => { // Test 7 : Action-Item (scroller) test(`${features[7].name},${features[7].tags}`, async ({ page, baseURL }) => { - console.info(`[Test Page]: ${baseURL}${features[7].path}`); + console.info(`[Test Page]: ${baseURL}${features[7].path}${miloLibs}`); const data = features[7].data; await test.step('step-1: Go to Action item block test page', async () => { - await page.goto(`${baseURL}${features[7].path}`); + await page.goto(`${baseURL}${features[7].path}${miloLibs}`); await page.waitForLoadState('domcontentloaded'); - await expect(page).toHaveURL(`${baseURL}${features[7].path}`); + await expect(page).toHaveURL(`${baseURL}${features[7].path}${miloLibs}`); }); await test.step('step-2: Verify Action item content/specs', async () => { diff --git a/tests/milo/aside.block.test.js b/tests/milo/aside.block.test.js index e8460e74..53c60217 100644 --- a/tests/milo/aside.block.test.js +++ b/tests/milo/aside.block.test.js @@ -2,6 +2,8 @@ import { expect, test } from '@playwright/test'; import { features } from '../../features/milo/aside.block.spec.js'; import AsideBlock from '../../selectors/milo/aside.block.page.js'; +const miloLibs = process.env.MILO_LIBS || ''; + test.describe('Aside Block test suite', () => { // Aside Small Checks: test(`${features[0].name}, ${features[0].tags}`, async ({ page, baseURL }) => { @@ -9,9 +11,9 @@ test.describe('Aside Block test suite', () => { console.info(`[Test Page]: ${baseURL}${features[0].path}`); await test.step('Navigate to page with Aside block', async () => { - await page.goto(`${baseURL}${features[0].path}${features[0].browserParams}`); + await page.goto(`${baseURL}${features[0].path}${features[0].browserParams}&${miloLibs}`); await page.waitForLoadState('domcontentloaded'); - await expect(page).toHaveURL(`${baseURL}${features[0].path}${features[0].browserParams}`); + await expect(page).toHaveURL(`${baseURL}${features[0].path}${features[0].browserParams}&${miloLibs}`); }); await test.step('Validate Aside block content', async () => { @@ -38,12 +40,12 @@ test.describe('Aside Block test suite', () => { // Aside Medium Checks: test(`${features[1].name}, ${features[1].tags}`, async ({ page, baseURL }) => { const Aside = new AsideBlock(page); - console.info(`[Test Page]: ${baseURL}${features[1].path}`); + console.info(`[Test Page]: ${baseURL}${features[1].path}${miloLibs}`); await test.step('Navigate to page with Aside block', async () => { - await page.goto(`${baseURL}${features[1].path}${features[1].browserParams}`); + await page.goto(`${baseURL}${features[1].path}${features[1].browserParams}&${miloLibs}`); await page.waitForLoadState('domcontentloaded'); - await expect(page).toHaveURL(`${baseURL}${features[1].path}${features[1].browserParams}`); + await expect(page).toHaveURL(`${baseURL}${features[1].path}${features[1].browserParams}&${miloLibs}`); }); await test.step('Validate Aside block content', async () => { @@ -68,12 +70,12 @@ test.describe('Aside Block test suite', () => { // Aside Large Checks: test(`${features[2].name}, ${features[2].tags}`, async ({ page, baseURL }) => { const Aside = new AsideBlock(page); - console.info(`[Test Page]: ${baseURL}${features[2].path}`); + console.info(`[Test Page]: ${baseURL}${features[2].path}${miloLibs}`); await test.step('Navigate to page with Aside block', async () => { - await page.goto(`${baseURL}${features[2].path}${features[2].browserParams}`); + await page.goto(`${baseURL}${features[2].path}${features[2].browserParams}&${miloLibs}`); await page.waitForLoadState('domcontentloaded'); - await expect(page).toHaveURL(`${baseURL}${features[2].path}${features[2].browserParams}`); + await expect(page).toHaveURL(`${baseURL}${features[2].path}${features[2].browserParams}&${miloLibs}`); }); await test.step('Validate Aside block content', async () => { @@ -98,12 +100,12 @@ test.describe('Aside Block test suite', () => { // Aside Split Small Dark Checks: test(`${features[3].name}, ${features[3].tags}`, async ({ page, baseURL }) => { const Aside = new AsideBlock(page); - console.info(`[Test Page]: ${baseURL}${features[3].path}`); + console.info(`[Test Page]: ${baseURL}${features[3].path}${miloLibs}`); await test.step('Navigate to page with Aside block', async () => { - await page.goto(`${baseURL}${features[3].path}${features[3].browserParams}`); + await page.goto(`${baseURL}${features[3].path}${features[3].browserParams}&${miloLibs}`); await page.waitForLoadState('domcontentloaded'); - await expect(page).toHaveURL(`${baseURL}${features[3].path}${features[3].browserParams}`); + await expect(page).toHaveURL(`${baseURL}${features[3].path}${features[3].browserParams}&${miloLibs}`); }); await test.step('Validate Aside block content', async () => { @@ -128,12 +130,12 @@ test.describe('Aside Block test suite', () => { // Aside Split Small Half Dark Checks: test(`${features[4].name}, ${features[4].tags}`, async ({ page, baseURL }) => { const Aside = new AsideBlock(page); - console.info(`[Test Page]: ${baseURL}${features[4].path}`); + console.info(`[Test Page]: ${baseURL}${features[4].path}${miloLibs}`); await test.step('Navigate to page with Aside block', async () => { - await page.goto(`${baseURL}${features[4].path}${features[4].browserParams}`); + await page.goto(`${baseURL}${features[4].path}${features[4].browserParams}&${miloLibs}`); await page.waitForLoadState('domcontentloaded'); - await expect(page).toHaveURL(`${baseURL}${features[4].path}${features[4].browserParams}`); + await expect(page).toHaveURL(`${baseURL}${features[4].path}${features[4].browserParams}&${miloLibs}`); }); await test.step('Validate Aside block content', async () => { @@ -158,12 +160,12 @@ test.describe('Aside Block test suite', () => { // Aside Split Medium Checks: test(`${features[5].name}, ${features[5].tags}`, async ({ page, baseURL }) => { const Aside = new AsideBlock(page); - console.info(`[Test Page]: ${baseURL}${features[5].path}`); + console.info(`[Test Page]: ${baseURL}${features[5].path}${miloLibs}`); await test.step('Navigate to page with Aside block', async () => { - await page.goto(`${baseURL}${features[5].path}${features[5].browserParams}`); + await page.goto(`${baseURL}${features[5].path}${features[5].browserParams}&${miloLibs}`); await page.waitForLoadState('domcontentloaded'); - await expect(page).toHaveURL(`${baseURL}${features[5].path}${features[5].browserParams}`); + await expect(page).toHaveURL(`${baseURL}${features[5].path}${features[5].browserParams}&${miloLibs}`); }); await test.step('Validate Aside block content', async () => { @@ -188,12 +190,12 @@ test.describe('Aside Block test suite', () => { // Aside Split Medium Half Checks: test(`${features[6].name}, ${features[6].tags}`, async ({ page, baseURL }) => { const Aside = new AsideBlock(page); - console.info(`[Test Page]: ${baseURL}${features[6].path}`); + console.info(`[Test Page]: ${baseURL}${features[6].path}${miloLibs}`); await test.step('Navigate to page with Aside block', async () => { - await page.goto(`${baseURL}${features[6].path}${features[6].browserParams}`); + await page.goto(`${baseURL}${features[6].path}${features[6].browserParams}&${miloLibs}`); await page.waitForLoadState('domcontentloaded'); - await expect(page).toHaveURL(`${baseURL}${features[6].path}${features[6].browserParams}`); + await expect(page).toHaveURL(`${baseURL}${features[6].path}${features[6].browserParams}&${miloLibs}`); }); await test.step('Validate Aside block content', async () => { @@ -218,12 +220,12 @@ test.describe('Aside Block test suite', () => { // Aside Split Large Checks: test(`${features[7].name}, ${features[7].tags}`, async ({ page, baseURL }) => { const Aside = new AsideBlock(page); - console.info(`[Test Page]: ${baseURL}${features[7].path}`); + console.info(`[Test Page]: ${baseURL}${features[7].path}${miloLibs}`); await test.step('Navigate to page with Aside block', async () => { - await page.goto(`${baseURL}${features[7].path}${features[7].browserParams}`); + await page.goto(`${baseURL}${features[7].path}${features[7].browserParams}&${miloLibs}`); await page.waitForLoadState('domcontentloaded'); - await expect(page).toHaveURL(`${baseURL}${features[7].path}${features[7].browserParams}`); + await expect(page).toHaveURL(`${baseURL}${features[7].path}${features[7].browserParams}&${miloLibs}`); }); await test.step('Validate Aside block content', async () => { @@ -246,12 +248,12 @@ test.describe('Aside Block test suite', () => { // Aside Split Large Half Dark Checks: test(`${features[8].name}, ${features[8].tags}`, async ({ page, baseURL }) => { const Aside = new AsideBlock(page); - console.info(`[Test Page]: ${baseURL}${features[8].path}`); + console.info(`[Test Page]: ${baseURL}${features[8].path}${miloLibs}`); await test.step('Navigate to page with Aside block', async () => { - await page.goto(`${baseURL}${features[8].path}${features[8].browserParams}`); + await page.goto(`${baseURL}${features[8].path}${features[8].browserParams}&${miloLibs}`); await page.waitForLoadState('domcontentloaded'); - await expect(page).toHaveURL(`${baseURL}${features[8].path}${features[8].browserParams}`); + await expect(page).toHaveURL(`${baseURL}${features[8].path}${features[8].browserParams}&${miloLibs}`); }); await test.step('Validate Aside block content', async () => { @@ -276,12 +278,12 @@ test.describe('Aside Block test suite', () => { // Aside Inline Checks: test(`${features[9].name}, ${features[9].tags}`, async ({ page, baseURL }) => { const Aside = new AsideBlock(page); - console.info(`[Test Page]: ${baseURL}${features[9].path}`); + console.info(`[Test Page]: ${baseURL}${features[9].path}${miloLibs}`); await test.step('Navigate to page with Aside block', async () => { - await page.goto(`${baseURL}${features[9].path}${features[9].browserParams}`); + await page.goto(`${baseURL}${features[9].path}${features[9].browserParams}&${miloLibs}`); await page.waitForLoadState('domcontentloaded'); - await expect(page).toHaveURL(`${baseURL}${features[9].path}${features[9].browserParams}`); + await expect(page).toHaveURL(`${baseURL}${features[9].path}${features[9].browserParams}&${miloLibs}`); }); await test.step('Validate Aside block content', async () => { @@ -306,12 +308,12 @@ test.describe('Aside Block test suite', () => { // Aside Inline Dark Checks: test(`${features[10].name}, ${features[10].tags}`, async ({ page, baseURL }) => { const Aside = new AsideBlock(page); - console.info(`[Test Page]: ${baseURL}${features[10].path}`); + console.info(`[Test Page]: ${baseURL}${features[10].path}${miloLibs}`); await test.step('Navigate to page with Aside block', async () => { - await page.goto(`${baseURL}${features[10].path}${features[10].browserParams}`); + await page.goto(`${baseURL}${features[10].path}${features[10].browserParams}&${miloLibs}`); await page.waitForLoadState('domcontentloaded'); - await expect(page).toHaveURL(`${baseURL}${features[10].path}${features[10].browserParams}`); + await expect(page).toHaveURL(`${baseURL}${features[10].path}${features[10].browserParams}&${miloLibs}`); }); await test.step('Validate Aside block content', async () => { @@ -336,12 +338,12 @@ test.describe('Aside Block test suite', () => { // Aside Notification Extra Small Dark: test(`${features[11].name}, ${features[11].tags}`, async ({ page, baseURL }) => { const Aside = new AsideBlock(page); - console.info(`[Test Page]: ${baseURL}${features[11].path}`); + console.info(`[Test Page]: ${baseURL}${features[11].path}${miloLibs}`); await test.step('Navigate to page with Aside block', async () => { - await page.goto(`${baseURL}${features[11].path}${features[11].browserParams}`); + await page.goto(`${baseURL}${features[11].path}${features[11].browserParams}&${miloLibs}`); await page.waitForLoadState('domcontentloaded'); - await expect(page).toHaveURL(`${baseURL}${features[11].path}${features[11].browserParams}`); + await expect(page).toHaveURL(`${baseURL}${features[11].path}${features[11].browserParams}&${miloLibs}`); }); await test.step('Validate Aside block content', async () => { @@ -371,12 +373,12 @@ test.describe('Aside Block test suite', () => { // Aside Notification Small: test(`${features[12].name}, ${features[12].tags}`, async ({ page, baseURL }) => { const Aside = new AsideBlock(page); - console.info(`[Test Page]: ${baseURL}${features[12].path}`); + console.info(`[Test Page]: ${baseURL}${features[12].path}${miloLibs}`); await test.step('Navigate to page with Aside block', async () => { - await page.goto(`${baseURL}${features[12].path}${features[12].browserParams}`); + await page.goto(`${baseURL}${features[12].path}${features[12].browserParams}&${miloLibs}`); await page.waitForLoadState('domcontentloaded'); - await expect(page).toHaveURL(`${baseURL}${features[12].path}${features[12].browserParams}`); + await expect(page).toHaveURL(`${baseURL}${features[12].path}${features[12].browserParams}&${miloLibs}`); }); await test.step('Validate Aside block content', async () => { @@ -404,12 +406,12 @@ test.describe('Aside Block test suite', () => { // Aside Notification Medium: test(`${features[13].name}, ${features[13].tags}`, async ({ page, baseURL }) => { const Aside = new AsideBlock(page); - console.info(`[Test Page]: ${baseURL}${features[13].path}`); + console.info(`[Test Page]: ${baseURL}${features[13].path}${miloLibs}`); await test.step('Navigate to page with Aside block', async () => { - await page.goto(`${baseURL}${features[13].path}${features[13].browserParams}`); + await page.goto(`${baseURL}${features[13].path}${features[13].browserParams}&${miloLibs}`); await page.waitForLoadState('domcontentloaded'); - await expect(page).toHaveURL(`${baseURL}${features[13].path}${features[13].browserParams}`); + await expect(page).toHaveURL(`${baseURL}${features[13].path}${features[13].browserParams}&${miloLibs}`); }); await test.step('Validate Aside block content', async () => { @@ -434,12 +436,12 @@ test.describe('Aside Block test suite', () => { // Aside Notification Medium Center: test(`${features[14].name}, ${features[14].tags}`, async ({ page, baseURL }) => { const Aside = new AsideBlock(page); - console.info(`[Test Page]: ${baseURL}${features[14].path}`); + console.info(`[Test Page]: ${baseURL}${features[14].path}${miloLibs}`); await test.step('Navigate to page with Aside block', async () => { - await page.goto(`${baseURL}${features[14].path}${features[14].browserParams}`); + await page.goto(`${baseURL}${features[14].path}${features[14].browserParams}&${miloLibs}`); await page.waitForLoadState('domcontentloaded'); - await expect(page).toHaveURL(`${baseURL}${features[14].path}${features[14].browserParams}`); + await expect(page).toHaveURL(`${baseURL}${features[14].path}${features[14].browserParams}&${miloLibs}`); }); await test.step('Validate Aside block content', async () => { @@ -464,12 +466,12 @@ test.describe('Aside Block test suite', () => { // Aside Notification Large: test(`${features[15].name}, ${features[15].tags}`, async ({ page, baseURL }) => { const Aside = new AsideBlock(page); - console.info(`[Test Page]: ${baseURL}${features[15].path}`); + console.info(`[Test Page]: ${baseURL}${features[15].path}${miloLibs}`); await test.step('Navigate to page with Aside block', async () => { - await page.goto(`${baseURL}${features[15].path}${features[15].browserParams}`); + await page.goto(`${baseURL}${features[15].path}${features[15].browserParams}&${miloLibs}`); await page.waitForLoadState('domcontentloaded'); - await expect(page).toHaveURL(`${baseURL}${features[15].path}${features[15].browserParams}`); + await expect(page).toHaveURL(`${baseURL}${features[15].path}${features[15].browserParams}&${miloLibs}`); }); await test.step('Validate Aside block content', async () => { @@ -494,12 +496,12 @@ test.describe('Aside Block test suite', () => { // Aside Notification Large Center: test(`${features[16].name}, ${features[16].tags}`, async ({ page, baseURL }) => { const Aside = new AsideBlock(page); - console.info(`[Test Page]: ${baseURL}${features[16].path}`); + console.info(`[Test Page]: ${baseURL}${features[16].path}${miloLibs}`); await test.step('Navigate to page with Aside block', async () => { - await page.goto(`${baseURL}${features[16].path}${features[16].browserParams}`); + await page.goto(`${baseURL}${features[16].path}${features[16].browserParams}&${miloLibs}`); await page.waitForLoadState('domcontentloaded'); - await expect(page).toHaveURL(`${baseURL}${features[16].path}${features[16].browserParams}`); + await expect(page).toHaveURL(`${baseURL}${features[16].path}${features[16].browserParams}&${miloLibs}`); }); await test.step('Validate Aside block content', async () => { diff --git a/tests/milo/breadcrumbs.block.test.js b/tests/milo/breadcrumbs.block.test.js index bb55cf2f..0f485e9b 100644 --- a/tests/milo/breadcrumbs.block.test.js +++ b/tests/milo/breadcrumbs.block.test.js @@ -5,16 +5,18 @@ import { expect, test } from '@playwright/test'; import { features } from '../../features/milo/breadcrumbs.block.spec.js'; import FedsHeader from '../../selectors/feds/feds.header.page.js'; +const miloLibs = process.env.MILO_LIBS || ''; + test.describe('Breadcrumbs Component Test Suite', () => { // FEDS Breadcrumbs-With-Base Checks: test(`${features[0].name}, ${features[0].tags}`, async ({ page, baseURL }) => { const Header = new FedsHeader(page); - console.info(`[FEDSInfo] Checking page: ${baseURL}${features[0].path}`); + console.info(`[FEDSInfo] Checking page: ${baseURL}${features[0].path}${miloLibs}`); await test.step('Navigate to FEDS Breadcrumbs-With-Base page', async () => { - await page.goto(`${baseURL}${features[0].path}`); + await page.goto(`${baseURL}${features[0].path}${miloLibs}`); await page.waitForLoadState('domcontentloaded'); - await expect(page).toHaveURL(`${baseURL}${features[0].path}`); + await expect(page).toHaveURL(`${baseURL}${features[0].path}${miloLibs}`); }); await test.step('Check breadcrumbs structure on current page', async () => { @@ -33,12 +35,12 @@ test.describe('Breadcrumbs Component Test Suite', () => { // FEDS Breadcrumbs-From-Document checks: test(`${features[1].name}, ${features[1].tags}`, async ({ page, baseURL }) => { const Header = new FedsHeader(page); - console.info(`[FEDSInfo] Checking page: ${baseURL}${features[1].path}`); + console.info(`[FEDSInfo] Checking page: ${baseURL}${features[1].path}${miloLibs}`); await test.step('Navigate to FEDS Breadcrumbs-From-Document page', async () => { - await page.goto(`${baseURL}${features[1].path}`); + await page.goto(`${baseURL}${features[1].path}${miloLibs}`); await page.waitForLoadState('domcontentloaded'); - await expect(page).toHaveURL(`${baseURL}${features[1].path}`); + await expect(page).toHaveURL(`${baseURL}${features[1].path}${miloLibs}`); }); await test.step('Check breadcrumbs structure on current page', async () => { @@ -57,12 +59,12 @@ test.describe('Breadcrumbs Component Test Suite', () => { // FEDS Breadcrumbs-Hidden-Links checks: test(`${features[2].name}, ${features[2].tags}`, async ({ page, baseURL }) => { const Header = new FedsHeader(page); - console.info(`[FEDSInfo] Checking page: ${baseURL}${features[2].path}`); + console.info(`[FEDSInfo] Checking page: ${baseURL}${features[2].path}${miloLibs}`); await test.step('Navigate to FEDS Breadcrumbs-Hidden-Links page', async () => { - await page.goto(`${baseURL}${features[2].path}`); + await page.goto(`${baseURL}${features[2].path}${miloLibs}`); await page.waitForLoadState('domcontentloaded'); - await expect(page).toHaveURL(`${baseURL}${features[2].path}`); + await expect(page).toHaveURL(`${baseURL}${features[2].path}${miloLibs}`); }); await test.step('Check breadcrumbs structure on current page', async () => { @@ -81,12 +83,12 @@ test.describe('Breadcrumbs Component Test Suite', () => { // FEDS Breadcrumbs-No-Hidden-Links checks: test(`${features[3].name}, ${features[3].tags}`, async ({ page, baseURL }) => { const Header = new FedsHeader(page); - console.info(`[FEDSInfo] Checking page: ${baseURL}${features[3].path}`); + console.info(`[FEDSInfo] Checking page: ${baseURL}${features[3].path}${miloLibs}`); await test.step('Navigate to FEDS Breadcrumbs-No-Hidden-Links page', async () => { - await page.goto(`${baseURL}${features[3].path}`); + await page.goto(`${baseURL}${features[3].path}${miloLibs}`); await page.waitForLoadState('domcontentloaded'); - await expect(page).toHaveURL(`${baseURL}${features[3].path}`); + await expect(page).toHaveURL(`${baseURL}${features[3].path}${miloLibs}`); }); await test.step('Check breadcrumbs structure on current page', async () => { diff --git a/tests/milo/card.block.test.js b/tests/milo/card.block.test.js index 87ed4e1a..30d92007 100644 --- a/tests/milo/card.block.test.js +++ b/tests/milo/card.block.test.js @@ -6,6 +6,8 @@ import ConsonantCard from '../../selectors/milo/card.block.page.js'; let card; let webUtil; +const miloLibs = process.env.MILO_LIBS || ''; + test.describe('Milo Consonant card feature test suite', () => { test.beforeEach(async ({ page }) => { card = new ConsonantCard(page); @@ -14,13 +16,13 @@ test.describe('Milo Consonant card feature test suite', () => { // Test 0 : Card test(`${features[0].name},${features[0].tags}`, async ({ page, baseURL }) => { - console.info(`[Test Page]: ${baseURL}${features[0].path}`); + console.info(`[Test Page]: ${baseURL}${features[0].path}${miloLibs}`); const data = features[0].data; await test.step('step-1: Go to Consonant Card feature test page', async () => { - await page.goto(`${baseURL}${features[0].path}`); + await page.goto(`${baseURL}${features[0].path}${miloLibs}`); await page.waitForLoadState('domcontentloaded'); - await expect(page).toHaveURL(`${baseURL}${features[0].path}`); + await expect(page).toHaveURL(`${baseURL}${features[0].path}${miloLibs}`); }); await test.step('step-2: Verify Card content/specs', async () => { @@ -42,13 +44,13 @@ test.describe('Milo Consonant card feature test suite', () => { // Test 1 : Card (half-card, border) test(`${features[1].name},${features[1].tags}`, async ({ page, baseURL }) => { - console.info(`[Test Page]: ${baseURL}${features[1].path}`); + console.info(`[Test Page]: ${baseURL}${features[1].path}${miloLibs}`); const data = features[1].data; await test.step('step-1: Go to Consonant Card feature test page', async () => { - await page.goto(`${baseURL}${features[1].path}`); + await page.goto(`${baseURL}${features[1].path}${miloLibs}`); await page.waitForLoadState('domcontentloaded'); - await expect(page).toHaveURL(`${baseURL}${features[1].path}`); + await expect(page).toHaveURL(`${baseURL}${features[1].path}${miloLibs}`); }); await test.step('step-2: Verify Half Card with Boarder content/specs', async () => { @@ -72,13 +74,13 @@ test.describe('Milo Consonant card feature test suite', () => { // Test 2 : card (double-width-card, border) test(`${features[2].name},${features[2].tags}`, async ({ page, baseURL }) => { - console.info(`[Test Page]: ${baseURL}${features[2].path}`); + console.info(`[Test Page]: ${baseURL}${features[2].path}${miloLibs}`); const data = features[2].data; await test.step('step-2: Go to Consonant Card feature test page', async () => { - await page.goto(`${baseURL}${features[2].path}`); + await page.goto(`${baseURL}${features[2].path}${miloLibs}`); await page.waitForLoadState('domcontentloaded'); - await expect(page).toHaveURL(`${baseURL}${features[2].path}`); + await expect(page).toHaveURL(`${baseURL}${features[2].path}${miloLibs}`); }); await test.step('step-2: Verify card (double-width-card, border) content/specs', async () => { @@ -95,13 +97,13 @@ test.describe('Milo Consonant card feature test suite', () => { // Test 3 : Card (product-card, border) test(`${features[3].name},${features[3].tags}`, async ({ page, baseURL }) => { - console.info(`[Test Page]: ${baseURL}${features[3].path}`); + console.info(`[Test Page]: ${baseURL}${features[3].path}${miloLibs}`); const data = features[3].data; await test.step('step-2: Go to Consonant Card feature test page', async () => { - await page.goto(`${baseURL}${features[3].path}`); + await page.goto(`${baseURL}${features[3].path}${miloLibs}`); await page.waitForLoadState('domcontentloaded'); - await expect(page).toHaveURL(`${baseURL}${features[3].path}`); + await expect(page).toHaveURL(`${baseURL}${features[3].path}${miloLibs}`); }); await test.step('step-2: Verify Card (product-card, border) content/specs', async () => { @@ -124,13 +126,13 @@ test.describe('Milo Consonant card feature test suite', () => { // Test 4 : Card (half-height-card, border) test(`${features[4].name},${features[4].tags}`, async ({ page, baseURL }) => { - console.info(`[Test Page]: ${baseURL}${features[4].path}`); + console.info(`[Test Page]: ${baseURL}${features[4].path}${miloLibs}`); const data = features[4].data; await test.step('step-2: Go to Consonant Card feature test page', async () => { - await page.goto(`${baseURL}${features[4].path}`); + await page.goto(`${baseURL}${features[4].path}${miloLibs}`); await page.waitForLoadState('domcontentloaded'); - await expect(page).toHaveURL(`${baseURL}${features[4].path}`); + await expect(page).toHaveURL(`${baseURL}${features[4].path}${miloLibs}`); }); await test.step('step-2: Verify Card (half-height-card, border) content/specs', async () => { @@ -147,13 +149,13 @@ test.describe('Milo Consonant card feature test suite', () => { // Test 5 : Card-horizontal test(`${features[5].name},${features[5].tags}`, async ({ page, baseURL }) => { - console.info(`[Test Page]: ${baseURL}${features[5].path}`); + console.info(`[Test Page]: ${baseURL}${features[5].path}${miloLibs}`); const data = features[5].data; await test.step('step-2: Go to Consonant Card feature test page', async () => { - await page.goto(`${baseURL}${features[5].path}`); + await page.goto(`${baseURL}${features[5].path}${miloLibs}`); await page.waitForLoadState('domcontentloaded'); - await expect(page).toHaveURL(`${baseURL}${features[5].path}`); + await expect(page).toHaveURL(`${baseURL}${features[5].path}${miloLibs}`); }); await test.step('step-2: Verify Card-horizontal content/specs', async () => { @@ -171,13 +173,13 @@ test.describe('Milo Consonant card feature test suite', () => { // Test 6 : Card-horizontal (tile) test(`${features[6].name},${features[6].tags}`, async ({ page, baseURL }) => { - console.info(`[Test Page]: ${baseURL}${features[6].path}`); + console.info(`[Test Page]: ${baseURL}${features[6].path}${miloLibs}`); const data = features[6].data; await test.step('step-2: Go to Consonant Card feature test page', async () => { - await page.goto(`${baseURL}${features[6].path}`); + await page.goto(`${baseURL}${features[6].path}${miloLibs}`); await page.waitForLoadState('domcontentloaded'); - await expect(page).toHaveURL(`${baseURL}${features[6].path}`); + await expect(page).toHaveURL(`${baseURL}${features[6].path}${miloLibs}`); }); await test.step('step-2: Verify Card-horizontal (tile) content/specs', async () => { diff --git a/tests/milo/carousel.block.test.js b/tests/milo/carousel.block.test.js index 289bb1fb..9d1d7822 100644 --- a/tests/milo/carousel.block.test.js +++ b/tests/milo/carousel.block.test.js @@ -4,18 +4,20 @@ import CarouselBlock from '../../selectors/milo/carousel.block.page.js'; let carousel; +const miloLibs = process.env.MILO_LIBS || ''; + test.describe('Milo Carousel Block test suite', () => { test.beforeEach(async ({ page }) => { carousel = new CarouselBlock(page); }); test(`${features[0].name},${features[0].tags}`, async ({ page, baseURL }) => { - console.info(`[Test Page]: ${baseURL}${features[0].path}`); + console.info(`[Test Page]: ${baseURL}${features[0].path}${miloLibs}`); await test.step('step-1: Go to Carousel block test page', async () => { - await page.goto(`${baseURL}${features[0].path}`); + await page.goto(`${baseURL}${features[0].path}${miloLibs}`); await page.waitForLoadState('domcontentloaded'); - await expect(page).toHaveURL(`${baseURL}${features[0].path}`); + await expect(page).toHaveURL(`${baseURL}${features[0].path}${miloLibs}`); }); await test.step('step-2: Verify Carousel container', async () => { @@ -50,12 +52,12 @@ test.describe('Milo Carousel Block test suite', () => { }); test(`${features[1].name},${features[1].tags}`, async ({ page, baseURL }) => { - console.info(`[Test Page]: ${baseURL}${features[0].path}`); + console.info(`[Test Page]: ${baseURL}${features[0].path}${miloLibs}`); await test.step('step-1: Go to Carousel lightbox block test page', async () => { - await page.goto(`${baseURL}${features[1].path}`); + await page.goto(`${baseURL}${features[1].path}${miloLibs}`); await page.waitForLoadState('domcontentloaded'); - await expect(page).toHaveURL(`${baseURL}${features[1].path}`); + await expect(page).toHaveURL(`${baseURL}${features[1].path}${miloLibs}`); }); await test.step('step-2: Verify carousel with lightbox features', async () => { @@ -83,12 +85,12 @@ test.describe('Milo Carousel Block test suite', () => { }); test(`${features[2].name},${features[2].tags}`, async ({ page, baseURL }) => { - console.info(`[Test Page]: ${baseURL}${features[2].path}`); + console.info(`[Test Page]: ${baseURL}${features[2].path}${miloLibs}`); await test.step('step-1: Go to Carousel multi-slide show-2 block test page', async () => { - await page.goto(`${baseURL}${features[2].path}`); + await page.goto(`${baseURL}${features[2].path}${miloLibs}`); await page.waitForLoadState('domcontentloaded'); - await expect(page).toHaveURL(`${baseURL}${features[2].path}`); + await expect(page).toHaveURL(`${baseURL}${features[2].path}${miloLibs}`); }); await test.step('step-2: Verify multi slide carousel show-2 features', async () => { diff --git a/tests/milo/chart.block.test.js b/tests/milo/chart.block.test.js index 3c108ca2..e50ccf48 100644 --- a/tests/milo/chart.block.test.js +++ b/tests/milo/chart.block.test.js @@ -3,6 +3,7 @@ import { features } from '../../features/milo/chart.block.spec.js'; import ChartBlock from '../../selectors/milo/chart.block.page.js'; let chart; +const miloLibs = process.env.MILO_LIBS || ''; test.describe('Milo Chart feature test suite', () => { test.beforeEach(async ({ page }) => { diff --git a/tests/milo/columns.block.test.js b/tests/milo/columns.block.test.js index 6e6d035c..de2c144f 100644 --- a/tests/milo/columns.block.test.js +++ b/tests/milo/columns.block.test.js @@ -7,6 +7,8 @@ import ColumnsBlock from '../../selectors/milo/columns.block.page.js'; let column; let webUtil; +const miloLibs = process.env.MILO_LIBS || ''; + test.describe('Milo Columns Block test suite', () => { test.beforeEach(async ({ page }) => { column = new ColumnsBlock(page); @@ -15,13 +17,13 @@ test.describe('Milo Columns Block test suite', () => { // Test 0 : Column default block test(`${features[0].name},${features[0].tags}`, async ({ page, baseURL }) => { - console.info(`[Test Page]: ${baseURL}${features[0].path}`); + console.info(`[Test Page]: ${baseURL}${features[0].path}${miloLibs}`); const { data } = features[0]; await test.step('step-1: Go to Columns block test page', async () => { - await page.goto(`${baseURL}${features[0].path}`); + await page.goto(`${baseURL}${features[0].path}${miloLibs}`); await page.waitForLoadState('domcontentloaded'); - await expect(page).toHaveURL(`${baseURL}${features[0].path}`); + await expect(page).toHaveURL(`${baseURL}${features[0].path}${miloLibs}`); }); await test.step('step-2: Verify Columns block content/specs', async () => { @@ -43,13 +45,13 @@ test.describe('Milo Columns Block test suite', () => { // Test 1 : Columns (contained) block test(`${features[1].name},${features[1].tags}`, async ({ page, baseURL }) => { - console.info(`[Test Page]: ${baseURL}${features[1].path}`); + console.info(`[Test Page]: ${baseURL}${features[1].path}${miloLibs}`); const { data } = features[1]; await test.step('step-1: Go to Columns block test page', async () => { - await page.goto(`${baseURL}${features[1].path}`); + await page.goto(`${baseURL}${features[1].path}${miloLibs}`); await page.waitForLoadState('domcontentloaded'); - await expect(page).toHaveURL(`${baseURL}${features[1].path}`); + await expect(page).toHaveURL(`${baseURL}${features[1].path}${miloLibs}`); }); await test.step('step-2: Verify Columns(contained) block content/specs', async () => { @@ -70,13 +72,13 @@ test.describe('Milo Columns Block test suite', () => { // Test 2 : Columns (contained,middle) block test(`${features[2].name},${features[2].tags}`, async ({ page, baseURL }) => { - console.info(`[Test Page]: ${baseURL}${features[2].path}`); + console.info(`[Test Page]: ${baseURL}${features[2].path}${miloLibs}`); const { data } = features[2]; await test.step('step-1: Go to Columns block test page', async () => { - await page.goto(`${baseURL}${features[2].path}`); + await page.goto(`${baseURL}${features[2].path}${miloLibs}`); await page.waitForLoadState('domcontentloaded'); - await expect(page).toHaveURL(`${baseURL}${features[2].path}`); + await expect(page).toHaveURL(`${baseURL}${features[2].path}${miloLibs}`); }); await test.step('step-2: Verify Columns(contained,middle) block content/specs', async () => { @@ -97,13 +99,13 @@ test.describe('Milo Columns Block test suite', () => { // Test 3 : Columns (table) block test(`${features[3].name},${features[3].tags}`, async ({ page, baseURL }) => { - console.info(`[Test Page]: ${baseURL}${features[3].path}`); + console.info(`[Test Page]: ${baseURL}${features[3].path}${miloLibs}`); const { data } = features[3]; await test.step('step-1: Go to Columns block test page', async () => { - await page.goto(`${baseURL}${features[3].path}`); + await page.goto(`${baseURL}${features[3].path}${miloLibs}`); await page.waitForLoadState('domcontentloaded'); - await expect(page).toHaveURL(`${baseURL}${features[3].path}`); + await expect(page).toHaveURL(`${baseURL}${features[3].path}${miloLibs}`); }); await test.step('step-2: Verify Columns(table) block content/specs', async () => { @@ -128,13 +130,13 @@ test.describe('Milo Columns Block test suite', () => { // Test 4 : Columns (contained,table) block test(`${features[4].name},${features[4].tags}`, async ({ page, baseURL }) => { - console.info(`[Test Page]: ${baseURL}${features[4].path}`); + console.info(`[Test Page]: ${baseURL}${features[4].path}${miloLibs}`); const { data } = features[4]; await test.step('step-1: Go to Columns block test page', async () => { - await page.goto(`${baseURL}${features[4].path}`); + await page.goto(`${baseURL}${features[4].path}${miloLibs}`); await page.waitForLoadState('domcontentloaded'); - await expect(page).toHaveURL(`${baseURL}${features[4].path}`); + await expect(page).toHaveURL(`${baseURL}${features[4].path}${miloLibs}`); }); await test.step('step-2: Verify Columns(contained,table) block content/specs', async () => { diff --git a/tests/milo/figure.block.test.js b/tests/milo/figure.block.test.js index cfccb8ad..07e52607 100644 --- a/tests/milo/figure.block.test.js +++ b/tests/milo/figure.block.test.js @@ -4,18 +4,20 @@ import FigureBlock from '../../selectors/milo/figure.block.page.js'; let figureBlock; +const miloLibs = process.env.MILO_LIBS || ''; + test.describe('Milo Figure Block test suite', () => { test.beforeEach(async ({ page }) => { figureBlock = new FigureBlock(page); }); test(`${features[0].name},${features[0].tags}`, async ({ page, baseURL }) => { - console.info(`[Test Page]: ${baseURL}${features[0].path}`); + console.info(`[Test Page]: ${baseURL}${features[0].path}${miloLibs}`); await test.step('step-1: Go to figure Block test page', async () => { - await page.goto(`${baseURL}${features[0].path}`); + await page.goto(`${baseURL}${features[0].path}${miloLibs}`); await page.waitForLoadState('domcontentloaded'); - await expect(page).toHaveURL(`${baseURL}${features[0].path}`); + await expect(page).toHaveURL(`${baseURL}${features[0].path}${miloLibs}`); }); await test.step('step-2: Verify figure block ', async () => { @@ -27,12 +29,12 @@ test.describe('Milo Figure Block test suite', () => { }); test(`${features[1].name},${features[1].tags}`, async ({ page, baseURL }) => { - console.info(`[Test Page]: ${baseURL}${features[1].path}`); + console.info(`[Test Page]: ${baseURL}${features[1].path}${miloLibs}`); await test.step('step-1: Go to figure block test page', async () => { - await page.goto(`${baseURL}${features[1].path}`); + await page.goto(`${baseURL}${features[1].path}${miloLibs}`); await page.waitForLoadState('domcontentloaded'); - await expect(page).toHaveURL(`${baseURL}${features[1].path}`); + await expect(page).toHaveURL(`${baseURL}${features[1].path}${miloLibs}`); }); await test.step('step-2: Verify figure block multiple images with caption ', async () => { diff --git a/tests/milo/footer.block.test.js b/tests/milo/footer.block.test.js index 7c22019e..418b0b90 100644 --- a/tests/milo/footer.block.test.js +++ b/tests/milo/footer.block.test.js @@ -5,16 +5,18 @@ import { expect, test } from '@playwright/test'; import { features } from '../../features/milo/footer.block.spec.js'; import FedsFooter from '../../selectors/feds/feds.footer.page.js'; +const miloLibs = process.env.MILO_LIBS || ''; + test.describe('Footer Block Test Suite', () => { // FEDS Default Footer Checks: test(`${features[0].name}, ${features[0].tags}`, async ({ page, baseURL }) => { const Footer = new FedsFooter(page); - console.info(`[FEDSInfo] Checking page: ${baseURL}${features[0].path}`); + console.info(`[FEDSInfo] Checking page: ${baseURL}${features[0].path}${miloLibs}`); await test.step('Navigate to FEDS Default Footer page', async () => { - await page.goto(`${baseURL}${features[0].path}`); + await page.goto(`${baseURL}${features[0].path}${miloLibs}`); await page.waitForLoadState('domcontentloaded'); - await expect(page).toHaveURL(`${baseURL}${features[0].path}`); + await expect(page).toHaveURL(`${baseURL}${features[0].path}${miloLibs}`); }); await test.step('Check FEDS Default Footer critical elements', async () => { @@ -30,8 +32,12 @@ test.describe('Footer Block Test Suite', () => { // !Note: Footer featuredProducts not appearing in NALA. Possible BUG! // await expect(Footer.featuredProductsContainer).toBeVisible(); await expect(Footer.footerColumns).toHaveCount(5); - await expect(Footer.footerSections).toHaveCount(6); - await expect(Footer.footerHeadings).toHaveCount(6); + + // updated the footer section and heading content as per consuming sites + // milo=6, cc=9 and so on + await expect([4, 6, 9].includes(await Footer.footerSections.count())).toBeTruthy(); + await expect([4, 6, 9].includes(await Footer.footerHeadings.count())).toBeTruthy(); + await expect(Footer.socialIcons).toHaveCount(4); await expect(Footer.legalLinks).toHaveCount(5); }); @@ -47,12 +53,12 @@ test.describe('Footer Block Test Suite', () => { // FEDS Skinny Footer Checks: test(`${features[1].name}, ${features[1].tags}`, async ({ page, baseURL }) => { const Footer = new FedsFooter(page); - console.info(`[FEDSInfo] Checking page: ${baseURL}${features[1].path}`); + console.info(`[FEDSInfo] Checking page: ${baseURL}${features[1].path}${miloLibs}`); await test.step('Navigate to FEDS Skinny Footer page', async () => { - await page.goto(`${baseURL}${features[1].path}`); + await page.goto(`${baseURL}${features[1].path}${miloLibs}`); await page.waitForLoadState('domcontentloaded'); - await expect(page).toHaveURL(`${baseURL}${features[1].path}`); + await expect(page).toHaveURL(`${baseURL}${features[1].path}${miloLibs}`); }); await test.step('Check FEDS Skinny Footer critical elements', async () => { @@ -66,18 +72,38 @@ test.describe('Footer Block Test Suite', () => { await expect(Footer.footerContainer).toBeVisible(); await expect(Footer.changeRegionContainer).toBeVisible(); - await expect(Footer.featuredProducts).toHaveCount(0); - await expect(Footer.featuredProductsContainer).not.toBeVisible(); + //await expect(Footer.featuredProducts).toHaveCount(0); + // updated the featuredProducts count as per consuming sites + // milo=0, cc=4 and so on + expect([0, 4].includes(await Footer.featuredProducts.count())).toBeTruthy(); + + const featuredProductsCount = await Footer.featuredProducts.count(); + + if (featuredProductsCount === 0) { + await expect(Footer.featuredProductsContainer).not.toBeVisible(); + } else { + await expect(Footer.featuredProductsContainer).toBeVisible(); + } await expect(Footer.legalLinks).toHaveCount(5); await expect(Footer.socialIcons).toHaveCount(4); - await expect(Footer.footerColumns).toHaveCount(0); - await expect(Footer.footerSections).toHaveCount(0); - await expect(Footer.footerHeadings).toHaveCount(0); - await expect(Footer.footerColumns).not.toBeVisible(); - await expect(Footer.footerSections).not.toBeVisible(); - await expect(Footer.footerHeadings).not.toBeVisible(); + //await expect(Footer.footerColumns).toHaveCount(0); + //await expect(Footer.footerSections).toHaveCount(0); + //await expect(Footer.footerHeadings).toHaveCount(0); + + const footerSectionsCount = await Footer.featuredProducts.count(); + + if (footerSectionsCount === 0) { + await expect(Footer.footerColumns).not.toBeVisible(); + await expect(Footer.footerSections).not.toBeVisible(); + await expect(Footer.footerHeadings).not.toBeVisible(); + } else { + expect([0, 5].includes(await Footer.footerColumns.count())).toBeTruthy(); + expect([4, 6, 9].includes(await Footer.footerSections.count())).toBeTruthy(); + expect([4, 6, 9].includes(await Footer.footerHeadings.count())).toBeTruthy(); + } + }); await test.step('Check ChangeRegion functionality', async () => { @@ -91,12 +117,12 @@ test.describe('Footer Block Test Suite', () => { // FEDS Privacy Footer Checks: test(`${features[2].name}, ${features[2].tags}`, async ({ page, baseURL }) => { const Footer = new FedsFooter(page); - console.info(`[FEDSInfo] Checking page: ${baseURL}${features[2].path}`); + console.info(`[FEDSInfo] Checking page: ${baseURL}${features[2].path}${miloLibs}`); await test.step('Navigate to FEDS Privacy Footer page', async () => { - await page.goto(`${baseURL}${features[2].path}`); + await page.goto(`${baseURL}${features[2].path}${miloLibs}`); await page.waitForLoadState('domcontentloaded'); - await expect(page).toHaveURL(`${baseURL}${features[2].path}`); + await expect(page).toHaveURL(`${baseURL}${features[2].path}${miloLibs}`); }); await test.step('Check FEDS Privacy Footer critical elements', async () => { @@ -112,13 +138,23 @@ test.describe('Footer Block Test Suite', () => { await expect(Footer.featuredProductsContainer).toBeVisible(); await expect(Footer.footerColumns).toHaveCount(5); - await expect(Footer.footerSections).toHaveCount(6); - await expect(Footer.footerHeadings).toHaveCount(6); - await expect(Footer.featuredProducts).toHaveCount(3); - await expect(Footer.legalSections).toHaveCount(2); + //await expect(Footer.footerSections).toHaveCount(9) + //await expect(Footer.footerHeadings).toHaveCount(9) + //await expect(Footer.featuredProducts).toHaveCount(3); + //await expect(Footer.legalSections).toHaveCount(2); await expect(Footer.socialIcons).toHaveCount(4); await expect(Footer.legalLinks).toHaveCount(5); + + // updated the footer section and heading content equal or greater + // than 6, to pass tests on cc pages. + expect([4, 6, 9].includes(await Footer.footerSections.count())).toBeTruthy(); + expect([4, 6, 9].includes(await Footer.footerHeadings.count())).toBeTruthy(); + expect([3, 4].includes(await Footer.featuredProducts.count())).toBeTruthy(); + expect([1, 2].includes(await Footer.legalSections.count())).toBeTruthy(); + expect([4].includes(await Footer.socialIcons.count())).toBeTruthy(); + expect([5].includes(await Footer.legalLinks.count())).toBeTruthy(); + }); await test.step('Check ChangeRegion functionality', async () => { diff --git a/tests/milo/georouting.feature.test.js b/tests/milo/georouting.feature.test.js index 4a42a428..534185a9 100644 --- a/tests/milo/georouting.feature.test.js +++ b/tests/milo/georouting.feature.test.js @@ -4,6 +4,8 @@ import Georouting from '../../selectors/milo/georouting.feature.page.js'; let modal; +const miloLibs = process.env.MILO_LIBS || ''; + test.describe('Milo Georouting feature test suite', () => { test.beforeEach(async ({ page }) => { modal = new Georouting(page); @@ -12,14 +14,14 @@ test.describe('Milo Georouting feature test suite', () => { test(`${features[0].name},${features[0].tags}`, async ({ page, baseURL, browserName }) => { test.skip(browserName === 'webkit', 'This feature is failing on Webkit browsers'); test.slow(); - console.info(`[Test Page]: ${baseURL}${features[0].path}`); + console.info(`[Test Page]: ${baseURL}${features[0].path}${miloLibs}`); const { data } = features[0]; await test.step('step-1: Clear cookies and access "DE" page from "US" region', async () => { await page.context().clearCookies(); - await page.goto(`${baseURL}${features[0].path}`); + await page.goto(`${baseURL}${features[0].path}${miloLibs}`); await page.waitForLoadState('domcontentloaded'); - await expect(page).toHaveURL(`${baseURL}${features[0].path}`); + await expect(page).toHaveURL(`${baseURL}${features[0].path}${miloLibs}`); await modal.geoModal.waitFor({ state: 'visible', timeout: 30000 }); }); @@ -36,14 +38,14 @@ test.describe('Milo Georouting feature test suite', () => { test(`${features[1].name},${features[1].tags}`, async ({ page, baseURL }) => { test.slow(); - console.info(`[Test Page]: ${baseURL}${features[1].path}`); + console.info(`[Test Page]: ${baseURL}${features[1].path}&${miloLibs}`); const { data } = features[1]; await test.step('step-1: Clear cookies and access "US" page with query param (akamailLocale=DE)', async () => { await page.context().clearCookies(); - await page.goto(`${baseURL}${features[1].path}`); + await page.goto(`${baseURL}${features[1].path}&${miloLibs}`); await page.waitForLoadState('domcontentloaded'); - await expect(page).toHaveURL(`${baseURL}${features[1].path}`); + await expect(page).toHaveURL(`${baseURL}${features[1].path}&${miloLibs}`); await modal.geoModal.waitFor({ state: 'visible', timeout: 10000 }); }); @@ -59,14 +61,14 @@ test.describe('Milo Georouting feature test suite', () => { test(`${features[2].name},${features[2].tags}`, async ({ page, baseURL }) => { test.slow(); - console.info(`[Test Page]: ${baseURL}${features[2].path}`); + console.info(`[Test Page]: ${baseURL}${features[2].path}${miloLibs}`); const { data } = features[2]; await test.step('step-1: Clear cookies and access "US" page', async () => { await page.context().clearCookies(); - await page.goto(`${baseURL}${features[2].path}`); + await page.goto(`${baseURL}${features[2].path}${miloLibs}`); await page.waitForLoadState('domcontentloaded'); - await expect(page).toHaveURL(`${baseURL}${features[2].path}`); + await expect(page).toHaveURL(`${baseURL}${features[2].path}${miloLibs}`); }); await test.step('step-2: Click "Change region" link from footer and navigate to "Deutschland" page', async () => { @@ -82,14 +84,14 @@ test.describe('Milo Georouting feature test suite', () => { test(`${features[3].name},${features[3].tags}`, async ({ page, baseURL }) => { test.slow(); - console.info(`[Test Page]: ${baseURL}${features[3].path}`); + console.info(`[Test Page]: ${baseURL}${features[3].path}&${miloLibs}`); const { data } = features[3]; await test.step('step-1: Clear cookies and access "US" page', async () => { await page.context().clearCookies(); - await page.goto(`${baseURL}${features[3].path}`); + await page.goto(`${baseURL}${features[3].path}&${miloLibs}`); await page.waitForLoadState('domcontentloaded'); - await expect(page).toHaveURL(`${baseURL}${features[3].path}`); + await expect(page).toHaveURL(`${baseURL}${features[3].path}&${miloLibs}`); await modal.geoModal.waitFor({ state: 'visible', timeout: 10000 }); }); @@ -99,14 +101,14 @@ test.describe('Milo Georouting feature test suite', () => { }); test(`${features[4].name},${features[4].tags}`, async ({ page, baseURL }) => { - console.info(`[Test Page]: ${baseURL}${features[4].path}`); + console.info(`[Test Page]: ${baseURL}${features[4].path}${miloLibs}`); const { data } = features[4]; await test.step('step-1: Clear cookies and access given "DE" page', async () => { await page.context().clearCookies(); - await page.goto(`${baseURL}${features[4].path}`); + await page.goto(`${baseURL}${features[4].path}${miloLibs}`); await page.waitForLoadState('domcontentloaded'); - await expect(page).toHaveURL(`${baseURL}${features[4].path}`); + await expect(page).toHaveURL(`${baseURL}${features[4].path}${miloLibs}`); }); await test.step('step-2: Verify that georouting modal is not shown', async () => { @@ -117,14 +119,14 @@ test.describe('Milo Georouting feature test suite', () => { test(`${features[5].name},${features[5].tags}`, async ({ page, browserName, baseURL }) => { test.skip(browserName === 'webkit', 'This feature is failing on Webkit browsers'); test.slow(); - console.info(`[Test Page]: ${baseURL}${features[5].path}`); + console.info(`[Test Page]: ${baseURL}${features[5].path}${miloLibs}`); const { data } = features[5]; await test.step('step-1: Clear cookies and access given "DE" page', async () => { await page.context().clearCookies(); - await page.goto(`${baseURL}${features[5].path}`); + await page.goto(`${baseURL}${features[5].path}${miloLibs}`); await page.waitForLoadState('domcontentloaded'); - await expect(page).toHaveURL(`${baseURL}${features[5].path}`); + await expect(page).toHaveURL(`${baseURL}${features[5].path}${miloLibs}`); await modal.geoModal.waitFor({ state: 'visible', timeout: 10000 }); }); diff --git a/tests/milo/header.block.test.js b/tests/milo/header.block.test.js index 946d7866..618fded6 100644 --- a/tests/milo/header.block.test.js +++ b/tests/milo/header.block.test.js @@ -5,16 +5,18 @@ import { expect, test } from '@playwright/test'; import { features } from '../../features/milo/header.block.spec.js'; import FedsHeader from '../../selectors/feds/feds.header.page.js'; +const miloLibs = process.env.MILO_LIBS || ''; + test.describe('Header Block Test Suite', () => { // FEDS Default Header Checks: test(`${features[0].name}, ${features[0].tags}`, async ({ page, baseURL }) => { const Header = new FedsHeader(page); - console.info(`[FEDSInfo] Checking page: ${baseURL}${features[0].path}`); + console.info(`[FEDSInfo] Checking page: ${baseURL}${features[0].path}${miloLibs}`); await test.step('Navigate to FEDS HEADER page', async () => { - await page.goto(`${baseURL}${features[0].path}`); + await page.goto(`${baseURL}${features[0].path}${miloLibs}`); await page.waitForLoadState('domcontentloaded'); - await expect(page).toHaveURL(`${baseURL}${features[0].path}`); + await expect(page).toHaveURL(`${baseURL}${features[0].path}${miloLibs}`); }); await test.step('Check HEADER block content', async () => { @@ -22,17 +24,25 @@ test.describe('Header Block Test Suite', () => { await Header.mainNavContainer.waitFor({ state: 'visible', timeout: 5000 }); // Check HEADER block content: await expect(Header.mainNavLogo).toBeVisible(); - await expect(Header.searchIcon).toBeVisible(); - + //skipping the step for PR branch runs - // working on better workaround soloution - + // working on better workaround soloution // await expect(Header.signInButton).toBeVisible(); }); await test.step('Check HEADER search component', async () => { - await Header.openSearchBar(); - await Header.closeSearchBar(); + + // adding the below check to accommodate testing on consuming sites + const isSearchIconVisible = await Header.searchIcon.isVisible(); + if (isSearchIconVisible) { + await test.step('Check HEADER search component', async () => { + await Header.openSearchBar(); + await Header.closeSearchBar(); + }); + } else { + console.info('Search icon is not visible, skipping the search component test.'); + } + }); await test.step('Check HEADER block mega menu component', async () => { diff --git a/tests/milo/howto.block.test.js b/tests/milo/howto.block.test.js index 4bf36f0f..a4597141 100644 --- a/tests/milo/howto.block.test.js +++ b/tests/milo/howto.block.test.js @@ -6,6 +6,8 @@ import HowToBlock from '../../selectors/milo/howto.block.page.js'; let webUtil; let howTo; +const miloLibs = process.env.MILO_LIBS || ''; + test.describe('Milo HowTo block test suite', () => { test.beforeEach(async ({ page }) => { webUtil = new WebUtil(page); @@ -14,12 +16,12 @@ test.describe('Milo HowTo block test suite', () => { // Test 0 : HowTo default block test(`${features[0].name},${features[0].tags}`, async ({ page, baseURL }) => { - console.info(`[Test Page]: ${baseURL}${features[0].path}`); + console.info(`[Test Page]: ${baseURL}${features[0].path}${miloLibs}`); await test.step('step-1: Go to HowTo block test page', async () => { - await page.goto(`${baseURL}${features[0].path}`); + await page.goto(`${baseURL}${features[0].path}${miloLibs}`); await page.waitForLoadState('domcontentloaded'); - await expect(page).toHaveURL(`${baseURL}${features[0].path}`); + await expect(page).toHaveURL(`${baseURL}${features[0].path}${miloLibs}`); }); await test.step('step-2: Verify HowTo specs', async () => { @@ -34,12 +36,12 @@ test.describe('Milo HowTo block test suite', () => { // Test 1 : how-to (large) block test(`${features[1].name},${features[1].tags}`, async ({ page, baseURL }) => { - console.info(`[Test Page]: ${baseURL}${features[1].path}`); + console.info(`[Test Page]: ${baseURL}${features[1].path}${miloLibs}`); await test.step('step-1: Go to HowTo large block test page', async () => { - await page.goto(`${baseURL}${features[1].path}`); + await page.goto(`${baseURL}${features[1].path}${miloLibs}`); await page.waitForLoadState('domcontentloaded'); - await expect(page).toHaveURL(`${baseURL}${features[1].path}`); + await expect(page).toHaveURL(`${baseURL}${features[1].path}${miloLibs}`); }); await test.step('step-2: Verify HowTo large specs', async () => { @@ -54,12 +56,12 @@ test.describe('Milo HowTo block test suite', () => { // Test 2 : how-to (seo) block test(`${features[2].name},${features[2].tags}`, async ({ page, baseURL }) => { - console.info(`[Test Page]: ${baseURL}${features[2].path}`); + console.info(`[Test Page]: ${baseURL}${features[2].path}${miloLibs}`); await test.step('step-1: Go to HowTo SEO block test page', async () => { - await page.goto(`${baseURL}${features[2].path}`); + await page.goto(`${baseURL}${features[2].path}${miloLibs}`); await page.waitForLoadState('domcontentloaded'); - await expect(page).toHaveURL(`${baseURL}${features[2].path}`); + await expect(page).toHaveURL(`${baseURL}${features[2].path}${miloLibs}`); }); await test.step('step-2: Verify HowTo SEO specs', async () => { diff --git a/tests/milo/htmlextn.feature.test.js b/tests/milo/htmlextn.feature.test.js index 1669d2e2..8673e6c7 100644 --- a/tests/milo/htmlextn.feature.test.js +++ b/tests/milo/htmlextn.feature.test.js @@ -2,6 +2,7 @@ import { expect, test } from '@playwright/test'; import { features } from '../../features/milo/htmlextn.spec.js' const envList = require('../../envs/envs.js'); +const miloLibs = process.env.MILO_LIBS || ''; test.describe('Milo Html Extension feature test suite', () => { @@ -14,7 +15,8 @@ test.describe('Milo Html Extension feature test suite', () => { for (const path of paths) { console.info('[Test Page]\n:', envList[env]+`${path}`); const url = envList[env]+ path; - await page.goto(url); + await page.goto(url); + await page.waitForLoadState('domcontentloaded'); if (!page.url().match(/@blog/) && (page.url().match(/customer-success-stories/))) { expect(page.url()).toContain('.html'); @@ -35,6 +37,7 @@ test.describe('Milo Html Extension feature test suite', () => { console.info('[Test Page]\n:', envList[env]+`${path}`); const url = envList[env]+ path; await page.goto(url); + await page.waitForLoadState('domcontentloaded'); if (!page.url().match(/@blog/) && (page.url().match(/customer-success-stories/))) { expect(page.url()).toContain('.html'); diff --git a/tests/milo/icon.block.test.js b/tests/milo/icon.block.test.js index 41ac1ad8..92f1f122 100644 --- a/tests/milo/icon.block.test.js +++ b/tests/milo/icon.block.test.js @@ -4,18 +4,20 @@ import IconBlock from '../../selectors/milo/icon.block.page.js'; let icon; +const miloLibs = process.env.MILO_LIBS || ''; + test.describe('Milo Icon Block test suite', () => { test.beforeEach(async ({ page }) => { icon = new IconBlock(page); }); test(`${features[0].name},${features[0].tags}`, async ({ page, baseURL }) => { - console.info(`[Test Page]: ${baseURL}${features[0].path}`); + console.info(`[Test Page]: ${baseURL}${features[0].path}${miloLibs}`); await test.step('step-1: Go to Icon block test page', async () => { - await page.goto(`${baseURL}${features[0].path}`); + await page.goto(`${baseURL}${features[0].path}${miloLibs}`); await page.waitForLoadState('domcontentloaded'); - await expect(page).toHaveURL(`${baseURL}${features[0].path}`); + await expect(page).toHaveURL(`${baseURL}${features[0].path}${miloLibs}`); }); await test.step('step-2: Verify Icon block content/specs', async () => { @@ -25,12 +27,12 @@ test.describe('Milo Icon Block test suite', () => { }); test(`${features[1].name},${features[1].tags}`, async ({ page, baseURL }) => { - console.info(`[Test Page]: ${baseURL}${features[1].path}`); + console.info(`[Test Page]: ${baseURL}${features[1].path}${miloLibs}`); await test.step('step-1: Go to Icon block test page', async () => { - await page.goto(`${baseURL}${features[1].path}`); + await page.goto(`${baseURL}${features[1].path}${miloLibs}`); await page.waitForLoadState('domcontentloaded'); - await expect(page).toHaveURL(`${baseURL}${features[1].path}`); + await expect(page).toHaveURL(`${baseURL}${features[1].path}${miloLibs}`); }); await test.step('step-2: Verify Icon block content/specs', async () => { @@ -40,12 +42,12 @@ test.describe('Milo Icon Block test suite', () => { }); test(`${features[2].name},${features[2].tags}`, async ({ page, baseURL }) => { - console.info(`[Test Page]: ${baseURL}${features[2].path}`); + console.info(`[Test Page]: ${baseURL}${features[2].path}${miloLibs}`); await test.step('step-1: Go to Icon block test page', async () => { - await page.goto(`${baseURL}${features[2].path}`); + await page.goto(`${baseURL}${features[2].path}${miloLibs}`); await page.waitForLoadState('domcontentloaded'); - await expect(page).toHaveURL(`${baseURL}${features[2].path}`); + await expect(page).toHaveURL(`${baseURL}${features[2].path}${miloLibs}`); }); await test.step('step-2: Verify Icon block content/specs', async () => { diff --git a/tests/milo/iframe.block.test.js b/tests/milo/iframe.block.test.js index ea36b87d..80215fa7 100644 --- a/tests/milo/iframe.block.test.js +++ b/tests/milo/iframe.block.test.js @@ -2,16 +2,18 @@ import { expect, test } from '@playwright/test'; import { features } from '../../features/milo/iframe.block.spec.js'; import IframeBlock from '../../selectors/milo/iframe.block.page.js'; +const miloLibs = process.env.MILO_LIBS || ''; + test.describe('Iframe Block test suite', () => { // Iframe Block Checks: test(`${features[0].name}, ${features[0].tags}`, async ({ page, baseURL }) => { const Iframe = new IframeBlock(page); - console.info(`[Test Page]: ${baseURL}${features[0].path}`); + console.info(`[Test Page]: ${baseURL}${features[0].path}${miloLibs}`); await test.step('Navigate to page with Iframe block', async () => { - await page.goto(`${baseURL}${features[0].path}${features[0].browserParams}`); + await page.goto(`${baseURL}${features[0].path}${features[0].browserParams}&${miloLibs}`); await page.waitForLoadState('domcontentloaded'); - await expect(page).toHaveURL(`${baseURL}${features[0].path}${features[0].browserParams}`); + await expect(page).toHaveURL(`${baseURL}${features[0].path}${features[0].browserParams}&${miloLibs}`); }); await test.step('Validate Iframe block content', async () => { diff --git a/tests/milo/marquee.block.test.js b/tests/milo/marquee.block.test.js index 7439fe65..6aef8ac8 100644 --- a/tests/milo/marquee.block.test.js +++ b/tests/milo/marquee.block.test.js @@ -6,6 +6,8 @@ import MarqueeBlock from '../../selectors/milo/marquee.block.page.js'; let webUtil; let marquee; let consoleErrors = []; + +const miloLibs = process.env.MILO_LIBS || ''; const knownConsoleErrors = ['Access-Control-Allow-Origin','Failed to load resource: net::ERR_FAILED','adobeid-na1-stg1.services']; test.describe('Milo Marquee Block test suite', () => { @@ -26,13 +28,13 @@ test.describe('Milo Marquee Block test suite', () => { // Test 0 : Marquee (light) test(`${features[0].name},${features[0].tags}`, async ({ page, baseURL }) => { - console.info(`[Test Page]: ${baseURL}${features[0].path}`); + console.info(`[Test Page]: ${baseURL}${features[0].path}${miloLibs}`); const { data } = features[0]; await test.step('step-1: Go to Marquee (light) block test page', async () => { - await page.goto(`${baseURL}${features[0].path}`); + await page.goto(`${baseURL}${features[0].path}${miloLibs}`); await page.waitForLoadState('domcontentloaded'); - await expect(page).toHaveURL(`${baseURL}${features[0].path}`); + await expect(page).toHaveURL(`${baseURL}${features[0].path}${miloLibs}`); }); await test.step('step-2: Verify marquee(light) specs', async () => { @@ -61,13 +63,13 @@ test.describe('Milo Marquee Block test suite', () => { // Test 1 : Marquee (small) test(`${features[1].name},${features[1].tags}`, async ({ page, baseURL }) => { - console.info(`[Test Page]: ${baseURL}${features[1].path}`); + console.info(`[Test Page]: ${baseURL}${features[1].path}${miloLibs}`); const { data } = features[1]; await test.step('step-1: Go to Marquee (small) block test page', async () => { - await page.goto(`${baseURL}${features[1].path}`); + await page.goto(`${baseURL}${features[1].path}${miloLibs}`); await page.waitForLoadState('domcontentloaded'); - await expect(page).toHaveURL(`${baseURL}${features[1].path}`); + await expect(page).toHaveURL(`${baseURL}${features[1].path}${miloLibs}`); }); await test.step('step-2: Verify Marquee (small) specs', async () => { @@ -94,13 +96,13 @@ test.describe('Milo Marquee Block test suite', () => { // Test 2 : Marquee (small,light) test(`${features[2].name},${features[2].tags}`, async ({ page, baseURL }) => { - console.info(`[Test Page]: ${baseURL}${features[2].path}`); + console.info(`[Test Page]: ${baseURL}${features[2].path}${miloLibs}`); const { data } = features[2]; await test.step('step-1: Go to Marquee (small, light ) block test page', async () => { - await page.goto(`${baseURL}${features[2].path}`); + await page.goto(`${baseURL}${features[2].path}${miloLibs}`); await page.waitForLoadState('domcontentloaded'); - await expect(page).toHaveURL(`${baseURL}${features[2].path}`); + await expect(page).toHaveURL(`${baseURL}${features[2].path}${miloLibs}`); }); await test.step('step-2: Verify Marquee (small, light) specs', async () => { @@ -130,13 +132,13 @@ test.describe('Milo Marquee Block test suite', () => { // Test 3 : Marquee (large) test(`${features[3].name},${features[3].tags}`, async ({ page, baseURL }) => { - console.info(`[Test Page]: ${baseURL}${features[3].path}`); + console.info(`[Test Page]: ${baseURL}${features[3].path}${miloLibs}`); const { data } = features[3]; await test.step('step-1: Go to Marquee (large ) block test page', async () => { - await page.goto(`${baseURL}${features[3].path}`); + await page.goto(`${baseURL}${features[3].path}${miloLibs}`); await page.waitForLoadState('domcontentloaded'); - await expect(page).toHaveURL(`${baseURL}${features[3].path}`); + await expect(page).toHaveURL(`${baseURL}${features[3].path}${miloLibs}`); }); await test.step('step-2: Verify Marquee (large) specs', async () => { @@ -165,13 +167,13 @@ test.describe('Milo Marquee Block test suite', () => { // Test 4 : Marquee (large,light) test(`${features[4].name},${features[4].tags}`, async ({ page, baseURL }) => { - console.info(`[Test Page]: ${baseURL}${features[4].path}`); + console.info(`[Test Page]: ${baseURL}${features[4].path}${miloLibs}`); const { data } = features[4]; await test.step('step-1: Go to Marquee (large, light ) block test page', async () => { - await page.goto(`${baseURL}${features[4].path}`); + await page.goto(`${baseURL}${features[4].path}${miloLibs}`); await page.waitForLoadState('domcontentloaded'); - await expect(page).toHaveURL(`${baseURL}${features[4].path}`); + await expect(page).toHaveURL(`${baseURL}${features[4].path}${miloLibs}`); }); await test.step('step-2: Verify Marquee (large, light) specs', async () => { @@ -200,13 +202,13 @@ test.describe('Milo Marquee Block test suite', () => { // Test 5 : Marquee (quiet) test(`${features[5].name},${features[5].tags}`, async ({ page, baseURL }) => { - console.info(`[Test Page]: ${baseURL}${features[5].path}`); + console.info(`[Test Page]: ${baseURL}${features[5].path}${miloLibs}`); const { data } = features[5]; await test.step('step-1: Go to Marquee (quiet ) block test page', async () => { - await page.goto(`${baseURL}${features[5].path}`); + await page.goto(`${baseURL}${features[5].path}${miloLibs}`); await page.waitForLoadState('domcontentloaded'); - await expect(page).toHaveURL(`${baseURL}${features[5].path}`); + await expect(page).toHaveURL(`${baseURL}${features[5].path}${miloLibs}`); }); await test.step('step-2: Verify Marquee (quiet) specs', async () => { @@ -233,13 +235,13 @@ test.describe('Milo Marquee Block test suite', () => { // Test 6 : Marquee (inline) test(`${features[6].name},${features[6].tags}`, async ({ page, baseURL }) => { - console.info(`[Test Page]: ${baseURL}${features[6].path}`); + console.info(`[Test Page]: ${baseURL}${features[6].path}${miloLibs}`); const { data } = features[6]; await test.step('step-1: Go to Marquee (inline ) block test page', async () => { - await page.goto(`${baseURL}${features[6].path}`); + await page.goto(`${baseURL}${features[6].path}${miloLibs}`); await page.waitForLoadState('domcontentloaded'); - await expect(page).toHaveURL(`${baseURL}${features[6].path}`); + await expect(page).toHaveURL(`${baseURL}${features[6].path}${miloLibs}`); }); await test.step('step-2: Verify Marquee (inline) specs', async () => { @@ -264,13 +266,13 @@ test.describe('Milo Marquee Block test suite', () => { // Test 7 : Marquee (split,small) test(`${features[7].name},${features[7].tags}`, async ({ page, baseURL }) => { - console.info(`[Test Page]: ${baseURL}${features[7].path}`); + console.info(`[Test Page]: ${baseURL}${features[7].path}${miloLibs}`); const { data } = features[7]; await test.step('step-1: Go to Marquee (split, small ) block test page', async () => { - await page.goto(`${baseURL}${features[7].path}`); + await page.goto(`${baseURL}${features[7].path}${miloLibs}`); await page.waitForLoadState('domcontentloaded'); - await expect(page).toHaveURL(`${baseURL}${features[7].path}`); + await expect(page).toHaveURL(`${baseURL}${features[7].path}${miloLibs}`); }); await test.step('step-2: Verify Marquee (split, small) specs', async () => { @@ -299,13 +301,13 @@ test.describe('Milo Marquee Block test suite', () => { // Test 8 : Marquee (split,large) test(`${features[8].name},${features[8].tags}`, async ({ page, baseURL }) => { - console.info(`[Test Page]: ${baseURL}${features[8].path}`); + console.info(`[Test Page]: ${baseURL}${features[8].path}${miloLibs}`); const { data } = features[8]; await test.step('step-1: Go to Marquee (split, large ) block test page', async () => { - await page.goto(`${baseURL}${features[8].path}`); + await page.goto(`${baseURL}${features[8].path}${miloLibs}`); await page.waitForLoadState('domcontentloaded'); - await expect(page).toHaveURL(`${baseURL}${features[8].path}`); + await expect(page).toHaveURL(`${baseURL}${features[8].path}${miloLibs}`); }); await test.step('step-2: Verify Marquee (split, large) specs ', async () => { @@ -338,13 +340,13 @@ test.describe('Milo Marquee Block test suite', () => { // Test 9 : Marquee (split,one-third,large,light) test(`${features[9].name},${features[9].tags}`, async ({ page, baseURL }) => { - console.info(`[Test Page]: ${baseURL}${features[9].path}`); + console.info(`[Test Page]: ${baseURL}${features[9].path}${miloLibs}`); const { data } = features[9]; await test.step('step-1: Go to Marquee (split, one-third, large, light ) block test page', async () => { - await page.goto(`${baseURL}${features[9].path}`); + await page.goto(`${baseURL}${features[9].path}${miloLibs}`); await page.waitForLoadState('domcontentloaded'); - await expect(page).toHaveURL(`${baseURL}${features[9].path}`); + await expect(page).toHaveURL(`${baseURL}${features[9].path}${miloLibs}`); }); await test.step('step-2: Verify Marquee (split, one-third, large, light) specs', async () => { @@ -377,13 +379,13 @@ test.describe('Milo Marquee Block test suite', () => { // Test 10 : Marquee (split,one-third) test(`${features[10].name},${features[10].tags}`, async ({ page, baseURL }) => { - console.info(`[Test Page]: ${baseURL}${features[10].path}`); + console.info(`[Test Page]: ${baseURL}${features[10].path}${miloLibs}`); const { data } = features[10]; await test.step('step-1: Go to Marquee (split, one-third ) block test page', async () => { - await page.goto(`${baseURL}${features[10].path}`); + await page.goto(`${baseURL}${features[10].path}${miloLibs}`); await page.waitForLoadState('domcontentloaded'); - await expect(page).toHaveURL(`${baseURL}${features[10].path}`); + await expect(page).toHaveURL(`${baseURL}${features[10].path}${miloLibs}`); }); await test.step('step-2: Verify Marquee (split, one-third) specs', async () => { @@ -416,13 +418,13 @@ test.describe('Milo Marquee Block test suite', () => { // Test 11 : Marquee (split,one-third,small,light) test(`${features[11].name},${features[11].tags}`, async ({ page, baseURL }) => { - console.info(`[Test Page]: ${baseURL}${features[11].path}`); + console.info(`[Test Page]: ${baseURL}${features[11].path}${miloLibs}`); const { data } = features[11]; await test.step('step-1: Go to Marquee (split,one-third,small,light ) block test page', async () => { - await page.goto(`${baseURL}${features[11].path}`); + await page.goto(`${baseURL}${features[11].path}${miloLibs}`); await page.waitForLoadState('domcontentloaded'); - await expect(page).toHaveURL(`${baseURL}${features[11].path}`); + await expect(page).toHaveURL(`${baseURL}${features[11].path}${miloLibs}`); }); await test.step('step-2: Verify Marquee (split,one-third,small,light) specs', async () => { @@ -452,13 +454,13 @@ test.describe('Milo Marquee Block test suite', () => { test(`${features[12].name},${features[12].tags}`, async ({ page, baseURL, browserName }) => { test.slow(); test.skip(browserName === 'webkit', 'This feature is failing on Webkit browsers') - console.info(`[Test Page]: ${baseURL}${features[12].path}`); + console.info(`[Test Page]: ${baseURL}${features[12].path}${miloLibs}`); const { data } = features[12]; await test.step('step-1: Go to Marquee (small) block test page', async () => { - await page.goto(`${baseURL}${features[12].path}`); + await page.goto(`${baseURL}${features[12].path}${miloLibs}`); await page.waitForLoadState('domcontentloaded'); - await expect(page).toHaveURL(`${baseURL}${features[12].path}`); + await expect(page).toHaveURL(`${baseURL}${features[12].path}${miloLibs}`); }); await test.step('step-2: Verify Marquee (small) background video playsinline specs', async () => { @@ -487,13 +489,13 @@ test.describe('Milo Marquee Block test suite', () => { test(`${features[13].name},${features[13].tags}`, async ({ page, baseURL, browserName }) => { test.skip(browserName === 'webkit', 'This feature is failing on Webkit browsers') test.slow(); - console.info(`[Test Page]: ${baseURL}${features[13].path}`); + console.info(`[Test Page]: ${baseURL}${features[13].path}${miloLibs}`); const { data } = features[13]; await test.step('step-1: Go to Marquee (large, light ) block test page', async () => { - await page.goto(`${baseURL}${features[13].path}`); + await page.goto(`${baseURL}${features[13].path}${miloLibs}`); await page.waitForLoadState('domcontentloaded'); - await expect(page).toHaveURL(`${baseURL}${features[13].path}`); + await expect(page).toHaveURL(`${baseURL}${features[13].path}${miloLibs}`); }); await test.step('step-2: Verify Marquee (large, light) desktop background specs', async () => { @@ -526,13 +528,13 @@ test.describe('Milo Marquee Block test suite', () => { // Test 14 : Marquee large (background video playsinline loop once) test(`${features[14].name},${features[14].tags}`, async ({ page, baseURL }) => { test.slow(); - console.info(`[Test Page]: ${baseURL}${features[14].path}`); + console.info(`[Test Page]: ${baseURL}${features[14].path}${miloLibs}`); const { data } = features[14]; await test.step('step-1: Go to Marquee (large, dark ) block test page', async () => { - await page.goto(`${baseURL}${features[14].path}`); + await page.goto(`${baseURL}${features[14].path}${miloLibs}`); await page.waitForLoadState('domcontentloaded'); - await expect(page).toHaveURL(`${baseURL}${features[14].path}`); + await expect(page).toHaveURL(`${baseURL}${features[14].path}${miloLibs}`); }); await test.step('step-2: Verify Marquee (large, dark) background specs', async () => { diff --git a/tests/milo/media.block.test.js b/tests/milo/media.block.test.js index a049a5f5..1d3335fe 100644 --- a/tests/milo/media.block.test.js +++ b/tests/milo/media.block.test.js @@ -6,6 +6,7 @@ import MediaBlock from '../../selectors/milo/media.block.page.js'; let webUtil; let media; let consoleErrors = []; +const miloLibs = process.env.MILO_LIBS || ''; const knownConsoleErrors = ['Access-Control-Allow-Origin','Failed to load resource: net::ERR_FAILED','adobeid-na1-stg1.services']; test.describe('Milo Media Block test suite', () => { @@ -26,13 +27,13 @@ test.describe('Milo Media Block test suite', () => { // Test 0 : Media (small) test(`${features[0].name},${features[0].tags}`, async ({ page, baseURL }) => { - console.info(`[Test Page]: ${baseURL}${features[0].path}`); + console.info(`[Test Page]: ${baseURL}${features[0].path}${miloLibs}`); const { data } = features[0]; await test.step('step-1: Go to Media (small) block test page', async () => { - await page.goto(`${baseURL}${features[0].path}`); + await page.goto(`${baseURL}${features[0].path}${miloLibs}`); await page.waitForLoadState('domcontentloaded'); - await expect(page).toHaveURL(`${baseURL}${features[0].path}`); + await expect(page).toHaveURL(`${baseURL}${features[0].path}${miloLibs}`); }); await test.step('step-2: Verify media (small) block specs', async () => { @@ -61,13 +62,13 @@ test.describe('Milo Media Block test suite', () => { // Test 1 : Media test(`${features[1].name},${features[1].tags}`, async ({ page, baseURL }) => { - console.info(`[Test Page]: ${baseURL}${features[1].path}`); + console.info(`[Test Page]: ${baseURL}${features[1].path}${miloLibs}`); const { data } = features[1]; await test.step('step-1: Go to media block test page', async () => { - await page.goto(`${baseURL}${features[1].path}`); + await page.goto(`${baseURL}${features[1].path}${miloLibs}`); await page.waitForLoadState('domcontentloaded'); - await expect(page).toHaveURL(`${baseURL}${features[1].path}`); + await expect(page).toHaveURL(`${baseURL}${features[1].path}${miloLibs}`); }); await test.step('step-2: Verify media block specs', async () => { @@ -95,13 +96,13 @@ test.describe('Milo Media Block test suite', () => { // Test 2 : Media (large, dark) test(`${features[2].name},${features[2].tags}`, async ({ page, baseURL }) => { - console.info(`[Test Page]: ${baseURL}${features[2].path}`); + console.info(`[Test Page]: ${baseURL}${features[2].path}${miloLibs}`); const { data } = features[2]; await test.step('step-1: Go to media block test page', async () => { - await page.goto(`${baseURL}${features[2].path}`); + await page.goto(`${baseURL}${features[2].path}${miloLibs}`); await page.waitForLoadState('domcontentloaded'); - await expect(page).toHaveURL(`${baseURL}${features[2].path}`); + await expect(page).toHaveURL(`${baseURL}${features[2].path}${miloLibs}`); }); await test.step('step-2: Verify media (large, dark) block specs', async () => { @@ -131,13 +132,13 @@ test.describe('Milo Media Block test suite', () => { test(`${features[3].name},${features[3].tags}`, async ({ page, baseURL, browserName }) => { test.skip(browserName === 'webkit', 'This feature is failing on Webkit browsers') test.slow(); - console.info(`[Test Page]: ${baseURL}${features[3].path}`); + console.info(`[Test Page]: ${baseURL}${features[3].path}${miloLibs}`); const { data } = features[3]; await test.step('step-1: Go to media block test page', async () => { - await page.goto(`${baseURL}${features[3].path}`); + await page.goto(`${baseURL}${features[3].path}${miloLibs}`); await page.waitForLoadState('domcontentloaded'); - await expect(page).toHaveURL(`${baseURL}${features[3].path}`); + await expect(page).toHaveURL(`${baseURL}${features[3].path}${miloLibs}`); }); await test.step('step-2: Verify media (large, dark) block specs', async () => { @@ -166,13 +167,13 @@ test.describe('Milo Media Block test suite', () => { // Test 5 : Media (large, dark) video, autoplay loop once test(`${features[4].name},${features[4].tags}`, async ({ page, baseURL }) => { test.slow(); - console.info(`[Test Page]: ${baseURL}${features[4].path}`); + console.info(`[Test Page]: ${baseURL}${features[4].path}${miloLibs}`); const { data } = features[4]; await test.step('step-1: Go to media block test page', async () => { - await page.goto(`${baseURL}${features[4].path}`); + await page.goto(`${baseURL}${features[4].path}${miloLibs}`); await page.waitForLoadState('domcontentloaded'); - await expect(page).toHaveURL(`${baseURL}${features[4].path}`); + await expect(page).toHaveURL(`${baseURL}${features[4].path}${miloLibs}`); }); await test.step('step-2: Verify media (large, dark) block specs', async () => { diff --git a/tests/milo/merchcard.block.test.js b/tests/milo/merchcard.block.test.js index bef690aa..b19a7efd 100644 --- a/tests/milo/merchcard.block.test.js +++ b/tests/milo/merchcard.block.test.js @@ -6,6 +6,8 @@ import MerchCard from '../../selectors/milo/merchcard.block.page.js'; let merchCard; let webUtil; +const miloLibs = process.env.MILO_LIBS || ''; + test.describe('Milo Modal feature test suite', () => { test.beforeEach(async ({ page }) => { merchCard = new MerchCard(page); @@ -14,13 +16,13 @@ test.describe('Milo Modal feature test suite', () => { // Test 0 : Merch Card (Segment) test(`${features[0].name},${features[0].tags}`, async ({ page, baseURL }) => { - console.info(`[Test Page]: ${baseURL}${features[0].path}`); + console.info(`[Test Page]: ${baseURL}${features[0].path}${miloLibs}`); const data = features[0].data; await test.step('step-1: Go to Merch Card feature test page', async () => { - await page.goto(`${baseURL}${features[0].path}`); + await page.goto(`${baseURL}${features[0].path}${miloLibs}`); await page.waitForLoadState('domcontentloaded'); - await expect(page).toHaveURL(`${baseURL}${features[0].path}`); + await expect(page).toHaveURL(`${baseURL}${features[0].path}${miloLibs}`); }); await test.step('step-2: Verify Merch Card content/specs', async () => { @@ -46,13 +48,13 @@ test.describe('Milo Modal feature test suite', () => { // Test 1 : Merch Card (Segment) with Badge test(`${features[1].name},${features[1].tags}`, async ({ page, baseURL }) => { - console.info(`[Test Page]: ${baseURL}${features[1].path}`); + console.info(`[Test Page]: ${baseURL}${features[1].path}${miloLibs}`); const data = features[1].data; await test.step('step-1: Go to Merch Card feature test page', async () => { - await page.goto(`${baseURL}${features[1].path}`); + await page.goto(`${baseURL}${features[1].path}${miloLibs}`); await page.waitForLoadState('domcontentloaded'); - await expect(page).toHaveURL(`${baseURL}${features[1].path}`); + await expect(page).toHaveURL(`${baseURL}${features[1].path}${miloLibs}`); }); await test.step('step-2: Verify Merch Card with Badge content/specs', async () => { @@ -85,13 +87,13 @@ test.describe('Milo Modal feature test suite', () => { // Test 2 : Merch Card (Special Offers) test(`${features[2].name},${features[2].tags}`, async ({ page, baseURL }) => { - console.info(`[Test Page]: ${baseURL}${features[2].path}`); + console.info(`[Test Page]: ${baseURL}${features[2].path}${miloLibs}`); const data = features[2].data; await test.step('step-1: Go to Merch Card feature test page', async () => { - await page.goto(`${baseURL}${features[2].path}`); + await page.goto(`${baseURL}${features[2].path}${miloLibs}`); await page.waitForLoadState('domcontentloaded'); - await expect(page).toHaveURL(`${baseURL}${features[2].path}`); + await expect(page).toHaveURL(`${baseURL}${features[2].path}${miloLibs}`); }); await test.step('step-2: Verify Merch Card special offers content/specs', async () => { @@ -113,13 +115,13 @@ test.describe('Milo Modal feature test suite', () => { // Test 3 : Merch Card (Special Offers) with badge test(`${features[3].name},${features[3].tags}`, async ({ page, baseURL }) => { - console.info(`[Test Page]: ${baseURL}${features[3].path}`); + console.info(`[Test Page]: ${baseURL}${features[3].path}${miloLibs}`); const data = features[3].data; await test.step('step-1: Go to Merch Card feature test page', async () => { - await page.goto(`${baseURL}${features[3].path}`); + await page.goto(`${baseURL}${features[3].path}${miloLibs}`); await page.waitForLoadState('domcontentloaded'); - await expect(page).toHaveURL(`${baseURL}${features[3].path}`); + await expect(page).toHaveURL(`${baseURL}${features[3].path}${miloLibs}`); }); await test.step('step-2: Verify Merch Card special offers content/specs', async () => { @@ -151,13 +153,13 @@ test.describe('Milo Modal feature test suite', () => { // Test 4 : Merch Card (plans) test(`${features[4].name},${features[4].tags}`, async ({ page, baseURL }) => { - console.info(`[Test Page]: ${baseURL}${features[4].path}`); + console.info(`[Test Page]: ${baseURL}${features[4].path}${miloLibs}`); const data = features[4].data; await test.step('step-1: Go to Merch Card feature test page', async () => { - await page.goto(`${baseURL}${features[4].path}`); + await page.goto(`${baseURL}${features[4].path}${miloLibs}`); await page.waitForLoadState('domcontentloaded'); - await expect(page).toHaveURL(`${baseURL}${features[4].path}`); + await expect(page).toHaveURL(`${baseURL}${features[4].path}${miloLibs}`); }); await test.step('step-2: Verify Merch Card special offers content/specs', async () => { @@ -180,13 +182,13 @@ test.describe('Milo Modal feature test suite', () => { // Test 5 : Merch Card (plans) with badge test(`${features[5].name},${features[5].tags}`, async ({ page, baseURL }) => { - console.info(`[Test Page]: ${baseURL}${features[5].path}`); + console.info(`[Test Page]: ${baseURL}${features[5].path}${miloLibs}`); const data = features[5].data; await test.step('step-1: Go to Merch Card feature test page', async () => { - await page.goto(`${baseURL}${features[5].path}`); + await page.goto(`${baseURL}${features[5].path}${miloLibs}`); await page.waitForLoadState('domcontentloaded'); - await expect(page).toHaveURL(`${baseURL}${features[5].path}`); + await expect(page).toHaveURL(`${baseURL}${features[5].path}${miloLibs}`); }); await test.step('step-2: Verify Merch Card special offers content/specs', async () => { @@ -213,13 +215,13 @@ test.describe('Milo Modal feature test suite', () => { // Test 6 : Merch Card (plans) with secure // Note: skipping the test as there were failures, informed the team test.skip(`${features[6].name},${features[6].tags}`, async ({ page, baseURL }) => { - console.info(`[Test Page]: ${baseURL}${features[6].path}`); + console.info(`[Test Page]: ${baseURL}${features[6].path}${miloLibs}`); const data = features[6].data; await test.step('step-1: Go to Merch Card feature test page', async () => { - await page.goto(`${baseURL}${features[6].path}`); + await page.goto(`${baseURL}${features[6].path}${miloLibs}`); await page.waitForLoadState('domcontentloaded'); - await expect(page).toHaveURL(`${baseURL}${features[6].path}`); + await expect(page).toHaveURL(`${baseURL}${features[6].path}${miloLibs}`); }); await test.step('step-2: Verify Merch Card special offers content/specs', async () => { @@ -260,13 +262,13 @@ test.describe('Milo Modal feature test suite', () => { // Test 7 : Merch Card (plans, secure) with badge // Note: skipping the test as there were failures, informed the team test.skip(`${features[7].name},${features[7].tags}`, async ({ page, baseURL }) => { - console.info(`[Test Page]: ${baseURL}${features[7].path}`); + console.info(`[Test Page]: ${baseURL}${features[7].path}${miloLibs}`); const data = features[7].data; await test.step('step-1: Go to Merch Card feature test page', async () => { - await page.goto(`${baseURL}${features[7].path}`); + await page.goto(`${baseURL}${features[7].path}${miloLibs}`); await page.waitForLoadState('domcontentloaded'); - await expect(page).toHaveURL(`${baseURL}${features[7].path}`); + await expect(page).toHaveURL(`${baseURL}${features[7].path}${miloLibs}`); }); await test.step('step-2: Verify Merch Card special offers content/specs', async () => { @@ -305,13 +307,13 @@ test.describe('Milo Modal feature test suite', () => { // Test 8 : Merch Card (catalog) test(`${features[8].name},${features[8].tags}`, async ({ page, baseURL }) => { - console.info(`[Test Page]: ${baseURL}${features[8].path}`); + console.info(`[Test Page]: ${baseURL}${features[8].path}${miloLibs}`); const data = features[8].data; await test.step('step-1: Go to Merch Card feature test page', async () => { - await page.goto(`${baseURL}${features[8].path}`); + await page.goto(`${baseURL}${features[8].path}${miloLibs}`); await page.waitForLoadState('domcontentloaded'); - await expect(page).toHaveURL(`${baseURL}${features[8].path}`); + await expect(page).toHaveURL(`${baseURL}${features[8].path}${miloLibs}`); }); await test.step('step-2: Verify Merch Card catalog content/specs', async () => { @@ -337,13 +339,13 @@ test.describe('Milo Modal feature test suite', () => { // Test 9 : Merch Card (catalog) with badge test(`${features[9].name},${features[9].tags}`, async ({ page, baseURL }) => { - console.info(`[Test Page]: ${baseURL}${features[9].path}`); + console.info(`[Test Page]: ${baseURL}${features[9].path}${miloLibs}`); const data = features[9].data; await test.step('step-1: Go to Merch Card feature test page', async () => { - await page.goto(`${baseURL}${features[9].path}`); + await page.goto(`${baseURL}${features[9].path}${miloLibs}`); await page.waitForLoadState('domcontentloaded'); - await expect(page).toHaveURL(`${baseURL}${features[9].path}`); + await expect(page).toHaveURL(`${baseURL}${features[9].path}${miloLibs}`); }); await test.step('step-2: Verify Merch Card catalog with badge content/specs', async () => { @@ -374,13 +376,13 @@ test.describe('Milo Modal feature test suite', () => { // Test 10 : Merch Card (catalog) with more info and badge test(`${features[10].name},${features[10].tags}`, async ({ page, baseURL }) => { - console.info(`[Test Page]: ${baseURL}${features[10].path}`); + console.info(`[Test Page]: ${baseURL}${features[10].path}${miloLibs}`); const data = features[10].data; await test.step('step-1: Go to Merch Card feature test page', async () => { - await page.goto(`${baseURL}${features[10].path}`); + await page.goto(`${baseURL}${features[10].path}${miloLibs}`); await page.waitForLoadState('domcontentloaded'); - await expect(page).toHaveURL(`${baseURL}${features[10].path}`); + await expect(page).toHaveURL(`${baseURL}${features[10].path}${miloLibs}`); }); await test.step('step-2: Verify Merch Card catalog with badge content/specs', async () => { diff --git a/tests/milo/modal.block.test.js b/tests/milo/modal.block.test.js index ba972b6f..e8077d2b 100644 --- a/tests/milo/modal.block.test.js +++ b/tests/milo/modal.block.test.js @@ -6,6 +6,8 @@ import ModalBlock from '../../selectors/milo/modal.block.page.js'; let modal; let webUtil; +const miloLibs = process.env.MILO_LIBS || ''; + test.describe('Milo Modal feature test suite', () => { test.beforeEach(async ({ page }) => { modal = new ModalBlock(page); @@ -14,12 +16,12 @@ test.describe('Milo Modal feature test suite', () => { // Test 0 : Modal with Text block test(`${features[0].name},${features[0].tags}`, async ({ page, baseURL }) => { - console.info(`[Test Page]: ${baseURL}${features[0].path}`); + console.info(`[Test Page]: ${baseURL}${features[0].path}${miloLibs}`); await test.step('step-1: Go to Modal feature test page', async () => { - await page.goto(`${baseURL}${features[0].path}`); + await page.goto(`${baseURL}${features[0].path}${miloLibs}`); await page.waitForLoadState('domcontentloaded'); - await expect(page).toHaveURL(`${baseURL}${features[0].path}`); + await expect(page).toHaveURL(`${baseURL}${features[0].path}${miloLibs}`); }); await test.step('step-2: Verify Modal text fragment content/specs', async () => { @@ -47,12 +49,12 @@ test.describe('Milo Modal feature test suite', () => { // Test 1 : Modal with Media block test(`${features[1].name}, ${features[1].tags}`, async ({ page, baseURL }) => { - console.info(`[Test Page]: ${baseURL}${features[1].path}`); + console.info(`[Test Page]: ${baseURL}${features[1].path}${miloLibs}`); await test.step('step-1: Go to Modal feature test page', async () => { - await page.goto(`${baseURL}${features[1].path}`); + await page.goto(`${baseURL}${features[1].path}${miloLibs}`); await page.waitForLoadState('domcontentloaded'); - await expect(page).toHaveURL(`${baseURL}${features[1].path}`); + await expect(page).toHaveURL(`${baseURL}${features[1].path}${miloLibs}`); }); await test.step('step-2: Verify Modal media fragement content/specs', async () => { @@ -82,12 +84,12 @@ test.describe('Milo Modal feature test suite', () => { // Test 2 : Modal with Video Autoplay test(`${features[2].name}, ${features[2].tags}`, async ({ page, baseURL }) => { - console.info(`[Test Page]: ${baseURL}${features[2].path}`); + console.info(`[Test Page]: ${baseURL}${features[2].path}${miloLibs}`); await test.step('step-1: Go to Modal feature test page', async () => { - await page.goto(`${baseURL}${features[2].path}`); + await page.goto(`${baseURL}${features[2].path}${miloLibs}`); await page.waitForLoadState('domcontentloaded'); - await expect(page).toHaveURL(`${baseURL}${features[2].path}`); + await expect(page).toHaveURL(`${baseURL}${features[2].path}${miloLibs}`); }); await test.step('step-2: Verify Modal media fragement content/specs', async () => { diff --git a/tests/milo/personalization.feature.test.js b/tests/milo/personalization.feature.test.js index 8b01fccd..8d3fd98e 100644 --- a/tests/milo/personalization.feature.test.js +++ b/tests/milo/personalization.feature.test.js @@ -11,6 +11,8 @@ let marquee; let text; let pznUrl; +const miloLibs = process.env.MILO_LIBS || ''; + test.describe('Milo Personalization feature test suite', () => { test.beforeEach(async ({ page }) => { webUtil = new WebUtil(page); @@ -18,16 +20,16 @@ test.describe('Milo Personalization feature test suite', () => { // Test 0 : Personalization (Replace content) test(`${features[0].name},${features[0].tags}`, async ({ page, baseURL }) => { - console.info(`[Test Page]: ${baseURL}${features[0].path}`); + console.info(`[Test Page]: ${baseURL}${features[0].path}${miloLibs}`); const data = features[0].data; text = new TextBlock(page); marquee = new MarqueeBlock(page); - pznUrl = `${baseURL}${features[0].path}${'?target='}${data.target}` + pznUrl = `${baseURL}${features[0].path}${'?target='}${data.target}&${miloLibs}` await test.step('step-1: Go to default test page', async () => { - await page.goto(`${baseURL}${features[0].path}`); + await page.goto(`${baseURL}${features[0].path}${miloLibs}`); await page.waitForLoadState('domcontentloaded'); - await expect(page).toHaveURL(`${baseURL}${features[0].path}`); + await expect(page).toHaveURL(`${baseURL}${features[0].path}${miloLibs}`); }); await test.step('step-2: Verify default test page content/specs', async () => { @@ -51,16 +53,16 @@ test.describe('Milo Personalization feature test suite', () => { // Test 1 : Personalization (Insert Content Before) test(`${features[1].name},${features[1].tags}`, async ({ page, baseURL }) => { - console.info(`[Test Page]: ${baseURL}${features[1].path}`); + console.info(`[Test Page]: ${baseURL}${features[1].path}${miloLibs}`); const data = features[1].data; text = new TextBlock(page); marquee = new MarqueeBlock(page); - pznUrl = `${baseURL}${features[1].path}${'?target='}${data.target}` + pznUrl = `${baseURL}${features[1].path}${'?target='}${data.target}&${miloLibs}` await test.step('step-1: Go to default test page', async () => { - await page.goto(`${baseURL}${features[1].path}`); + await page.goto(`${baseURL}${features[1].path}${miloLibs}`); await page.waitForLoadState('domcontentloaded'); - await expect(page).toHaveURL(`${baseURL}${features[1].path}`); + await expect(page).toHaveURL(`${baseURL}${features[1].path}${miloLibs}`); }); await test.step('step-2: Verify default test page content/specs', async () => { @@ -90,16 +92,16 @@ test.describe('Milo Personalization feature test suite', () => { // Test 2 : Personalization (Insert Content After) test(`${features[2].name},${features[2].tags}`, async ({ page, baseURL }) => { - console.info(`[Test Page]: ${baseURL}${features[2].path}`); + console.info(`[Test Page]: ${baseURL}${features[2].path}${miloLibs}`); const data = features[2].data; text = new TextBlock(page); howto = new Howto(page); - pznUrl = `${baseURL}${features[2].path}${'?target='}${data.target}` + pznUrl = `${baseURL}${features[2].path}${'?target='}${data.target}&${miloLibs}` await test.step('step-1: Go to default test page', async () => { - await page.goto(`${baseURL}${features[2].path}`); + await page.goto(`${baseURL}${features[2].path}${miloLibs}`); await page.waitForLoadState('domcontentloaded'); - await expect(page).toHaveURL(`${baseURL}${features[2].path}`); + await expect(page).toHaveURL(`${baseURL}${features[2].path}${miloLibs}`); }); await test.step('step-2: Verify default test page content/specs', async () => { diff --git a/tests/milo/quote.block.test.js b/tests/milo/quote.block.test.js index bcecd2a5..ef914a42 100644 --- a/tests/milo/quote.block.test.js +++ b/tests/milo/quote.block.test.js @@ -6,6 +6,8 @@ import QuoteBlock from '../../selectors/milo/quote.block.page.js'; let quote; let webUtil +const miloLibs = process.env.MILO_LIBS || ''; + test.describe('Milo Quote Block test suite', () => { test.beforeEach(async ({ page }) => { webUtil = new WebUtil(page); @@ -14,13 +16,13 @@ test.describe('Milo Quote Block test suite', () => { // Test 0 : Quote default block test(`${features[0].name},${features[0].tags}`, async ({ page, baseURL }) => { - console.info(`[Test Page]: ${baseURL}${features[0].path}`); + console.info(`[Test Page]: ${baseURL}${features[0].path}${miloLibs}`); const { data } = features[0]; await test.step('step-1: Go to Quote block test page', async () => { - await page.goto(`${baseURL}${features[0].path}`); + await page.goto(`${baseURL}${features[0].path}${miloLibs}`); await page.waitForLoadState('domcontentloaded'); - await expect(page).toHaveURL(`${baseURL}${features[0].path}`); + await expect(page).toHaveURL(`${baseURL}${features[0].path}${miloLibs}`); }); await test.step('step-2: Verify Quote block content/specs', async () => { @@ -37,13 +39,13 @@ test.describe('Milo Quote Block test suite', () => { // Test 1 : quote (contained) test(`${features[1].name},${features[1].tags}`, async ({ page, baseURL }) => { - console.info(`[Test Page]: ${baseURL}${features[1].path}`); + console.info(`[Test Page]: ${baseURL}${features[1].path}${miloLibs}`); const { data } = features[1]; await test.step('step-1: Go to Quote block test page', async () => { - await page.goto(`${baseURL}${features[1].path}`); + await page.goto(`${baseURL}${features[1].path}${miloLibs}`); await page.waitForLoadState('domcontentloaded'); - await expect(page).toHaveURL(`${baseURL}${features[1].path}`); + await expect(page).toHaveURL(`${baseURL}${features[1].path}${miloLibs}`); }); await test.step('step-2: Verify Quote (contained) block content/specs', async () => { @@ -59,13 +61,13 @@ test.describe('Milo Quote Block test suite', () => { // Test 2 : Quote (inline,contained) test(`${features[2].name},${features[2].tags}`, async ({ page, baseURL }) => { - console.info(`[Test Page]: ${baseURL}${features[2].path}`); + console.info(`[Test Page]: ${baseURL}${features[2].path}${miloLibs}`); const { data } = features[2]; await test.step('step-1: Go to Quote (inline) block test page', async () => { - await page.goto(`${baseURL}${features[2].path}`); + await page.goto(`${baseURL}${features[2].path}${miloLibs}`); await page.waitForLoadState('domcontentloaded'); - await expect(page).toHaveURL(`${baseURL}${features[2].path}`); + await expect(page).toHaveURL(`${baseURL}${features[2].path}${miloLibs}`); }); await test.step('step-2: Verify Quote (inline) block content/specs', async () => { @@ -82,13 +84,13 @@ test.describe('Milo Quote Block test suite', () => { // Test 3 : quote (borders) test(`${features[3].name},${features[3].tags}`, async ({ page, baseURL }) => { - console.info(`[MiloInfo] Checking page: ${baseURL}${features[3].path}`); + console.info(`[MiloInfo] Checking page: ${baseURL}${features[3].path}${miloLibs}`); const { data } = features[3]; await test.step('step-1: Go to Quote (borders) block test page', async () => { - await page.goto(`${baseURL}${features[3].path}`); + await page.goto(`${baseURL}${features[3].path}${miloLibs}`); await page.waitForLoadState('domcontentloaded'); - await expect(page).toHaveURL(`${baseURL}${features[3].path}`); + await expect(page).toHaveURL(`${baseURL}${features[3].path}${miloLibs}`); }); await test.step('step-2: Verify Quote (borders) block content/specs', async () => { @@ -104,13 +106,13 @@ test.describe('Milo Quote Block test suite', () => { // Test 4 : quote (align-right) test(`${features[4].name},${features[4].tags}`, async ({ page, baseURL }) => { - console.info(`[Test Page]: ${baseURL}${features[4].path}`); + console.info(`[Test Page]: ${baseURL}${features[4].path}${miloLibs}`); const { data } = features[4]; await test.step('step-1: Go to Quote (align-right) block test page', async () => { - await page.goto(`${baseURL}${features[4].path}`); + await page.goto(`${baseURL}${features[4].path}${miloLibs}`); await page.waitForLoadState('domcontentloaded'); - await expect(page).toHaveURL(`${baseURL}${features[4].path}`); + await expect(page).toHaveURL(`${baseURL}${features[4].path}${miloLibs}`); }); await test.step('step-2: Verify Quote (align-right) block content/specs', async () => { @@ -126,13 +128,13 @@ test.describe('Milo Quote Block test suite', () => { // Test 5 : quote (xl-spaced) test(`${features[5].name},${features[5].tags}`, async ({ page, baseURL }) => { - console.info(`[Test Page]: ${baseURL}${features[5].path}`); + console.info(`[Test Page]: ${baseURL}${features[5].path}${miloLibs}`); const { data } = features[5]; await test.step('step-1: Go to Quote (xl-spaced) block test page', async () => { - await page.goto(`${baseURL}${features[5].path}`); + await page.goto(`${baseURL}${features[5].path}${miloLibs}`); await page.waitForLoadState('domcontentloaded'); - await expect(page).toHaveURL(`${baseURL}${features[5].path}`); + await expect(page).toHaveURL(`${baseURL}${features[5].path}${miloLibs}`); }); await test.step('step-2: Verify Quote (xl-spaced) block content/specs', async () => { diff --git a/tests/milo/review.block.test.js b/tests/milo/review.block.test.js index bc6151af..aea505a2 100644 --- a/tests/milo/review.block.test.js +++ b/tests/milo/review.block.test.js @@ -4,6 +4,8 @@ import ReviewBlock from '../../selectors/milo/review.block.page.js'; let review; +const miloLibs = process.env.MILO_LIBS || ''; + test.describe('Milo Review Block test suite', () => { test.beforeEach(async ({ page, browser }) => { // review block requires clearing cookies @@ -13,12 +15,12 @@ test.describe('Milo Review Block test suite', () => { }); test(`${features[0].name},${features[0].tags}`, async ({ page, baseURL }) => { - console.info(`[Test Page]: ${baseURL}${features[0].path}`); + console.info(`[Test Page]: ${baseURL}${features[0].path}${miloLibs}`); await test.step('step-1: Go to review feature test page', async () => { - await page.goto(`${baseURL}${features[0].path}`); + await page.goto(`${baseURL}${features[0].path}${miloLibs}`); await page.waitForLoadState('domcontentloaded'); - await expect(page).toHaveURL(`${baseURL}${features[0].path}`); + await expect(page).toHaveURL(`${baseURL}${features[0].path}${miloLibs}`); }); await test.step('step-2: Verify review block and submit the review < 3', async () => { @@ -29,12 +31,12 @@ test.describe('Milo Review Block test suite', () => { }); test(`${features[1].name},${features[1].tags}`, async ({ page, baseURL }) => { - console.info(`[Test Page]: ${baseURL}${features[1].path}`); + console.info(`[Test Page]: ${baseURL}${features[1].path}${miloLibs}`); await test.step('step-1: Go to review block test page', async () => { - await page.goto(`${baseURL}${features[1].path}`); + await page.goto(`${baseURL}${features[1].path}${miloLibs}`); await page.waitForLoadState('domcontentloaded'); - await expect(page).toHaveURL(`${baseURL}${features[1].path}`); + await expect(page).toHaveURL(`${baseURL}${features[1].path}${miloLibs}`); }); await test.step('step-2: Verify review block and submit the review > 3', async () => { diff --git a/tests/milo/tab.block.test.js b/tests/milo/tab.block.test.js index 93db25cf..a0bbe178 100644 --- a/tests/milo/tab.block.test.js +++ b/tests/milo/tab.block.test.js @@ -4,6 +4,8 @@ import TabBlock from '../../selectors/milo/tabs.block.page.js'; let tab; +const miloLibs = process.env.MILO_LIBS || ''; + test.describe('Milo Tab block feature test suite', () => { test.beforeEach(async ({ page }) => { tab = new TabBlock(page); @@ -11,13 +13,13 @@ test.describe('Milo Tab block feature test suite', () => { // Test 0 : Tabs (xl-spacing) test(`${features[0].name},${features[0].tags}`, async ({ page, baseURL }) => { - console.info(`[Test Page]: ${baseURL}${features[0].path}`); + console.info(`[Test Page]: ${baseURL}${features[0].path}${miloLibs}`); const data = features[0].data; await test.step('step-1: Go to Tabs block feature test page', async () => { - await page.goto(`${baseURL}${features[0].path}`); + await page.goto(`${baseURL}${features[0].path}${miloLibs}`); await page.waitForLoadState('domcontentloaded'); - await expect(page).toHaveURL(`${baseURL}${features[0].path}`); + await expect(page).toHaveURL(`${baseURL}${features[0].path}${miloLibs}`); }); await test.step('step-2: Verify tabs content/specs', async () => { @@ -43,13 +45,13 @@ test.describe('Milo Tab block feature test suite', () => { // Test 1 : Tabs (Quiet, Dark, Center) test(`${features[1].name},${features[1].tags}`, async ({ page, baseURL }) => { - console.info(`[Test Page]: ${baseURL}${features[1].path}`); + console.info(`[Test Page]: ${baseURL}${features[1].path}${miloLibs}`); const data = features[1].data; await test.step('step-1: Go to Tabs block feature test page', async () => { - await page.goto(`${baseURL}${features[1].path}`); + await page.goto(`${baseURL}${features[1].path}${miloLibs}`); await page.waitForLoadState('domcontentloaded'); - await expect(page).toHaveURL(`${baseURL}${features[1].path}`); + await expect(page).toHaveURL(`${baseURL}${features[1].path}${miloLibs}`); }); await test.step('step-2: Verify tabs content/specs', async () => { diff --git a/tests/milo/table.block.test.js b/tests/milo/table.block.test.js index 08bb26b4..e30f706b 100644 --- a/tests/milo/table.block.test.js +++ b/tests/milo/table.block.test.js @@ -4,6 +4,8 @@ import TableBlock from '../../selectors/milo/table.block.page'; let table; +const miloLibs = process.env.MILO_LIBS || ''; + test.describe('Milo Table block feature test suite', () => { test.beforeEach(async ({ page }) => { table = new TableBlock(page); @@ -11,13 +13,13 @@ test.describe('Milo Table block feature test suite', () => { // Test 0 : Table block (default) test(`${features[0].name},${features[0].tags}`, async ({ page, baseURL }) => { - console.info(`[Test Page]: ${baseURL}${features[0].path}`); + console.info(`[Test Page]: ${baseURL}${features[0].path}${miloLibs}`); const data = features[0].data; await test.step('step-1: Go to Table block test page', async () => { - await page.goto(`${baseURL}${features[0].path}`); + await page.goto(`${baseURL}${features[0].path}${miloLibs}`); await page.waitForLoadState('domcontentloaded'); - await expect(page).toHaveURL(`${baseURL}${features[0].path}`); + await expect(page).toHaveURL(`${baseURL}${features[0].path}${miloLibs}`); }); await test.step('step-2: Verify table content/specs', async () => { @@ -43,13 +45,13 @@ test.describe('Milo Table block feature test suite', () => { // Test 1 : Table (highlight) test(`${features[1].name},${features[1].tags}`, async ({ page, baseURL }) => { - console.info(`[Test Page]: ${baseURL}${features[1].path}`); + console.info(`[Test Page]: ${baseURL}${features[1].path}${miloLibs}`); const data = features[1].data; await test.step('step-1: Go to Table block test page', async () => { - await page.goto(`${baseURL}${features[1].path}`); + await page.goto(`${baseURL}${features[1].path}${miloLibs}`); await page.waitForLoadState('domcontentloaded'); - await expect(page).toHaveURL(`${baseURL}${features[1].path}`); + await expect(page).toHaveURL(`${baseURL}${features[1].path}${miloLibs}`); }); await test.step('step-2: Verify table content/specs', async () => { @@ -83,13 +85,13 @@ test.describe('Milo Table block feature test suite', () => { // Test 2 : Table (sticky) test(`${features[2].name},${features[2].tags}`, async ({ page, baseURL }) => { - console.info(`[Test Page]: ${baseURL}${features[2].path}`); + console.info(`[Test Page]: ${baseURL}${features[2].path}${miloLibs}`); const data = features[2].data; await test.step('step-1: Go to Table block test page', async () => { - await page.goto(`${baseURL}${features[2].path}`); + await page.goto(`${baseURL}${features[2].path}${miloLibs}`); await page.waitForLoadState('domcontentloaded'); - await expect(page).toHaveURL(`${baseURL}${features[2].path}`); + await expect(page).toHaveURL(`${baseURL}${features[2].path}${miloLibs}`); }); await test.step('step-2: Verify table content/specs', async () => { @@ -119,13 +121,13 @@ test.describe('Milo Table block feature test suite', () => { // Test 3 : Table (highlight, collapse, sticky) test(`${features[3].name},${features[3].tags}`, async ({ page, baseURL }) => { - console.info(`[Test Page]: ${baseURL}${features[3].path}`); + console.info(`[Test Page]: ${baseURL}${features[3].path}${miloLibs}`); const data = features[3].data; await test.step('step-1: Go to Table block test page', async () => { - await page.goto(`${baseURL}${features[3].path}`); + await page.goto(`${baseURL}${features[3].path}${miloLibs}`); await page.waitForLoadState('domcontentloaded'); - await expect(page).toHaveURL(`${baseURL}${features[3].path}`); + await expect(page).toHaveURL(`${baseURL}${features[3].path}${miloLibs}`); }); await test.step('step-2: Verify table content/specs', async () => { @@ -165,13 +167,13 @@ test.describe('Milo Table block feature test suite', () => { // Test 4 : Table (merch) test(`${features[4].name},${features[4].tags}`, async ({ page, baseURL }) => { - console.info(`[Test Page]: ${baseURL}${features[4].path}`); + console.info(`[Test Page]: ${baseURL}${features[4].path}${miloLibs}`); const data = features[4].data; await test.step('step-1: Go to Table block test page', async () => { - await page.goto(`${baseURL}${features[4].path}`); + await page.goto(`${baseURL}${features[4].path}${miloLibs}`); await page.waitForLoadState('domcontentloaded'); - await expect(page).toHaveURL(`${baseURL}${features[4].path}`); + await expect(page).toHaveURL(`${baseURL}${features[4].path}${miloLibs}`); }); await test.step('step-2: Verify table content/specs', async () => { diff --git a/tests/milo/text.block.test.js b/tests/milo/text.block.test.js index 98bdd25c..cdd221d5 100644 --- a/tests/milo/text.block.test.js +++ b/tests/milo/text.block.test.js @@ -6,6 +6,8 @@ import TextBlock from '../../selectors/milo/text.block.page.js'; let text; let webUtil; +const miloLibs = process.env.MILO_LIBS || ''; + test.describe('Milo Text Block test suite', () => { test.beforeEach(async ({ page }) => { text = new TextBlock(page); @@ -14,13 +16,13 @@ test.describe('Milo Text Block test suite', () => { // Test 0 : Text test(`${features[0].name},${features[0].tags}`, async ({ page, baseURL }) => { - console.info(`[Test Page]: ${baseURL}${features[0].path}`); + console.info(`[Test Page]: ${baseURL}${features[0].path}${miloLibs}`); const { data } = features[0]; await test.step('step-1: Go to Text block test page', async () => { - await page.goto(`${baseURL}${features[0].path}`); + await page.goto(`${baseURL}${features[0].path}${miloLibs}`); await page.waitForLoadState('domcontentloaded'); - await expect(page).toHaveURL(`${baseURL}${features[0].path}`); + await expect(page).toHaveURL(`${baseURL}${features[0].path}${miloLibs}`); }); await test.step('step-2: Verify Text specs', async () => { @@ -43,13 +45,13 @@ test.describe('Milo Text Block test suite', () => { // Test 1 : Text (intro) test(`${features[1].name},${features[1].tags}`, async ({ page, baseURL }) => { - console.info(`[Test Page]: ${baseURL}${features[1].path}`); + console.info(`[Test Page]: ${baseURL}${features[1].path}${miloLibs}`); const { data } = features[1]; await test.step('step-1: Go to Text (intro) block test page', async () => { - await page.goto(`${baseURL}${features[1].path}`); + await page.goto(`${baseURL}${features[1].path}${miloLibs}`); await page.waitForLoadState('domcontentloaded'); - await expect(page).toHaveURL(`${baseURL}${features[1].path}`); + await expect(page).toHaveURL(`${baseURL}${features[1].path}${miloLibs}`); }); await test.step('step-2: Verify Text (intro) specs', async () => { @@ -70,13 +72,13 @@ test.describe('Milo Text Block test suite', () => { // Test 2 : Text (full-width) test(`${features[2].name},${features[2].tags}`, async ({ page, baseURL }) => { - console.info(`[Test Page]: ${baseURL}${features[2].path}`); + console.info(`[Test Page]: ${baseURL}${features[2].path}${miloLibs}`); const { data } = features[2]; await test.step('step-1: Go to Text (full width) block test page', async () => { - await page.goto(`${baseURL}${features[2].path}`); + await page.goto(`${baseURL}${features[2].path}${miloLibs}`); await page.waitForLoadState('domcontentloaded'); - await expect(page).toHaveURL(`${baseURL}${features[2].path}`); + await expect(page).toHaveURL(`${baseURL}${features[2].path}${miloLibs}`); }); await test.step('step-2: Verify Text (full width) specs', async () => { @@ -100,13 +102,13 @@ test.describe('Milo Text Block test suite', () => { // Test 3 : Text (full-width, large) test(`${features[3].name},${features[3].tags}`, async ({ page, baseURL }) => { - console.info(`[Test Page]: ${baseURL}${features[3].path}`); + console.info(`[Test Page]: ${baseURL}${features[3].path}${miloLibs}`); const { data } = features[3]; await test.step('step-1: Go to text (full-width, large) block test page', async () => { - await page.goto(`${baseURL}${features[3].path}`); + await page.goto(`${baseURL}${features[3].path}${miloLibs}`); await page.waitForLoadState('domcontentloaded'); - await expect(page).toHaveURL(`${baseURL}${features[3].path}`); + await expect(page).toHaveURL(`${baseURL}${features[3].path}${miloLibs}`); }); await test.step('step-2: Verify Text (full-width, large) specs', async () => { @@ -129,13 +131,13 @@ test.describe('Milo Text Block test suite', () => { // Test 4 : Text (long-form, large) test(`${features[4].name},${features[4].tags}`, async ({ page, baseURL }) => { - console.info(`[Test Page]: ${baseURL}${features[4].path}`); + console.info(`[Test Page]: ${baseURL}${features[4].path}${miloLibs}`); const { data } = features[4]; await test.step('step-1: Go to Text (long form, large) block test page', async () => { - await page.goto(`${baseURL}${features[4].path}`); + await page.goto(`${baseURL}${features[4].path}${miloLibs}`); await page.waitForLoadState('domcontentloaded'); - await expect(page).toHaveURL(`${baseURL}${features[4].path}`); + await expect(page).toHaveURL(`${baseURL}${features[4].path}${miloLibs}`); }); await test.step('step-2: Verify Text (long form, large) specs', async () => { @@ -158,13 +160,13 @@ test.describe('Milo Text Block test suite', () => { // Test 5 : Text (inset, medium, m-spacing) test(`${features[5].name},${features[5].tags}`, async ({ page, baseURL }) => { - console.info(`[Test Page]: ${baseURL}${features[5].path}`); + console.info(`[Test Page]: ${baseURL}${features[5].path}${miloLibs}`); const { data } = features[5]; await test.step('step-1: Go to Text (inset, medium, m-spacing ) block test page', async () => { - await page.goto(`${baseURL}${features[5].path}`); + await page.goto(`${baseURL}${features[5].path}${miloLibs}`); await page.waitForLoadState('domcontentloaded'); - await expect(page).toHaveURL(`${baseURL}${features[5].path}`); + await expect(page).toHaveURL(`${baseURL}${features[5].path}${miloLibs}`); }); await test.step('step-2: Verify Text (inset, large, m spacing) specs', async () => { @@ -187,13 +189,13 @@ test.describe('Milo Text Block test suite', () => { // Test 6 : Text (legal) test(`${features[6].name},${features[6].tags}`, async ({ page, baseURL }) => { - console.info(`[Test Page]: ${baseURL}${features[6].path}`); + console.info(`[Test Page]: ${baseURL}${features[6].path}${miloLibs}`); const { data } = features[6]; await test.step('step-1: Go to Text (legal) block test page', async () => { - await page.goto(`${baseURL}${features[6].path}`); + await page.goto(`${baseURL}${features[6].path}${miloLibs}`); await page.waitForLoadState('domcontentloaded'); - await expect(page).toHaveURL(`${baseURL}${features[6].path}`); + await expect(page).toHaveURL(`${baseURL}${features[6].path}${miloLibs}`); }); await test.step('step-2: Verify Text (legal) specs', async () => { @@ -214,13 +216,13 @@ test.describe('Milo Text Block test suite', () => { }); test(`${features[7].name},${features[7].tags}`, async ({ page, baseURL }) => { - console.info(`[Test Page]: ${baseURL}${features[7].path}`); + console.info(`[Test Page]: ${baseURL}${features[7].path}${miloLibs}`); const { data } = features[7]; await test.step('step-1: Go to Text (link-farm) block test page', async () => { - await page.goto(`${baseURL}${features[7].path}`); + await page.goto(`${baseURL}${features[7].path}${miloLibs}`); await page.waitForLoadState('domcontentloaded'); - await expect(page).toHaveURL(`${baseURL}${features[7].path}`); + await expect(page).toHaveURL(`${baseURL}${features[7].path}${miloLibs}`); }); await test.step('step-2: Verify Text (link-farm) specs', async () => { diff --git a/tests/milo/video.block.test.js b/tests/milo/video.block.test.js index b99976a8..1b8bd4b5 100644 --- a/tests/milo/video.block.test.js +++ b/tests/milo/video.block.test.js @@ -6,6 +6,7 @@ import VideoBlock from '../../selectors/milo/video.block.page.js'; let webUtil; let video; let consoleErrors = []; +const miloLibs = process.env.MILO_LIBS || ''; const knownConsoleErrors = ['Access-Control-Allow-Origin','Failed to load resource: net::ERR_FAILED']; test.describe('Milo Video Block test suite', () => { @@ -26,13 +27,13 @@ test.describe('Milo Video Block test suite', () => { // Test 0 : Video default test(`${features[0].name},${features[0].tags}`, async ({ page, baseURL }) => { - console.info(`[Test Page]: ${baseURL}${features[0].path}`); + console.info(`[Test Page]: ${baseURL}${features[0].path}${miloLibs}`); const { data } = features[0]; await test.step('step-1: Go to video block test page', async () => { - await page.goto(`${baseURL}${features[0].path}`); + await page.goto(`${baseURL}${features[0].path}${miloLibs}`); await page.waitForLoadState('domcontentloaded'); - await expect(page).toHaveURL(`${baseURL}${features[0].path}`); + await expect(page).toHaveURL(`${baseURL}${features[0].path}${miloLibs}`); }); await test.step('step-2: Verify video block content/specs', async () => { @@ -51,13 +52,13 @@ test.describe('Milo Video Block test suite', () => { // Test 1 : Video autoplay loop test(`${features[1].name},${features[1].tags}`, async ({ page, baseURL }) => { - console.info(`[Test Page]: ${baseURL}${features[1].path}`); + console.info(`[Test Page]: ${baseURL}${features[1].path}${miloLibs}`); const { data } = features[1]; await test.step('step-1: Go to video block test page', async () => { - await page.goto(`${baseURL}${features[1].path}`); + await page.goto(`${baseURL}${features[1].path}${miloLibs}`); await page.waitForLoadState('domcontentloaded'); - await expect(page).toHaveURL(`${baseURL}${features[1].path}`); + await expect(page).toHaveURL(`${baseURL}${features[1].path}${miloLibs}`); }); await test.step('step-2: Verify video block content/specs', async () => { @@ -76,13 +77,13 @@ test.describe('Milo Video Block test suite', () => { // Test 2 : Video autoplay loop once test(`${features[2].name},${features[2].tags}`, async ({ page, baseURL }) => { - console.info(`[Test Page]: ${baseURL}${features[2].path}`); + console.info(`[Test Page]: ${baseURL}${features[2].path}${miloLibs}`); const { data } = features[2]; await test.step('step-1: Go to video block test page', async () => { - await page.goto(`${baseURL}${features[2].path}`); + await page.goto(`${baseURL}${features[2].path}${miloLibs}`); await page.waitForLoadState('domcontentloaded'); - await expect(page).toHaveURL(`${baseURL}${features[2].path}`); + await expect(page).toHaveURL(`${baseURL}${features[2].path}${miloLibs}`); }); await test.step('step-2: Verify video block content/specs', async () => { @@ -101,13 +102,13 @@ test.describe('Milo Video Block test suite', () => { // Test 3 : Video hover play test(`${features[3].name},${features[3].tags}`, async ({ page, baseURL }) => { - console.info(`[Test Page]: ${baseURL}${features[3].path}`); + console.info(`[Test Page]: ${baseURL}${features[3].path}${miloLibs}`); const { data } = features[3]; await test.step('step-1: Go to video block test page', async () => { - await page.goto(`${baseURL}${features[3].path}`); + await page.goto(`${baseURL}${features[3].path}${miloLibs}`); await page.waitForLoadState('domcontentloaded'); - await expect(page).toHaveURL(`${baseURL}${features[3].path}`); + await expect(page).toHaveURL(`${baseURL}${features[3].path}${miloLibs}`); }); await test.step('step-2: Verify video block content/specs', async () => { @@ -129,13 +130,13 @@ test.describe('Milo Video Block test suite', () => { // Test 4 : MPC Video test(`${features[4].name},${features[4].tags}`, async ({ page, baseURL }) => { test.slow(); - console.info(`[Test Page]: ${baseURL}${features[4].path}`); + console.info(`[Test Page]: ${baseURL}${features[4].path}${miloLibs}`); const { data } = features[4]; await test.step('step-1: Go to video block test page', async () => { - await page.goto(`${baseURL}${features[4].path}`); + await page.goto(`${baseURL}${features[4].path}${miloLibs}`); await page.waitForLoadState('domcontentloaded'); - await expect(page).toHaveURL(`${baseURL}${features[4].path}`); + await expect(page).toHaveURL(`${baseURL}${features[4].path}${miloLibs}`); }); await test.step('step-2: Verify video block content/specs', async () => { @@ -158,13 +159,13 @@ test.describe('Milo Video Block test suite', () => { // Test 5 : MPC Video Autoplay Looping test(`${features[5].name},${features[5].tags}`, async ({ page, baseURL }) => { test.slow(); - console.info(`[Test Page]: ${baseURL}${features[5].path}`); + console.info(`[Test Page]: ${baseURL}${features[5].path}${miloLibs}`); const { data } = features[5]; await test.step('step-1: Go to video block test page', async () => { - await page.goto(`${baseURL}${features[5].path}`); + await page.goto(`${baseURL}${features[5].path}${miloLibs}`); await page.waitForLoadState('domcontentloaded'); - await expect(page).toHaveURL(`${baseURL}${features[5].path}`); + await expect(page).toHaveURL(`${baseURL}${features[5].path}${miloLibs}`); }); await test.step('step-2: Verify video block content/specs', async () => { @@ -186,13 +187,13 @@ test.describe('Milo Video Block test suite', () => { // Test 6 : Youtube Video test(`${features[6].name},${features[6].tags}`, async ({ page, baseURL }) => { test.slow(); - console.info(`[Test Page]: ${baseURL}${features[6].path}`); + console.info(`[Test Page]: ${baseURL}${features[6].path}${miloLibs}`); const { data } = features[6]; await test.step('step-1: Go to video block test page', async () => { - await page.goto(`${baseURL}${features[6].path}`); + await page.goto(`${baseURL}${features[6].path}${miloLibs}`); await page.waitForLoadState('domcontentloaded'); - await expect(page).toHaveURL(`${baseURL}${features[6].path}`); + await expect(page).toHaveURL(`${baseURL}${features[6].path}${miloLibs}`); }); await test.step('step-2: Verify video block content/specs', async () => { @@ -214,13 +215,13 @@ test.describe('Milo Video Block test suite', () => { // Test 7 : Modal Video default test(`${features[7].name},${features[7].tags}`, async ({ page, baseURL }) => { test.slow(); - console.info(`[Test Page]: ${baseURL}${features[7].path}`); + console.info(`[Test Page]: ${baseURL}${features[7].path}${miloLibs}`); const { data } = features[7]; await test.step('step-1: Go to video block test page', async () => { - await page.goto(`${baseURL}${features[7].path}`); + await page.goto(`${baseURL}${features[7].path}${miloLibs}`); await page.waitForLoadState('domcontentloaded'); - await expect(page).toHaveURL(`${baseURL}${features[7].path}`); + await expect(page).toHaveURL(`${baseURL}${features[7].path}${miloLibs}`); }); await test.step('step-2: Verify video block content/specs', async () => { @@ -243,13 +244,13 @@ test.describe('Milo Video Block test suite', () => { // Test 8 : Modal video with cards test(`${features[8].name},${features[8].tags}`, async ({ page, baseURL,browserName }) => { test.slow(); - console.info(`[Test Page]: ${baseURL}${features[8].path}`); + console.info(`[Test Page]: ${baseURL}${features[8].path}${miloLibs}`); const { data } = features[8]; await test.step('step-1: Go to video block test page', async () => { - await page.goto(`${baseURL}${features[8].path}`); + await page.goto(`${baseURL}${features[8].path}${miloLibs}`); await page.waitForLoadState('domcontentloaded'); - await expect(page).toHaveURL(`${baseURL}${features[8].path}`); + await expect(page).toHaveURL(`${baseURL}${features[8].path}${miloLibs}`); }); await test.step('step-2: Verify consonant cards with modal video block content/specs', async () => { diff --git a/tests/milo/zpattern.block.test.js b/tests/milo/zpattern.block.test.js index 2930397e..85b7adb0 100644 --- a/tests/milo/zpattern.block.test.js +++ b/tests/milo/zpattern.block.test.js @@ -6,6 +6,8 @@ import ZPatternBlock from '../../selectors/milo/zpattern.block.page.js'; let webUtil; let zpattern; +const miloLibs = process.env.MILO_LIBS || ''; + test.describe('Milo Z Pattern Block test suite', () => { test.beforeEach(async ({ page }) => { webUtil = new WebUtil(page); @@ -14,13 +16,13 @@ test.describe('Milo Z Pattern Block test suite', () => { // Test 0 : ZPattern default block test(`${features[0].name},${features[0].tags}`, async ({ page, baseURL }) => { - console.info(`[Test Page]: ${baseURL}${features[0].path}`); + console.info(`[Test Page]: ${baseURL}${features[0].path}${miloLibs}`); const { data } = features[0]; await test.step('step-1: Go to Z Pattern block test page', async () => { - await page.goto(`${baseURL}${features[0].path}`); + await page.goto(`${baseURL}${features[0].path}${miloLibs}`); await page.waitForLoadState('domcontentloaded'); - await expect(page).toHaveURL(`${baseURL}${features[0].path}`); + await expect(page).toHaveURL(`${baseURL}${features[0].path}${miloLibs}`); }); await test.step('step-2: Verify Z Pattern block specs', async () => { @@ -53,13 +55,13 @@ test.describe('Milo Z Pattern Block test suite', () => { // Test 1 :ZPattern (small) block test(`${features[1].name},${features[1].tags}`, async ({ page, baseURL }) => { - console.info(`[Test Page]: ${baseURL}${features[1].path}`); + console.info(`[Test Page]: ${baseURL}${features[1].path}${miloLibs}`); const { data } = features[1]; await test.step('step-1: Go to z-pattern (small) block test page', async () => { - await page.goto(`${baseURL}${features[1].path}`); + await page.goto(`${baseURL}${features[1].path}${miloLibs}`); await page.waitForLoadState('domcontentloaded'); - await expect(page).toHaveURL(`${baseURL}${features[1].path}`); + await expect(page).toHaveURL(`${baseURL}${features[1].path}${miloLibs}`); }); await test.step('step-2: Verify z-pattern (small) block specs', async () => { @@ -92,13 +94,13 @@ test.describe('Milo Z Pattern Block test suite', () => { // Test 2 :Zpattern (large) block test(`${features[2].name},${features[2].tags}`, async ({ page, baseURL }) => { - console.info(`[Test Page]: ${baseURL}${features[2].path}`); + console.info(`[Test Page]: ${baseURL}${features[2].path}${miloLibs}`); const { data } = features[2]; await test.step('step-1: Go to z-pattern (large) block test page', async () => { - await page.goto(`${baseURL}${features[2].path}`); + await page.goto(`${baseURL}${features[2].path}${miloLibs}`); await page.waitForLoadState('domcontentloaded'); - await expect(page).toHaveURL(`${baseURL}${features[2].path}`); + await expect(page).toHaveURL(`${baseURL}${features[2].path}${miloLibs}`); }); await test.step('step-2: Verify z-pattern (large) block specs', async () => { @@ -131,13 +133,13 @@ test.describe('Milo Z Pattern Block test suite', () => { // Test 3 :Zpattern (dark) block test(`${features[3].name},${features[3].tags}`, async ({ page, baseURL }) => { - console.info(`[Test Page]: ${baseURL}${features[3].path}`); + console.info(`[Test Page]: ${baseURL}${features[3].path}${miloLibs}`); const { data } = features[3]; await test.step('step-1: Go to z-pattern (large) block test page', async () => { - await page.goto(`${baseURL}${features[3].path}`); + await page.goto(`${baseURL}${features[3].path}${miloLibs}`); await page.waitForLoadState('domcontentloaded'); - await expect(page).toHaveURL(`${baseURL}${features[3].path}`); + await expect(page).toHaveURL(`${baseURL}${features[3].path}${miloLibs}`); }); await test.step('step-2: Verify z-pattern (dark) block specs', async () => { From 5311c9438145a18236da8a23eec9df257299337e Mon Sep 17 00:00:00 2001 From: Jacky Sun <67350368+JackySun9@users.noreply.github.com> Date: Fri, 12 Jan 2024 11:00:36 -0800 Subject: [PATCH 49/53] update final path for CC quiz (#241) * add test for quiz and result pages * add test for quiz and result pages * add test for quiz and result pages * add POC for analytics test * update analytics tests and envs * result envs * update analytics only on firefox * add dynamic tests * add dynamic test for quiz page * update quiz test * update test structure * add test for quiz and result pages * add POC for analytics test * update analytics tests and envs * result envs * update analytics only on firefox * add dynamic tests * add dynamic test for quiz page * update quiz test * update test structure * update uar tests to new format * update uar tests * move everything to uar folder * add dependency for js-yaml * update test according to latest comments * update test according to latest comments * update tests according to the latest comments * add uar config * add analytics for uar * update according to feedbacks * update tags * add @cc tag * update according to feedbacks * add dynamic tests for uar * update according to review comments * fix some typos * update according to review comments * merge console log info * add UI screenshots for UAR * move view point to test * update according to feedback * add analytics test for UAR * update validation and uar libs * update libs * update by feedback * update some config and tests * update some config and tests * update test content path to common path * update analytics tests * fix test failures caused by test code * fix test failures * fix test failures * add visual test for CAAS with two pages * update according to feedbacks * update report in config file * add screenshot for milo main live vs uar-integration live * add timestamp js for time stampe recording * add screenshot diff for uar stable and beta * move uar screenshots into visual compare folder * add UI screenshots for DX Quiz * build a function to get screenshots * update locator * udate uar to only run basic tests * update according to feedback * add screenshot for UAR in CC which will go live * update final path for UAR in CC * update the final CC path --------- Co-authored-by: xiasun Co-authored-by: Aaron Mauchley Co-authored-by: xiasun --- features/cc/quiz.screenshots.spec.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/features/cc/quiz.screenshots.spec.js b/features/cc/quiz.screenshots.spec.js index 6f953729..a61f9dd3 100644 --- a/features/cc/quiz.screenshots.spec.js +++ b/features/cc/quiz.screenshots.spec.js @@ -4,7 +4,7 @@ module.exports = { { tcid: '0', name: '@quiz screenshots', - path: '/creativecloud/plan-recommender/', + path: '/creativecloud/plan-recommender/quiz', tags: '@cc @uar-quiz-screenshots @uar-quiz-static', data: 'data/cc/quiz/quiz-basic.yml', }, From 74f675136d2750e2e48a19db9a2360c270c2ec5a Mon Sep 17 00:00:00 2001 From: Jacky Sun <67350368+JackySun9@users.noreply.github.com> Date: Thu, 18 Jan 2024 14:05:02 -0800 Subject: [PATCH 50/53] Update CC UAR to hlx.live vs stage (#243) * add test for quiz and result pages * add test for quiz and result pages * add test for quiz and result pages * add POC for analytics test * update analytics tests and envs * result envs * update analytics only on firefox * add dynamic tests * add dynamic test for quiz page * update quiz test * update test structure * add test for quiz and result pages * add POC for analytics test * update analytics tests and envs * result envs * update analytics only on firefox * add dynamic tests * add dynamic test for quiz page * update quiz test * update test structure * update uar tests to new format * update uar tests * move everything to uar folder * add dependency for js-yaml * update test according to latest comments * update test according to latest comments * update tests according to the latest comments * add uar config * add analytics for uar * update according to feedbacks * update tags * add @cc tag * update according to feedbacks * add dynamic tests for uar * update according to review comments * fix some typos * update according to review comments * merge console log info * add UI screenshots for UAR * move view point to test * update according to feedback * add analytics test for UAR * update validation and uar libs * update libs * update by feedback * update some config and tests * update some config and tests * update test content path to common path * update analytics tests * fix test failures caused by test code * fix test failures * fix test failures * add visual test for CAAS with two pages * update according to feedbacks * update report in config file * add screenshot for milo main live vs uar-integration live * add timestamp js for time stampe recording * add screenshot diff for uar stable and beta * move uar screenshots into visual compare folder * add UI screenshots for DX Quiz * build a function to get screenshots * update locator * udate uar to only run basic tests * update according to feedback * add screenshot for UAR in CC which will go live * update final path for UAR in CC * update the final CC path * update cc uar screenshots to hlx.live vs stage --------- Co-authored-by: xiasun Co-authored-by: Aaron Mauchley Co-authored-by: xiasun --- features/cc/quiz.screenshots.spec.js | 2 ++ tests/cc/quiz.screenshots.test.js | 54 ++++++++++++++++------------ 2 files changed, 34 insertions(+), 22 deletions(-) diff --git a/features/cc/quiz.screenshots.spec.js b/features/cc/quiz.screenshots.spec.js index a61f9dd3..a941751c 100644 --- a/features/cc/quiz.screenshots.spec.js +++ b/features/cc/quiz.screenshots.spec.js @@ -5,6 +5,8 @@ module.exports = { tcid: '0', name: '@quiz screenshots', path: '/creativecloud/plan-recommender/quiz', + stable: '@adobe_stage', + beta: '@cc_live', tags: '@cc @uar-quiz-screenshots @uar-quiz-static', data: 'data/cc/quiz/quiz-basic.yml', }, diff --git a/tests/cc/quiz.screenshots.test.js b/tests/cc/quiz.screenshots.test.js index bbab3e39..3cb92d1b 100644 --- a/tests/cc/quiz.screenshots.test.js +++ b/tests/cc/quiz.screenshots.test.js @@ -3,12 +3,10 @@ /* eslint-disable no-restricted-syntax */ import { expect, test } from '@playwright/test'; import Quiz from '../../selectors/uar/quiz.page.js'; -import QuizOldPage from '../../selectors/uar/quiz.old.page.js'; -const QuizSpec = require('../../features/cc/quiz.screenshots.spec.js'); - -const { features } = QuizSpec; +const { features } = require('../../features/cc/quiz.screenshots.spec.js'); const { WebUtil } = require('../../libs/webutil.js'); +const envs = require('../../envs/envs.js'); test.describe('Quiz flow test suite', () => { // reset timeout because we use this to run all test data @@ -16,11 +14,13 @@ test.describe('Quiz flow test suite', () => { for (const feature of features) { test( `${feature.name}, ${feature.tags}`, - async ({ page, baseURL }) => { - const quiz = new Quiz(page); - const quizOldPage = new QuizOldPage(page); - const url = `${baseURL}${feature.path}`; - console.info(url); + async ({ page }) => { + const stablePage = new Quiz(page); + const betaPage = new Quiz(page); + const stableURL = `${envs[feature.stable]}${feature.path}`; + console.info(stableURL); + const betaURL = `${envs[feature.beta]}${feature.path}`; + console.info(betaURL); // load test data from static files const testdata = await WebUtil.loadTestData(`${feature.data}`); @@ -29,17 +29,11 @@ test.describe('Quiz flow test suite', () => { for (let key of Object.keys(testdata)) { console.log(key); - let oldProduct = ''; - let newProduct = ''; + let stableProduct = ''; + let betaProduct = ''; + let stableProductScreenshots = []; + let betaProductScreenshots = []; keyNumber += 1; - await test.step(`Old: Select each answer on test page according to ${key}`, async () => { - await quizOldPage.clickEachAnswer('https://www.adobe.com/creativecloud/quiz-recommender.html', key, keyNumber, true); - }); - - await test.step('Old: Check results on test page', async () => { - oldProduct = await quizOldPage.checkResultPage(testdata[key], key, keyNumber, true); - }); - if (key.includes('PDFs > Edit quickly')) { // eslint-disable-next-line no-continue continue; @@ -49,15 +43,31 @@ test.describe('Quiz flow test suite', () => { key = key.replace('PDFs > Take the time to control every detail', 'PDFs'); } + await test.step(`Old: Select each answer on test page according to ${key}`, async () => { + await stablePage.clickEachAnswer(stableURL, key, keyNumber, 'stable', true); + }); + + await test.step('Old: Check results on test page', async () => { + stableProduct = await stablePage.checkResultPage(testdata[key], key, keyNumber, 'stable', true); + }); + + stableProductScreenshots = stablePage.screenshots.slice(); + stablePage.screenshots = []; + await test.step(`New: Select each answer on test page according to ${key}`, async () => { - await quiz.clickEachAnswer(url, key, keyNumber, 'new', true); + await betaPage.clickEachAnswer(betaURL, key, keyNumber, 'beta', true); }); await test.step('New: Check results on test page', async () => { - newProduct = await quiz.checkResultPage(testdata[key], key, keyNumber, 'new', true); + betaProduct = await betaPage.checkResultPage(testdata[key], key, keyNumber, 'beta', true); }); - // expect.soft(newProduct).toContain(oldProduct); + betaProductScreenshots = betaPage.screenshots.slice(); + betaPage.screenshots = []; + + WebUtil.compareScreenshots(stableProductScreenshots, betaProductScreenshots, 'screenshots/uar'); + + expect.soft(betaProduct).toContain(stableProduct); } }, ); From dff3d47f8f93bc5b34bca353ae86a9af2b292727 Mon Sep 17 00:00:00 2001 From: Jacky Sun <67350368+JackySun9@users.noreply.github.com> Date: Fri, 19 Jan 2024 10:30:07 -0800 Subject: [PATCH 51/53] Update screenshot test (#245) * add test for quiz and result pages * add test for quiz and result pages * add test for quiz and result pages * add POC for analytics test * update analytics tests and envs * result envs * update analytics only on firefox * add dynamic tests * add dynamic test for quiz page * update quiz test * update test structure * add test for quiz and result pages * add POC for analytics test * update analytics tests and envs * result envs * update analytics only on firefox * add dynamic tests * add dynamic test for quiz page * update quiz test * update test structure * update uar tests to new format * update uar tests * move everything to uar folder * add dependency for js-yaml * update test according to latest comments * update test according to latest comments * update tests according to the latest comments * add uar config * add analytics for uar * update according to feedbacks * update tags * add @cc tag * update according to feedbacks * add dynamic tests for uar * update according to review comments * fix some typos * update according to review comments * merge console log info * add UI screenshots for UAR * move view point to test * update according to feedback * add analytics test for UAR * update validation and uar libs * update libs * update by feedback * update some config and tests * update some config and tests * update test content path to common path * update analytics tests * fix test failures caused by test code * fix test failures * fix test failures * add visual test for CAAS with two pages * update according to feedbacks * update report in config file * add screenshot for milo main live vs uar-integration live * add timestamp js for time stampe recording * add screenshot diff for uar stable and beta * move uar screenshots into visual compare folder * add UI screenshots for DX Quiz * build a function to get screenshots * update locator * udate uar to only run basic tests * update according to feedback * add screenshot for UAR in CC which will go live * update final path for UAR in CC * update the final CC path * update cc uar screenshots to hlx.live vs stage * update test --------- Co-authored-by: xiasun Co-authored-by: Aaron Mauchley Co-authored-by: xiasun --- tests/cc/quiz.screenshots.test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/cc/quiz.screenshots.test.js b/tests/cc/quiz.screenshots.test.js index 3cb92d1b..5d487e6c 100644 --- a/tests/cc/quiz.screenshots.test.js +++ b/tests/cc/quiz.screenshots.test.js @@ -67,7 +67,7 @@ test.describe('Quiz flow test suite', () => { WebUtil.compareScreenshots(stableProductScreenshots, betaProductScreenshots, 'screenshots/uar'); - expect.soft(betaProduct).toContain(stableProduct); + // expect.soft(betaProduct).toContain(stableProduct); } }, ); From 5c5c9ea2fa2c795cd9d70617dec3991ce716c5b9 Mon Sep 17 00:00:00 2001 From: Jacky Sun <67350368+JackySun9@users.noreply.github.com> Date: Fri, 19 Jan 2024 12:26:51 -0800 Subject: [PATCH 52/53] Update screenshot tests (#246) * add test for quiz and result pages * add test for quiz and result pages * add test for quiz and result pages * add POC for analytics test * update analytics tests and envs * result envs * update analytics only on firefox * add dynamic tests * add dynamic test for quiz page * update quiz test * update test structure * add test for quiz and result pages * add POC for analytics test * update analytics tests and envs * result envs * update analytics only on firefox * add dynamic tests * add dynamic test for quiz page * update quiz test * update test structure * update uar tests to new format * update uar tests * move everything to uar folder * add dependency for js-yaml * update test according to latest comments * update test according to latest comments * update tests according to the latest comments * add uar config * add analytics for uar * update according to feedbacks * update tags * add @cc tag * update according to feedbacks * add dynamic tests for uar * update according to review comments * fix some typos * update according to review comments * merge console log info * add UI screenshots for UAR * move view point to test * update according to feedback * add analytics test for UAR * update validation and uar libs * update libs * update by feedback * update some config and tests * update some config and tests * update test content path to common path * update analytics tests * fix test failures caused by test code * fix test failures * fix test failures * add visual test for CAAS with two pages * update according to feedbacks * update report in config file * add screenshot for milo main live vs uar-integration live * add timestamp js for time stampe recording * add screenshot diff for uar stable and beta * move uar screenshots into visual compare folder * add UI screenshots for DX Quiz * build a function to get screenshots * update locator * udate uar to only run basic tests * update according to feedback * add screenshot for UAR in CC which will go live * update final path for UAR in CC * update the final CC path * update cc uar screenshots to hlx.live vs stage * update test * update screenshot test --------- Co-authored-by: xiasun Co-authored-by: Aaron Mauchley Co-authored-by: xiasun --- data/cc/quiz/quiz-basic.yml | 2 +- data/uar/quiz/quiz-basic.yml | 2 +- visual-compare-tests/uar/quiz.vc.test.js | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/data/cc/quiz/quiz-basic.yml b/data/cc/quiz/quiz-basic.yml index 8133df3a..0957d743 100644 --- a/data/cc/quiz/quiz-basic.yml +++ b/data/cc/quiz/quiz-basic.yml @@ -13,5 +13,5 @@ 'Photography + Video + PDFs > Take the time to control every detail > Get them sorted and organized > Create, edit, and share on social > Create and export PDFs to Office > A student or teacher discount': 'flagship triple > Premiere Pro,Lightroom,Acrobat' '3D/AR > Assemble, stage, and render 3D scenes > Neither apply': '3D single > Substance 3D Stager' -'Photography + 3D/AR > Get them sorted and organized > Create 3D models with digital clay > A student or teacher discount': '3D doouble > Lightroom,Substance 3D Modeler' +'Photography + 3D/AR > Get them sorted and organized > Create 3D models with digital clay > A student or teacher discount': '3D double > Lightroom,Substance 3D Modeler' 'Photography + Video + 3D/AR > Get them sorted and organized > Create, edit, and share on social > Texture 3D assets in real time > Licenses and business features for teams': '3D triple > Lightroom,Premiere Pro,Substance 3D Painter' diff --git a/data/uar/quiz/quiz-basic.yml b/data/uar/quiz/quiz-basic.yml index 8133df3a..0957d743 100644 --- a/data/uar/quiz/quiz-basic.yml +++ b/data/uar/quiz/quiz-basic.yml @@ -13,5 +13,5 @@ 'Photography + Video + PDFs > Take the time to control every detail > Get them sorted and organized > Create, edit, and share on social > Create and export PDFs to Office > A student or teacher discount': 'flagship triple > Premiere Pro,Lightroom,Acrobat' '3D/AR > Assemble, stage, and render 3D scenes > Neither apply': '3D single > Substance 3D Stager' -'Photography + 3D/AR > Get them sorted and organized > Create 3D models with digital clay > A student or teacher discount': '3D doouble > Lightroom,Substance 3D Modeler' +'Photography + 3D/AR > Get them sorted and organized > Create 3D models with digital clay > A student or teacher discount': '3D double > Lightroom,Substance 3D Modeler' 'Photography + Video + 3D/AR > Get them sorted and organized > Create, edit, and share on social > Texture 3D assets in real time > Licenses and business features for teams': '3D triple > Lightroom,Premiere Pro,Substance 3D Painter' diff --git a/visual-compare-tests/uar/quiz.vc.test.js b/visual-compare-tests/uar/quiz.vc.test.js index 028e5920..d9147682 100644 --- a/visual-compare-tests/uar/quiz.vc.test.js +++ b/visual-compare-tests/uar/quiz.vc.test.js @@ -58,7 +58,7 @@ test.describe('Quiz flow test suite', () => { WebUtil.compareScreenshots(stableProductScreenshots, betaProductScreenshots, 'screenshots/uar'); - expect.soft(betaProduct).toContain(stableProduct); + // expect.soft(betaProduct).toContain(stableProduct); } }, ); From d3dd709c3acb74caf3b7c1e0c4e820ebab507a33 Mon Sep 17 00:00:00 2001 From: sigadamramesh <130433161+sigadamvenkata@users.noreply.github.com> Date: Mon, 22 Jan 2024 20:48:49 +0530 Subject: [PATCH 53/53] CC Merchtable block automation (#248) CC Merchtable block automation (JIra: MWPW-140978) --- features/cc/merchtable.spec.js | 42 ++++++++++++++ selectors/cc/merchtable.page.js | 30 ++++++++++ tests/cc/merchtable.test.js | 97 +++++++++++++++++++++++++++++++++ 3 files changed, 169 insertions(+) create mode 100644 features/cc/merchtable.spec.js create mode 100644 selectors/cc/merchtable.page.js create mode 100644 tests/cc/merchtable.test.js diff --git a/features/cc/merchtable.spec.js b/features/cc/merchtable.spec.js new file mode 100644 index 00000000..3e5da79f --- /dev/null +++ b/features/cc/merchtable.spec.js @@ -0,0 +1,42 @@ +module.exports = { +name: 'merchtable', + features: [ + { + tcid: '0', + name: '@merchtable-3column-layout-block', + path: '/drafts/Automation-PW/merch-table?georouting=off', + tags: '@cc @cc-merchtable @cc-merchtableui', + }, + { + tcid: '1', + name: '@merchtable-headrowitems', + path: '/drafts/Automation-PW/merch-table?georouting=off', + tags: '@cc @cc-merchtable @cc-merchtableheadrow', + }, + { + tcid: '2', + name: '@merchtable-rowheadprices', + path: '/drafts/Automation-PW/merch-table?georouting=off', + tags: '@cc @cc-merchtable @cc-merchtableprices', + data: { + ccIndividualPrice: 'US$54.99/mo', + ccStudentPrice: 'US$9.99/mo', + ccTeamsprice: 'US$22.99/mo', + ccTeamsStrikeThrough: 'Regularly at US$54.99 per month' + }, + }, + { + tcid: '3', + name: '@merchtable-appdetails', + path: '/drafts/Automation-PW/merch-table?georouting=off', + tags: '@cc @cc-merchtable @cc-appdeatilsinrows', + }, + { + tcid: '4', + name: '@merchtable-priceCTA', + path: '/drafts/Automation-PW/merch-table?georouting=off', + tags: '@cc @cc-merchtable @cc-PriceCtacommerce', + commerceurl : 'https://commerce.adobe.com/store/commitment?items%5B0%5D%5Bid%5D=632B3ADD940A7FBB7864AA5AD19B8D28&cli=adobe_com&co=IN&ctx=fp&lang=en', + }, + ], +}; diff --git a/selectors/cc/merchtable.page.js b/selectors/cc/merchtable.page.js new file mode 100644 index 00000000..cdae4590 --- /dev/null +++ b/selectors/cc/merchtable.page.js @@ -0,0 +1,30 @@ +export default class merchtable { + constructor(page) { + this.page = page; + // merch table page UI selectors to check 3 column layout + this.merchTableSection = page.locator('.section.table-merch-section'); + this.firstColumn = this.merchTableSection.locator('.col.col-1.col-heading'); + this.secondColumn = this.merchTableSection.locator('.col.col-2.col-heading.light'); + this.thirdColumn = this.merchTableSection.locator('.col.col-3.col-heading.dark'); + this.productMnemonics = page.locator('//img[@src="./media_139dede8055046fb80034053bbe235aaadc823b7a.png?width=750&format=png&optimize=medium"]').first(); + //@merchtable-headrowitems + this.FirstRowHeading = page.locator('.row.row-1.row-heading'); + this.firstColumnHeading = this.FirstRowHeading.locator('.col.col-1.col-heading'); + this.secondColumnHeading = this.FirstRowHeading.locator('.col.col-2.col-heading.light'); + this.thirdColumnHeading = this.FirstRowHeading.locator('.col.col-3.col-heading.dark'); + this.fixedColumnheading = page.locator('//div[@class="section-head-title col col-1"]//strong[text()="Includes:"]'); + //@merchtable-rowheadprices + this.ccIndividaulProductPrice = page.locator('.price.price-optical').nth(0); + this.ccStudentProductPrice = page.locator('.price.price-optical').nth(1); + this.ccTeamsProductPrice = page.locator('.price').nth(2); + this.freeTrialBtn = page.locator('.con-button.outline.button-l').first(); + this.buyNowBtn = page.locator('.con-button.blue.button-l').first(); + //@merchtable-appdetails + this.listOfAppsInRows1 = page.locator('.col-merch-content').nth(0); + this.appPhotoshop = this.listOfAppsInRows1.locator('//p[text()="Photoshop"]').nth(0); + this.listOfAppsInRows2 = page.locator('.col-merch-content').nth(4); + this.appFresco = this.listOfAppsInRows1.locator('//p[text()="fresco"]').nth(1); + this.listOfAppsInRows3 = page.locator('.col-merch-content').nth(8); + this.appPhotoshopExpress = this.listOfAppsInRows1.locator('//p[text()="Photoshop Express"]').nth(2); +} +}; diff --git a/tests/cc/merchtable.test.js b/tests/cc/merchtable.test.js new file mode 100644 index 00000000..b37c9f91 --- /dev/null +++ b/tests/cc/merchtable.test.js @@ -0,0 +1,97 @@ +import { expect, test } from '@playwright/test'; +import { features } from '../../features/cc/merchtable.spec.js'; +import Merchtable from '../../selectors/cc/merchtable.page.js'; + +let merchtable; +test.describe('verify merch table colum layout, headings, CSS styles, images rendering, price CTAs' , () => { + test.beforeEach(async ({ page }) => { + merchtable = new Merchtable(page); + }); + // Test merch table block to be shown 3 column layout when placed on page + test(`${features[0].name},${features[0].tags}`, async ({ page, baseURL }) => { + console.info(`[Test Page]: ${baseURL}${features[0].path}`); + await test.step('merch table should have 3 column layout when authored', async () => { + await page.goto(`${baseURL}${features[0].path}`); + await page.waitForLoadState('domcontentloaded'); + await expect(page).toHaveURL(`${baseURL}${features[0].path}`); + }); + await test.step('step-2: 3 columns should showup with memonics', async () => { + await page.waitForLoadState(); + expect(await merchtable.merchTableSection).toBeTruthy(); + expect(await merchtable.firstColumn).toBeTruthy(); + expect(await merchtable.secondColumn).toBeTruthy(); + expect(await merchtable.thirdColumn).toBeTruthy(); + expect(await merchtable.productMnemonics).toBeTruthy(); + }); + }); + + // Test merch table first row in the 3 column has heading + test(`${features[1].name},${features[1].tags}`, async ({ page, baseURL }) => { + console.info(`[Test Page]: ${baseURL}${features[1].path}`); + await test.step('merch table first row in the 3 column has product headings', async () => { + await page.goto(`${baseURL}${features[1].path}`); + await page.waitForLoadState('domcontentloaded'); + await expect(page).toHaveURL(`${baseURL}${features[1].path}`); + }); + await test.step('step-2: 3 columns first row is head column', async () => { + await page.waitForLoadState(); + expect(await merchtable.fixedColumnheading).toBeTruthy(); + expect(await merchtable.firstColumnHeading).toBeTruthy(); + expect(await merchtable.secondColumnHeading).toBeTruthy(); + expect(await merchtable.thirdColumnHeading).toBeTruthy(); + }); + }); + + // Test merch table column heading showing valid prodcut price with CTAs + test(`${features[2].name},${features[2].tags}`, async ({ page, baseURL }) => { + console.info(`[Test Page]: ${baseURL}${features[2].path}`); + const { data } = features[2]; + await test.step('merch table column heading has valid product prices and CTAs', async () => { + await page.goto(`${baseURL}${features[2].path}`); + await page.waitForLoadState('domcontentloaded'); + await expect(page).toHaveURL(`${baseURL}${features[2].path}`); + }); + await test.step('step-2: product price checks with CTAs', async () => { + await page.waitForLoadState(); + await expect(merchtable.freeTrialBtn).toBeVisible(); + await expect(merchtable.buyNowBtn).toBeVisible(); + await expect(merchtable.ccIndividaulProductPrice).toContainText(data.ccIndividualPrice); + await expect(merchtable.ccStudentProductPrice).toContainText(data.ccStudentPrice); + await expect(merchtable.ccTeamsProductPrice).toContainText(data.ccTeamsprice); + }); + }); + + // Test merch table app details rows in each product column + test(`${features[3].name},${features[3].tags}`, async ({ page, baseURL }) => { + console.info(`[Test Page]: ${baseURL}${features[3].path}`); + await test.step('merch table had product details in each column', async () => { + await page.goto(`${baseURL}${features[3].path}`); + await page.waitForLoadState('domcontentloaded'); + await expect(page).toHaveURL(`${baseURL}${features[3].path}`); + }); + await test.step('step-2: apps display in the colums as list', async () => { + await page.waitForLoadState(); + expect(await merchtable.appPhotoshop).toBeTruthy(); + expect(await merchtable.appFresco).toBeTruthy(); + expect(await merchtable.appPhotoshopExpress).toBeTruthy(); + }); + }); + + // Test buynow navigates to commerce page + test(`${features[4].name},${features[4].tags}`, async ({ page, baseURL }) => { + console.info(`[Test Page]: ${baseURL}${features[4].path}`); + const url = features[4].commerceurl; + await test.step('merch table had product details in each column', async () => { + await page.goto(`${baseURL}${features[4].path}`); + await page.waitForLoadState('domcontentloaded'); + await expect(page).toHaveURL(`${baseURL}${features[4].path}`); + }); + await test.step('step-2: CTA go to commerce page', async () => { + await page.waitForLoadState(); + await expect(merchtable.buyNowBtn).toBeVisible(); + await merchtable.buyNowBtn.click(); + await page.waitForTimeout(1000); + await expect(page).toHaveURL(url); + }); + }); +});