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[] }> {
|
||||
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';
|
||||
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) {
|
||||
// expect(locator).toBeHidden() passes when there is no element.
|
||||
if (!options.isNot && options.expression === 'to.be.hidden')
|
||||
return { matches: true };
|
||||
|
||||
// expect(locator).not.toBeVisible() passes when there is no element.
|
||||
if (options.isNot && options.expression === 'to.be.visible')
|
||||
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.
|
||||
return progress.continuePolling;
|
||||
}
|
||||
result = progress.injectedScript.expectSingleElement(progress, element, options);
|
||||
}
|
||||
|
||||
const { matches, received } = progress.injectedScript.expect(progress, element, options, elements);
|
||||
if (matches === options.isNot) {
|
||||
if (result.matches === options.isNot) {
|
||||
// Keep waiting in these cases:
|
||||
// expect(locator).conditionThatDoesNotMatch
|
||||
// expect(locator).not.conditionThatDoesMatch
|
||||
progress.setIntermediateResult(received);
|
||||
if (!Array.isArray(received))
|
||||
progress.log(` unexpected value "${received}"`);
|
||||
progress.setIntermediateResult(result.received);
|
||||
if (!Array.isArray(result.received))
|
||||
progress.log(` unexpected value "${result.received}"`);
|
||||
return progress.continuePolling;
|
||||
}
|
||||
|
||||
// Reached the expected state!
|
||||
return { matches, received };
|
||||
}, options, { strict: true, querySelectorAll, mainWorld, omitAttached: true, logScale: true, ...options }).catch(e => {
|
||||
return result;
|
||||
}, { ...options, isArray }, { strict: true, querySelectorAll: isArray, mainWorld, omitAttached: true, logScale: true, ...options }).catch(e => {
|
||||
if (js.isJavaScriptErrorInEvaluate(e))
|
||||
throw e;
|
||||
// Q: Why not throw upon isSessionClosedError(e) as in other places?
|
||||
|
@ -798,7 +798,7 @@ export class InjectedScript {
|
||||
}).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 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
|
||||
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.
|
||||
let received: string[] | undefined;
|
||||
if (expression === 'to.have.text.array' || expression === 'to.contain.text.array')
|
||||
@ -911,8 +913,7 @@ export class InjectedScript {
|
||||
}
|
||||
return { received, matches: allMatchesFound };
|
||||
}
|
||||
}
|
||||
throw this.createStacklessError('Unknown expect matcher: ' + options.expression);
|
||||
throw this.createStacklessError('Unknown expect matcher: ' + expression);
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user