tests/app-onboarding-posthog.unit.test.ts
Rama main · réplica de lectura del repositorio original.
import { describe, expect, it } from 'vitest'
import { buildAppOnboardingStepPosthogEvent } from '../supabase/functions/_backend/utils/app_onboarding_posthog.ts'
describe('app onboarding step PostHog event', () => {
it.concurrent('links the committed history entry to its user and organization', () => {
expect(buildAppOnboardingStepPosthogEvent({
appId: 'com.example.app',
auth: { authType: 'jwt', userId: 'user-id', apikey: null, jwt: 'token' },
change: { stepId: 'build_project', status: 'done', at: '2026-09-11T18:00:00.000Z', historyLength: 3, historyFull: false },
orgId: 'org-id',
setup: { todo_list_version: 2, source: 'cli', outcome: 'in_progress', steps: {} },
})).toMatchObject({
event: 'App Onboarding Step Changed',
groups: { organization: 'org-id' },
user_id: 'user-id',
setPersonProperties: false,
timestamp: '2026-09-11T18:00:00.000Z',
nonPersonTags: {
$insert_id: 'app-onboarding-step:com.example.app:build_project:2026-09-11T18:00:00.000Z:3',
app_id: 'com.example.app',
auth_type: 'jwt',
history_entry_type: 'status',
history_length: 3,
onboarding_outcome: 'in_progress',
onboarding_source: 'cli',
todo_list_version: 2,
step_id: 'build_project',
step_status: 'done',
},
})
})
it.concurrent('attributes queue observations to the app rather than a human', () => {
expect(buildAppOnboardingStepPosthogEvent({
appId: 'com.example.app',
system: true,
change: { stepId: 'run_device', status: 'done', at: '2026-09-11T18:00:00.000Z', historyLength: 1, historyFull: false },
orgId: 'org-id',
setup: { todo_list_version: 4, ota_todo_list_version: '1', source: 'manual', outcome: 'in_progress', steps: {} },
})).toMatchObject({
distinct_id: 'app-onboarding-app:com.example.app',
setPersonProperties: false,
nonPersonTags: { auth_type: 'system', step_id: 'run_device', todo_list_version: 4 },
})
})
it.concurrent('marks backend-inferred completion with its source step', () => {
expect(buildAppOnboardingStepPosthogEvent({
appId: 'com.example.app',
system: true,
change: {
stepId: 'add_code',
status: 'done',
at: '2026-09-30T10:00:00.000Z',
historyLength: 1,
historyFull: false,
completionSource: 'inferred',
inferredFromStepId: 'test_update',
},
orgId: 'org-id',
setup: { todo_list_version: 4, ota_todo_list_version: '1', source: 'manual', outcome: 'in_progress', steps: {} },
}).nonPersonTags).toMatchObject({
step_id: 'add_code',
step_completion_source: 'inferred',
step_inferred_from: 'test_update',
})
})
it.concurrent('carries the skip reason only for an explicit skip', () => {
const base = {
appId: 'com.example.app',
auth: { authType: 'jwt' as const, userId: 'user-id', apikey: null, jwt: 'token' },
orgId: 'org-id',
setup: { todo_list_version: 4, ota_todo_list_version: '1', source: 'manual' as const, outcome: 'in_progress' as const, steps: {} },
skipReason: 'My AI agent set it up',
}
expect(buildAppOnboardingStepPosthogEvent({ ...base, change: { stepId: 'login_cli_mcp', status: 'skipped', at: '2026-10-21T10:00:00.000Z', historyLength: 1, historyFull: false } }).nonPersonTags)
.toMatchObject({ step_status: 'skipped', skip_reason: 'My AI agent set it up' })
const { skipReason: _skipReason, ...withoutReason } = base
expect(buildAppOnboardingStepPosthogEvent({ ...withoutReason, change: { stepId: 'login_cli_mcp', status: 'done', at: '2026-10-21T10:00:00.000Z', historyLength: 2, historyFull: false } }).nonPersonTags)
.not.toHaveProperty('skip_reason')
})
})