From c931c5d5be9e3c5b699f6680b0677e64e0581991 Mon Sep 17 00:00:00 2001 From: Jacky Sun <67350368+JackySun9@users.noreply.github.com> Date: Wed, 20 Nov 2024 11:35:18 -0800 Subject: [PATCH] add tests for graybox-cc and graybox-homepage (#464) * add tests for graybox-bacom * just use chrome * add more waiting time * add merch card * add 404 checker for graxybox-bacom * update gitignore and file name * add screenshots for graybox-dc * add 404 checking for graybox dc * adjust screenshot tests * update screenshot tests to public s3 and git action to run them * fix git action * update git action * install dependencies * only able to run hlx.live pages not stage pages * add tests for graybox cc and homepage --- configs/graybox-bacom.config.js | 2 +- configs/graybox-cc.config.js | 80 ++++++++++++++++++++ configs/graybox-homepage.config.js | 80 ++++++++++++++++++++ data/graybox/sot-cc.yml | 15 ++++ data/graybox/sot-homepage.yml | 10 +++ envs/envs.js | 2 + features/graybox/sot.cc.404.spec.js | 13 ++++ features/graybox/sot.homepage.404.spec.js | 13 ++++ features/visual/graybox/sot.cc.spec.js | 13 ++++ features/visual/graybox/sot.homepage.spec.js | 13 ++++ tests/graybox/sot.bacom.404.test.js | 4 +- tests/graybox/sot.cc.404.test.js | 70 +++++++++++++++++ tests/graybox/sot.dc.404.test.js | 4 +- tests/graybox/sot.homepage.404.test.js | 70 +++++++++++++++++ tests/visual/graybox/sot.cc.test.js | 45 +++++++++++ tests/visual/graybox/sot.homepage.test.js | 45 +++++++++++ 16 files changed, 476 insertions(+), 3 deletions(-) create mode 100644 configs/graybox-cc.config.js create mode 100644 configs/graybox-homepage.config.js create mode 100644 data/graybox/sot-cc.yml create mode 100644 data/graybox/sot-homepage.yml create mode 100644 features/graybox/sot.cc.404.spec.js create mode 100644 features/graybox/sot.homepage.404.spec.js create mode 100644 features/visual/graybox/sot.cc.spec.js create mode 100644 features/visual/graybox/sot.homepage.spec.js create mode 100644 tests/graybox/sot.cc.404.test.js create mode 100644 tests/graybox/sot.homepage.404.test.js create mode 100644 tests/visual/graybox/sot.cc.test.js create mode 100644 tests/visual/graybox/sot.homepage.test.js diff --git a/configs/graybox-bacom.config.js b/configs/graybox-bacom.config.js index e0bc4b88..8d1302e0 100644 --- a/configs/graybox-bacom.config.js +++ b/configs/graybox-bacom.config.js @@ -65,7 +65,7 @@ const config = { name: 'bacom-live-chrome', use: { ...devices['Desktop Chrome'], - baseURL: envs['@bacom_graybox'], + baseURL: envs['@graybox_bacom'], }, }, { diff --git a/configs/graybox-cc.config.js b/configs/graybox-cc.config.js new file mode 100644 index 00000000..8f3e1c5f --- /dev/null +++ b/configs/graybox-cc.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/', + testMatch: ['cc/**/*.test.js', 'milo/**/*.test.js', 'graybox/**/*.test.js'], + outputDir: '../test-results', + /* Maximum time one test can run for. */ + timeout: 45 * 1000, + expect: { + /** + * Maximum time expect() should wait for the condition to be met. + * For example in `await expect(locator).toHaveText();` + */ + timeout: 10 * 1000, + }, + /* 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'], ['json', { outputFile: '../test-json-results/test-results.json' }]] + : [ + [ + 'html', + { + outputFolder: 'test-html-results', + open: 'never', + }, + ], + ['list'], + ['../utils/reporters/base-reporter.js'], + ['json', { outputFile: '../test-json-results/test-results.json' }], + ], + + /* 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.BASE_URL + || envs['@graybox_dc'] + || 'https://main--cc--adobecom.hlx.live', + }, + + /* Configure projects for major browsers */ + projects: [ + { + name: 'cc-live-chrome', + use: { + ...devices['Desktop Chrome'], + baseURL: envs['@graybox_cc'], + }, + }, + { + name: 'cc-stage-chrome', + use: { + ...devices['Desktop Chrome'], + baseURL: envs['@adobe_stage'], + }, + }, + ], +}; +module.exports = config; diff --git a/configs/graybox-homepage.config.js b/configs/graybox-homepage.config.js new file mode 100644 index 00000000..6fd51704 --- /dev/null +++ b/configs/graybox-homepage.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/', + testMatch: ['dc/**/*.test.js', 'milo/**/*.test.js', 'graybox/**/*.test.js'], + outputDir: '../test-results', + /* Maximum time one test can run for. */ + timeout: 45 * 1000, + expect: { + /** + * Maximum time expect() should wait for the condition to be met. + * For example in `await expect(locator).toHaveText();` + */ + timeout: 10 * 1000, + }, + /* 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'], ['json', { outputFile: '../test-json-results/test-results.json' }]] + : [ + [ + 'html', + { + outputFolder: 'test-html-results', + open: 'never', + }, + ], + ['list'], + ['../utils/reporters/base-reporter.js'], + ['json', { outputFile: '../test-json-results/test-results.json' }], + ], + + /* 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.BASE_URL + || envs['@graybox_homepage'] + || 'https://www.stage.adobe.com', + }, + + /* Configure projects for major browsers */ + projects: [ + { + name: 'homepage-live-chrome', + use: { + ...devices['Desktop Chrome'], + baseURL: envs['@graybox_homepage'], + }, + }, + { + name: 'homepage-stage-chrome', + use: { + ...devices['Desktop Chrome'], + baseURL: envs['@adobe_stage'], + }, + }, + ], +}; +module.exports = config; diff --git a/data/graybox/sot-cc.yml b/data/graybox/sot-cc.yml new file mode 100644 index 00000000..92407a24 --- /dev/null +++ b/data/graybox/sot-cc.yml @@ -0,0 +1,15 @@ +--- +'CreativeCloud': 'https://www.stage.adobe.com/creativecloud.html' +'CreativeCloudFeatures': 'https://www.stage.adobe.com/creativecloud/features.html' +'CreativeCloudPhotography': 'https://www.stage.adobe.com/creativecloud/photography.html' +'CreativeCloudStudents': 'https://www.stage.adobe.com/creativecloud/buy/students.html' +'CreativeCloudAllApps': 'https://www.stage.adobe.com/creativecloud/all-apps.html' +'CreativeCloudPhotoshop': 'https://www.stage.adobe.com/products/photoshop.html' +'CreativeCloudPhotoshopLightroom': 'https://www.stage.adobe.com/products/photoshop-lightroom.html' +'CreativeCloudIllustrator': 'https://www.stage.adobe.com/products/illustrator.html' +'CreativeCloudPremiere': 'https://www.stage.adobe.com/products/premiere.html' +'CreativeCloudAIOverview': 'https://www.stage.adobe.com/ai/overview.html' +'CreativeCloudFirefly': 'https://www.stage.adobe.com/products/firefly.html' +'CreativeCloudPhotographyApps': 'https://www.stage.adobe.com/creativecloud/photography/apps.html' +'CreativeCloudDesign': 'https://www.stage.adobe.com/creativecloud/design.html' +'CreativeCloudVideo': 'https://www.stage.adobe.com/creativecloud/video.html' diff --git a/data/graybox/sot-homepage.yml b/data/graybox/sot-homepage.yml new file mode 100644 index 00000000..b2084d0b --- /dev/null +++ b/data/graybox/sot-homepage.yml @@ -0,0 +1,10 @@ +--- +'AdobeHomepageNoMEP': 'https://www.stage.adobe.com/?mep=off' +'AdobeHomepage': 'https://www.stage.adobe.com' +'AdobeHomepageUK': 'https://www.stage.adobe.com/uk/?mep=off&akamaiLocale=uk' +'AdobeHomepageUKNoMEP': 'https://www.stage.adobe.com/uk/?akamaiLocale=uk' +'AdobeHomepageDE': 'https://www.stage.adobe.com/de?akamaiLocale=de' +'AdobeHomepageFR': 'https://www.stage.adobe.com/fr?akamaiLocale=fr' +'AdobeHomepageES': 'https://www.stage.adobe.com/es?akamaiLocale=es' +'AdobeHomepageJP': 'https://www.stage.adobe.com/jp?akamaiLocale=jp' +'AdobeHomepageMENA': 'https://www.stage.adobe.com/mena_ar?akamaiLocale=mena' diff --git a/envs/envs.js b/envs/envs.js index 82153eb1..1c5bb0c2 100644 --- a/envs/envs.js +++ b/envs/envs.js @@ -27,4 +27,6 @@ module.exports = { '@express_live': 'https://main--express--adobecom.hlx.live', '@graybox_bacom': 'https://test.business-graybox.adobe.com', '@graybox_dc': 'https://test.graybox.adobe.com', + '@graybox_homepage': 'https://test.graybox.adobe.com', + '@graybox_cc': 'https://test.graybox.adobe.com', }; diff --git a/features/graybox/sot.cc.404.spec.js b/features/graybox/sot.cc.404.spec.js new file mode 100644 index 00000000..c02b652e --- /dev/null +++ b/features/graybox/sot.cc.404.spec.js @@ -0,0 +1,13 @@ +module.exports = { + name: 'Graybox CC SOT 404 Check', + features: [ + { + tcid: '0', + name: '@graybox-cc-404-check', + stable: '@adobe_stage', + beta: '@graybox_cc', + tags: '@graybox-cc-404-check', + data: 'data/graybox/sot-cc.yml', + }, + ], +}; diff --git a/features/graybox/sot.homepage.404.spec.js b/features/graybox/sot.homepage.404.spec.js new file mode 100644 index 00000000..871a9221 --- /dev/null +++ b/features/graybox/sot.homepage.404.spec.js @@ -0,0 +1,13 @@ +module.exports = { + name: 'Graybox Homepage SOT 404 Check', + features: [ + { + tcid: '0', + name: '@graybox-homepage-404-check', + stable: '@adobe_stage', + beta: '@graybox_homepage', + tags: '@graybox-homepage-404-check', + data: 'data/graybox/sot-homepage.yml', + }, + ], +}; diff --git a/features/visual/graybox/sot.cc.spec.js b/features/visual/graybox/sot.cc.spec.js new file mode 100644 index 00000000..d8a70973 --- /dev/null +++ b/features/visual/graybox/sot.cc.spec.js @@ -0,0 +1,13 @@ +module.exports = { + name: 'Graybox CC SOT Visual Comparison', + features: [ + { + tcid: '0', + name: '@graybox-cc-visual', + stable: '@adobe_stage', + beta: '@graybox_cc', + tags: '@graybox-cc-visual @visual @graybox-cc-screenshots', + data: 'data/graybox/sot-cc.yml', + }, + ], +}; diff --git a/features/visual/graybox/sot.homepage.spec.js b/features/visual/graybox/sot.homepage.spec.js new file mode 100644 index 00000000..48131d70 --- /dev/null +++ b/features/visual/graybox/sot.homepage.spec.js @@ -0,0 +1,13 @@ +module.exports = { + name: 'Graybox Homepage SOT Visual Comparison', + features: [ + { + tcid: '0', + name: '@graybox-homepage-visual', + stable: '@adobe_stage', + beta: '@graybox_homepage ', + tags: '@graybox-homepage-visual @visual @graybox-homepage-screenshots', + data: 'data/graybox/sot-homepage.yml', + }, + ], +}; diff --git a/tests/graybox/sot.bacom.404.test.js b/tests/graybox/sot.bacom.404.test.js index 69578058..417a4a61 100644 --- a/tests/graybox/sot.bacom.404.test.js +++ b/tests/graybox/sot.bacom.404.test.js @@ -49,7 +49,9 @@ test.describe('Graybox Bacom SOT 404 Check test suite', () => { // Wait for some time to ensure all resources are loaded await page.waitForLoadState('networkidle'); // Better way to wait for page load // {{ edit_1 }}: Log all links on the page - const links = await page.$$eval('a', (anchors) => anchors.map((anchor) => anchor.href)); + const links = await page.$$eval('a', (anchors) => anchors + .map((anchor) => anchor.href) + .filter((href) => !href.includes('test.business-graybox'))); console.log('Links on the page:', links); results[betaURL] = { four0FourErrors, diff --git a/tests/graybox/sot.cc.404.test.js b/tests/graybox/sot.cc.404.test.js new file mode 100644 index 00000000..75902ad5 --- /dev/null +++ b/tests/graybox/sot.cc.404.test.js @@ -0,0 +1,70 @@ +/* eslint-disable no-restricted-syntax */ +/* eslint-disable import/named */ +import { test } from '@playwright/test'; +import { features } from '../../features/graybox/sot.cc.404.spec.js'; + +const fs = require('fs'); // Add this import at the top + +const { WebUtil } = require('../../libs/webutil.js'); + +const results = {}; +let consoleErrors = []; +let four0FourErrors = []; + +test.describe('Graybox CC SOT 404 Check test suite', () => { + test.setTimeout(20 * 60 * 1000); + test.beforeEach(async ({ page }) => { + // Check for 404s + page.on('response', (response) => { + if (response.status() === 404) { + console.log(`Resource not found: ${response.url()}`); + four0FourErrors.push(`Resource not found: ${response.url()}`); + } + }); + + // Check for console errors + page.on('console', (msg) => { + if (msg.type() === 'error') { + console.error(`Console error: ${msg.text()}`); + consoleErrors.push(`Console error: ${msg.text()}`); // Fix to store console errors in the results object + } + }); + }); + + for (const feature of features) { + // eslint-disable-next-line no-loop-func + test(`${feature.name},${feature.tags}`, async ({ page }) => { + // load test data from static files + const testdata = await WebUtil.loadTestData(`${feature.data}`); + + for (const key of Object.keys(testdata)) { + consoleErrors = []; + four0FourErrors = []; + const stableURL = testdata[key]; + const betaURL = stableURL.replace('www.stage', 'test.graybox'); + console.info('Checking for 404s on:', betaURL); + // Go to the page you want to check + await page.goto(betaURL); + + // Wait for some time to ensure all resources are loaded + await page.waitForLoadState('networkidle'); // Better way to wait for page load + // {{ edit_1 }}: Log all links on the page + const links = await page.$$eval('a', (anchors) => anchors + .map((anchor) => anchor.href) + .filter((href) => !href.includes('test.graybox'))); + console.log('Links on the page:', links); + results[betaURL] = { + four0FourErrors, + consoleErrors, + links, + }; + } + }); + } + + // {{ edit_3 }}: Write results to JSON file after all tests + test.afterAll(async () => { + fs.writeFileSync('graybox-cc-404-results.json', JSON.stringify(results, null, 2)); + console.log('Results saved to graybox-cc-404-results.json'); + }); +}); diff --git a/tests/graybox/sot.dc.404.test.js b/tests/graybox/sot.dc.404.test.js index 6471cbfd..8901ccd0 100644 --- a/tests/graybox/sot.dc.404.test.js +++ b/tests/graybox/sot.dc.404.test.js @@ -49,7 +49,9 @@ test.describe('Graybox DC SOT 404 Check test suite', () => { // Wait for some time to ensure all resources are loaded await page.waitForLoadState('networkidle'); // Better way to wait for page load // {{ edit_1 }}: Log all links on the page - const links = await page.$$eval('a', (anchors) => anchors.map((anchor) => anchor.href)); + const links = await page.$$eval('a', (anchors) => anchors + .map((anchor) => anchor.href) + .filter((href) => !href.includes('test.graybox'))); console.log('Links on the page:', links); results[betaURL] = { four0FourErrors, diff --git a/tests/graybox/sot.homepage.404.test.js b/tests/graybox/sot.homepage.404.test.js new file mode 100644 index 00000000..0fe7aa99 --- /dev/null +++ b/tests/graybox/sot.homepage.404.test.js @@ -0,0 +1,70 @@ +/* eslint-disable no-restricted-syntax */ +/* eslint-disable import/named */ +import { test } from '@playwright/test'; +import { features } from '../../features/graybox/sot.homepage.404.spec.js'; + +const fs = require('fs'); // Add this import at the top + +const { WebUtil } = require('../../libs/webutil.js'); + +const results = {}; +let consoleErrors = []; +let four0FourErrors = []; + +test.describe('Graybox Homepage SOT 404 Check test suite', () => { + test.setTimeout(20 * 60 * 1000); + test.beforeEach(async ({ page }) => { + // Check for 404s + page.on('response', (response) => { + if (response.status() === 404) { + console.log(`Resource not found: ${response.url()}`); + four0FourErrors.push(`Resource not found: ${response.url()}`); + } + }); + + // Check for console errors + page.on('console', (msg) => { + if (msg.type() === 'error') { + console.error(`Console error: ${msg.text()}`); + consoleErrors.push(`Console error: ${msg.text()}`); // Fix to store console errors in the results object + } + }); + }); + + for (const feature of features) { + // eslint-disable-next-line no-loop-func + test(`${feature.name},${feature.tags}`, async ({ page }) => { + // load test data from static files + const testdata = await WebUtil.loadTestData(`${feature.data}`); + + for (const key of Object.keys(testdata)) { + consoleErrors = []; + four0FourErrors = []; + const stableURL = testdata[key]; + const betaURL = stableURL.replace('www.stage', 'test.graybox'); + console.info('Checking for 404s on:', betaURL); + // Go to the page you want to check + await page.goto(betaURL); + + // Wait for some time to ensure all resources are loaded + await page.waitForLoadState('networkidle'); // Better way to wait for page load + // {{ edit_1 }}: Log all links on the page + const links = await page.$$eval('a', (anchors) => anchors + .map((anchor) => anchor.href) + .filter((href) => !href.includes('test.graybox'))); + console.log('Links on the page:', links); + results[betaURL] = { + four0FourErrors, + consoleErrors, + links, + }; + } + }); + } + + // {{ edit_3 }}: Write results to JSON file after all tests + test.afterAll(async () => { + fs.writeFileSync('graybox-homepage-404-results.json', JSON.stringify(results, null, 2)); + console.log('Results saved to graybox-homepage-404-results.json'); + }); +}); diff --git a/tests/visual/graybox/sot.cc.test.js b/tests/visual/graybox/sot.cc.test.js new file mode 100644 index 00000000..8a78bdc8 --- /dev/null +++ b/tests/visual/graybox/sot.cc.test.js @@ -0,0 +1,45 @@ +/* eslint-disable no-restricted-syntax */ +/* eslint-disable import/named */ +import { test } from '@playwright/test'; +import { features } from '../../../features/visual/graybox/sot.cc.spec.js'; +import { takeTwo } from '../../../libs/screenshot/take.js'; +import { writeResultsToFile } from '../../../libs/screenshot/utils.js'; + +const { WebUtil } = require('../../../libs/webutil.js'); + +const folderPath = 'screenshots/graybox-cc'; +const results = {}; + +test.describe('Graybox CC SOT visual comparison test suite', () => { + // reset timeout because we use this to run all test data + test.setTimeout(20 * 60 * 1000); + for (const feature of features) { + // eslint-disable-next-line no-loop-func + test(`${feature.name},${feature.tags}`, async ({ page }, testInfo) => { + // load test data from static files + const testdata = await WebUtil.loadTestData(`${feature.data}`); + + for (const key of Object.keys(testdata)) { + const stableURL = testdata[key]; + console.info(stableURL); + const betaURL = testdata[key].replace('www.stage', 'test.graybox'); + console.info(betaURL); + + const name = `${feature.name}-${key}-${testInfo.project.name}`; + // eslint-disable-next-line no-await-in-loop + const result = await takeTwo( + page, + stableURL, + async () => { await page.waitForTimeout(10000); }, + betaURL, + async () => { await page.waitForTimeout(15000); }, + folderPath, + name, + { fullPage: true }, + ); + results[name] = [result]; + } + writeResultsToFile(folderPath, testInfo, results); + }); + } +}); diff --git a/tests/visual/graybox/sot.homepage.test.js b/tests/visual/graybox/sot.homepage.test.js new file mode 100644 index 00000000..2ab43195 --- /dev/null +++ b/tests/visual/graybox/sot.homepage.test.js @@ -0,0 +1,45 @@ +/* eslint-disable no-restricted-syntax */ +/* eslint-disable import/named */ +import { test } from '@playwright/test'; +import { features } from '../../../features/visual/graybox/sot.homepage.spec.js'; +import { takeTwo } from '../../../libs/screenshot/take.js'; +import { writeResultsToFile } from '../../../libs/screenshot/utils.js'; + +const { WebUtil } = require('../../../libs/webutil.js'); + +const folderPath = 'screenshots/graybox-homepage'; +const results = {}; + +test.describe('Graybox Homepage SOT visual comparison test suite', () => { + // reset timeout because we use this to run all test data + test.setTimeout(20 * 60 * 1000); + for (const feature of features) { + // eslint-disable-next-line no-loop-func + test(`${feature.name},${feature.tags}`, async ({ page }, testInfo) => { + // load test data from static files + const testdata = await WebUtil.loadTestData(`${feature.data}`); + + for (const key of Object.keys(testdata)) { + const stableURL = testdata[key]; + console.info(stableURL); + const betaURL = testdata[key].replace('www.stage', 'test.graybox'); + console.info(betaURL); + + const name = `${feature.name}-${key}-${testInfo.project.name}`; + // eslint-disable-next-line no-await-in-loop + const result = await takeTwo( + page, + stableURL, + async () => { await page.waitForTimeout(10000); }, + betaURL, + async () => { await page.waitForTimeout(15000); }, + folderPath, + name, + { fullPage: true }, + ); + results[name] = [result]; + } + writeResultsToFile(folderPath, testInfo, results); + }); + } +});