import { describe, expect, it } from 'vitest' import { bundleInstallStatsTestUtils } from '../supabase/functions/_backend/private/bundle_install_stats.ts' describe('bundle install stats helpers', () => { it.concurrent('normalizes supported period days', () => { expect(bundleInstallStatsTestUtils.normalizePeriodDays(undefined)).toBe(30) expect(bundleInstallStatsTestUtils.normalizePeriodDays(1)).toBe(1) expect(bundleInstallStatsTestUtils.normalizePeriodDays(7)).toBe(7) expect(bundleInstallStatsTestUtils.normalizePeriodDays(30)).toBe(30) expect(bundleInstallStatsTestUtils.normalizePeriodDays(2)).toBeNull() expect(bundleInstallStatsTestUtils.normalizePeriodDays(365)).toBeNull() }) it.concurrent('computes success rate from install and fail counts', () => { expect(bundleInstallStatsTestUtils.computeSuccessRate(90, 10)).toBe(90) expect(bundleInstallStatsTestUtils.computeSuccessRate(0, 0)).toBeNull() expect(bundleInstallStatsTestUtils.computeSuccessRate(1, 0)).toBe(100) }) it('pairs download start to set for install timing samples', () => { const samples = bundleInstallStatsTestUtils.buildInstallTimingsFromEvents([ { app_id: 'com.demo.app', device_id: 'device-1', action: 'download_0', version_name: '1.0.0', metadata: null, duration_ms: null, created_at: '2026-07-01T10:00:00.000Z', }, { app_id: 'com.demo.app', device_id: 'device-1', action: 'set', version_name: '1.0.0', metadata: null, duration_ms: null, created_at: '2026-07-01T10:00:05.000Z', }, ], { periodStartMs: Date.parse('2026-07-01T00:00:00.000Z'), }) expect(samples).toHaveLength(1) expect(samples[0]?.version_name).toBe('1.0.0') expect(samples[0]?.duration_ms).toBe(5000) }) it('aggregates install timing percentiles per version', () => { const rows = bundleInstallStatsTestUtils.aggregateInstallTimingsByVersion([ { version_name: '1.0.0', duration_ms: 1000 }, { version_name: '1.0.0', duration_ms: 3000 }, { version_name: '1.0.0', duration_ms: 5000 }, { version_name: '1.1.0', duration_ms: 2000 }, ]) const v100 = rows.get('1.0.0') expect(v100?.samples).toBe(3) expect(v100?.p50_ms).toBe(3000) expect(v100?.p70_ms).toBe(3800) expect(rows.get('1.1.0')?.p50_ms).toBe(2000) }) it('builds merged bundle response sorted by activity', () => { const response = bundleInstallStatsTestUtils.buildBundleInstallResponse({ days: 7, start: '2026-07-01T00:00:00.000Z', end: '2026-07-07T23:59:59.999Z', successRows: [ { version_name: '1.0.0', install: 10, fail: 2 }, { version_name: '1.1.0', install: 50, fail: 5 }, ], timingRows: new Map([ ['1.0.0', { version_name: '1.0.0', samples: 8, p50_ms: 1200, p70_ms: 1500, p90_ms: 1800, p95_ms: 2000 }], ]), }) expect(response.bundles[0]?.version_name).toBe('1.1.0') expect(response.bundles[0]?.success_rate).toBe(90.9) expect(response.totals.success_rate).toBe(89.6) expect(response.bundles[1]?.timing.p50_ms).toBe(1200) }) it.concurrent('filters cached response by version_name without mutating the source', () => { const response = bundleInstallStatsTestUtils.buildBundleInstallResponse({ days: 7, start: '2026-07-01T00:00:00.000Z', end: '2026-07-07T23:59:59.999Z', successRows: [ { version_name: '1.0.0', install: 10, fail: 2 }, { version_name: '1.1.0', install: 50, fail: 5 }, ], timingRows: new Map(), }) const responseBeforeFiltering = structuredClone(response) const filtered = bundleInstallStatsTestUtils.filterResponseByVersionName(response, '1.0.0') expect(filtered.bundles).toHaveLength(1) expect(filtered.bundles[0]?.version_name).toBe('1.0.0') expect(filtered.totals.install).toBe(10) expect(filtered.totals.fail).toBe(2) expect(filtered.totals.success_rate).toBe(83.3) expect(response).toEqual(responseBeforeFiltering) expect(response.bundles).toHaveLength(2) }) it.concurrent('aggregates rolling version usage into install/fail rows', () => { const rows = bundleInstallStatsTestUtils.aggregateSuccessRowsFromVersionUsage([ { date: '2026-08-15', app_id: 'com.demo.app', version_name: '1.0.0', get: 0, fail: 1, install: 4, uninstall: 0 }, { date: '2026-08-16', app_id: 'com.demo.app', version_name: '1.0.0', get: 0, fail: 1, install: 6, uninstall: 0 }, { date: '2026-08-16', app_id: 'com.demo.app', version_name: '2.0.0', get: 0, fail: 0, install: 3, uninstall: 0 }, { date: '2026-08-16', app_id: 'com.demo.app', version_name: 'skip-me', get: 0, fail: 9, install: 9, uninstall: 0 }, ], new Set(['1.0.0', '2.0.0'])) expect(rows).toEqual([ { version_name: '1.0.0', install: 10, fail: 2 }, { version_name: '2.0.0', install: 3, fail: 0 }, ]) }) it.concurrent('reads channel-scoped success rates from version_usage for every period', () => { // daily_version has no channel dimension, so channel requests must not use it. expect(bundleInstallStatsTestUtils.readsSuccessFromVersionUsage(30, { id: 1, name: 'production' })).toBe(true) expect(bundleInstallStatsTestUtils.readsSuccessFromVersionUsage(7, { id: 1, name: 'production' })).toBe(true) expect(bundleInstallStatsTestUtils.readsSuccessFromVersionUsage(1)).toBe(true) expect(bundleInstallStatsTestUtils.readsSuccessFromVersionUsage(30)).toBe(false) }) it.concurrent('reports the legacy download_fail ignored per bundle', () => { const response = bundleInstallStatsTestUtils.buildBundleInstallResponse({ days: 7, start: '2026-10-20T00:00:00.000Z', end: '2026-10-26T23:59:59.999Z', successRows: [{ version_name: '1.2.0', install: 500, fail: 30 }], timingRows: new Map(), versionFilter: new Set(['1.2.0', '1.1.0']), legacyCheckFailures: [ { version_name: '1.2.0', excluded: 450, plugin_versions: ['8.51.16'] }, // Installed before the period: only ignored reports, still in the notice. { version_name: '1.1.0', excluded: 5, plugin_versions: ['6.40.0'] }, // Outside the channel's bundles. { version_name: '0.9.0', excluded: 7, plugin_versions: ['5.1.0'] }, ], }) expect(response.bundles.map(bundle => bundle.version_name)).toEqual(['1.2.0']) expect(response.totals).toEqual({ install: 500, fail: 30, success_rate: 94.3 }) expect(response.legacy_check_failures).toEqual({ excluded: 455, plugin_versions: ['6.40.0', '8.51.16'], fixed_in: '8.53.0' }) // A single bundle keeps only its own count and plugin versions. const single = bundleInstallStatsTestUtils.filterResponseByVersionName(response, '1.1.0') expect(single.legacy_check_failures).toEqual({ excluded: 5, plugin_versions: ['6.40.0'], fixed_in: '8.53.0' }) expect(single.legacy_check_failures_by_bundle).toEqual([{ version_name: '1.1.0', excluded: 5, plugin_versions: ['6.40.0'] }]) const none = bundleInstallStatsTestUtils.buildBundleInstallResponse({ days: 7, start: '2026-10-20T00:00:00.000Z', end: '2026-10-26T23:59:59.999Z', successRows: [{ version_name: '1.0.0', install: 10, fail: 1 }], timingRows: new Map(), }) expect(none.legacy_check_failures).toBeNull() expect(none.legacy_check_failures_by_bundle).toEqual([]) }) })