From 0ce74402e2ddd6c216f916878b90f5260c08929a Mon Sep 17 00:00:00 2001 From: Paul D'Ambra Date: Fri, 15 Nov 2024 09:43:59 +0000 Subject: [PATCH 1/7] fly-by fix comment --- src/extensions/replay/sessionrecording.ts | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/extensions/replay/sessionrecording.ts b/src/extensions/replay/sessionrecording.ts index 55c154494..f6f679fcb 100644 --- a/src/extensions/replay/sessionrecording.ts +++ b/src/extensions/replay/sessionrecording.ts @@ -430,10 +430,8 @@ export class SessionRecording { } /** - * Any one trigger can activate the session - * So, if they are all the same - return that value - * If either is disabled return the other's valu - * @private + * trigger is active if _either_ URL _or_ event trigger is active + * and is pending if _either_ URL _or_ event trigger is pending */ private get triggerStatus(): TriggerStatus { const eitherIsActivated = From c983e81daa89c942ec2401dd2b32102dcaa618ef Mon Sep 17 00:00:00 2001 From: Paul D'Ambra Date: Fri, 15 Nov 2024 09:46:49 +0000 Subject: [PATCH 2/7] flip order of precedence --- src/entrypoints/recorder.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/entrypoints/recorder.ts b/src/entrypoints/recorder.ts index 134b252ff..653997632 100644 --- a/src/entrypoints/recorder.ts +++ b/src/entrypoints/recorder.ts @@ -386,7 +386,7 @@ function prepareRequest({ timeOrigin, timestamp, method: method, - initiatorType: entry ? (entry.initiatorType as InitiatorType) : initiatorType, + initiatorType: initiatorType ? initiatorType : entry ? (entry.initiatorType as InitiatorType) : undefined, status, requestHeaders: networkRequest.requestHeaders, requestBody: networkRequest.requestBody, From 8864c636ccec594784990202e5626fb1103d4ead Mon Sep 17 00:00:00 2001 From: Paul D'Ambra Date: Fri, 15 Nov 2024 09:50:44 +0000 Subject: [PATCH 3/7] req.method is GET by default, use the provided method not the req.method --- src/entrypoints/recorder.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/entrypoints/recorder.ts b/src/entrypoints/recorder.ts index 653997632..ffda9496a 100644 --- a/src/entrypoints/recorder.ts +++ b/src/entrypoints/recorder.ts @@ -309,7 +309,7 @@ function initXhrObserver(cb: networkCallback, win: IWindow, options: Required { const requests = prepareRequest({ entry, - method: req.method, + method: method, status: xhr?.status, networkRequest, start, From 34a50a7481f43b8a9f743f0cc75af1a6b657de24 Mon Sep 17 00:00:00 2001 From: Paul D'Ambra Date: Fri, 15 Nov 2024 10:10:39 +0000 Subject: [PATCH 4/7] add an e2e test for this --- cypress/e2e/session-recording.cy.ts | 56 +++++++++++++++++++++++++++++ playground/cypress/index.html | 22 ++++++++++++ 2 files changed, 78 insertions(+) diff --git a/cypress/e2e/session-recording.cy.ts b/cypress/e2e/session-recording.cy.ts index 5eb87b162..56f1134b4 100644 --- a/cypress/e2e/session-recording.cy.ts +++ b/cypress/e2e/session-recording.cy.ts @@ -280,6 +280,62 @@ describe('Session recording', () => { ) }) }) + + it('it captures XHR method correctly', () => { + cy.get('[data-cy-xhr-call-button]').click() + cy.wait('@example.com') + cy.wait('@session-recording') + cy.phCaptures({ full: true }).then((captures) => { + const snapshots = captures.filter((c) => c.event === '$snapshot') + + const capturedRequests: Record[] = [] + for (const snapshot of snapshots) { + for (const snapshotData of snapshot.properties['$snapshot_data']) { + if (snapshotData.type === 6) { + for (const req of snapshotData.data.payload.requests) { + capturedRequests.push(req) + } + } + } + } + + const expectedCaptureds: [RegExp, string][] = [ + [/http:\/\/localhost:\d+\/playground\/cypress\//, 'navigation'], + [/http:\/\/localhost:\d+\/static\/array.js/, 'script'], + [ + /http:\/\/localhost:\d+\/decide\/\?v=3&ip=1&_=\d+&ver=1\.\d\d\d\.\d+&compression=base64/, + 'xmlhttprequest', + ], + [/http:\/\/localhost:\d+\/static\/recorder.js\?v=1\.\d\d\d\.\d+/, 'script'], + [/https:\/\/example.com/, 'xmlhttprequest'], + ] + + // yay, includes expected type 6 network data + expect(capturedRequests.length).to.equal(expectedCaptureds.length) + expectedCaptureds.forEach(([url, initiatorType], index) => { + expect(capturedRequests[index].name).to.match(url) + expect(capturedRequests[index].initiatorType).to.equal(initiatorType) + }) + + // the HTML file that cypress is operating on (playground/cypress/index.html) + // when the button for this test is click makes a post to https://example.com + const capturedFetchRequest = capturedRequests.find((cr) => cr.name === 'https://example.com/') + expect(capturedFetchRequest).to.not.be.undefined + + expect(capturedFetchRequest.fetchStart).to.be.greaterThan(0) // proxy for including network timing info + + expect(capturedFetchRequest.initiatorType).to.eql('xmlhttprequest') + expect(capturedFetchRequest.method).to.eql('POST') + expect(capturedFetchRequest.isInitial).to.be.undefined + expect(capturedFetchRequest.requestBody).to.eq('i am the xhr body') + + expect(capturedFetchRequest.responseBody).to.eq( + JSON.stringify({ + message: 'This is a JSON response', + }) + ) + }) + }) }) }) diff --git a/playground/cypress/index.html b/playground/cypress/index.html index 06830c7c9..b078af68e 100644 --- a/playground/cypress/index.html +++ b/playground/cypress/index.html @@ -19,6 +19,28 @@ Make network call + + +