chore: headless mode for codegen (#12020)

This commit is contained in:
Pavel Feldman 2022-02-10 21:23:16 -08:00 коммит произвёл GitHub
Родитель 66b5cf5ae1
Коммит 5ab7bc3a59
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
2 изменённых файлов: 59 добавлений и 11 удалений

Просмотреть файл

@ -38,7 +38,18 @@ declare global {
}
}
export class RecorderApp extends EventEmitter {
export interface IRecorderApp extends EventEmitter {
close(): Promise<void>;
setPaused(paused: boolean): Promise<void>;
setMode(mode: 'none' | 'recording' | 'inspecting'): Promise<void>;
setFile(file: string): Promise<void>;
setSelector(selector: string, focus?: boolean): Promise<void>;
updateCallLogs(callLogs: CallLog[]): Promise<void>;
bringToFront(): void;
setSources(sources: Source[]): Promise<void>;
}
export class RecorderApp extends EventEmitter implements IRecorderApp {
private _page: Page;
readonly wsEndpoint: string | undefined;
@ -85,7 +96,9 @@ export class RecorderApp extends EventEmitter {
await mainFrame.goto(internalCallMetadata(), 'https://playwright/index.html');
}
static async open(sdkLanguage: string, headed: boolean): Promise<RecorderApp> {
static async open(sdkLanguage: string, headed: boolean): Promise<IRecorderApp> {
if (process.env.PW_CODEGEN_NO_INSPECTOR)
return new HeadlessRecorderApp();
const recorderPlaywright = (require('../../playwright').createPlaywright as typeof import('../../playwright').createPlaywright)('javascript', true);
const args = [
'--app=data:text/html,',
@ -163,3 +176,14 @@ export class RecorderApp extends EventEmitter {
await this._page.bringToFront();
}
}
class HeadlessRecorderApp extends EventEmitter implements IRecorderApp {
async close(): Promise<void> {}
async setPaused(paused: boolean): Promise<void> {}
async setMode(mode: 'none' | 'recording' | 'inspecting'): Promise<void> {}
async setFile(file: string): Promise<void> {}
async setSelector(selector: string, focus?: boolean): Promise<void> {}
async updateCallLogs(callLogs: CallLog[]): Promise<void> {}
bringToFront(): void {}
async setSources(sources: Source[]): Promise<void> {}
}

Просмотреть файл

@ -28,7 +28,7 @@ import { CSharpLanguageGenerator } from './recorder/csharp';
import { PythonLanguageGenerator } from './recorder/python';
import * as recorderSource from '../../generated/recorderSource';
import * as consoleApiSource from '../../generated/consoleApiSource';
import { RecorderApp } from './recorder/recorderApp';
import { IRecorderApp, RecorderApp } from './recorder/recorderApp';
import { CallMetadata, InstrumentationListener, SdkObject } from '../instrumentation';
import { Point } from '../../common/types';
import { CallLog, CallLogStatus, EventData, Mode, Source, UIState } from './recorder/recorderTypes';
@ -46,7 +46,7 @@ export class RecorderSupplement implements InstrumentationListener {
private _context: BrowserContext;
private _mode: Mode;
private _highlightedSelector = '';
private _recorderApp: RecorderApp | null = null;
private _recorderApp: IRecorderApp | null = null;
private _currentCallsMetadata = new Map<CallMetadata, SdkObject>();
private _recorderSources: Source[] = [];
private _userSources = new Map<string, Source>();
@ -317,7 +317,7 @@ class ContextRecorder extends EventEmitter {
this._recorderSources = [];
const generator = new CodeGenerator(context._browser.options.name, !!params.startRecording, params.launchOptions || {}, params.contextOptions || {}, params.device, params.saveStorage);
let text = '';
const throttledOutputFile = params.outputFile ? new ThrottledFile(params.outputFile) : null;
generator.on('change', () => {
this._recorderSources = [];
for (const languageGenerator of orderedLanguages) {
@ -330,21 +330,19 @@ class ContextRecorder extends EventEmitter {
source.revealLine = source.text.split('\n').length - 1;
this._recorderSources.push(source);
if (languageGenerator === orderedLanguages[0])
text = source.text;
throttledOutputFile?.setContent(source.text);
}
this.emit(ContextRecorder.Events.Change, {
sources: this._recorderSources,
primaryFileName: primaryLanguage.fileName
});
});
if (params.outputFile) {
if (throttledOutputFile) {
context.on(BrowserContext.Events.BeforeClose, () => {
fs.writeFileSync(params.outputFile!, text);
text = '';
throttledOutputFile.flush();
});
process.on('exit', () => {
if (text)
fs.writeFileSync(params.outputFile!, text);
throttledOutputFile.flush();
});
}
this._generator = generator;
@ -590,3 +588,29 @@ function languageForFile(file: string) {
return 'csharp';
return 'javascript';
}
class ThrottledFile {
private _file: string;
private _timer: NodeJS.Timeout | undefined;
private _text: string | undefined;
constructor(file: string) {
this._file = file;
}
setContent(text: string) {
this._text = text;
if (!this._timer)
this._timer = setTimeout(() => this.flush(), 1000);
}
flush(): void {
if (this._timer) {
clearTimeout(this._timer);
this._timer = undefined;
}
if (this._text)
fs.writeFileSync(this._file, this._text);
this._text = undefined;
}
}