mirror of
https://github.com/microsoft/playwright.git
synced 2025-01-05 19:04:43 +03:00
fix(locator.count): do not touch main workd when computing count (#11256)
This commit is contained in:
parent
71a8da9c88
commit
dc07fa6da6
@ -213,6 +213,10 @@ export class Frame extends ChannelOwner<channels.FrameChannel> implements api.Fr
|
||||
return result.elements.map(e => ElementHandle.from(e) as ElementHandle<SVGElement | HTMLElement>);
|
||||
}
|
||||
|
||||
async _queryCount(selector: string): Promise<number> {
|
||||
return (await this._channel.queryCount({ selector })).value;
|
||||
}
|
||||
|
||||
async content(): Promise<string> {
|
||||
return (await this._channel.content()).value;
|
||||
}
|
||||
|
@ -135,7 +135,7 @@ export class Locator implements api.Locator {
|
||||
}
|
||||
|
||||
async count(): Promise<number> {
|
||||
return this.evaluateAll(ee => ee.length);
|
||||
return this._frame._queryCount(this._selector);
|
||||
}
|
||||
|
||||
async getAttribute(name: string, options?: TimeoutOptions): Promise<string | null> {
|
||||
|
@ -100,6 +100,10 @@ export class FrameDispatcher extends Dispatcher<Frame, channels.FrameChannel> im
|
||||
return { elements: elements.map(e => ElementHandleDispatcher.from(this._scope, e)) };
|
||||
}
|
||||
|
||||
async queryCount(params: channels.FrameQueryCountParams): Promise<channels.FrameQueryCountResult> {
|
||||
return { value: await this._frame.queryCount(params.selector) };
|
||||
}
|
||||
|
||||
async content(): Promise<channels.FrameContentResult> {
|
||||
return { value: await this._frame.content() };
|
||||
}
|
||||
|
@ -1794,6 +1794,7 @@ export interface FrameChannel extends FrameEventTarget, Channel {
|
||||
press(params: FramePressParams, metadata?: Metadata): Promise<FramePressResult>;
|
||||
querySelector(params: FrameQuerySelectorParams, metadata?: Metadata): Promise<FrameQuerySelectorResult>;
|
||||
querySelectorAll(params: FrameQuerySelectorAllParams, metadata?: Metadata): Promise<FrameQuerySelectorAllResult>;
|
||||
queryCount(params: FrameQueryCountParams, metadata?: Metadata): Promise<FrameQueryCountResult>;
|
||||
selectOption(params: FrameSelectOptionParams, metadata?: Metadata): Promise<FrameSelectOptionResult>;
|
||||
setContent(params: FrameSetContentParams, metadata?: Metadata): Promise<FrameSetContentResult>;
|
||||
setInputFiles(params: FrameSetInputFilesParams, metadata?: Metadata): Promise<FrameSetInputFilesResult>;
|
||||
@ -2210,6 +2211,15 @@ export type FrameQuerySelectorAllOptions = {
|
||||
export type FrameQuerySelectorAllResult = {
|
||||
elements: ElementHandleChannel[],
|
||||
};
|
||||
export type FrameQueryCountParams = {
|
||||
selector: string,
|
||||
};
|
||||
export type FrameQueryCountOptions = {
|
||||
|
||||
};
|
||||
export type FrameQueryCountResult = {
|
||||
value: number,
|
||||
};
|
||||
export type FrameSelectOptionParams = {
|
||||
selector: string,
|
||||
strict?: boolean,
|
||||
|
@ -1640,6 +1640,12 @@ Frame:
|
||||
type: array
|
||||
items: ElementHandle
|
||||
|
||||
queryCount:
|
||||
parameters:
|
||||
selector: string
|
||||
returns:
|
||||
value: number
|
||||
|
||||
selectOption:
|
||||
parameters:
|
||||
selector: string
|
||||
|
@ -826,6 +826,9 @@ export function createScheme(tChannel: (name: string) => Validator): Scheme {
|
||||
scheme.FrameQuerySelectorAllParams = tObject({
|
||||
selector: tString,
|
||||
});
|
||||
scheme.FrameQueryCountParams = tObject({
|
||||
selector: tString,
|
||||
});
|
||||
scheme.FrameSelectOptionParams = tObject({
|
||||
selector: tString,
|
||||
strict: tOptional(tBoolean),
|
||||
|
@ -797,7 +797,7 @@ export class ElementHandle<T extends Node = Node> extends js.JSHandle<T> {
|
||||
throw new Error(`Error: failed to find frame for selector "${selector}"`);
|
||||
const { frame, info } = pair;
|
||||
// If we end up in the same frame => use the scope again, line above was noop.
|
||||
const arrayHandle = await this._page.selectors._queryArray(frame, info, this._frame === frame ? this : undefined);
|
||||
const arrayHandle = await this._page.selectors._queryArrayInMainWorld(frame, info, this._frame === frame ? this : undefined);
|
||||
const result = await arrayHandle.evaluateExpressionAndWaitForSignals(expression, isFunction, true, arg);
|
||||
arrayHandle.dispose();
|
||||
return result;
|
||||
|
@ -780,7 +780,7 @@ export class Frame extends SdkObject {
|
||||
const pair = await this.resolveFrameForSelectorNoWait(selector, {});
|
||||
if (!pair)
|
||||
throw new Error(`Error: failed to find frame for selector "${selector}"`);
|
||||
const arrayHandle = await this._page.selectors._queryArray(pair.frame, pair.info);
|
||||
const arrayHandle = await this._page.selectors._queryArrayInMainWorld(pair.frame, pair.info);
|
||||
const result = await arrayHandle.evaluateExpressionAndWaitForSignals(expression, isFunction, true, arg);
|
||||
arrayHandle.dispose();
|
||||
return result;
|
||||
@ -793,6 +793,13 @@ export class Frame extends SdkObject {
|
||||
return this._page.selectors._queryAll(pair.frame, pair.info, undefined, true /* adoptToMain */);
|
||||
}
|
||||
|
||||
async queryCount(selector: string): Promise<number> {
|
||||
const pair = await this.resolveFrameForSelectorNoWait(selector);
|
||||
if (!pair)
|
||||
throw new Error(`Error: failed to find frame for selector "${selector}"`);
|
||||
return await this._page.selectors._queryCount(pair.frame, pair.info);
|
||||
}
|
||||
|
||||
async content(): Promise<string> {
|
||||
try {
|
||||
const context = await this._utilityContext();
|
||||
@ -1536,7 +1543,7 @@ export class Frame extends SdkObject {
|
||||
return { frame, info: this._page.parseSelector(frameChunks[frameChunks.length - 1], options) };
|
||||
}
|
||||
|
||||
async resolveFrameForSelectorNoWait(selector: string, options: types.StrictOptions & types.TimeoutOptions, scope?: dom.ElementHandle): Promise<SelectorInFrame | null> {
|
||||
async resolveFrameForSelectorNoWait(selector: string, options: types.StrictOptions & types.TimeoutOptions = {}, scope?: dom.ElementHandle): Promise<SelectorInFrame | null> {
|
||||
let frame: Frame | null = this;
|
||||
const frameChunks = splitSelectorByFrame(selector);
|
||||
|
||||
|
@ -83,7 +83,7 @@ export class Selectors {
|
||||
return this._adoptIfNeeded(elementHandle, mainContext);
|
||||
}
|
||||
|
||||
async _queryArray(frame: frames.Frame, info: SelectorInfo, scope?: dom.ElementHandle): Promise<js.JSHandle<Element[]>> {
|
||||
async _queryArrayInMainWorld(frame: frames.Frame, info: SelectorInfo, scope?: dom.ElementHandle): Promise<js.JSHandle<Element[]>> {
|
||||
const context = await frame._mainContext();
|
||||
const injectedScript = await context.injectedScript();
|
||||
const arrayHandle = await injectedScript.evaluateHandle((injected, { parsed, scope }) => {
|
||||
@ -92,6 +92,14 @@ export class Selectors {
|
||||
return arrayHandle;
|
||||
}
|
||||
|
||||
async _queryCount(frame: frames.Frame, info: SelectorInfo, scope?: dom.ElementHandle): Promise<number> {
|
||||
const context = await frame._utilityContext();
|
||||
const injectedScript = await context.injectedScript();
|
||||
return await injectedScript.evaluate((injected, { parsed, scope }) => {
|
||||
return injected.querySelectorAll(parsed, scope || document).length;
|
||||
}, { parsed: info.parsed, scope });
|
||||
}
|
||||
|
||||
async _queryAll(frame: frames.Frame, selector: SelectorInfo, scope?: dom.ElementHandle, adoptToMain?: boolean): Promise<dom.ElementHandle<Element>[]> {
|
||||
const info = typeof selector === 'string' ? frame._page.parseSelector(selector) : selector;
|
||||
const context = await frame._context(info.world);
|
||||
|
@ -113,3 +113,10 @@ it('should combine visible with other selectors', async ({ page }) => {
|
||||
await expect(locator).toHaveText('visible data2');
|
||||
await expect(page.locator('.item >> visible=true >> text=data3')).toHaveText('visible data3');
|
||||
});
|
||||
|
||||
it('locator.count should work with deleted Map in main world', async ({ page }) => {
|
||||
it.info().annotations.push({ type: 'issue', description: 'https://github.com/microsoft/playwright/issues/11254' });
|
||||
await page.evaluate('Map = 1');
|
||||
await page.locator('#searchResultTableDiv .x-grid3-row').count();
|
||||
await expect(page.locator('#searchResultTableDiv .x-grid3-row')).toHaveCount(0);
|
||||
});
|
||||
|
Loading…
Reference in New Issue
Block a user