mirror of
https://github.com/microsoft/playwright.git
synced 2025-06-26 21:40:17 +00:00
chore(expect): simplify expect array edge cases (#9942)
This commit is contained in:
parent
2bfbf65b8d
commit
9cfbc0c171
@ -1156,48 +1156,40 @@ export class Frame extends SdkObject {
|
|||||||
|
|
||||||
async expect(metadata: CallMetadata, selector: string, options: FrameExpectParams): Promise<{ matches: boolean, received?: any, log?: string[] }> {
|
async expect(metadata: CallMetadata, selector: string, options: FrameExpectParams): Promise<{ matches: boolean, received?: any, log?: string[] }> {
|
||||||
const controller = new ProgressController(metadata, this);
|
const controller = new ProgressController(metadata, this);
|
||||||
const querySelectorAll = options.expression === 'to.have.count' || options.expression.endsWith('.array');
|
const isArray = options.expression === 'to.have.count' || options.expression.endsWith('.array');
|
||||||
const mainWorld = options.expression === 'to.have.property';
|
const mainWorld = options.expression === 'to.have.property';
|
||||||
return await this._scheduleRerunnableTaskWithController(controller, selector, (progress, element, options, elements) => {
|
return await this._scheduleRerunnableTaskWithController(controller, selector, (progress, element, options, elements) => {
|
||||||
|
let result: { matches: boolean, received?: any };
|
||||||
|
|
||||||
|
if (options.isArray) {
|
||||||
|
result = progress.injectedScript.expectArray(elements, options);
|
||||||
|
} else {
|
||||||
if (!element) {
|
if (!element) {
|
||||||
// expect(locator).toBeHidden() passes when there is no element.
|
// expect(locator).toBeHidden() passes when there is no element.
|
||||||
if (!options.isNot && options.expression === 'to.be.hidden')
|
if (!options.isNot && options.expression === 'to.be.hidden')
|
||||||
return { matches: true };
|
return { matches: true };
|
||||||
|
|
||||||
// expect(locator).not.toBeVisible() passes when there is no element.
|
// expect(locator).not.toBeVisible() passes when there is no element.
|
||||||
if (options.isNot && options.expression === 'to.be.visible')
|
if (options.isNot && options.expression === 'to.be.visible')
|
||||||
return { matches: false };
|
return { matches: false };
|
||||||
|
|
||||||
// expect(listLocator).toHaveText([]) passes when there are no elements matching.
|
|
||||||
// expect(listLocator).not.toHaveText(['foo']) passes when there are no elements matching.
|
|
||||||
const expectsEmptyList = options.expectedText?.length === 0;
|
|
||||||
if (options.expression.endsWith('.array') && expectsEmptyList !== options.isNot)
|
|
||||||
return { matches: expectsEmptyList };
|
|
||||||
|
|
||||||
// expect(listLocator).toHaveCount(0) passes when there are no elements matching.
|
|
||||||
// expect(listLocator).not.toHaveCount(1) passes when there are no elements matching.
|
|
||||||
const expectsEmptyCount = options.expectedNumber === 0;
|
|
||||||
if (options.expression === 'to.have.count' && expectsEmptyCount !== options.isNot)
|
|
||||||
return { matches: expectsEmptyCount, received: 0 };
|
|
||||||
|
|
||||||
// When none of the above applies, keep waiting for the element.
|
// When none of the above applies, keep waiting for the element.
|
||||||
return progress.continuePolling;
|
return progress.continuePolling;
|
||||||
}
|
}
|
||||||
|
result = progress.injectedScript.expectSingleElement(progress, element, options);
|
||||||
|
}
|
||||||
|
|
||||||
const { matches, received } = progress.injectedScript.expect(progress, element, options, elements);
|
if (result.matches === options.isNot) {
|
||||||
if (matches === options.isNot) {
|
|
||||||
// Keep waiting in these cases:
|
// Keep waiting in these cases:
|
||||||
// expect(locator).conditionThatDoesNotMatch
|
// expect(locator).conditionThatDoesNotMatch
|
||||||
// expect(locator).not.conditionThatDoesMatch
|
// expect(locator).not.conditionThatDoesMatch
|
||||||
progress.setIntermediateResult(received);
|
progress.setIntermediateResult(result.received);
|
||||||
if (!Array.isArray(received))
|
if (!Array.isArray(result.received))
|
||||||
progress.log(` unexpected value "${received}"`);
|
progress.log(` unexpected value "${result.received}"`);
|
||||||
return progress.continuePolling;
|
return progress.continuePolling;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reached the expected state!
|
// Reached the expected state!
|
||||||
return { matches, received };
|
return result;
|
||||||
}, options, { strict: true, querySelectorAll, mainWorld, omitAttached: true, logScale: true, ...options }).catch(e => {
|
}, { ...options, isArray }, { strict: true, querySelectorAll: isArray, mainWorld, omitAttached: true, logScale: true, ...options }).catch(e => {
|
||||||
if (js.isJavaScriptErrorInEvaluate(e))
|
if (js.isJavaScriptErrorInEvaluate(e))
|
||||||
throw e;
|
throw e;
|
||||||
// Q: Why not throw upon isSessionClosedError(e) as in other places?
|
// Q: Why not throw upon isSessionClosedError(e) as in other places?
|
||||||
|
@ -798,7 +798,7 @@ export class InjectedScript {
|
|||||||
}).observe(document, { childList: true });
|
}).observe(document, { childList: true });
|
||||||
}
|
}
|
||||||
|
|
||||||
expect(progress: InjectedScriptProgress, element: Element, options: FrameExpectParams, elements: Element[]): { matches: boolean, received?: any } {
|
expectSingleElement(progress: InjectedScriptProgress, element: Element, options: FrameExpectParams): { matches: boolean, received?: any } {
|
||||||
const injected = progress.injectedScript;
|
const injected = progress.injectedScript;
|
||||||
const expression = options.expression;
|
const expression = options.expression;
|
||||||
|
|
||||||
@ -835,15 +835,6 @@ export class InjectedScript {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
|
||||||
// Single number value.
|
|
||||||
if (expression === 'to.have.count') {
|
|
||||||
const received = elements.length;
|
|
||||||
const matches = received === options.expectedNumber;
|
|
||||||
return { received, matches };
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
{
|
||||||
// JS property
|
// JS property
|
||||||
if (expression === 'to.have.property') {
|
if (expression === 'to.have.property') {
|
||||||
@ -882,7 +873,18 @@ export class InjectedScript {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
throw this.createStacklessError('Unknown expect matcher: ' + expression);
|
||||||
|
}
|
||||||
|
|
||||||
|
expectArray(elements: Element[], options: FrameExpectParams): { matches: boolean, received?: any } {
|
||||||
|
const expression = options.expression;
|
||||||
|
|
||||||
|
if (expression === 'to.have.count') {
|
||||||
|
const received = elements.length;
|
||||||
|
const matches = received === options.expectedNumber;
|
||||||
|
return { received, matches };
|
||||||
|
}
|
||||||
|
|
||||||
// List of values.
|
// List of values.
|
||||||
let received: string[] | undefined;
|
let received: string[] | undefined;
|
||||||
if (expression === 'to.have.text.array' || expression === 'to.contain.text.array')
|
if (expression === 'to.have.text.array' || expression === 'to.contain.text.array')
|
||||||
@ -911,8 +913,7 @@ export class InjectedScript {
|
|||||||
}
|
}
|
||||||
return { received, matches: allMatchesFound };
|
return { received, matches: allMatchesFound };
|
||||||
}
|
}
|
||||||
}
|
throw this.createStacklessError('Unknown expect matcher: ' + expression);
|
||||||
throw this.createStacklessError('Unknown expect matcher: ' + options.expression);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user