Skip to content

Commit dd29abd

Browse files
authored
Added missing unit tests for the Recorder (#1344)
1 parent 78bfeb8 commit dd29abd

File tree

2 files changed

+221
-0
lines changed

2 files changed

+221
-0
lines changed

test/replay/unit/recorder.collectEvents.test.js

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { expect } from 'chai';
2+
import sinon from 'sinon';
23
import { EventType } from '@rrweb/types';
34

45
import Recorder from '../../../src/browser/replay/recorder.js';
@@ -140,6 +141,21 @@ describe('Recorder buffer-index event collection', function () {
140141
});
141142
});
142143

144+
describe('_replayEndEvent', function () {
145+
it('returns replay.end marker event with current timestamp', function () {
146+
const clock = sinon.useFakeTimers(1234567890);
147+
const event = Recorder._replayEndEvent();
148+
149+
expect(event).to.deep.equal({
150+
type: EventType.Custom,
151+
timestamp: 1234567890,
152+
data: { tag: 'replay.end', payload: {} },
153+
});
154+
155+
clock.restore();
156+
});
157+
});
158+
143159
describe('bufferCursor', () => {
144160
it('returns current buffer index and offset', () => {
145161
recorder._buffers[0] = [

test/replay/unit/recorder.test.js

Lines changed: 205 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,205 @@
1+
import { expect } from 'chai';
2+
import sinon from 'sinon';
3+
4+
import Recorder from '../../../src/browser/replay/recorder.js';
5+
6+
describe('Recorder', function () {
7+
const mockRecordFn = () => () => {};
8+
9+
describe('constructor', function () {
10+
it('initializes with provided options', function () {
11+
const options = {
12+
enabled: true,
13+
autoStart: false,
14+
maxSeconds: 10,
15+
postDuration: 5,
16+
};
17+
18+
const recorder = new Recorder(options, mockRecordFn);
19+
20+
expect(recorder.options).to.deep.equal({
21+
enabled: true,
22+
autoStart: false,
23+
maxSeconds: 10,
24+
postDuration: 5,
25+
triggers: undefined,
26+
debug: undefined,
27+
});
28+
expect(recorder.isReady).to.be.false;
29+
expect(recorder.isRecording).to.be.false;
30+
});
31+
32+
it('throws when recordFn is not provided', function () {
33+
expect(() => new Recorder({}, null)).to.throw(
34+
TypeError,
35+
"Expected 'recordFn' to be provided",
36+
);
37+
});
38+
39+
it('initializes buffers and slots correctly', function () {
40+
const recorder = new Recorder({}, mockRecordFn);
41+
42+
expect(recorder._buffers).to.deep.equal([[], []]);
43+
expect(recorder._currentSlot).to.equal(0);
44+
expect(recorder._previousSlot).to.equal(1);
45+
});
46+
});
47+
48+
describe('options getter/setter', function () {
49+
it('returns configured options', function () {
50+
const recorder = new Recorder(
51+
{ enabled: true, maxSeconds: 10 },
52+
mockRecordFn,
53+
);
54+
55+
expect(recorder.options).to.have.property('enabled', true);
56+
expect(recorder.options).to.have.property('maxSeconds', 10);
57+
});
58+
59+
it('calls configure when setting options', function () {
60+
const recorder = new Recorder({}, mockRecordFn);
61+
sinon.spy(recorder, 'configure');
62+
63+
recorder.options = { enabled: false };
64+
65+
sinon.assert.calledOnce(recorder.configure);
66+
sinon.assert.calledWith(recorder.configure, { enabled: false });
67+
});
68+
});
69+
70+
describe('configure', function () {
71+
it('updates Rollbar options', function () {
72+
const recorder = new Recorder({ enabled: true }, mockRecordFn);
73+
74+
recorder.configure({
75+
enabled: false,
76+
maxSeconds: 20,
77+
postDuration: 10,
78+
triggers: ['error'],
79+
debug: { logEmits: true },
80+
});
81+
82+
expect(recorder.options).to.deep.equal({
83+
enabled: false,
84+
autoStart: undefined,
85+
maxSeconds: 20,
86+
postDuration: 10,
87+
triggers: ['error'],
88+
debug: { logEmits: true },
89+
});
90+
});
91+
92+
it('separates rrweb options from Rollbar options', function () {
93+
const recorder = new Recorder({}, mockRecordFn);
94+
95+
recorder.configure({
96+
enabled: true,
97+
maxSeconds: 10,
98+
sampling: { mousemove: true },
99+
blockClass: 'rr-block',
100+
});
101+
102+
expect(recorder.options).to.not.have.property('sampling');
103+
expect(recorder.options).to.not.have.property('blockClass');
104+
expect(recorder._rrwebOptions).to.have.property('sampling');
105+
expect(recorder._rrwebOptions).to.have.property('blockClass');
106+
});
107+
108+
it('filters out disallowed rrweb options', function () {
109+
const recorder = new Recorder({}, mockRecordFn);
110+
111+
recorder.configure({
112+
enabled: true,
113+
emit: () => {},
114+
checkoutEveryNms: 5000,
115+
});
116+
117+
expect(recorder._rrwebOptions).to.not.have.property('emit');
118+
expect(recorder._rrwebOptions).to.not.have.property('checkoutEveryNms');
119+
});
120+
121+
it('stops recording when enabled is set to false', function () {
122+
const recorder = new Recorder({ enabled: true }, mockRecordFn);
123+
recorder._stopFn = () => {};
124+
sinon.spy(recorder, 'stop');
125+
126+
recorder.configure({ enabled: false });
127+
128+
sinon.assert.calledOnce(recorder.stop);
129+
});
130+
});
131+
132+
describe('isRecording', function () {
133+
it('returns false when not recording', function () {
134+
const recorder = new Recorder({}, mockRecordFn);
135+
136+
expect(recorder.isRecording).to.be.false;
137+
});
138+
139+
it('returns true when recording', function () {
140+
const recorder = new Recorder({}, mockRecordFn);
141+
recorder._stopFn = () => {};
142+
143+
expect(recorder.isRecording).to.be.true;
144+
});
145+
});
146+
147+
describe('isReady', function () {
148+
it('returns false initially', function () {
149+
const recorder = new Recorder({}, mockRecordFn);
150+
151+
expect(recorder.isReady).to.be.false;
152+
});
153+
});
154+
155+
describe('checkoutEveryNms', function () {
156+
it('returns half of maxSeconds in milliseconds', function () {
157+
const recorder = new Recorder({ maxSeconds: 10 }, mockRecordFn);
158+
159+
expect(recorder.checkoutEveryNms()).to.equal(5000);
160+
});
161+
162+
it('uses default of 10 seconds when maxSeconds not provided', function () {
163+
const recorder = new Recorder({}, mockRecordFn);
164+
165+
expect(recorder.checkoutEveryNms()).to.equal(5000);
166+
});
167+
168+
it('calculates correctly for different maxSeconds values', function () {
169+
const recorder = new Recorder({ maxSeconds: 20 }, mockRecordFn);
170+
171+
expect(recorder.checkoutEveryNms()).to.equal(10000);
172+
});
173+
});
174+
175+
describe('_previousSlot', function () {
176+
it('returns 1 when currentSlot is 0', function () {
177+
const recorder = new Recorder({}, mockRecordFn);
178+
recorder._currentSlot = 0;
179+
180+
expect(recorder._previousSlot).to.equal(1);
181+
});
182+
183+
it('returns 0 when currentSlot is 1', function () {
184+
const recorder = new Recorder({}, mockRecordFn);
185+
recorder._currentSlot = 1;
186+
187+
expect(recorder._previousSlot).to.equal(0);
188+
});
189+
});
190+
191+
describe('clear', function () {
192+
it('resets buffers and state', function () {
193+
const recorder = new Recorder({}, mockRecordFn);
194+
recorder._buffers = [[{ data: 1 }], [{ data: 2 }]];
195+
recorder._currentSlot = 1;
196+
recorder._isReady = true;
197+
198+
recorder.clear();
199+
200+
expect(recorder._buffers).to.deep.equal([[], []]);
201+
expect(recorder._currentSlot).to.equal(0);
202+
expect(recorder.isReady).to.be.false;
203+
});
204+
});
205+
});

0 commit comments

Comments
 (0)