Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions apps/frontend/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@

# Playwright
node_modules/
/test-results/
/playwright-report/
/blob-report/
/playwright/.cache/
4 changes: 3 additions & 1 deletion apps/frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,13 @@
"lint": "eslint . && prettier --check .",
"fix": "eslint . --fix && prettier --write .",
"intl:extract": "formatjs extract \"{,src/components,src/composables,src/layouts,src/middleware,src/modules,src/pages,src/plugins,src/utils}/**/*.{vue,ts,tsx,js,jsx,mts,cts,mjs,cjs}\" \"src/error.vue\" --ignore '**/*.d.ts' --ignore 'node_modules' --out-file src/locales/en-US/index.json --format crowdin --preserve-whitespace",
"test": "nuxi build"
"test": "playwright test",
"test:gen": "playwright codegen http://localhost:3000"
},
"devDependencies": {
"@formatjs/cli": "^6.2.12",
"@nuxt/devtools": "^1.3.3",
"@playwright/test": "^1.54.2",
"@types/dompurify": "^3.0.5",
"@types/node": "^20.1.0",
"@vintl/compact-number": "^2.0.5",
Expand Down
61 changes: 61 additions & 0 deletions apps/frontend/playwright.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import { defineConfig, devices } from '@playwright/test'

/**
* See https://playwright.dev/docs/test-configuration.
*/
export default defineConfig({
testDir: './tests',
fullyParallel: true,
forbidOnly: !!process.env.CI,
retries: process.env.CI ? 2 : 0,
workers: process.env.CI ? 1 : undefined,
reporter: 'html',
use: {
baseURL: 'http://localhost:3000',
Copy link
Member Author

@IMB11 IMB11 Aug 19, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See previous comment.

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' },
// },
],

webServer: {
command: 'pnpm run dev',
Copy link
Member Author

@IMB11 IMB11 Aug 19, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ideally we want to use the Cloudflare deployment associated with the PR for CI, rather than a dev runner, since nuxt has a tendency to hot reload quite often during warmup which might affect tests.

url: 'http://localhost:3000',
reuseExistingServer: !process.env.CI,
},
})
32 changes: 32 additions & 0 deletions apps/frontend/tests/switch-theme.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { expect, test, type Page } from '@playwright/test'

async function hasThemeOnElement(page: Page, element: string) {
const htmlElement = page.locator('html')
return await htmlElement.evaluate((el, theme) => el.classList.contains(theme), element)
}

test('test', async ({ page }, testInfo) => {
await page.goto('http://localhost:3000/')
await page.getByRole('link', { name: 'Settings' }).click()
await page.locator('html').click()

await page.getByRole('button', { name: 'Light' }).click()
const lightMode = await page.screenshot()
expect(await hasThemeOnElement(page, 'light-mode')).toBe(true)

await page.waitForTimeout(1000)

await page.getByRole('button', { name: 'Dark' }).click()
const darkMode = await page.screenshot()
expect(await hasThemeOnElement(page, 'dark-mode')).toBe(true)

await page.waitForTimeout(1000)

await page.getByRole('button', { name: 'OLED' }).click()
const oledMode = await page.screenshot()
expect(await hasThemeOnElement(page, 'oled-mode')).toBe(true)

testInfo.attach('test-results/light-mode', { body: lightMode, contentType: 'image/png' })
testInfo.attach('test-results/dark-mode', { body: darkMode, contentType: 'image/png' })
testInfo.attach('test-results/oled-mode', { body: oledMode, contentType: 'image/png' })
})
38 changes: 38 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading