Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 9 additions & 8 deletions __tests__/e2e/__snapshots__/happy-path.e2e.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -116,24 +116,25 @@ exports[`happy-path flow > navigates Welcome → SystemCheck → Authenticate
exports[`happy-path flow > navigates Welcome → SystemCheck → Authenticate → InstallPlugins → ConnectTools → SelectGoal → OnboardProject → Done > select-goal 1`] = `
" Confidence by Spotify https://confidence.spotify.com/

Which features would you like to set up? Todo (4/5)
Select the features you'd like to set up Todo (4/5)

Choose the Confidence features to integrate with your project. ● Check system
Toggle Confidence features to integrate with your project. ● Check system
● Sign in to Confidence
◆ Session Recordings (β) require the feature to be enabled on your ● Set up your agent
Confidence account. ● Connect tools
✱ Event Tracking works best with a managed warehouse or an ● Set up your agent
existing warehouse setup. ● Connect tools
▶ Onboard project
✱ Session Recordings (β) require the feature to be enabled on your
Confidence account.


──────────────────────────────────────────────────────────────────────────────────────────────────
Select features to set up:
Toggle features to set up (select none to skip):

❯ Feature Flags
Event Tracking
Session Recordings (β)
YOLO! Set up everything
Skip setup

↑↓ navigate enter confirm vX.Y.Z"
↑↓ navigate space toggle enter confirm vX.Y.Z"
`;

exports[`happy-path flow > navigates Welcome → SystemCheck → Authenticate → InstallPlugins → ConnectTools → SelectGoal → OnboardProject → Done > system-check 1`] = `
Expand Down
17 changes: 9 additions & 8 deletions __tests__/e2e/__snapshots__/select-goal.e2e.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -3,22 +3,23 @@
exports[`SelectGoal screen > shows goal options for a browser framework > select-goal 1`] = `
" Confidence by Spotify https://confidence.spotify.com/

Which features would you like to set up? Todo (4/5)
Select the features you'd like to set up Todo (4/5)

Choose the Confidence features to integrate with your project. ● Check system
Toggle Confidence features to integrate with your project. ● Check system
● Sign in to Confidence
◆ Session Recordings (β) require the feature to be enabled on your ● Set up your agent
Confidence account. ● Connect tools
✱ Event Tracking works best with a managed warehouse or an ● Set up your agent
existing warehouse setup. ● Connect tools
▶ Onboard project
✱ Session Recordings (β) require the feature to be enabled on your
Confidence account.


──────────────────────────────────────────────────────────────────────────────────────────────────
Select features to set up:
Toggle features to set up (select none to skip):

❯ Feature Flags
Event Tracking
Session Recordings (β)
YOLO! Set up everything
Skip setup

↑↓ navigate enter confirm vX.Y.Z"
↑↓ navigate space toggle enter confirm vX.Y.Z"
`;
3 changes: 2 additions & 1 deletion __tests__/e2e/chat-launch.e2e.ts
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,8 @@ describe('when the user starts chat after onboarding', () => {
await session.waitForText('Skipped');

// SelectGoal
await session.waitForText('Which features would you like to set up?');
await session.waitForText("Select the features you'd like to set up");
await session.press('Space');
await session.press('Enter');

// OnboardProject
Expand Down
3 changes: 2 additions & 1 deletion __tests__/e2e/happy-path.e2e.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,9 +43,10 @@ describe('happy-path flow', () => {
await session.waitForText('Connected successfully');

// SelectGoal
await session.waitForText('Which features would you like to set up?');
await session.waitForText("Select the features you'd like to set up");
expect(session.snapshot()).toMatchSnapshot('select-goal');
session.checkpoint();
await session.press('Space');
await session.press('Enter');

// OnboardProject
Expand Down
52 changes: 36 additions & 16 deletions __tests__/e2e/select-goal.e2e.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,9 @@ describe('SelectGoal screen', () => {

await session.waitForText('Feature Flags');
await session.waitForText('Session Recordings');
await session.waitForText('YOLO');
await session.waitForText('Skip setup');
await session.waitForText('Event Tracking');
await session.waitForText('space');
await session.waitForText('toggle');
expect(session.snapshot()).toMatchSnapshot('select-goal');
});

Expand All @@ -22,6 +23,7 @@ describe('SelectGoal screen', () => {

await navigateToGoalSelection(session);
session.checkpoint();
await session.press('Space');
await session.press('Enter');

await session.waitForText('Start onboarding?');
Expand All @@ -35,52 +37,70 @@ describe('SelectGoal screen', () => {
await navigateToGoalSelection(session);
session.checkpoint();

// Session Recordings — 2nd option
await session.press('ArrowDown');
// Session Recordings — 3rd option
await session.pressRepeat('ArrowDown', 2);
await session.press('Space');
await session.press('Enter');

await session.waitForText('Start onboarding?');
expect(session.snapshot()).toContain('add the Confidence SDK');
expect(session.snapshot()).toContain('set up session recordings');
});

it('shows combined steps after selecting YOLO', async () => {
it('shows combined steps when multiple goals are selected', async () => {
using session = createSession();

await navigateToGoalSelection(session);
session.checkpoint();

// YOLO — 3rd option
await session.pressRepeat('ArrowDown', 2);
// Toggle Feature Flags (1st), Event Tracking (2nd), Session Recordings (3rd)
await session.press('Space');
await session.press('ArrowDown');
await session.press('Space');
await session.pressRepeat('ArrowDown', 1);
await session.press('Space');
await session.press('Enter');

await session.waitForText('Start onboarding?');
expect(session.snapshot()).toContain('set up feature flags');
expect(session.snapshot()).toContain('create your first feature flag');
expect(session.snapshot()).toContain('instrument event tracking');
expect(session.snapshot()).toContain('set up session recordings');
});

it('advances to Done when skip is selected', async () => {
it('shows event tracking steps after selecting Event Tracking', async () => {
using session = createSession();

await navigateToGoalSelection(session);
session.checkpoint();

// Event Tracking — 2nd option
await session.press('ArrowDown');
await session.press('Space');
await session.press('Enter');

await session.waitForText('Start onboarding?');
expect(session.snapshot()).toContain('add the Confidence SDK');
expect(session.snapshot()).toContain('instrument event tracking');
});

it('advances to Done when submitting with nothing selected', async () => {
using session = createSession();

// Skip setup — 4th option
await session.pressRepeat('ArrowDown', 3);
await navigateToGoalSelection(session);
await session.press('Enter');

await session.waitForText('Onboarding skipped');
});

it('auto-advances for non-browser project', async () => {
it('shows goal selection for non-browser project without recording option', async () => {
using session = createSession({ project: 'statsig-node' });

await navigateToConnectTools(session);
session.checkpoint();
await session.press('Enter');

// Non-browser project auto-advances past goal selection to onboarding
await session.waitForText('Start onboarding?');
expect(session.snapshot()).toContain('add the Confidence SDK');
expect(session.snapshot()).toContain('create your first feature flag');
// Non-browser project now shows goal selection (without Session Recordings)
await session.waitForText('Feature Flags');
await session.waitForText('Event Tracking');
});
});
6 changes: 4 additions & 2 deletions __tests__/e2e/skip-plugins.e2e.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@ describe('when the user skips installing AI plugin', () => {
await session.waitForText('Connected successfully');

// SelectGoal
await session.waitForText('Which features would you like to set up?');
await session.waitForText("Select the features you'd like to set up");
await session.press('Space');
await session.press('Enter');

// OnboardProject
Expand Down Expand Up @@ -50,7 +51,8 @@ describe('when the user skips installing AI plugin', () => {
await session.waitForText('Connected successfully');

// SelectGoal
await session.waitForText('Which features would you like to set up?');
await session.waitForText("Select the features you'd like to set up");
await session.press('Space');
await session.press('Enter');

await session.waitForText('Start onboarding?');
Expand Down
3 changes: 2 additions & 1 deletion __tests__/e2e/skip-tools.e2e.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@ describe('when the user skips connecting tools', () => {
await session.waitForText('Skipped');

// SelectGoal
await session.waitForText('Which features would you like to set up?');
await session.waitForText("Select the features you'd like to set up");
await session.press('Space');
await session.press('Enter');

// OnboardProject
Expand Down
3 changes: 2 additions & 1 deletion __tests__/e2e/stale-mcp-auth.e2e.ts
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,8 @@ describe('when MCP config has expired auth tokens', () => {
await session.waitForText('Skipped');

// SelectGoal
await session.waitForText('Which features would you like to set up?');
await session.waitForText("Select the features you'd like to set up");
await session.press('Space');
await session.press('Enter');

// OnboardProject
Expand Down
10 changes: 6 additions & 4 deletions __tests__/e2e/testing-framework/navigation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ export async function navigateToGoalSelection(session: TerminalSession): Promise
await navigateToConnectTools(session);
session.checkpoint();
await session.press('Enter');
await session.waitForText('Which features would you like to set up?');
await session.waitForText("Select the features you'd like to set up");
}

/**
Expand All @@ -82,6 +82,7 @@ export async function navigateToGoalSelection(session: TerminalSession): Promise
export async function navigateToOnboarding(session: TerminalSession): Promise<void> {
await navigateToGoalSelection(session);
session.checkpoint();
await session.press('Space');
await session.press('Enter');
await session.waitForText('Start onboarding?');
}
Expand Down Expand Up @@ -114,17 +115,18 @@ export async function selectIdeAndOnboard(
const matched = await session.waitForText([
'Start onboarding?',
'Connect Confidence tools?',
'Which features would you like to set up?',
"Select the features you'd like to set up",
]);

if (matched === 'Connect Confidence tools?') {
await session.press('Enter');
await session.waitForText('Connected successfully');
await session.waitForText('Which features would you like to set up?');
await session.waitForText("Select the features you'd like to set up");
}

if (matched !== 'Start onboarding?') {
// SelectGoal — pick Feature Flags (default)
// SelectGoal — toggle Feature Flags and submit
await session.press('Space');
await session.press('Enter');
await session.waitForText('Start onboarding?');
}
Expand Down
111 changes: 111 additions & 0 deletions __tests__/lib/report-templates.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
import { buildReportTemplate } from '@lib/onboarding-prompt/report-templates.js';
import type { OnboardingGoal } from '@lib/session.js';

function fileEntries(goals: OnboardingGoal[]): string[] {
const { start } = buildReportTemplate(goals);
const section = start.split('**New/modified files:**')[1]?.split('**New dependencies:**')[0];
return section
? section
.split('\n')
.map((l) => l.trim())
.filter((l) => l.startsWith('- '))
: [];
}

function depEntries(goals: OnboardingGoal[]): string[] {
const { start } = buildReportTemplate(goals);
const section = start.split('**New dependencies:**')[1];
return section
? section
.split('\n')
.map((l) => l.trim())
.filter((l) => l.startsWith('- '))
: [];
}

describe('when only feature-flags is selected', () => {
const goals: OnboardingGoal[] = ['feature-flags'];

it('includes .env, entry point with SDK initialization, and flag evaluation', () => {
const sut = fileEntries(goals);

expect(sut).toEqual([
'- `<.env file>` — added `CONFIDENCE_CLIENT_SECRET`',
'- `<entry point file>` — added SDK initialization',
'- `<aha target file>` — added flag evaluation',
]);
});

it('lists the feature flags SDK dependency', () => {
const sut = depEntries(goals);
expect(sut).toEqual(['- `<feature flags SDK package name>`']);
});
});

describe('when only session-recordings is selected', () => {
const goals: OnboardingGoal[] = ['session-recordings'];

it('includes separate entry point lines for SDK init and session recording', () => {
const sut = fileEntries(goals);

expect(sut).toEqual([
'- `<.env file>` — added `CONFIDENCE_CLIENT_SECRET`',
'- `<entry point file>` — added SDK initialization',
'- `<entry point file>` — added session recording provider',
]);
});

it('lists the session recording SDK dependency', () => {
const sut = depEntries(goals);
expect(sut).toEqual(['- `<session recording SDK package name>`']);
});
});

describe('when only event-tracking is selected', () => {
const goals: OnboardingGoal[] = ['event-tracking'];

it('includes .env, entry point, and track() calls without duplicates', () => {
const sut = fileEntries(goals);

expect(sut).toEqual([
'- `<.env file>` — added `CONFIDENCE_CLIENT_SECRET`',
'- `<entry point file>` — added SDK initialization',
'- `<files with track() calls>` — added event tracking calls',
]);
});

it('lists a specific event tracking SDK dependency', () => {
const sut = depEntries(goals);
expect(sut).toEqual(['- `<event tracking SDK package name>`']);
});
});

describe('when all goals are selected', () => {
const goals: OnboardingGoal[] = ['feature-flags', 'session-recordings', 'event-tracking'];

it('produces one .env line and no duplicate entry point lines', () => {
const sut = fileEntries(goals);
const envLines = sut.filter((l) => l.includes('.env file'));
const entryPointLines = sut.filter((l) => l.includes('entry point file'));

expect(envLines).toHaveLength(1);
expect(entryPointLines).toHaveLength(2);
expect(entryPointLines[0]).toContain('SDK initialization');
expect(entryPointLines[1]).toContain('session recording provider');
});

it('lists separate entry point lines for SDK init and session recording', () => {
const sut = fileEntries(goals);
const entryPointLines = sut.filter((l) => l.includes('entry point file'));

expect(entryPointLines).toEqual([
'- `<entry point file>` — added SDK initialization',
'- `<entry point file>` — added session recording provider',
]);
});

it('lists all three SDK dependencies', () => {
const sut = depEntries(goals);
expect(sut).toHaveLength(3);
});
});
Loading