@@ -30,6 +30,90 @@ describe("window.onunhandledrejection", function() {
30
30
} ) ;
31
31
} ) ;
32
32
33
+ // something, somewhere, (likely a browser extension) effectively casts PromiseRejectionEvents
34
+ // to CustomEvents, moving the `promise` and `reason` attributes of the PRE into
35
+ // the CustomEvent's `detail` attribute, since they're not part of CustomEvent's spec
36
+ // see https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent and
37
+ // https://github.com/getsentry/sentry-javascript/issues/2380
38
+ it ( "should capture PromiseRejectionEvent cast to CustomEvent with type unhandledrejection" , function ( ) {
39
+ return runInSandbox ( sandbox , function ( ) {
40
+ if ( supportsOnunhandledRejection ( ) ) {
41
+ // this isn't how it happens in real life, in that the promise and reason
42
+ // values come from an actual PromiseRejectionEvent, but it's enough to test
43
+ // how the SDK handles the structure
44
+ window . dispatchEvent (
45
+ new CustomEvent ( "unhandledrejection" , {
46
+ detail : {
47
+ promise : new Promise ( ( ) => { } ) ,
48
+ // we're testing with an error here but it could be anything - really
49
+ // all we're testing is that it gets dug out correctly
50
+ reason : new Error ( "test2" ) ,
51
+ } ,
52
+ } )
53
+ ) ;
54
+ Promise . reject ( ) ;
55
+ } else {
56
+ window . resolveTest ( { window : window } ) ;
57
+ }
58
+ } ) . then ( function ( summary ) {
59
+ if ( summary . window . supportsOnunhandledRejection ( ) ) {
60
+ assert . equal ( summary . events [ 0 ] . exception . values [ 0 ] . value , "test2" ) ;
61
+ assert . equal ( summary . events [ 0 ] . exception . values [ 0 ] . type , "Error" ) ;
62
+
63
+ // Of course Safari had to screw up here...
64
+ if ( ! / V e r s i o n \/ \d .+ S a f a r i \/ \d / . test ( window . navigator . userAgent ) ) {
65
+ assert . isAtLeast (
66
+ summary . events [ 0 ] . exception . values [ 0 ] . stacktrace . frames . length ,
67
+ 1
68
+ ) ;
69
+ }
70
+ assert . equal (
71
+ summary . events [ 0 ] . exception . values [ 0 ] . mechanism . handled ,
72
+ false
73
+ ) ;
74
+ assert . equal (
75
+ summary . events [ 0 ] . exception . values [ 0 ] . mechanism . type ,
76
+ "onunhandledrejection"
77
+ ) ;
78
+ // even though it's a regular Event (rather than a PRE) it should still only
79
+ // come through this channel
80
+ assert . equal ( summary . events . length , 1 ) ;
81
+ }
82
+ } ) ;
83
+ } ) ;
84
+
85
+ // there's no evidence that this actually happens, but it could, and our code correctly
86
+ // handles it, so might as well prevent future regression on that score
87
+ it ( "should capture a random Event with type unhandledrejection" , function ( ) {
88
+ return runInSandbox ( sandbox , function ( ) {
89
+ if ( supportsOnunhandledRejection ( ) ) {
90
+ window . dispatchEvent ( new Event ( "unhandledrejection" ) ) ;
91
+ } else {
92
+ window . resolveTest ( { window : window } ) ;
93
+ }
94
+ } ) . then ( function ( summary ) {
95
+ if ( summary . window . supportsOnunhandledRejection ( ) ) {
96
+ // non-error rejections don't provide stacktraces so we can skip that assertion
97
+ assert . equal (
98
+ summary . events [ 0 ] . exception . values [ 0 ] . value ,
99
+ "Non-Error promise rejection captured with keys: currentTarget, isTrusted, target, type"
100
+ ) ;
101
+ assert . equal ( summary . events [ 0 ] . exception . values [ 0 ] . type , "Event" ) ;
102
+ assert . equal (
103
+ summary . events [ 0 ] . exception . values [ 0 ] . mechanism . handled ,
104
+ false
105
+ ) ;
106
+ assert . equal (
107
+ summary . events [ 0 ] . exception . values [ 0 ] . mechanism . type ,
108
+ "onunhandledrejection"
109
+ ) ;
110
+ // even though it's a regular Event (rather than a PRE) it should sill only
111
+ // come through this channel
112
+ assert . equal ( summary . events . length , 1 ) ;
113
+ }
114
+ } ) ;
115
+ } ) ;
116
+
33
117
it ( "should capture unhandledrejection with a string" , function ( ) {
34
118
return runInSandbox ( sandbox , function ( ) {
35
119
if ( supportsOnunhandledRejection ( ) ) {
@@ -39,7 +123,7 @@ describe("window.onunhandledrejection", function() {
39
123
}
40
124
} ) . then ( function ( summary ) {
41
125
if ( summary . window . supportsOnunhandledRejection ( ) ) {
42
- // non-error rejections doesnt provide stacktraces so we can skip the assertion
126
+ // non-error rejections don't provide stacktraces so we can skip that assertion
43
127
assert . equal (
44
128
summary . events [ 0 ] . exception . values [ 0 ] . value ,
45
129
"Non-Error promise rejection captured with value: test"
@@ -69,7 +153,7 @@ describe("window.onunhandledrejection", function() {
69
153
}
70
154
} ) . then ( function ( summary ) {
71
155
if ( summary . window . supportsOnunhandledRejection ( ) ) {
72
- // non-error rejections doesnt provide stacktraces so we can skip the assertion
156
+ // non-error rejections don't provide stacktraces so we can skip that assertion
73
157
assert . equal ( summary . events [ 0 ] . exception . values [ 0 ] . value . length , 253 ) ;
74
158
assert . include (
75
159
summary . events [ 0 ] . exception . values [ 0 ] . value ,
@@ -100,7 +184,7 @@ describe("window.onunhandledrejection", function() {
100
184
}
101
185
} ) . then ( function ( summary ) {
102
186
if ( summary . window . supportsOnunhandledRejection ( ) ) {
103
- // non-error rejections doesnt provide stacktraces so we can skip the assertion
187
+ // non-error rejections don't provide stacktraces so we can skip that assertion
104
188
assert . equal (
105
189
summary . events [ 0 ] . exception . values [ 0 ] . value ,
106
190
"Non-Error promise rejection captured with keys: a, b, c"
@@ -137,7 +221,7 @@ describe("window.onunhandledrejection", function() {
137
221
}
138
222
} ) . then ( function ( summary ) {
139
223
if ( summary . window . supportsOnunhandledRejection ( ) ) {
140
- // non-error rejections doesnt provide stacktraces so we can skip the assertion
224
+ // non-error rejections don't provide stacktraces so we can skip that assertion
141
225
assert . equal (
142
226
summary . events [ 0 ] . exception . values [ 0 ] . value ,
143
227
"Non-Error promise rejection captured with keys: a, b, c, d, e"
@@ -167,7 +251,7 @@ describe("window.onunhandledrejection", function() {
167
251
}
168
252
} ) . then ( function ( summary ) {
169
253
if ( summary . window . supportsOnunhandledRejection ( ) ) {
170
- // non-error rejections doesnt provide stacktraces so we can skip the assertion
254
+ // non-error rejections don't provide stacktraces so we can skip that assertion
171
255
assert . equal (
172
256
summary . events [ 0 ] . exception . values [ 0 ] . value ,
173
257
"Non-Error promise rejection captured with value: 1337"
@@ -197,7 +281,7 @@ describe("window.onunhandledrejection", function() {
197
281
}
198
282
} ) . then ( function ( summary ) {
199
283
if ( summary . window . supportsOnunhandledRejection ( ) ) {
200
- // non-error rejections doesnt provide stacktraces so we can skip the assertion
284
+ // non-error rejections don't provide stacktraces so we can skip that assertion
201
285
assert . equal (
202
286
summary . events [ 0 ] . exception . values [ 0 ] . value ,
203
287
"Non-Error promise rejection captured with value: null"
@@ -227,7 +311,7 @@ describe("window.onunhandledrejection", function() {
227
311
}
228
312
} ) . then ( function ( summary ) {
229
313
if ( summary . window . supportsOnunhandledRejection ( ) ) {
230
- // non-error rejections doesnt provide stacktraces so we can skip the assertion
314
+ // non-error rejections don't provide stacktraces so we can skip that assertion
231
315
assert . equal (
232
316
summary . events [ 0 ] . exception . values [ 0 ] . value ,
233
317
"Non-Error promise rejection captured with value: undefined"
0 commit comments