feat(webServer): support name option for custom web server log prefixes (#35105)

This commit is contained in:
Pengoose 2025-03-11 11:12:59 +09:00 committed by GitHub
parent 2a53108cf0
commit 43ee924087
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 74 additions and 4 deletions

View File

@ -668,6 +668,7 @@ export default defineConfig({
- `signal` <["SIGINT"|"SIGTERM"]>
- `timeout` <[int]>
- `url` ?<[string]> The url on your http server that is expected to return a 2xx, 3xx, 400, 401, 402, or 403 status code when the server is ready to accept connections. Redirects (3xx status codes) are being followed and the new location is checked. Either `port` or `url` should be specified.
- `name` ?<[string]> Specifies a custom name for the web server. This name will be prefixed to log messages. Defaults to `[WebServer]`.
Launch a development web server (or multiple) during the tests.
@ -720,12 +721,14 @@ export default defineConfig({
{
command: 'npm run start',
url: 'http://localhost:3000',
name: 'Frontend',
timeout: 120 * 1000,
reuseExistingServer: !process.env.CI,
},
{
command: 'npm run backend',
url: 'http://localhost:3333',
name: 'Backend',
timeout: 120 * 1000,
reuseExistingServer: !process.env.CI,
}

View File

@ -38,6 +38,7 @@ export default defineConfig({
| `stderr` | Whether to pipe the stderr of the command to the process stderr or ignore it. Defaults to `"pipe"`. |
| `timeout` | How long to wait for the process to start up and be available in milliseconds. Defaults to 60000. |
| `gracefulShutdown` | How to shut down the process. If unspecified, the process group is forcefully `SIGKILL`ed. If set to `{ signal: 'SIGTERM', timeout: 500 }`, the process group is sent a `SIGTERM` signal, followed by `SIGKILL` if it doesn't exit within 500ms. You can also use `SIGINT` as the signal instead. A `0` timeout means no `SIGKILL` will be sent. Windows doesn't support `SIGTERM` and `SIGINT` signals, so this option is ignored on Windows. Note that shutting down a Docker container requires `SIGTERM`. |
| `name` | Specifies a custom name for the web server. This name will be prefixed to log messages. Defaults to `[WebServer]`. |
## Adding a server timeout
@ -107,12 +108,14 @@ export default defineConfig({
{
command: 'npm run start',
url: 'http://localhost:3000',
name: 'Frontend',
timeout: 120 * 1000,
reuseExistingServer: !process.env.CI,
},
{
command: 'npm run backend',
url: 'http://localhost:3333',
name: 'Backend',
timeout: 120 * 1000,
reuseExistingServer: !process.env.CI,
}

View File

@ -37,6 +37,7 @@ export type WebServerPluginOptions = {
env?: { [key: string]: string; };
stdout?: 'pipe' | 'ignore';
stderr?: 'pipe' | 'ignore';
name?: string;
};
const DEFAULT_ENVIRONMENT_VARIABLES = {
@ -136,11 +137,11 @@ export class WebServerPlugin implements TestRunnerPlugin {
launchedProcess.stderr!.on('data', data => {
if (debugWebServer.enabled || (this._options.stderr === 'pipe' || !this._options.stderr))
this._reporter!.onStdErr?.(prefixOutputLines(data.toString()));
this._reporter!.onStdErr?.(prefixOutputLines(data.toString(), this._options.name));
});
launchedProcess.stdout!.on('data', data => {
if (debugWebServer.enabled || this._options.stdout === 'pipe')
this._reporter!.onStdOut?.(prefixOutputLines(data.toString()));
this._reporter!.onStdOut?.(prefixOutputLines(data.toString(), this._options.name));
});
}
@ -223,12 +224,12 @@ export const webServerPluginsForConfig = (config: FullConfigInternal): TestRunne
return webServerPlugins;
};
function prefixOutputLines(output: string) {
function prefixOutputLines(output: string, prefixName: string = 'WebServer'): string {
const lastIsNewLine = output[output.length - 1] === '\n';
let lines = output.split('\n');
if (lastIsNewLine)
lines.pop();
lines = lines.map(line => colors.dim('[WebServer] ') + line);
lines = lines.map(line => colors.dim(`[${prefixName}] `) + line);
if (lastIsNewLine)
lines.push('');
return lines.join('\n');

View File

@ -957,12 +957,14 @@ interface TestConfig<TestArgs = {}, WorkerArgs = {}> {
* {
* command: 'npm run start',
* url: 'http://localhost:3000',
* name: 'Frontend',
* timeout: 120 * 1000,
* reuseExistingServer: !process.env.CI,
* },
* {
* command: 'npm run backend',
* url: 'http://localhost:3333',
* name: 'Backend',
* timeout: 120 * 1000,
* reuseExistingServer: !process.env.CI,
* }
@ -9973,5 +9975,10 @@ interface TestConfigWebServer {
* checked. Either `port` or `url` should be specified.
*/
url?: string;
/**
* Specifies a custom name for the web server. This name will be prefixed to log messages. Defaults to `[WebServer]`.
*/
name?: string;
}

View File

@ -808,3 +808,59 @@ test.describe('gracefulShutdown option', () => {
expect(parseOutputLines(result).sort()).toEqual(['childprocess received SIGINT', 'webserver received SIGINT but stubbornly refuses to wind down']);
});
});
test.describe('name option', () => {
test('should use custom prefix', async ({ runInlineTest }, { workerIndex }) => {
const port = workerIndex * 2 + 10500;
const name1 = 'CustomName1';
const name2 = 'CustomName2';
const defaultPrefix = 'WebServer';
const result = await runInlineTest({
'test.spec.ts': `
import { test, expect } from '@playwright/test';
test('pass', async ({}) => {});
`,
'playwright.config.ts': `
module.exports = {
webServer: [
{
command: 'node ${JSON.stringify(SIMPLE_SERVER_PATH)} ${port}',
port: ${port},
name: '${name1}',
},
{
command: 'node ${JSON.stringify(SIMPLE_SERVER_PATH)} ${port + 1}',
port: ${port + 1},
name: '${name2}',
}
],
};
`,
}, undefined);
expect(result.exitCode).toBe(0);
expect(result.output).toContain(`[${name1}]`);
expect(result.output).toContain(`[${name2}]`);
expect(result.output).not.toContain(`[${defaultPrefix}]`);
});
test('should use default prefix when name option is not set', async ({ runInlineTest }, { workerIndex }) => {
const port = workerIndex * 2 + 10500;
const defaultPrefix = 'WebServer';
const result = await runInlineTest({
'test.spec.ts': `
import { test, expect } from '@playwright/test';
test('pass', async ({}) => {});
`,
'playwright.config.ts': `
module.exports = {
webServer: {
command: 'node ${JSON.stringify(SIMPLE_SERVER_PATH)} ${port}',
port: ${port},
},
};
`,
}, undefined);
expect(result.exitCode).toBe(0);
expect(result.output).toContain(`[${defaultPrefix}]`);
});
});