Skip to content

Commit

Permalink
fix: adjust playwright-crx to playrwight 1.50
Browse files Browse the repository at this point in the history
  • Loading branch information
ruifigueira committed Jan 19, 2025
1 parent 8280aeb commit 9db1a3a
Show file tree
Hide file tree
Showing 7 changed files with 488 additions and 61 deletions.
29 changes: 13 additions & 16 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ clientConnection.onmessage = message => setImmediate(() => dispatcherConnection.
clientConnection.toImpl = (x: any) => x ? dispatcherConnection._dispatchers.get(x._guid)!._object : dispatcherConnection._dispatchers.get('');
(playwrightAPI as any)._toImpl = clientConnection.toImpl;

export const { _crx: crx, selectors } = playwrightAPI;
export const { _crx: crx, selectors, errors } = playwrightAPI;
export default playwrightAPI;

wrapClientApis();
8 changes: 4 additions & 4 deletions src/server/crx.ts
Original file line number Diff line number Diff line change
Expand Up @@ -236,7 +236,7 @@ export class CrxApplication extends SdkObject {
}

tabIdForPage(page: Page) {
const targetId = this._crPages().find(crPage => crPage._initializedPage === page)?._targetId;
const targetId = this._crPages().find(crPage => crPage._page === page)?._targetId;
if (!targetId)
return;

Expand All @@ -251,7 +251,7 @@ export class CrxApplication extends SdkObject {
mode: mode === 'none' ? undefined : mode,
...otherOptions
};
Recorder.show('actions', this._context, recorder => this._createRecorderApp(recorder), recorderParams);
Recorder.show(this._context, recorder => this._createRecorderApp(recorder), recorderParams);
}

await this._recorderApp!.open(options);
Expand All @@ -275,7 +275,7 @@ export class CrxApplication extends SdkObject {
}
const crPage = this._crPageByTargetId(targetId);
assert(crPage);
const pageOrError = await crPage.pageOrError();
const pageOrError = await crPage._page.waitForInitializedOrError();
if (pageOrError instanceof Error)
throw pageOrError;
return pageOrError;
Expand Down Expand Up @@ -389,7 +389,7 @@ export class CrxApplication extends SdkObject {
if (!crPage)
return;

const pageOrError = await crPage.pageOrError();
const pageOrError = await crPage._page.waitForInitializedOrError();
if (pageOrError instanceof Error)
throw pageOrError;

Expand Down
19 changes: 9 additions & 10 deletions src/server/recorder/crxPlayer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,15 +21,17 @@ import { createGuid, isUnderTest, ManualPromise, monotonicTime, serializeExpecte
import type { Frame } from 'playwright-core/lib/server/frames';
import type { CallMetadata } from '@protocol/callMetadata';
import { serializeError } from 'playwright-core/lib/server/errors';
import { buildFullSelector, traceParamsForAction } from 'playwright-core/lib/utils/isomorphic/recorderUtils';
import { buildFullSelector } from 'playwright-core/lib/server/recorder/recorderUtils';
import { toKeyboardModifiers } from 'playwright-core/lib/server/codegen/language';
import type { ActionInContextWithLocation, Location } from './parser';
import type { ActionInContext, FrameDescription } from '@recorder/actions';
import { toClickOptions } from 'playwright-core/lib/server/recorder/recorderRunner';
import { parseAriaSnapshot } from 'playwright-core/lib/server/ariaSnapshot';
import { parseAriaSnapshotUnsafe } from 'playwright-core/lib/utils/isomorphic/ariaSnapshot';
import { serverSideCallMetadata } from 'playwright-core/lib/server';
import type { Crx } from '../crx';
import type { InstrumentationListener } from 'playwright-core/lib/server/instrumentation';
import { traceParamsForAction } from './recorderUtils';
import { yaml } from 'playwright-core/lib/utilsBundle';

class Stopped extends Error {}

Expand Down Expand Up @@ -148,14 +150,10 @@ export default class CrxPlayer extends EventEmitter {
const innerPerformAction = async (mainFrame: Frame | null, actionInContext: PerformAction, cb: (callMetadata: CallMetadata) => Promise<any>): Promise<void> => {
// we must use the default browser context here!
const context = mainFrame ?? browserContext;
let traceParams: ReturnType<typeof traceParamsForAction>;

switch (actionInContext.action.name) {
case 'pause': traceParams = { method: 'pause', params: {}, apiName: 'page.pause' }; break;
case 'openPage': traceParams = { method: 'newPage', params: {}, apiName: 'browserContext.newPage' }; break;
case 'closePage': traceParams = { method: 'close', params: {}, apiName: 'page.close' }; break;
default: traceParams = traceParamsForAction(actionInContext as ActionInContext); break;
}
const traceParams = actionInContext.action.name === 'pause' ?
{ method: 'pause', params: {}, apiName: 'page.pause' } :
traceParamsForAction(actionInContext as ActionInContext);

const callMetadata: CallMetadata = {
id: `call@${createGuid()}`,
Expand Down Expand Up @@ -257,6 +255,7 @@ export default class CrxPlayer extends EventEmitter {
return await innerPerformAction(mainFrame, actionInContext, callMetadata => mainFrame.expect(callMetadata, selector, {
selector,
expression: 'to.be.checked',
expectedValue: { checked: true },
isNot: !action.checked,
timeout: kActionTimeout,
}));
Expand Down Expand Up @@ -291,7 +290,7 @@ export default class CrxPlayer extends EventEmitter {
return await innerPerformAction(mainFrame, actionInContext, callMetadata => mainFrame.expect(callMetadata, selector, {
selector,
expression: 'to.match.aria',
expectedValue: parseAriaSnapshot(action.snapshot),
expectedValue: parseAriaSnapshotUnsafe(yaml, action.snapshot),
isNot: false,
timeout: kActionTimeout,
}));
Expand Down
147 changes: 147 additions & 0 deletions src/server/recorder/recorderUtils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
/**
* Copyright (c) Microsoft Corporation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import type * as recorderActions from '@recorder/actions';
import type * as channels from '@protocol/channels';
import { toKeyboardModifiers } from 'playwright-core/lib/server/codegen/language';
import { buildFullSelector } from 'playwright-core/lib/server/recorder/recorderUtils';

const kDefaultTimeout = 5_000;

export function traceParamsForAction(actionInContext: recorderActions.ActionInContext): { method: string, apiName: string, params: any } {
const { action } = actionInContext;
switch (action.name) {
case 'navigate': {
const params: channels.FrameGotoParams = {
url: action.url,
};
return { method: 'goto', apiName: 'page.goto', params };
}
case 'openPage': {
return { method: 'newPage', params: {}, apiName: 'browserContext.newPage' };
}
case 'closePage': {
return { method: 'close', params: {}, apiName: 'page.close' };
}
}
const selector = buildFullSelector(actionInContext.frame.framePath, action.selector);
switch (action.name) {

case 'click': {
const params: channels.FrameClickParams = {
selector,
strict: true,
modifiers: toKeyboardModifiers(action.modifiers),
button: action.button,
clickCount: action.clickCount,
position: action.position,
};
return { method: 'click', apiName: 'locator.click', params };
}
case 'press': {
const params: channels.FramePressParams = {
selector,
strict: true,
key: [...toKeyboardModifiers(action.modifiers), action.key].join('+'),
};
return { method: 'press', apiName: 'locator.press', params };
}
case 'fill': {
const params: channels.FrameFillParams = {
selector,
strict: true,
value: action.text,
};
return { method: 'fill', apiName: 'locator.fill', params };
}
case 'setInputFiles': {
const params: channels.FrameSetInputFilesParams = {
selector,
strict: true,
localPaths: action.files,
};
return { method: 'setInputFiles', apiName: 'locator.setInputFiles', params };
}
case 'check': {
const params: channels.FrameCheckParams = {
selector,
strict: true,
};
return { method: 'check', apiName: 'locator.check', params };
}
case 'uncheck': {
const params: channels.FrameUncheckParams = {
selector,
strict: true,
};
return { method: 'uncheck', apiName: 'locator.uncheck', params };
}
case 'select': {
const params: channels.FrameSelectOptionParams = {
selector,
strict: true,
options: action.options.map(option => ({ value: option })),
};
return { method: 'selectOption', apiName: 'locator.selectOption', params };
}
case 'assertChecked': {
const params: channels.FrameExpectParams = {
selector: action.selector,
expression: 'to.be.checked',
isNot: !action.checked,
timeout: kDefaultTimeout,
};
return { method: 'expect', apiName: 'expect.toBeChecked', params };
}
case 'assertText': {
const params: channels.FrameExpectParams = {
selector,
expression: 'to.have.text',
expectedText: [],
isNot: false,
timeout: kDefaultTimeout,
};
return { method: 'expect', apiName: 'expect.toContainText', params };
}
case 'assertValue': {
const params: channels.FrameExpectParams = {
selector,
expression: 'to.have.value',
expectedValue: undefined,
isNot: false,
timeout: kDefaultTimeout,
};
return { method: 'expect', apiName: 'expect.toHaveValue', params };
}
case 'assertVisible': {
const params: channels.FrameExpectParams = {
selector,
expression: 'to.be.visible',
isNot: false,
timeout: kDefaultTimeout,
};
return { method: 'expect', apiName: 'expect.toBeVisible', params };
}
case 'assertSnapshot': {
const params: channels.FrameExpectParams = {
selector,
expression: 'to.match.aria',
isNot: false,
timeout: kDefaultTimeout,
};
return { method: 'expect', apiName: 'expect.toMatchAriaSnapshot', params };
}
}
}
Loading

0 comments on commit 9db1a3a

Please sign in to comment.