Skip to content

Commit

Permalink
fix: XHR req method capture (#1527)
Browse files Browse the repository at this point in the history
  • Loading branch information
pauldambra authored Nov 15, 2024
1 parent d8e5b26 commit 8d420c7
Show file tree
Hide file tree
Showing 4 changed files with 80 additions and 8 deletions.
56 changes: 56 additions & 0 deletions cypress/e2e/session-recording.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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<string, any>[] = []
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',
})
)
})
})
})
})

Expand Down
22 changes: 22 additions & 0 deletions playground/cypress/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,28 @@
Make network call
</button>

<button data-cy-xhr-call-button onclick="makeXHRNetworkPOST()">
Make XHR post network call
</button>

<script>
function makeXHRNetworkPOST() {
const xhr = new XMLHttpRequest();
xhr.open('POST', 'https://example.com');
xhr.setRequestHeader('Content-Type', 'application/json');
xhr.onload = function () {
if (xhr.status >= 200 && xhr.status < 300) {
console.log('Response:', xhr.responseText);
} else {
console.error('Request failed with status:', xhr.status);
}
};
xhr.onerror = function () {
console.error('Network error');
};
xhr.send('i am the xhr body');
}
</script>
<br />

<button data-cy-feature-flag-button onclick="console.log(posthog.isFeatureEnabled('some-feature'))">
Expand Down
4 changes: 2 additions & 2 deletions src/entrypoints/recorder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -309,7 +309,7 @@ function initXhrObserver(cb: networkCallback, win: IWindow, options: Required<Ne
.then((entry) => {
const requests = prepareRequest({
entry,
method: req.method,
method: method,
status: xhr?.status,
networkRequest,
start,
Expand Down Expand Up @@ -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,
Expand Down
6 changes: 0 additions & 6 deletions src/extensions/replay/sessionrecording.ts
Original file line number Diff line number Diff line change
Expand Up @@ -429,12 +429,6 @@ export class SessionRecording {
return currentTriggerSession === this.sessionId ? 'trigger_activated' : 'trigger_pending'
}

/**
* 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
*/
private get triggerStatus(): TriggerStatus {
const eitherIsActivated =
this.eventTriggerStatus === 'trigger_activated' || this.urlTriggerStatus === 'trigger_activated'
Expand Down

0 comments on commit 8d420c7

Please sign in to comment.