diff --git a/.prettierignore b/.prettierignore index f2ddf012c98e..f616ea97e557 100644 --- a/.prettierignore +++ b/.prettierignore @@ -1,2 +1,3 @@ *.md .nxcache +packages/browser-integration-tests/fixtures/loader.js diff --git a/packages/browser-integration-tests/.eslintrc.js b/packages/browser-integration-tests/.eslintrc.js index 47e485f9068a..a19cfba8812a 100644 --- a/packages/browser-integration-tests/.eslintrc.js +++ b/packages/browser-integration-tests/.eslintrc.js @@ -13,6 +13,14 @@ module.exports = { 'fixtures/**', 'tmp/**', ], + overrides: [ + { + files: ['loader-suites/**/{subject,init}.js'], + globals: { + Sentry: true, + }, + }, + ], parserOptions: { sourceType: 'module', }, diff --git a/packages/browser-integration-tests/fixtures/loader.js b/packages/browser-integration-tests/fixtures/loader.js index 5ae0a94ebda8..a6fa24465a4f 100644 --- a/packages/browser-integration-tests/fixtures/loader.js +++ b/packages/browser-integration-tests/fixtures/loader.js @@ -1,4 +1,4 @@ -!function(e,n,r,t,i,o,a,c,s){for(var f=s,forceLoad=!1,u=0;u-1){f&&"no"===document.scripts[u].getAttribute("data-lazy")&&(f=!1);break}var p=!1,d=[],l=function(e){("e"in e||"p"in e||e.f&&e.f.indexOf("capture")>-1||e.f&&e.f.indexOf("showReportDialog")>-1)&&f&&h(d),l.data.push(e)};function _(){l({e:[].slice.call(arguments)})}function v(e){l({p:"reason"in e?e.reason:"detail"in e&&"reason"in e.detail?e.detail.reason:e})}function h(o){if(!p){p=!0;var s=n.scripts[0],f=n.createElement("script");f.src=a,f.crossOrigin="anonymous",f.addEventListener("load",(function(){try{e.removeEventListener(r,_),e.removeEventListener(t,v),e.SENTRY_SDK_SOURCE="loader";var n=e[i],a=n.init;n.init=function(e){var r=c;for(var t in e)Object.prototype.hasOwnProperty.call(e,t)&&(r[t]=e[t]);!function(e,n){var r=e.integrations||[];if(!Array.isArray(r))return;var t=r.map((function(e){return e.name}));e.tracesSampleRate&&-1===t.indexOf("BrowserTracing")&&r.push(new n.BrowserTracing);(e.replaysSessionSampleRate||e.replaysOnErrorSampleRate)&&-1===t.indexOf("Replay")&&r.push(new n.Replay);e.integrations=r}(r,n),a(r)},function(n,r){try{for(var t=0;t-1){s&&"no"===document.scripts[f].getAttribute("data-lazy")&&(s=!1);break}var p=[];function l(n){return"e"in n}function d(n){return"p"in n}function _(n){return"f"in n}var v=[];function h(n){s&&(l(n)||d(n)||_(n)&&n.f.indexOf("capture")>-1||_(n)&&n.f.indexOf("showReportDialog")>-1)&&O(),v.push(n)}function y(){h({e:[].slice.call(arguments)})}function E(n){h({p:"reason"in n?n.reason:"detail"in n&&"reason"in n.detail?n.detail.reason:n})}function m(){try{n.SENTRY_SDK_SOURCE="loader";var e=n[i],o=e.init;e.init=function(i){n.removeEventListener(r,y),n.removeEventListener(t,E);var a=c;for(var u in i)Object.prototype.hasOwnProperty.call(i,u)&&(a[u]=i[u]);!function(n,e){var r=n.integrations||[];if(!Array.isArray(r))return;var t=r.map((function(n){return n.name}));n.tracesSampleRate&&-1===t.indexOf("BrowserTracing")&&r.push(new e.BrowserTracing);(n.replaysSessionSampleRate||n.replaysOnErrorSampleRate)&&-1===t.indexOf("Replay")&&r.push(new e.Replay);n.integrations=r}(a,e),o(a)},setTimeout((function(){return function(e){try{for(var r=0;r { cdnScript.src = '/cdn.bundle.js'; cdnScript.addEventListener('load', () => { - window.Sentry.init({ + Sentry.init({ dsn: 'https://public@dsn.ingest.sentry.io/1337', replaysSessionSampleRate: 0.42, }); diff --git a/packages/browser-integration-tests/loader-suites/loader/onLoad/captureExceptionInOnLoad/init.js b/packages/browser-integration-tests/loader-suites/loader/onLoad/captureExceptionInOnLoad/init.js index 71a703f2f9e1..8c8c99e30367 100644 --- a/packages/browser-integration-tests/loader-suites/loader/onLoad/captureExceptionInOnLoad/init.js +++ b/packages/browser-integration-tests/loader-suites/loader/onLoad/captureExceptionInOnLoad/init.js @@ -1,7 +1,5 @@ -import * as Sentry from '@sentry/browser'; - -window.Sentry = Sentry; - Sentry.onLoad(function () { + // You _have_ to call Sentry.init() before calling Sentry.captureException() in Sentry.onLoad()! + Sentry.init(); Sentry.captureException('Test exception'); }); diff --git a/packages/browser-integration-tests/loader-suites/loader/onLoad/captureExceptionInOnLoad/test.ts b/packages/browser-integration-tests/loader-suites/loader/onLoad/captureExceptionInOnLoad/test.ts index b63a8d6db1e4..b3cf79bde5c2 100644 --- a/packages/browser-integration-tests/loader-suites/loader/onLoad/captureExceptionInOnLoad/test.ts +++ b/packages/browser-integration-tests/loader-suites/loader/onLoad/captureExceptionInOnLoad/test.ts @@ -4,6 +4,14 @@ import { sentryTest } from '../../../../utils/fixtures'; import { envelopeRequestParser, waitForErrorRequestOnUrl } from '../../../../utils/helpers'; sentryTest('captureException works inside of onLoad', async ({ getLocalTestUrl, page }) => { + await page.route('https://dsn.ingest.sentry.io/**/*', route => { + return route.fulfill({ + status: 200, + contentType: 'application/json', + body: JSON.stringify({ id: 'test-id' }), + }); + }); + const url = await getLocalTestUrl({ testDir: __dirname }); const req = await waitForErrorRequestOnUrl(page, url); diff --git a/packages/browser-integration-tests/loader-suites/loader/onLoad/customBrowserTracing/init.js b/packages/browser-integration-tests/loader-suites/loader/onLoad/customBrowserTracing/init.js index cf30bc698e53..269593b620f1 100644 --- a/packages/browser-integration-tests/loader-suites/loader/onLoad/customBrowserTracing/init.js +++ b/packages/browser-integration-tests/loader-suites/loader/onLoad/customBrowserTracing/init.js @@ -1,6 +1,3 @@ -import * as Sentry from '@sentry/browser'; - -window.Sentry = Sentry; window._testBaseTimestamp = performance.timeOrigin / 1000; Sentry.onLoad(function () { diff --git a/packages/browser-integration-tests/loader-suites/loader/onLoad/customInit/init.js b/packages/browser-integration-tests/loader-suites/loader/onLoad/customInit/init.js new file mode 100644 index 000000000000..4a9e000fd1c2 --- /dev/null +++ b/packages/browser-integration-tests/loader-suites/loader/onLoad/customInit/init.js @@ -0,0 +1,20 @@ +window.__sentryOnLoad = 0; + +setTimeout(() => { + Sentry.onLoad(function () { + window.__hadSentry = window.sentryIsLoaded(); + + Sentry.init({ + sampleRate: 0.5, + }); + + window.__sentryOnLoad++; + }); +}); + +window.sentryIsLoaded = () => { + const __sentry = window.__SENTRY__; + + // If there is a global __SENTRY__ that means that in any of the callbacks init() was already invoked + return !!(!(typeof __sentry === 'undefined') && __sentry.hub && __sentry.hub.getClient()); +}; diff --git a/packages/browser-integration-tests/loader-suites/loader/onLoad/customInit/test.ts b/packages/browser-integration-tests/loader-suites/loader/onLoad/customInit/test.ts new file mode 100644 index 000000000000..eeea9de48fb2 --- /dev/null +++ b/packages/browser-integration-tests/loader-suites/loader/onLoad/customInit/test.ts @@ -0,0 +1,34 @@ +import { expect } from '@playwright/test'; + +import { sentryTest } from '../../../../utils/fixtures'; +import { LOADER_CONFIGS } from '../../../../utils/generatePlugin'; + +const bundle = process.env.PW_BUNDLE || ''; +const isLazy = LOADER_CONFIGS[bundle]?.lazy; + +sentryTest('always calls onLoad init correctly', async ({ getLocalTestUrl, page }) => { + await page.route('https://dsn.ingest.sentry.io/**/*', route => { + return route.fulfill({ + status: 200, + contentType: 'application/json', + body: JSON.stringify({ id: 'test-id' }), + }); + }); + + const url = await getLocalTestUrl({ testDir: __dirname }); + + await page.goto(url); + + // We want to test that if we are _not_ lazy, we are correctly calling onLoad init() + // But if we are lazy and call `forceLoad`, we also call the onLoad init() correctly + if (isLazy) { + expect(await page.evaluate('window.__sentryOnLoad')).toEqual(0); + await page.evaluate('Sentry.forceLoad()'); + } + + await page.waitForFunction('window.__sentryOnLoad && window.sentryIsLoaded()'); + + expect(await page.evaluate('window.__hadSentry')).toEqual(false); + expect(await page.evaluate('window.__sentryOnLoad')).toEqual(1); + expect(await page.evaluate('Sentry.getCurrentHub().getClient().getOptions().sampleRate')).toEqual(0.5); +}); diff --git a/packages/browser-integration-tests/loader-suites/loader/onLoad/customIntegrations/init.js b/packages/browser-integration-tests/loader-suites/loader/onLoad/customIntegrations/init.js index a5440c1979c5..5d2920680cfc 100644 --- a/packages/browser-integration-tests/loader-suites/loader/onLoad/customIntegrations/init.js +++ b/packages/browser-integration-tests/loader-suites/loader/onLoad/customIntegrations/init.js @@ -1,7 +1,3 @@ -import * as Sentry from '@sentry/browser'; - -window.Sentry = Sentry; - class CustomIntegration { constructor() { this.name = 'CustomIntegration'; diff --git a/packages/browser-integration-tests/loader-suites/loader/onLoad/customIntegrationsFunction/init.js b/packages/browser-integration-tests/loader-suites/loader/onLoad/customIntegrationsFunction/init.js index 4c1e600794d5..0836f8b3b887 100644 --- a/packages/browser-integration-tests/loader-suites/loader/onLoad/customIntegrationsFunction/init.js +++ b/packages/browser-integration-tests/loader-suites/loader/onLoad/customIntegrationsFunction/init.js @@ -1,7 +1,3 @@ -import * as Sentry from '@sentry/browser'; - -window.Sentry = Sentry; - class CustomIntegration { constructor() { this.name = 'CustomIntegration'; diff --git a/packages/browser-integration-tests/loader-suites/loader/onLoad/customReplay/init.js b/packages/browser-integration-tests/loader-suites/loader/onLoad/customReplay/init.js index 64d2463ed668..921209ce14dc 100644 --- a/packages/browser-integration-tests/loader-suites/loader/onLoad/customReplay/init.js +++ b/packages/browser-integration-tests/loader-suites/loader/onLoad/customReplay/init.js @@ -1,7 +1,3 @@ -import * as Sentry from '@sentry/browser'; - -window.Sentry = Sentry; - Sentry.onLoad(function () { Sentry.init({ integrations: [ diff --git a/packages/browser-integration-tests/loader-suites/loader/onLoad/init.js b/packages/browser-integration-tests/loader-suites/loader/onLoad/init.js index 5a9398da8d47..e63705186b2f 100644 --- a/packages/browser-integration-tests/loader-suites/loader/onLoad/init.js +++ b/packages/browser-integration-tests/loader-suites/loader/onLoad/init.js @@ -1,7 +1,3 @@ -import * as Sentry from '@sentry/browser'; - -window.Sentry = Sentry; - Sentry.onLoad(function () { Sentry.init({}); }); diff --git a/packages/browser-integration-tests/loader-suites/loader/onLoad/onLoadLate/init.js b/packages/browser-integration-tests/loader-suites/loader/onLoad/onLoadLate/init.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/packages/browser-integration-tests/loader-suites/loader/onLoad/onLoadLate/subject.js b/packages/browser-integration-tests/loader-suites/loader/onLoad/onLoadLate/subject.js new file mode 100644 index 000000000000..1dcef58798cc --- /dev/null +++ b/packages/browser-integration-tests/loader-suites/loader/onLoad/onLoadLate/subject.js @@ -0,0 +1,7 @@ +Sentry.forceLoad(); + +setTimeout(() => { + Sentry.onLoad(function () { + Sentry.captureException('Test exception'); + }); +}, 200); diff --git a/packages/browser-integration-tests/loader-suites/loader/onLoad/onLoadLate/test.ts b/packages/browser-integration-tests/loader-suites/loader/onLoad/onLoadLate/test.ts new file mode 100644 index 000000000000..46bbf81f3c58 --- /dev/null +++ b/packages/browser-integration-tests/loader-suites/loader/onLoad/onLoadLate/test.ts @@ -0,0 +1,21 @@ +import { expect } from '@playwright/test'; + +import { sentryTest } from '../../../../utils/fixtures'; +import { envelopeRequestParser, waitForErrorRequestOnUrl } from '../../../../utils/helpers'; + +sentryTest('late onLoad call is handled', async ({ getLocalTestUrl, page }) => { + await page.route('https://dsn.ingest.sentry.io/**/*', route => { + return route.fulfill({ + status: 200, + contentType: 'application/json', + body: JSON.stringify({ id: 'test-id' }), + }); + }); + + const url = await getLocalTestUrl({ testDir: __dirname }); + const req = await waitForErrorRequestOnUrl(page, url); + + const eventData = envelopeRequestParser(req); + + expect(eventData.message).toBe('Test exception'); +}); diff --git a/packages/browser-integration-tests/loader-suites/loader/onLoad/pageloadTransaction/init.js b/packages/browser-integration-tests/loader-suites/loader/onLoad/pageloadTransaction/init.js index dcb6c3e90d0d..7c0fceed58a4 100644 --- a/packages/browser-integration-tests/loader-suites/loader/onLoad/pageloadTransaction/init.js +++ b/packages/browser-integration-tests/loader-suites/loader/onLoad/pageloadTransaction/init.js @@ -1,6 +1,3 @@ -import * as Sentry from '@sentry/browser'; - -window.Sentry = Sentry; window._testBaseTimestamp = performance.timeOrigin / 1000; Sentry.onLoad(function () { diff --git a/packages/browser-integration-tests/loader-suites/loader/onLoad/replay/init.js b/packages/browser-integration-tests/loader-suites/loader/onLoad/replay/init.js index 5a9398da8d47..e63705186b2f 100644 --- a/packages/browser-integration-tests/loader-suites/loader/onLoad/replay/init.js +++ b/packages/browser-integration-tests/loader-suites/loader/onLoad/replay/init.js @@ -1,7 +1,3 @@ -import * as Sentry from '@sentry/browser'; - -window.Sentry = Sentry; - Sentry.onLoad(function () { Sentry.init({}); });