Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions TESTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -261,6 +261,14 @@ three processes per case and uses 30 seconds on Windows and 10 seconds elsewhere
tests retain their default timeout. `waitForServer` already scales its timeout on Windows;
callers should pass an unscaled value and leave enough hook time for that wait and setup.

Start integration servers with `startServer` from `test/integration-helpers.ts`, and pass
`--strictPort` to Vite. A server binds its port seconds after the port is chosen, so another
process can take it first. Vite without `--strictPort` then moves to the next port, which can be
another test's port. With it, the server exits and `startServer` starts it again on a new port.
Another process that took the port can answer on it too, so answers count only after the server
prints its own URL with the port (`Local: http://…:<port>/` or `Listening on http://…:<port>`).
For a server that prints no URL, pass `printsUrl: false` and an `expectBody` only that app serves.

Windows integration tests also use `maxConcurrency: 2`. `maxWorkers` caps files, not concurrent
tests inside each file: two CI workers with Vitest's default concurrency of five can open ten
isolated browser contexts at once. The Windows cap reduces that to four without serializing
Expand Down
122 changes: 59 additions & 63 deletions packages/md/test/integration/markdown-blog.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,10 @@ import { join } from 'node:path';
import spawn from 'cross-spawn';
import { chromium, type Browser, type Page } from 'playwright';
import { describe, expect, it, beforeAll, afterAll } from 'vite-plus/test';
import { getPort, waitForServer, killChild } from '../../../../test/integration-helpers.ts';
import { killChild, startServer } from '../../../../test/integration-helpers.ts';

const ROOT = join(import.meta.dirname, '..', '..', '..', '..');
let DEV_PORT: number;
let DEV_BASE: string;
let PREVIEW_PORT: number;
let PREVIEW_BASE: string;

let browser: Browser;
Expand Down Expand Up @@ -200,36 +198,36 @@ describe('markdown-blog playground', () => {
let stderr = '';

beforeAll(async () => {
DEV_PORT = await getPort();
DEV_BASE = `http://127.0.0.1:${DEV_PORT}`;

child = spawn(
'vp',
[
'run',
'--filter',
'./playground/markdown-blog',
'dev',
'--host',
'127.0.0.1',
'--port',
String(DEV_PORT),
],
{
cwd: ROOT,
stdio: ['ignore', 'pipe', 'pipe'],
env: {
...process.env,
VOID_INSPECTOR_PORT: 'false',
const server = await startServer((port) => {
child = spawn(
'vp',
[
'run',
'--filter',
'./playground/markdown-blog',
'dev',
'--host',
'127.0.0.1',
'--port',
String(port),
'--strictPort',
],
{
cwd: ROOT,
stdio: ['ignore', 'pipe', 'pipe'],
env: {
...process.env,
VOID_INSPECTOR_PORT: 'false',
},
},
},
);

child.stderr!.on('data', (chunk: Buffer) => {
stderr += String(chunk);
});

await waitForServer(DEV_BASE, 20_000);
);
stderr = '';
child.stderr!.on('data', (chunk: Buffer) => {
stderr += String(chunk);
});
return child;
}, 20_000);
DEV_BASE = server.base;
});

afterAll(async () => {
Expand Down Expand Up @@ -307,38 +305,36 @@ describe('markdown-blog playground', () => {
stdio: 'pipe',
});

PREVIEW_PORT = await getPort();
PREVIEW_BASE = `http://127.0.0.1:${PREVIEW_PORT}`;

child = spawn(
'vp',
[
'run',
'--filter',
'./playground/markdown-blog',
'preview',
'--host',
'127.0.0.1',
'--port',
String(PREVIEW_PORT),
],
{
cwd: ROOT,
stdio: ['ignore', 'pipe', 'pipe'],
env: {
...process.env,
VOID_INSPECTOR_PORT: 'false',
const server = await startServer((port) => {
child = spawn(
'vp',
[
'run',
'--filter',
'./playground/markdown-blog',
'preview',
'--host',
'127.0.0.1',
'--port',
String(port),
'--strictPort',
],
{
cwd: ROOT,
stdio: ['ignore', 'pipe', 'pipe'],
env: {
...process.env,
VOID_INSPECTOR_PORT: 'false',
},
},
},
);

child.stderr!.on('data', (chunk: Buffer) => {
stderr += String(chunk);
});

await waitForServer(PREVIEW_BASE, 20_000, {
isAlive: () => child.exitCode === null,
});
);
stderr = '';
child.stderr!.on('data', (chunk: Buffer) => {
stderr += String(chunk);
});
return child;
}, 20_000);
PREVIEW_BASE = server.base;
});

afterAll(async () => {
Expand Down
133 changes: 60 additions & 73 deletions packages/react/test/integration/react-pages-client.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,7 @@ import spawn from 'cross-spawn';
import { type Browser, type Page } from 'playwright';
import { describe, expect, it, beforeAll, afterAll } from 'vite-plus/test';
import { waitForIslandsHydrated } from '../../../../test/browser-helpers.ts';
import {
collectServerOutput,
getPort,
waitForServer,
killChild,
} from '../../../../test/integration-helpers.ts';
import { killChild, startServer, waitForServer } from '../../../../test/integration-helpers.ts';
import { launchPagesBrowser } from '../../../../test/pages-browser.ts';
import { registerSharedClientTests } from '../../../../test/pages-client-contract.ts';
import { defineSharedIslandTests } from '../../../../test/pages-island-contract.ts';
Expand Down Expand Up @@ -41,9 +36,7 @@ const ROOT = join(import.meta.dirname, '..', '..', '..', '..');
const REACT_PAGES_ROOT = join(ROOT, 'playground/react-pages');
const REACT_PAGES_LAYOUT = join(REACT_PAGES_ROOT, 'pages/layout.tsx');
const LATE_WORKER_DEPS_ROOT = join(REACT_PAGES_ROOT, 'node_modules/@void-repro');
let DEV_PORT: number;
let DEV_BASE: string;
let PREVIEW_PORT: number;
let PREVIEW_BASE: string;

let browser: Browser;
Expand Down Expand Up @@ -615,40 +608,37 @@ describe('react-pages client (dev)', () => {
writeFileSync(REACT_PAGES_LAYOUT, lateWorkerDepLayout());
rmSync(join(REACT_PAGES_ROOT, 'node_modules/.vite'), { recursive: true, force: true });

DEV_PORT = await getPort();
DEV_BASE = `http://127.0.0.1:${DEV_PORT}`;

child = spawn(
'vp',
[
'run',
'--filter',
'./playground/react-pages',
'dev',
'--host',
'127.0.0.1',
'--port',
String(DEV_PORT),
],
{
cwd: ROOT,
stdio: ['ignore', 'pipe', 'pipe'],
env: {
...process.env,
VOID_INSPECTOR_PORT: 'false',
},
},
);

child.stderr!.on('data', (chunk: Buffer) => {
stderr += String(chunk);
});

const serverTimeout = process.platform === 'win32' ? 45_000 : 20_000;
await waitForServer(DEV_BASE, serverTimeout, {
isAlive: () => child.exitCode === null && child.signalCode === null,
diagnostics: collectServerOutput(child),
});
const server = await startServer((port) => {
child = spawn(
'vp',
[
'run',
'--filter',
'./playground/react-pages',
'dev',
'--host',
'127.0.0.1',
'--port',
String(port),
'--strictPort',
],
{
cwd: ROOT,
stdio: ['ignore', 'pipe', 'pipe'],
env: {
...process.env,
VOID_INSPECTOR_PORT: 'false',
},
},
);
stderr = '';
child.stderr!.on('data', (chunk: Buffer) => {
stderr += String(chunk);
});
return child;
}, serverTimeout);
DEV_BASE = server.base;
const paths = ['/', '/users', '/action-error', '/router-params/alpha', '/visit-await'];
coldStartResponses.push(
...(await Promise.all(
Expand Down Expand Up @@ -1099,39 +1089,36 @@ describe('react-pages client (preview)', { retry: 2 }, () => {
});
}

PREVIEW_PORT = await getPort();
PREVIEW_BASE = `http://127.0.0.1:${PREVIEW_PORT}`;

child = spawn(
'vp',
[
'run',
'--filter',
'./playground/react-pages',
'preview',
'--host',
'127.0.0.1',
'--port',
String(PREVIEW_PORT),
],
{
cwd: ROOT,
stdio: ['ignore', 'pipe', 'pipe'],
env: {
...process.env,
VOID_INSPECTOR_PORT: 'false',
const server = await startServer((port) => {
child = spawn(
'vp',
[
'run',
'--filter',
'./playground/react-pages',
'preview',
'--host',
'127.0.0.1',
'--port',
String(port),
'--strictPort',
],
{
cwd: ROOT,
stdio: ['ignore', 'pipe', 'pipe'],
env: {
...process.env,
VOID_INSPECTOR_PORT: 'false',
},
},
},
);

child.stderr!.on('data', (chunk: Buffer) => {
stderr += String(chunk);
});

await waitForServer(PREVIEW_BASE, 30_000, {
isAlive: () => child.exitCode === null && child.signalCode === null,
diagnostics: collectServerOutput(child),
});
);
stderr = '';
child.stderr!.on('data', (chunk: Buffer) => {
stderr += String(chunk);
});
return child;
}, 30_000);
PREVIEW_BASE = server.base;
});

afterAll(async () => {
Expand Down
Loading
Loading