From 43b0387379e6fb3b96ba9a230786314cfc195b38 Mon Sep 17 00:00:00 2001 From: Mikael Siidorow Date: Sat, 10 Aug 2024 19:07:27 +0300 Subject: [PATCH] wip: integration tests --- .github/workflows/playwright.yml | 37 +++++++++ package.json | 4 +- pnpm-lock.yaml | 137 +++++++++++++++++++++---------- pnpm-workspace.yaml | 2 + tests/.gitignore | 5 ++ tests/package.json | 13 +++ tests/playwright.config.ts | 71 ++++++++++++++++ tests/tests/main.spec.ts | 15 ++++ tests/tsconfig.json | 3 + turbo.json | 6 +- 10 files changed, 245 insertions(+), 48 deletions(-) create mode 100644 .github/workflows/playwright.yml create mode 100644 tests/.gitignore create mode 100644 tests/package.json create mode 100644 tests/playwright.config.ts create mode 100644 tests/tests/main.spec.ts create mode 100644 tests/tsconfig.json diff --git a/.github/workflows/playwright.yml b/.github/workflows/playwright.yml new file mode 100644 index 00000000..fe92e0d7 --- /dev/null +++ b/.github/workflows/playwright.yml @@ -0,0 +1,37 @@ +name: Playwright Tests +on: + push: + # branches: [main] + pull_request: + # branches: [main] +jobs: + test: + timeout-minutes: 60 + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - uses: pnpm/action-setup@v4 + with: + version: 9.6.0 + + - uses: actions/setup-node@v4 + with: + node-version: 22 + cache: "pnpm" + + - name: Install dependencies + run: pnpm install + + - name: Install Playwright Browsers + run: pnpm exec playwright install --with-deps + + - name: Run Playwright tests + run: pnpm exec playwright test + + - uses: actions/upload-artifact@v4 + if: always() + with: + name: playwright-report + path: playwright-report/ + retention-days: 30 diff --git a/package.json b/package.json index 5bb990ef..2614480f 100644 --- a/package.json +++ b/package.json @@ -20,10 +20,12 @@ "docker:start:web": "docker run -p 3000:3000 web", "format": "prettier --write \"**/*.{js,ts,ts,tsx,md,json}\"", "lint": "turbo run lint --cache-dir=.turbo", - "start": "dotenv -- turbo run start --cache-dir=.turbo", + "start": "NODE_ENV=\"production\" dotenv -- turbo run start --cache-dir=.turbo", + "test": "turbo run test --cache-dir=.turbo", "typecheck": "turbo run typecheck --cache-dir=.turbo" }, "devDependencies": { + "@playwright/test": "catalog:", "dotenv-cli": "^7.4.2", "prettier": "^3.3.3", "prettier-plugin-packagejson": "^2.5.1", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 082a0a46..c8c54d6d 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -6,6 +6,9 @@ settings: catalogs: default: + '@playwright/test': + specifier: ^1.46.0 + version: 1.46.0 '@tailwindcss/typography': specifier: ^0.5.14 version: 0.5.14 @@ -60,6 +63,9 @@ importers: .: devDependencies: + '@playwright/test': + specifier: 'catalog:' + version: 1.46.0 dotenv-cli: specifier: ^7.4.2 version: 7.4.2 @@ -183,13 +189,13 @@ importers: version: 4.17.21 next: specifier: ^14.2.5 - version: 14.2.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.77.8) + version: 14.2.5(@playwright/test@1.46.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.77.8) next-international: specifier: ^1.2.4 version: 1.2.4(patch_hash=xeq66wimb7lsj4vnwftgigy5za) nextjs-toploader: specifier: ^1.6.12 - version: 1.6.12(next@14.2.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.77.8))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + version: 1.6.12(next@14.2.5(@playwright/test@1.46.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.77.8))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) payload-admin-bar: specifier: ^1.0.6 version: 1.0.6(react-dom@18.3.1(react@18.3.1))(react@18.3.1) @@ -402,6 +408,18 @@ importers: specifier: 'catalog:' version: 5.5.4 + tests: + devDependencies: + '@playwright/test': + specifier: 'catalog:' + version: 1.46.0 + '@tietokilta/config-typescript': + specifier: workspace:* + version: link:../packages/config-typescript + '@types/node': + specifier: 'catalog:' + version: 22.2.0 + packages: '@alloc/quick-lru@5.2.0': @@ -1649,6 +1667,11 @@ packages: resolution: {integrity: sha512-cq8o4cWH0ibXh9VGi5P20Tu9XF/0fFXl9EUinr9QfTM7a7p0oTA4iJRCQWppXR1Pg8dSM0UCItCkPwsk9qWWYA==} engines: {node: ^12.20.0 || ^14.18.0 || >=16.0.0} + '@playwright/test@1.46.0': + resolution: {integrity: sha512-/QYft5VArOrGRP5pgkrfKksqsKA6CEFyGQ/gjNe6q0y4tZ1aaPfq4gIjudr1s3D+pXyrPRdsy4opKDrjBabE5w==} + engines: {node: '>=18'} + hasBin: true + '@polka/url@1.0.0-next.25': resolution: {integrity: sha512-j7P6Rgr3mmtdkeDGTe0E/aYyWEWVtc5yFXtHCRHs28/jptDEWfaVOc5T7cblqy1XKPPfCxJc/8DwQ5YgLOZOVQ==} @@ -2894,13 +2917,6 @@ packages: resolution: {integrity: sha512-Xcz9l0z7y9yQ9rdDaxlmaI4uJHf/T8g9hOEzJcsEqX2SjCj4J20uK7+ldkDHMbpJDK76wF7xEIgxc/vSlsfw5w==} engines: {node: '>=10.12.0'} - autoprefixer@10.4.19: - resolution: {integrity: sha512-BaENR2+zBZ8xXhM4pUaKUxlVdxZ0EZhjvbopwnXmxRUfqDmwSpC2lAi/QXvx7NRdPCo1WKEcEF6mV64si1z4Ew==} - engines: {node: ^10 || ^12 || >=14} - hasBin: true - peerDependencies: - postcss: ^8.1.0 - autoprefixer@10.4.20: resolution: {integrity: sha512-XY25y5xSv/wEoqzDyXXME4AFfkZI0P23z6Fs3YgymDnKJkCGOnkL0iTxCa85UTqaSgfcqyf3UA6+c7wUvx/16g==} engines: {node: ^10 || ^12 || >=14} @@ -4125,6 +4141,11 @@ packages: fs.realpath@1.0.0: resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} + fsevents@2.3.2: + resolution: {integrity: sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==} + engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} + os: [darwin] + fsevents@2.3.3: resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} @@ -5749,6 +5770,16 @@ packages: resolution: {integrity: sha512-nDywThFk1i4BQK4twPQ6TA4RT8bDY96yeuCVBWL3ePARCiEKDRSrNGbFIgUJpLp+XeIR65v8ra7WuJOFUBtkMA==} engines: {node: '>=8'} + playwright-core@1.46.0: + resolution: {integrity: sha512-9Y/d5UIwuJk8t3+lhmMSAJyNP1BUC/DqP3cQJDQQL/oWqAiuPTLgy7Q5dzglmTLwcBRdetzgNM/gni7ckfTr6A==} + engines: {node: '>=18'} + hasBin: true + + playwright@1.46.0: + resolution: {integrity: sha512-XYJ5WvfefWONh1uPAUAi0H2xXV5S3vrtcnXe6uAOgdGi3aSpqOSXX08IAjXW34xitfuOJsvXU5anXZxPSEQiJw==} + engines: {node: '>=18'} + hasBin: true + pluralize@8.0.0: resolution: {integrity: sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==} engines: {node: '>=4'} @@ -8390,7 +8421,7 @@ snapshots: '@babel/helper-split-export-declaration': 7.24.7 '@babel/parser': 7.24.8 '@babel/types': 7.24.9 - debug: 4.3.5 + debug: 4.3.6 globals: 11.12.0 transitivePeerDependencies: - supports-color @@ -8807,7 +8838,7 @@ snapshots: '@eslint/eslintrc@2.1.4': dependencies: ajv: 6.12.6 - debug: 4.3.5 + debug: 4.3.6 espree: 9.6.1 globals: 13.24.0 ignore: 5.3.1 @@ -8863,7 +8894,7 @@ snapshots: '@humanwhocodes/config-array@0.11.14': dependencies: '@humanwhocodes/object-schema': 2.0.3 - debug: 4.3.5 + debug: 4.3.6 minimatch: 3.1.2 transitivePeerDependencies: - supports-color @@ -9356,6 +9387,10 @@ snapshots: '@pkgr/core@0.1.1': {} + '@playwright/test@1.46.0': + dependencies: + playwright: 1.46.0 + '@polka/url@1.0.0-next.25': {} '@popperjs/core@2.11.8': {} @@ -10364,7 +10399,7 @@ snapshots: dependencies: '@typescript-eslint/typescript-estree': 7.16.1(typescript@5.5.4) '@typescript-eslint/utils': 7.16.1(eslint@8.57.0)(typescript@5.5.4) - debug: 4.3.5 + debug: 4.3.6 eslint: 8.57.0 ts-api-utils: 1.3.0(typescript@5.5.4) optionalDependencies: @@ -10380,7 +10415,7 @@ snapshots: dependencies: '@typescript-eslint/types': 5.62.0 '@typescript-eslint/visitor-keys': 5.62.0 - debug: 4.3.5 + debug: 4.3.6 globby: 11.1.0 is-glob: 4.0.3 semver: 7.6.2 @@ -10394,7 +10429,7 @@ snapshots: dependencies: '@typescript-eslint/types': 7.16.1 '@typescript-eslint/visitor-keys': 7.16.1 - debug: 4.3.5 + debug: 4.3.6 globby: 11.1.0 is-glob: 4.0.3 minimatch: 9.0.5 @@ -10618,7 +10653,7 @@ snapshots: agent-base@7.1.1: dependencies: - debug: 4.3.5 + debug: 4.3.6 transitivePeerDependencies: - supports-color @@ -10773,7 +10808,7 @@ snapshots: atomically@1.7.0: {} - autoprefixer@10.4.19(postcss@8.4.31): + autoprefixer@10.4.20(postcss@8.4.31): dependencies: browserslist: 4.23.3 caniuse-lite: 1.0.30001649 @@ -11226,13 +11261,13 @@ snapshots: css-loader@5.2.7(webpack@5.93.0(@swc/core@1.6.1(@swc/helpers@0.5.12))(webpack-cli@4.10.0)): dependencies: - icss-utils: 5.1.0(postcss@8.4.31) + icss-utils: 5.1.0(postcss@8.4.41) loader-utils: 2.0.4 - postcss: 8.4.31 - postcss-modules-extract-imports: 3.1.0(postcss@8.4.31) - postcss-modules-local-by-default: 4.0.5(postcss@8.4.31) - postcss-modules-scope: 3.2.0(postcss@8.4.31) - postcss-modules-values: 4.0.0(postcss@8.4.31) + postcss: 8.4.41 + postcss-modules-extract-imports: 3.1.0(postcss@8.4.41) + postcss-modules-local-by-default: 4.0.5(postcss@8.4.41) + postcss-modules-scope: 3.2.0(postcss@8.4.41) + postcss-modules-values: 4.0.0(postcss@8.4.41) postcss-value-parser: 4.2.0 schema-utils: 3.3.0 semver: 7.6.2 @@ -11986,7 +12021,7 @@ snapshots: ajv: 6.12.6 chalk: 4.1.2 cross-spawn: 7.0.3 - debug: 4.3.5 + debug: 4.3.6 doctrine: 3.0.0 escape-string-regexp: 4.0.0 eslint-scope: 7.2.2 @@ -12325,6 +12360,9 @@ snapshots: fs.realpath@1.0.0: {} + fsevents@2.3.2: + optional: true + fsevents@2.3.3: optional: true @@ -12639,7 +12677,7 @@ snapshots: http-proxy-agent@7.0.2: dependencies: agent-base: 7.1.1 - debug: 4.3.5 + debug: 4.3.6 transitivePeerDependencies: - supports-color @@ -12648,7 +12686,7 @@ snapshots: https-proxy-agent@7.0.5: dependencies: agent-base: 7.1.1 - debug: 4.3.5 + debug: 4.3.6 transitivePeerDependencies: - supports-color @@ -12668,9 +12706,9 @@ snapshots: dependencies: safer-buffer: 2.1.2 - icss-utils@5.1.0(postcss@8.4.31): + icss-utils@5.1.0(postcss@8.4.41): dependencies: - postcss: 8.4.31 + postcss: 8.4.41 ieee754@1.2.1: {} @@ -13617,7 +13655,7 @@ snapshots: micromark@2.11.4: dependencies: - debug: 4.3.5 + debug: 4.3.6 parse-entities: 2.0.0 transitivePeerDependencies: - supports-color @@ -13625,7 +13663,7 @@ snapshots: micromark@4.0.0: dependencies: '@types/debug': 4.1.12 - debug: 4.3.5 + debug: 4.3.6 decode-named-character-reference: 1.0.2 devlop: 1.1.0 micromark-core-commonmark: 2.0.1 @@ -13801,7 +13839,7 @@ snapshots: next-tick@1.1.0: {} - next@14.2.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.77.8): + next@14.2.5(@playwright/test@1.46.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.77.8): dependencies: '@next/env': 14.2.5 '@swc/helpers': 0.5.5 @@ -13822,14 +13860,15 @@ snapshots: '@next/swc-win32-arm64-msvc': 14.2.5 '@next/swc-win32-ia32-msvc': 14.2.5 '@next/swc-win32-x64-msvc': 14.2.5 + '@playwright/test': 1.46.0 sass: 1.77.8 transitivePeerDependencies: - '@babel/core' - babel-plugin-macros - nextjs-toploader@1.6.12(next@14.2.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.77.8))(react-dom@18.3.1(react@18.3.1))(react@18.3.1): + nextjs-toploader@1.6.12(next@14.2.5(@playwright/test@1.46.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.77.8))(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: - next: 14.2.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.77.8) + next: 14.2.5(@playwright/test@1.46.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.77.8) nprogress: 0.2.0 prop-types: 15.8.1 react: 18.3.1 @@ -14332,6 +14371,14 @@ snapshots: dependencies: find-up: 3.0.0 + playwright-core@1.46.0: {} + + playwright@1.46.0: + dependencies: + playwright-core: 1.46.0 + optionalDependencies: + fsevents: 2.3.2 + pluralize@8.0.0: {} possible-typed-array-names@1.0.0: {} @@ -14482,26 +14529,26 @@ snapshots: postcss: 8.4.31 postcss-value-parser: 4.2.0 - postcss-modules-extract-imports@3.1.0(postcss@8.4.31): + postcss-modules-extract-imports@3.1.0(postcss@8.4.41): dependencies: - postcss: 8.4.31 + postcss: 8.4.41 - postcss-modules-local-by-default@4.0.5(postcss@8.4.31): + postcss-modules-local-by-default@4.0.5(postcss@8.4.41): dependencies: - icss-utils: 5.1.0(postcss@8.4.31) - postcss: 8.4.31 + icss-utils: 5.1.0(postcss@8.4.41) + postcss: 8.4.41 postcss-selector-parser: 6.1.1 postcss-value-parser: 4.2.0 - postcss-modules-scope@3.2.0(postcss@8.4.31): + postcss-modules-scope@3.2.0(postcss@8.4.41): dependencies: - postcss: 8.4.31 + postcss: 8.4.41 postcss-selector-parser: 6.1.1 - postcss-modules-values@4.0.0(postcss@8.4.31): + postcss-modules-values@4.0.0(postcss@8.4.41): dependencies: - icss-utils: 5.1.0(postcss@8.4.31) - postcss: 8.4.31 + icss-utils: 5.1.0(postcss@8.4.41) + postcss: 8.4.41 postcss-nested@6.2.0(postcss@8.4.41): dependencies: @@ -14558,7 +14605,7 @@ snapshots: '@csstools/postcss-text-decoration-shorthand': 3.0.7(postcss@8.4.31) '@csstools/postcss-trigonometric-functions': 3.0.10(postcss@8.4.31) '@csstools/postcss-unset-value': 3.0.1(postcss@8.4.31) - autoprefixer: 10.4.19(postcss@8.4.31) + autoprefixer: 10.4.20(postcss@8.4.31) browserslist: 4.23.2 css-blank-pseudo: 6.0.2(postcss@8.4.31) css-has-pseudo: 6.0.5(postcss@8.4.31) @@ -16085,7 +16132,7 @@ snapshots: '@types/node': 20.14.11 '@types/unist': 3.0.2 concat-stream: 2.0.0 - debug: 4.3.5 + debug: 4.3.6 extend: 3.0.2 glob: 10.4.5 ignore: 5.3.1 diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index 26aa8718..f5df701e 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -1,7 +1,9 @@ packages: - apps/* - packages/* + - tests catalog: + "@playwright/test": ^1.46.0 "@tailwindcss/typography": ^0.5.14 "@types/node": ^22.2.0 "@types/react-dom": ^18.3.0 diff --git a/tests/.gitignore b/tests/.gitignore new file mode 100644 index 00000000..68c5d18f --- /dev/null +++ b/tests/.gitignore @@ -0,0 +1,5 @@ +node_modules/ +/test-results/ +/playwright-report/ +/blob-report/ +/playwright/.cache/ diff --git a/tests/package.json b/tests/package.json new file mode 100644 index 00000000..cdf0cced --- /dev/null +++ b/tests/package.json @@ -0,0 +1,13 @@ +{ + "name": "tests", + "version": "0.0.0", + "private": true, + "scripts": { + "test": "playwright test --repeat-each=100" + }, + "devDependencies": { + "@playwright/test": "catalog:", + "@tietokilta/config-typescript": "workspace:*", + "@types/node": "catalog:" + } +} diff --git a/tests/playwright.config.ts b/tests/playwright.config.ts new file mode 100644 index 00000000..ebeae534 --- /dev/null +++ b/tests/playwright.config.ts @@ -0,0 +1,71 @@ +import { defineConfig, devices } from "@playwright/test"; + +/** + * 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: "http://127.0.0.1:3000", + + /* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */ + trace: "on-first-retry", + }, + + /* Configure projects for major browsers */ + projects: [ + { + name: "chromium", + use: { ...devices["Desktop Chrome"], locale: "fi-FI" }, + }, + + { + name: "firefox", + use: { ...devices["Desktop Firefox"], locale: "fi-FI" }, + }, + + { + name: "webkit", + use: { ...devices["Desktop Safari"], locale: "fi-FI" }, + }, + + /* 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/tests/tests/main.spec.ts b/tests/tests/main.spec.ts new file mode 100644 index 00000000..3cdf2f2d --- /dev/null +++ b/tests/tests/main.spec.ts @@ -0,0 +1,15 @@ +import { test, expect } from "@playwright/test"; + +test("has title", async ({ page }) => { + await page.goto("/"); + + await expect(page).toHaveTitle(/Tietokilta/); +}); + +test("upcoming events link", async ({ page }) => { + await page.goto("/"); + + await page.getByRole("link", { name: "Tulevat tapahtumat" }).click(); + + await expect(page.getByRole("heading", { name: "Tapahtumat" })).toBeVisible(); +}); diff --git a/tests/tsconfig.json b/tests/tsconfig.json new file mode 100644 index 00000000..27f4ac12 --- /dev/null +++ b/tests/tsconfig.json @@ -0,0 +1,3 @@ +{ + "extends": "@tietokilta/config-typescript/base.json" +} diff --git a/turbo.json b/turbo.json index ea29fa8a..253e3b66 100644 --- a/turbo.json +++ b/turbo.json @@ -19,7 +19,8 @@ "PUBLIC_ILMOMASIINA_URL", "PUBLIC_LEGACY_URL", "GIT_COMMIT_SHA", - "NODE_ENV" + "NODE_ENV", + "CI" ], "tasks": { "build": { @@ -40,10 +41,11 @@ "persistent": true }, "start": { - "dependsOn": ["^build", "codegen", "^codegen"], + "dependsOn": ["build", "^build", "codegen", "^codegen"], "cache": false, "persistent": true }, + "test": {}, "clean": { "cache": false }