Skip to content

Commit 755ee64

Browse files
committed
feat(replay): account for V2 trigger groups
1 parent d7391a3 commit 755ee64

File tree

9 files changed

+1638
-36
lines changed

9 files changed

+1638
-36
lines changed

packages/browser/src/__tests__/extensions/replay/lazy-sessionrecording.test.ts

Lines changed: 189 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4142,4 +4142,193 @@ describe('Lazy SessionRecording', () => {
41424142
expect(posthog.capture).toHaveBeenCalled()
41434143
})
41444144
})
4145+
4146+
describe('V2 Trigger Groups Integration', () => {
4147+
it('registers session properties when trigger group matches and is sampled', () => {
4148+
const registerSpy = jest.spyOn(posthog, 'register_for_session')
4149+
4150+
sessionRecording.onRemoteConfig(
4151+
makeFlagsResponse({
4152+
sessionRecording: {
4153+
endpoint: '/s/',
4154+
version: 2,
4155+
triggerGroups: [
4156+
{
4157+
id: 'error-group',
4158+
name: 'Error Tracking',
4159+
sampleRate: 1.0,
4160+
conditions: {
4161+
matchType: 'any',
4162+
events: ['$exception'],
4163+
},
4164+
},
4165+
],
4166+
},
4167+
})
4168+
)
4169+
4170+
expect(sessionRecording.status).toBe('buffering')
4171+
4172+
// Trigger the event
4173+
simpleEventEmitter.emit('eventCaptured', { event: '$exception' })
4174+
4175+
// Should transition to sampled
4176+
expect(sessionRecording.status).toBe('sampled')
4177+
4178+
// Verify session properties were registered
4179+
expect(registerSpy).toHaveBeenCalledWith(
4180+
expect.objectContaining({
4181+
$sdk_debug_replay_matched_recording_trigger_groups: expect.arrayContaining([
4182+
expect.objectContaining({
4183+
id: 'error-group',
4184+
name: 'Error Tracking',
4185+
matched: true,
4186+
sampled: true,
4187+
}),
4188+
]),
4189+
})
4190+
)
4191+
})
4192+
4193+
it('respects URL blocklist even when trigger group matches', () => {
4194+
sessionRecording.onRemoteConfig(
4195+
makeFlagsResponse({
4196+
sessionRecording: {
4197+
endpoint: '/s/',
4198+
version: 2,
4199+
triggerGroups: [
4200+
{
4201+
id: 'all-events',
4202+
name: 'All Events',
4203+
sampleRate: 1.0,
4204+
conditions: {
4205+
matchType: 'any',
4206+
events: ['$pageview'],
4207+
},
4208+
},
4209+
],
4210+
urlBlocklist: [
4211+
{
4212+
matching: 'regex',
4213+
url: '/admin',
4214+
},
4215+
],
4216+
},
4217+
})
4218+
)
4219+
4220+
expect(sessionRecording.status).toBe('buffering')
4221+
4222+
// Navigate to blocked URL
4223+
fakeNavigateTo('https://test.com/admin')
4224+
_emit(createIncrementalSnapshot({ data: { source: 1 } }))
4225+
4226+
// Trigger event on blocked URL
4227+
simpleEventEmitter.emit('eventCaptured', { event: '$pageview' })
4228+
4229+
// Should be PAUSED, not SAMPLED (blocklist takes priority)
4230+
expect(sessionRecording.status).toBe('paused')
4231+
})
4232+
4233+
it('tracks multiple trigger groups with union behavior', () => {
4234+
const registerSpy = jest.spyOn(posthog, 'register_for_session')
4235+
4236+
sessionRecording.onRemoteConfig(
4237+
makeFlagsResponse({
4238+
sessionRecording: {
4239+
endpoint: '/s/',
4240+
version: 2,
4241+
triggerGroups: [
4242+
{
4243+
id: 'errors',
4244+
name: 'Error Tracking',
4245+
sampleRate: 1.0,
4246+
conditions: {
4247+
matchType: 'any',
4248+
events: ['$exception'],
4249+
},
4250+
},
4251+
{
4252+
id: 'pageviews',
4253+
name: 'Pageview Tracking',
4254+
sampleRate: 1.0,
4255+
conditions: {
4256+
matchType: 'any',
4257+
events: ['$pageview'],
4258+
},
4259+
},
4260+
],
4261+
},
4262+
})
4263+
)
4264+
4265+
// Trigger both groups
4266+
simpleEventEmitter.emit('eventCaptured', { event: '$exception' })
4267+
simpleEventEmitter.emit('eventCaptured', { event: '$pageview' })
4268+
4269+
expect(sessionRecording.status).toBe('sampled')
4270+
4271+
// Should track both groups
4272+
expect(registerSpy).toHaveBeenCalledWith(
4273+
expect.objectContaining({
4274+
$sdk_debug_replay_matched_recording_trigger_groups: expect.arrayContaining([
4275+
expect.objectContaining({ id: 'errors', sampled: true }),
4276+
expect.objectContaining({ id: 'pageviews', sampled: true }),
4277+
]),
4278+
})
4279+
)
4280+
4281+
// Find the call with the trigger groups property
4282+
const callsWithProperty = registerSpy.mock.calls.filter(
4283+
(call) => call[0].$sdk_debug_replay_matched_recording_trigger_groups
4284+
)
4285+
expect(callsWithProperty.length).toBeGreaterThan(0)
4286+
const groups = callsWithProperty[callsWithProperty.length - 1][0]
4287+
.$sdk_debug_replay_matched_recording_trigger_groups
4288+
expect(groups).toHaveLength(2)
4289+
})
4290+
4291+
it('triggers immediately when trigger group has empty conditions', () => {
4292+
const registerSpy = jest.spyOn(posthog, 'register_for_session')
4293+
4294+
sessionRecording.onRemoteConfig(
4295+
makeFlagsResponse({
4296+
sessionRecording: {
4297+
endpoint: '/s/',
4298+
version: 2,
4299+
triggerGroups: [
4300+
{
4301+
id: 'all-sessions',
4302+
name: 'All Sessions',
4303+
sampleRate: 1.0,
4304+
minDurationMs: 0,
4305+
conditions: {
4306+
matchType: 'any',
4307+
// Empty conditions - no events, urls, or flags
4308+
},
4309+
},
4310+
],
4311+
},
4312+
})
4313+
)
4314+
4315+
// Should immediately trigger without needing any events
4316+
// Status should be sampled (not buffering)
4317+
expect(sessionRecording.status).toBe('sampled')
4318+
4319+
// Verify session properties were registered
4320+
expect(registerSpy).toHaveBeenCalledWith(
4321+
expect.objectContaining({
4322+
$sdk_debug_replay_matched_recording_trigger_groups: expect.arrayContaining([
4323+
expect.objectContaining({
4324+
id: 'all-sessions',
4325+
name: 'All Sessions',
4326+
matched: true,
4327+
sampled: true,
4328+
}),
4329+
]),
4330+
})
4331+
)
4332+
})
4333+
})
41454334
})

0 commit comments

Comments
 (0)