Skip to content

Commit 78bfeb8

Browse files
authored
Extract canSendReplay into its own private ReplayManager static function (#1343)
1 parent 2542736 commit 78bfeb8

File tree

2 files changed

+104
-5
lines changed

2 files changed

+104
-5
lines changed

src/browser/replay/replayManager.js

Lines changed: 30 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -248,6 +248,31 @@ export default class ReplayManager {
248248
return replayId;
249249
}
250250

251+
/**
252+
* Determines if a replay can be sent based on API response and headers.
253+
*
254+
* @param {Error|null} err - Any error that occurred during the API request
255+
* @param {Object|null} resp - The API response object
256+
* @param {Object|null} hs - The response headers
257+
* @returns {boolean} true if the replay can be sent, false otherwise.
258+
* @private
259+
*/
260+
static _canSendReplay(err, resp, hs) {
261+
if (!hs) return false;
262+
263+
const hasNoErrors = !err && resp?.err === 0;
264+
265+
const headers = Object.fromEntries(
266+
Object.entries(hs).map(([k, v]) => [k.toLowerCase(), String(v).trim()]),
267+
);
268+
269+
const headersAreValid =
270+
headers['rollbar-replay-enabled'] === 'true' &&
271+
headers['rollbar-replay-ratelimit-remaining'] !== '0';
272+
273+
return hasNoErrors && headersAreValid;
274+
}
275+
251276
/**
252277
* Sends or discards a replay based on whether it can be sent.
253278
*
@@ -260,13 +285,13 @@ export default class ReplayManager {
260285
* Called by Queue after determining replay eligibility from API response.
261286
*
262287
* @param {string} replayId - The ID of the replay to send or discard
288+
* @param {Error|null} err - Any error that occurred during the API request
289+
* @param {Object|null} resp - The API response object
290+
* @param {Object|null} headers - The response headers
291+
* @returns {Promise<void>} A promise that resolves when the operation is complete
263292
*/
264293
async sendOrDiscardReplay(replayId, err, resp, headers) {
265-
const canSendReplay =
266-
!err &&
267-
resp?.err === 0 &&
268-
headers?.['Rollbar-Replay-Enabled'] === 'true' &&
269-
headers?.['Rollbar-Replay-RateLimit-Remaining'] !== '0';
294+
const canSendReplay = ReplayManager._canSendReplay(err, resp, headers);
270295

271296
if (canSendReplay) {
272297
try {

test/replay/unit/replayManager.test.js

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -429,6 +429,80 @@ describe('ReplayManager', function () {
429429
});
430430
});
431431

432+
describe('_canSendReplay', function () {
433+
it('returns true when all conditions are met', function () {
434+
const result = ReplayManager._canSendReplay(
435+
null,
436+
{ err: 0 },
437+
{
438+
'Rollbar-Replay-Enabled': 'true',
439+
'Rollbar-Replay-RateLimit-Remaining': '10',
440+
},
441+
);
442+
expect(result).to.be.true;
443+
});
444+
445+
it('returns false when err is truthy', function () {
446+
const result = ReplayManager._canSendReplay(
447+
new Error('API error'),
448+
{ err: 0 },
449+
{ 'Rollbar-Replay-Enabled': 'true' },
450+
);
451+
expect(result).to.be.false;
452+
});
453+
454+
it('returns false when resp.err is non-zero', function () {
455+
const result = ReplayManager._canSendReplay(null, { err: 1 }, {
456+
'Rollbar-Replay-Enabled': 'true',
457+
});
458+
expect(result).to.be.false;
459+
});
460+
461+
it('returns false when resp is null', function () {
462+
const result = ReplayManager._canSendReplay(null, null, {
463+
'Rollbar-Replay-Enabled': 'true',
464+
});
465+
expect(result).to.be.false;
466+
});
467+
468+
it('returns false when Rollbar-Replay-Enabled is not "true"', function () {
469+
const result = ReplayManager._canSendReplay(null, { err: 0 }, {
470+
'Rollbar-Replay-Enabled': 'false',
471+
'Rollbar-Replay-RateLimit-Remaining': '10',
472+
});
473+
expect(result).to.be.false;
474+
});
475+
476+
it('returns false when Rollbar-Replay-RateLimit-Remaining is "0"', function () {
477+
const result = ReplayManager._canSendReplay(null, { err: 0 }, {
478+
'Rollbar-Replay-Enabled': 'true',
479+
'Rollbar-Replay-RateLimit-Remaining': '0',
480+
});
481+
expect(result).to.be.false;
482+
});
483+
484+
it('returns false when headers are null', function () {
485+
const result = ReplayManager._canSendReplay(null, { err: 0 }, null);
486+
expect(result).to.be.false;
487+
});
488+
489+
it('handles case-insensitive headers', function () {
490+
const result = ReplayManager._canSendReplay(null, { err: 0 }, {
491+
'rollbar-replay-enabled': 'true',
492+
'ROLLBAR-REPLAY-RATELIMIT-REMAINING': '10',
493+
});
494+
expect(result).to.be.true;
495+
});
496+
497+
it('handles whitespace in header values', function () {
498+
const result = ReplayManager._canSendReplay(null, { err: 0 }, {
499+
'Rollbar-Replay-Enabled': ' true ',
500+
'Rollbar-Replay-RateLimit-Remaining': ' 10 ',
501+
});
502+
expect(result).to.be.true;
503+
});
504+
});
505+
432506
describe('sendOrDiscardReplay', function () {
433507
beforeEach(function () {
434508
replayManager.setSpans('test-replay', [{ id: 'span1' }]);

0 commit comments

Comments
 (0)