Skip to content

Commit

Permalink
🤷
Browse files Browse the repository at this point in the history
  • Loading branch information
pauldambra committed Nov 21, 2024
2 parents c718cb6 + d71ecd6 commit 80d7709
Show file tree
Hide file tree
Showing 84 changed files with 18,663 additions and 1,716 deletions.
5 changes: 4 additions & 1 deletion .github/workflows/es-check.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ on:

jobs:
ssr:
name: Cypress
name: Build and check ES5/ES6 support
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
Expand All @@ -21,3 +21,6 @@ jobs:

- name: Run es-check to check if our ie11 bundle is ES5 compatible
run: npx [email protected] es5 dist/array.full.es5.js

- name: Run es-check to check if our main bundle is ES6 compatible
run: npx [email protected] es6 dist/array.full.js
4 changes: 2 additions & 2 deletions .github/workflows/testcafe.yml
Original file line number Diff line number Diff line change
Expand Up @@ -54,13 +54,13 @@ jobs:
run: pnpm build-rollup

- name: Run ${{ matrix.name }} test
timeout-minutes: 30
timeout-minutes: 10
env:
BRANCH_NAME: ${{ github.head_ref || github.ref_name }}
RUN_ID: ${{ github.run_id }}
BROWSER: ${{ matrix.browser }}
run: pnpm testcafe ${{ matrix.browser }} --stop-on-first-fail

- name: Check ${{ matrix.name }} events
timeout-minutes: 15
timeout-minutes: 10
run: pnpm check-testcafe-results
116 changes: 116 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,119 @@
## 1.187.2 - 2024-11-20

- fix: improve ES6 bundling (#1542)

## 1.187.1 - 2024-11-19

- fix: patch angular wrap detection in rrweb (#1543)

## 1.187.0 - 2024-11-19

- feat: allow config of before_send function to edit or reject events (#1515)
- chore: timeout test cafe jobs (#1540)
- chore: specify an explicit browserslist version (#1539)

## 1.186.4 - 2024-11-19

- chore: always transform exponentiation (#1537)
- chore: very small change to IE11 bundling (#1536)

## 1.186.3 - 2024-11-18

- fix: refactor native mutation observer implementation (#1535)
- chore: update dependency versions (#1534)
- chore: remove custom exceptions endpoint (#1513)

## 1.186.2 - 2024-11-18

- fix: angular change detection mutation observer (#1531)
- chore: Added CSP headers to next app for testing what we document (#1528)

## 1.186.1 - 2024-11-15

- fix: XHR req method capture (#1527)

## 1.186.0 - 2024-11-15

- feat: allow triggering sessions when events occur (#1523)

## 1.185.0 - 2024-11-15

- feat: Add customization to add all person profile properties as setPersonPropertiesForFlags (#1517)

## 1.184.2 - 2024-11-13

- fix(flags): support multiple children prop in PostHogFeature (#1516)
- fix: Don't use session storage in memory mode (#1521)

## 1.184.1 - 2024-11-12

- chore: add type to Sentry exception (#1520)

## 1.184.0 - 2024-11-12

- feat: deadclicks in heatmaps (#1510)

## 1.183.0 - 2024-11-12

- feat: add recording url blocklist (#1500)

## 1.182.0 - 2024-11-11

- chore: upgrade rrweb to alpha.17 (#1489)

## 1.181.0 - 2024-11-05

- chore: add stack type (#1511)

## 1.180.1 - 2024-11-01

- fix: dead click fixes from watching in prod (#1508)

## 1.180.0 - 2024-10-31

- feat: allow mutation rate limiter configuration (#1506)

## 1.179.0 - 2024-10-31

- feat: dead click detection (#1463)
- chore: refactor towards dead clicks autocapture (#1505)

## 1.178.0 - 2024-10-30

- feat: Add timezone to events (#1504)
- chore: update README to include missing steps for running local nextjs playground (#1455)

## 1.177.0 - 2024-10-28

- feat: Only set missing campaign params to null if there is at least one non-null (#1493)

## 1.176.1 - 2024-10-28

- fix: reduce keep alive threshold (#1501)
- fix: empty query param when calling external dependency toolbar.js (#1456)
- fix: careful now (#1497)

## 1.176.0 - 2024-10-24

- fix(surveys): Reset Survey storage after posthog.reset is called (#1494)

## 1.175.1 - 2024-10-24

- chore: set platform on stack frame (#1495)

## 1.175.0 - 2024-10-24

- fix: allow canvas local config (#1496)

## 1.174.4 - 2024-10-24

- fix: expose the last activity timestamp in session id check result (#1491)

## 1.174.3 - 2024-10-22

- chore: upgrade rrweb to alpha.16 (#1276)
- chore: test that autocapture allowlists are unioned (#1476)

## 1.174.2 - 2024-10-18

- fix: no need to swallow import errors (#1486)
Expand Down
11 changes: 7 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,12 @@ After all this, you'll be able to run through the below steps:
You can use the create react app setup in `playground/nextjs` to test posthog-js as an npm module in a Nextjs application.

1. Run `posthog` locally on port 8000 (`DEBUG=1 TEST=1 ./bin/start`).
2. Run `python manage.py setup_dev --no-data` on posthog repo, which sets up a demo account.
3. Copy posthog token found in `http://localhost:8000/project/settings` and then
4. `cd playground/nextjs`and run `NEXT_PUBLIC_POSTHOG_KEY='<your-local-api-key>' pnpm dev`
1. Run `python manage.py setup_dev --no-data` on posthog repo, which sets up a demo account.
1. Copy Project API key found in `http://localhost:8000/project/settings` and save it for the last step.
1. Run `cd playground/nextjs`.
1. Run `pnpm i` to install dependencies.
1. Run `pnpm run build-posthog-js` to build `posthog-js` locally.
1. Run `NEXT_PUBLIC_POSTHOG_KEY='<your-local-api-key>' NEXT_PUBLIC_POSTHOG_HOST='http://localhost:8000' pnpm dev` to start the application.

### Tiers of testing

Expand Down Expand Up @@ -100,4 +103,4 @@ Only one person is set as a collaborator on NPM, so they're the only person that

Use the "release alpha" label on your PR to have an alpha version published automatically. This automation currently doesn't check whether an alpha exists for the version it will try to publish. If you need to publish two alphas from one PR you'll need to fix that

Remember that these versions are public and folk might use them, so make sure they're not _too_ alpha 🙈
Remember that these versions are public and folk might use them, so make sure they're not _too_ alpha 🙈
48 changes: 48 additions & 0 deletions cypress/e2e/before_send.cy.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
/// <reference types="cypress" />

import { start } from '../support/setup'
import { isArray } from '../../src/utils/type-utils'

describe('before_send', () => {
it('can sample and edit with before_send', () => {
start({})

cy.posthog().then((posthog) => {
let counter = 0
const og = posthog.config.before_send
// cypress tests rely on existing before_send function to capture events
// so we have to add it back in here
posthog.config.before_send = [
(cr) => {
if (cr.event === 'custom-event') {
counter++
if (counter === 2) {
return null
}
}
if (cr.event === '$autocapture') {
return {
...cr,
event: 'redacted',
}
}
return cr
},
...(isArray(og) ? og : [og]),
]
})

cy.get('[data-cy-custom-event-button]').click()
cy.get('[data-cy-custom-event-button]').click()

cy.phCaptures().should('deep.equal', [
// before adding the new before sendfn
'$pageview',
'redacted',
'custom-event',
// second button click only has the redacted autocapture event
'redacted',
// because the second custom-event is rejected
])
})
})
56 changes: 55 additions & 1 deletion cypress/e2e/capture.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { version } from '../../package.json'

import { getBase64EncodedPayload, getGzipEncodedPayload, getPayload } from '../support/compression'
import { start } from '../support/setup'
import { pollPhCaptures } from '../support/assertions'

const urlWithVersion = new RegExp(`&ver=${version}`)

Expand Down Expand Up @@ -286,7 +287,9 @@ describe('Event capture', () => {
it('does not autocapture anything when /decide is disabled', () => {
start({ options: { autocapture: false, advanced_disable_decide: true }, waitForDecide: false })

cy.get('body').click(100, 100).click(98, 102).click(101, 103)
cy.get('body').click(100, 100)
cy.get('body').click(98, 102)
cy.get('body').click(101, 103)
cy.get('[data-cy-custom-event-button]').click()

// No autocapture events, still captures custom events
Expand Down Expand Up @@ -375,4 +378,55 @@ describe('Event capture', () => {
})
})
})

it('capture dead clicks when configured to', () => {
start({
options: {
capture_dead_clicks: true,
},
})

cy.get('[data-cy-not-an-order-button]').click()

pollPhCaptures('$dead_click').then(() => {
cy.phCaptures({ full: true }).then((captures) => {
const deadClicks = captures.filter((capture) => capture.event === '$dead_click')
expect(deadClicks.length).to.eq(1)
const deadClick = deadClicks[0]
expect(deadClick.properties.$dead_click_last_mutation_timestamp).to.be.a('number')
expect(deadClick.properties.$dead_click_event_timestamp).to.be.a('number')
expect(deadClick.properties.$dead_click_absolute_delay_ms).to.be.greaterThan(2500)
expect(deadClick.properties.$dead_click_scroll_timeout).to.eq(false)
expect(deadClick.properties.$dead_click_mutation_timeout).to.eq(false)
expect(deadClick.properties.$dead_click_absolute_timeout).to.eq(true)
})
})
})

it('does not capture dead click for selected text', () => {
start({
options: {
capture_dead_clicks: true,
},
})

cy.get('[data-cy-dead-click-text]').then(($el) => {
const text = $el.text()
const wordToSelect = text.split(' ')[0]
const position = text.indexOf(wordToSelect)

// click the text to make a selection
cy.get('[data-cy-dead-click-text]')
.trigger('mousedown', position, 0)
.trigger('mousemove', position + wordToSelect.length, 0)
.trigger('mouseup')
.trigger('dblclick', position, 0)
})

cy.wait(1000)
cy.phCaptures({ full: true }).then((captures) => {
const deadClicks = captures.filter((capture) => capture.event === '$dead_click')
expect(deadClicks.length).to.eq(0)
})
})
})
1 change: 1 addition & 0 deletions cypress/e2e/error-tracking.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ describe('Exception capture', () => {
cy.phCaptures({ full: true }).then((captures) => {
expect(captures.map((c) => c.event)).to.deep.equal(['$pageview', '$autocapture', '$exception'])
expect(captures[2].event).to.be.eql('$exception')
expect(captures[2].properties.$exception_list[0].stacktrace.type).to.be.eq('raw')
expect(captures[2].properties.$exception_list[0].stacktrace.frames.length).to.be.eq(1)
expect(captures[2].properties.$exception_list[0].stacktrace.frames[0].function).to.be.eq(
'HTMLButtonElement.onclick'
Expand Down
58 changes: 57 additions & 1 deletion 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 Expand Up @@ -654,7 +710,7 @@ describe('Session recording', () => {
cy.posthog().invoke('capture', 'test_registered_property')
cy.phCaptures({ full: true }).then((captures) => {
expect((captures || []).map((c) => c.event)).to.deep.equal(['$pageview', 'test_registered_property'])
expect(captures[1]['properties']['$session_recording_start_reason']).to.equal('sampling_override')
expect(captures[1]['properties']['$session_recording_start_reason']).to.equal('sampling_overridden')
})

cy.resetPhCaptures()
Expand Down
Loading

0 comments on commit 80d7709

Please sign in to comment.