@@ -6,23 +6,55 @@ import 'jsdom-worker';
66import type { MockInstance } from 'vitest' ;
77import { afterEach , beforeEach , describe , expect , it , vi } from 'vitest' ;
88import { EventBufferProxy } from '../../../src/eventBuffer/EventBufferProxy' ;
9+ import { debug } from '../../../src/util/logger' ;
910import { BASE_TIMESTAMP } from '../..' ;
1011import { decompress } from '../../utils/compression' ;
1112import { getTestEventIncremental } from '../../utils/getTestEvent' ;
1213import { createEventBuffer } from './../../../src/eventBuffer' ;
1314
1415const TEST_EVENT = getTestEventIncremental ( { timestamp : BASE_TIMESTAMP } ) ;
1516
17+ /**
18+ * Worker stub that only answers when the test tells it to, so the buffer can be
19+ * destroyed while the switch to the compression worker is still in flight.
20+ */
21+ class ControlledWorker extends EventTarget {
22+ public posted : Array < { id : number ; method : string } > = [ ] ;
23+
24+ public postMessage ( data : unknown ) : void {
25+ this . posted . push ( data as { id : number ; method : string } ) ;
26+ }
27+
28+ public terminate ( ) : void {
29+ // noop
30+ }
31+
32+ /** Emit the message the worker sends once its script has loaded. */
33+ public sendReady ( ) : void {
34+ this . dispatchEvent ( new MessageEvent ( 'message' , { data : { success : true } } ) ) ;
35+ }
36+
37+ /** Answer all posted requests with an unsuccessful response. */
38+ public failAll ( ) : void {
39+ this . posted . forEach ( ( { id, method } ) => {
40+ this . dispatchEvent ( new MessageEvent ( 'message' , { data : { id, method, success : false } } ) ) ;
41+ } ) ;
42+ }
43+ }
44+
1645describe ( 'Unit | eventBuffer | EventBufferProxy' , ( ) => {
1746 let consoleErrorSpy : MockInstance < any > ;
47+ let exceptionSpy : MockInstance < any > ;
1848
1949 beforeEach ( ( ) => {
2050 // Avoid logging errors to console
2151 consoleErrorSpy = vi . spyOn ( console , 'error' ) . mockImplementation ( ( ) => { } ) ;
52+ exceptionSpy = vi . spyOn ( debug , 'exception' ) . mockImplementation ( ( ) => { } ) ;
2253 } ) ;
2354
2455 afterEach ( ( ) => {
2556 consoleErrorSpy . mockRestore ( ) ;
57+ exceptionSpy . mockRestore ( ) ;
2658 } ) ;
2759
2860 it ( 'waits for the worker to be loaded when calling finish' , async function ( ) {
@@ -67,4 +99,34 @@ describe('Unit | eventBuffer | EventBufferProxy', () => {
6799 expect ( typeof result2 ) . toBe ( 'string' ) ;
68100 expect ( result2 ) . toEqual ( JSON . stringify ( [ TEST_EVENT , TEST_EVENT , TEST_EVENT ] ) ) ;
69101 } ) ;
102+
103+ it ( 'does not report an error if the worker is destroyed while switching buffers' , async function ( ) {
104+ const worker = new ControlledWorker ( ) ;
105+ const buffer = new EventBufferProxy ( worker as unknown as Worker ) ;
106+
107+ await buffer . addEvent ( TEST_EVENT ) ;
108+
109+ worker . sendReady ( ) ;
110+ await vi . waitFor ( ( ) => expect ( worker . posted ) . toHaveLength ( 1 ) ) ;
111+
112+ buffer . destroy ( ) ;
113+
114+ await buffer . ensureWorkerIsLoaded ( ) ;
115+ expect ( exceptionSpy ) . not . toHaveBeenCalled ( ) ;
116+ } ) ;
117+
118+ it ( 'reports an error if adding events fails while switching buffers' , async function ( ) {
119+ const worker = new ControlledWorker ( ) ;
120+ const buffer = new EventBufferProxy ( worker as unknown as Worker ) ;
121+
122+ await buffer . addEvent ( TEST_EVENT ) ;
123+
124+ worker . sendReady ( ) ;
125+ await vi . waitFor ( ( ) => expect ( worker . posted ) . toHaveLength ( 1 ) ) ;
126+
127+ worker . failAll ( ) ;
128+
129+ await buffer . ensureWorkerIsLoaded ( ) ;
130+ expect ( exceptionSpy ) . toHaveBeenCalledWith ( expect . any ( Error ) , 'Failed to add events when switching buffers.' ) ;
131+ } ) ;
70132} ) ;
0 commit comments