Skip to content

Commit

Permalink
chore: generate simple dom descriptions in codegen (#32333)
Browse files Browse the repository at this point in the history
  • Loading branch information
pavelfeldman authored Aug 27, 2024
1 parent 3f085d5 commit bc87467
Show file tree
Hide file tree
Showing 13 changed files with 217 additions and 108 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ export type FrameDescription = {

export type ActionInContext = {
frame: FrameDescription;
description?: string;
action: Action;
committed?: boolean;
};
Expand Down
8 changes: 7 additions & 1 deletion packages/playwright-core/src/server/codegen/javascript.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ export class JavaScriptLanguageGenerator implements LanguageGenerator {
if (signals.download)
formatter.add(`const download${signals.download.downloadAlias}Promise = ${pageAlias}.waitForEvent('download');`);

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

if (signals.popup)
formatter.add(`const ${signals.popup.popupAlias} = await ${signals.popup.popupAlias}Promise;`);
Expand Down Expand Up @@ -259,3 +259,9 @@ export class JavaScriptFormatter {
function quote(text: string) {
return escapeWithQuotes(text, '\'');
}

function wrapWithStep(description: string | undefined, body: string) {
return description ? `await test.step(\`${description}\`, async () => {
${body}
});` : body;
}
2 changes: 1 addition & 1 deletion packages/playwright-core/src/server/frames.ts
Original file line number Diff line number Diff line change
Expand Up @@ -800,7 +800,7 @@ export class Frame extends SdkObject {
const result = await resolved.injected.evaluateHandle((injected, { info, root }) => {
const elements = injected.querySelectorAll(info.parsed, root || document);
const element: Element | undefined = elements[0];
const visible = element ? injected.isVisible(element) : false;
const visible = element ? injected.utils.isElementVisible(element) : false;
let log = '';
if (elements.length > 1) {
if (info.strict)
Expand Down
27 changes: 19 additions & 8 deletions packages/playwright-core/src/server/injected/.eslintrc.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,21 @@
const path = require('path');

module.exports = {
rules: {
"no-restricted-globals": [
"error",
{ "name": "window" },
{ "name": "document" },
{ "name": "globalThis" },
]
}
parser: "@typescript-eslint/parser",
plugins: ["@typescript-eslint", "notice"],
parserOptions: {
ecmaVersion: 9,
sourceType: "module",
project: path.join(__dirname, '../../../../../tsconfig.json'),
},
rules: {
"no-restricted-globals": [
"error",
{ "name": "window" },
{ "name": "document" },
{ "name": "globalThis" },
],
'@typescript-eslint/no-floating-promises': 'error',
"@typescript-eslint/no-unnecessary-boolean-literal-compare": 2,
},
};
2 changes: 1 addition & 1 deletion packages/playwright-core/src/server/injected/clock.ts
Original file line number Diff line number Diff line change
Expand Up @@ -216,7 +216,7 @@ export class ClockController {
const sinceLastSync = now - this._realTime!.lastSyncTicks;
this._realTime!.lastSyncTicks = now;
// eslint-disable-next-line no-console
this._runTo(shiftTicks(this._now.ticks, sinceLastSync)).catch(e => console.error(e)).then(() => this._updateRealTimeTimer());
void this._runTo(shiftTicks(this._now.ticks, sinceLastSync)).catch(e => console.error(e)).then(() => this._updateRealTimeTimer());
}, callAt - this._now.ticks),
};
}
Expand Down
48 changes: 27 additions & 21 deletions packages/playwright-core/src/server/injected/injectedScript.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,12 @@ import type { CSSComplexSelectorList } from '../../utils/isomorphic/cssParser';
import { generateSelector, type GenerateSelectorOptions } from './selectorGenerator';
import type * as channels from '@protocol/channels';
import { Highlight } from './highlight';
import { getChecked, getAriaDisabled, getAriaRole, getElementAccessibleName, getElementAccessibleDescription } from './roleUtils';
import { getChecked, getAriaDisabled, getAriaRole, getElementAccessibleName, getElementAccessibleDescription, beginAriaCaches, endAriaCaches } from './roleUtils';
import { kLayoutSelectorNames, type LayoutSelectorName, layoutSelectorScore } from './layoutSelectorUtils';
import { asLocator } from '../../utils/isomorphic/locatorGenerators';
import type { Language } from '../../utils/isomorphic/locatorGenerators';
import { cacheNormalizedWhitespaces, normalizeWhiteSpace, trimStringWithEllipsis } from '../../utils/isomorphic/stringUtils';
import { cacheNormalizedWhitespaces, escapeHTML, escapeHTMLAttribute, normalizeWhiteSpace, trimStringWithEllipsis } from '../../utils/isomorphic/stringUtils';
import { generateSimpleDom, generateSimpleDomNode, selectorForSimpleDomNodeId } from './simpleDom';

export type FrameExpectParams = Omit<channels.FrameExpectParams, 'expectedValue'> & { expectedValue?: any };

Expand Down Expand Up @@ -66,7 +67,28 @@ export class InjectedScript {
// eslint-disable-next-line no-restricted-globals
readonly window: Window & typeof globalThis;
readonly document: Document;
readonly utils = { isInsideScope, elementText, asLocator, normalizeWhiteSpace, cacheNormalizedWhitespaces };

// Recorder must use any external dependencies through InjectedScript.
// Otherwise it will end up with a copy of all modules it uses, and any
// module-level globals will be duplicated, which leads to subtle bugs.
readonly utils = {
asLocator,
beginAriaCaches,
cacheNormalizedWhitespaces,
elementText,
endAriaCaches,
escapeHTML,
escapeHTMLAttribute,
generateSimpleDom: generateSimpleDom.bind(undefined, this),
generateSimpleDomNode: generateSimpleDomNode.bind(undefined, this),
getAriaRole,
getElementAccessibleDescription,
getElementAccessibleName,
isElementVisible,
isInsideScope,
normalizeWhiteSpace,
selectorForSimpleDomNodeId: selectorForSimpleDomNodeId.bind(undefined, this),
};

// eslint-disable-next-line no-restricted-globals
constructor(window: Window & typeof globalThis, isUnderTest: boolean, sdkLanguage: Language, testIdAttributeNameForStrictErrorAndConsoleCodegen: string, stableRafCount: number, browserName: string, customEngines: { name: string, engine: SelectorEngine }[]) {
Expand Down Expand Up @@ -426,10 +448,6 @@ export class InjectedScript {
return new constrFunction(this, params);
}

isVisible(element: Element): boolean {
return isElementVisible(element);
}

async viewportRatio(element: Element): Promise<number> {
return await new Promise(resolve => {
const observer = new IntersectionObserver(entries => {
Expand Down Expand Up @@ -567,9 +585,9 @@ export class InjectedScript {
}

if (state === 'visible')
return this.isVisible(element);
return isElementVisible(element);
if (state === 'hidden')
return !this.isVisible(element);
return !isElementVisible(element);

const disabled = getAriaDisabled(element);
if (state === 'disabled')
Expand Down Expand Up @@ -1296,18 +1314,6 @@ export class InjectedScript {
}
throw this.createStacklessError('Unknown expect matcher: ' + expression);
}

getElementAccessibleName(element: Element, includeHidden?: boolean): string {
return getElementAccessibleName(element, !!includeHidden);
}

getElementAccessibleDescription(element: Element, includeHidden?: boolean): string {
return getElementAccessibleDescription(element, !!includeHidden);
}

getAriaRole(element: Element) {
return getAriaRole(element);
}
}

const autoClosingTags = new Set(['AREA', 'BASE', 'BR', 'COL', 'COMMAND', 'EMBED', 'HR', 'IMG', 'INPUT', 'KEYGEN', 'LINK', 'MENUITEM', 'META', 'PARAM', 'SOURCE', 'TRACK', 'WBR']);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Recorder must use any external dependencies through InjectedScript.
# Recorder must use any external dependencies through injectedScript.utils.
# Otherwise it will end up with a copy of all modules it uses, and any
# module-level globals will be duplicated, which leads to subtle bugs.
[*]
Loading

0 comments on commit bc87467

Please sign in to comment.