Skip to content

Commit

Permalink
test utils: Include origin of failed browser.* in stack (#74553)
Browse files Browse the repository at this point in the history
i.e. the stack will now include the actual test util in the test that failed not just a single frame from util internals.

New stack for e.g. a failed `waitForElementByCSS`:

```diff
 ● app dir - navigation with Suspense in nested layout › resolves data after client navigation to a nested layout with Suspense

     page.waitForSelector: Timeout 1000ms exceeded.
     Call log:
       - waiting for locator('[data-testid="nested-resolved"]')
 
       423 |     return this.chain(() => {
       424 |       return page
     > 425 |         .waitForSelector(selector, { timeout, state: 'attached' })
          |          ^
       426 |         .then(async (el) => {
       427 |           // it seems selenium waits longer and tests rely on this behavior
       428 |           // so we wait for the load event fire before returning

       at waitForSelector (lib/browsers/playwright.ts:425:10)
+      at BrowserInterface.chain (lib/browsers/base.ts:17:23)
+      at BrowserInterface.chain [as waitForElementByCss] (lib/browsers/playwright.ts:423:17)
+      at Object.waitForElementByCss (e2e/app-dir/navigation-layout-suspense/navigation-layout-suspense.test.ts:17:19)
```

Ideally we'd just display the stack starting by `at Object.waitForElementByCss` but that would mean passing a sync error from each `this.chain` callsite and this may actually hide internal errors and I'm not sure of the interaction with actual chaining e.g. `browser.waitForElementByCSS().click().waitForElementByCSS()`.

 This is improves readability of CI errors by a lot with minimal changes.
  • Loading branch information
eps1lon authored Jan 6, 2025
1 parent c14c6e0 commit c94fdef
Showing 1 changed file with 14 additions and 1 deletion.
15 changes: 14 additions & 1 deletion test/lib/browsers/base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,20 @@ export abstract class BrowserInterface<TCurrent = any> {
protected chain<TNext>(
nextCall: (current: TCurrent) => TNext | Promise<TNext>
): BrowserInterface<TNext> & Promise<TNext> {
const promise = Promise.resolve(this.promise).then(nextCall)
const syncError = new Error('next-browser-base-chain-error')
const promise = Promise.resolve(this.promise)
.then(nextCall)
.catch((reason) => {
if (
reason !== null &&
typeof reason === 'object' &&
'stack' in reason
) {
const syncCallStack = syncError.stack.split(syncError.message)[1]
reason.stack += `\n${syncCallStack}`
}
throw reason
})

function get(target: BrowserInterface<TNext>, p: string | symbol): any {
switch (p) {
Expand Down

0 comments on commit c94fdef

Please sign in to comment.