From cdfa4e20f769e99ff2d91101e6e810b62ae59994 Mon Sep 17 00:00:00 2001 From: wandyezj Date: Tue, 25 Jun 2024 21:00:27 -0700 Subject: [PATCH] Add Playwright (#12) --- .github/workflows/main.yml | 24 ++++++-- .gitignore | 5 +- .vscode/extensions.json | 1 + config/jest.config.js | 11 +++- config/playwright.config.ts | 120 ++++++++++++++++++++++++++++++++++++ docs/notes.md | 7 +++ package-lock.json | 73 +++++++++++++++++++--- package.json | 8 +++ test/package.spec.ts | 8 +++ 9 files changed, 242 insertions(+), 15 deletions(-) create mode 100644 config/playwright.config.ts create mode 100644 test/package.spec.ts diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 7674bba..637546c 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -48,22 +48,38 @@ jobs: - name: check-tools run: npm run check-tools --if-present - # Build + # 'npm run build' broken into separate steps - name: clean run: npm run clean --if-present - name: style run: npm run style-check --if-present + - name: spell-check + run: npm run spell-check --if-present + - name: lint run: npm run lint --if-present - name: compile run: npm run compile --if-present - - name: spell-check - run: npm run spell-check --if-present - # Test - name: test run: npm test --if-present + + # end to end tests + + # Separate commands to make it easier to see test results. + - name: Playwright Install + run: npm run playwright-install + + - name: Playwright Test + run: npm run playwright-test + + - uses: actions/upload-artifact@v4 + if: ${{ !cancelled() }} + with: + name: playwright-report + path: playwright-report/ + retention-days: 30 diff --git a/.gitignore b/.gitignore index 69ba61a..643cf55 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,6 @@ node_modules/ dist/ -temp/ \ No newline at end of file +temp/ +/test-results/ +/playwright-report/ +/playwright/.cache/ \ No newline at end of file diff --git a/.vscode/extensions.json b/.vscode/extensions.json index 5ed0c4e..7229117 100644 --- a/.vscode/extensions.json +++ b/.vscode/extensions.json @@ -3,6 +3,7 @@ "esbenp.prettier-vscode", "dbaeumer.vscode-eslint", "davidanson.vscode-markdownlint", + "ms-playwright.playwright", "bierner.github-markdown-preview", "streetsidesoftware.code-spell-checker", "vscode-icons-team.vscode-icons", diff --git a/config/jest.config.js b/config/jest.config.js index 312102c..9a8ff26 100644 --- a/config/jest.config.js +++ b/config/jest.config.js @@ -1,7 +1,12 @@ -// eslint-disable-next-line no-undef -module.exports = { +/** @type {import('jest').Config} */ +const config = { rootDir: "../", + // Only run test files with postfix .test.ts + testRegex: ".*test.ts", preset: "ts-jest", testEnvironment: "node", - coverageDirectory: "./temp/coverage" + coverageDirectory: "./temp/coverage", }; + +// eslint-disable-next-line no-undef +module.exports = config; diff --git a/config/playwright.config.ts b/config/playwright.config.ts new file mode 100644 index 0000000..4523b68 --- /dev/null +++ b/config/playwright.config.ts @@ -0,0 +1,120 @@ +import { defineConfig, devices } from "@playwright/test"; +import path from "path"; +import * as fs from "fs"; + +// path is based on the current working directory which is different between the extension and command line. + +// extension requires +const testDirExtension = path.resolve("..", "test"); + +// command line requires +const testDirCmd = path.resolve("test"); + +// Decide based on what cwd is. +const isCmd = fs.existsSync(testDirCmd); + +const testDir = isCmd ? testDirCmd : testDirExtension; + +/** + * See https://playwright.dev/docs/test-configuration. + */ +const config = defineConfig({ + testDir, + testMatch: "test/*.spec.ts", + + /* Maximum time one test can run for. */ + timeout: 30 * 1000, + expect: { + /** + * Maximum time expect() should wait for the condition to be met. + * For example in `await expect(locator).toHaveText();` + */ + timeout: 5000, + }, + /* 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"], process.env.CI ? ["github"] : ["list"]], + /* 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: 0, + /* 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", + + // allow reading from clipboard + permissions: ["clipboard-read"], + }, + + /* 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: { + // channel: 'msedge', + // }, + // }, + // { + // name: 'Google Chrome', + // use: { + // channel: 'chrome', + // }, + // }, + ], + + /* Folder for test artifacts such as screenshots, videos, traces, etc. */ + // outputDir: 'test-results/', + + /* Run your local dev server before starting the tests */ + // webServer: { + // command: 'npm run start', + // port: 3000, + // }, +}); + +export default config; diff --git a/docs/notes.md b/docs/notes.md index d7e5cef..fd1b813 100644 --- a/docs/notes.md +++ b/docs/notes.md @@ -35,6 +35,7 @@ Designed for developing TypeScript NPM libraries. The layout can be applied to o - [prettier disables](#prettier-disables) - [prettier settings](#prettier-settings) - [cspell](#cspell) + - [Playwright](#playwright) - [jest](#jest) - [jest commands](#jest-commands) - [jest coverage disables](#jest-coverage-disables) @@ -190,6 +191,7 @@ should be used to build everything and test the package. - [node](https://nodejs.org/) [download node lts](https://nodejs.org/en/download/) - [TypeScript](https://www.typescriptlang.org/) - [jest](https://jestjs.io/) +- [Playwright](https://playwright.dev/) - [prettier](https://prettier.io/) - [eslint](https://eslint.org/) - [api-extractor](https://api-extractor.com/) @@ -240,6 +242,9 @@ cSpell:ignore dbaeumer esbenp DavidAnson - Code Spell Checker - id: `streetsidesoftware.code-spell-checker` - config: `.vscode\settings.json` add additional words `cSpell.words` +- Playwright + - id: `ms-playwright.playwright` + - config: `config\playwright.config.ts` ## Tool Notes @@ -299,6 +304,8 @@ Ignore a specific word in a file. [cspell Inline Document Settings](https://cspell.org/configuration/document-settings/#inline-document-settings) +### Playwright + ### Jest #### jest commands diff --git a/package-lock.json b/package-lock.json index be0f641..279f5a7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,6 +8,10 @@ "name": "package", "version": "0.0.0", "license": "Unlicense", + "dependencies": { + "@playwright/test": "^1.45.0", + "playwright": "^1.45.0" + }, "devDependencies": { "@microsoft/api-documenter": "7.23.15", "@microsoft/api-extractor": "7.39.0", @@ -1921,6 +1925,20 @@ "node": ">=14" } }, + "node_modules/@playwright/test": { + "version": "1.45.0", + "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.45.0.tgz", + "integrity": "sha512-TVYsfMlGAaxeUllNkywbwek67Ncf8FRGn8ZlRdO291OL3NjG9oMbfVhyP82HQF0CZLMrYsvesqoUekxdWuF9Qw==", + "dependencies": { + "playwright": "1.45.0" + }, + "bin": { + "playwright": "cli.js" + }, + "engines": { + "node": ">=18" + } + }, "node_modules/@rushstack/node-core-library": { "version": "3.62.0", "resolved": "https://registry.npmjs.org/@rushstack/node-core-library/-/node-core-library-3.62.0.tgz", @@ -2589,12 +2607,12 @@ } }, "node_modules/braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", "dev": true, "dependencies": { - "fill-range": "^7.0.1" + "fill-range": "^7.1.1" }, "engines": { "node": ">=8" @@ -3753,9 +3771,9 @@ } }, "node_modules/fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", "dev": true, "dependencies": { "to-regex-range": "^5.0.1" @@ -5535,6 +5553,47 @@ "node": ">=8" } }, + "node_modules/playwright": { + "version": "1.45.0", + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.45.0.tgz", + "integrity": "sha512-4z3ac3plDfYzGB6r0Q3LF8POPR20Z8D0aXcxbJvmfMgSSq1hkcgvFRXJk9rUq5H/MJ0Ktal869hhOdI/zUTeLA==", + "dependencies": { + "playwright-core": "1.45.0" + }, + "bin": { + "playwright": "cli.js" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "fsevents": "2.3.2" + } + }, + "node_modules/playwright-core": { + "version": "1.45.0", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.45.0.tgz", + "integrity": "sha512-lZmHlFQ0VYSpAs43dRq1/nJ9G/6SiTI7VPqidld9TDefL9tX87bTKExWZZUF5PeRyqtXqd8fQi2qmfIedkwsNQ==", + "bin": { + "playwright-core": "cli.js" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/playwright/node_modules/fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, "node_modules/prelude-ls": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", diff --git a/package.json b/package.json index 32e47a1..869d69d 100644 --- a/package.json +++ b/package.json @@ -33,6 +33,10 @@ "check-install": "ts-node scripts/check-install.ts", "check-environment": "ts-node scripts/check-environment.ts", "package-update": "ts-node scripts/update.ts", + "playwright": "npm run playwright-install && npm run playwright-test", + "playwright-install": "playwright install --with-deps chromium", + "playwright-test": "playwright test --config ./config/playwright.config.ts", + "playwright-report": "playwright show-report", "start": "ts-node test/main.ts" }, "repository": { @@ -62,5 +66,9 @@ "ts-jest": "29.0.5", "ts-node": "10.9.1", "typescript": "5.3.3" + }, + "dependencies": { + "@playwright/test": "^1.45.0", + "playwright": "^1.45.0" } } diff --git a/test/package.spec.ts b/test/package.spec.ts new file mode 100644 index 0000000..1e24829 --- /dev/null +++ b/test/package.spec.ts @@ -0,0 +1,8 @@ +import { test, expect } from "@playwright/test"; +import { hello } from "../src/index"; + +test("basic", () => { + const actual = hello(); + const expected = "hello"; + expect(actual).toBe(expected); +});