From 1106c7d7855662ffcb6ed41cc1067b645c08a0da Mon Sep 17 00:00:00 2001 From: Paul D'Ambra Date: Wed, 10 Jan 2024 16:28:13 +0000 Subject: [PATCH] feat: capture session options in a custom event (#954) * feat: capture session options in a custom event * update integration tests --- cypress/e2e/session-recording.cy.js | 9 +++++--- .../replay/sessionrecording.test.ts | 23 +++++++++++++++++++ src/extensions/replay/sessionrecording.ts | 8 ++++++- 3 files changed, 36 insertions(+), 4 deletions(-) diff --git a/cypress/e2e/session-recording.cy.js b/cypress/e2e/session-recording.cy.js index 5f3a07585..83bc810a5 100644 --- a/cypress/e2e/session-recording.cy.js +++ b/cypress/e2e/session-recording.cy.js @@ -44,8 +44,9 @@ describe('Session recording', () => { // a meta and then a full snapshot expect(captures[1]['properties']['$snapshot_data'][0].type).to.equal(4) // meta expect(captures[1]['properties']['$snapshot_data'][1].type).to.equal(2) // full_snapshot + expect(captures[1]['properties']['$snapshot_data'][2].type).to.equal(5) // custom event with options // Making a set from the rest should all be 3 - incremental snapshots - const incrementalSnapshots = captures[1]['properties']['$snapshot_data'].slice(2) + const incrementalSnapshots = captures[1]['properties']['$snapshot_data'].slice(3) expect(new Set(incrementalSnapshots.map((s) => s.type))).to.deep.equal(new Set([3])) }) }) @@ -84,9 +85,10 @@ describe('Session recording', () => { // a meta and then a full snapshot expect(captures[1]['properties']['$snapshot_data'][0].type).to.equal(4) // meta expect(captures[1]['properties']['$snapshot_data'][1].type).to.equal(2) // full_snapshot + expect(captures[1]['properties']['$snapshot_data'][2].type).to.equal(5) // custom event with options // Making a set from the rest should all be 3 - incremental snapshots expect( - new Set(captures[1]['properties']['$snapshot_data'].slice(2).map((s) => s.type)) + new Set(captures[1]['properties']['$snapshot_data'].slice(3).map((s) => s.type)) ).to.deep.equal(new Set([3])) }) }) @@ -205,9 +207,10 @@ describe('Session recording', () => { // a meta and then a full snapshot expect(captures[1]['properties']['$snapshot_data'][0].type).to.equal(4) // meta expect(captures[1]['properties']['$snapshot_data'][1].type).to.equal(2) // full_snapshot + expect(captures[1]['properties']['$snapshot_data'][2].type).to.equal(5) // custom event with options const xPositions = [] - for (let i = 2; i < captures[1]['properties']['$snapshot_data'].length; i++) { + for (let i = 3; i < captures[1]['properties']['$snapshot_data'].length; i++) { expect(captures[1]['properties']['$snapshot_data'][i].type).to.equal(3) expect(captures[1]['properties']['$snapshot_data'][i].data.source).to.equal( 6, diff --git a/src/__tests__/extensions/replay/sessionrecording.test.ts b/src/__tests__/extensions/replay/sessionrecording.test.ts index 79e23290f..bee68567e 100644 --- a/src/__tests__/extensions/replay/sessionrecording.test.ts +++ b/src/__tests__/extensions/replay/sessionrecording.test.ts @@ -179,6 +179,7 @@ describe('SessionRecording', () => { // need to cast as any to mock private methods jest.spyOn(sessionRecording as any, 'startCaptureAndTrySendingQueuedSnapshots') jest.spyOn(sessionRecording, 'stopRecording') + jest.spyOn(sessionRecording as any, '_tryAddCustomEvent') }) it('call startCaptureAndTrySendingQueuedSnapshots if its enabled', () => { @@ -186,6 +187,28 @@ describe('SessionRecording', () => { expect((sessionRecording as any).startCaptureAndTrySendingQueuedSnapshots).toHaveBeenCalled() }) + it('emits an options event', () => { + sessionRecording.startRecordingIfEnabled() + expect((sessionRecording as any)['_tryAddCustomEvent']).toHaveBeenCalledWith('$session_options', { + activePlugins: [], + sessionRecordingOptions: { + blockClass: 'ph-no-capture', + blockSelector: undefined, + collectFonts: false, + ignoreClass: 'ph-ignore-input', + inlineStylesheet: true, + maskAllInputs: false, + maskInputFn: undefined, + maskInputOptions: {}, + maskTextClass: 'ph-mask', + maskTextFn: undefined, + maskTextSelector: undefined, + recordCrossOriginIframes: false, + slimDOMOptions: {}, + }, + }) + }) + it('call stopRecording if its not enabled', () => { posthog.config.disable_session_recording = true sessionRecording.startRecordingIfEnabled() diff --git a/src/extensions/replay/sessionrecording.ts b/src/extensions/replay/sessionrecording.ts index 99ee95e44..d3c71eeab 100644 --- a/src/extensions/replay/sessionrecording.ts +++ b/src/extensions/replay/sessionrecording.ts @@ -511,11 +511,12 @@ export class SessionRecording { }, }) + const activePlugins = this._gatherRRWebPlugins() this.stopRrweb = this.rrwebRecord({ emit: (event) => { this.onRRwebEmit(event) }, - plugins: this._gatherRRWebPlugins(), + plugins: activePlugins, ...sessionRecordingOptions, }) @@ -540,6 +541,11 @@ export class SessionRecording { // We reset the last activity timestamp, resetting the idle timer this._lastActivityTimestamp = Date.now() this.isIdle = false + + this._tryAddCustomEvent('$session_options', { + sessionRecordingOptions, + activePlugins: activePlugins.map((p) => p?.name), + }) } private _gatherRRWebPlugins() {