From 9c64eef5159eb27e46bc4dedbb9a8408bdace00e Mon Sep 17 00:00:00 2001 From: elysableu Date: Thu, 4 Dec 2025 22:30:14 -0700 Subject: [PATCH 1/4] Rename userHome to Profile and updated in imports --- .../{userHome => profile}/components/CharacterRoster.test.tsx | 0 src/app/{userHome => profile}/components/CharacterRoster.tsx | 0 .../components/CharacterRosterCard.test.tsx | 0 .../{userHome => profile}/components/CharacterRosterCard.tsx | 0 src/app/{userHome => profile}/components/ProfileDetails.tsx | 0 src/app/{userHome => profile}/page.tsx | 0 src/components/layout/Header/header.tsx | 2 +- 7 files changed, 1 insertion(+), 1 deletion(-) rename src/app/{userHome => profile}/components/CharacterRoster.test.tsx (100%) rename src/app/{userHome => profile}/components/CharacterRoster.tsx (100%) rename src/app/{userHome => profile}/components/CharacterRosterCard.test.tsx (100%) rename src/app/{userHome => profile}/components/CharacterRosterCard.tsx (100%) rename src/app/{userHome => profile}/components/ProfileDetails.tsx (100%) rename src/app/{userHome => profile}/page.tsx (100%) diff --git a/src/app/userHome/components/CharacterRoster.test.tsx b/src/app/profile/components/CharacterRoster.test.tsx similarity index 100% rename from src/app/userHome/components/CharacterRoster.test.tsx rename to src/app/profile/components/CharacterRoster.test.tsx diff --git a/src/app/userHome/components/CharacterRoster.tsx b/src/app/profile/components/CharacterRoster.tsx similarity index 100% rename from src/app/userHome/components/CharacterRoster.tsx rename to src/app/profile/components/CharacterRoster.tsx diff --git a/src/app/userHome/components/CharacterRosterCard.test.tsx b/src/app/profile/components/CharacterRosterCard.test.tsx similarity index 100% rename from src/app/userHome/components/CharacterRosterCard.test.tsx rename to src/app/profile/components/CharacterRosterCard.test.tsx diff --git a/src/app/userHome/components/CharacterRosterCard.tsx b/src/app/profile/components/CharacterRosterCard.tsx similarity index 100% rename from src/app/userHome/components/CharacterRosterCard.tsx rename to src/app/profile/components/CharacterRosterCard.tsx diff --git a/src/app/userHome/components/ProfileDetails.tsx b/src/app/profile/components/ProfileDetails.tsx similarity index 100% rename from src/app/userHome/components/ProfileDetails.tsx rename to src/app/profile/components/ProfileDetails.tsx diff --git a/src/app/userHome/page.tsx b/src/app/profile/page.tsx similarity index 100% rename from src/app/userHome/page.tsx rename to src/app/profile/page.tsx diff --git a/src/components/layout/Header/header.tsx b/src/components/layout/Header/header.tsx index 27db17e..7150f90 100644 --- a/src/components/layout/Header/header.tsx +++ b/src/components/layout/Header/header.tsx @@ -17,7 +17,7 @@ export default function Header() { About
  • - Profile + Profile
  • Create From 853c8491bf73ff47a7574be06565fd9c7d316061 Mon Sep 17 00:00:00 2001 From: elysableu Date: Thu, 4 Dec 2025 22:31:29 -0700 Subject: [PATCH 2/4] Add playwright to project for e2e testing --- .github/workflows/playwright.yml | 27 +++++++++++ .gitignore | 10 +++- e2e/example.spec.ts | 18 ++++++++ package-lock.json | 64 ++++++++++++++++++++++++++ package.json | 1 + playwright.config.ts | 79 ++++++++++++++++++++++++++++++++ 6 files changed, 198 insertions(+), 1 deletion(-) create mode 100644 .github/workflows/playwright.yml create mode 100644 e2e/example.spec.ts create mode 100644 playwright.config.ts diff --git a/.github/workflows/playwright.yml b/.github/workflows/playwright.yml new file mode 100644 index 0000000..3eb1314 --- /dev/null +++ b/.github/workflows/playwright.yml @@ -0,0 +1,27 @@ +name: Playwright Tests +on: + push: + branches: [ main, master ] + pull_request: + branches: [ main, master ] +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 ci + - name: Install Playwright Browsers + run: npx playwright install --with-deps + - name: Run Playwright tests + run: npx 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 5d9bd8d..9a750cb 100644 --- a/.gitignore +++ b/.gitignore @@ -43,4 +43,12 @@ next-env.d.ts # jest testing coverage/ .jest-cache/ -__snapshots__/ \ No newline at end of file +__snapshots__/ + +# Playwright +node_modules/ +/test-results/ +/playwright-report/ +/blob-report/ +/playwright/.cache/ +/playwright/.auth/ diff --git a/e2e/example.spec.ts b/e2e/example.spec.ts new file mode 100644 index 0000000..54a906a --- /dev/null +++ b/e2e/example.spec.ts @@ -0,0 +1,18 @@ +import { test, expect } from '@playwright/test'; + +test('has title', async ({ page }) => { + await page.goto('https://playwright.dev/'); + + // Expect a title "to contain" a substring. + await expect(page).toHaveTitle(/Playwright/); +}); + +test('get started link', async ({ page }) => { + await page.goto('https://playwright.dev/'); + + // Click the get started link. + await page.getByRole('link', { name: 'Get started' }).click(); + + // Expects page to have a heading with the name of Installation. + await expect(page.getByRole('heading', { name: 'Installation' })).toBeVisible(); +}); diff --git a/package-lock.json b/package-lock.json index 6502bf5..0768551 100644 --- a/package-lock.json +++ b/package-lock.json @@ -15,6 +15,7 @@ "devDependencies": { "@eslint/eslintrc": "^3.3.1", "@eslint/js": "^9.39.1", + "@playwright/test": "^1.57.0", "@tailwindcss/postcss": "^4", "@testing-library/dom": "^10.4.1", "@testing-library/jest-dom": "^6.9.1", @@ -2540,6 +2541,22 @@ "node": ">=12.4.0" } }, + "node_modules/@playwright/test": { + "version": "1.57.0", + "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.57.0.tgz", + "integrity": "sha512-6TyEnHgd6SArQO8UO2OMTxshln3QMWBtPGrOCgs3wVEmQmwyuNtB10IZMfmYDE0riwNR1cu4q+pPcxMVtaG3TA==", + "devOptional": true, + "license": "Apache-2.0", + "dependencies": { + "playwright": "1.57.0" + }, + "bin": { + "playwright": "cli.js" + }, + "engines": { + "node": ">=18" + } + }, "node_modules/@rtsao/scc": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@rtsao/scc/-/scc-1.1.0.tgz", @@ -10036,6 +10053,53 @@ "node": ">=8" } }, + "node_modules/playwright": { + "version": "1.57.0", + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.57.0.tgz", + "integrity": "sha512-ilYQj1s8sr2ppEJ2YVadYBN0Mb3mdo9J0wQ+UuDhzYqURwSoW4n1Xs5vs7ORwgDGmyEh33tRMeS8KhdkMoLXQw==", + "devOptional": true, + "license": "Apache-2.0", + "dependencies": { + "playwright-core": "1.57.0" + }, + "bin": { + "playwright": "cli.js" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "fsevents": "2.3.2" + } + }, + "node_modules/playwright-core": { + "version": "1.57.0", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.57.0.tgz", + "integrity": "sha512-agTcKlMw/mjBWOnD6kFZttAAGHgi/Nw0CZ2o6JqWSbMlI219lAFLZZCyqByTsvVAJq5XA5H8cA6PrvBRpBWEuQ==", + "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.1.0", "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.1.0.tgz", diff --git a/package.json b/package.json index 6fdc9b0..3fec892 100644 --- a/package.json +++ b/package.json @@ -21,6 +21,7 @@ "devDependencies": { "@eslint/eslintrc": "^3.3.1", "@eslint/js": "^9.39.1", + "@playwright/test": "^1.57.0", "@tailwindcss/postcss": "^4", "@testing-library/dom": "^10.4.1", "@testing-library/jest-dom": "^6.9.1", diff --git a/playwright.config.ts b/playwright.config.ts new file mode 100644 index 0000000..dfe72ab --- /dev/null +++ b/playwright.config.ts @@ -0,0 +1,79 @@ +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') }); + +/** + * 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://localhost: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://localhost:3000', + // reuseExistingServer: !process.env.CI, + // }, +}); From 8c800d2a41e48cd18bdc3e8ff7d9f12544793020 Mon Sep 17 00:00:00 2001 From: elysableu Date: Thu, 4 Dec 2025 22:35:34 -0700 Subject: [PATCH 3/4] Remove unnecessary example test from e2e --- e2e/example.spec.ts | 18 ------------------ e2e/fixtures/.keep | 0 e2e/tests/.keep | 0 3 files changed, 18 deletions(-) delete mode 100644 e2e/example.spec.ts create mode 100644 e2e/fixtures/.keep create mode 100644 e2e/tests/.keep diff --git a/e2e/example.spec.ts b/e2e/example.spec.ts deleted file mode 100644 index 54a906a..0000000 --- a/e2e/example.spec.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { test, expect } from '@playwright/test'; - -test('has title', async ({ page }) => { - await page.goto('https://playwright.dev/'); - - // Expect a title "to contain" a substring. - await expect(page).toHaveTitle(/Playwright/); -}); - -test('get started link', async ({ page }) => { - await page.goto('https://playwright.dev/'); - - // Click the get started link. - await page.getByRole('link', { name: 'Get started' }).click(); - - // Expects page to have a heading with the name of Installation. - await expect(page.getByRole('heading', { name: 'Installation' })).toBeVisible(); -}); diff --git a/e2e/fixtures/.keep b/e2e/fixtures/.keep new file mode 100644 index 0000000..e69de29 diff --git a/e2e/tests/.keep b/e2e/tests/.keep new file mode 100644 index 0000000..e69de29 From 6a253491c4489c7ff4ee420b013752971355fc60 Mon Sep 17 00:00:00 2001 From: elysableu Date: Thu, 4 Dec 2025 23:28:12 -0700 Subject: [PATCH 4/4] Update configurations to handle both jest and playwright tests --- e2e/tests/.keep | 0 e2e/tests/example.spec.ts | 5 ++++ jest.config.ts | 12 ++++++++ package.json | 8 ++++- playwright.config.ts | 29 ++++++++++++++----- .../components/CharacterRoster.test.tsx | 1 - tsconfig.e2e.json | 11 +++++++ tsconfig.json | 4 +-- 8 files changed, 59 insertions(+), 11 deletions(-) delete mode 100644 e2e/tests/.keep create mode 100644 e2e/tests/example.spec.ts create mode 100644 tsconfig.e2e.json diff --git a/e2e/tests/.keep b/e2e/tests/.keep deleted file mode 100644 index e69de29..0000000 diff --git a/e2e/tests/example.spec.ts b/e2e/tests/example.spec.ts new file mode 100644 index 0000000..0cba90d --- /dev/null +++ b/e2e/tests/example.spec.ts @@ -0,0 +1,5 @@ +import { test, expect as playwrightExpect } from '@playwright/test' + +test('placeholder test', async ({ page }) => { + playwrightExpect(true).toBe(true) +}) \ No newline at end of file diff --git a/jest.config.ts b/jest.config.ts index bfdfd8e..3e8b76f 100644 --- a/jest.config.ts +++ b/jest.config.ts @@ -12,6 +12,18 @@ const config: Config = { moduleNameMapper: { '^@/(.*)$': '/$1', }, + + testMatch: [ + '/src/**/*.test.{js,jsx,ts,tsx}', + '/src/**/__tests__/**/*.{js,jsx,ts,tsx}', + ], + + testPathIgnorePatterns: [ + '/node_modules/', + '/e2e/', // Ignore Playwright tests + '/.next/', + '/dist/', + ], // Coverage configuration collectCoverageFrom: [ diff --git a/package.json b/package.json index 3fec892..b5580e3 100644 --- a/package.json +++ b/package.json @@ -11,7 +11,13 @@ "format:check": "prettier --check \"src/**/*.{ts,tsx,js,jsx,json,css}\"", "test": "jest", "test:watch": "jest --watch", - "test:coverage": "jest --coverage" + "test:coverage": "jest --coverage", + "test:e2e": "playwright test", + "test:e2e:ui": "playwright test --ui", + "test:e2e:headed": "playwright test --headed", + "test:e2e:debug": "playwright test --debug", + "test:e2e:report": "playwright show-report", + "test:all": "npm test && npm run test:e2e" }, "dependencies": { "next": "15.3.1", diff --git a/playwright.config.ts b/playwright.config.ts index dfe72ab..cf8be3b 100644 --- a/playwright.config.ts +++ b/playwright.config.ts @@ -12,7 +12,7 @@ import { defineConfig, devices } from '@playwright/test'; * See https://playwright.dev/docs/test-configuration. */ export default defineConfig({ - testDir: './e2e', + testDir: './e2e/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,15 +21,27 @@ export default defineConfig({ 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', + /* Only match .spec.ts files (avoid conflicts with Jest .test.ts files) */ + testMatch: '**/*.spec.ts', + /* Ignore non-test files */ + testIgnore: ['**/.keep', '**/README.md', '**/node_modules/**'], /* 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://localhost:3000', + baseURL: 'http://localhost:3001', /* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */ trace: 'on-first-retry', + + /* Take screenshot on failure */ + screenshot: 'only-on-failure', + + /* Record video on failure */ + video: 'retain-on-failure', + }, /* Configure projects for major browsers */ @@ -71,9 +83,12 @@ export default defineConfig({ ], /* Run your local dev server before starting the tests */ - // webServer: { - // command: 'npm run start', - // url: 'http://localhost:3000', - // reuseExistingServer: !process.env.CI, - // }, + webServer: { + command: 'npm run dev', + url: 'http://localhost:3001', + reuseExistingServer: !process.env.CI, + timeout: 120 * 1000, // 2 minutes for Next.js to start + stdout: 'pipe', // Show server output + stderr: 'pipe', + }, }); diff --git a/src/app/profile/components/CharacterRoster.test.tsx b/src/app/profile/components/CharacterRoster.test.tsx index a32a432..affdaa1 100644 --- a/src/app/profile/components/CharacterRoster.test.tsx +++ b/src/app/profile/components/CharacterRoster.test.tsx @@ -6,7 +6,6 @@ import '@testing-library/jest-dom' describe('CharacterRoster', () => { it('renders all character cards', () => { render() - console.log(mockCharacters); mockCharacters.forEach((character) => { expect(screen.getByText(character.name)).toBeInTheDocument() diff --git a/tsconfig.e2e.json b/tsconfig.e2e.json new file mode 100644 index 0000000..5a62ac7 --- /dev/null +++ b/tsconfig.e2e.json @@ -0,0 +1,11 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "target": "ES2020", + "lib": ["ES2021"], + "types": ["@playwright/test", "node"], + "moduleResolution": "node" + }, + "include": ["e2e/**/*"], + "exclude": ["node_modules"] +} \ No newline at end of file diff --git a/tsconfig.json b/tsconfig.json index 2ff581a..00948e1 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,6 +1,6 @@ { "compilerOptions": { - "target": "ES2017", + "target": "ES2020", "lib": ["dom", "dom.iterable", "esnext"], "allowJs": true, "skipLibCheck": true, @@ -24,5 +24,5 @@ } }, "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"], - "exclude": ["node_modules"] + "exclude": ["node_modules", "e2e"] }