Add attention inbox and AI usage observability
This commit is contained in:
1 parent
ca59ba0f1f
commit
83b5f1f5b6
30 files changed
+702
-28
No files matched your search
@@ -79,7 +79,7 @@ describe('dashboard foundation', () => {
|
||||
const { router } = renderDashboard('/');
|
||||
|
||||
const navigation = screen.getByRole('navigation', { name: 'Primary navigation' });
|
||||
for (const label of ['Overview', 'Conversations', 'Media', 'Performance', 'Operations', 'Settings']) {
|
||||
for (const label of ['Overview', 'Needs attention', 'Conversations', 'Media', 'Performance', 'Operations', 'Settings']) {
|
||||
expect(within(navigation).getByRole('link', { name: label })).toBeInTheDocument();
|
||||
}
|
||||
|
||||
@@ -91,6 +91,24 @@ describe('dashboard foundation', () => {
|
||||
expect(screen.getByRole('heading', { name: 'Operations' })).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('shows actionable attention items and links handoffs to their conversation', async () => {
|
||||
installSuccessfulApi();
|
||||
server.use(http.get('/api/attention', () => HttpResponse.json({
|
||||
generatedAt: Date.parse('2026-08-09T08:00:00Z'),
|
||||
items: [{
|
||||
id: 'conversation:one', kind: 'human-required', severity: 'warning',
|
||||
title: 'Human follow-up required for u/alice', detail: 'Automated turns are exhausted.',
|
||||
occurredAt: Date.parse('2026-08-09T07:00:00Z'),
|
||||
owner: { accountId: '@one:reddit.com', redditUsername: 'operator' },
|
||||
conversationId: '@one:reddit.com~!room:reddit.com', username: 'alice',
|
||||
}],
|
||||
})));
|
||||
renderDashboard('/attention');
|
||||
expect(await screen.findByRole('heading', { name: 'Needs attention' })).toBeInTheDocument();
|
||||
expect(screen.getByText('Human follow-up required for u/alice')).toBeInTheDocument();
|
||||
expect(screen.getByRole('link', { name: 'Open conversation' })).toHaveAttribute('href', '/conversations/%40one%3Areddit.com~!room%3Areddit.com');
|
||||
});
|
||||
|
||||
it('hydrates media filters from the routed URL', async () => {
|
||||
installSuccessfulApi();
|
||||
server.use(
|
||||
|
||||
@@ -83,12 +83,24 @@ describe('PerformancePage', () => {
|
||||
upsell: 3,
|
||||
images: 2,
|
||||
})),
|
||||
http.get('/api/analytics/ai-usage', ({ request }) => {
|
||||
expect(new URL(request.url).searchParams.get('days')).toBe('30');
|
||||
return HttpResponse.json({
|
||||
days: 30, requests: 12, successes: 9, refusals: 2, errors: 1,
|
||||
promptTokens: 1200, completionTokens: 300, totalTokens: 1500,
|
||||
costUsd: 0.0123, averageLatencyMs: 420,
|
||||
models: [{ model: 'model-a', requests: 12, successes: 9, refusals: 2, errors: 1, promptTokens: 1200, completionTokens: 300, totalTokens: 1500, costUsd: 0.0123, averageLatencyMs: 420 }],
|
||||
});
|
||||
}),
|
||||
);
|
||||
|
||||
renderPage(<PerformancePage />);
|
||||
|
||||
expect(await screen.findByRole('heading', { name: 'Performance' })).toBeInTheDocument();
|
||||
expect(screen.getByRole('heading', { name: 'Outcome funnel' })).toBeInTheDocument();
|
||||
expect(screen.getByRole('heading', { name: 'AI cost and reliability' })).toBeInTheDocument();
|
||||
expect(screen.getByRole('table', { name: 'AI usage by model' })).toHaveTextContent('model-a');
|
||||
expect(screen.getByLabelText('AI usage totals')).toHaveTextContent('$0.0123');
|
||||
expect(screen.getByText('5 awaiting maturity')).toBeInTheDocument();
|
||||
const subredditTable = screen.getByRole('table', { name: 'Subreddit performance' });
|
||||
expect(within(subredditTable).getByText('n = 40')).toBeInTheDocument();
|
||||
|
||||
Reference in new issue
Block a user