From ee09f979fac61fc5b1db4a528c9e3a20667b796f Mon Sep 17 00:00:00 2001 From: OrcaWin Date: Tue, 27 Oct 2026 21:00:57 -0700 Subject: [PATCH] test: remove 78 low-value cases and four entire suites (#34687) Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com> --- config/reliability-gates.jsonc | 4 +- config/scripts/ci-shard-timings.json | 1 - ...aemon-pty-adapter-full-disk-access.test.ts | 37 -- .../github/project-view-field-values.test.ts | 18 - ...ttings-queue-follow-ups-projection.test.ts | 28 -- .../quit-and-stop-all-sessions-prompt.test.ts | 28 -- .../client-agent-dashboard-snapshot.test.ts | 32 +- src/main/telemetry/client-lifecycle.test.ts | 61 +-- src/main/telemetry/consent.test.ts | 27 +- .../onboarding-cohort-classifier.test.ts | 28 -- ...onboarding-feature-setup-validator.test.ts | 23 - src/main/telemetry/validator.test.ts | 422 ------------------ src/main/telemetry/wsl-usage-reporter.test.ts | 43 -- src/main/telemetry/wsl-usage-snapshot.test.ts | 46 -- 14 files changed, 5 insertions(+), 793 deletions(-) delete mode 100644 src/main/daemon/daemon-pty-adapter-full-disk-access.test.ts delete mode 100644 src/main/github/project-view-field-values.test.ts delete mode 100644 src/main/runtime/runtime-client-settings-queue-follow-ups-projection.test.ts delete mode 100644 src/main/startup/quit-and-stop-all-sessions-prompt.test.ts diff --git a/config/reliability-gates.jsonc b/config/reliability-gates.jsonc index 45445eb7c8e..ccb9d48ae2b 100644 --- a/config/reliability-gates.jsonc +++ b/config/reliability-gates.jsonc @@ -21198,7 +21198,7 @@ "invariant": "A packaged macOS daemon runs from the verified signed helper copy for its build, which the updater never touches, and never beside a job that may own the endpoint; the fork fallback still fits the startup gate. A copy is deleted only when lsof proves it unused.", "oracle": "Deterministic launch, fallback-deadline, per-build copy, retirement and status tests, plus the signed launcher validation recorded in #25848.", "commands": [ - "ORCA_BACKGROUND_LAUNCH=1 pnpm test src/main/daemon/macos-daemon-bundle.test.ts src/main/daemon/macos-daemon-launchd.test.ts src/main/daemon/daemon-init-macos-stable-launch-fallback.test.ts src/main/daemon/macos-daemon-job-state.test.ts src/main/daemon/macos-daemon-bundle-retirement.test.ts src/main/daemon/daemon-full-disk-access-status.test.ts src/main/daemon/daemon-pty-adapter-full-disk-access.test.ts config/scripts/macos-folder-usage-descriptions.test.mjs src/renderer/src/components/settings/DeveloperPermissionsPane.test.tsx" + "ORCA_BACKGROUND_LAUNCH=1 pnpm test src/main/daemon/macos-daemon-bundle.test.ts src/main/daemon/macos-daemon-launchd.test.ts src/main/daemon/daemon-init-macos-stable-launch-fallback.test.ts src/main/daemon/macos-daemon-job-state.test.ts src/main/daemon/macos-daemon-bundle-retirement.test.ts src/main/daemon/daemon-full-disk-access-status.test.ts config/scripts/macos-folder-usage-descriptions.test.mjs src/renderer/src/components/settings/DeveloperPermissionsPane.test.tsx" ], "testFiles": [ "src/main/daemon/macos-daemon-bundle.test.ts", @@ -21207,7 +21207,6 @@ "src/main/daemon/macos-daemon-job-state.test.ts", "src/main/daemon/macos-daemon-bundle-retirement.test.ts", "src/main/daemon/daemon-full-disk-access-status.test.ts", - "src/main/daemon/daemon-pty-adapter-full-disk-access.test.ts", "config/scripts/macos-folder-usage-descriptions.test.mjs", "src/renderer/src/components/settings/DeveloperPermissionsPane.test.tsx" ], @@ -21241,6 +21240,7 @@ "runner": "local", "platform": "macos", "command": "ORCA_BACKGROUND_LAUNCH=1 pnpm test src/main/daemon/macos-daemon-bundle.test.ts src/main/daemon/macos-daemon-launchd.test.ts src/main/daemon/daemon-init-macos-stable-launch-fallback.test.ts src/main/daemon/macos-daemon-job-state.test.ts src/main/daemon/macos-daemon-bundle-retirement.test.ts src/main/daemon/daemon-full-disk-access-status.test.ts src/main/daemon/daemon-pty-adapter-full-disk-access.test.ts config/scripts/macos-folder-usage-descriptions.test.mjs src/renderer/src/components/settings/DeveloperPermissionsPane.test.tsx", + "currentCommand": "ORCA_BACKGROUND_LAUNCH=1 pnpm test src/main/daemon/macos-daemon-bundle.test.ts src/main/daemon/macos-daemon-launchd.test.ts src/main/daemon/daemon-init-macos-stable-launch-fallback.test.ts src/main/daemon/macos-daemon-job-state.test.ts src/main/daemon/macos-daemon-bundle-retirement.test.ts src/main/daemon/daemon-full-disk-access-status.test.ts config/scripts/macos-folder-usage-descriptions.test.mjs src/renderer/src/components/settings/DeveloperPermissionsPane.test.tsx", "result": "passed", "durationSeconds": 2.38, "summary": "All 82 focused launch, fallback-deadline, per-build copy, retirement, status and packaging tests passed." diff --git a/config/scripts/ci-shard-timings.json b/config/scripts/ci-shard-timings.json index fe5c823994b..6a1ff73cde9 100644 --- a/config/scripts/ci-shard-timings.json +++ b/config/scripts/ci-shard-timings.json @@ -2125,7 +2125,6 @@ "src/main/daemon/daemon-pty-adapter-cold-restore-seed.test.ts": 751, "src/main/daemon/daemon-pty-adapter-concurrent-recovery.test.ts": 700, "src/main/daemon/daemon-pty-adapter-daemon-recovery.test.ts": 1326, - "src/main/daemon/daemon-pty-adapter-full-disk-access.test.ts": 505, "src/main/daemon/daemon-pty-adapter-history-checkpoints.test.ts": 1460, "src/main/daemon/daemon-pty-adapter-history-recovery.test.ts": 1078, "src/main/daemon/daemon-pty-adapter-history-shutdown-admission.test.ts": 671, diff --git a/src/main/daemon/daemon-pty-adapter-full-disk-access.test.ts b/src/main/daemon/daemon-pty-adapter-full-disk-access.test.ts deleted file mode 100644 index 1f45be336a5..00000000000 --- a/src/main/daemon/daemon-pty-adapter-full-disk-access.test.ts +++ /dev/null @@ -1,37 +0,0 @@ -import { afterEach, expect, it, vi } from 'vitest' -import { DaemonClient } from './client' -import { DaemonPtyAdapter } from './daemon-pty-adapter' - -afterEach(() => vi.restoreAllMocks()) - -it.each([ - [{ status: 'granted' }, 'granted'], - [{ status: 'denied' }, 'denied'], - [{ status: 'future-status' }, 'unknown'], - [null, 'unknown'] -])('checks the owning connection and validates %j', async (response, expected) => { - vi.spyOn(DaemonClient.prototype, 'isConnected').mockReturnValue(true) - const request = vi.spyOn(DaemonClient.prototype, 'request').mockResolvedValue(response) - const adapter = new DaemonPtyAdapter({ socketPath: '/unused', tokenPath: '/unused' }) - expect(await adapter.getFullDiskAccessStatus()).toBe(expected) - expect(request).toHaveBeenCalledWith('fullDiskAccessStatus', undefined, 3000) -}) - -it.each(['Unknown request type', 'Request timed out', 'Connection lost'])( - 'keeps old or unreachable hosts unknown: %s', - async (message) => { - vi.spyOn(DaemonClient.prototype, 'isConnected').mockReturnValue(true) - vi.spyOn(DaemonClient.prototype, 'request').mockRejectedValue(new Error(message)) - const adapter = new DaemonPtyAdapter({ socketPath: '/unused', tokenPath: '/unused' }) - expect(await adapter.getFullDiskAccessStatus()).toBe('unknown') - } -) - -it('does not reconnect or respawn a disconnected host to obtain a verdict', async () => { - const request = vi.spyOn(DaemonClient.prototype, 'request') - const connect = vi.spyOn(DaemonClient.prototype, 'ensureConnected') - const adapter = new DaemonPtyAdapter({ socketPath: '/unused', tokenPath: '/unused' }) - expect(await adapter.getFullDiskAccessStatus()).toBe('unknown') - expect(request).not.toHaveBeenCalled() - expect(connect).not.toHaveBeenCalled() -}) diff --git a/src/main/github/project-view-field-values.test.ts b/src/main/github/project-view-field-values.test.ts deleted file mode 100644 index 5b1b6cd3634..00000000000 --- a/src/main/github/project-view-field-values.test.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { describe, expect, it } from 'vitest' -import { normalizeLinkedPullRequests } from './project-view/project-view-field-normalization' -describe('normalizeLinkedPullRequests linked PR values', () => { - it('normalizes linked pull requests with a visible overflow count', () => { - const value = normalizeLinkedPullRequests({ - __typename: 'ProjectV2ItemFieldPullRequestValue', - field: { id: 'field-pr', name: 'Linked pull requests', dataType: 'LINKED_PULL_REQUESTS' }, - pullRequests: { - totalCount: 12, - nodes: [{ number: 12, title: 'Fix', url: 'https://github.com/o/r/pull/12' }, null] - } - }) - expect(value).toEqual({ - pullRequests: [{ number: 12, title: 'Fix', url: 'https://github.com/o/r/pull/12' }], - totalCount: 12 - }) - }) -}) diff --git a/src/main/runtime/runtime-client-settings-queue-follow-ups-projection.test.ts b/src/main/runtime/runtime-client-settings-queue-follow-ups-projection.test.ts deleted file mode 100644 index 4a6c1ad038c..00000000000 --- a/src/main/runtime/runtime-client-settings-queue-follow-ups-projection.test.ts +++ /dev/null @@ -1,28 +0,0 @@ -import { describe, expect, it } from 'vitest' -import { RuntimeClientSettingsController } from './runtime-client-settings' -import { createGlobalSettingsFixture } from '../../shared/global-settings-test-fixture' -import type { GlobalSettings } from '../../shared/global-settings-types' - -// Missing nativeChatQueueFollowUps looks like an older host to mobile, which then queues mid-turn sends. -function projectionOf(settings: Partial) { - // oxlint-disable-next-line typescript/consistent-type-assertions -- SAFETY: get() reads nothing but store.getSettings(); every other RuntimeStore member is unreachable from that path. - return new RuntimeClientSettingsController({ getSettings: () => settings } as never).get() -} - -function hostSettings(overrides: Partial): Partial { - return { ...createGlobalSettingsFixture({ workspaceDir: '/w' }), ...overrides } -} - -describe('RuntimeClientSettingsController queue follow-ups projection', () => { - it('publishes the opt-out to paired clients', () => { - expect( - projectionOf(hostSettings({ nativeChatQueueFollowUps: false })).nativeChatQueueFollowUps - ).toBe(false) - }) - - it('reports on when the host has no persisted preference', () => { - const settings = hostSettings({}) - delete settings.nativeChatQueueFollowUps - expect(projectionOf(settings).nativeChatQueueFollowUps).toBe(true) - }) -}) diff --git a/src/main/startup/quit-and-stop-all-sessions-prompt.test.ts b/src/main/startup/quit-and-stop-all-sessions-prompt.test.ts deleted file mode 100644 index f9e3db8149b..00000000000 --- a/src/main/startup/quit-and-stop-all-sessions-prompt.test.ts +++ /dev/null @@ -1,28 +0,0 @@ -import type { MessageBoxOptions, MessageBoxReturnValue } from 'electron' -import { describe, expect, it, vi } from 'vitest' -import { confirmQuitAndStopAllSessions } from './quit-and-stop-all-sessions-prompt' - -function showMessageBoxAnswering(response: number) { - return vi.fn(async (_options: MessageBoxOptions): Promise => ({ - response, - checkboxChecked: false - })) -} - -describe('confirmQuitAndStopAllSessions', () => { - it('confirms only when the user picks Stop Sessions and Quit', async () => { - await expect(confirmQuitAndStopAllSessions(showMessageBoxAnswering(0))).resolves.toBe(true) - await expect(confirmQuitAndStopAllSessions(showMessageBoxAnswering(1))).resolves.toBe(false) - }) - - it('makes Cancel the default so Return or Escape never stops running agents', async () => { - const showMessageBox = showMessageBoxAnswering(1) - - await confirmQuitAndStopAllSessions(showMessageBox) - - const options = showMessageBox.mock.calls[0][0] - expect(options.buttons).toEqual(['Stop Sessions and Quit', 'Cancel']) - expect(options.defaultId).toBe(1) - expect(options.cancelId).toBe(1) - }) -}) diff --git a/src/main/telemetry/client-agent-dashboard-snapshot.test.ts b/src/main/telemetry/client-agent-dashboard-snapshot.test.ts index 6a188d82c59..1a4e1f75f63 100644 --- a/src/main/telemetry/client-agent-dashboard-snapshot.test.ts +++ b/src/main/telemetry/client-agent-dashboard-snapshot.test.ts @@ -1,5 +1,5 @@ import { afterEach, beforeEach, describe, expect, it } from 'vitest' -import { eventSchemas } from '../../shared/telemetry-events' + import { persistBannerAcknowledgeWithoutEmitting, track, trackAppOpenedOnce } from './client' import { cleanupTelemetryClientTest, @@ -45,28 +45,6 @@ describe('Agent Dashboard app-open snapshot', () => { expect(state.mock.capture.mock.calls[0]?.[0].properties.agent_dashboard_enabled).toBe(true) }) - it.each(['opt_out', 'pending_banner', 'do_not_track', 'orca_disabled', 'ci'])( - 'sends no snapshot when consent is blocked by %s', - (block) => { - state.settings.experimentalAgentDashboardPopout = true - if (block === 'opt_out') { - state.settings.telemetry!.optedIn = false - } else if (block === 'pending_banner') { - state.settings.telemetry!.optedIn = null - } else if (block === 'do_not_track') { - process.env.DO_NOT_TRACK = '1' - } else if (block === 'orca_disabled') { - process.env.ORCA_TELEMETRY_DISABLED = '1' - } else { - process.env.CI = '1' - } - - trackAppOpenedOnce() - - expect(state.mock.capture).not.toHaveBeenCalled() - } - ) - it('reads the latest setting when the pending banner is resolved', async () => { state.settings.telemetry!.optedIn = null state.settings.telemetry!.existedBeforeTelemetryRelease = true @@ -84,12 +62,4 @@ describe('Agent Dashboard app-open snapshot', () => { properties: { agent_dashboard_enabled: true } }) }) - - it('keeps the app-open schema compatible with older payloads and rejects non-boolean state', () => { - expect(eventSchemas.app_opened.safeParse({}).success).toBe(true) - expect(eventSchemas.app_opened.safeParse({ agent_dashboard_enabled: true }).success).toBe(true) - expect(eventSchemas.app_opened.safeParse({ agent_dashboard_enabled: 'true' }).success).toBe( - false - ) - }) }) diff --git a/src/main/telemetry/client-lifecycle.test.ts b/src/main/telemetry/client-lifecycle.test.ts index 236f251d2bc..4b5ccd731ee 100644 --- a/src/main/telemetry/client-lifecycle.test.ts +++ b/src/main/telemetry/client-lifecycle.test.ts @@ -1,18 +1,8 @@ -import type { PostHog } from 'posthog-node' import { afterEach, beforeEach, describe, expect, it } from 'vitest' -import { - _enableTransportForTests, - _setPostHogClientForTests, - _setShuttingDownForTests, - persistBannerAcknowledgeWithoutEmitting, - setOptIn, - shouldOptOutSdkAtInit, - shutdownTelemetry -} from './client' +import { persistBannerAcknowledgeWithoutEmitting, setOptIn } from './client' import { BASE_COMMON, cleanupTelemetryClientTest, - makeMockPostHog, setupTelemetryClientTest, type MockPostHog, type TelemetryClientTestState @@ -66,17 +56,6 @@ describe('setOptIn()', () => { ) }) - it('drops telemetry_opted_in silently in non-official builds', async () => { - state.settings.telemetry!.optedIn = false - _setPostHogClientForTests(null) - _enableTransportForTests(false) - - await setOptIn('settings', true) - - expect(mock.capture).not.toHaveBeenCalled() - expect(console.debug).not.toHaveBeenCalled() - }) - it('fires app_opened once after pending-banner opt-in enables the SDK', async () => { state.settings.telemetry = { optedIn: null, @@ -129,41 +108,3 @@ describe('persistBannerAcknowledgeWithoutEmitting()', () => { ) }) }) - -// pending_banner must not opt out the SDK before the banner Turn Off capture can enqueue. -describe('shouldOptOutSdkAtInit()', () => { - it('opts out the SDK for every disabled-reason', () => { - for (const reason of ['user_opt_out', 'ci', 'do_not_track', 'orca_disabled'] as const) { - expect(shouldOptOutSdkAtInit({ effective: 'disabled', reason })).toBe(true) - } - }) - - it('does NOT opt out the SDK for pending_banner', () => { - expect(shouldOptOutSdkAtInit({ effective: 'pending_banner' })).toBe(false) - }) - - it('does NOT opt out the SDK for enabled', () => { - expect(shouldOptOutSdkAtInit({ effective: 'enabled' })).toBe(false) - }) -}) - -describe('shutdownTelemetry()', () => { - afterEach(() => { - _setShuttingDownForTests(false) - _setPostHogClientForTests(null) - }) - - it('sets the shutdown gate and calls posthog.shutdown(2000)', async () => { - const mock = makeMockPostHog() - _setPostHogClientForTests(mock as unknown as PostHog) - _setShuttingDownForTests(false) - await shutdownTelemetry() - expect(mock.shutdown).toHaveBeenCalledWith(2_000) - _setPostHogClientForTests(null) - }) - - it('is a no-op when no client is initialized', async () => { - _setPostHogClientForTests(null) - await expect(shutdownTelemetry()).resolves.toBeUndefined() - }) -}) diff --git a/src/main/telemetry/consent.test.ts b/src/main/telemetry/consent.test.ts index 39ca7aab7b2..70dd0af473e 100644 --- a/src/main/telemetry/consent.test.ts +++ b/src/main/telemetry/consent.test.ts @@ -1,4 +1,4 @@ -import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest' +import { describe, it, expect, beforeEach, afterEach } from 'vitest' import type { GlobalSettings } from '../../shared/global-settings-types' import { resolveConsent, _resetMisconfigWarnCacheForTests } from './consent' @@ -146,31 +146,6 @@ describe('resolveConsent', () => { ).toEqual({ effective: 'enabled' }) }) - it('warns to stderr once for misconfigured env var values like "yes" / "on" / "FALSE"', () => { - const spy = vi.spyOn(process.stderr, 'write').mockReturnValue(true) - try { - process.env.DO_NOT_TRACK = 'yes' - resolveConsent( - settingsWithTelemetry({ - optedIn: true, - installId: 'x', - existedBeforeTelemetryRelease: false - }) - ) - resolveConsent( - settingsWithTelemetry({ - optedIn: true, - installId: 'x', - existedBeforeTelemetryRelease: false - }) - ) - expect(spy).toHaveBeenCalledTimes(1) - expect(spy.mock.calls[0][0]).toContain('DO_NOT_TRACK') - } finally { - spy.mockRestore() - } - }) - it('treats a misconfigured DO_NOT_TRACK=0 as unset (not truthy)', () => { // String zero must not disable telemetry through ordinary JavaScript truthiness. process.env.DO_NOT_TRACK = '0' diff --git a/src/main/telemetry/onboarding-cohort-classifier.test.ts b/src/main/telemetry/onboarding-cohort-classifier.test.ts index bd91897512a..8a7de1ee158 100644 --- a/src/main/telemetry/onboarding-cohort-classifier.test.ts +++ b/src/main/telemetry/onboarding-cohort-classifier.test.ts @@ -73,21 +73,6 @@ describe('onboarding-cohort-classifier', () => { expect(getOnboardingCohortAtEmit()).toEqual({ cohort: 'upgrade_backfill' }) }) - it('classifies a live-completed existing user as upgrade_backfill (known limitation)', () => { - // Migration backfill and existing-user live completion share one shape; dashboards must forward-fill cohort from session _started events. - initOnboardingCohortClassifier( - makeFakeStore({ - existedBefore: true, - onboarding: { - outcome: 'completed', - lastCompletedStep: ONBOARDING_FINAL_STEP, - closedAt: 1234567890 - } - }) - ) - expect(getOnboardingCohortAtEmit()).toEqual({ cohort: 'upgrade_backfill' }) - }) - it('classifies an existing user mid-wizard as fresh_install (the funnel cohort)', () => { // Without canonical backfill completion, existing users still going through the wizard belong to fresh_install. initOnboardingCohortClassifier( @@ -104,10 +89,6 @@ describe('onboarding-cohort-classifier', () => { expect(getOnboardingCohortAtEmit()).toEqual({ cohort: undefined }) }) - it('returns undefined when the store is not initialized', () => { - expect(getOnboardingCohortAtEmit()).toEqual({ cohort: undefined }) - }) - it('never throws and returns undefined when getSettings throws', () => { initOnboardingCohortClassifier(makeFakeStore({ existedBefore: false, throwOnSettings: true })) expect(() => getOnboardingCohortAtEmit()).not.toThrow() @@ -119,13 +100,4 @@ describe('onboarding-cohort-classifier', () => { expect(() => getOnboardingCohortAtEmit()).not.toThrow() expect(getOnboardingCohortAtEmit()).toEqual({ cohort: undefined }) }) - - it('warns at most once per session even across many degraded calls', () => { - initOnboardingCohortClassifier(makeFakeStore({ existedBefore: false, throwOnSettings: true })) - const warnSpy = console.warn as unknown as ReturnType - for (let i = 0; i < 50; i++) { - getOnboardingCohortAtEmit() - } - expect(warnSpy).toHaveBeenCalledTimes(1) - }) }) diff --git a/src/main/telemetry/onboarding-feature-setup-validator.test.ts b/src/main/telemetry/onboarding-feature-setup-validator.test.ts index dc52246e15e..a41a0345936 100644 --- a/src/main/telemetry/onboarding-feature-setup-validator.test.ts +++ b/src/main/telemetry/onboarding-feature-setup-validator.test.ts @@ -38,29 +38,6 @@ describe('onboarding feature setup telemetry validation', () => { } }) - it('rejects raw strings and unknown fields', () => { - expect( - validate('onboarding_feature_setup_toggled', { - feature: 'browser_use', - selected: false, - path: '/Users/alice/project' - }).ok - ).toBe(false) - expect( - validate('onboarding_feature_setup_run', { - browser_use: true, - computer_use: false, - linear_tickets: false, - orchestration: false, - selected_count: 1, - cli_touched: false, - skill_install_result: 'Installed ยท 1 left alone', - computer_use_permissions_opened: false, - warning_count: 0 - }).ok - ).toBe(false) - }) - it('rejects selected_count values that do not match selected features', () => { expect( validate('onboarding_feature_setup_run', { diff --git a/src/main/telemetry/validator.test.ts b/src/main/telemetry/validator.test.ts index 94e41267b35..a5ac7aeb9dd 100644 --- a/src/main/telemetry/validator.test.ts +++ b/src/main/telemetry/validator.test.ts @@ -10,67 +10,6 @@ describe('validate', () => { vi.restoreAllMocks() }) - it('accepts a well-formed app_opened payload', () => { - const result = validate('app_opened', {}) - expect(result.ok).toBe(true) - }) - - it('accepts a well-formed agent_started payload', () => { - const result = validate('agent_started', { - agent_kind: 'claude-code', - launch_source: 'command_palette', - request_kind: 'new' - }) - expect(result.ok).toBe(true) - }) - - it('accepts a well-formed agent_prompt_sent payload', () => { - const result = validate('agent_prompt_sent', { - agent_kind: 'claude-code', - launch_source: 'unknown', - request_kind: 'followup', - nth_repo_added: 1 - }) - expect(result.ok).toBe(true) - }) - - it('accepts a well-formed star_nag_outcome payload with cohort context', () => { - const result = validate('star_nag_outcome', { - outcome: 'opened_repo', - source: 'force_show', - mode: 'web', - threshold: 35, - agents_since_baseline: 42, - agents_since_baseline_bucket: '35-69', - nth_repo_added: 4 - }) - expect(result.ok).toBe(true) - }) - - it('rejects malformed star_nag_outcome payloads', () => { - expect( - validate('star_nag_outcome', { - outcome: 'opened_repo', - source: 'force_show', - mode: 'web', - threshold: 35, - agents_since_baseline: 42, - agents_since_baseline_bucket: '35-69', - raw_error: 'nope' - } as never).ok - ).toBe(false) - expect( - validate('star_nag_outcome', { - outcome: 'opened_repo', - source: 'force_show', - mode: 'web', - threshold: 0, - agents_since_baseline: 42, - agents_since_baseline_bucket: '35-69' - } as never).ok - ).toBe(false) - }) - it('drops unknown event names', () => { const result = validate('not_a_real_event' as never, {}) expect(result.ok).toBe(false) @@ -78,365 +17,4 @@ describe('validate', () => { expect(result.reason).toMatch(/unknown event/) } }) - - it('rejects extra keys via .strict()', () => { - const result = validate('app_opened', { unexpected: 'value' }) - expect(result.ok).toBe(false) - }) - - // Raw agent error strings must fail schema validation and never transmit. - it('rejects error_message on agent_error', () => { - const result = validate('agent_error', { - error_class: 'unknown', - agent_kind: 'claude-code', - error_message: 'at /Users/alice/secret/path/index.ts:42' - } as never) - expect(result.ok).toBe(false) - }) - - it('rejects error_stack on agent_error', () => { - const result = validate('agent_error', { - error_class: 'unknown', - agent_kind: 'claude-code', - error_stack: 'Error: boom\n at /Users/alice/...' - } as never) - expect(result.ok).toBe(false) - }) - - it('drops on missing required key', () => { - const result = validate('agent_started', { - agent_kind: 'claude-code', - launch_source: 'sidebar' - // missing request_kind - } as never) - expect(result.ok).toBe(false) - }) - - it('drops on wrong enum value', () => { - const result = validate('agent_started', { - agent_kind: 'claude-code', - launch_source: 'command_palette', - request_kind: 'restart' // not in ['new', 'resume', 'followup'] - } as never) - expect(result.ok).toBe(false) - }) - - it('accepts a well-formed agent_error payload', () => { - const result = validate('agent_error', { - error_class: 'binary_not_found', - agent_kind: 'claude-code' - }) - expect(result.ok).toBe(true) - }) - - it('rejects agent_error with a deferred enum value', () => { - const result = validate('agent_error', { - error_class: 'auth_expired', - agent_kind: 'claude-code' - } as never) - expect(result.ok).toBe(false) - }) - - // Optional cohort permits degraded undefined; reject negative/noninteger/string shapes (onboarding-funnel-cohort-addendum.md). - - it('accepts app_opened with nth_repo_added=0 (the session-zero cohort signal)', () => { - const result = validate('app_opened', { nth_repo_added: 0 }) - expect(result.ok).toBe(true) - }) - - it('accepts repo_added with nth_repo_added=1', () => { - const result = validate('repo_added', { method: 'folder_picker', nth_repo_added: 1 }) - expect(result.ok).toBe(true) - }) - - // Git/folder evidence belongs to repo_added after project selection left onboarding; optional for remote edges. - - it('accepts repo_added with is_git_repo=true', () => { - const result = validate('repo_added', { method: 'clone_url', is_git_repo: true }) - expect(result.ok).toBe(true) - }) - - it('accepts repo_added with is_git_repo=false', () => { - const result = validate('repo_added', { method: 'folder_picker', is_git_repo: false }) - expect(result.ok).toBe(true) - }) - - it('accepts repo_added without is_git_repo (SSH/remote degraded mode)', () => { - const result = validate('repo_added', { method: 'folder_picker' }) - expect(result.ok).toBe(true) - }) - - it('rejects non-boolean is_git_repo on repo_added', () => { - const result = validate('repo_added', { - method: 'folder_picker', - is_git_repo: 'yes' - } as never) - expect(result.ok).toBe(false) - }) - - it('rejects the retired is_git_repo field on onboarding_completed', () => { - // Strict onboarding-completed schema must reject the retired Git-project field. - const result = validate('onboarding_completed', { - path: 'add_project_modal', - is_git_repo: false, - total_duration_ms: 100 - } as never) - expect(result.ok).toBe(false) - }) - - it('accepts onboarding_completed without is_git_repo', () => { - const result = validate('onboarding_completed', { - path: 'add_project_modal', - total_duration_ms: 100 - }) - expect(result.ok).toBe(true) - }) - - it('rejects negative nth_repo_added', () => { - const result = validate('app_opened', { nth_repo_added: -1 } as never) - expect(result.ok).toBe(false) - }) - - it('rejects non-integer nth_repo_added', () => { - const result = validate('app_opened', { nth_repo_added: 1.5 } as never) - expect(result.ok).toBe(false) - }) - - it('rejects nth_repo_added on a non-cohort event (settings_changed)', () => { - // Undeclared injected cohort fields must drop; IPC therefore injects only where schema declares them. - const result = validate('settings_changed', { - setting_key: 'editorAutoSave', - value_kind: 'bool', - nth_repo_added: 1 - } as never) - expect(result.ok).toBe(false) - }) - - it('accepts onboarding_agent_picked with all required fields', () => { - const result = validate('onboarding_agent_picked', { - agent_kind: 'claude-code', - on_path: true, - detected_count: 2, - detection_state: 'complete', - from_collapsed_section: false - }) - expect(result.ok).toBe(true) - }) - - it('accepts onboarding_agent_picked with cohort injected', () => { - // Optional cohort injection must remain compatible with strict schemas. - const result = validate('onboarding_agent_picked', { - agent_kind: 'codex', - on_path: false, - detected_count: 0, - detection_state: 'pending', - from_collapsed_section: true, - cohort: 'fresh_install' - }) - expect(result.ok).toBe(true) - }) - - it('rejects onboarding_agent_picked with unknown detection_state', () => { - const result = validate('onboarding_agent_picked', { - agent_kind: 'claude-code', - on_path: true, - detected_count: 1, - detection_state: 'detecting', - from_collapsed_section: false - } as never) - expect(result.ok).toBe(false) - }) - - it('accepts onboarding_agent_picked with path_source and path_failure_reason', () => { - const result = validate('onboarding_agent_picked', { - agent_kind: 'claude-code', - on_path: false, - detected_count: 0, - detection_state: 'complete', - from_collapsed_section: false, - path_source: 'sync_seed_only', - path_failure_reason: 'timeout' - }) - expect(result.ok).toBe(true) - }) - - it('accepts onboarding_agent_picked without the new optional path fields', () => { - const result = validate('onboarding_agent_picked', { - agent_kind: 'codex', - on_path: true, - detected_count: 2, - detection_state: 'complete', - from_collapsed_section: false - }) - expect(result.ok).toBe(true) - }) - - it('rejects onboarding_agent_picked with unknown path_source', () => { - const result = validate('onboarding_agent_picked', { - agent_kind: 'claude-code', - on_path: true, - detected_count: 1, - detection_state: 'complete', - from_collapsed_section: false, - path_source: 'env_path' - } as never) - expect(result.ok).toBe(false) - }) - - it('rejects onboarding_agent_picked with unknown path_failure_reason', () => { - const result = validate('onboarding_agent_picked', { - agent_kind: 'claude-code', - on_path: true, - detected_count: 1, - detection_state: 'complete', - from_collapsed_section: false, - path_failure_reason: 'parse_failed' - } as never) - expect(result.ok).toBe(false) - }) - - it('accepts onboarding_ghostty_discovered with field_group_count_bucket', () => { - const result = validate('onboarding_ghostty_discovered', { - state: 'found', - field_group_count_bucket: '4-7' - }) - expect(result.ok).toBe(true) - }) - - it('rejects onboarding_ghostty_discovered with raw count instead of bucket', () => { - // Raw environment counts fingerprint installs and must never transmit. - const result = validate('onboarding_ghostty_discovered', { - state: 'found', - field_group_count_bucket: 5 - } as never) - expect(result.ok).toBe(false) - }) - - it('accepts onboarding_ghostty_import_clicked with no payload', () => { - const result = validate('onboarding_ghostty_import_clicked', {}) - expect(result.ok).toBe(true) - }) - - it('accepts onboarding_ghostty_import_failed with each enum reason', () => { - for (const reason of ['no_config', 'empty_diff', 'unknown'] as const) { - const result = validate('onboarding_ghostty_import_failed', { reason }) - expect(result.ok).toBe(true) - } - }) - - it('accepts onboarding_step_completed with duration_ms and advanced_via', () => { - const result = validate('onboarding_step_completed', { - step: 1, - value_kind: 'agent', - duration_ms: 1234, - advanced_via: 'keyboard' - }) - expect(result.ok).toBe(true) - }) - - it('accepts onboarding_step_completed without the new optional fields', () => { - // Optional additions keep pre-deploy events valid. - const result = validate('onboarding_step_completed', { - step: 2, - value_kind: 'theme' - }) - expect(result.ok).toBe(true) - }) - - it('accepts the Windows terminal onboarding step value kind', () => { - const result = validate('onboarding_step_completed', { - step: 4, - value_kind: 'windows_terminal' - }) - expect(result.ok).toBe(true) - }) - - it('rejects onboarding_step_completed with negative duration_ms', () => { - const result = validate('onboarding_step_completed', { - step: 1, - value_kind: 'agent', - duration_ms: -5 - } as never) - expect(result.ok).toBe(false) - }) - - it('rejects onboarding_step_completed with unknown advanced_via', () => { - const result = validate('onboarding_step_completed', { - step: 1, - value_kind: 'agent', - advanced_via: 'voice' - } as never) - expect(result.ok).toBe(false) - }) - - it('accepts onboarding_task_sources_snapshot with bounded statuses', () => { - const result = validate('onboarding_task_sources_snapshot', { - github_status: 'connected', - linear_status: 'not_connected', - exit_action: 'continue', - duration_ms: 1200, - advanced_via: 'button' - }) - expect(result.ok).toBe(true) - }) - - it('rejects onboarding_task_sources_snapshot with unknown status strings', () => { - const result = validate('onboarding_task_sources_snapshot', { - github_status: 'signed-in', - linear_status: 'not_connected', - exit_action: 'continue' - } as never) - expect(result.ok).toBe(false) - }) - - it('accepts onboarding_windows_terminal_snapshot with bounded choices', () => { - const result = validate('onboarding_windows_terminal_snapshot', { - default_shell: 'git_bash', - right_click_behavior: 'menu', - exit_action: 'continue', - duration_ms: 1200, - advanced_via: 'keyboard' - }) - expect(result.ok).toBe(true) - }) - - it('rejects onboarding_windows_terminal_snapshot with raw shell values', () => { - const result = validate('onboarding_windows_terminal_snapshot', { - default_shell: 'C:\\Program Files\\Git\\bin\\bash.exe', - right_click_behavior: 'menu', - exit_action: 'continue' - } as never) - expect(result.ok).toBe(false) - }) - - it('accepts onboarding_started with cohort upgrade_backfill', () => { - const result = validate('onboarding_started', { cohort: 'upgrade_backfill' }) - expect(result.ok).toBe(true) - }) - - it('rejects cohort on a non-onboarding event', () => { - // Schema shape drives selective IPC cohort injection; reject it elsewhere. - const result = validate('app_opened', { - cohort: 'fresh_install' - } as never) - expect(result.ok).toBe(false) - }) - - it('accepts onboarding_started with cohort: undefined (classifier fail-soft)', () => { - // Fail-soft IPC spread creates an explicit undefined cohort key; optional schema must accept it just like omission. - const result = validate('onboarding_started', { cohort: undefined }) - expect(result.ok).toBe(true) - }) - - // First rejection warns; repeats in the same minute must not flood stderr. - it('rate-limits warns to 1/min per event name', () => { - const warn = vi.spyOn(console, 'warn').mockImplementation(() => {}) - _resetValidatorWarnCacheForTests() - validate('app_opened', { bogus: true } as never) - const afterFirst = warn.mock.calls.length - validate('app_opened', { bogus2: true } as never) - const afterSecond = warn.mock.calls.length - expect(afterFirst).toBe(1) - expect(afterSecond).toBe(1) - }) }) diff --git a/src/main/telemetry/wsl-usage-reporter.test.ts b/src/main/telemetry/wsl-usage-reporter.test.ts index f32c15070b8..a4b0ceb9aa7 100644 --- a/src/main/telemetry/wsl-usage-reporter.test.ts +++ b/src/main/telemetry/wsl-usage-reporter.test.ts @@ -12,7 +12,6 @@ vi.mock('./client', () => ({ import { collectWslProjects, countWindowsDriveReposWithWslWorktrees, - listRunningDistrosForSnapshot, WSL_USAGE_SNAPSHOT_INTERVAL_MS, WslUsageReporter, type WslUsageStore @@ -74,14 +73,6 @@ describe('WslUsageReporter', () => { expect(gather).toHaveBeenCalledTimes(2) }) - it('gathers nothing off Windows or while telemetry is off', async () => { - expect(await reporter({ platform: 'darwin' }).reportIfDue()).toBe(false) - expect(await reporter({ platform: 'linux' }).reportIfDue()).toBe(false) - expect(await reporter({ telemetryEnabled: () => false }).reportIfDue()).toBe(false) - expect(gather).not.toHaveBeenCalled() - expect(trackMock).not.toHaveBeenCalled() - }) - it('does not regather an hour after a failed gather', async () => { gather.mockRejectedValueOnce(new Error('store unavailable')) const warn = vi.spyOn(console, 'warn').mockImplementation(() => {}) @@ -111,40 +102,6 @@ describe('WslUsageReporter', () => { writeFileSync(join(dir, 'wsl-usage-telemetry.json'), 'not json') expect(await reporter().reportIfDue()).toBe(true) }) - - it('never throws when gathering fails', async () => { - gather.mockRejectedValueOnce(new Error('reg.exe timed out')) - const warn = vi.spyOn(console, 'warn').mockImplementation(() => {}) - expect(await reporter().reportIfDue()).toBe(false) - warn.mockRestore() - }) -}) - -describe('listRunningDistrosForSnapshot', () => { - it('reuses a confirmed list without probing', async () => { - const probe = vi.fn(async () => ['Other']) - const running = await listRunningDistrosForSnapshot( - [{ distro: 'Ubuntu' }], - () => ['Ubuntu'], - probe - ) - expect(running).toEqual(['Ubuntu']) - expect(probe).not.toHaveBeenCalled() - }) - - it('probes once when nothing is cached and a user distro exists', async () => { - const probe = vi.fn(async () => ['Ubuntu']) - const running = await listRunningDistrosForSnapshot([{ distro: 'Ubuntu' }], () => null, probe) - expect(running).toEqual(['Ubuntu']) - expect(probe).toHaveBeenCalledTimes(1) - }) - - it('never probes without a user distro', async () => { - const probe = vi.fn(async () => []) - await listRunningDistrosForSnapshot([{ distro: 'docker-desktop' }], () => null, probe) - await listRunningDistrosForSnapshot(null, () => null, probe) - expect(probe).not.toHaveBeenCalled() - }) }) describe('collectWslProjects', () => { diff --git a/src/main/telemetry/wsl-usage-snapshot.test.ts b/src/main/telemetry/wsl-usage-snapshot.test.ts index f8115a2bad4..962312ddfb2 100644 --- a/src/main/telemetry/wsl-usage-snapshot.test.ts +++ b/src/main/telemetry/wsl-usage-snapshot.test.ts @@ -3,11 +3,8 @@ import { validate } from './validator' import { buildWslUsageSnapshot, classifyLocalWslProject, - classifyWslHostProject, - toWslMajorMinor, type WslUsageSnapshotInput } from './wsl-usage-snapshot' -import { bucketWslUsageCount } from '../../shared/telemetry-wsl-usage-event-schemas' const baseInput: WslUsageSnapshotInput = { registeredDistroCount: 0, @@ -19,33 +16,6 @@ const baseInput: WslUsageSnapshotInput = { wslHostsGateOpen: false } -describe('bucketWslUsageCount', () => { - it.each([ - [0, '0'], - [1, '1'], - [2, '2-5'], - [5, '2-5'], - [6, '6-20'], - [20, '6-20'], - [21, '21+'], - [500, '21+'] - ])('%i -> %s', (count, bucket) => { - expect(bucketWslUsageCount(count)).toBe(bucket) - }) -}) - -describe('toWslMajorMinor', () => { - it('keeps major.minor only', () => { - expect(toWslMajorMinor('2.4.13.0')).toBe('2.4') - expect(toWslMajorMinor('2.6')).toBe('2.6') - }) - it('drops anything not version-shaped', () => { - expect(toWslMajorMinor(null)).toBeNull() - expect(toWslMajorMinor('Ubuntu 2.4')).toBeNull() - expect(toWslMajorMinor('2')).toBeNull() - }) -}) - describe('classifyLocalWslProject', () => { it('counts a \\\\wsl$ share as inside the distro', () => { expect( @@ -109,15 +79,6 @@ describe('classifyLocalWslProject', () => { }) }) -describe('classifyWslHostProject', () => { - it('splits /mnt/ from distro paths', () => { - expect(classifyWslHostProject({ path: '/mnt/c/src/app' }, 'Ubuntu').location).toBe( - 'windows_drive' - ) - expect(classifyWslHostProject({ path: '/home/me/app' }, 'Ubuntu').location).toBe('distro_fs') - }) -}) - describe('buildWslUsageSnapshot', () => { it('reports buckets and booleans only, and passes the event validator', () => { const props = buildWslUsageSnapshot({ @@ -167,11 +128,4 @@ describe('buildWslUsageSnapshot', () => { expect('wsl_version' in props).toBe(false) expect(validate('wsl_usage_snapshot', props).ok).toBe(true) }) - - it('the validator rejects identifying extras', () => { - const props = buildWslUsageSnapshot(baseInput) - expect(validate('wsl_usage_snapshot', { ...props, distro: 'Ubuntu' }).ok).toBe(false) - expect(validate('wsl_usage_snapshot', { ...props, wsl_version: 'Ubuntu' }).ok).toBe(false) - expect(validate('wsl_usage_snapshot', { ...props, distros_installed: '3' }).ok).toBe(false) - }) })