diff --git a/src/client/connection.ts b/src/client/connection.ts index 9de2b92116..e6d980f11a 100644 --- a/src/client/connection.ts +++ b/src/client/connection.ts @@ -110,7 +110,7 @@ export class Connection extends EventEmitter { if (!callback) throw new Error(`Cannot find command to respond: ${id}`); this._callbacks.delete(id); - if (error) + if (error && !result) callback.reject(parseError(error)); else callback.resolve(this._replaceGuidsWithChannels(result)); diff --git a/src/dispatchers/dispatcher.ts b/src/dispatchers/dispatcher.ts index 159021c4ec..45ba25afea 100644 --- a/src/dispatchers/dispatcher.ts +++ b/src/dispatchers/dispatcher.ts @@ -281,11 +281,12 @@ export class DispatcherConnection { await sdkObject?.instrumentation.onAfterCall(sdkObject, callMetadata); } - const log = validMetadata.collectLogs ? callMetadata.log : undefined; - if (callMetadata.error) - this.onmessage({ id, error: error, log }); - else - this.onmessage({ id, result: callMetadata.result, log }); + const response: any = { id }; + if (callMetadata.result) + response.result = callMetadata.result; + if (error) + response.error = error; + this.onmessage(response); } private _replaceDispatchersWithGuids(payload: any): any { diff --git a/src/dispatchers/frameDispatcher.ts b/src/dispatchers/frameDispatcher.ts index 29ff6be139..f643174bbc 100644 --- a/src/dispatchers/frameDispatcher.ts +++ b/src/dispatchers/frameDispatcher.ts @@ -232,6 +232,8 @@ export class FrameDispatcher extends Dispatcher Validator): Scheme { scheme.Metadata = tObject({ stack: tOptional(tArray(tType('StackFrame'))), apiName: tOptional(tString), - collectLogs: tOptional(tBoolean), }); scheme.Point = tObject({ x: tNumber, diff --git a/src/test/expect.ts b/src/test/expect.ts index f0fb688d4f..f8bab74da6 100644 --- a/src/test/expect.ts +++ b/src/test/expect.ts @@ -107,7 +107,6 @@ function wrap(matcherName: string, matcher: any) { reportStepError(e); } }; - result.displayName = 'expect.' + matcherName; return result; } diff --git a/src/test/index.ts b/src/test/index.ts index 6294a7ca01..ad7c81b8b0 100644 --- a/src/test/index.ts +++ b/src/test/index.ts @@ -212,6 +212,8 @@ export const test = _baseTest.extend({ } (context as any)._csi = { onApiCallBegin: (apiCall: string) => { + if (apiCall.startsWith('expect.')) + return { userObject: null }; const step = (testInfo as any)._addStep({ category: 'pw:api', title: apiCall, diff --git a/src/utils/stackTrace.ts b/src/utils/stackTrace.ts index 21815165fc..7aaa5db11d 100644 --- a/src/utils/stackTrace.ts +++ b/src/utils/stackTrace.ts @@ -62,15 +62,14 @@ export function captureStackTrace(): ParsedStackTrace { return null; if (frame.file.startsWith('internal')) return null; - if (frame.file.includes(path.join('node_modules', 'expect'))) - return null; const fileName = path.resolve(process.cwd(), frame.file); if (isTesting && fileName.includes(path.join('playwright', 'tests', 'config', 'coverage.js'))) return null; const inClient = // Allow fixtures in the reported stacks. (!fileName.includes('test/index') && !fileName.includes('test\\index')) && ( - fileName.startsWith(CLIENT_LIB) + frame.file.includes(path.join('node_modules', 'expect')) + || fileName.startsWith(CLIENT_LIB) || fileName.startsWith(CLIENT_SRC) || fileName.startsWith(TEST_LIB) || fileName.startsWith(TEST_SRC)); @@ -94,7 +93,15 @@ export function captureStackTrace(): ParsedStackTrace { for (let i = 0; i < parsedFrames.length - 1; i++) { if (parsedFrames[i].inClient && !parsedFrames[i + 1].inClient) { const frame = parsedFrames[i].frame; - apiName = frame.function ? frame.function[0].toLowerCase() + frame.function.slice(1) : ''; + const text = parsedFrames[i].frameText; + // expect matchers have the following stack structure: + // at __EXTERNAL_MATCHER_TRAP__ (.../index.js:342:30) + // at Object.throwingMatcher [as toBeChecked] (.../index.js:343:15) + const aliasIndex = text.indexOf('[as '); + if (aliasIndex !== -1) + apiName = 'expect.' + text.substring(aliasIndex + 4, text.indexOf(']')); + else + apiName = frame.function ? frame.function[0].toLowerCase() + frame.function.slice(1) : ''; parsedFrames = parsedFrames.slice(i + 1); break; } diff --git a/tests/config/browserTest.ts b/tests/config/browserTest.ts index b66250f114..c3a5666105 100644 --- a/tests/config/browserTest.ts +++ b/tests/config/browserTest.ts @@ -143,6 +143,8 @@ export const playwrightFixtures: Fixtures { + if (apiCall.startsWith('expect.')) + return { userObject: null }; const testInfoImpl = testInfo as any; const step = testInfoImpl._addStep({ category: 'pw:api', diff --git a/tests/playwright-test/reporter.spec.ts b/tests/playwright-test/reporter.spec.ts index f0f8f530bf..507dad9a15 100644 --- a/tests/playwright-test/reporter.spec.ts +++ b/tests/playwright-test/reporter.spec.ts @@ -229,9 +229,7 @@ test('should report expect steps', async ({ runInlineTest }) => { `%% end {\"title\":\"browserContext.newPage\",\"category\":\"pw:api\"}`, `%% end {\"title\":\"Before Hooks\",\"category\":\"hook\",\"steps\":[{\"title\":\"browserContext.newPage\",\"category\":\"pw:api\"}]}`, `%% begin {\"title\":\"expect.not.toHaveTitle\",\"category\":\"expect\"}`, - `%% begin {\"title\":\"object.expect.toHaveTitle(:root)\",\"category\":\"pw:api\"}`, - `%% end {\"title\":\"object.expect.toHaveTitle(:root)\",\"category\":\"pw:api\"}`, - `%% end {\"title\":\"expect.not.toHaveTitle\",\"category\":\"expect\",\"steps\":[{\"title\":\"object.expect.toHaveTitle(:root)\",\"category\":\"pw:api\"}]}`, + `%% end {\"title\":\"expect.not.toHaveTitle\",\"category\":\"expect\"}`, `%% begin {\"title\":\"After Hooks\",\"category\":\"hook\"}`, `%% begin {\"title\":\"browserContext.close\",\"category\":\"pw:api\"}`, `%% end {\"title\":\"browserContext.close\",\"category\":\"pw:api\"}`,