Skip to content

Commit

Permalink
Extract repeated pattern
Browse files Browse the repository at this point in the history
  • Loading branch information
pauldambra committed Dec 29, 2024
1 parent 8c94136 commit 49138f9
Show file tree
Hide file tree
Showing 8 changed files with 109 additions and 93 deletions.
24 changes: 12 additions & 12 deletions playwright/session-recording/opting-out.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,13 +58,13 @@ test.describe('Session Recording - opting out', () => {
test('can start recording after starting opted out', async ({ page, context }) => {
await startWith({ opt_out_capturing_by_default: true }, page, context)

const loadRecorder = page.waitForResponse('**/recorder.js*')
await page.evaluate(() => {
const ph = (window as WindowWithPostHog).posthog
ph?.opt_in_capturing()
ph?.startSessionRecording()
await page.waitingForNetworkCausedBy(['**/recorder.js*'], async () => {
await page.evaluate(() => {
const ph = (window as WindowWithPostHog).posthog
ph?.opt_in_capturing()
ph?.startSessionRecording()
})
})
await loadRecorder

expect((await page.capturedEvents()).map((x) => x.event)).toEqual(['$opt_in', '$pageview'])

Expand All @@ -78,13 +78,13 @@ test.describe('Session Recording - opting out', () => {
test('can start recording when starting disabled', async ({ page, context }) => {
await startWith({ disable_session_recording: true }, page, context)

const loadRecorder = page.waitForResponse('**/recorder.js*')
await page.resetCapturedEvents()
await page.evaluate(() => {
const ph = (window as WindowWithPostHog).posthog
ph?.startSessionRecording()
await page.waitingForNetworkCausedBy(['**/recorder.js*'], async () => {
await page.resetCapturedEvents()
await page.evaluate(() => {
const ph = (window as WindowWithPostHog).posthog
ph?.startSessionRecording()
})
})
await loadRecorder

await page.locator('[data-cy-input]').type('hello posthog!')
await pollUntilEventCaptured(page, '$snapshot')
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,9 @@ test.describe('session recording in array.full.js', () => {
test('captures session events', async ({ page, context }) => {
await start(startOptions, page, context)

const responsePromise = page.waitForResponse('**/ses/*')
await page.locator('[data-cy-input]').fill('hello posthog!')
await responsePromise
await page.waitingForNetworkCausedBy(['**/ses/*'], async () => {
await page.locator('[data-cy-input]').fill('hello posthog!')
})

await page.evaluate(() => {
const ph = (window as WindowWithPostHog).posthog
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,14 +31,14 @@ test.describe('Session recording - multiple ingestion controls', () => {
})

test('respects sampling when overriding linked flag', async ({ page }) => {
const loadRecorder = page.waitForResponse('**/recorder.js*')
await page.evaluate(() => {
const ph = (window as WindowWithPostHog).posthog
ph?.opt_in_capturing()
// this won't start recording because of the linked flag and sample rate
ph?.startSessionRecording()
await page.waitingForNetworkCausedBy(['**/recorder.js*'], async () => {
await page.evaluate(() => {
const ph = (window as WindowWithPostHog).posthog
ph?.opt_in_capturing()
// this won't start recording because of the linked flag and sample rate
ph?.startSessionRecording()
})
})
await loadRecorder

expect((await page.capturedEvents()).map((x) => x.event)).toEqual(['$opt_in', '$pageview'])

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,14 +29,14 @@ test.describe('Session recording - linked flags', () => {
})

test('can opt in and override linked flag', async ({ page }) => {
const loadRecorder = page.waitForResponse('**/recorder.js*')
await page.evaluate(() => {
const ph = (window as WindowWithPostHog).posthog
ph?.opt_in_capturing()
// starting does not begin recording because of the linked flag
ph?.startSessionRecording()
await page.waitingForNetworkCausedBy(['**/recorder.js*'], async () => {
await page.evaluate(() => {
const ph = (window as WindowWithPostHog).posthog
ph?.opt_in_capturing()
// starting does not begin recording because of the linked flag
ph?.startSessionRecording()
})
})
await loadRecorder
expect((await page.capturedEvents()).map((x) => x.event)).toEqual(['$opt_in', '$pageview'])

await page.resetCapturedEvents()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,27 +59,28 @@ test.beforeEach(async ({ context }) => {
})
}

await start(
{
options: {
session_recording: {},
},
decideResponseOverrides: {
sessionRecording: {
endpoint: '/ses/',
networkPayloadCapture: { recordBody: true, recordHeaders: true },
await page.waitingForNetworkCausedBy(['**/recorder.js*'], async () => {
await start(
{
options: {
session_recording: {},
},
decideResponseOverrides: {
sessionRecording: {
endpoint: '/ses/',
networkPayloadCapture: { recordBody: true, recordHeaders: true },
},
capturePerformance: true,
autocapture_opt_out: true,
},
capturePerformance: true,
autocapture_opt_out: true,
url: './playground/cypress/index.html',
runBeforePostHogInit: wrapInPageContext,
runAfterPostHogInit: wrapInPageContext,
},
url: './playground/cypress/index.html',
runBeforePostHogInit: wrapInPageContext,
runAfterPostHogInit: wrapInPageContext,
},
page,
context
)
await page.waitForResponse('**/recorder.js*')
page,
context
)
})

// also wrap after posthog is loaded
await page.evaluate((isBadlyBehaved) => {
Expand All @@ -98,12 +99,9 @@ test.beforeEach(async ({ context }) => {
})
;['fetch', 'xhr'].forEach((networkType) => {
test('it captures ' + networkType, async ({ page, browserName }) => {
const exampleComResponse = page.waitForResponse('https://example.com/')
const sessionRecordingDataSent = page.waitForResponse('**/ses/*')
await page.click(`[data-cy-${networkType}-call-button]`)
await exampleComResponse
await sessionRecordingDataSent

await page.waitingForNetworkCausedBy(['**/ses/*', 'https://example.com/'], async () => {
await page.click(`[data-cy-${networkType}-call-button]`)
})
const capturedEvents = await page.capturedEvents()
const snapshots = capturedEvents.filter((c) => c.event === '$snapshot')

Expand Down
30 changes: 16 additions & 14 deletions playwright/session-recording/session-recording-sampling.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,10 @@ test.describe('Session recording - sampling', () => {
},
}
test.beforeEach(async ({ page, context }) => {
await start(startOptions, page, context)
await page.waitingForNetworkCausedBy(['**/recorder.js*'], async () => {
await start(startOptions, page, context)
})

await page.waitForResponse('**/recorder.js*')
const capturedEvents = await page.evaluate(() => (window as WindowWithPostHog).capturedEvents || [])
expect(capturedEvents.map((x) => x.event)).toEqual(['$pageview'])
await page.resetCapturedEvents()
Expand Down Expand Up @@ -58,18 +59,19 @@ test.describe('Session recording - sampling', () => {
await page.resetCapturedEvents()
await page.reload()

await start(
{
...sampleZeroStartOptions,
type: 'reload',
},
page,
context
)
await page.waitForResponse('**/recorder.js*')
const responsePromise = page.waitForResponse('**/ses/*')
await page.locator('[data-cy-input]').fill('hello posthog!')
await responsePromise
await page.waitingForNetworkCausedBy(['**/recorder.js*'], async () => {
await start(
{
...sampleZeroStartOptions,
type: 'reload',
},
page,
context
)
})
await page.waitingForNetworkCausedBy(['**/ses/*'], async () => {
await page.locator('[data-cy-input]').fill('hello posthog!')
})

const afterReloadCapturedEvents = await page.capturedEvents()
const lastCaptured = afterReloadCapturedEvents[afterReloadCapturedEvents.length - 1]
Expand Down
50 changes: 25 additions & 25 deletions playwright/session-recording/session-recording.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -146,22 +146,22 @@ test.describe('Session recording - array.js', () => {
const capturedEvents = await page.capturedEvents()
expect(new Set(capturedEvents.map((c) => c['properties']['$session_id']))).toEqual(new Set([firstSessionId]))

const waitForRecorder = page.waitForResponse('**/recorder.js*')
await start(
{
...startOptions,
type: 'reload',
},
page,
page.context()
)

await page.resetCapturedEvents()
await waitForRecorder
await page.waitingForNetworkCausedBy(['**/recorder.js*'], async () => {
await start(
{
...startOptions,
type: 'reload',
},
page,
page.context()
)

await page.resetCapturedEvents()
})

const moreResponsePromise = page.waitForResponse('**/ses/*')
await page.locator('[data-cy-input]').type('hello posthog!')
await moreResponsePromise
await page.waitingForNetworkCausedBy(['**/ses/*'], async () => {
await page.locator('[data-cy-input]').type('hello posthog!')
})

const capturedAfterActivity = await page.capturedEvents()
expect(capturedAfterActivity.map((x) => x.event)).toEqual(['$snapshot'])
Expand Down Expand Up @@ -194,9 +194,9 @@ test.describe('Session recording - array.js', () => {
ph?.reset()
})

const responsePromise = page.waitForResponse('**/ses/*')
await page.locator('[data-cy-input]').fill('hello posthog!')
await responsePromise
await page.waitingForNetworkCausedBy(['**/ses/*'], async () => {
await page.locator('[data-cy-input]').fill('hello posthog!')
})

const capturedEvents = await page.capturedEvents()
const postResetSessionIds = new Set(capturedEvents.map((c) => c['properties']['$session_id']))
Expand All @@ -207,9 +207,9 @@ test.describe('Session recording - array.js', () => {
})

test('rotates sessions after 24 hours', async ({ page }) => {
const responsePromise = page.waitForResponse('**/ses/*')
await page.locator('[data-cy-input]').fill('hello posthog!')
await responsePromise
await page.waitingForNetworkCausedBy(['**/ses/*'], async () => {
await page.locator('[data-cy-input]').fill('hello posthog!')
})

await page.evaluate(() => {
const ph = (window as WindowWithPostHog).posthog
Expand Down Expand Up @@ -239,10 +239,10 @@ test.describe('Session recording - array.js', () => {
ph.sessionManager['_sessionStartTimestamp'] = startTs - timeout - 1000
})

const anotherResponsePromise = page.waitForResponse('**/ses/*')
// using fill here means the session id doesn't rotate, must need some kind of user interaction
await page.locator('[data-cy-input]').type('hello posthog!')
await anotherResponsePromise
await page.waitingForNetworkCausedBy(['**/ses/*'], async () => {
// using fill here means the session id doesn't rotate, must need some kind of user interaction
await page.locator('[data-cy-input]').type('hello posthog!')
})

await page.evaluate(() => {
const ph = (window as WindowWithPostHog).posthog
Expand Down
16 changes: 16 additions & 0 deletions playwright/utils/posthog-playwright-test-base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,10 @@ declare module '@playwright/test' {
*/
interface Page {
resetCapturedEvents(): Promise<void>

capturedEvents(): Promise<CaptureResult[]>

waitingForNetworkCausedBy: (urlPatterns: (string | RegExp)[], action: () => Promise<void>) => Promise<void>
}
}

Expand All @@ -44,6 +47,19 @@ export const test = base.extend<{ mockStaticAssets: void; page: Page }>({
return (window as WindowWithPostHog).capturedEvents || []
})
}
page.waitingForNetworkCausedBy = async function (
urlPatterns: (string | RegExp)[],
action: () => Promise<void>
) {
const responsePromises = urlPatterns.map((urlPattern) => {
return this.waitForResponse(urlPattern)
})

await action()

// eslint-disable-next-line compat/compat
await Promise.allSettled(responsePromises)
}

// Pass the extended page to the test
await use(page)
Expand Down

0 comments on commit 49138f9

Please sign in to comment.