Skip to content
Merged
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
163 changes: 163 additions & 0 deletions apps/dashboard/src/components/AnalyticsTab.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,128 @@ function compareResponse(): CompareResponse {
};
}

function differingCompareResponse(): CompareResponse {
return {
experiments: ['model-compare'],
targets: ['gpt-5.4', 'gpt-5.4-mini'],
cells: [
{
experiment: 'model-compare',
target: 'gpt-5.4',
eval_count: 2,
quality_count: 2,
passed_count: 1,
pass_rate: 0.5,
avg_score: 0.5,
tests: [],
},
{
experiment: 'model-compare',
target: 'gpt-5.4-mini',
eval_count: 2,
quality_count: 2,
passed_count: 2,
pass_rate: 1,
avg_score: 1,
tests: [],
},
],
runs: [
{
run_id: '2026-07-07T14-06-40-813Z',
started_at: '2026-07-07T14:06:40.813Z',
experiment: 'model-compare',
target: '2 providers',
targets: ['gpt-5.4', 'gpt-5.4-mini'],
source: 'local',
eval_count: 4,
quality_count: 4,
passed_count: 3,
pass_rate: 0.75,
avg_score: 0.75,
tests: [
{
test_id: 'matching-row',
target: 'gpt-5.4',
score: 1,
passed: true,
execution_status: 'ok',
answer: 'same answer',
},
{
test_id: 'matching-row',
target: 'gpt-5.4-mini',
score: 1,
passed: true,
execution_status: 'ok',
answer: 'same answer',
},
{
test_id: 'answer-differs',
target: 'gpt-5.4',
score: 1,
passed: true,
execution_status: 'ok',
answer: 'alpha answer',
},
{
test_id: 'answer-differs',
target: 'gpt-5.4-mini',
score: 1,
passed: true,
execution_status: 'ok',
answer: 'beta answer',
},
{
test_id: 'status-differs',
target: 'gpt-5.4',
score: 1,
passed: true,
execution_status: 'ok',
answer: 'completed',
},
{
test_id: 'status-differs',
target: 'gpt-5.4-mini',
score: 0,
passed: false,
execution_status: 'execution_error',
answer: 'completed',
},
],
},
],
};
}

function matchingCompareResponse(): CompareResponse {
const data = differingCompareResponse();
return {
...data,
runs: data.runs?.map((run) => ({
...run,
tests: [
{
test_id: 'matching-row',
target: 'gpt-5.4',
score: 1,
passed: true,
execution_status: 'ok',
answer: 'same answer',
},
{
test_id: 'matching-row',
target: 'gpt-5.4-mini',
score: 1,
passed: true,
execution_status: 'ok',
answer: 'same answer',
},
],
})),
};
}

describe('AnalyticsTab provider/model comparison', () => {
it('renders same-test provider/model outputs side by side', () => {
const queryClient = new QueryClient();
Expand All @@ -112,4 +234,45 @@ describe('AnalyticsTab provider/model comparison', () => {
expect(html).toContain('Answer');
expect(html).toContain('result_dir=exact-token-gpt54');
});

it('filters provider/model comparison rows to differing outputs', () => {
const queryClient = new QueryClient();
const html = renderToStaticMarkup(
<QueryClientProvider client={queryClient}>
<AnalyticsTab
data={differingCompareResponse()}
isLoading={false}
isError={false}
defaultProviderModelDisplayMode="differing"
/>
</QueryClientProvider>,
);

expect(html).toContain('All');
expect(html).toContain('Differing');
expect(html).toContain('answer-differs');
expect(html).toContain('alpha answer');
expect(html).toContain('beta answer');
expect(html).toContain('status-differs');
expect(html).toContain('error');
expect(html).not.toContain('matching-row');
});

it('shows an empty state when all provider/model comparison rows match', () => {
const queryClient = new QueryClient();
const html = renderToStaticMarkup(
<QueryClientProvider client={queryClient}>
<AnalyticsTab
data={matchingCompareResponse()}
isLoading={false}
isError={false}
defaultProviderModelDisplayMode="differing"
/>
</QueryClientProvider>,
);

expect(html).toContain('All compared rows match');
expect(html).toContain('Switch back to All rows to inspect the full provider/model table.');
expect(html).not.toContain('matching-row');
});
});
Loading
Loading