Phase 1 step 2 of VNCprodbuild. e2e/electron-smoke.spec.ts uses Playwright's
_electron.launch() to boot the real skeleton (dist-electron/main.js from
step 1) and asserts:
- the login screen renders (same input[type="text"]/[type="password"]
selectors as e2e/login.spec.ts's browser-based check)
- zero uncaught page errors fire during load
Sets JMAP_SERVER_URL (any non-empty value) so the app reaches
lib/setup/state.ts's "env-managed" state and serves the normal login screen
instead of 302ing to the first-run /setup wizard - no live mail server or
mock JMAP build flag needed just to prove the shell renders.
playwright.electron.config.ts is deliberately separate from
playwright.config.ts: it has no `webServer` block, since this suite's app
boots its own server and would otherwise race pointlessly with `npm run dev`
starting on :3000 for the browser-based e2e/*.spec.ts suite.
Wired as `npm run test:electron`. Verified green locally (2 passed) after
`npm run build:standalone && npm run build:electron`; every later step in
the Electron rollout must keep this passing before moving on.
63 lines
2.5 KiB
TypeScript
63 lines
2.5 KiB
TypeScript
import { test, expect, _electron as electron } from '@playwright/test';
|
|
import type { ElectronApplication, Page } from '@playwright/test';
|
|
import path from 'node:path';
|
|
|
|
// Regression gate for the Electron desktop shell (electron/main.ts +
|
|
// electron/preload.ts). Launches the real skeleton - the same standalone
|
|
// Next.js server artifact the Dockerfile produces, booted as a child
|
|
// process by main.ts, with a real BrowserWindow on top - and asserts the
|
|
// login screen renders with zero uncaught page errors. Every later step in
|
|
// the Electron rollout (notification bridge, realtime sync, packaging) must
|
|
// keep this green; run it before touching anything else.
|
|
//
|
|
// Requires `npm run build:standalone && npm run build:electron` to have run
|
|
// first (see package.json's `electron:dev`/`test:electron` scripts, which
|
|
// this suite assumes but does not itself trigger, matching how
|
|
// playwright.config.ts's browser suite assumes `npm run build` for its own
|
|
// prod-mode runs).
|
|
const projectRoot = path.resolve(__dirname, '..');
|
|
|
|
test.describe('Electron desktop shell', () => {
|
|
let electronApp: ElectronApplication;
|
|
let window: Page;
|
|
const pageErrors: Error[] = [];
|
|
|
|
test.beforeAll(async () => {
|
|
electronApp = await electron.launch({
|
|
args: [projectRoot],
|
|
env: {
|
|
...process.env,
|
|
// Bypass the first-run setup wizard (lib/setup/state.ts's
|
|
// "bootstrap" state, which 302s everything to /setup) without
|
|
// needing a reachable JMAP server just to prove the login screen
|
|
// renders - any non-empty JMAP_SERVER_URL is enough to reach
|
|
// "env-managed" state and serve the normal app shell.
|
|
JMAP_SERVER_URL: 'https://stalwart.sandbox.vnc.de',
|
|
SESSION_SECRET: 'electron-smoke-test-not-for-production',
|
|
NODE_ENV: 'production',
|
|
},
|
|
});
|
|
|
|
window = await electronApp.firstWindow();
|
|
window.on('pageerror', (error) => {
|
|
pageErrors.push(error);
|
|
});
|
|
await window.waitForLoadState('domcontentloaded');
|
|
});
|
|
|
|
test.afterAll(async () => {
|
|
await electronApp?.close();
|
|
});
|
|
|
|
test('boots the standalone server and renders the login screen', async () => {
|
|
// Same selectors as e2e/login.spec.ts's browser-based check - the
|
|
// shell should render the identical login form, not a different view.
|
|
await expect(window.locator('input[type="text"]')).toBeVisible({ timeout: 20000 });
|
|
await expect(window.locator('input[type="password"]')).toBeVisible();
|
|
});
|
|
|
|
test('produces zero uncaught page errors', () => {
|
|
expect(pageErrors).toEqual([]);
|
|
});
|
|
});
|