diff --git a/app/client/models/errors.ts b/app/client/models/errors.ts index ee388556..c884b04b 100644 --- a/app/client/models/errors.ts +++ b/app/client/models/errors.ts @@ -70,6 +70,18 @@ export function reportSuccess(msg: MessageType, options?: Partial - doReportError(err || ev)); + G.window.addEventListener('error', (ev: ErrorEvent) => doReportError(ev.error || ev.message, ev)); G.window.addEventListener('unhandledrejection', (ev: any) => { const reason = ev.reason || (ev.detail && ev.detail.reason); diff --git a/test/nbrowser/gristUtils.ts b/test/nbrowser/gristUtils.ts index 63b3755e..e9b9250d 100644 --- a/test/nbrowser/gristUtils.ts +++ b/test/nbrowser/gristUtils.ts @@ -3068,6 +3068,19 @@ export async function assertIsRickRowing(expected: boolean) { assert.equal(await driver.find('iframe#youtube-player-dQw4w9WgXcQ').isPresent(), expected); } + +export function produceUncaughtError(message: string) { + // Simply throwing an error from driver.executeScript() may produce a sanitized "Script error", + // depending on browser/webdriver version. This is a trick to ensure the uncaught error is + // considered same-origin by the main window. + return driver.executeScript((msg: string) => { + const script = document.createElement("script"); + script.type = "text/javascript"; + script.innerText = 'setTimeout(() => { throw new Error(' + JSON.stringify(msg) + '); }, 0)'; + document.head.appendChild(script); + }, message); +} + } // end of namespace gristUtils stackWrapOwnMethods(gristUtils);