chore: plumb terminal size and port language (#5149)
This commit is contained in:
parent
5033261d27
commit
45f7d73470
|
|
@ -327,7 +327,15 @@ async function codegen(options: Options, url: string | undefined, language: stri
|
||||||
const { context, launchOptions, contextOptions } = await launchContext(options, false);
|
const { context, launchOptions, contextOptions } = await launchContext(options, false);
|
||||||
if (process.env.PWTRACE)
|
if (process.env.PWTRACE)
|
||||||
contextOptions._traceDir = path.join(process.cwd(), '.trace');
|
contextOptions._traceDir = path.join(process.cwd(), '.trace');
|
||||||
await context._enableRecorder(language, launchOptions, contextOptions, options.device, options.saveStorage, !!process.stdout.columns, outputFile ? path.resolve(outputFile) : undefined);
|
await context._enableRecorder({
|
||||||
|
language,
|
||||||
|
launchOptions,
|
||||||
|
contextOptions,
|
||||||
|
device: options.device,
|
||||||
|
saveStorage: options.saveStorage,
|
||||||
|
terminal: !!process.stdout.columns,
|
||||||
|
outputFile: outputFile ? path.resolve(outputFile) : undefined
|
||||||
|
});
|
||||||
await openPage(context, url);
|
await openPage(context, url);
|
||||||
if (process.env.PWCLI_EXIT_FOR_TEST)
|
if (process.env.PWCLI_EXIT_FOR_TEST)
|
||||||
await Promise.all(context.pages().map(p => p.close()));
|
await Promise.all(context.pages().map(p => p.close()));
|
||||||
|
|
|
||||||
|
|
@ -270,23 +270,16 @@ export class BrowserContext extends ChannelOwner<channels.BrowserContextChannel,
|
||||||
await this._channel.consoleSupplementExpose();
|
await this._channel.consoleSupplementExpose();
|
||||||
}
|
}
|
||||||
|
|
||||||
async _enableRecorder(
|
async _enableRecorder(params: {
|
||||||
language: string,
|
language: string,
|
||||||
launchOptions?: LaunchOptions,
|
launchOptions?: LaunchOptions,
|
||||||
contextOptions?: BrowserContextOptions,
|
contextOptions?: BrowserContextOptions,
|
||||||
device?: string,
|
device?: string,
|
||||||
saveStorage?: string,
|
saveStorage?: string,
|
||||||
terminal?: boolean,
|
terminal?: boolean,
|
||||||
outputFile?: string) {
|
outputFile?: string
|
||||||
await this._channel.recorderSupplementEnable({
|
}) {
|
||||||
language,
|
await this._channel.recorderSupplementEnable(params);
|
||||||
launchOptions,
|
|
||||||
contextOptions,
|
|
||||||
device,
|
|
||||||
saveStorage,
|
|
||||||
terminal,
|
|
||||||
outputFile,
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,7 @@ declare global {
|
||||||
playwrightRecorderPerformAction: (action: actions.Action) => Promise<void>;
|
playwrightRecorderPerformAction: (action: actions.Action) => Promise<void>;
|
||||||
playwrightRecorderRecordAction: (action: actions.Action) => Promise<void>;
|
playwrightRecorderRecordAction: (action: actions.Action) => Promise<void>;
|
||||||
playwrightRecorderCommitAction: () => Promise<void>;
|
playwrightRecorderCommitAction: () => Promise<void>;
|
||||||
playwrightRecorderState: () => Promise<{ state: any, paused: boolean, tool: 'codegen' | 'pause' }>;
|
playwrightRecorderState: () => Promise<{ state: any, paused: boolean, app: 'codegen' | 'debug' | 'pause' }>;
|
||||||
playwrightRecorderSetState: (state: any) => Promise<void>;
|
playwrightRecorderSetState: (state: any) => Promise<void>;
|
||||||
playwrightRecorderResume: () => Promise<boolean>;
|
playwrightRecorderResume: () => Promise<boolean>;
|
||||||
}
|
}
|
||||||
|
|
@ -51,7 +51,7 @@ export class Recorder {
|
||||||
private _recordElement: HTMLElement;
|
private _recordElement: HTMLElement;
|
||||||
private _resumeElement: HTMLElement;
|
private _resumeElement: HTMLElement;
|
||||||
private _mode: 'inspecting' | 'recording' | 'none' = 'none';
|
private _mode: 'inspecting' | 'recording' | 'none' = 'none';
|
||||||
private _tool: 'codegen' | 'pause' = 'pause';
|
private _app: 'codegen' | 'debug' | 'pause' = 'debug';
|
||||||
private _paused = false;
|
private _paused = false;
|
||||||
|
|
||||||
constructor(injectedScript: InjectedScript) {
|
constructor(injectedScript: InjectedScript) {
|
||||||
|
|
@ -130,7 +130,7 @@ export class Recorder {
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" height="24" width="24"><path d="M24 24H0V0h24v24z" fill="none"/><circle cx="12" cy="12" r="8"/></svg>
|
<svg xmlns="http://www.w3.org/2000/svg" height="24" width="24"><path d="M24 24H0V0h24v24z" fill="none"/><circle cx="12" cy="12" r="8"/></svg>
|
||||||
</x-pw-button>`;
|
</x-pw-button>`;
|
||||||
this._resumeElement = html`
|
this._resumeElement = html`
|
||||||
<x-pw-button tabIndex=0 class="playwright-resume">
|
<x-pw-button tabIndex=0 class="playwright-resume hidden">
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" height="24" width="24"><path d="M0 0h24v24H0z" fill="none"/><path d="M8 5v14l11-7z"/></svg>
|
<svg xmlns="http://www.w3.org/2000/svg" height="24" width="24"><path d="M0 0h24v24H0z" fill="none"/><path d="M8 5v14l11-7z"/></svg>
|
||||||
</x-pw-button>`;
|
</x-pw-button>`;
|
||||||
|
|
||||||
|
|
@ -180,6 +180,9 @@ export class Recorder {
|
||||||
x-pw-button.hidden {
|
x-pw-button.hidden {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
x-pw-button svg {
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
</style>`);
|
</style>`);
|
||||||
|
|
||||||
const iconElement = html`<x-pw-button class="logo" tabIndex=0 style="background-size: 32px 32px;"></x-pw-button>`;
|
const iconElement = html`<x-pw-button class="logo" tabIndex=0 style="background-size: 32px 32px;"></x-pw-button>`;
|
||||||
|
|
@ -244,7 +247,7 @@ export class Recorder {
|
||||||
clearTimeout(this._pollRecorderModeTimer);
|
clearTimeout(this._pollRecorderModeTimer);
|
||||||
const result = await window.playwrightRecorderState().catch(e => null);
|
const result = await window.playwrightRecorderState().catch(e => null);
|
||||||
if (result) {
|
if (result) {
|
||||||
const { state, paused, tool } = result;
|
const { state, paused, app } = result;
|
||||||
if (state && state.mode !== this._mode) {
|
if (state && state.mode !== this._mode) {
|
||||||
this._mode = state.mode as any;
|
this._mode = state.mode as any;
|
||||||
this._inspectElement.classList.toggle('toggled', this._mode === 'inspecting');
|
this._inspectElement.classList.toggle('toggled', this._mode === 'inspecting');
|
||||||
|
|
@ -255,11 +258,12 @@ export class Recorder {
|
||||||
}
|
}
|
||||||
if (paused !== this._paused) {
|
if (paused !== this._paused) {
|
||||||
this._paused = paused;
|
this._paused = paused;
|
||||||
|
this._resumeElement.classList.toggle('hidden', false);
|
||||||
this._resumeElement.classList.toggle('disabled', !this._paused);
|
this._resumeElement.classList.toggle('disabled', !this._paused);
|
||||||
}
|
}
|
||||||
if (tool !== this._tool) {
|
if (app !== this._app) {
|
||||||
this._tool = tool;
|
this._app = app;
|
||||||
this._resumeElement.classList.toggle('hidden', this._tool !== 'pause');
|
this._resumeElement.classList.toggle('hidden', this._app !== 'pause');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this._pollRecorderModeTimer = setTimeout(() => this._pollRecorderMode(), 250);
|
this._pollRecorderModeTimer = setTimeout(() => this._pollRecorderMode(), 250);
|
||||||
|
|
@ -295,6 +299,8 @@ export class Recorder {
|
||||||
}
|
}
|
||||||
|
|
||||||
private _onClick(event: MouseEvent) {
|
private _onClick(event: MouseEvent) {
|
||||||
|
if (this._mode === 'inspecting' && !this._isInToolbar(event.target as HTMLElement))
|
||||||
|
console.log(this._hoveredModel ? this._hoveredModel.selector : ''); // eslint-disable-line no-console
|
||||||
if (this._shouldIgnoreMouseEvent(event))
|
if (this._shouldIgnoreMouseEvent(event))
|
||||||
return;
|
return;
|
||||||
if (this._actionInProgress(event))
|
if (this._actionInProgress(event))
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,9 @@
|
||||||
import { BrowserContext, ContextListener, contextListeners } from '../browserContext';
|
import { BrowserContext, ContextListener, contextListeners } from '../browserContext';
|
||||||
import { isDebugMode } from '../../utils/utils';
|
import { isDebugMode } from '../../utils/utils';
|
||||||
import { ConsoleApiSupplement } from './consoleApiSupplement';
|
import { ConsoleApiSupplement } from './consoleApiSupplement';
|
||||||
|
import { RecorderSupplement } from './recorderSupplement';
|
||||||
|
import { Page } from '../page';
|
||||||
|
import { ConsoleMessage } from '../console';
|
||||||
|
|
||||||
export function installInspectorController() {
|
export function installInspectorController() {
|
||||||
contextListeners.add(new InspectorController());
|
contextListeners.add(new InspectorController());
|
||||||
|
|
@ -27,6 +30,13 @@ class InspectorController implements ContextListener {
|
||||||
if (isDebugMode()) {
|
if (isDebugMode()) {
|
||||||
const consoleApi = new ConsoleApiSupplement(context);
|
const consoleApi = new ConsoleApiSupplement(context);
|
||||||
await consoleApi.install();
|
await consoleApi.install();
|
||||||
|
RecorderSupplement.getOrCreate(context, 'debug', {
|
||||||
|
language: 'javascript',
|
||||||
|
terminal: true,
|
||||||
|
});
|
||||||
|
context.on(BrowserContext.Events.Page, (page: Page) => {
|
||||||
|
page.on(Page.Events.Console, (message: ConsoleMessage) => context.emit(BrowserContext.Events.StdOut, message.text() + '\n'));
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
async onContextWillDestroy(context: BrowserContext): Promise<void> {}
|
async onContextWillDestroy(context: BrowserContext): Promise<void> {}
|
||||||
|
|
|
||||||
|
|
@ -31,7 +31,7 @@ import * as consoleApiSource from '../../generated/consoleApiSource';
|
||||||
import { FileOutput, FlushingTerminalOutput, OutputMultiplexer, RecorderOutput, TerminalOutput, Writable } from './recorder/outputs';
|
import { FileOutput, FlushingTerminalOutput, OutputMultiplexer, RecorderOutput, TerminalOutput, Writable } from './recorder/outputs';
|
||||||
|
|
||||||
type BindingSource = { frame: Frame, page: Page };
|
type BindingSource = { frame: Frame, page: Page };
|
||||||
type Tool = 'codegen' | 'pause';
|
type App = 'codegen' | 'debug' | 'pause';
|
||||||
type Mode = 'inspecting' | 'recording' | 'none';
|
type Mode = 'inspecting' | 'recording' | 'none';
|
||||||
|
|
||||||
const symbol = Symbol('RecorderSupplement');
|
const symbol = Symbol('RecorderSupplement');
|
||||||
|
|
@ -47,23 +47,23 @@ export class RecorderSupplement {
|
||||||
private _resumeCallback: (() => void) | null = null;
|
private _resumeCallback: (() => void) | null = null;
|
||||||
private _recorderState: { mode: Mode };
|
private _recorderState: { mode: Mode };
|
||||||
private _paused = false;
|
private _paused = false;
|
||||||
private _tool: Tool;
|
private _app: App;
|
||||||
private _output: OutputMultiplexer;
|
private _output: OutputMultiplexer;
|
||||||
|
|
||||||
static getOrCreate(context: BrowserContext, tool: Tool, params: channels.BrowserContextRecorderSupplementEnableParams): Promise<RecorderSupplement> {
|
static getOrCreate(context: BrowserContext, app: App, params: channels.BrowserContextRecorderSupplementEnableParams): Promise<RecorderSupplement> {
|
||||||
let recorderPromise = (context as any)[symbol] as Promise<RecorderSupplement>;
|
let recorderPromise = (context as any)[symbol] as Promise<RecorderSupplement>;
|
||||||
if (!recorderPromise) {
|
if (!recorderPromise) {
|
||||||
const recorder = new RecorderSupplement(context, tool, params);
|
const recorder = new RecorderSupplement(context, app, params);
|
||||||
recorderPromise = recorder.install().then(() => recorder);
|
recorderPromise = recorder.install().then(() => recorder);
|
||||||
(context as any)[symbol] = recorderPromise;
|
(context as any)[symbol] = recorderPromise;
|
||||||
}
|
}
|
||||||
return recorderPromise;
|
return recorderPromise;
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor(context: BrowserContext, tool: Tool, params: channels.BrowserContextRecorderSupplementEnableParams) {
|
constructor(context: BrowserContext, app: App, params: channels.BrowserContextRecorderSupplementEnableParams) {
|
||||||
this._context = context;
|
this._context = context;
|
||||||
this._tool = tool;
|
this._app = app;
|
||||||
this._recorderState = { mode: tool === 'codegen' ? 'recording' : 'none' };
|
this._recorderState = { mode: app === 'codegen' ? 'recording' : 'none' };
|
||||||
let languageGenerator: LanguageGenerator;
|
let languageGenerator: LanguageGenerator;
|
||||||
switch (params.language) {
|
switch (params.language) {
|
||||||
case 'javascript': languageGenerator = new JavaScriptLanguageGenerator(); break;
|
case 'javascript': languageGenerator = new JavaScriptLanguageGenerator(); break;
|
||||||
|
|
@ -83,10 +83,10 @@ export class RecorderSupplement {
|
||||||
if (params.outputFile)
|
if (params.outputFile)
|
||||||
outputs.push(new FileOutput(params.outputFile));
|
outputs.push(new FileOutput(params.outputFile));
|
||||||
this._output = new OutputMultiplexer(outputs);
|
this._output = new OutputMultiplexer(outputs);
|
||||||
this._output.setEnabled(tool === 'codegen');
|
this._output.setEnabled(app === 'codegen');
|
||||||
context.on(BrowserContext.Events.BeforeClose, () => this._output.flush());
|
context.on(BrowserContext.Events.BeforeClose, () => this._output.flush());
|
||||||
|
|
||||||
const generator = new CodeGenerator(context._browser._options.name, tool === 'codegen', params.launchOptions || {}, params.contextOptions || {}, this._output, languageGenerator, params.device, params.saveStorage);
|
const generator = new CodeGenerator(context._browser._options.name, app === 'codegen', params.launchOptions || {}, params.contextOptions || {}, this._output, languageGenerator, params.device, params.saveStorage);
|
||||||
this._generator = generator;
|
this._generator = generator;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -117,7 +117,7 @@ export class RecorderSupplement {
|
||||||
await this._context.exposeBinding('playwrightRecorderState', false, () => {
|
await this._context.exposeBinding('playwrightRecorderState', false, () => {
|
||||||
return {
|
return {
|
||||||
state: this._recorderState,
|
state: this._recorderState,
|
||||||
tool: this._tool,
|
app: this._app,
|
||||||
paused: this._paused
|
paused: this._paused
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -39,7 +39,7 @@ fixtures.contextWrapper.init(async ({ browser }, runTest) => {
|
||||||
const context = await browser.newContext() as BrowserContext;
|
const context = await browser.newContext() as BrowserContext;
|
||||||
const outputBuffer = new WritableBuffer();
|
const outputBuffer = new WritableBuffer();
|
||||||
(context as any)._stdout = outputBuffer;
|
(context as any)._stdout = outputBuffer;
|
||||||
await (context as any)._enableRecorder('javascript');
|
await (context as any)._enableRecorder({ language: 'javascript' });
|
||||||
await runTest({ context, output: outputBuffer });
|
await runTest({ context, output: outputBuffer });
|
||||||
await context.close();
|
await context.close();
|
||||||
});
|
});
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue