diff options
| author | Your Name <you@example.com> | 2026-05-16 13:02:23 +0530 |
|---|---|---|
| committer | Your Name <you@example.com> | 2026-05-16 13:02:23 +0530 |
| commit | 236b61d619f60d941119d891dc1c6a49b504a880 (patch) | |
| tree | 3f5faffc36284d8082fe1a468eecdb89c3b9e11a /tests/captive-portal.spec.mjs | |
| parent | 38aa9ec3801f5895e09866fe92cb8e44fb987cee (diff) | |
Fix captive portal detection on GrapheneOS + embed mint URL in portal HTML
- Add esp_netif_set_dns_info() on AP interface so DHCP advertises
AP as DNS server to clients (fixes captive portal on GrapheneOS)
- Embed price and mint URL directly in portal HTML via server-side
template substitution (no JavaScript fetch to :2121 needed)
- Move supported mints section below the token input field
- Add Playwright tests: no unresolved placeholders, embedded mint/price,
DOM order verification (14/14 passing)
Diffstat (limited to 'tests/captive-portal.spec.mjs')
| -rw-r--r-- | tests/captive-portal.spec.mjs | 38 |
1 files changed, 36 insertions, 2 deletions
diff --git a/tests/captive-portal.spec.mjs b/tests/captive-portal.spec.mjs index bc7a1fa..9411183 100644 --- a/tests/captive-portal.spec.mjs +++ b/tests/captive-portal.spec.mjs | |||
| @@ -15,7 +15,41 @@ test.describe('Captive Portal - Phase 2', () => { | |||
| 15 | test('portal shows price from API', async ({ page }) => { | 15 | test('portal shows price from API', async ({ page }) => { |
| 16 | await page.goto(PORTAL_URL); | 16 | await page.goto(PORTAL_URL); |
| 17 | const priceEl = page.locator('.price-amount'); | 17 | const priceEl = page.locator('.price-amount'); |
| 18 | await expect(priceEl).not.toBeEmpty({ timeout: 5000 }); | 18 | await expect(priceEl).toHaveText(/\d+/, { timeout: 5000 }); |
| 19 | }); | ||
| 20 | |||
| 21 | test('portal embeds mint URL without JavaScript fetch', async ({ request }) => { | ||
| 22 | const resp = await request.fetch(PORTAL_URL); | ||
| 23 | const body = await resp.text(); | ||
| 24 | expect(body).not.toContain('Loading...'); | ||
| 25 | expect(body).not.toContain('Error loading mint URL'); | ||
| 26 | expect(body).toMatch(/testnut\.cashu\.space/); | ||
| 27 | }); | ||
| 28 | |||
| 29 | test('portal embeds price without JavaScript fetch', async ({ request }) => { | ||
| 30 | const resp = await request.fetch(PORTAL_URL); | ||
| 31 | const body = await resp.text(); | ||
| 32 | expect(body).not.toContain('__PRICE__'); | ||
| 33 | expect(body).toMatch(/price-amount['"]>\d+</); | ||
| 34 | }); | ||
| 35 | |||
| 36 | test('portal HTML has no unresolved template placeholders', async ({ request }) => { | ||
| 37 | const resp = await request.fetch(PORTAL_URL); | ||
| 38 | const body = await resp.text(); | ||
| 39 | expect(body).not.toContain('__AP_IP__'); | ||
| 40 | expect(body).not.toContain('__MINT_URL__'); | ||
| 41 | expect(body).not.toContain('__PRICE__'); | ||
| 42 | }); | ||
| 43 | |||
| 44 | test('mints section appears after token input in DOM order', async ({ page }) => { | ||
| 45 | await page.goto(PORTAL_URL); | ||
| 46 | const textarea = page.locator('#tokenInput'); | ||
| 47 | const mintUrl = page.locator('#mintUrl'); | ||
| 48 | await expect(textarea).toBeVisible(); | ||
| 49 | await expect(mintUrl).toBeVisible(); | ||
| 50 | const inputBox = await textarea.boundingBox(); | ||
| 51 | const mintBox = await mintUrl.boundingBox(); | ||
| 52 | expect(mintBox.y).toBeGreaterThan(inputBox.y); | ||
| 19 | }); | 53 | }); |
| 20 | 54 | ||
| 21 | test('portal has Cashu token input', async ({ page }) => { | 55 | test('portal has Cashu token input', async ({ page }) => { |
| @@ -52,7 +86,7 @@ test.describe('Captive Portal - Phase 2', () => { | |||
| 52 | expect(resp.status()).toBe(200); | 86 | expect(resp.status()).toBe(200); |
| 53 | const text = await resp.text(); | 87 | const text = await resp.text(); |
| 54 | expect(text).toMatch(/ip=\d+\.\d+\.\d+\.\d+/); | 88 | expect(text).toMatch(/ip=\d+\.\d+\.\d+\.\d+/); |
| 55 | expect(text).toMatch(/mac=[0-9a-f]{2}:/); | 89 | expect(text).toMatch(/mac=(unknown|[0-9a-f]{2}:)/); |
| 56 | }); | 90 | }); |
| 57 | 91 | ||
| 58 | test('/usage returns -1/-1 before payment', async ({ page }) => { | 92 | test('/usage returns -1/-1 before payment', async ({ page }) => { |