@openobserve/browser-core 0.3.2 → 0.3.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (83) hide show
  1. package/cjs/boot/init.js +1 -1
  2. package/cjs/domain/configuration/endpointBuilder.js +1 -1
  3. package/cjs/domain/tags.js +1 -1
  4. package/cjs/domain/telemetry/telemetry.js +1 -1
  5. package/cjs/domain/telemetry/telemetryEvent.types.d.ts +1 -1
  6. package/esm/boot/init.js +1 -1
  7. package/esm/domain/configuration/endpointBuilder.js +1 -1
  8. package/esm/domain/tags.js +1 -1
  9. package/esm/domain/telemetry/telemetry.js +1 -1
  10. package/esm/domain/telemetry/telemetryEvent.types.d.ts +1 -1
  11. package/package.json +2 -2
  12. package/src/domain/telemetry/telemetryEvent.types.ts +1 -1
  13. package/src/boot/displayAlreadyInitializedError.spec.ts +0 -18
  14. package/src/boot/init.spec.ts +0 -50
  15. package/src/browser/addEventListener.spec.ts +0 -141
  16. package/src/browser/cookie.spec.ts +0 -53
  17. package/src/browser/fetchObservable.spec.ts +0 -334
  18. package/src/browser/pageMayExitObservable.spec.ts +0 -56
  19. package/src/browser/xhrObservable.spec.ts +0 -405
  20. package/src/domain/allowedTrackingOrigins.spec.ts +0 -210
  21. package/src/domain/bufferedData.spec.ts +0 -34
  22. package/src/domain/configuration/configuration.spec.ts +0 -236
  23. package/src/domain/configuration/endpointBuilder.spec.ts +0 -173
  24. package/src/domain/configuration/transportConfiguration.spec.ts +0 -130
  25. package/src/domain/connectivity/connectivity.spec.ts +0 -50
  26. package/src/domain/console/consoleObservable.spec.ts +0 -151
  27. package/src/domain/context/contextManager.spec.ts +0 -152
  28. package/src/domain/context/contextUtils.spec.ts +0 -26
  29. package/src/domain/context/storeContextManager.spec.ts +0 -103
  30. package/src/domain/contexts/accountContext.spec.ts +0 -99
  31. package/src/domain/contexts/globalContext.spec.ts +0 -88
  32. package/src/domain/contexts/userContext.spec.ts +0 -156
  33. package/src/domain/error/error.spec.ts +0 -294
  34. package/src/domain/error/trackRuntimeError.spec.ts +0 -343
  35. package/src/domain/eventRateLimiter/createEventRateLimiter.spec.ts +0 -119
  36. package/src/domain/extension/extensionUtils.spec.ts +0 -47
  37. package/src/domain/report/reportObservable.spec.ts +0 -71
  38. package/src/domain/session/oldCookiesMigration.spec.ts +0 -76
  39. package/src/domain/session/sessionManager.spec.ts +0 -684
  40. package/src/domain/session/sessionState.spec.ts +0 -88
  41. package/src/domain/session/sessionStore.spec.ts +0 -647
  42. package/src/domain/session/sessionStoreOperations.spec.ts +0 -234
  43. package/src/domain/session/storeStrategies/sessionInCookie.spec.ts +0 -228
  44. package/src/domain/session/storeStrategies/sessionInLocalStorage.spec.ts +0 -75
  45. package/src/domain/synthetics/syntheticsWorkerValues.spec.ts +0 -82
  46. package/src/domain/tags.spec.ts +0 -74
  47. package/src/domain/telemetry/telemetry.spec.ts +0 -494
  48. package/src/domain/trackingConsent.spec.ts +0 -44
  49. package/src/tools/abstractHooks.spec.ts +0 -76
  50. package/src/tools/abstractLifeCycle.spec.ts +0 -46
  51. package/src/tools/boundedBuffer.spec.ts +0 -40
  52. package/src/tools/catchUserErrors.spec.ts +0 -20
  53. package/src/tools/encoder.spec.ts +0 -112
  54. package/src/tools/experimentalFeatures.spec.ts +0 -60
  55. package/src/tools/getZoneJsOriginalValue.spec.ts +0 -36
  56. package/src/tools/instrumentMethod.spec.ts +0 -381
  57. package/src/tools/matchOption.spec.ts +0 -41
  58. package/src/tools/mergeInto.spec.ts +0 -198
  59. package/src/tools/monitor.spec.ts +0 -172
  60. package/src/tools/observable.spec.ts +0 -259
  61. package/src/tools/queueMicrotask.spec.ts +0 -24
  62. package/src/tools/readBytesFromStream.spec.ts +0 -62
  63. package/src/tools/requestIdleCallback.spec.ts +0 -65
  64. package/src/tools/serialisation/jsonStringify.spec.ts +0 -76
  65. package/src/tools/serialisation/sanitize.spec.ts +0 -284
  66. package/src/tools/stackTrace/capturedExceptions.specHelper.ts +0 -316
  67. package/src/tools/stackTrace/computeStackTrace.spec.ts +0 -1007
  68. package/src/tools/stackTrace/handlingStack.spec.ts +0 -20
  69. package/src/tools/taskQueue.spec.ts +0 -60
  70. package/src/tools/timer.spec.ts +0 -76
  71. package/src/tools/utils/browserDetection.spec.ts +0 -120
  72. package/src/tools/utils/byteUtils.spec.ts +0 -29
  73. package/src/tools/utils/functionUtils.spec.ts +0 -229
  74. package/src/tools/utils/numberUtils.spec.ts +0 -27
  75. package/src/tools/utils/stringUtils.spec.ts +0 -74
  76. package/src/tools/utils/typeUtils.spec.ts +0 -25
  77. package/src/tools/utils/urlPolyfill.spec.ts +0 -55
  78. package/src/tools/valueHistory.spec.ts +0 -180
  79. package/src/transport/batch.spec.ts +0 -261
  80. package/src/transport/eventBridge.spec.ts +0 -90
  81. package/src/transport/flushController.spec.ts +0 -267
  82. package/src/transport/httpRequest.spec.ts +0 -400
  83. package/src/transport/sendWithRetryStrategy.spec.ts +0 -393
@@ -1,343 +0,0 @@
1
- import { disableJasmineUncaughtExceptionTracking, wait } from '../../../test'
2
- import type { UnhandledErrorCallback } from './trackRuntimeError'
3
- import { instrumentOnError, instrumentUnhandledRejection, trackRuntimeError } from './trackRuntimeError'
4
- import type { RawError } from './error.types'
5
-
6
- describe('trackRuntimeError', () => {
7
- const ERROR_MESSAGE = 'foo'
8
-
9
- const errorViaTrackRuntimeError = async (callback: () => void): Promise<RawError> => {
10
- disableJasmineUncaughtExceptionTracking()
11
-
12
- const errorObservable = trackRuntimeError()
13
- const errorNotification = new Promise<RawError>((resolve) => {
14
- errorObservable.subscribe((e: RawError) => resolve(e))
15
- })
16
-
17
- try {
18
- await invokeAndWaitForErrorHandlers(callback)
19
- return await errorNotification
20
- } finally {
21
- stop()
22
- }
23
- }
24
-
25
- it('should collect unhandled error', async () => {
26
- const error = await errorViaTrackRuntimeError(() => {
27
- throw new Error(ERROR_MESSAGE)
28
- })
29
- expect(error.message).toEqual(ERROR_MESSAGE)
30
- })
31
-
32
- it('should collect unhandled rejection', async () => {
33
- if (!('onunhandledrejection' in window)) {
34
- pending('onunhandledrejection not supported')
35
- }
36
-
37
- const error = await errorViaTrackRuntimeError(() => {
38
- // Reject with a string instead of an Error here because Jasmine forwards the
39
- // unhandled rejection to the onerror handler with the wrong argument structure if
40
- // you use an Error. (It uses the argument structure you'd use for
41
- // addEventListener('error'). We could make our error processing code robust to
42
- // that, but since it's a Jasmine-specific issue with a simple workaround, it makes
43
- // sense to just work around it here.
44
- // eslint-disable-next-line @typescript-eslint/prefer-promise-reject-errors
45
- void Promise.reject(ERROR_MESSAGE)
46
- })
47
- expect(error.message).toEqual(jasmine.stringContaining(ERROR_MESSAGE))
48
- })
49
- })
50
-
51
- describe('instrumentOnError', () => {
52
- const testLineNo = 1337
53
- const testColNo = 42
54
- const ERROR_MESSAGE = 'foo'
55
-
56
- const spyViaInstrumentOnError = async (callback: () => void) => {
57
- const onErrorSpy = spyOn(window as any, 'onerror')
58
- const callbackSpy = jasmine.createSpy<UnhandledErrorCallback>()
59
- const { stop } = instrumentOnError(callbackSpy)
60
-
61
- try {
62
- await invokeAndWaitForErrorHandlers(callback)
63
- expect(onErrorSpy).toHaveBeenCalled()
64
- return callbackSpy
65
- } finally {
66
- stop()
67
- }
68
- }
69
-
70
- it('should call original error handler', async () => {
71
- // withInstrumentOnError() asserts that the original error handler has been called for
72
- // every test, so we don't need an explicit expectation here.
73
- await spyViaInstrumentOnError(() => {
74
- throw new Error(ERROR_MESSAGE)
75
- })
76
- })
77
-
78
- it('should notify unhandled error instance', async () => {
79
- const error = new Error(ERROR_MESSAGE)
80
- const spy = await spyViaInstrumentOnError(() => {
81
- throw error
82
- })
83
-
84
- const [originalError, stack] = spy.calls.mostRecent().args
85
- expect(originalError).toBe(error)
86
- expect(stack).toBeUndefined()
87
- })
88
-
89
- it('should notify unhandled string', async () => {
90
- const error = 'foo' as any
91
- const spy = await spyViaInstrumentOnError(() => {
92
- throw error
93
- })
94
-
95
- const [originalError, stack] = spy.calls.mostRecent().args
96
- expect(originalError).toBe(error)
97
- expect(stack).toBeDefined()
98
- })
99
-
100
- it('should notify unhandled object', async () => {
101
- const error = { a: 'foo' } as any
102
- const spy = await spyViaInstrumentOnError(() => {
103
- throw error
104
- })
105
-
106
- const [originalError, stack] = spy.calls.mostRecent().args
107
- expect(originalError).toBe(error)
108
- expect(stack).toBeDefined()
109
- })
110
-
111
- describe('uncaught exception handling', () => {
112
- it('should not go into an infinite loop', async () => {
113
- const spy = await spyViaInstrumentOnError(() => {
114
- throw new Error('expected error')
115
- })
116
-
117
- expect(spy).toHaveBeenCalledTimes(1)
118
- await wait(1000)
119
- expect(spy).toHaveBeenCalledTimes(1)
120
- })
121
-
122
- it('should get extra arguments (isWindowError and exception)', async () => {
123
- const exception = new Error('expected error')
124
- const spy = await spyViaInstrumentOnError(() => {
125
- throw exception
126
- })
127
-
128
- expect(spy).toHaveBeenCalledTimes(1)
129
- await wait(1000)
130
- expect(spy).toHaveBeenCalledTimes(1)
131
- const [reportedError] = spy.calls.mostRecent().args
132
- expect(reportedError).toEqual(exception)
133
- })
134
- })
135
-
136
- describe('should handle direct onerror calls', () => {
137
- it('with objects', async () => {
138
- const error = { foo: 'bar' } as any
139
- const spy = await spyViaInstrumentOnError(() => {
140
- window.onerror!(error, 'http://example.com', testLineNo, testColNo)
141
- })
142
-
143
- const [originalError, stack] = spy.calls.mostRecent().args
144
- expect(originalError).toBe(error)
145
- expect(stack).toBeDefined()
146
- })
147
-
148
- describe('with undefined arguments', () => {
149
- it('discards the stack', async () => {
150
- // this is probably not good behavior; just writing this test to verify
151
- // that it doesn't change unintentionally
152
- const spy = await spyViaInstrumentOnError(() => {
153
- window.onerror!(undefined!, undefined, testLineNo)
154
- })
155
-
156
- const [, stack] = spy.calls.mostRecent().args
157
- expect(stack).toBeUndefined()
158
- })
159
- })
160
-
161
- describe('when no 5th argument (error object)', () => {
162
- it('should separate name, message for default error types (e.g. ReferenceError)', async () => {
163
- const spy = await spyViaInstrumentOnError(() => {
164
- window.onerror!('ReferenceError: foo is undefined', 'http://example.com', testLineNo)
165
- })
166
-
167
- const [, stack] = spy.calls.mostRecent().args
168
- expect(stack!.name).toEqual('ReferenceError')
169
- expect(stack!.message).toEqual('foo is undefined')
170
- })
171
-
172
- it('should separate name, message for default error types (e.g. Uncaught ReferenceError)', async () => {
173
- // should work with/without 'Uncaught'
174
- const spy = await spyViaInstrumentOnError(() => {
175
- window.onerror!('Uncaught ReferenceError: foo is undefined', 'http://example.com', testLineNo)
176
- })
177
-
178
- const [, stack] = spy.calls.mostRecent().args
179
- expect(stack!.name).toEqual('ReferenceError')
180
- expect(stack!.message).toEqual('foo is undefined')
181
- })
182
-
183
- it('should separate name, message for default error types on Opera Mini', async () => {
184
- const spy = await spyViaInstrumentOnError(() => {
185
- window.onerror!(
186
- 'Uncaught exception: ReferenceError: Undefined variable: foo',
187
- 'http://example.com',
188
- testLineNo
189
- )
190
- })
191
-
192
- const [, stack] = spy.calls.mostRecent().args
193
- expect(stack!.name).toEqual('ReferenceError')
194
- expect(stack!.message).toEqual('Undefined variable: foo')
195
- })
196
-
197
- it('should separate name, message for error with multiline message', async () => {
198
- const spy = await spyViaInstrumentOnError(() => {
199
- window.onerror!(
200
- "TypeError: foo is not a function. (In 'my.function(\n foo)",
201
- 'http://example.com',
202
- testLineNo
203
- )
204
- })
205
-
206
- const [, stack] = spy.calls.mostRecent().args
207
- expect(stack!.message).toEqual("foo is not a function. (In 'my.function(\n foo)")
208
- expect(stack!.name).toEqual('TypeError')
209
- })
210
-
211
- it('should ignore unknown error types', async () => {
212
- const spy = await spyViaInstrumentOnError(() => {
213
- window.onerror!('CustomError: woo scary', 'http://example.com', testLineNo)
214
- })
215
-
216
- // TODO: should we attempt to parse this?
217
- const [, stack] = spy.calls.mostRecent().args
218
- expect(stack!.name).toEqual(undefined)
219
- expect(stack!.message).toEqual('CustomError: woo scary')
220
- })
221
-
222
- it('should ignore arbitrary messages passed through onerror', async () => {
223
- const spy = await spyViaInstrumentOnError(() => {
224
- window.onerror!('all work and no play makes homer: something something', 'http://example.com', testLineNo)
225
- })
226
-
227
- const [, stack] = spy.calls.mostRecent().args
228
- expect(stack!.name).toEqual(undefined)
229
- expect(stack!.message).toEqual('all work and no play makes homer: something something')
230
- })
231
-
232
- it('should handle object message passed through onerror', async () => {
233
- const spy = await spyViaInstrumentOnError(() => {
234
- window.onerror!({ foo: 'bar' } as any, 'http://example.com', testLineNo, testColNo)
235
- })
236
-
237
- const [error, stack] = spy.calls.mostRecent().args
238
- expect(stack!.message).toBeUndefined()
239
- expect(error).toEqual({ foo: 'bar' }) // consider the message as initial error
240
- })
241
- })
242
-
243
- describe('when 5th argument (errorObj) is not of type Error', () => {
244
- it('should handle strings', async () => {
245
- const spy = await spyViaInstrumentOnError(() => {
246
- window.onerror!(
247
- 'Any error message',
248
- 'https://example.com',
249
- testLineNo,
250
- testColNo,
251
- 'Actual Error Message' as any
252
- )
253
- })
254
-
255
- const [error, stack] = spy.calls.mostRecent().args
256
- expect(stack!.message).toBe('Any error message')
257
- expect(stack!.stack).toEqual([{ url: 'https://example.com', column: testColNo, line: testLineNo }])
258
- expect(error).toEqual('Actual Error Message')
259
- })
260
-
261
- it('should handle objects', async () => {
262
- const spy = await spyViaInstrumentOnError(() => {
263
- window.onerror!('Any error message', 'https://example.com', testLineNo, testColNo, {
264
- message: 'SyntaxError',
265
- data: 'foo',
266
- } as any)
267
- })
268
-
269
- const [error, stack] = spy.calls.mostRecent().args
270
- expect(stack!.message).toBe('Any error message')
271
- expect(stack!.stack).toEqual([{ url: 'https://example.com', column: testColNo, line: testLineNo }])
272
- expect(error).toEqual({ message: 'SyntaxError', data: 'foo' })
273
- })
274
- })
275
- })
276
- })
277
-
278
- describe('instrumentUnhandledRejection', () => {
279
- const ERROR_MESSAGE = 'foo'
280
-
281
- const spyViaInstrumentOnUnhandledRejection = async (callback: () => void) => {
282
- if (!('onunhandledrejection' in window)) {
283
- pending('onunhandledrejection not supported')
284
- }
285
-
286
- const onUnhandledRejectionSpy = spyOn(window as any, 'onunhandledrejection')
287
- const callbackSpy = jasmine.createSpy<UnhandledErrorCallback>()
288
- const { stop } = instrumentUnhandledRejection(callbackSpy)
289
-
290
- try {
291
- await invokeAndWaitForErrorHandlers(callback)
292
- expect(onUnhandledRejectionSpy).toHaveBeenCalled()
293
- return callbackSpy
294
- } finally {
295
- stop()
296
- }
297
- }
298
-
299
- it('should call original unhandled rejection handler', async () => {
300
- // withInstrumentOnUnhandledRejection() asserts that the original unhandled
301
- // rejection handler has been called for every test, so we don't need an
302
- // explicit expectation here.
303
- await spyViaInstrumentOnUnhandledRejection(() => {
304
- window.onunhandledrejection!({
305
- reason: new Error(ERROR_MESSAGE),
306
- } as PromiseRejectionEvent)
307
- })
308
- })
309
-
310
- it('should notify unhandled rejection', async () => {
311
- const reason = new Error(ERROR_MESSAGE)
312
- const spy = await spyViaInstrumentOnUnhandledRejection(() => {
313
- window.onunhandledrejection!({ reason } as PromiseRejectionEvent)
314
- })
315
-
316
- const [originalError, stack] = spy.calls.mostRecent().args
317
- expect(originalError).toBe(reason)
318
- expect(stack).toBeUndefined()
319
- })
320
- })
321
-
322
- /**
323
- * Invokes the given callback, which is expected to be a function that throws or generates
324
- * an unhandled promise rejection, and returns a promise that resolves after the callback
325
- * has finished running and any global error handlers that run as a result are complete.
326
- */
327
- function invokeAndWaitForErrorHandlers(callback: () => void): Promise<void> {
328
- return new Promise<void>((resolve) => {
329
- setTimeout(() => {
330
- try {
331
- // Invoke the callback.
332
- callback()
333
- } finally {
334
- // The callback has generated an error here, but global error handlers
335
- // have not yet run. The global unhandledrejection handler will run at
336
- // the end of the next microtask checkpoint; the global error handler
337
- // will run in a later macrotask. So, schedule a new task to resolve
338
- // the promise after both of those things have happened.
339
- setTimeout(resolve)
340
- }
341
- })
342
- })
343
- }
@@ -1,119 +0,0 @@
1
- import type { Clock } from '../../../test'
2
- import { mockClock } from '../../../test'
3
- import { relativeToClocks, ONE_MINUTE } from '../../tools/utils/timeUtils'
4
- import { noop } from '../../tools/utils/functionUtils'
5
- import type { RawError } from '../error/error.types'
6
- import { createEventRateLimiter } from './createEventRateLimiter'
7
- import type { EventRateLimiter } from './createEventRateLimiter'
8
-
9
- describe('createEventRateLimiter', () => {
10
- let eventLimiter: EventRateLimiter | undefined
11
- let clock: Clock
12
- const limit = 1
13
- beforeEach(() => {
14
- clock = mockClock()
15
- })
16
-
17
- it('returns false if the limit is not reached', () => {
18
- eventLimiter = createEventRateLimiter('error', noop, limit)
19
-
20
- expect(eventLimiter.isLimitReached()).toBe(false)
21
- })
22
-
23
- it('returns true if the limit is reached', () => {
24
- eventLimiter = createEventRateLimiter('error', noop, limit)
25
-
26
- eventLimiter.isLimitReached()
27
- expect(eventLimiter.isLimitReached()).toBe(true)
28
- })
29
-
30
- it('returns false again when one minute is passed after the first counted error', () => {
31
- eventLimiter = createEventRateLimiter('error', noop, limit)
32
-
33
- eventLimiter.isLimitReached()
34
- eventLimiter.isLimitReached()
35
- clock.tick(ONE_MINUTE)
36
- expect(eventLimiter.isLimitReached()).toBe(false)
37
- })
38
-
39
- it('calls the "onLimitReached" callback with the raw "limit reached" error when the limit is reached', () => {
40
- const onLimitReachedSpy = jasmine.createSpy<(rawError: RawError) => void>()
41
- eventLimiter = createEventRateLimiter('error', onLimitReachedSpy, limit)
42
-
43
- eventLimiter.isLimitReached()
44
- eventLimiter.isLimitReached()
45
- expect(onLimitReachedSpy).toHaveBeenCalledOnceWith({
46
- message: 'Reached max number of errors by minute: 1',
47
- source: 'agent',
48
- startClocks: relativeToClocks(clock.relative(0)),
49
- })
50
- })
51
-
52
- it('returns false when called from the "onLimitReached" callback to bypass the limit for the "limit reached" error', () => {
53
- eventLimiter = createEventRateLimiter(
54
- 'error',
55
- () => {
56
- expect(eventLimiter!.isLimitReached()).toBe(false)
57
- },
58
- limit
59
- )
60
-
61
- eventLimiter.isLimitReached()
62
- eventLimiter.isLimitReached()
63
- })
64
-
65
- it('does not call the "onLimitReached" callback more than once when the limit is reached', () => {
66
- const onLimitReachedSpy = jasmine.createSpy<(rawError: RawError) => void>()
67
- eventLimiter = createEventRateLimiter('error', onLimitReachedSpy, limit)
68
-
69
- eventLimiter.isLimitReached()
70
- eventLimiter.isLimitReached()
71
- eventLimiter.isLimitReached()
72
- eventLimiter.isLimitReached()
73
- eventLimiter.isLimitReached()
74
- expect(onLimitReachedSpy).toHaveBeenCalledTimes(1)
75
- })
76
-
77
- it('returns true after reaching the limit even if the "onLimitReached" callback throws', () => {
78
- eventLimiter = createEventRateLimiter(
79
- 'error',
80
- () => {
81
- throw new Error('oops')
82
- },
83
- limit
84
- )
85
-
86
- eventLimiter.isLimitReached()
87
- expect(() => eventLimiter!.isLimitReached()).toThrow()
88
- expect(eventLimiter.isLimitReached()).toBe(true)
89
- expect(eventLimiter.isLimitReached()).toBe(true)
90
- })
91
-
92
- it('returns true when the limit is reached and the "onLimitReached" callback does not call "isLimitReached" (ex: excluded by beforeSend)', () => {
93
- eventLimiter = createEventRateLimiter(
94
- 'error',
95
- () => {
96
- // do not call isLimitReached
97
- },
98
- limit
99
- )
100
-
101
- eventLimiter.isLimitReached()
102
- eventLimiter.isLimitReached()
103
- expect(eventLimiter.isLimitReached()).toBe(true)
104
- })
105
-
106
- it('returns false only once when called from the "onLimitReached" callback (edge case)', () => {
107
- eventLimiter = createEventRateLimiter(
108
- 'error',
109
- () => {
110
- expect(eventLimiter!.isLimitReached()).toBe(false)
111
- expect(eventLimiter!.isLimitReached()).toBe(true)
112
- },
113
- limit
114
- )
115
-
116
- eventLimiter.isLimitReached()
117
- eventLimiter.isLimitReached()
118
- })
119
- })
@@ -1,47 +0,0 @@
1
- import {
2
- STACK_WITH_INIT_IN_EXTENSION,
3
- STACK_WITH_INIT_IN_EXTENSION_FIREFOX,
4
- STACK_WITH_INIT_IN_PAGE,
5
- } from '../../../test'
6
- import { containsExtensionUrl, EXTENSION_PREFIXES, isUnsupportedExtensionEnvironment } from './extensionUtils'
7
-
8
- describe('extensionUtils', () => {
9
- describe('containsExtensionUrl', () => {
10
- it('should return true if string contains an extension URL', () => {
11
- EXTENSION_PREFIXES.forEach((prefix) => {
12
- expect(containsExtensionUrl(`${prefix}some/path`)).toBe(true)
13
- })
14
- })
15
-
16
- it('should return false if string does not contain extension URL', () => {
17
- expect(containsExtensionUrl('https://example.com')).toBe(false)
18
- expect(containsExtensionUrl('')).toBe(false)
19
- })
20
- })
21
-
22
- describe('isUnsupportedExtensionEnvironment', () => {
23
- it('should return true when window location is a regular URL and error stack init is in an extension', () => {
24
- expect(isUnsupportedExtensionEnvironment('https://example.com', STACK_WITH_INIT_IN_EXTENSION)).toBe(true)
25
- })
26
-
27
- it('should return false when both window location and error stack init are regular URLs', () => {
28
- expect(isUnsupportedExtensionEnvironment('https://example.com', STACK_WITH_INIT_IN_PAGE)).toBe(false)
29
- })
30
-
31
- it('should return false when error stack is empty', () => {
32
- expect(isUnsupportedExtensionEnvironment('https://example.com', '')).toBe(false)
33
- })
34
-
35
- it('should handle each extension prefix in firefox', () => {
36
- expect(isUnsupportedExtensionEnvironment('https://example.com', STACK_WITH_INIT_IN_EXTENSION_FIREFOX)).toBe(true)
37
- })
38
-
39
- it('should handle case when stack trace is undefined', () => {
40
- expect(isUnsupportedExtensionEnvironment('https://example.com')).toBe(false)
41
- })
42
-
43
- it('should handle extension stack trace', () => {
44
- expect(isUnsupportedExtensionEnvironment('https://example.com', STACK_WITH_INIT_IN_EXTENSION)).toBe(true)
45
- })
46
- })
47
- })
@@ -1,71 +0,0 @@
1
- import type { MockCspEventListener, MockReportingObserver } from '../../../test'
2
- import { mockReportingObserver, mockCspEventListener, FAKE_CSP_VIOLATION_EVENT } from '../../../test'
3
- import type { Subscription } from '../../tools/observable'
4
- import type { Configuration } from '../configuration'
5
- import { ErrorHandling, ErrorSource } from '../error/error.types'
6
- import type { RawReportError } from './reportObservable'
7
- import { initReportObservable, RawReportType } from './reportObservable'
8
-
9
- describe('report observable', () => {
10
- let reportingObserver: MockReportingObserver
11
- let cspEventListener: MockCspEventListener
12
- let consoleSubscription: Subscription
13
- let notifyReport: jasmine.Spy<(reportError: RawReportError) => void>
14
- let configuration: Configuration
15
-
16
- beforeEach(() => {
17
- if (!window.ReportingObserver) {
18
- pending('ReportingObserver not supported')
19
- }
20
- configuration = {} as Configuration
21
- reportingObserver = mockReportingObserver()
22
- cspEventListener = mockCspEventListener()
23
- notifyReport = jasmine.createSpy('notifyReport')
24
- })
25
-
26
- afterEach(() => {
27
- consoleSubscription?.unsubscribe()
28
- })
29
- ;[RawReportType.deprecation, RawReportType.intervention].forEach((type) => {
30
- it(`should notify ${type} reports`, () => {
31
- consoleSubscription = initReportObservable(configuration, [type]).subscribe(notifyReport)
32
- reportingObserver.raiseReport(type)
33
-
34
- const [report] = notifyReport.calls.mostRecent().args
35
-
36
- expect(report).toEqual(
37
- jasmine.objectContaining({
38
- message: `${type}: foo bar`,
39
- type: 'NavigatorVibrate',
40
- })
41
- )
42
- })
43
- })
44
-
45
- it(`should compute stack for ${RawReportType.intervention}`, () => {
46
- consoleSubscription = initReportObservable(configuration, [RawReportType.intervention]).subscribe(notifyReport)
47
- reportingObserver.raiseReport(RawReportType.intervention)
48
-
49
- const [report] = notifyReport.calls.mostRecent().args
50
-
51
- expect(report.stack).toEqual(`NavigatorVibrate: foo bar
52
- at <anonymous> @ http://foo.bar/index.js:20:10`)
53
- })
54
-
55
- it(`should notify ${RawReportType.cspViolation}`, () => {
56
- consoleSubscription = initReportObservable(configuration, [RawReportType.cspViolation]).subscribe(notifyReport)
57
- cspEventListener.dispatchEvent()
58
-
59
- expect(notifyReport).toHaveBeenCalledOnceWith({
60
- startClocks: jasmine.any(Object),
61
- source: ErrorSource.REPORT,
62
- message: "csp_violation: 'blob' blocked by 'worker-src' directive",
63
- type: 'worker-src',
64
- originalError: FAKE_CSP_VIOLATION_EVENT,
65
- stack: `worker-src: 'blob' blocked by 'worker-src' directive of the policy "worker-src 'none'"
66
- at <anonymous> @ http://foo.bar/index.js:17:8`,
67
- handling: ErrorHandling.UNHANDLED,
68
- csp: { disposition: 'enforce' },
69
- })
70
- })
71
- })
@@ -1,76 +0,0 @@
1
- import { getCookie, resetInitCookies, setCookie } from '../../browser/cookie'
2
- import { getSessionState } from '../../../test'
3
- import type { Configuration } from '../configuration'
4
- import {
5
- OLD_LOGS_COOKIE_NAME,
6
- OLD_RUM_COOKIE_NAME,
7
- OLD_SESSION_COOKIE_NAME,
8
- tryOldCookiesMigration,
9
- } from './oldCookiesMigration'
10
- import { SESSION_EXPIRATION_DELAY } from './sessionConstants'
11
- import { initCookieStrategy } from './storeStrategies/sessionInCookie'
12
- import type { SessionStoreStrategy } from './storeStrategies/sessionStoreStrategy'
13
- import { SESSION_STORE_KEY } from './storeStrategies/sessionStoreStrategy'
14
- const DEFAULT_INIT_CONFIGURATION = { trackAnonymousUser: true } as Configuration
15
-
16
- describe('old cookies migration', () => {
17
- let sessionStoreStrategy: SessionStoreStrategy
18
-
19
- beforeEach(() => {
20
- sessionStoreStrategy = initCookieStrategy(DEFAULT_INIT_CONFIGURATION, {})
21
- resetInitCookies()
22
- })
23
-
24
- afterEach(() => {
25
- resetInitCookies()
26
- })
27
-
28
- it('should not touch current cookie', () => {
29
- setCookie(SESSION_STORE_KEY, 'id=abcde&rum=0&logs=1&expire=1234567890', SESSION_EXPIRATION_DELAY)
30
-
31
- tryOldCookiesMigration(sessionStoreStrategy)
32
-
33
- expect(getCookie(SESSION_STORE_KEY)).toBe('id=abcde&rum=0&logs=1&expire=1234567890')
34
- })
35
-
36
- it('should create new cookie from old cookie values', () => {
37
- setCookie(OLD_SESSION_COOKIE_NAME, 'abcde', SESSION_EXPIRATION_DELAY)
38
- setCookie(OLD_LOGS_COOKIE_NAME, '1', SESSION_EXPIRATION_DELAY)
39
- setCookie(OLD_RUM_COOKIE_NAME, '0', SESSION_EXPIRATION_DELAY)
40
-
41
- tryOldCookiesMigration(sessionStoreStrategy)
42
-
43
- expect(getSessionState(SESSION_STORE_KEY).id).toBe('abcde')
44
- expect(getSessionState(SESSION_STORE_KEY).rum).toBe('0')
45
- expect(getSessionState(SESSION_STORE_KEY).logs).toBe('1')
46
- expect(getSessionState(SESSION_STORE_KEY).expire).toMatch(/\d+/)
47
- })
48
-
49
- it('should create new cookie from a single old cookie', () => {
50
- setCookie(OLD_RUM_COOKIE_NAME, '0', SESSION_EXPIRATION_DELAY)
51
-
52
- tryOldCookiesMigration(sessionStoreStrategy)
53
- expect(getSessionState(SESSION_STORE_KEY).id).not.toBeDefined()
54
- expect(getSessionState(SESSION_STORE_KEY).rum).toBe('0')
55
- expect(getSessionState(SESSION_STORE_KEY).expire).toMatch(/\d+/)
56
- })
57
-
58
- it('should not create a new cookie if no old cookie is present', () => {
59
- tryOldCookiesMigration(sessionStoreStrategy)
60
- expect(getCookie(SESSION_STORE_KEY)).toBeUndefined()
61
- })
62
-
63
- it('should behave correctly when performing the migration multiple times', () => {
64
- setCookie(OLD_SESSION_COOKIE_NAME, 'abcde', SESSION_EXPIRATION_DELAY)
65
- setCookie(OLD_LOGS_COOKIE_NAME, '1', SESSION_EXPIRATION_DELAY)
66
- setCookie(OLD_RUM_COOKIE_NAME, '0', SESSION_EXPIRATION_DELAY)
67
-
68
- tryOldCookiesMigration(sessionStoreStrategy)
69
- tryOldCookiesMigration(sessionStoreStrategy)
70
-
71
- expect(getSessionState(SESSION_STORE_KEY).id).toBe('abcde')
72
- expect(getSessionState(SESSION_STORE_KEY).rum).toBe('0')
73
- expect(getSessionState(SESSION_STORE_KEY).logs).toBe('1')
74
- expect(getSessionState(SESSION_STORE_KEY).expire).toMatch(/\d+/)
75
- })
76
- })