feat(test runner): allow stopping testrun with escape
This commit is contained in:
parent
d1926e2f9b
commit
382f41d89e
|
|
@ -28,6 +28,7 @@ import { EventEmitter } from 'stream';
|
||||||
import { type TestServerTransport, TestServerConnection } from '../isomorphic/testServerConnection';
|
import { type TestServerTransport, TestServerConnection } from '../isomorphic/testServerConnection';
|
||||||
import { TeleSuiteUpdater } from '../isomorphic/teleSuiteUpdater';
|
import { TeleSuiteUpdater } from '../isomorphic/teleSuiteUpdater';
|
||||||
import { restartWithExperimentalTsEsm } from '../common/configLoader';
|
import { restartWithExperimentalTsEsm } from '../common/configLoader';
|
||||||
|
import type { Disposable } from '../isomorphic/events';
|
||||||
|
|
||||||
class InMemoryTransport extends EventEmitter implements TestServerTransport {
|
class InMemoryTransport extends EventEmitter implements TestServerTransport {
|
||||||
public readonly _send: (data: string) => void;
|
public readonly _send: (data: string) => void;
|
||||||
|
|
@ -251,12 +252,37 @@ export async function runWatchModeLoop(configLocation: ConfigLocation, initialOp
|
||||||
return result === 'passed' ? teardown.status : result;
|
return result === 'passed' ? teardown.status : result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function readKeyPress(handler: (text: string, key: any) => void): Disposable {
|
||||||
|
const rl = readline.createInterface({ input: process.stdin, escapeCodeTimeout: 50 });
|
||||||
|
readline.emitKeypressEvents(process.stdin, rl);
|
||||||
|
if (process.stdin.isTTY)
|
||||||
|
process.stdin.setRawMode(true);
|
||||||
|
|
||||||
|
process.stdin.on('keypress', handler);
|
||||||
|
|
||||||
|
return {
|
||||||
|
dispose: () => {
|
||||||
|
process.stdin.off('keypress', handler);
|
||||||
|
rl.close();
|
||||||
|
if (process.stdin.isTTY)
|
||||||
|
process.stdin.setRawMode(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const isInterrupt = (text: string, key: any) => text === '\x03' || text === '\x1B' || (key && key.name === 'escape') || (key && key.ctrl && key.name === 'c');
|
||||||
|
|
||||||
async function runTests(watchOptions: WatchModeOptions, testServerConnection: TestServerConnection, options?: {
|
async function runTests(watchOptions: WatchModeOptions, testServerConnection: TestServerConnection, options?: {
|
||||||
title?: string,
|
title?: string,
|
||||||
testIds?: string[],
|
testIds?: string[],
|
||||||
}) {
|
}) {
|
||||||
printConfiguration(watchOptions, options?.title);
|
printConfiguration(watchOptions, options?.title);
|
||||||
|
|
||||||
|
const reader = readKeyPress((text: string, key: any) => {
|
||||||
|
if (isInterrupt(text, key))
|
||||||
|
testServerConnection.stopTestsNoReply({});
|
||||||
|
});
|
||||||
|
|
||||||
await testServerConnection.runTests({
|
await testServerConnection.runTests({
|
||||||
grep: watchOptions.grep,
|
grep: watchOptions.grep,
|
||||||
testIds: options?.testIds,
|
testIds: options?.testIds,
|
||||||
|
|
@ -266,18 +292,14 @@ async function runTests(watchOptions: WatchModeOptions, testServerConnection: Te
|
||||||
reuseContext: connectWsEndpoint ? true : undefined,
|
reuseContext: connectWsEndpoint ? true : undefined,
|
||||||
workers: connectWsEndpoint ? 1 : undefined,
|
workers: connectWsEndpoint ? 1 : undefined,
|
||||||
headed: connectWsEndpoint ? true : undefined,
|
headed: connectWsEndpoint ? true : undefined,
|
||||||
});
|
}).finally(reader.dispose);
|
||||||
}
|
}
|
||||||
|
|
||||||
function readCommand(): ManualPromise<Command> {
|
function readCommand(): ManualPromise<Command> {
|
||||||
const result = new ManualPromise<Command>();
|
const result = new ManualPromise<Command>();
|
||||||
const rl = readline.createInterface({ input: process.stdin, escapeCodeTimeout: 50 });
|
|
||||||
readline.emitKeypressEvents(process.stdin, rl);
|
|
||||||
if (process.stdin.isTTY)
|
|
||||||
process.stdin.setRawMode(true);
|
|
||||||
|
|
||||||
const handler = (text: string, key: any) => {
|
const reader = readKeyPress((text: string, key: any) => {
|
||||||
if (text === '\x03' || text === '\x1B' || (key && key.name === 'escape') || (key && key.ctrl && key.name === 'c')) {
|
if (isInterrupt(text, key)) {
|
||||||
result.resolve('interrupted');
|
result.resolve('interrupted');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -316,15 +338,9 @@ Change settings
|
||||||
case 'f': result.resolve('failed'); break;
|
case 'f': result.resolve('failed'); break;
|
||||||
case 's': result.resolve('toggle-show-browser'); break;
|
case 's': result.resolve('toggle-show-browser'); break;
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
process.stdin.on('keypress', handler);
|
|
||||||
void result.finally(() => {
|
|
||||||
process.stdin.off('keypress', handler);
|
|
||||||
rl.close();
|
|
||||||
if (process.stdin.isTTY)
|
|
||||||
process.stdin.setRawMode(false);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
void result.finally(reader.dispose);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -814,3 +814,23 @@ test('should run global teardown before exiting', async ({ runWatchTest }) => {
|
||||||
testProcess.write('\x1B');
|
testProcess.write('\x1B');
|
||||||
await testProcess.waitForOutput('running teardown');
|
await testProcess.waitForOutput('running teardown');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('should stop testrun on pressing escape', async ({ runWatchTest }) => {
|
||||||
|
const testProcess = await runWatchTest({
|
||||||
|
'a.test.ts': `
|
||||||
|
import { test, expect } from '@playwright/test';
|
||||||
|
test('stalls', async () => {
|
||||||
|
await new Promise(() => {});
|
||||||
|
});
|
||||||
|
`,
|
||||||
|
});
|
||||||
|
// add once https://github.com/microsoft/playwright/pull/32583 lands
|
||||||
|
// await testProcess.waitForOutput('Waiting for file changes.');
|
||||||
|
// testProcess.clearOutput();
|
||||||
|
// testProcess.write('\r\n');
|
||||||
|
|
||||||
|
await testProcess.waitForOutput('Running 1 test');
|
||||||
|
await timers.setTimeout(500);
|
||||||
|
testProcess.write('\x1B');
|
||||||
|
await testProcess.waitForOutput('1 interrupted');
|
||||||
|
});
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue