From f1efb56d524d7391b440911d0de653edeb5647e4 Mon Sep 17 00:00:00 2001 From: Mikyo King Date: Tue, 10 Sep 2024 16:38:28 -0600 Subject: [PATCH 1/9] feat(auth): playwright tests --- app/.gitignore | 6 +- app/package.json | 3 + app/playwright.config.ts | 78 +++++++++++++++++++++ app/pnpm-lock.yaml | 147 +++++++++++++++++++++++++-------------- app/tests/login.spec.ts | 10 +++ 5 files changed, 190 insertions(+), 54 deletions(-) create mode 100644 app/playwright.config.ts create mode 100644 app/tests/login.spec.ts diff --git a/app/.gitignore b/app/.gitignore index d875631601..960a0f90da 100644 --- a/app/.gitignore +++ b/app/.gitignore @@ -1,3 +1,7 @@ node_modules dist -stats.html \ No newline at end of file +stats.html +/test-results/ +/playwright-report/ +/blob-report/ +/playwright/.cache/ diff --git a/app/package.json b/app/package.json index 55d3b3422d..7387748060 100644 --- a/app/package.json +++ b/app/package.json @@ -50,11 +50,13 @@ }, "devDependencies": { "@emotion/react": "^11.11.4", + "@playwright/test": "^1.47.0", "@types/d3-format": "^3.0.4", "@types/d3-scale-chromatic": "^3.0.3", "@types/d3-time-format": "^4.0.3", "@types/jest": "^29.5.12", "@types/lodash": "^4.17.7", + "@types/node": "^22.5.4", "@types/react": "18.2.48", "@types/react-dom": "^18.3.0", "@types/react-relay": "^16.0.6", @@ -88,6 +90,7 @@ "build:static": "cpy ./static ../src/phoenix/server", "build:relay": "relay-compiler", "test": "jest --config ./jest.config.js", + "test:e2e": "pnpm run dev:auth & playwright test --ui", "dev": "pnpm run dev:server & pnpm run build:static && pnpm run build:relay && vite", "dev:auth": "export PHOENIX_ENABLE_AUTH=true && export PHOENIX_SECRET=sa18f44bd9b6b4b0606e58a2d03d09039aee8283e0074c6517fda58577a07dd#A && pnpm run dev:server & pnpm run build:static && pnpm run build:relay && vite", "dev:ui": "pnpm run build:static && pnpm run build:relay && vite", diff --git a/app/playwright.config.ts b/app/playwright.config.ts new file mode 100644 index 0000000000..4a501ea116 --- /dev/null +++ b/app/playwright.config.ts @@ -0,0 +1,78 @@ +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: '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'] }, + }, + + { + 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/app/pnpm-lock.yaml b/app/pnpm-lock.yaml index 8c6ec25f12..f3a0ca5661 100644 --- a/app/pnpm-lock.yaml +++ b/app/pnpm-lock.yaml @@ -138,6 +138,9 @@ importers: '@emotion/react': specifier: ^11.11.4 version: 11.11.4(@types/react@18.2.48)(react@18.2.0) + '@playwright/test': + specifier: ^1.47.0 + version: 1.47.0 '@types/d3-format': specifier: ^3.0.4 version: 3.0.4 @@ -153,6 +156,9 @@ importers: '@types/lodash': specifier: ^4.17.7 version: 4.17.7 + '@types/node': + specifier: ^22.5.4 + version: 22.5.4 '@types/react': specifier: 18.2.48 version: 18.2.48 @@ -179,7 +185,7 @@ importers: version: 7.16.1(eslint@8.57.0)(typescript@5.4.5) '@vitejs/plugin-react': specifier: ^4.3.1 - version: 4.3.1(vite@5.3.3(@types/node@20.14.11)) + version: 4.3.1(vite@5.3.3(@types/node@22.5.4)) cpy-cli: specifier: ^5.0.0 version: 5.0.0 @@ -203,7 +209,7 @@ importers: version: 16.9.0 jest: specifier: ^29.7.0 - version: 29.7.0(@types/node@20.14.11)(babel-plugin-macros@3.1.0) + version: 29.7.0(@types/node@22.5.4)(babel-plugin-macros@3.1.0) jest-environment-jsdom: specifier: ^29.7.0 version: 29.7.0 @@ -221,16 +227,16 @@ importers: version: 5.12.0(rollup@4.18.1) ts-jest: specifier: ^29.2.2 - version: 29.2.2(@babel/core@7.24.9)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.24.9))(esbuild@0.23.0)(jest@29.7.0(@types/node@20.14.11)(babel-plugin-macros@3.1.0))(typescript@5.4.5) + version: 29.2.2(@babel/core@7.24.9)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.24.9))(esbuild@0.23.0)(jest@29.7.0(@types/node@22.5.4)(babel-plugin-macros@3.1.0))(typescript@5.4.5) typescript: specifier: ~5.4.5 version: 5.4.5 vite: specifier: ^5.3.3 - version: 5.3.3(@types/node@20.14.11) + version: 5.3.3(@types/node@22.5.4) vite-plugin-relay: specifier: ^2.1.0 - version: 2.1.0(babel-plugin-relay@17.0.0)(vite@5.3.3(@types/node@20.14.11)) + version: 2.1.0(babel-plugin-relay@17.0.0)(vite@5.3.3(@types/node@22.5.4)) packages: @@ -1012,6 +1018,11 @@ packages: resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} engines: {node: '>= 8'} + '@playwright/test@1.47.0': + resolution: {integrity: sha512-SgAdlSwYVpToI4e/IH19IHHWvoijAYH5hu2MWSXptRypLSnzj51PcGD+rsOXFayde4P9ZLi+loXVwArg6IUkCA==} + engines: {node: '>=18'} + hasBin: true + '@react-aria/breadcrumbs@3.5.13': resolution: {integrity: sha512-G1Gqf/P6kVdfs94ovwP18fTWuIxadIQgHsXS08JEVcFVYMjb9YjqnEBaohUxD1tq2WldMbYw53ahQblT4NTG+g==} peerDependencies: @@ -1599,8 +1610,8 @@ packages: '@types/ms@0.7.34': resolution: {integrity: sha512-nG96G3Wp6acyAgJqGasjODb+acrI7KltPiRxzHPXnP3NgI28bpQDRv53olbqGXbfcgF5aiiHmO3xpwEpS5Ld9g==} - '@types/node@20.14.11': - resolution: {integrity: sha512-kprQpL8MMeszbz6ojB5/tU8PLN4kesnN8Gjzw349rDlNgsSzg90lAVj3llK99Dh7JON+t9AuscPPFW6mPbTnSA==} + '@types/node@22.5.4': + resolution: {integrity: sha512-FDuKUJQm/ju9fT/SeX/6+gBzoPzlVCzfzmGkwKvRHQVxi4BntVbyIwf6a4Xn62mrvndLiml6z/UBXIdEVjQLXg==} '@types/offscreencanvas@2019.7.3': resolution: {integrity: sha512-ieXiYmgSRXUDeOntE1InxjWyvEelZGP63M+cGuquuRLuIKKT1osnkXjxev9B7d1nXSug5vpunx+gNlbVxMlC9A==} @@ -2682,6 +2693,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} @@ -3882,6 +3898,16 @@ packages: resolution: {integrity: sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==} engines: {node: '>=8'} + playwright-core@1.47.0: + resolution: {integrity: sha512-1DyHT8OqkcfCkYUD9zzUTfg7EfTd+6a8MkD/NWOvjo0u/SCNd5YmY/lJwFvUZOxJbWNds+ei7ic2+R/cRz/PDg==} + engines: {node: '>=18'} + hasBin: true + + playwright@1.47.0: + resolution: {integrity: sha512-jOWiRq2pdNAX/mwLiwFYnPHpEZ4rM+fRSQpRHwEwZlP2PUANvL3+aJOF/bvISMhFD30rqMxUB4RJx9aQbfh4Ww==} + engines: {node: '>=18'} + hasBin: true + polished@4.3.1: resolution: {integrity: sha512-OBatVyC/N7SCW/FaDHrSd+vn0o5cS855TOmYi4OkdWUMSJCET/xip//ch8xGUvtr3i44X9LVyWwQlRMTN3pwSA==} engines: {node: '>=10'} @@ -4566,8 +4592,8 @@ packages: unbox-primitive@1.0.2: resolution: {integrity: sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==} - undici-types@5.26.5: - resolution: {integrity: sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==} + undici-types@6.19.8: + resolution: {integrity: sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==} unified@11.0.5: resolution: {integrity: sha512-xKvGhPWw3k84Qjh8bI3ZeJjqnyadK+GEFtazSfZv/rKeTkTjOJho6mFqh2SM96iIcZokxiOpg78GazTSg8+KHA==} @@ -5522,7 +5548,7 @@ snapshots: '@jest/console@29.7.0': dependencies: '@jest/types': 29.6.3 - '@types/node': 20.14.11 + '@types/node': 22.5.4 chalk: 4.1.2 jest-message-util: 29.7.0 jest-util: 29.7.0 @@ -5535,14 +5561,14 @@ snapshots: '@jest/test-result': 29.7.0 '@jest/transform': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 20.14.11 + '@types/node': 22.5.4 ansi-escapes: 4.3.2 chalk: 4.1.2 ci-info: 3.9.0 exit: 0.1.2 graceful-fs: 4.2.11 jest-changed-files: 29.7.0 - jest-config: 29.7.0(@types/node@20.14.11)(babel-plugin-macros@3.1.0) + jest-config: 29.7.0(@types/node@22.5.4)(babel-plugin-macros@3.1.0) jest-haste-map: 29.7.0 jest-message-util: 29.7.0 jest-regex-util: 29.6.3 @@ -5567,7 +5593,7 @@ snapshots: dependencies: '@jest/fake-timers': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 20.14.11 + '@types/node': 22.5.4 jest-mock: 29.7.0 '@jest/expect-utils@29.7.0': @@ -5585,7 +5611,7 @@ snapshots: dependencies: '@jest/types': 29.6.3 '@sinonjs/fake-timers': 10.3.0 - '@types/node': 20.14.11 + '@types/node': 22.5.4 jest-message-util: 29.7.0 jest-mock: 29.7.0 jest-util: 29.7.0 @@ -5607,7 +5633,7 @@ snapshots: '@jest/transform': 29.7.0 '@jest/types': 29.6.3 '@jridgewell/trace-mapping': 0.3.25 - '@types/node': 20.14.11 + '@types/node': 22.5.4 chalk: 4.1.2 collect-v8-coverage: 1.0.2 exit: 0.1.2 @@ -5696,7 +5722,7 @@ snapshots: dependencies: '@types/istanbul-lib-coverage': 2.0.6 '@types/istanbul-reports': 3.0.4 - '@types/node': 20.14.11 + '@types/node': 22.5.4 '@types/yargs': 15.0.19 chalk: 4.1.2 @@ -5705,7 +5731,7 @@ snapshots: '@jest/schemas': 29.6.3 '@types/istanbul-lib-coverage': 2.0.6 '@types/istanbul-reports': 3.0.4 - '@types/node': 20.14.11 + '@types/node': 22.5.4 '@types/yargs': 17.0.32 chalk: 4.1.2 @@ -5773,6 +5799,10 @@ snapshots: '@nodelib/fs.scandir': 2.1.5 fastq: 1.17.1 + '@playwright/test@1.47.0': + dependencies: + playwright: 1.47.0 + '@react-aria/breadcrumbs@3.5.13(react@18.2.0)': dependencies: '@react-aria/i18n': 3.11.1(react@18.2.0) @@ -6526,7 +6556,7 @@ snapshots: '@types/graceful-fs@4.1.9': dependencies: - '@types/node': 20.14.11 + '@types/node': 22.5.4 '@types/hast@3.0.4': dependencies: @@ -6549,7 +6579,7 @@ snapshots: '@types/jsdom@20.0.1': dependencies: - '@types/node': 20.14.11 + '@types/node': 22.5.4 '@types/tough-cookie': 4.0.5 parse5: 7.1.2 @@ -6561,9 +6591,9 @@ snapshots: '@types/ms@0.7.34': {} - '@types/node@20.14.11': + '@types/node@22.5.4': dependencies: - undici-types: 5.26.5 + undici-types: 6.19.8 '@types/offscreencanvas@2019.7.3': {} @@ -6764,14 +6794,14 @@ snapshots: '@use-gesture/core': 10.3.1 react: 18.2.0 - '@vitejs/plugin-react@4.3.1(vite@5.3.3(@types/node@20.14.11))': + '@vitejs/plugin-react@4.3.1(vite@5.3.3(@types/node@22.5.4))': dependencies: '@babel/core': 7.24.9 '@babel/plugin-transform-react-jsx-self': 7.24.7(@babel/core@7.24.9) '@babel/plugin-transform-react-jsx-source': 7.24.7(@babel/core@7.24.9) '@types/babel__core': 7.20.5 react-refresh: 0.14.2 - vite: 5.3.3(@types/node@20.14.11) + vite: 5.3.3(@types/node@22.5.4) transitivePeerDependencies: - supports-color @@ -7270,13 +7300,13 @@ snapshots: p-filter: 3.0.0 p-map: 6.0.0 - create-jest@29.7.0(@types/node@20.14.11)(babel-plugin-macros@3.1.0): + create-jest@29.7.0(@types/node@22.5.4)(babel-plugin-macros@3.1.0): dependencies: '@jest/types': 29.6.3 chalk: 4.1.2 exit: 0.1.2 graceful-fs: 4.2.11 - jest-config: 29.7.0(@types/node@20.14.11)(babel-plugin-macros@3.1.0) + jest-config: 29.7.0(@types/node@22.5.4)(babel-plugin-macros@3.1.0) jest-util: 29.7.0 prompts: 2.4.2 transitivePeerDependencies: @@ -7947,6 +7977,9 @@ snapshots: fs.realpath@1.0.0: {} + fsevents@2.3.2: + optional: true + fsevents@2.3.3: optional: true @@ -8448,7 +8481,7 @@ snapshots: '@jest/expect': 29.7.0 '@jest/test-result': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 20.14.11 + '@types/node': 22.5.4 chalk: 4.1.2 co: 4.6.0 dedent: 1.5.3(babel-plugin-macros@3.1.0) @@ -8468,16 +8501,16 @@ snapshots: - babel-plugin-macros - supports-color - jest-cli@29.7.0(@types/node@20.14.11)(babel-plugin-macros@3.1.0): + jest-cli@29.7.0(@types/node@22.5.4)(babel-plugin-macros@3.1.0): dependencies: '@jest/core': 29.7.0(babel-plugin-macros@3.1.0) '@jest/test-result': 29.7.0 '@jest/types': 29.6.3 chalk: 4.1.2 - create-jest: 29.7.0(@types/node@20.14.11)(babel-plugin-macros@3.1.0) + create-jest: 29.7.0(@types/node@22.5.4)(babel-plugin-macros@3.1.0) exit: 0.1.2 import-local: 3.1.0 - jest-config: 29.7.0(@types/node@20.14.11)(babel-plugin-macros@3.1.0) + jest-config: 29.7.0(@types/node@22.5.4)(babel-plugin-macros@3.1.0) jest-util: 29.7.0 jest-validate: 29.7.0 yargs: 17.7.2 @@ -8487,7 +8520,7 @@ snapshots: - supports-color - ts-node - jest-config@29.7.0(@types/node@20.14.11)(babel-plugin-macros@3.1.0): + jest-config@29.7.0(@types/node@22.5.4)(babel-plugin-macros@3.1.0): dependencies: '@babel/core': 7.24.9 '@jest/test-sequencer': 29.7.0 @@ -8512,7 +8545,7 @@ snapshots: slash: 3.0.0 strip-json-comments: 3.1.1 optionalDependencies: - '@types/node': 20.14.11 + '@types/node': 22.5.4 transitivePeerDependencies: - babel-plugin-macros - supports-color @@ -8542,7 +8575,7 @@ snapshots: '@jest/fake-timers': 29.7.0 '@jest/types': 29.6.3 '@types/jsdom': 20.0.1 - '@types/node': 20.14.11 + '@types/node': 22.5.4 jest-mock: 29.7.0 jest-util: 29.7.0 jsdom: 20.0.3 @@ -8556,7 +8589,7 @@ snapshots: '@jest/environment': 29.7.0 '@jest/fake-timers': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 20.14.11 + '@types/node': 22.5.4 jest-mock: 29.7.0 jest-util: 29.7.0 @@ -8566,7 +8599,7 @@ snapshots: dependencies: '@jest/types': 26.6.2 '@types/graceful-fs': 4.1.9 - '@types/node': 20.14.11 + '@types/node': 22.5.4 anymatch: 3.1.3 fb-watchman: 2.0.2 graceful-fs: 4.2.11 @@ -8586,7 +8619,7 @@ snapshots: dependencies: '@jest/types': 29.6.3 '@types/graceful-fs': 4.1.9 - '@types/node': 20.14.11 + '@types/node': 22.5.4 anymatch: 3.1.3 fb-watchman: 2.0.2 graceful-fs: 4.2.11 @@ -8625,7 +8658,7 @@ snapshots: jest-mock@29.7.0: dependencies: '@jest/types': 29.6.3 - '@types/node': 20.14.11 + '@types/node': 22.5.4 jest-util: 29.7.0 jest-pnp-resolver@1.2.3(jest-resolve@29.7.0): @@ -8662,7 +8695,7 @@ snapshots: '@jest/test-result': 29.7.0 '@jest/transform': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 20.14.11 + '@types/node': 22.5.4 chalk: 4.1.2 emittery: 0.13.1 graceful-fs: 4.2.11 @@ -8690,7 +8723,7 @@ snapshots: '@jest/test-result': 29.7.0 '@jest/transform': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 20.14.11 + '@types/node': 22.5.4 chalk: 4.1.2 cjs-module-lexer: 1.3.1 collect-v8-coverage: 1.0.2 @@ -8710,7 +8743,7 @@ snapshots: jest-serializer@26.6.2: dependencies: - '@types/node': 20.14.11 + '@types/node': 22.5.4 graceful-fs: 4.2.11 jest-snapshot@29.7.0: @@ -8741,7 +8774,7 @@ snapshots: jest-util@26.6.2: dependencies: '@jest/types': 26.6.2 - '@types/node': 20.14.11 + '@types/node': 22.5.4 chalk: 4.1.2 graceful-fs: 4.2.11 is-ci: 2.0.0 @@ -8750,7 +8783,7 @@ snapshots: jest-util@29.7.0: dependencies: '@jest/types': 29.6.3 - '@types/node': 20.14.11 + '@types/node': 22.5.4 chalk: 4.1.2 ci-info: 3.9.0 graceful-fs: 4.2.11 @@ -8769,7 +8802,7 @@ snapshots: dependencies: '@jest/test-result': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 20.14.11 + '@types/node': 22.5.4 ansi-escapes: 4.3.2 chalk: 4.1.2 emittery: 0.13.1 @@ -8778,23 +8811,23 @@ snapshots: jest-worker@26.6.2: dependencies: - '@types/node': 20.14.11 + '@types/node': 22.5.4 merge-stream: 2.0.0 supports-color: 7.2.0 jest-worker@29.7.0: dependencies: - '@types/node': 20.14.11 + '@types/node': 22.5.4 jest-util: 29.7.0 merge-stream: 2.0.0 supports-color: 8.1.1 - jest@29.7.0(@types/node@20.14.11)(babel-plugin-macros@3.1.0): + jest@29.7.0(@types/node@22.5.4)(babel-plugin-macros@3.1.0): dependencies: '@jest/core': 29.7.0(babel-plugin-macros@3.1.0) '@jest/types': 29.6.3 import-local: 3.1.0 - jest-cli: 29.7.0(@types/node@20.14.11)(babel-plugin-macros@3.1.0) + jest-cli: 29.7.0(@types/node@22.5.4)(babel-plugin-macros@3.1.0) transitivePeerDependencies: - '@types/node' - babel-plugin-macros @@ -9572,6 +9605,14 @@ snapshots: dependencies: find-up: 4.1.0 + playwright-core@1.47.0: {} + + playwright@1.47.0: + dependencies: + playwright-core: 1.47.0 + optionalDependencies: + fsevents: 2.3.2 + polished@4.3.1: dependencies: '@babel/runtime': 7.24.8 @@ -10257,12 +10298,12 @@ snapshots: dependencies: typescript: 5.4.5 - ts-jest@29.2.2(@babel/core@7.24.9)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.24.9))(esbuild@0.23.0)(jest@29.7.0(@types/node@20.14.11)(babel-plugin-macros@3.1.0))(typescript@5.4.5): + ts-jest@29.2.2(@babel/core@7.24.9)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.24.9))(esbuild@0.23.0)(jest@29.7.0(@types/node@22.5.4)(babel-plugin-macros@3.1.0))(typescript@5.4.5): dependencies: bs-logger: 0.2.6 ejs: 3.1.10 fast-json-stable-stringify: 2.1.0 - jest: 29.7.0(@types/node@20.14.11)(babel-plugin-macros@3.1.0) + jest: 29.7.0(@types/node@22.5.4)(babel-plugin-macros@3.1.0) jest-util: 29.7.0 json5: 2.2.3 lodash.memoize: 4.1.2 @@ -10344,7 +10385,7 @@ snapshots: has-symbols: 1.0.3 which-boxed-primitive: 1.0.2 - undici-types@5.26.5: {} + undici-types@6.19.8: {} unified@11.0.5: dependencies: @@ -10469,21 +10510,21 @@ snapshots: d3-time: 3.1.0 d3-timer: 3.0.1 - vite-plugin-relay@2.1.0(babel-plugin-relay@17.0.0)(vite@5.3.3(@types/node@20.14.11)): + vite-plugin-relay@2.1.0(babel-plugin-relay@17.0.0)(vite@5.3.3(@types/node@22.5.4)): dependencies: '@babel/core': 7.24.9 babel-plugin-relay: 17.0.0 - vite: 5.3.3(@types/node@20.14.11) + vite: 5.3.3(@types/node@22.5.4) transitivePeerDependencies: - supports-color - vite@5.3.3(@types/node@20.14.11): + vite@5.3.3(@types/node@22.5.4): dependencies: esbuild: 0.21.5 postcss: 8.4.39 rollup: 4.18.1 optionalDependencies: - '@types/node': 20.14.11 + '@types/node': 22.5.4 fsevents: 2.3.3 w3c-keyname@2.2.8: {} diff --git a/app/tests/login.spec.ts b/app/tests/login.spec.ts new file mode 100644 index 0000000000..38dfc16bcd --- /dev/null +++ b/app/tests/login.spec.ts @@ -0,0 +1,10 @@ +import { expect, test } from "@playwright/test"; + +test("can log in", async ({ page }) => { + await page.goto("http://localhost:6006/login"); + + await page.getByLabel("Email").fill("admin@localhost"); + await page.getByLabel("Password").fill("admin"); + // Submit the form + await page.getByRole("button", { name: "Login" }).click(); +}); From 0d6ca3bb6c2cc9aad990f252993cd1e2c713fe60 Mon Sep 17 00:00:00 2001 From: Mikyo King Date: Wed, 11 Sep 2024 15:22:19 -0600 Subject: [PATCH 2/9] add test server --- app/package.json | 6 ++-- app/playwright.config.ts | 37 ++++++++++++------------ app/src/pages/auth/ResetPasswordForm.tsx | 2 +- app/tests/login.spec.ts | 10 ------- 4 files changed, 24 insertions(+), 31 deletions(-) delete mode 100644 app/tests/login.spec.ts diff --git a/app/package.json b/app/package.json index 7387748060..1148df97c8 100644 --- a/app/package.json +++ b/app/package.json @@ -90,12 +90,14 @@ "build:static": "cpy ./static ../src/phoenix/server", "build:relay": "relay-compiler", "test": "jest --config ./jest.config.js", - "test:e2e": "pnpm run dev:auth & playwright test --ui", + "test:e2e": "playwright test", + "test:e2e:ui": "playwright test --ui", "dev": "pnpm run dev:server & pnpm run build:static && pnpm run build:relay && vite", "dev:auth": "export PHOENIX_ENABLE_AUTH=true && export PHOENIX_SECRET=sa18f44bd9b6b4b0606e58a2d03d09039aee8283e0074c6517fda58577a07dd#A && pnpm run dev:server & pnpm run build:static && pnpm run build:relay && vite", "dev:ui": "pnpm run build:static && pnpm run build:relay && vite", - "dev:server:init": "python -m phoenix.server.main --dev serve --with-fixture=chatbot --with-project=demo_llama_index --force-fixture-ingestion", "dev:server": "python -m phoenix.server.main --dev serve", + "dev:server:test": "node ./tests/utils/testServer.mjs", + "dev:server:init": "python -m phoenix.server.main --dev serve --with-fixture=chatbot --with-project=demo_llama_index --force-fixture-ingestion", "typecheck": "tsc --noEmit", "lint": "eslint ./src", "prettier": "prettier --write './src/**/*'", diff --git a/app/playwright.config.ts b/app/playwright.config.ts index 4a501ea116..024fac7194 100644 --- a/app/playwright.config.ts +++ b/app/playwright.config.ts @@ -1,4 +1,4 @@ -import { defineConfig, devices } from '@playwright/test'; +import { defineConfig, devices } from "@playwright/test"; /** * Read environment variables from file. @@ -11,7 +11,7 @@ import { defineConfig, devices } from '@playwright/test'; * See https://playwright.dev/docs/test-configuration. */ export default defineConfig({ - testDir: './tests', + 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. */ @@ -21,33 +21,34 @@ export default defineConfig({ /* 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', + 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', + trace: "on-first-retry", }, /* Configure projects for major browsers */ projects: [ { - name: 'chromium', - use: { ...devices['Desktop Chrome'] }, + name: "setup", + testMatch: /global\.setup\.ts/, }, - { - name: 'firefox', - use: { ...devices['Desktop Firefox'] }, + name: "chromium", + use: { ...devices["Desktop Chrome"] }, }, - { - name: 'webkit', - use: { ...devices['Desktop Safari'] }, + name: "firefox", + use: { ...devices["Desktop Firefox"] }, + }, + { + name: "webkit", + use: { ...devices["Desktop Safari"] }, }, - /* Test against mobile viewports. */ // { // name: 'Mobile Chrome', @@ -70,9 +71,9 @@ export default defineConfig({ ], /* 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, - // }, + webServer: { + command: "pnpm run dev:server:test", + url: "http://localhost:6006", + reuseExistingServer: false, // !process.env.CI, + }, }); diff --git a/app/src/pages/auth/ResetPasswordForm.tsx b/app/src/pages/auth/ResetPasswordForm.tsx index 10e487eddf..39ef11dddf 100644 --- a/app/src/pages/auth/ResetPasswordForm.tsx +++ b/app/src/pages/auth/ResetPasswordForm.tsx @@ -106,7 +106,7 @@ export function ResetPasswordForm() { fieldState: { invalid, error }, }) => ( { - await page.goto("http://localhost:6006/login"); - - await page.getByLabel("Email").fill("admin@localhost"); - await page.getByLabel("Password").fill("admin"); - // Submit the form - await page.getByRole("button", { name: "Login" }).click(); -}); From d0e629b578ebe0d6f23f7bf34c6eb8a3b522a564 Mon Sep 17 00:00:00 2001 From: Mikyo King Date: Wed, 11 Sep 2024 15:24:23 -0600 Subject: [PATCH 3/9] add workflow --- app/.github/workflows/playwright.yml | 28 +++++++++++++++++++++++ app/tests/global.setup.ts | 16 +++++++++++++ app/tests/utils/testServer.mjs | 34 ++++++++++++++++++++++++++++ 3 files changed, 78 insertions(+) create mode 100644 app/.github/workflows/playwright.yml create mode 100644 app/tests/global.setup.ts create mode 100644 app/tests/utils/testServer.mjs diff --git a/app/.github/workflows/playwright.yml b/app/.github/workflows/playwright.yml new file mode 100644 index 0000000000..dbca3511ae --- /dev/null +++ b/app/.github/workflows/playwright.yml @@ -0,0 +1,28 @@ +# TODO(mikeldking): enable tests +name: Playwright Tests +on: + push: + branches: [] + pull_request: + branches: [] +jobs: + test: + timeout-minutes: 60 + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 + with: + node-version: lts/* + - name: Install dependencies + run: npm install -g pnpm && 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/app/tests/global.setup.ts b/app/tests/global.setup.ts new file mode 100644 index 0000000000..3fbacf702f --- /dev/null +++ b/app/tests/global.setup.ts @@ -0,0 +1,16 @@ +import { test } from "@playwright/test"; + +test("first time login expects reset password", async ({ page }) => { + await page.goto("http://localhost:6006/login"); + + await page.getByLabel("Email").fill("admin@localhost"); + await page.getByLabel("Password").fill("admin"); + await page.getByRole("button", { name: "Login" }).click(); + + // Reset the password + await page.waitForURL("**/reset-password"); + await page.getByLabel("Old Password").fill("admin"); + await page.getByLabel("New Password").fill("admin123"); + await page.getByLabel("Confirm Password").fill("admin123"); + await page.getByRole("button", { name: "Reset Password" }).click(); +}); diff --git a/app/tests/utils/testServer.mjs b/app/tests/utils/testServer.mjs new file mode 100644 index 0000000000..c9a59a57a4 --- /dev/null +++ b/app/tests/utils/testServer.mjs @@ -0,0 +1,34 @@ +//@ts-check +/* eslint-disable no-console */ +import { exec } from "child_process"; +import fs from "fs"; +import * as crypto from "node:crypto"; +import os from "os"; +import path from "path"; +import process from "process"; + +let tmpDir; +const appPrefix = "phoenix"; +try { + tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), appPrefix)); + + // the rest of your app goes here +} catch { + // handle error +} + +// Set environment variables for the server +process.env["PHOENIX_WORKING_DIR"] = tmpDir; +process.env["PHOENIX_ENABLE_AUTH"] = "True"; +process.env["PHOENIX_SECRET"] = crypto.randomBytes(32).toString("hex"); + +console.log("Phoenix test server starting..."); +console.log("PHOENIX_SECRET: ", process.env["PHOENIX_SECRET"]); +console.log("PHOENIX_WORKING_DIR: ", process.env["PHOENIX_WORKING_DIR"]); + +// Execute the server +// TODO: Might have to force install the phoenix server +const childProcess = exec("python -m phoenix.server.main serve"); + +childProcess.stdout.pipe(process.stdout); +childProcess.stderr.pipe(process.stderr); From 6e35afd1e4574957ea5e7fcbbc55de6928a7a89a Mon Sep 17 00:00:00 2001 From: Mikyo King Date: Wed, 11 Sep 2024 15:27:27 -0600 Subject: [PATCH 4/9] update server --- app/tests/utils/testServer.mjs | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/app/tests/utils/testServer.mjs b/app/tests/utils/testServer.mjs index c9a59a57a4..ff0daf099c 100644 --- a/app/tests/utils/testServer.mjs +++ b/app/tests/utils/testServer.mjs @@ -7,15 +7,8 @@ import os from "os"; import path from "path"; import process from "process"; -let tmpDir; const appPrefix = "phoenix"; -try { - tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), appPrefix)); - - // the rest of your app goes here -} catch { - // handle error -} +const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), appPrefix)); // Set environment variables for the server process.env["PHOENIX_WORKING_DIR"] = tmpDir; From 4a111af23aee109e519095dade26bfb7e8b30aeb Mon Sep 17 00:00:00 2001 From: Mikyo King Date: Wed, 11 Sep 2024 17:26:18 -0600 Subject: [PATCH 5/9] test workflow --- .github/workflows/playwright.yaml | 41 +++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 .github/workflows/playwright.yaml diff --git a/.github/workflows/playwright.yaml b/.github/workflows/playwright.yaml new file mode 100644 index 0000000000..2aeab8074c --- /dev/null +++ b/.github/workflows/playwright.yaml @@ -0,0 +1,41 @@ +name: Playwright Tests + +env: + pip-version: 24.2 + +on: + push: + branches: [] + pull_request: + branches: [auth] +jobs: + test: + timeout-minutes: 60 + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-python@v5 + with: + python-version: 3.12 + - name: Install dependencies + run: | + python -m pip install --upgrade pip==${{ env.pip-version }} + pip install . + - uses: actions/setup-node@v4 + with: + node-version: lts/* + - name: Install dependencies + working-directory: ./app + run: npm install -g pnpm && pnpm install + - name: Install Playwright Browsers + working-directory: ./app + run: pnpm exec playwright install --with-deps + - name: Run Playwright tests + working-directory: ./app + run: pnpm exec playwright test + - uses: actions/upload-artifact@v4 + if: always() + with: + name: playwright-report + path: app/playwright-report/ + retention-days: 30 From 0d2faf84bf356549305418c57754f5c40be82e72 Mon Sep 17 00:00:00 2001 From: Mikyo King Date: Wed, 11 Sep 2024 17:28:45 -0600 Subject: [PATCH 6/9] playwright workflow --- .github/workflows/playwright.yaml | 4 ++-- app/.github/workflows/playwright.yml | 28 ---------------------------- 2 files changed, 2 insertions(+), 30 deletions(-) delete mode 100644 app/.github/workflows/playwright.yml diff --git a/.github/workflows/playwright.yaml b/.github/workflows/playwright.yaml index 2aeab8074c..b673b54df2 100644 --- a/.github/workflows/playwright.yaml +++ b/.github/workflows/playwright.yaml @@ -4,8 +4,8 @@ env: pip-version: 24.2 on: - push: - branches: [] + # push: + # branches: [] pull_request: branches: [auth] jobs: diff --git a/app/.github/workflows/playwright.yml b/app/.github/workflows/playwright.yml deleted file mode 100644 index dbca3511ae..0000000000 --- a/app/.github/workflows/playwright.yml +++ /dev/null @@ -1,28 +0,0 @@ -# TODO(mikeldking): enable tests -name: Playwright Tests -on: - push: - branches: [] - pull_request: - branches: [] -jobs: - test: - timeout-minutes: 60 - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - uses: actions/setup-node@v4 - with: - node-version: lts/* - - name: Install dependencies - run: npm install -g pnpm && 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 From 679c26a6dbe7abfd3a415412ed313018f82da2f4 Mon Sep 17 00:00:00 2001 From: Mikyo King Date: Wed, 11 Sep 2024 17:42:33 -0600 Subject: [PATCH 7/9] playwright workflow --- .github/workflows/playwright.yaml | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/.github/workflows/playwright.yaml b/.github/workflows/playwright.yaml index b673b54df2..62a943947c 100644 --- a/.github/workflows/playwright.yaml +++ b/.github/workflows/playwright.yaml @@ -14,13 +14,6 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - - uses: actions/setup-python@v5 - with: - python-version: 3.12 - - name: Install dependencies - run: | - python -m pip install --upgrade pip==${{ env.pip-version }} - pip install . - uses: actions/setup-node@v4 with: node-version: lts/* @@ -30,6 +23,16 @@ jobs: - name: Install Playwright Browsers working-directory: ./app run: pnpm exec playwright install --with-deps + - name: Build the app + working-directory: ./app + run: pnpm run build + - uses: actions/setup-python@v5 + with: + python-version: 3.12 + - name: Install Phoenix + run: | + python -m pip install --upgrade pip==${{ env.pip-version }} + pip install . - name: Run Playwright tests working-directory: ./app run: pnpm exec playwright test From 03f6ca6b7bb2986b409df2305c3662a0a38ffc9c Mon Sep 17 00:00:00 2001 From: Mikyo King Date: Wed, 11 Sep 2024 19:50:28 -0600 Subject: [PATCH 8/9] WIP --- app/playwright.config.ts | 2 +- app/tests/global.setup.ts | 25 +++++++++++++++++++++++++ 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/app/playwright.config.ts b/app/playwright.config.ts index 024fac7194..2aeb43d25e 100644 --- a/app/playwright.config.ts +++ b/app/playwright.config.ts @@ -25,7 +25,7 @@ export default defineConfig({ /* 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', + baseURL: "http://localhost:6006", /* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */ trace: "on-first-retry", diff --git a/app/tests/global.setup.ts b/app/tests/global.setup.ts index 3fbacf702f..727e4f852f 100644 --- a/app/tests/global.setup.ts +++ b/app/tests/global.setup.ts @@ -1,5 +1,7 @@ import { test } from "@playwright/test"; +test.describe.configure({ mode: "serial" }); + test("first time login expects reset password", async ({ page }) => { await page.goto("http://localhost:6006/login"); @@ -14,3 +16,26 @@ test("first time login expects reset password", async ({ page }) => { await page.getByLabel("Confirm Password").fill("admin123"); await page.getByRole("button", { name: "Reset Password" }).click(); }); + +test("create a member", async ({ page }) => { + await page.goto("http://localhost:6006/login"); + + await page.getByLabel("Email").fill("admin@localhost"); + await page.getByLabel("Password").fill("admin123"); + await page.getByRole("button", { name: "Login" }).click(); + await page.waitForURL("**/projects/**"); + // Reset the password + await page.goto("/settings"); + await page.waitForURL("**/settings"); + await page.getByRole("button", { name: "Add User" }).click(); + + // Add the user + await page.getByLabel("Email").fill("member@localhost.com"); + await page.getByLabel("Password").fill("member123"); + await page.getByLabel("member", { exact: true }).click(); + await page.getByRole("option", { name: "member" }).click(); + await page + .getByRole("dialog") + .getByRole("button", { name: "Add User" }) + .click(); +}); From f4612638330277777d039ab4ebab45a02ae8800b Mon Sep 17 00:00:00 2001 From: Mikyo King Date: Wed, 11 Sep 2024 19:51:48 -0600 Subject: [PATCH 9/9] WIP --- .github/workflows/playwright.yaml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/playwright.yaml b/.github/workflows/playwright.yaml index 62a943947c..cd6e2e7742 100644 --- a/.github/workflows/playwright.yaml +++ b/.github/workflows/playwright.yaml @@ -4,10 +4,10 @@ env: pip-version: 24.2 on: - # push: - # branches: [] + push: + branches: [auth, main] pull_request: - branches: [auth] + branches: [auth, main] jobs: test: timeout-minutes: 60