- .github/workflows/ci.yml: three parallel jobs on pull_request and
pushes to main/develop, none needing a backend:
unit (typecheck, lint, test:coverage), e2e (pnpm build, then the
mocked Playwright suite against the standalone server, chromium) and
storybook (build-storybook).
- Mocked e2e reliability:
- saved-views.spec mocked /qqq/v1/processes/<name>/init with a JSON
`values` field, but the app posts saved-view processes to the
registered route (/processes/<name>/init) with one multipart field
per value, so three tests saw no views. The mocks now match the
real request.
- playwright.config: QQQ_E2E_SERVER=production serves the `pnpm build`
standalone output (scripts/e2e-server.mjs) instead of compiling
routes on first hit; QQQ_E2E_PORT picks the port; retries 0 so a
flaky test fails instead of passing on retry; trace kept on failure.
- 104/104 pass; 520/520 with --repeat-each=5 --workers=4.
- vitest.config: coverage thresholds for src/lib just under the measured
82.8/75.65/89.87/84.42 (statements/branches/functions/lines), and
higher per-folder floors for src/lib/api and src/lib/utils.
- Storybook: silence Rollup's per-module "use client" directive and
sourcemap-location warnings (100 lines per build).
- playwright-report/index.html and test-results/.last-run.json were
committed despite being ignored; untracked.
28 lines
1.3 KiB
JavaScript
28 lines
1.3 KiB
JavaScript
/*
|
|
* Copyright 2026 QRun.IO, Inc.
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at https://www.apache.org/licenses/LICENSE-2.0
|
|
*/
|
|
|
|
// Serves the production standalone build (`pnpm build`) for the mocked e2e suite. No backend
|
|
// runs: the specs answer every API call with page.route mocks (tests/e2e/api-mocks.ts).
|
|
import { spawn } from 'node:child_process'
|
|
import { cpSync, existsSync } from 'node:fs'
|
|
import path from 'node:path'
|
|
|
|
const standalone = path.resolve('.next/standalone')
|
|
if (!existsSync(path.join(standalone, 'server.js'))) {
|
|
console.error('No standalone build in .next/standalone; run `pnpm build` first.')
|
|
process.exit(1)
|
|
}
|
|
cpSync(path.resolve('.next/static'), path.join(standalone, '.next/static'), { recursive: true })
|
|
cpSync(path.resolve('public'), path.join(standalone, 'public'), { recursive: true })
|
|
const server = spawn('node', ['server.js'], {
|
|
cwd: standalone,
|
|
stdio: 'inherit',
|
|
env: { ...process.env, NODE_ENV: 'production', HOSTNAME: '127.0.0.1', PORT: process.env.QQQ_E2E_PORT ?? '3000' },
|
|
})
|
|
for (const signal of ['SIGINT', 'SIGTERM']) process.on(signal, () => server.kill('SIGTERM'))
|
|
server.on('exit', (code) => process.exit(code ?? 1))
|