Skip to content

Commit

Permalink
chore: make console stream live in ui mode (#26562)
Browse files Browse the repository at this point in the history
  • Loading branch information
pavelfeldman committed Aug 21, 2023
1 parent 32a309c commit f83d819
Show file tree
Hide file tree
Showing 9 changed files with 50 additions and 15 deletions.
9 changes: 7 additions & 2 deletions packages/playwright-core/src/client/tracing.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,15 @@ export class Tracing extends ChannelOwner<channels.TracingChannel> implements ap
super(parent, type, guid, initializer);
}

async start(options: { name?: string, title?: string, snapshots?: boolean, screenshots?: boolean, sources?: boolean } = {}) {
async start(options: { name?: string, title?: string, snapshots?: boolean, screenshots?: boolean, sources?: boolean, _live?: boolean } = {}) {
this._includeSources = !!options.sources;
const traceName = await this._wrapApiCall(async () => {
await this._channel.tracingStart(options);
await this._channel.tracingStart({
name: options.name,
snapshots: options.snapshots,
screenshots: options.screenshots,
live: options._live,
});
const response = await this._channel.tracingStartChunk({ name: options.name, title: options.title });
return response.traceName;
});
Expand Down
2 changes: 1 addition & 1 deletion packages/playwright-core/src/protocol/validator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2130,7 +2130,7 @@ scheme.TracingTracingStartParams = tObject({
name: tOptional(tString),
snapshots: tOptional(tBoolean),
screenshots: tOptional(tBoolean),
sources: tOptional(tBoolean),
live: tOptional(tBoolean),
});
scheme.TracingTracingStartResult = tOptional(tObject({}));
scheme.TracingTracingStartChunkParams = tObject({
Expand Down
5 changes: 3 additions & 2 deletions packages/playwright-core/src/server/trace/recorder/tracing.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ export type TracerOptions = {
name?: string;
snapshots?: boolean;
screenshots?: boolean;
live?: boolean;
};

type RecordingState = {
Expand Down Expand Up @@ -455,8 +456,8 @@ export class Tracing extends SdkObject implements InstrumentationListener, Snaps

private _appendTraceEvent(event: trace.TraceEvent) {
const visited = visitTraceEvent(event, this._state!.traceSha1s);
// Do not flush events, they are too noisy.
const flush = event.type !== 'event' && event.type !== 'object';
// Do not flush (console) events, they are too noisy, unless we are in ui mode (live).
const flush = this._state!.options.live || (event.type !== 'event' && event.type !== 'object');
this._fs.appendFile(this._state!.traceFile, JSON.stringify(visited) + '\n', flush);
}

Expand Down
4 changes: 2 additions & 2 deletions packages/playwright-test/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -526,7 +526,7 @@ class ArtifactsRecorder {
private _traceMode: TraceMode;
private _captureTrace = false;
private _screenshotOptions: { mode: ScreenshotMode } & Pick<playwrightLibrary.PageScreenshotOptions, 'fullPage' | 'omitBackground'> | undefined;
private _traceOptions: { screenshots: boolean, snapshots: boolean, sources: boolean, attachments: boolean, mode?: TraceMode };
private _traceOptions: { screenshots: boolean, snapshots: boolean, sources: boolean, attachments: boolean, _live: boolean, mode?: TraceMode };
private _temporaryTraceFiles: string[] = [];
private _temporaryScreenshots: string[] = [];
private _reusedContexts = new Set<BrowserContext>();
Expand All @@ -541,7 +541,7 @@ class ArtifactsRecorder {
this._screenshotMode = normalizeScreenshotMode(screenshot);
this._screenshotOptions = typeof screenshot === 'string' ? undefined : screenshot;
this._traceMode = normalizeTraceMode(trace);
const defaultTraceOptions = { screenshots: true, snapshots: true, sources: true, attachments: true };
const defaultTraceOptions = { screenshots: true, snapshots: true, sources: true, attachments: true, _live: false };
this._traceOptions = typeof trace === 'string' ? defaultTraceOptions : { ...defaultTraceOptions, ...trace, mode: undefined };
this._screenshottedSymbol = Symbol('screenshotted');
this._startedCollectingArtifacts = Symbol('startedCollectingArtifacts');
Expand Down
2 changes: 1 addition & 1 deletion packages/playwright-test/src/runner/uiMode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ class UIMode {
p.project.repeatEach = 1;
}
config.configCLIOverrides.use = config.configCLIOverrides.use || {};
config.configCLIOverrides.use.trace = { mode: 'on', sources: false };
config.configCLIOverrides.use.trace = { mode: 'on', sources: false, _live: true };

this._originalStdoutWrite = process.stdout.write;
this._originalStderrWrite = process.stderr.write;
Expand Down
4 changes: 2 additions & 2 deletions packages/protocol/src/channels.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3803,13 +3803,13 @@ export type TracingTracingStartParams = {
name?: string,
snapshots?: boolean,
screenshots?: boolean,
sources?: boolean,
live?: boolean,
};
export type TracingTracingStartOptions = {
name?: string,
snapshots?: boolean,
screenshots?: boolean,
sources?: boolean,
live?: boolean,
};
export type TracingTracingStartResult = void;
export type TracingTracingStartChunkParams = {
Expand Down
2 changes: 1 addition & 1 deletion packages/protocol/src/protocol.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3014,7 +3014,7 @@ Tracing:
name: string?
snapshots: boolean?
screenshots: boolean?
sources: boolean?
live: boolean?

tracingStartChunk:
parameters:
Expand Down
12 changes: 8 additions & 4 deletions packages/trace-viewer/src/ui/consoleTab.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -200,10 +200,14 @@ function format(args: { preview: string, value: any }[]): JSX.Element[] {
function parseCSSStyle(cssFormat: string): Record<string, string | number> {
try {
const styleObject: Record<string, string | number> = {};
const cssText = cssFormat.replace(/;$/, '').replace(/: /g, ':').replace(/; /g, ';');
const cssProperties = cssText.split(';');
for (const property of cssProperties) {
const [key, value] = property.split(':');
const cssProperties = cssFormat.split(';');
for (const token of cssProperties) {
const property = token.trim();
if (!property)
continue;
let [key, value] = property.split(':');
key = key.trim();
value = value.trim();
if (!supportProperty(key))
continue;
// cssProperties are background-color, JSDom ones are backgroundColor
Expand Down
25 changes: 25 additions & 0 deletions tests/playwright-test/ui-mode-test-output.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -151,3 +151,28 @@ test('should format console messages in page', async ({ runUITest }, testInfo) =
await expect(link).toHaveCSS('color', 'rgb(0, 0, 255)');
await expect(link).toHaveCSS('text-decoration', 'none solid rgb(0, 0, 255)');
});

test('should stream console messages live', async ({ runUITest }, testInfo) => {
const { page } = await runUITest({
'a.spec.ts': `
import { test, expect } from '@playwright/test';
test('print', async ({ page }) => {
await page.setContent('<button>Click me</button>');
const button = page.getByRole('button', { name: 'Click me' });
await button.evaluate(node => node.addEventListener('click', () => {
setTimeout(() => { console.log('I was clicked'); }, 1000);
}));
await button.click();
await page.locator('#not-there').waitFor();
});
`,
});
await page.getByTitle('Run all').click();
await page.getByText('Console').click();
await page.getByText('print').click();

await expect(page.locator('.console-tab .console-line-message')).toHaveText([
'I was clicked',
]);
await page.getByTitle('Stop').click();
});

0 comments on commit f83d819

Please sign in to comment.