From 3a25e3666dfcda5a3e74df517ed843737dc77360 Mon Sep 17 00:00:00 2001 From: Logan Graham Date: Fri, 13 Sep 2024 08:54:51 -0400 Subject: [PATCH] [Playwright] Add integration tests (#137) Co-authored-by: Logan Graham --- .github/workflows/playwright-integration.yml | 43 ++++++ visual-js/visual-playwright/Dockerfile | 15 ++ .../integration-tests/.gitignore | 5 + .../integration-tests/custom-test.ts | 12 ++ .../integration-tests/global-setup.ts | 7 + .../integration-tests/global-teardown.ts | 7 + .../integration-tests/package-lock.json | 140 ++++++++++++++++++ .../integration-tests/package.json | 17 +++ .../integration-tests/playwright.config.ts | 81 ++++++++++ .../tests/integration-test.spec.ts | 11 ++ visual-js/yarn.lock | 4 +- 11 files changed, 340 insertions(+), 2 deletions(-) create mode 100644 .github/workflows/playwright-integration.yml create mode 100644 visual-js/visual-playwright/Dockerfile create mode 100644 visual-js/visual-playwright/integration-tests/.gitignore create mode 100644 visual-js/visual-playwright/integration-tests/custom-test.ts create mode 100644 visual-js/visual-playwright/integration-tests/global-setup.ts create mode 100644 visual-js/visual-playwright/integration-tests/global-teardown.ts create mode 100644 visual-js/visual-playwright/integration-tests/package-lock.json create mode 100644 visual-js/visual-playwright/integration-tests/package.json create mode 100644 visual-js/visual-playwright/integration-tests/playwright.config.ts create mode 100644 visual-js/visual-playwright/integration-tests/tests/integration-test.spec.ts diff --git a/.github/workflows/playwright-integration.yml b/.github/workflows/playwright-integration.yml new file mode 100644 index 00000000..452aa7f2 --- /dev/null +++ b/.github/workflows/playwright-integration.yml @@ -0,0 +1,43 @@ +name: playwright (integration test) + +on: + push: + branches: + - main + paths: + - 'visual-js/visual-playwright/**' + - .github/workflows/js-build.yml + - .github/workflows/playwright-integration.yml + pull_request: + paths: + - 'visual-js/visual-playwright/**' + - .github/workflows/js-build.yml + - .github/workflows/playwright-integration.yml + +defaults: + run: + working-directory: visual-js/visual-playwright + +jobs: + integration-test: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + - name: Build and push to local registry + uses: docker/build-push-action@v5 + with: + context: '{{defaultContext}}:visual-js' + tags: saucelabs/visual-playwright + file: visual-playwright/Dockerfile + load: true + - name: Run the integration tests + run: | + npm ci + npm run test + working-directory: tests + env: + SAUCE_USERNAME: ${{ secrets.SAUCE_USERNAME }} + SAUCE_ACCESS_KEY: ${{ secrets.SAUCE_ACCESS_KEY }} + CONTAINER_IMAGE_NAME: saucelabs/visual-playwright diff --git a/visual-js/visual-playwright/Dockerfile b/visual-js/visual-playwright/Dockerfile new file mode 100644 index 00000000..ddbf6926 --- /dev/null +++ b/visual-js/visual-playwright/Dockerfile @@ -0,0 +1,15 @@ +FROM node:18 AS runner + +WORKDIR app + +RUN corepack enable + +COPY . ./ + +RUN yarn install && npm run build --workspaces --if-present + +WORKDIR ./visual-playwright/integration-tests + +RUN npm install && npx playwright install --with-deps chromium + +ENTRYPOINT ["npm", "run", "sauce-visual"] diff --git a/visual-js/visual-playwright/integration-tests/.gitignore b/visual-js/visual-playwright/integration-tests/.gitignore new file mode 100644 index 00000000..68c5d18f --- /dev/null +++ b/visual-js/visual-playwright/integration-tests/.gitignore @@ -0,0 +1,5 @@ +node_modules/ +/test-results/ +/playwright-report/ +/blob-report/ +/playwright/.cache/ diff --git a/visual-js/visual-playwright/integration-tests/custom-test.ts b/visual-js/visual-playwright/integration-tests/custom-test.ts new file mode 100644 index 00000000..53f1df75 --- /dev/null +++ b/visual-js/visual-playwright/integration-tests/custom-test.ts @@ -0,0 +1,12 @@ +import { test as base } from "@playwright/test"; +import { sauceVisualFixtures, SauceVisualFixtures } from "@saucelabs/visual-playwright"; + +export const test = base.extend({ + // Set up the Sauce Visual fixture, and optionally customize the global options which are sent + // with each sauce visual check to reduce duplication. + ...sauceVisualFixtures({ + captureDom: true, + }), +}); + +export { expect } from "@playwright/test"; diff --git a/visual-js/visual-playwright/integration-tests/global-setup.ts b/visual-js/visual-playwright/integration-tests/global-setup.ts new file mode 100644 index 00000000..788d249b --- /dev/null +++ b/visual-js/visual-playwright/integration-tests/global-setup.ts @@ -0,0 +1,7 @@ +import { FullConfig } from '@playwright/test'; +import { sauceVisualSetup } from "@saucelabs/visual-playwright"; + + +export default async function globalSetup(config: FullConfig){ + await sauceVisualSetup(); +} diff --git a/visual-js/visual-playwright/integration-tests/global-teardown.ts b/visual-js/visual-playwright/integration-tests/global-teardown.ts new file mode 100644 index 00000000..07cd4b02 --- /dev/null +++ b/visual-js/visual-playwright/integration-tests/global-teardown.ts @@ -0,0 +1,7 @@ +import { FullConfig } from '@playwright/test'; +import { sauceVisualTeardown } from "@saucelabs/visual-playwright"; + + +export default async function globalTeardown(config: FullConfig) { + await sauceVisualTeardown(); +} diff --git a/visual-js/visual-playwright/integration-tests/package-lock.json b/visual-js/visual-playwright/integration-tests/package-lock.json new file mode 100644 index 00000000..4eeca19b --- /dev/null +++ b/visual-js/visual-playwright/integration-tests/package-lock.json @@ -0,0 +1,140 @@ +{ + "name": "playwright-js", + "version": "1.0.0", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "name": "playwright-js", + "version": "1.0.0", + "license": "ISC", + "devDependencies": { + "@playwright/test": "1.47.0", + "@types/node": "22.5.4" + } + }, + "node_modules/@playwright/test": { + "version": "1.47.0", + "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.47.0.tgz", + "integrity": "sha512-SgAdlSwYVpToI4e/IH19IHHWvoijAYH5hu2MWSXptRypLSnzj51PcGD+rsOXFayde4P9ZLi+loXVwArg6IUkCA==", + "dev": true, + "dependencies": { + "playwright": "1.47.0" + }, + "bin": { + "playwright": "cli.js" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@types/node": { + "version": "22.5.4", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.5.4.tgz", + "integrity": "sha512-FDuKUJQm/ju9fT/SeX/6+gBzoPzlVCzfzmGkwKvRHQVxi4BntVbyIwf6a4Xn62mrvndLiml6z/UBXIdEVjQLXg==", + "dev": true, + "dependencies": { + "undici-types": "~6.19.2" + } + }, + "node_modules/fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "dev": true, + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/playwright": { + "version": "1.47.0", + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.47.0.tgz", + "integrity": "sha512-jOWiRq2pdNAX/mwLiwFYnPHpEZ4rM+fRSQpRHwEwZlP2PUANvL3+aJOF/bvISMhFD30rqMxUB4RJx9aQbfh4Ww==", + "dev": true, + "dependencies": { + "playwright-core": "1.47.0" + }, + "bin": { + "playwright": "cli.js" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "fsevents": "2.3.2" + } + }, + "node_modules/playwright-core": { + "version": "1.47.0", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.47.0.tgz", + "integrity": "sha512-1DyHT8OqkcfCkYUD9zzUTfg7EfTd+6a8MkD/NWOvjo0u/SCNd5YmY/lJwFvUZOxJbWNds+ei7ic2+R/cRz/PDg==", + "dev": true, + "bin": { + "playwright-core": "cli.js" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/undici-types": { + "version": "6.19.8", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz", + "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==", + "dev": true + } + }, + "dependencies": { + "@playwright/test": { + "version": "1.47.0", + "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.47.0.tgz", + "integrity": "sha512-SgAdlSwYVpToI4e/IH19IHHWvoijAYH5hu2MWSXptRypLSnzj51PcGD+rsOXFayde4P9ZLi+loXVwArg6IUkCA==", + "dev": true, + "requires": { + "playwright": "1.47.0" + } + }, + "@types/node": { + "version": "22.5.4", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.5.4.tgz", + "integrity": "sha512-FDuKUJQm/ju9fT/SeX/6+gBzoPzlVCzfzmGkwKvRHQVxi4BntVbyIwf6a4Xn62mrvndLiml6z/UBXIdEVjQLXg==", + "dev": true, + "requires": { + "undici-types": "~6.19.2" + } + }, + "fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "dev": true, + "optional": true + }, + "playwright": { + "version": "1.47.0", + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.47.0.tgz", + "integrity": "sha512-jOWiRq2pdNAX/mwLiwFYnPHpEZ4rM+fRSQpRHwEwZlP2PUANvL3+aJOF/bvISMhFD30rqMxUB4RJx9aQbfh4Ww==", + "dev": true, + "requires": { + "fsevents": "2.3.2", + "playwright-core": "1.47.0" + } + }, + "playwright-core": { + "version": "1.47.0", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.47.0.tgz", + "integrity": "sha512-1DyHT8OqkcfCkYUD9zzUTfg7EfTd+6a8MkD/NWOvjo0u/SCNd5YmY/lJwFvUZOxJbWNds+ei7ic2+R/cRz/PDg==", + "dev": true + }, + "undici-types": { + "version": "6.19.8", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz", + "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==", + "dev": true + } + } +} diff --git a/visual-js/visual-playwright/integration-tests/package.json b/visual-js/visual-playwright/integration-tests/package.json new file mode 100644 index 00000000..0a0e0531 --- /dev/null +++ b/visual-js/visual-playwright/integration-tests/package.json @@ -0,0 +1,17 @@ +{ + "name": "playwright-js", + "version": "1.0.0", + "description": "", + "main": "index.js", + "scripts": { + "sauce-visual": "playwright test", + "sauce-visual-check": "VISUAL_CHECK=1 playwright test" + }, + "keywords": [], + "author": "", + "license": "ISC", + "devDependencies": { + "@playwright/test": "1.47.0", + "@types/node": "22.5.4" + } +} diff --git a/visual-js/visual-playwright/integration-tests/playwright.config.ts b/visual-js/visual-playwright/integration-tests/playwright.config.ts new file mode 100644 index 00000000..1d9bc7b3 --- /dev/null +++ b/visual-js/visual-playwright/integration-tests/playwright.config.ts @@ -0,0 +1,81 @@ +import { defineConfig, devices } from '@playwright/test'; + +/** + * Read environment variables from file. + * https://github.com/motdotla/dotenv + */ +// import dotenv from 'dotenv'; +// dotenv.config({ path: path.resolve(__dirname, '.env') }); + +/** + * See https://playwright.dev/docs/test-configuration. + */ +export default defineConfig({ + testDir: './tests', + /* 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 ? 1 : undefined, + /* Reporter to use. See https://playwright.dev/docs/test-reporters */ + reporter: 'html', + /* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */ + use: { + /* Base URL to use in actions like `await page.goto('/')`. */ + baseURL: 'https://www.saucedemo.com', + testIdAttribute: 'data-test', + /* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */ + trace: 'on-first-retry', + }, + + globalSetup: require.resolve('./global-setup'), + globalTeardown: require.resolve('./global-teardown'), + + /* Configure projects for major browsers */ + projects: [ + { + name: 'chromium', + use: { ...devices['Desktop Chrome'] }, + }, + + // { + // name: 'firefox', + // use: { ...devices['Desktop Firefox'] }, + // }, + // + // { + // name: 'webkit', + // use: { ...devices['Desktop Safari'] }, + // }, + + /* Test against mobile viewports. */ + // { + // name: 'Mobile Chrome', + // use: { ...devices['Pixel 5'] }, + // }, + // { + // name: 'Mobile Safari', + // use: { ...devices['iPhone 12'] }, + // }, + + /* Test against branded browsers. */ + // { + // name: 'Microsoft Edge', + // use: { ...devices['Desktop Edge'], channel: 'msedge' }, + // }, + // { + // name: 'Google Chrome', + // use: { ...devices['Desktop Chrome'], channel: 'chrome' }, + // }, + ], + + /* Run your local dev server before starting the tests */ + // webServer: { + // command: 'npm run start', + // url: 'http://127.0.0.1:3000', + // reuseExistingServer: !process.env.CI, + // }, +}); diff --git a/visual-js/visual-playwright/integration-tests/tests/integration-test.spec.ts b/visual-js/visual-playwright/integration-tests/tests/integration-test.spec.ts new file mode 100644 index 00000000..7652ab48 --- /dev/null +++ b/visual-js/visual-playwright/integration-tests/tests/integration-test.spec.ts @@ -0,0 +1,11 @@ +import { test, expect } from '../custom-test'; + +test.beforeEach(async ({ page }) => { + await page.goto('/'); + await expect(page).toHaveTitle(/Swag Labs/); + await page.waitForLoadState('networkidle'); +}) + +test('loads the login page', async ({ page, sauceVisual }) => { + await sauceVisual.visualCheck("Before Login"); +}); diff --git a/visual-js/yarn.lock b/visual-js/yarn.lock index 516b3ae7..fe3240ff 100644 --- a/visual-js/yarn.lock +++ b/visual-js/yarn.lock @@ -3577,7 +3577,7 @@ __metadata: languageName: unknown linkType: soft -"@saucelabs/visual-playwright@^0.1.1, @saucelabs/visual-playwright@workspace:visual-playwright": +"@saucelabs/visual-playwright@^0.1.2, @saucelabs/visual-playwright@workspace:visual-playwright": version: 0.0.0-use.local resolution: "@saucelabs/visual-playwright@workspace:visual-playwright" dependencies: @@ -3613,7 +3613,7 @@ __metadata: dependencies: "@jest/globals": ^28.0.0 || ^29.0.0 "@saucelabs/visual": ^0.8.2 - "@saucelabs/visual-playwright": ^0.1.1 + "@saucelabs/visual-playwright": ^0.1.2 "@storybook/test-runner": ">=0.13.0" "@storybook/types": ^8.0.2 "@tsconfig/node18": ^2.0.0