diff --git a/app/renderer/sections/Compare.test.tsx b/app/renderer/sections/Compare.test.tsx index c547099f..edfa6641 100644 --- a/app/renderer/sections/Compare.test.tsx +++ b/app/renderer/sections/Compare.test.tsx @@ -3,6 +3,7 @@ import { render, screen, waitFor, within } from '@testing-library/react' import userEvent from '@testing-library/user-event' import { beforeEach, describe, expect, it, vi } from 'vitest' +import { __resetPolledMemo } from '../hooks/usePolled' import type { CohortComparisonReport, CompareJsonReport, ModelStats } from '../lib/types' import { Compare } from './Compare' @@ -162,6 +163,21 @@ describe('Compare', () => { expect(mocks.getCompareModels).toHaveBeenCalledWith('30days', 'all') }) + it('never requests the previous pair against a period whose models do not include it', async () => { + __resetPolledMemo() + const haiku = { ...modelA, model: 'Haiku 5' } + const gpt = { ...modelB, model: 'GPT-6' } + mocks.getCompareModels.mockImplementation(async period => period === 'today' ? [haiku, gpt] : [modelA, modelB]) + mocks.getCompare.mockResolvedValue(report) + const { rerender } = render() + await waitFor(() => expect(mocks.getCompare).toHaveBeenCalledWith('30days', 'all', 'Opus 4.8', 'Sonnet 5')) + + rerender() + await waitFor(() => expect(mocks.getCompare).toHaveBeenCalledWith('today', 'all', 'Haiku 5', 'GPT-6')) + const stale = mocks.getCompare.mock.calls.filter(([period, , a, b]) => period === 'today' && (a === 'Opus 4.8' || b === 'Sonnet 5')) + expect(stale).toEqual([]) + }) + it('renders the need-two-models note without requesting a report', async () => { mocks.getCompareModels.mockResolvedValue([modelA]) render() @@ -334,6 +350,23 @@ describe('Compare cohorts mode', () => { }) }) + it('never requests the previous pair against a period whose models do not include it', async () => { + __resetPolledMemo() + const haiku = { ...modelA, model: 'Haiku 5' } + const gpt = { ...modelB, model: 'GPT-6' } + mocks.getCompareCohortModels.mockImplementation(async period => + period === 'today' ? { ...facets, models: [haiku, gpt] } : facets) + const user = userEvent.setup() + const { rerender } = render() + await user.click(await screen.findByRole('tab', { name: 'Cohorts' })) + await waitFor(() => expect(mocks.getCompareCohort).toHaveBeenCalledWith('30days', 'all', 'Opus 4.8', 'Sonnet 5', undefined, undefined, undefined)) + + rerender() + await waitFor(() => expect(mocks.getCompareCohort).toHaveBeenCalledWith('today', 'all', 'Haiku 5', 'GPT-6', undefined, undefined, undefined)) + const stale = mocks.getCompareCohort.mock.calls.filter(([period, , a, b]) => period === 'today' && (a === 'Opus 4.8' || b === 'Sonnet 5')) + expect(stale).toEqual([]) + }) + it('returns to the classic comparison unchanged', async () => { const user = await openCohorts() mocks.getCompareModels.mockResolvedValue([modelA, modelB]) diff --git a/app/renderer/sections/Compare.tsx b/app/renderer/sections/Compare.tsx index 22b6e9bb..28d41475 100644 --- a/app/renderer/sections/Compare.tsx +++ b/app/renderer/sections/Compare.tsx @@ -194,7 +194,7 @@ function ClassicCompare({ }} /> - {modelA && modelB && modelA !== modelB && ( + {modelA && modelB && modelA !== modelB && modelRows.some(row => row.model === modelA) && modelRows.some(row => row.model === modelB) && ( !!model && !!facets.data?.models.some(row => row.model === model) const report = usePolled( () => codeburn.getCompareCohort(period, provider, modelA ?? '', modelB ?? '', range ?? undefined, project ? [project] : undefined, category || undefined), [period, provider, modelA, modelB, range?.from, range?.to, project, category, refreshToken], { - enabled: ready && !!modelA && !!modelB && modelA !== modelB, + enabled: ready && listed(modelA) && listed(modelB) && modelA !== modelB, memoKey: reportMemoKey('cohort-v2', period, provider, range, JSON.stringify([modelA, modelB, project, category])), }, )