diff --git a/.github/workflows/container-ecr-viewer.yaml b/.github/workflows/container-ecr-viewer.yaml index 5361e75a8..f23139a13 100644 --- a/.github/workflows/container-ecr-viewer.yaml +++ b/.github/workflows/container-ecr-viewer.yaml @@ -50,52 +50,43 @@ jobs: - name: Run tests working-directory: ./containers/${{env.CONTAINER}} # Navigate to your Node.js app directory run: npm test - cypress-e2e-tests: - if: false + e2e-test: runs-on: ubuntu-latest - timeout-minutes: 20 + timeout-minutes: 45 steps: - name: Checkout code uses: actions/checkout@v4 + - name: Set up Node.js uses: actions/setup-node@v4 with: node-version: ${{env.NODE_VERSION}} + - name: Install dependencies working-directory: ./containers/${{env.CONTAINER}} # Navigate to your Node.js app directory - run: npm install + run: npm ci - - name: Start ${{env.CONTAINER}} - working-directory: ./containers/${{env.CONTAINER}}/cypress - run: docker compose --env-file ../.env.test up -d + - name: Install Playwright Browsers + run: npx playwright install --with-deps - - name: Run cypress tests + - name: Set up env vars + run: npm run setup-local-env working-directory: ./containers/${{env.CONTAINER}} - run: npm run cypress:run - - name: Archive cypress failures - if: always() - uses: actions/upload-artifact@v4 - with: - name: cypress-results - path: | - containers/ecr-viewer/cypress/screenshots/* - containers/ecr-viewer/cypress/videos/* - - - name: Get docker logs - if: always() - working-directory: ./containers/${{env.CONTAINER}}/cypress - shell: bash - run: | - echo "Saving $container logs" - docker compose logs --timestamps >& cypress-run.log + - name: Run seed data conversion + run: npm run convert-seed-data:build + working-directory: ./containers/${{env.CONTAINER}} + + - name: Run Playwright tests + working-directory: ./containers/${{env.CONTAINER}} + run: npx @dotenvx/dotenvx run -f .env.local -- sh -c 'docker compose -f ./e2e/docker-compose.yml --profile ${SOURCE} --profile ${METADATA_DATABASE_TYPE} --profile ecr-viewer up' - - name: Archive docker logs - if: always() - uses: actions/upload-artifact@v4 + - uses: actions/upload-artifact@v4 + if: ${{ !cancelled() }} with: - name: logs - path: ./containers/${{env.CONTAINER}}/cypress/cypress-run.log + name: playwright-report + path: containers/${{env.CONTAINER}}/playwright-report/ + retention-days: 30 lighthouse: runs-on: ubuntu-latest diff --git a/containers/ecr-viewer/.dockerignore b/containers/ecr-viewer/.dockerignore new file mode 100644 index 000000000..a92149159 --- /dev/null +++ b/containers/ecr-viewer/.dockerignore @@ -0,0 +1,5 @@ +node_modules +Dockerfile +.dockerignore +e2e +.next \ No newline at end of file diff --git a/containers/ecr-viewer/.gitignore b/containers/ecr-viewer/.gitignore index 61a036c11..cdc0c98e0 100644 --- a/containers/ecr-viewer/.gitignore +++ b/containers/ecr-viewer/.gitignore @@ -9,4 +9,8 @@ seed-scripts/baseECR/KY seed-scripts/baseECR/ME cypress/screenshots -cypress/videos \ No newline at end of file +cypress/videos +/test-results/ +/playwright-report/ +/blob-report/ +/playwright/.cache/ diff --git a/containers/ecr-viewer/e2e/docker-compose.yml b/containers/ecr-viewer/e2e/docker-compose.yml new file mode 100644 index 000000000..44aa1632c --- /dev/null +++ b/containers/ecr-viewer/e2e/docker-compose.yml @@ -0,0 +1,17 @@ +name: ecr-viewer + +include: + - ../docker-compose.yml + +services: + playwright: + image: mcr.microsoft.com/playwright:v1.49.0-noble + working_dir: /work/ + command: + - /bin/sh + - -c + - | + npm i + npm run test:e2e + volumes: + - ../:/work/ diff --git a/containers/ecr-viewer/e2e/ecrLibrary.spec.ts b/containers/ecr-viewer/e2e/ecrLibrary.spec.ts new file mode 100644 index 000000000..01cb72b02 --- /dev/null +++ b/containers/ecr-viewer/e2e/ecrLibrary.spec.ts @@ -0,0 +1,22 @@ +import { test, expect } from "@playwright/test"; + +// http://host.docker.internal:3000/ +// const E2E_URL = "http://localhost:3000/ecr-viewer"; +const E2E_URL = "http://ecr-viewer:3000/ecr-viewer"; + +test("eCRs per page should persist on reload ", async ({ page }) => { + await page.goto(E2E_URL); + await page.getByTestId("Select").selectOption("75"); + await page.reload(); + await expect(page.getByTestId("Select")).toContainText("75"); +}); + +test("eCR search filters results", async ({ page }) => { + await page.goto(E2E_URL); + await page.getByTestId("textInput").click(); + await page.getByTestId("textInput").fill("test"); + await page.getByTestId("form").getByTestId("button").click(); + await expect( + page.getByRole("cell", { name: "Adam Test DOB: 01/01/" }).first(), + ).toBeVisible(); +}); diff --git a/containers/ecr-viewer/e2e/ecrViewer.spec.ts b/containers/ecr-viewer/e2e/ecrViewer.spec.ts new file mode 100644 index 000000000..0771d99fa --- /dev/null +++ b/containers/ecr-viewer/e2e/ecrViewer.spec.ts @@ -0,0 +1,24 @@ +import { test, expect } from "@playwright/test"; + +// host.docker.internal +// const E2E_URL = "http://localhost:3000/ecr-viewer"; +const E2E_URL = "http://ecr-viewer:3000/ecr-viewer"; + +test("eCR Viewer matches snapshot", async ({ page }) => { + await page.goto( + `${E2E_URL}/view-data?id=1.2.840.114350.1.13.297.3.7.8.688883.573942`, + ); + await page.getByText("Patient Name").first().waitFor(); + await expect(page).toHaveScreenshot({ fullPage: true }); +}); + +test("eCR Viewer matches snapshot fully expanded", async ({ page }) => { + await page.goto( + `${E2E_URL}/view-data?id=1.2.840.114350.1.13.297.3.7.8.688883.573942`, + ); + await page.getByTestId("accordionButton_Giardiasis").click(); + await page.getByTestId("accordionButton_Cryptosporidiosis").click(); + await page.getByTestId("accordionButton_Amebiasis").click(); + await page.getByRole("button", { name: "Expand all labs" }).click(); + await expect(page).toHaveScreenshot({ fullPage: true }); +}); diff --git a/containers/ecr-viewer/e2e/ecrViewer.spec.ts-snapshots/eCR-Viewer-matches-snapshot-1-chromium-darwin.png b/containers/ecr-viewer/e2e/ecrViewer.spec.ts-snapshots/eCR-Viewer-matches-snapshot-1-chromium-darwin.png new file mode 100644 index 000000000..87ed3e63f Binary files /dev/null and b/containers/ecr-viewer/e2e/ecrViewer.spec.ts-snapshots/eCR-Viewer-matches-snapshot-1-chromium-darwin.png differ diff --git a/containers/ecr-viewer/e2e/ecrViewer.spec.ts-snapshots/eCR-Viewer-matches-snapshot-1-chromium-linux.png b/containers/ecr-viewer/e2e/ecrViewer.spec.ts-snapshots/eCR-Viewer-matches-snapshot-1-chromium-linux.png new file mode 100644 index 000000000..bb5481340 Binary files /dev/null and b/containers/ecr-viewer/e2e/ecrViewer.spec.ts-snapshots/eCR-Viewer-matches-snapshot-1-chromium-linux.png differ diff --git a/containers/ecr-viewer/e2e/ecrViewer.spec.ts-snapshots/eCR-Viewer-matches-snapshot-1-firefox-darwin.png b/containers/ecr-viewer/e2e/ecrViewer.spec.ts-snapshots/eCR-Viewer-matches-snapshot-1-firefox-darwin.png new file mode 100644 index 000000000..108e90d17 Binary files /dev/null and b/containers/ecr-viewer/e2e/ecrViewer.spec.ts-snapshots/eCR-Viewer-matches-snapshot-1-firefox-darwin.png differ diff --git a/containers/ecr-viewer/e2e/ecrViewer.spec.ts-snapshots/eCR-Viewer-matches-snapshot-1-firefox-linux.png b/containers/ecr-viewer/e2e/ecrViewer.spec.ts-snapshots/eCR-Viewer-matches-snapshot-1-firefox-linux.png new file mode 100644 index 000000000..3f5074de0 Binary files /dev/null and b/containers/ecr-viewer/e2e/ecrViewer.spec.ts-snapshots/eCR-Viewer-matches-snapshot-1-firefox-linux.png differ diff --git a/containers/ecr-viewer/e2e/ecrViewer.spec.ts-snapshots/eCR-Viewer-matches-snapshot-1-webkit-darwin.png b/containers/ecr-viewer/e2e/ecrViewer.spec.ts-snapshots/eCR-Viewer-matches-snapshot-1-webkit-darwin.png new file mode 100644 index 000000000..e637e5ffd Binary files /dev/null and b/containers/ecr-viewer/e2e/ecrViewer.spec.ts-snapshots/eCR-Viewer-matches-snapshot-1-webkit-darwin.png differ diff --git a/containers/ecr-viewer/e2e/ecrViewer.spec.ts-snapshots/eCR-Viewer-matches-snapshot-1-webkit-linux.png b/containers/ecr-viewer/e2e/ecrViewer.spec.ts-snapshots/eCR-Viewer-matches-snapshot-1-webkit-linux.png new file mode 100644 index 000000000..f6d620262 Binary files /dev/null and b/containers/ecr-viewer/e2e/ecrViewer.spec.ts-snapshots/eCR-Viewer-matches-snapshot-1-webkit-linux.png differ diff --git a/containers/ecr-viewer/e2e/ecrViewer.spec.ts-snapshots/eCR-Viewer-matches-snapshot-fully-expanded-1-chromium-darwin.png b/containers/ecr-viewer/e2e/ecrViewer.spec.ts-snapshots/eCR-Viewer-matches-snapshot-fully-expanded-1-chromium-darwin.png new file mode 100644 index 000000000..96e69766c Binary files /dev/null and b/containers/ecr-viewer/e2e/ecrViewer.spec.ts-snapshots/eCR-Viewer-matches-snapshot-fully-expanded-1-chromium-darwin.png differ diff --git a/containers/ecr-viewer/e2e/ecrViewer.spec.ts-snapshots/eCR-Viewer-matches-snapshot-fully-expanded-1-chromium-linux.png b/containers/ecr-viewer/e2e/ecrViewer.spec.ts-snapshots/eCR-Viewer-matches-snapshot-fully-expanded-1-chromium-linux.png new file mode 100644 index 000000000..c689ee4ed Binary files /dev/null and b/containers/ecr-viewer/e2e/ecrViewer.spec.ts-snapshots/eCR-Viewer-matches-snapshot-fully-expanded-1-chromium-linux.png differ diff --git a/containers/ecr-viewer/e2e/ecrViewer.spec.ts-snapshots/eCR-Viewer-matches-snapshot-fully-expanded-1-firefox-darwin.png b/containers/ecr-viewer/e2e/ecrViewer.spec.ts-snapshots/eCR-Viewer-matches-snapshot-fully-expanded-1-firefox-darwin.png new file mode 100644 index 000000000..27282c063 Binary files /dev/null and b/containers/ecr-viewer/e2e/ecrViewer.spec.ts-snapshots/eCR-Viewer-matches-snapshot-fully-expanded-1-firefox-darwin.png differ diff --git a/containers/ecr-viewer/e2e/ecrViewer.spec.ts-snapshots/eCR-Viewer-matches-snapshot-fully-expanded-1-firefox-linux.png b/containers/ecr-viewer/e2e/ecrViewer.spec.ts-snapshots/eCR-Viewer-matches-snapshot-fully-expanded-1-firefox-linux.png new file mode 100644 index 000000000..fb2f8bee0 Binary files /dev/null and b/containers/ecr-viewer/e2e/ecrViewer.spec.ts-snapshots/eCR-Viewer-matches-snapshot-fully-expanded-1-firefox-linux.png differ diff --git a/containers/ecr-viewer/e2e/ecrViewer.spec.ts-snapshots/eCR-Viewer-matches-snapshot-fully-expanded-1-webkit-darwin.png b/containers/ecr-viewer/e2e/ecrViewer.spec.ts-snapshots/eCR-Viewer-matches-snapshot-fully-expanded-1-webkit-darwin.png new file mode 100644 index 000000000..f4ab61de1 Binary files /dev/null and b/containers/ecr-viewer/e2e/ecrViewer.spec.ts-snapshots/eCR-Viewer-matches-snapshot-fully-expanded-1-webkit-darwin.png differ diff --git a/containers/ecr-viewer/e2e/ecrViewer.spec.ts-snapshots/eCR-Viewer-matches-snapshot-fully-expanded-1-webkit-linux.png b/containers/ecr-viewer/e2e/ecrViewer.spec.ts-snapshots/eCR-Viewer-matches-snapshot-fully-expanded-1-webkit-linux.png new file mode 100644 index 000000000..6dc5fb188 Binary files /dev/null and b/containers/ecr-viewer/e2e/ecrViewer.spec.ts-snapshots/eCR-Viewer-matches-snapshot-fully-expanded-1-webkit-linux.png differ diff --git a/containers/ecr-viewer/jest.config.js b/containers/ecr-viewer/jest.config.js index ab9102221..1a1883d29 100644 --- a/containers/ecr-viewer/jest.config.js +++ b/containers/ecr-viewer/jest.config.js @@ -8,6 +8,7 @@ const createJestConfig = nextJest({ // Add any custom config to be passed to Jest const customJestConfig = { setupFilesAfterEnv: ["/jest.setup.ts"], + testPathIgnorePatterns: ["/e2e/"], testEnvironment: "jest-environment-jsdom", }; diff --git a/containers/ecr-viewer/package-lock.json b/containers/ecr-viewer/package-lock.json index 3cb42043f..7569168f5 100644 --- a/containers/ecr-viewer/package-lock.json +++ b/containers/ecr-viewer/package-lock.json @@ -52,6 +52,7 @@ "devDependencies": { "@dotenvx/dotenvx": "^1.22.0", "@next/eslint-plugin-next": "^14.2.5", + "@playwright/test": "^1.49.0", "@smithy/util-stream": "^2.1.2", "@testing-library/jest-dom": "^6.1.5", "@testing-library/react": "^15.0.7", @@ -4413,6 +4414,22 @@ "url": "https://opencollective.com/unts" } }, + "node_modules/@playwright/test": { + "version": "1.49.0", + "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.49.0.tgz", + "integrity": "sha512-DMulbwQURa8rNIQrf94+jPJQ4FmOVdpE5ZppRNvWVjvhC+6sOeo28r8MgIpQRYouXRtt/FCCXU7zn20jnHR4Qw==", + "devOptional": true, + "license": "Apache-2.0", + "dependencies": { + "playwright": "1.49.0" + }, + "bin": { + "playwright": "cli.js" + }, + "engines": { + "node": ">=18" + } + }, "node_modules/@protobufjs/aspromise": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz", @@ -13656,6 +13673,53 @@ "node": ">=8" } }, + "node_modules/playwright": { + "version": "1.49.0", + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.49.0.tgz", + "integrity": "sha512-eKpmys0UFDnfNb3vfsf8Vx2LEOtflgRebl0Im2eQQnYMA4Aqd+Zw8bEOB+7ZKvN76901mRnqdsiOGKxzVTbi7A==", + "devOptional": true, + "license": "Apache-2.0", + "dependencies": { + "playwright-core": "1.49.0" + }, + "bin": { + "playwright": "cli.js" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "fsevents": "2.3.2" + } + }, + "node_modules/playwright-core": { + "version": "1.49.0", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.49.0.tgz", + "integrity": "sha512-R+3KKTQF3npy5GTiKH/T+kdhoJfJojjHESR1YEWhYuEKRVfVaxH3+4+GvXE5xyCngCxhxnykk0Vlah9v8fs3jA==", + "devOptional": true, + "license": "Apache-2.0", + "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==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, "node_modules/possible-typed-array-names": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz", diff --git a/containers/ecr-viewer/package.json b/containers/ecr-viewer/package.json index 54c4d1977..70211d254 100644 --- a/containers/ecr-viewer/package.json +++ b/containers/ecr-viewer/package.json @@ -13,6 +13,9 @@ "lint": "next lint", "test": "TZ=America/New_York jest", "test:watch": "TZ=America/New_York jest --watch", + "test:e2e": "playwright test", + "test:e2e:record": "playwright codegen localhost:3000/ecr-viewer", + "test:e2e:update-snapshots": "playwright test --update-snapshots", "clear-local": "docker compose -f ./docker-compose.yml --profile \"*\" down -v", "convert-seed-data": "npx @dotenvx/dotenvx run -f .env.local -- sh -c 'docker compose -f ./seed-scripts/docker-compose-seed.yml --profile ${SOURCE} --profile ${METADATA_DATABASE_TYPE} --profile ecr-viewer up --abort-on-container-exit'", "convert-seed-data:build": "npx @dotenvx/dotenvx run -f .env.local -- sh -c 'docker compose -f ./seed-scripts/docker-compose-seed.yml --profile ${SOURCE} --profile ${METADATA_DATABASE_TYPE} --profile ecr-viewer up --abort-on-container-exit --build'", @@ -67,6 +70,7 @@ "devDependencies": { "@dotenvx/dotenvx": "^1.22.0", "@next/eslint-plugin-next": "^14.2.5", + "@playwright/test": "^1.49.0", "@smithy/util-stream": "^2.1.2", "@testing-library/jest-dom": "^6.1.5", "@testing-library/react": "^15.0.7", diff --git a/containers/ecr-viewer/playwright.config.ts b/containers/ecr-viewer/playwright.config.ts new file mode 100644 index 000000000..a18a99f17 --- /dev/null +++ b/containers/ecr-viewer/playwright.config.ts @@ -0,0 +1,84 @@ +import { defineConfig, devices } from "@playwright/test"; + +/** + * Read environment variables from file. + * https://github.com/motdotla/dotenv + */ +// import dotenv from 'dotenv'; +// import path from 'path'; +// dotenv.config({ path: path.resolve(__dirname, '.env') }); + +// http://host.docker.internal:3000/ +// const E2E_URL = "http://localhost:3000/ecr-viewer"; +const E2E_URL = "http://ecr-viewer:3000/ecr-viewer"; + +/** + * See https://playwright.dev/docs/test-configuration. + */ +export default defineConfig({ + testDir: "./e2e", + /* 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 build && npm run start", + url: E2E_URL, + reuseExistingServer: true, + timeout: 120000, + }, +}); diff --git a/containers/ecr-viewer/src/app/Header.tsx b/containers/ecr-viewer/src/app/Header.tsx index 73b9614af..ec84b1af2 100644 --- a/containers/ecr-viewer/src/app/Header.tsx +++ b/containers/ecr-viewer/src/app/Header.tsx @@ -1,3 +1,4 @@ +import Link from "next/link"; import React from "react"; /** @@ -13,9 +14,7 @@ const Header: React.FC = () => (

- - DIBBs eCR Viewer - + DIBBs eCR Viewer