diff options
Diffstat (limited to 'tests/captive-portal.spec.mjs')
| -rw-r--r-- | tests/captive-portal.spec.mjs | 75 |
1 files changed, 75 insertions, 0 deletions
diff --git a/tests/captive-portal.spec.mjs b/tests/captive-portal.spec.mjs new file mode 100644 index 0000000..b6ad96b --- /dev/null +++ b/tests/captive-portal.spec.mjs | |||
| @@ -0,0 +1,75 @@ | |||
| 1 | import { test, expect } from '@playwright/test'; | ||
| 2 | |||
| 3 | const PORTAL_IP = process.env.TOLLGATE_IP || '192.168.4.1'; | ||
| 4 | const PORTAL_URL = `http://${PORTAL_IP}`; | ||
| 5 | |||
| 6 | test.describe('Captive Portal - Phase 1', () => { | ||
| 7 | |||
| 8 | test('portal page loads with TollGate branding', async ({ page }) => { | ||
| 9 | await page.goto(PORTAL_URL); | ||
| 10 | await expect(page.locator('h1')).toHaveText('TollGate'); | ||
| 11 | await expect(page.locator('.subtitle')).toContainText('internet access'); | ||
| 12 | }); | ||
| 13 | |||
| 14 | test('portal shows price', async ({ page }) => { | ||
| 15 | await page.goto(PORTAL_URL); | ||
| 16 | const priceEl = page.locator('.price-amount'); | ||
| 17 | await expect(priceEl).not.toBeEmpty({ timeout: 5000 }); | ||
| 18 | }); | ||
| 19 | |||
| 20 | test('grant access button exists', async ({ page }) => { | ||
| 21 | await page.goto(PORTAL_URL); | ||
| 22 | const btn = page.locator('#grantBtn'); | ||
| 23 | await expect(btn).toBeVisible(); | ||
| 24 | await expect(btn).toHaveText(/Grant Free Access/i); | ||
| 25 | }); | ||
| 26 | |||
| 27 | test('click grant access shows connected', async ({ page }) => { | ||
| 28 | await page.goto(PORTAL_URL); | ||
| 29 | const btn = page.locator('#grantBtn'); | ||
| 30 | await btn.click(); | ||
| 31 | const status = page.locator('#status.success'); | ||
| 32 | await expect(status).toBeVisible({ timeout: 10000 }); | ||
| 33 | await expect(status).toContainText(/Connected/i); | ||
| 34 | }); | ||
| 35 | |||
| 36 | test('captive detection URIs return portal', async ({ page }) => { | ||
| 37 | const uris = ['/generate_204', '/hotspot-detect.html', '/canonical.html', '/success.txt']; | ||
| 38 | for (const uri of uris) { | ||
| 39 | const resp = await page.goto(`${PORTAL_URL}${uri}`); | ||
| 40 | expect(resp.status()).toBe(200); | ||
| 41 | const body = await resp.text(); | ||
| 42 | expect(body).toContain('TollGate'); | ||
| 43 | } | ||
| 44 | }); | ||
| 45 | |||
| 46 | test('/api/status returns JSON with price', async ({ page }) => { | ||
| 47 | const resp = await page.goto(`${PORTAL_URL}/api/status`); | ||
| 48 | expect(resp.status()).toBe(200); | ||
| 49 | const data = await resp.json(); | ||
| 50 | expect(data).toHaveProperty('connected'); | ||
| 51 | expect(data).toHaveProperty('price'); | ||
| 52 | expect(typeof data.price).toBe('number'); | ||
| 53 | }); | ||
| 54 | |||
| 55 | test('/whoami returns mac address', async ({ page }) => { | ||
| 56 | const resp = await page.goto(`${PORTAL_URL}/whoami`); | ||
| 57 | expect(resp.status()).toBe(200); | ||
| 58 | const text = await resp.text(); | ||
| 59 | expect(text).toMatch(/^mac=/); | ||
| 60 | }); | ||
| 61 | |||
| 62 | test('/usage returns -1/-1 before auth', async ({ page }) => { | ||
| 63 | const resp = await page.goto(`${PORTAL_URL}/usage`); | ||
| 64 | expect(resp.status()).toBe(200); | ||
| 65 | const text = await resp.text(); | ||
| 66 | expect(text).toBe('-1/-1'); | ||
| 67 | }); | ||
| 68 | |||
| 69 | test('/reset_authentication works', async ({ page }) => { | ||
| 70 | const resp = await page.goto(`${PORTAL_URL}/reset_authentication`); | ||
| 71 | expect(resp.status()).toBe(200); | ||
| 72 | const data = await resp.json(); | ||
| 73 | expect(data.status).toBe('reset'); | ||
| 74 | }); | ||
| 75 | }); | ||