diff --git a/.github/workflows/caas.daily.yml b/.github/workflows/caas.daily.yml new file mode 100644 index 00000000..07814888 --- /dev/null +++ b/.github/workflows/caas.daily.yml @@ -0,0 +1,46 @@ +name: CAAS 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: 'CAAS 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 caas + 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/caas.config.js b/configs/caas.config.js new file mode 100644 index 00000000..488095c9 --- /dev/null +++ b/configs/caas.config.js @@ -0,0 +1,120 @@ +// @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/caas', + outputDir: '../test-results', + /* Maximum time one test can run for. */ + timeout: 45 * 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'], ['../utils/reporters/json-reporter.js'], ['../utils/reporters/json-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: process.env.BASE_URL || envs['@milo_live'] || 'https://main--milo--adobecom.hlx.live', + }, + + /* Configure projects for major browsers */ + projects: [ + { + name: 'milo-live-chrome', + use: { + ...devices['Desktop Chrome'], + baseURL: envs['@milo-live'], + contextOptions: { permissions: ['clipboard-read', 'clipboard-write'] }, + headless: false, + }, + }, + + { + name: 'milo-live-firefox', + use: { + ...devices['Desktop Firefox'], + baseURL: envs['@milo-live'], + launchOptions: { + firefoxUserPrefs: { + 'dom.events.asyncClipboard.readText': true, + 'dom.events.testing.asyncClipboard': true, + 'dom.events.asyncClipboard.clipboardItem': true, + }, + }, + }, + }, + + { + name: 'milo-live-webkit', + use: { + ...devices['Desktop Safari'], + baseURL: envs['@milo-live'], + }, + }, + + { + name: 'milo-prod-chrome', + use: { + ...devices['Desktop Chrome'], + baseURL: envs['@milo_prod'], + contextOptions: { permissions: ['clipboard-read', 'clipboard-write'] }, + headless: false, + }, + }, + + { + name: 'milo-prod-firefox', + use: { + ...devices['Desktop Firefox'], + baseURL: envs['@milo_prod'], + launchOptions: { + firefoxUserPrefs: { + 'dom.events.asyncClipboard.readText': true, + 'dom.events.testing.asyncClipboard': true, + }, + }, + }, + }, + + { + name: 'milo-prod-webkit', + use: { + ...devices['Desktop Safari'], + baseURL: envs['@milo_prod'], + }, + }, + ], +}; +export default config; diff --git a/features/caas/caas.spec.js b/features/caas/caas.spec.js new file mode 100644 index 00000000..3af978a1 --- /dev/null +++ b/features/caas/caas.spec.js @@ -0,0 +1,16 @@ +module.exports = { + FeatureName: 'CAAS Feature', + features: [ + { + tcid: '0', + name: '@Card Collection', + path: '/drafts/nala/features/caas/caascollection', + data: { + cardsPerPage: 4, + caasTitle: 'Consonant Card Collection Title', + paginator: '1 - 4 of 8 results', + }, + tags: '@caas @smoke @regression @milo', + }, + ], +}; diff --git a/selectors/caas/caas.feature.page.js b/selectors/caas/caas.feature.page.js new file mode 100644 index 00000000..495ea2aa --- /dev/null +++ b/selectors/caas/caas.feature.page.js @@ -0,0 +1,11 @@ +export default class Caas { + constructor(page) { + this.page = page; + + // caas locators + this.caasFirstCard = this.page.locator('.consonant-Card').nth(0); + this.caasCards = this.page.locator('.consonant-Card'); + this.caasTitle = this.page.locator('.consonant-FiltersInfo-title'); + this.caasPaginator = this.page.locator('.consonant-Pagination-summary'); + } +} diff --git a/tests/caas/caas.feature.test.js b/tests/caas/caas.feature.test.js new file mode 100644 index 00000000..ef03faf9 --- /dev/null +++ b/tests/caas/caas.feature.test.js @@ -0,0 +1,48 @@ +import { expect, test } from '@playwright/test'; +import { features } from '../../features/caas/caas.spec.js'; +import Caas from '../../selectors/caas/caas.feature.page.js'; + +let caas; +let consoleErrors = []; + +const miloLibs = process.env.MILO_LIBS || ''; + +test.describe('Milo CAAS Feature test suite', () => { + test.beforeEach(async ({ page }) => { + caas = new Caas(page); + + page.on('console', (exception) => { + if (exception.type() === 'error') { + consoleErrors.push(exception.text()); + } + }); + }); + + test.afterEach(async () => { + console.log('Console Errors:', consoleErrors); + consoleErrors = []; + }); + + // Test 0 : Card Collection + test(`${features[0].name},${features[0].tags}`, async ({ page, baseURL }) => { + console.info(`[Test Page]: ${baseURL}${features[0].path}${miloLibs}`); + const { data } = features[0]; + + await test.step('step-1: Go to CAAS collection 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 CAAS collection content/specs', async () => { + await page.waitForSelector('.consonant-Card', { state: 'visible', timeout: 60000 }); + // verify number of cards in the collection + await expect(await caas.caasFirstCard).toBeVisible(); + await expect(await caas.caasCards).toHaveCount(data.cardsPerPage); + + // verify caas title and paginator + await expect(await caas.caasTitle).toContainText(data.caasTitle); + await expect(await caas.caasPaginator).toContainText(data.paginator); + }); + }); +});