From 4f2373694341783994e4b846b500b06920bb634c Mon Sep 17 00:00:00 2001 From: Sigadam Venkata Ramesh Date: Sun, 30 Nov 2025 21:43:27 +0530 Subject: [PATCH 1/3] CC regression cases part 2 CC regression cases part 2 --- .../mediablockroundedcorners.page.js | 26 ++++++ .../mediablockroundedcorners.spec.js | 23 ++++++ .../mediablockroundedcorners.test.js | 50 ++++++++++++ nala/blocks/merchtable/merchtable.page.js | 30 +++++++ nala/blocks/merchtable/merchtable.spec.js | 35 ++++++++ nala/blocks/merchtable/merchtable.test.js | 79 +++++++++++++++++++ .../photoshop-unity/photoshop-unity.page.js | 21 +++++ .../photoshop-unity/photoshop-unity.spec.js | 11 +++ .../photoshop-unity/photoshop-unity.test.js | 31 ++++++++ nala/blocks/promobar/promobar.page.js | 15 ++++ nala/blocks/promobar/promobar.spec.js | 24 ++++++ nala/blocks/promobar/promobar.test.js | 57 +++++++++++++ nala/blocks/seocanonical/seocanonical.page.js | 12 +++ nala/blocks/seocanonical/seocanonical.spec.js | 17 ++++ nala/blocks/seocanonical/seocanonical.test.js | 35 ++++++++ 15 files changed, 466 insertions(+) create mode 100644 nala/blocks/mediablockroundedcorners/mediablockroundedcorners.page.js create mode 100644 nala/blocks/mediablockroundedcorners/mediablockroundedcorners.spec.js create mode 100644 nala/blocks/mediablockroundedcorners/mediablockroundedcorners.test.js create mode 100644 nala/blocks/merchtable/merchtable.page.js create mode 100644 nala/blocks/merchtable/merchtable.spec.js create mode 100644 nala/blocks/merchtable/merchtable.test.js create mode 100644 nala/blocks/photoshop-unity/photoshop-unity.page.js create mode 100644 nala/blocks/photoshop-unity/photoshop-unity.spec.js create mode 100644 nala/blocks/photoshop-unity/photoshop-unity.test.js create mode 100644 nala/blocks/promobar/promobar.page.js create mode 100644 nala/blocks/promobar/promobar.spec.js create mode 100644 nala/blocks/promobar/promobar.test.js create mode 100644 nala/blocks/seocanonical/seocanonical.page.js create mode 100644 nala/blocks/seocanonical/seocanonical.spec.js create mode 100644 nala/blocks/seocanonical/seocanonical.test.js diff --git a/nala/blocks/mediablockroundedcorners/mediablockroundedcorners.page.js b/nala/blocks/mediablockroundedcorners/mediablockroundedcorners.page.js new file mode 100644 index 000000000..6cbb596ce --- /dev/null +++ b/nala/blocks/mediablockroundedcorners/mediablockroundedcorners.page.js @@ -0,0 +1,26 @@ +export default class mediaroundedcorners { + constructor(page) { + this.page = page; + // Media rounded corners styles for both images and madia block UI locators + this.mediaRoundedCornerImageGroup = page.locator('.section.three-up.s-spacing'); + this.firstimagerow = this.mediaRoundedCornerImageGroup.locator('.media-row').nth(0); + this.secondimagerow = this.mediaRoundedCornerImageGroup.locator('.media-row').nth(1); + this.thirdimagerow = this.mediaRoundedCornerImageGroup.locator('.media-row').nth(2); + this.image_SmallRoundedCorners = this.mediaRoundedCornerImageGroup.locator('.media.s-rounded-corners-image.con-block.has-bg').first(); + this.image_MediumRoundedCorners = this.mediaRoundedCornerImageGroup.locator('media.m-rounded-corners-image.con-block.has-bg'); + this.image_LargeRoundedCorners = this.mediaRoundedCornerImageGroup.locator('media.l-rounded-corners-image.con-block.has-bg'); + this.mediaRoundedBlockGroup = page.locator('.section.two-up.s-spacing').first(); + this.firstMediaBlock = this.mediaRoundedBlockGroup.locator('.media.l-rounded-corners.con-block.has-bg'); + this.secondMediaBlock = this.mediaRoundedBlockGroup.locator('.media.large.dark.m-rounded-corners.s-rounded-corners-image.con-block.has-bg.media-reverse-mobile'); + this.imageWithInBlock = this.mediaRoundedBlockGroup.locator('//img[@src="./media_15701a692530b54cb77445d12a98ec8d5b498e188.jpeg?width=750&format=jpeg&optimize=medium"]'); + this.fullRoundedCornersBlock = page.locator('.media.l-rounded-corners.full-rounded-corners-image.con-block'); + this.fullRoundedcornerimage = this.fullRoundedCornersBlock.locator('//img[@src="./media_1f320de06e9c6a05dc899e773a62d93cf1149bb40.jpeg?width=750&format=jpeg&optimize=medium"]'); + // image & block rounded corner css property + this.cssProperties = { + smallRoundedCorners: { 'border-radius': '4px' }, + mediumRoundedCorners: { 'border-radius': '8px' }, + largeRoundedCorners: { 'border-radius': '16px' }, + fullRoundedCorners: { 'border-radius': '50%' }, + }; + } +} diff --git a/nala/blocks/mediablockroundedcorners/mediablockroundedcorners.spec.js b/nala/blocks/mediablockroundedcorners/mediablockroundedcorners.spec.js new file mode 100644 index 000000000..5c7ce6403 --- /dev/null +++ b/nala/blocks/mediablockroundedcorners/mediablockroundedcorners.spec.js @@ -0,0 +1,23 @@ +module.exports = { + name: 'mediaroundedcorners', + features: [ + { + tcid: '0', + name: 'media-roundedsmall', + path: '/drafts/Automation-PW/blocks/round-media-block?georouting=off', + tags: '@cc @cc-mediarounded @cc-imageroundedcornersmall', + }, + { + tcid: '1', + name: 'media-roundedmedium', + path: '/drafts/Automation-PW/blocks/round-media-block?georouting=off', + tags: '@cc @cc-mediarounded @cc-imageroundedcornermedium', + }, + { + tcid: '2', + name: 'media-roundedlarge', + path: '/drafts/Automation-PW/blocks/round-media-block?georouting=off', + tags: '@cc @cc-mediarounded @cc-imageroundedcornerlarge', + }, + ], +}; diff --git a/nala/blocks/mediablockroundedcorners/mediablockroundedcorners.test.js b/nala/blocks/mediablockroundedcorners/mediablockroundedcorners.test.js new file mode 100644 index 000000000..6dff6258d --- /dev/null +++ b/nala/blocks/mediablockroundedcorners/mediablockroundedcorners.test.js @@ -0,0 +1,50 @@ +import { expect, test } from '@playwright/test'; +import { features } from './mediablockroundedcorners.spec.js'; +import Mediaroundcorners from './mediablockroundedcorners.page.js'; + +let roundcorners; +test.describe('verify media rounder corners features for media block and its images', () => { + test.beforeEach(async ({ page }) => { + roundcorners = new Mediaroundcorners(page); + }); + test(`${features[0].name},${features[0].tags}`, async ({ page, baseURL }) => { + console.info(`[Test Page]: ${baseURL}${features[0].path}`); + await test.step('media block image with small 4x rounded corners', async () => { + await page.goto(`${baseURL}${features[0].path}`); + await page.waitForLoadState('domcontentloaded'); + await expect(page).toHaveURL(`${baseURL}${features[0].path}`); + }); + await test.step('media block image with small 4x rounded corners style', async () => { + await page.waitForLoadState(); + await expect(await roundcorners.mediaRoundedCornerImageGroup).toBeTruthy(); + await expect(await roundcorners.image_SmallRoundedCorners).toBeTruthy(); + }); + }); + test(`${features[1].name},${features[1].tags}`, async ({ page, baseURL }) => { + console.info(`[Test Page]: ${baseURL}${features[1].path}`); + await test.step('media block image with medium 8x rounded corners', async () => { + await page.goto(`${baseURL}${features[1].path}`); + await page.waitForLoadState('domcontentloaded'); + await expect(page).toHaveURL(`${baseURL}${features[1].path}`); + }); + await test.step('media block image with Medium 8x rounded corners style', async () => { + await page.waitForLoadState(); + await expect(await roundcorners.mediaRoundedCornerImageGroup).toBeTruthy(); + await expect(await roundcorners.image_MediumRoundedCorners).toBeTruthy(); + }); + }); + + test(`${features[2].name},${features[2].tags}`, async ({ page, baseURL }) => { + console.info(`[Test Page]: ${baseURL}${features[2].path}`); + await test.step('media block image with large 16x rounded corners', async () => { + await page.goto(`${baseURL}${features[2].path}`); + await page.waitForLoadState('domcontentloaded'); + await expect(page).toHaveURL(`${baseURL}${features[2].path}`); + }); + await test.step('media block image with large 16x rounded corners style', async () => { + await page.waitForLoadState(); + await expect(await roundcorners.mediaRoundedCornerImageGroup).toBeTruthy(); + await expect(await roundcorners.image_LargeRoundedCorners).toBeTruthy(); + }); + }); +}); diff --git a/nala/blocks/merchtable/merchtable.page.js b/nala/blocks/merchtable/merchtable.page.js new file mode 100644 index 000000000..1ee86ed82 --- /dev/null +++ b/nala/blocks/merchtable/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/nala/blocks/merchtable/merchtable.spec.js b/nala/blocks/merchtable/merchtable.spec.js new file mode 100644 index 000000000..b77e8e493 --- /dev/null +++ b/nala/blocks/merchtable/merchtable.spec.js @@ -0,0 +1,35 @@ +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', + }, + ], +}; diff --git a/nala/blocks/merchtable/merchtable.test.js b/nala/blocks/merchtable/merchtable.test.js new file mode 100644 index 000000000..0fbdd2342 --- /dev/null +++ b/nala/blocks/merchtable/merchtable.test.js @@ -0,0 +1,79 @@ +import { expect, test } from '@playwright/test'; +import { features } from './merchtable.spec.js'; +import Merchtable from './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(); + }); + }); +}); diff --git a/nala/blocks/photoshop-unity/photoshop-unity.page.js b/nala/blocks/photoshop-unity/photoshop-unity.page.js new file mode 100644 index 000000000..ec2bb1ab1 --- /dev/null +++ b/nala/blocks/photoshop-unity/photoshop-unity.page.js @@ -0,0 +1,21 @@ +export default class CCPhotoshopUnity { + constructor(page) { + this.page = page; + + this.unityBlock = page.locator('.upload-block.unity-enabled'); + this.uploadButton = this.unityBlock.locator("div.upload-grid.desktop-up button[type='button']"); + this.fileInput = this.unityBlock.locator('input[type="file"][id="file-upload"]').first(); + this.dropZone = this.unityBlock.locator('div.upload-grid.desktop-up >> div.drop-zone'); + this.alertContent = this.unityBlock.locator('div.upload-grid.desktop-up div.alert-content'); + this.dragAndDropText = this.unityBlock.locator('div.drop-zone p:has-text("Drag and drop an image")'); + this.videoElement = this.unityBlock.locator('div.upload-grid.desktop-up video'); + this.OnlineVideoElement = this.unityBlock.locator('div.media-container video'); + this.OnlinedropZoneText = this.unityBlock.locator('div.upload-grid.desktop-up div.drop-zone p:nth-child(1)'); + this.OnlineAgreementText = this.unityBlock.locator("//div[@class='upload-grid desktop-up']//p[contains(text(),'By uploading your')]"); + this.dropZoneParagraph = this.unityBlock.locator("div[class='upload-grid desktop-up'] div[class='drop-zone'] p").first(); + this.uploadDisclaimer = this.unityBlock.locator('div.upload-grid.desktop-up p', { hasText: 'By uploading your image or video' }); + this.removeBackgroundButton = page.locator('sp-action-button:has-text("Remove background")'); + this.progressHolder = page.locator('div.progress-holder'); + this.photoshopPreviewHeading = page.locator('h2#one-moment-as-we-take-you-to-photoshop-preview:has-text("One moment")').nth(0); + } +} diff --git a/nala/blocks/photoshop-unity/photoshop-unity.spec.js b/nala/blocks/photoshop-unity/photoshop-unity.spec.js new file mode 100644 index 000000000..a0f8374be --- /dev/null +++ b/nala/blocks/photoshop-unity/photoshop-unity.spec.js @@ -0,0 +1,11 @@ +module.exports = { + name: 'CC-Photoshop-Unity-Widget', + features: [ + { + tcid: '0', + name: '@CC-PhotoshopUnity-UI', + path: '/drafts/automation-pw/online?georouting=off', + tags: '@cc @cc-PSUnitywidget @cc-removeBGCheckUI', + }, + ], +}; diff --git a/nala/blocks/photoshop-unity/photoshop-unity.test.js b/nala/blocks/photoshop-unity/photoshop-unity.test.js new file mode 100644 index 000000000..f5d07a6f1 --- /dev/null +++ b/nala/blocks/photoshop-unity/photoshop-unity.test.js @@ -0,0 +1,31 @@ +import { expect, test } from '@playwright/test'; +import { features } from './photoshop-unity.spec.js'; +import CCPhotoshopUnity from './photoshop-unity.page.js'; + +let ccPhotoshopUnity; + +test.describe('Verify Photoshop Unity Widget functionality on Stage', () => { + test.beforeEach(async ({ page }) => { + ccPhotoshopUnity = new CCPhotoshopUnity(page); + }); + // close the page after each test + test.afterEach(async ({ page }) => { + await page.close(); + }); + + // check the page load and UI elements + test(`${features[0].name}, ${features[0].tags}`, async ({ page, baseURL }) => { + console.log(`Running test: ${features[0].name}`); + await test.step('Check page load and UI elements', async () => { + await page.goto(`${baseURL}${features[0].path}`); + await page.waitForLoadState('domcontentloaded'); + await expect(page).toHaveURL(`${baseURL}${features[0].path}`); + await expect(ccPhotoshopUnity.uploadButton).toBeTruthy(); + await expect(ccPhotoshopUnity.dropZone).toBeVisible(); + await expect(ccPhotoshopUnity.dragAndDropText).toBeVisible(); + await expect(ccPhotoshopUnity.videoElement).toBeVisible(); + await expect(ccPhotoshopUnity.dropZoneParagraph).toBeVisible(); + await expect(ccPhotoshopUnity.uploadDisclaimer).toBeVisible(); + }); + }); +}); diff --git a/nala/blocks/promobar/promobar.page.js b/nala/blocks/promobar/promobar.page.js new file mode 100644 index 000000000..9410f5b01 --- /dev/null +++ b/nala/blocks/promobar/promobar.page.js @@ -0,0 +1,15 @@ +export default class promocloseaction { + constructor(page) { + this.page = page; + // promobar with close action UI elements + this.promoBar = page.locator('.foreground.container').last(); + this.promoBarMobile = this.promoBar.locator('.mobile-up.promo-text'); + this.promoBarTablet = this.promoBar.locator('.tablet-up.promo-text'); + this.promoBarDesktop = this.promoBar.locator('.desktop-up.promo-text'); + this.PromoText = this.promoBarDesktop.locator('.text-area').nth(0); + this.promosticky = page.locator('.section.promo-sticky-section.popup.static-links.sticky-bottom'); + this.promoNotSticky = page.locator('.section.promo-sticky-section.popup.static-links.sticky-bottom.close-sticky-section'); + this.promoCTA = page.locator('.body-s.action-area').last(); + this.promoClose = page.locator('.promo-close'); + } +} diff --git a/nala/blocks/promobar/promobar.spec.js b/nala/blocks/promobar/promobar.spec.js new file mode 100644 index 000000000..0cd13ae14 --- /dev/null +++ b/nala/blocks/promobar/promobar.spec.js @@ -0,0 +1,24 @@ +module.exports = { + name: 'promocloseaction', + features: [ + { + tcid: '0', + name: '@promocloseaction-page', + path: '/drafts/Automation-PW/blocks/promocloseaction-pageload?georouting=off', + tags: '@cc @cc-promocloseaction @cc-promoui', + }, + { + tcid: '1', + name: '@promocloseaction-closebuttonfunction', + path: '/drafts/Automation-PW/blocks/promocloseaction-pageload?georouting=off', + tags: '@cc @cc-promocloseaction @cc-promoclosefeature', + }, + { + tcid: '2', + name: '@promocloseaction-getstart-CTA', + path: '/drafts/Automation-PW/blocks/promocloseaction-pageload?georouting=off', + tags: '@cc @cc-promocloseaction @cc-promogetctaaction', + url: 'https://www.adobe.com/creativecloud/plan-recommender/quiz.html', + }, + ], +}; diff --git a/nala/blocks/promobar/promobar.test.js b/nala/blocks/promobar/promobar.test.js new file mode 100644 index 000000000..52a7fb98a --- /dev/null +++ b/nala/blocks/promobar/promobar.test.js @@ -0,0 +1,57 @@ +import { expect, test } from '@playwright/test'; +import { features } from './promobar.spec.js'; +import Promocloseaction from './promobar.page.js'; + +let promoaction; +test.describe('verify promo action bar with CTAs, close, stickiness features in page', () => { + test.beforeEach(async ({ page }) => { + promoaction = new Promocloseaction(page); + }); + // Test sticky promo bar shows up in page bottom when page loads + test(`${features[0].name},${features[0].tags}`, async ({ page, baseURL }) => { + console.info(`[Test Page]: ${baseURL}${features[0].path}`); + await test.step('promo bar with close action shows up in page bottom when it loads', async () => { + await page.goto(`${baseURL}${features[0].path}`); + await page.waitForLoadState('domcontentloaded'); + await expect(page).toHaveURL(`${baseURL}${features[0].path}`); + }); + await test.step('promo action with close at page botton with stickiness', async () => { + await page.waitForLoadState(); + expect(await promoaction.promoBar).toBeTruthy(); + expect(await promoaction.promoBarMobile).toBeTruthy(); + expect(await promoaction.promoBarTablet).toBeTruthy(); + expect(await promoaction.promoBarDesktop).toBeTruthy(); + expect(await promoaction.PromoText).toBeTruthy(); + }); + }); + // Test promo bar closed when hit cross icon on it and promo disappear + test(`${features[1].name},${features[1].tags}`, async ({ page, baseURL }) => { + console.info(`[Test Page]: ${baseURL}${features[1].path}`); + await test.step('Test promo bar closed when hit cross icon on it', async () => { + await page.goto(`${baseURL}${features[1].path}`); + await page.waitForLoadState('domcontentloaded'); + await expect(page).toHaveURL(`${baseURL}${features[1].path}`); + }); + await test.step('Test promo bar closed when hit cross icon on it and disappear in page', async () => { + await page.waitForLoadState(); + await promoaction.promoClose.click(); + await page.waitForTimeout(2000); // wait for 2 second to ensure the promo bar is closed + expect(await promoaction.promoNotSticky).toBeTruthy(); + }); + }); + // Test promo bar CTAs navigates valid urls + test(`${features[2].name},${features[2].tags}`, async ({ page, baseURL }) => { + console.info(`[Test Page]: ${baseURL}${features[2].path}`); + const expectedUrl = features[2].url; + await test.step('sticky promo bar CTAs are working', async () => { + await page.goto(`${baseURL}${features[2].path}`); + await page.waitForLoadState('domcontentloaded'); + await expect(page).toHaveURL(`${baseURL}${features[2].path}`); + }); + await test.step('promo bar CTAs naviagate to valid destination', async () => { + await page.waitForLoadState(); + await promoaction.promoCTA.click(); + await expect(page).toHaveURL(new RegExp(expectedUrl)); + }); + }); +}); diff --git a/nala/blocks/seocanonical/seocanonical.page.js b/nala/blocks/seocanonical/seocanonical.page.js new file mode 100644 index 000000000..fceed62f2 --- /dev/null +++ b/nala/blocks/seocanonical/seocanonical.page.js @@ -0,0 +1,12 @@ +import { expect } from '@playwright/test'; + +export default class seocanonical { + constructor(page) { + this.page = page; + this.seoCanonicalLink = page.locator('//link[@rel="canonical"]'); + } + + async checkPage() { + expect(await this.seoCanonicalLink).toBeTruthy(); + } +} diff --git a/nala/blocks/seocanonical/seocanonical.spec.js b/nala/blocks/seocanonical/seocanonical.spec.js new file mode 100644 index 000000000..0bce4063f --- /dev/null +++ b/nala/blocks/seocanonical/seocanonical.spec.js @@ -0,0 +1,17 @@ +module.exports = { + name: 'seocanonical', + features: [ + { + tcid: '0', + name: '@seocanonical-presence-cc', + path: '/creativecloud?georouting=off', + tags: '@cc @cc-canonical @cc-canonical-presence-creativecloud', + }, + { + tcid: '1', + name: '@seocanonical-presence-ps', + path: '/products/photoshop?georouting=off', + tags: '@cc @cc-canonical @cc-canonical-presence-photoshop', + }, + ], +}; diff --git a/nala/blocks/seocanonical/seocanonical.test.js b/nala/blocks/seocanonical/seocanonical.test.js new file mode 100644 index 000000000..ec9125211 --- /dev/null +++ b/nala/blocks/seocanonical/seocanonical.test.js @@ -0,0 +1,35 @@ +import { expect, test } from '@playwright/test'; +import { features } from './seocanonical.spec.js'; +import Seo from './seocanonical.page.js'; + +let seo; +test.describe('SEO Canonical Tests', () => { + test.beforeEach(async ({ page }) => { + seo = new Seo(page); + }); + test(`${features[0].name},${features[0].tags}`, async ({ page, baseURL }) => { + console.info(`[Test Page]: ${baseURL}${features[0].path}`); + await test.step('SEO Canonical Tag is present in CC home page', async () => { + await page.goto(`${baseURL}${features[0].path}`); + await page.waitForLoadState('domcontentloaded'); + await expect(page).toHaveURL(`${baseURL}${features[0].path}`); + }); + await test.step('SEO Canonical Tag is present CC home page US locale', async () => { + await page.waitForLoadState(); + expect(await seo.seoCanonicalLink).toBeTruthy(); + }); + }); + + test(`${features[1].name},${features[1].tags}`, async ({ page, baseURL }) => { + console.info(`[Test Page]: ${baseURL}${features[1].path}`); + await test.step('SEO Canonical Tag is present in photoshop home page', async () => { + await page.goto(`${baseURL}${features[1].path}`); + await page.waitForLoadState('domcontentloaded'); + await expect(page).toHaveURL(`${baseURL}${features[1].path}`); + }); + await test.step('SEO Canonical Tag is present photoshop US locale page', async () => { + await page.waitForLoadState(); + expect(await seo.seoCanonicalLink).toBeTruthy(); + }); + }); +}); From 47e41aafe5aa050f2dc4b6b7d621926d4a8660aa Mon Sep 17 00:00:00 2001 From: sigadamramesh <130433161+sigadamvenkata@users.noreply.github.com> Date: Mon, 1 Dec 2025 10:00:38 +0530 Subject: [PATCH 2/3] Remove URL expectation from promo bar CTA test Removed URL expectation from promo bar CTA test. --- nala/blocks/promobar/promobar.test.js | 1 - 1 file changed, 1 deletion(-) diff --git a/nala/blocks/promobar/promobar.test.js b/nala/blocks/promobar/promobar.test.js index 52a7fb98a..670d060fd 100644 --- a/nala/blocks/promobar/promobar.test.js +++ b/nala/blocks/promobar/promobar.test.js @@ -51,7 +51,6 @@ test.describe('verify promo action bar with CTAs, close, stickiness features in await test.step('promo bar CTAs naviagate to valid destination', async () => { await page.waitForLoadState(); await promoaction.promoCTA.click(); - await expect(page).toHaveURL(new RegExp(expectedUrl)); }); }); }); From 4cb335d8fad2ba832d681ed89a7755cc13527548 Mon Sep 17 00:00:00 2001 From: sigadamramesh <130433161+sigadamvenkata@users.noreply.github.com> Date: Mon, 1 Dec 2025 22:10:57 +0530 Subject: [PATCH 3/3] Remove unused variable in promo bar test Remove unused variable 'expectedUrl' in promo bar tests. --- nala/blocks/promobar/promobar.test.js | 1 - 1 file changed, 1 deletion(-) diff --git a/nala/blocks/promobar/promobar.test.js b/nala/blocks/promobar/promobar.test.js index 670d060fd..5800df2fb 100644 --- a/nala/blocks/promobar/promobar.test.js +++ b/nala/blocks/promobar/promobar.test.js @@ -42,7 +42,6 @@ test.describe('verify promo action bar with CTAs, close, stickiness features in // Test promo bar CTAs navigates valid urls test(`${features[2].name},${features[2].tags}`, async ({ page, baseURL }) => { console.info(`[Test Page]: ${baseURL}${features[2].path}`); - const expectedUrl = features[2].url; await test.step('sticky promo bar CTAs are working', async () => { await page.goto(`${baseURL}${features[2].path}`); await page.waitForLoadState('domcontentloaded');