-
-
Notifications
You must be signed in to change notification settings - Fork 1.9k
feat(browser): Add onError callback to showReportDialog
#24780
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
72b5231
1c0b723
4ef64e4
9f25624
dd22082
dd35f77
02680be
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,6 @@ | ||
| Sentry.showReportDialog({ | ||
| eventId: 'test_id', | ||
| onError: error => { | ||
| window._reportDialogError = error.message; | ||
| }, | ||
| }); |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,15 @@ | ||
| import { expect } from '@playwright/test'; | ||
| import { sentryTest } from '../../../../utils/fixtures'; | ||
|
|
||
| sentryTest('calls `onError` when the dialog script is blocked', async ({ getLocalTestUrl, page }) => { | ||
| const url = await getLocalTestUrl({ testDir: __dirname }); | ||
|
|
||
| // Registered after `getLocalTestUrl` so it takes precedence over the fixture's ingest route | ||
| await page.route(/\/api\/embed\/error-page\//, route => route.abort('blockedbyclient')); | ||
|
|
||
| await page.goto(url); | ||
|
|
||
| const errorMessage = await page.waitForFunction(() => (window as any)._reportDialogError); | ||
|
|
||
| expect(await errorMessage.jsonValue()).toBe('Failed to load the report dialog script'); | ||
| }); |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -36,17 +36,30 @@ export function showReportDialog(options: ReportDialogOptions = {}): void { | |
| eventId: options.eventId || lastEventId(), | ||
| }; | ||
|
|
||
| const { onLoad, onClose, onError } = mergedOptions; | ||
|
|
||
| // The endpoint rejects requests without an event ID, and a failed script load hides the reason | ||
| if (!mergedOptions.eventId) { | ||
| DEBUG_BUILD && debug.error('[showReportDialog] No event ID'); | ||
| onError?.(new Error('No event ID to show the report dialog for')); | ||
| return; | ||
| } | ||
|
Comment on lines
+42
to
+46
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think rejecting on missing But it never worked in the first place 🤔 EDIT: Never mind, if they don't have the callback then nothing happens. Disregard. |
||
|
|
||
| const script = WINDOW.document.createElement('script'); | ||
| script.async = true; | ||
| script.crossOrigin = 'anonymous'; | ||
| script.src = getReportDialogEndpoint(dsn, mergedOptions); | ||
|
|
||
| const { onLoad, onClose } = mergedOptions; | ||
|
|
||
| if (onLoad) { | ||
| script.onload = onLoad; | ||
| } | ||
|
|
||
| if (onError) { | ||
| script.onerror = () => { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Doesn't the error handler need to be registered before
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. To the best of my knowledge, the script starts loading only once its attached to the DOM, so when we set these properties makes no difference. This is different from when you write a script tag directly to the DOM.
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yep, scripts load only when added to the DOM, unlike images. |
||
| onError(new Error('Failed to load the report dialog script')); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It may be prudent to propagate the original error via
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Just tested this and browsers just give back a plain Event here, there's no |
||
| }; | ||
| } | ||
|
sentry[bot] marked this conversation as resolved.
|
||
|
|
||
| if (onClose) { | ||
| const reportDialogClosedMessageHandler = (event: MessageEvent): void => { | ||
| if (event.data === '__sentry_reportdialog_closed__') { | ||
|
|
@@ -58,6 +71,10 @@ export function showReportDialog(options: ReportDialogOptions = {}): void { | |
| } | ||
| }; | ||
| WINDOW.addEventListener('message', reportDialogClosedMessageHandler); | ||
| // A dialog that never loads never closes, so the listener would stay forever | ||
| script.addEventListener('error', () => { | ||
| WINDOW.removeEventListener('message', reportDialogClosedMessageHandler); | ||
| }); | ||
| } | ||
|
|
||
| injectionPoint.appendChild(script); | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
q: The docs say,
onErroronly reports load errors. Wondering if we should adjust docs (probably) or remove the invocation here, wdyt?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Updated the docs in dd22082