Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 3 additions & 8 deletions packages/isomorphic/codegen/actions.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ export type NavigationSignal = BaseSignal & {

export type PopupSignal = BaseSignal & {
name: 'popup',
popupAlias: string,
popupPageGuid: string,
};

export type DownloadSignal = BaseSignal & {
Expand All @@ -163,20 +163,15 @@ export type ExpectSignal = BaseSignal & {

export type Signal = NavigationSignal | PopupSignal | DownloadSignal | DialogSignal | ExpectSignal;

export type FrameDescription = {
pageGuid: string;
pageAlias: string;
};

export type ActionInContext = {
frame: FrameDescription;
pageGuid: string;
action: Action;
startTime: number;
endTime?: number;
};

export type SignalInContext = {
frame: FrameDescription;
pageGuid: string;
signal: Signal;
timestamp: number;
};
34 changes: 21 additions & 13 deletions packages/isomorphic/codegen/csharp.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ export class CSharpLanguageGenerator implements LanguageGenerator {
name: string;
highlighter = 'csharp' as Language;
_mode: CSharpLanguageMode;
private _pageAliases = new Map<string, string>();

constructor(mode: CSharpLanguageMode) {
if (mode === 'library') {
Expand All @@ -51,6 +52,22 @@ export class CSharpLanguageGenerator implements LanguageGenerator {
this._mode = mode;
}

reset() {
this._pageAliases.clear();
}

private _pageAlias(pageGuid: string): string {
let alias = this._pageAliases.get(pageGuid);
if (!alias) {
alias = 'page' + (this._pageAliases.size || '');
// Outside of the library mode, the first page is a class member, the rest are local variables.
if (this._mode !== 'library' && alias === 'page')
alias = 'Page';
this._pageAliases.set(pageGuid, alias);
}
return alias;
}

generateAction(actionInContext: actions.ActionInContext, options: LanguageGeneratorOptions): string {
const action = this._generateActionInner(actionInContext, options);
if (action)
Expand All @@ -60,9 +77,10 @@ export class CSharpLanguageGenerator implements LanguageGenerator {

_generateActionInner(actionInContext: actions.ActionInContext, options: LanguageGeneratorOptions): string {
const action = actionInContext.action;
// Resolve before the early return, so that pages are named in the order they are opened.
const pageAlias = this._pageAlias(actionInContext.pageGuid);
if (this._mode !== 'library' && (action.name === 'openPage' || action.name === 'closePage'))
return '';
const pageAlias = this._formatPageAlias(actionInContext.frame.pageAlias);
const formatter = new CSharpFormatter(this._mode === 'library' ? 0 : 8);

if (action.name === 'openPage') {
Expand Down Expand Up @@ -94,7 +112,8 @@ export class CSharpLanguageGenerator implements LanguageGenerator {
}

if (signals.popup) {
lines.unshift(`var ${this._formatPageAlias(signals.popup.popupAlias)} = await ${pageAlias}.RunAndWaitForPopupAsync(async () =>\n{`);
const popupAlias = this._pageAlias(signals.popup.popupPageGuid);
lines.unshift(`var ${popupAlias} = await ${pageAlias}.RunAndWaitForPopupAsync(async () =>\n{`);
lines.push(`});`);
}

Expand All @@ -107,17 +126,6 @@ export class CSharpLanguageGenerator implements LanguageGenerator {
return formatter.format();
}

private _formatPageAlias(pageAlias: string): string {
if (this._mode === 'library')
return pageAlias;

if (pageAlias === 'page')
return 'Page'; // first page is class member

// other pages are local variables
return pageAlias;
}

private _generateActionCall(subject: string, actionInContext: actions.ActionInContext): string {
const action = actionInContext.action;
switch (action.name) {
Expand Down
20 changes: 18 additions & 2 deletions packages/isomorphic/codegen/java.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ export class JavaLanguageGenerator implements LanguageGenerator {
name: string;
highlighter = 'java' as Language;
_mode: JavaLanguageMode;
private _pageAliases = new Map<string, string>();

constructor(mode: JavaLanguageMode) {
if (mode === 'library') {
Expand All @@ -47,9 +48,23 @@ export class JavaLanguageGenerator implements LanguageGenerator {
this._mode = mode;
}

reset() {
this._pageAliases.clear();
}

private _pageAlias(pageGuid: string): string {
let alias = this._pageAliases.get(pageGuid);
if (!alias) {
alias = 'page' + (this._pageAliases.size || '');
this._pageAliases.set(pageGuid, alias);
}
return alias;
}

generateAction(actionInContext: actions.ActionInContext, options: LanguageGeneratorOptions): string {
const action = actionInContext.action;
const pageAlias = actionInContext.frame.pageAlias;
// Resolve before the early return, so that pages are named in the order they are opened.
const pageAlias = this._pageAlias(actionInContext.pageGuid);
const offset = this._mode === 'junit' ? 4 : 6;
const formatter = new JavaScriptFormatter(offset);

Expand All @@ -76,7 +91,8 @@ export class JavaLanguageGenerator implements LanguageGenerator {
let code = this._generateActionCall(subject, actionInContext);

if (signals.popup) {
code = `Page ${signals.popup.popupAlias} = ${pageAlias}.waitForPopup(() -> {
const popupAlias = this._pageAlias(signals.popup.popupPageGuid);
code = `Page ${popupAlias} = ${pageAlias}.waitForPopup(() -> {
${code}
});`;
}
Expand Down
26 changes: 21 additions & 5 deletions packages/isomorphic/codegen/javascript.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,19 +29,34 @@ export class JavaScriptLanguageGenerator implements LanguageGenerator {
name: string;
highlighter = 'javascript' as Language;
private _isTest: boolean;
private _pageAliases = new Map<string, string>();

constructor(isTest: boolean) {
this.id = isTest ? 'playwright-test' : 'javascript';
this.name = isTest ? 'Test Runner' : 'Library';
this._isTest = isTest;
}

reset() {
this._pageAliases.clear();
}

private _pageAlias(pageGuid: string): string {
let alias = this._pageAliases.get(pageGuid);
if (!alias) {
alias = 'page' + (this._pageAliases.size || '');
this._pageAliases.set(pageGuid, alias);
}
return alias;
}

generateAction(actionInContext: actions.ActionInContext, options: LanguageGeneratorOptions): string {
const action = actionInContext.action;
// Resolve before the early return, so that pages are named in the order they are opened.
const pageAlias = this._pageAlias(actionInContext.pageGuid);
if (this._isTest && (action.name === 'openPage' || action.name === 'closePage'))
return '';

const pageAlias = actionInContext.frame.pageAlias;
const formatter = new JavaScriptFormatter(2);

if (action.name === 'openPage') {
Expand All @@ -61,15 +76,16 @@ export class JavaScriptLanguageGenerator implements LanguageGenerator {
});`);
}

if (signals.popup)
formatter.add(`const ${signals.popup.popupAlias}Promise = ${pageAlias}.waitForEvent('popup');`);
const popupAlias = signals.popup ? this._pageAlias(signals.popup.popupPageGuid) : undefined;
if (popupAlias)
formatter.add(`const ${popupAlias}Promise = ${pageAlias}.waitForEvent('popup');`);
if (signals.download)
formatter.add(`const download${signals.download.downloadAlias}Promise = ${pageAlias}.waitForEvent('download');`);

formatter.add(this._generateActionCall(subject, actionInContext));

if (signals.popup)
formatter.add(`const ${signals.popup.popupAlias} = await ${signals.popup.popupAlias}Promise;`);
if (popupAlias)
formatter.add(`const ${popupAlias} = await ${popupAlias}Promise;`);
if (signals.download)
formatter.add(`const download${signals.download.downloadAlias} = await download${signals.download.downloadAlias}Promise;`);
if (options.generateExpectSignal && signals.expect)
Expand Down
5 changes: 4 additions & 1 deletion packages/isomorphic/codegen/jsonl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,14 @@ export class JsonlLanguageGenerator implements LanguageGenerator {
name = 'JSONL';
highlighter = 'javascript' as Language;

reset() {
}

generateAction(actionInContext: actions.ActionInContext, options: LanguageGeneratorOptions): string {
const locator = (actionInContext.action as any).selector ? JSON.parse(asLocator('jsonl', (actionInContext.action as any).selector)) : undefined;
const entry = {
...actionInContext.action,
...actionInContext.frame,
pageGuid: actionInContext.pageGuid,
locator,
ariaSnapshot: undefined,
};
Expand Down
3 changes: 2 additions & 1 deletion packages/isomorphic/codegen/language.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import type { LanguageGenerator, LanguageGeneratorOptions } from './types';
import type * as actions from './actions';

export function generateCode(actions: actions.ActionInContext[], languageGenerator: LanguageGenerator, options: LanguageGeneratorOptions) {
languageGenerator.reset();
const header = languageGenerator.generateHeader(options);
const footer = languageGenerator.generateFooter(options.saveStorage);
const actionTexts = actions.map(a => languageGenerator.generateAction(a, options)).filter(Boolean);
Expand All @@ -29,7 +30,7 @@ export function generateCode(actions: actions.ActionInContext[], languageGenerat

export function expectSignalAction(actionInContext: actions.ActionInContext, signal: actions.ExpectSignal): actions.ActionInContext {
return {
frame: actionInContext.frame,
pageGuid: actionInContext.pageGuid,
startTime: actionInContext.startTime,
endTime: actionInContext.startTime,
action: {
Expand Down
22 changes: 19 additions & 3 deletions packages/isomorphic/codegen/python.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ export class PythonLanguageGenerator implements LanguageGenerator {
private _asyncPrefix: '' | 'async ';
private _isAsync: boolean;
private _isPyTest: boolean;
private _pageAliases = new Map<string, string>();

constructor(isAsync: boolean, isPyTest: boolean) {
this.id = isPyTest ? 'python-pytest' : (isAsync ? 'python-async' : 'python');
Expand All @@ -43,12 +44,26 @@ export class PythonLanguageGenerator implements LanguageGenerator {
this._asyncPrefix = isAsync ? 'async ' : '';
}

reset() {
this._pageAliases.clear();
}

private _pageAlias(pageGuid: string): string {
let alias = this._pageAliases.get(pageGuid);
if (!alias) {
alias = 'page' + (this._pageAliases.size || '');
this._pageAliases.set(pageGuid, alias);
}
return alias;
}

generateAction(actionInContext: actions.ActionInContext, options: LanguageGeneratorOptions): string {
const action = actionInContext.action;
// Resolve before the early return, so that pages are named in the order they are opened.
const pageAlias = this._pageAlias(actionInContext.pageGuid);
if (this._isPyTest && (action.name === 'openPage' || action.name === 'closePage'))
return '';

const pageAlias = actionInContext.frame.pageAlias;
const formatter = new PythonFormatter(4);

if (action.name === 'openPage') {
Expand All @@ -67,10 +82,11 @@ export class PythonLanguageGenerator implements LanguageGenerator {
let code = `${this._awaitPrefix}${this._generateActionCall(subject, actionInContext)}`;

if (signals.popup) {
code = `${this._asyncPrefix}with ${pageAlias}.expect_popup() as ${signals.popup.popupAlias}_info {
const popupAlias = this._pageAlias(signals.popup.popupPageGuid);
code = `${this._asyncPrefix}with ${pageAlias}.expect_popup() as ${popupAlias}_info {
${code}
}
${signals.popup.popupAlias} = ${this._awaitPrefix}${signals.popup.popupAlias}_info.value`;
${popupAlias} = ${this._awaitPrefix}${popupAlias}_info.value`;
}

if (signals.download) {
Expand Down
1 change: 1 addition & 0 deletions packages/isomorphic/codegen/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ export interface LanguageGenerator {
groupName: string;
name: string;
highlighter: Language;
reset(): void;
generateHeader(options: LanguageGeneratorOptions): string;
generateAction(actionInContext: actions.ActionInContext, options: LanguageGeneratorOptions): string;
generateFooter(saveStorage: string | undefined): string;
Expand Down
2 changes: 1 addition & 1 deletion packages/playwright-core/src/server/debugController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -213,7 +213,7 @@ function wireListeners(recorder: Recorder, debugController: DebugController) {
actionsChanged();
});
recorder.on(RecorderEvent.SignalAdded, (signal: actions.SignalInContext) => {
const lastAction = actions.findLast(a => a.frame.pageGuid === signal.frame.pageGuid);
const lastAction = actions.findLast(a => a.pageGuid === signal.pageGuid);
if (lastAction)
lastAction.action.signals.push(signal.signal);
actionsChanged();
Expand Down
Loading
Loading