Skip to content

Commit 8e5921e

Browse files
committed
fix sr api inconsistencies
1 parent a9b249e commit 8e5921e

File tree

4 files changed

+105
-7
lines changed

4 files changed

+105
-7
lines changed

src/features/session_replay/aggregate/index.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,7 @@ export class Aggregate extends AggregateBase {
136136
if (!this.agentRef.runtime.isRecording) this.recorder.startRecording(TRIGGERS.SWITCH_TO_FULL, this.mode) // off --> full
137137
this.syncWithSessionManager({ sessionReplayMode: this.mode })
138138
} else {
139-
this.initializeRecording(MODE.FULL, true)
139+
this.initializeRecording(MODE.FULL, true, TRIGGERS.SWITCH_TO_FULL)
140140
}
141141
}
142142

src/features/session_replay/shared/recorder.js

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,11 @@ export class Recorder {
5757
this.stopRecording()
5858
}, this.srFeatureName, this.ee)
5959

60-
registerHandler(RRWEB_DATA_CHANNEL, (event, isCheckout) => { this.audit(event, isCheckout) }, this.srFeatureName, this.ee)
60+
/** If Agg is already drained before importing the recorder (likely deferred API call pattern),
61+
* registerHandler wont do anything. Just set up the on listener directly */
62+
const processReplayNode = (event, isCheckout) => { this.audit(event, isCheckout) }
63+
if (this.srInstrument.featAggregate?.drained) this.ee.on(RRWEB_DATA_CHANNEL, processReplayNode)
64+
else registerHandler(RRWEB_DATA_CHANNEL, processReplayNode, this.srFeatureName, this.ee)
6165
}
6266

6367
get trigger () {
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
<!DOCTYPE html>
2+
<!--
3+
Copyright 2020 New Relic Corporation.
4+
PDX-License-Identifier: Apache-2.0
5+
-->
6+
<html>
7+
<head>
8+
<title>RUM Unit Test</title>
9+
<style>
10+
.left{
11+
position: absolute; left: 50px; top: 200px;
12+
}
13+
.right {
14+
position: absolute; right: 50px; top: 200px;
15+
}
16+
</style>
17+
<link rel="stylesheet" type="text/css" href="style.css">
18+
{init}
19+
{config}
20+
<script>
21+
localStorage.clear()
22+
NREUM.init.privacy.cookies_enabled = true
23+
NREUM.init.session_replay.enabled = true
24+
window.addEventListener('load', () => {console.log("loaded")})
25+
</script>
26+
{loader}
27+
</head>
28+
<body>
29+
this is a page that provides several types of elements with selectors that session_replay can interact with based on how it is configured
30+
<hr />
31+
<hr />
32+
<textarea id="plain"></textarea>
33+
<textarea id="ignore" class="nr-ignore"></textarea>
34+
<textarea id="block" class="nr-block"></textarea>
35+
<textarea id="mask" class="nr-mask"></textarea>
36+
<textarea id="nr-block" data-nr-block></textarea>
37+
<textarea id="other-block" data-other-block></textarea>
38+
<input type="password" id="pass-input">
39+
<input type="text" id="text-input">
40+
<hr />
41+
<button onclick="moveImage()">Click</button>
42+
<img src="https://upload.wikimedia.org/wikipedia/commons/d/d7/House_of_Commons_Chamber_1.png" />
43+
<a href="./rrweb-instrumented.html" target="_blank">New Tab</a>
44+
<script>
45+
function moveImage(){
46+
document.querySelector("img").classList.toggle("left")
47+
document.querySelector("img").classList.toggle("right")
48+
}
49+
</script>
50+
</body>
51+
</html>

tests/specs/session-replay/sr-api.e2e.js

Lines changed: 48 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,66 @@
1+
import { testBlobReplayRequest } from '../../../tools/testing-server/utils/expect-tests'
12
import { srConfig, getSR } from '../util/helpers'
23

34
describe('Replay API', () => {
5+
let sessionReplaysCapture
6+
beforeEach(async () => {
7+
sessionReplaysCapture = await browser.testHandle.createNetworkCaptures('bamServer', { test: testBlobReplayRequest })
8+
})
49
afterEach(async () => {
510
await browser.destroyAgentSession()
611
})
712

8-
it('recordReplay called before page load does not start a replay (no entitlements yet)', async () => {
13+
it('recordReplay called before page load starts a replay', async () => {
14+
await browser.enableSessionReplay(0, 0)
15+
const [sessionReplayHarvests] = await Promise.all([
16+
sessionReplaysCapture.waitForResult({ totalCount: 1 }),
17+
browser.url(await browser.testHandle.assetURL('rrweb-api-record-before-load.html', srConfig()))
18+
.then(() => browser.waitForFeatureAggregate('session_replay'))
19+
])
20+
21+
await browser.pause(1000)
22+
await expect(getSR()).resolves.toMatchObject({
23+
initialized: true,
24+
mode: 1
25+
})
26+
expect(sessionReplayHarvests.length).toBeGreaterThanOrEqual(1)
27+
})
28+
29+
it('recordReplay called after page load starts a replay', async () => {
930
await browser.enableSessionReplay(0, 0)
10-
await browser.url(await browser.testHandle.assetURL('rrweb-api-record-before-load.html', srConfig()))
31+
32+
browser.url(await browser.testHandle.assetURL('rrweb-api-record-no-call.html', srConfig()))
1133
.then(() => browser.waitForFeatureAggregate('session_replay'))
1234

35+
await browser.pause(5000)
36+
37+
await expect(getSR()).resolves.toMatchObject({
38+
initialized: true,
39+
mode: 0
40+
})
41+
42+
const [sessionReplayHarvests] = await Promise.all([
43+
sessionReplaysCapture.waitForResult({ totalCount: 1 }),
44+
browser.execute(function () {
45+
newrelic.recordReplay()
46+
})
47+
])
48+
1349
await browser.pause(1000)
1450
await expect(getSR()).resolves.toMatchObject({
1551
initialized: true,
1652
mode: 1
1753
})
54+
expect(sessionReplayHarvests.length).toBeGreaterThanOrEqual(1)
1855
})
1956

2057
it('pauseReplay called before page load stops the replay', async () => {
2158
await browser.enableSessionReplay(100, 0)
22-
await browser.url(await browser.testHandle.assetURL('rrweb-api-pause-before-load.html', srConfig()))
23-
.then(() => browser.waitForFeatureAggregate('session_replay'))
59+
const [sessionReplayHarvests] = await Promise.all([
60+
sessionReplaysCapture.waitForResult({ timeout: 10000 }),
61+
browser.url(await browser.testHandle.assetURL('rrweb-api-pause-before-load.html', srConfig()))
62+
.then(() => browser.waitForFeatureAggregate('session_replay'))
63+
])
2464

2565
await browser.pause(1000) // give time for the features to drain fully
2666
await expect(getSR()).resolves.toMatchObject({
@@ -29,11 +69,12 @@ describe('Replay API', () => {
2969
events: expect.any(Array),
3070
mode: 0
3171
})
72+
expect(sessionReplayHarvests).toHaveLength(0)
3273
})
3374

3475
it('Paused replays can be restarted on next page load of same session', async () => {
3576
const url = await browser.testHandle.assetURL('rrweb-instrumented.html', srConfig())
36-
await browser.url(url).then(() => browser.waitForSessionReplayRecording())
77+
await browser.url(url).then(() => browser.waitForAgentLoad())
3778
let replayState = await getSR()
3879
expect(replayState.mode).toEqual(1)
3980

@@ -52,5 +93,7 @@ describe('Replay API', () => {
5293
}).then(() => browser.pause(500))
5394
replayState = await getSR() // record should be able to restart replay on this same session on a hard page load
5495
expect(replayState.mode).toEqual(1)
96+
const sessionReplayHarvests = await sessionReplaysCapture.waitForResult({ totalCount: 1 })
97+
expect(sessionReplayHarvests.length).toBeGreaterThanOrEqual(1)
5598
})
5699
})

0 commit comments

Comments
 (0)