Files
punimtag/e2e/tests/prod.smoke.spec.ts
T
ilia 4273162d9e
CI / skip-ci-check (pull_request) Successful in 4s
CI / docker-ci (pull_request) Successful in 6s
CI / secret-scan (pull_request) Successful in 11s
CI / viewer-unit (pull_request) Failing after 1m3s
CI / admin-unit (pull_request) Failing after 1m1s
CI / e2e (pull_request) Failing after 59s
test: interceptNetworkCall + Zod widening, PROD smoke, NextAuth write gates
- upload.smoke.spec.ts / gallery.search-filters.spec.ts: replace
  waitForResponse/text-scrape with typed interceptNetworkCall spies (status
  + JSON shape) on the real upload POST and the filtered /api/search GET.
- api.fastapi-login.spec.ts: Zod-validate the FastAPI TokenResponse and
  /auth/me UserResponse instead of loose casts. gallery.search-filters.spec.ts
  gets the same treatment for the Prisma-backed SearchResponse.
- prod.smoke.spec.ts: opt-in (PROD_BASE_URL) health + login-page check on a
  real PROD host; skips as a no-op until the PROD LXC exists (none does yet
  per `pct list` — see ROADMAP).
- viewer.write-gates.spec.ts: NextAuth (browser-session) hasWriteAccess gate
  on POST /api/faces/{id}/identify — viewer 403s, admin passes through.
  Provisioned a third, independent auth-DB user (e2e-viewer@levkine.ca,
  hasWriteAccess=false) for this via ansible's provision-punimtag-e2e-user.py
  (see that repo for the vault/Infisical/Gitea/Vaultwarden side).
2026-07-14 22:07:30 -04:00

37 lines
1.5 KiB
TypeScript

import { test as base, expect } from '@playwright/test';
import { assertPublicHost } from '@levkin/playkit';
/**
* PROD smoke: health + public login page only — no mutating actions, no
* login attempt, no LAN-only FastAPI dependency. Deliberately does NOT use
* the shared `fixtures.ts` (`api`/`playkitConfig` there resolve to DEV via
* `env-defaults.json`); PROD has its own base URL, set only when the PROD
* LXC actually exists (`vault_punimtag_nextauth_url_prod` is unset today —
* LXC 9103 hasn't been provisioned, see ROADMAP "Ops / docs debt").
*
* Set `PROD_BASE_URL` (e.g. `https://punimtag.levkin.ca`) to enable; skips
* otherwise so this spec is a no-op until PROD ships.
*/
const prodBaseUrl = process.env.PROD_BASE_URL || '';
base.describe('PROD smoke @prod', () => {
base.skip(!prodBaseUrl, 'PROD_BASE_URL not set — PROD LXC not provisioned yet');
base('health endpoint reports ok', async ({ request }) => {
assertPublicHost(prodBaseUrl);
const res = await request.get(`${prodBaseUrl}/api/health`);
expect(res.ok()).toBeTruthy();
const body = await res.json();
expect(body.status).toBe('ok');
});
base('login page loads on the public host', async ({ page }) => {
assertPublicHost(prodBaseUrl);
await page.goto(`${prodBaseUrl}/login`);
expect(new URL(page.url()).hostname).toBe(new URL(prodBaseUrl).hostname);
await expect(page.getByRole('button', { name: /Sign in/i })).toBeVisible({
timeout: 20_000,
});
});
});