From 2cc4969678f4d073ebddec0e7e9f2aac707fb761 Mon Sep 17 00:00:00 2001 From: Adam Soltys Date: Wed, 11 Feb 2026 09:44:48 -0800 Subject: playwright test --- bun.lock | 9 +++++++++ package.json | 2 ++ playwright.config.ts | 37 ++++++++++++++++++++++++++++++++++ src/components/Balance.svelte | 8 ++++++-- src/routes/(static)/login/+page.svelte | 10 +++++++-- test/e2e/login-balance.spec.ts | 23 +++++++++++++++++++++ 6 files changed, 85 insertions(+), 4 deletions(-) create mode 100644 playwright.config.ts create mode 100644 test/e2e/login-balance.spec.ts diff --git a/bun.lock b/bun.lock index b8c83485..a38ab114 100644 --- a/bun.lock +++ b/bun.lock @@ -19,6 +19,7 @@ "@capacitor/core": "^8.0.2", "@capacitor/ios": "^8.0.2", "@iconify/iconify": "^3.1.1", + "@playwright/test": "^1.54.2", "@scure/base": "^2.0.0", "@scure/bip39": "^2.0.1", "@scure/btc-signer": "^2.0.1", @@ -206,6 +207,8 @@ "@paralleldrive/cuid2": ["@paralleldrive/cuid2@2.2.2", "", { "dependencies": { "@noble/hashes": "^1.1.5" } }, "sha512-ZOBkgDwEdoYVlSeRbYYXs0S9MejQofiVYoTbKzy/6GQa39/q5tQU2IX46+shYnUkpEl3wc+J6wRlar7r2EK2xA=="], + "@playwright/test": ["@playwright/test@1.58.2", "", { "dependencies": { "playwright": "1.58.2" }, "bin": { "playwright": "cli.js" } }, "sha512-akea+6bHYBBfA9uQqSYmlJXn61cTa+jbO87xVLCWbTqbWadRVmhxlXATaOjOgcBaWU4ePo0wB41KMFv3o35IXA=="], + "@polka/url": ["@polka/url@1.0.0-next.29", "", {}, "sha512-wwQAWhWSuHaag8c4q/KN/vCoeOJYshAIvMQwD4GpSb3OiZklFfvAgmj0VCBBImRpuF/aFgIRzllXlVX93Jevww=="], "@prettier/plugin-xml": ["@prettier/plugin-xml@2.2.0", "", { "dependencies": { "@xml-tools/parser": "^1.0.11", "prettier": ">=2.4.0" } }, "sha512-UWRmygBsyj4bVXvDiqSccwT1kmsorcwQwaIy30yVh8T+Gspx4OlC0shX1y+ZuwXZvgnafmpRYKks0bAu9urJew=="], @@ -924,6 +927,10 @@ "pify": ["pify@2.3.0", "", {}, "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog=="], + "playwright": ["playwright@1.58.2", "", { "dependencies": { "playwright-core": "1.58.2" }, "optionalDependencies": { "fsevents": "2.3.2" }, "bin": { "playwright": "cli.js" } }, "sha512-vA30H8Nvkq/cPBnNw4Q8TWz1EJyqgpuinBcHET0YVJVFldr8JDNiU9LaWAE1KqSkRYazuaBhTpB5ZzShOezQ6A=="], + + "playwright-core": ["playwright-core@1.58.2", "", { "bin": { "playwright-core": "cli.js" } }, "sha512-yZkEtftgwS8CsfYo7nm0KE8jsvm6i/PTgVtB8DL726wNf6H2IMsDuxCpJj59KDaxCtSnrWan2AeDqM7JBaultg=="], + "plist": ["plist@3.1.0", "", { "dependencies": { "@xmldom/xmldom": "^0.8.8", "base64-js": "^1.5.1", "xmlbuilder": "^15.1.1" } }, "sha512-uysumyrvkUX0rX/dEVqt8gC3sTBzd4zoWfLeS29nb53imdaXVvLINYXTI2GNqzaMuvacNx4uJQ8+b3zXR0pkgQ=="], "pngjs": ["pngjs@5.0.0", "", {}, "sha512-40QW5YalBNfQo5yRYmiw7Yz6TKKVr3h6970B2YE+3fQpsWcrbj1PzJgxeJ19DRQjhMbKPIuMY8rFaXc8moolVw=="], @@ -1368,6 +1375,8 @@ "path-type/pify": ["pify@3.0.0", "", {}, "sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg=="], + "playwright/fsevents": ["fsevents@2.3.2", "", { "os": "darwin" }, "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA=="], + "plist/@xmldom/xmldom": ["@xmldom/xmldom@0.8.11", "", {}, "sha512-cQzWCtO6C8TQiYl1ruKNn2U6Ao4o4WBBcbL61yJl84x+j5sOWWFU9X7DpND8XZG3daDppSsigMdfAIl2upQBRw=="], "prebuild-install/tar-fs": ["tar-fs@2.1.3", "", { "dependencies": { "chownr": "^1.1.1", "mkdirp-classic": "^0.5.2", "pump": "^3.0.0", "tar-stream": "^2.1.4" } }, "sha512-090nwYJDmlhwFwEW3QQl+vaNnxsO2yVsd45eTKRBzSzu+hlb1w2K9inVq5b0ngXuLVqQ4ApvsUHHnu/zQNkWAg=="], diff --git a/package.json b/package.json index 9d72de2e..49da557a 100644 --- a/package.json +++ b/package.json @@ -2,6 +2,7 @@ "name": "coinos", "version": "1.0.9", "devDependencies": { + "@playwright/test": "^1.54.2", "@capacitor/android": "^8.0.2", "@capacitor/assets": "^3.0.5", "@capacitor/cli": "^8.0.2", @@ -57,6 +58,7 @@ "buildstaging": "vite build --mode staging", "docker": "docker build . -t coinos-ui", "preview": "vite preview", + "test:e2e": "playwright test", "lint": "prettier --check .", "format": "prettier --write ." }, diff --git a/playwright.config.ts b/playwright.config.ts new file mode 100644 index 00000000..f245b4e4 --- /dev/null +++ b/playwright.config.ts @@ -0,0 +1,37 @@ +import { defineConfig, devices } from "@playwright/test"; + +const port = Number(process.env.E2E_PORT || 4173); +const host = process.env.E2E_HOST || "127.0.0.1"; +const baseURL = process.env.E2E_BASE_URL || `http://${host}:${port}`; + +export default defineConfig({ + testDir: "./test/e2e", + timeout: 30_000, + expect: { + timeout: 10_000, + }, + fullyParallel: true, + forbidOnly: !!process.env.CI, + retries: process.env.CI ? 2 : 0, + workers: process.env.CI ? 1 : undefined, + reporter: [["list"]], + use: { + baseURL, + trace: "on-first-retry", + }, + projects: [ + { + name: "chromium", + use: { ...devices["Desktop Chrome"] }, + }, + ], + webServer: process.env.E2E_SKIP_WEBSERVER + ? undefined + : { + command: `PUBLIC_RECAPTCHA_SITE_KEY= bunx vite dev --host ${host} --port ${port}`, + url: baseURL, + reuseExistingServer: true, + stdout: "pipe", + stderr: "pipe", + }, +}); diff --git a/src/components/Balance.svelte b/src/components/Balance.svelte index cf61e0b0..4ceaa65a 100644 --- a/src/components/Balance.svelte +++ b/src/components/Balance.svelte @@ -22,13 +22,17 @@
{#if user.haspin && !$pin} - {:else if !isNaN(rate)} -
+
new Promise((resolve, reject) => { - if (isTor) return resolve(""); + if (isTor || !recaptchaSiteKey) return resolve(""); if (!browser || !grecaptcha) return reject(new Error("captcha unavailable")); grecaptcha.ready(() => { grecaptcha @@ -182,6 +182,7 @@
- diff --git a/test/e2e/login-balance.spec.ts b/test/e2e/login-balance.spec.ts new file mode 100644 index 00000000..75148bc4 --- /dev/null +++ b/test/e2e/login-balance.spec.ts @@ -0,0 +1,23 @@ +import { expect, test } from "@playwright/test"; + +const username = process.env.E2E_USERNAME || "bob"; +const password = process.env.E2E_PASSWORD || "pw"; + +test("login and report account balance", async ({ page }) => { + await page.goto("/login"); + + await page.getByTestId("login-username").fill(username); + await page.locator('input[name="password"]').first().fill(password); + await page.getByTestId("login-submit").click(); + + await expect(page).toHaveURL(new RegExp(`/${username}(?:[/?#]|$)`)); + + const balances = page.getByTestId("balance-value"); + await expect(balances.first()).toBeVisible(); + + const balanceText = (await balances.first().innerText()).trim(); + const hasNumericBalance = /\d/.test(balanceText); + expect(hasNumericBalance).toBeTruthy(); + + console.log(`[e2e] ${username} visible balance: ${balanceText}`); +}); -- cgit v1.2.3