Improve job status notifications
This commit is contained in:
122
lib/server/task-notifications.test.ts
Normal file
122
lib/server/task-notifications.test.ts
Normal file
@@ -0,0 +1,122 @@
|
||||
import { describe, expect, it } from 'bun:test';
|
||||
import type { Task } from '@/lib/types';
|
||||
import { buildTaskNotification } from '@/lib/server/task-notifications';
|
||||
|
||||
function baseTask(overrides: Partial<Omit<Task, 'notification'>> = {}): Omit<Task, 'notification'> {
|
||||
return {
|
||||
id: 'task-1',
|
||||
user_id: 'user-1',
|
||||
task_type: 'sync_filings',
|
||||
status: 'running',
|
||||
stage: 'sync.extract_taxonomy',
|
||||
stage_detail: 'Extracting XBRL taxonomy for 0000320193-26-000001',
|
||||
stage_context: {
|
||||
progress: {
|
||||
current: 2,
|
||||
total: 5,
|
||||
unit: 'filings'
|
||||
},
|
||||
counters: {
|
||||
hydrated: 1,
|
||||
failed: 0
|
||||
},
|
||||
subject: {
|
||||
ticker: 'AAPL',
|
||||
accessionNumber: '0000320193-26-000001'
|
||||
}
|
||||
},
|
||||
resource_key: 'sync_filings:AAPL',
|
||||
notification_read_at: null,
|
||||
notification_silenced_at: null,
|
||||
priority: 50,
|
||||
payload: {
|
||||
ticker: 'AAPL',
|
||||
limit: 20
|
||||
},
|
||||
result: null,
|
||||
error: null,
|
||||
attempts: 1,
|
||||
max_attempts: 3,
|
||||
workflow_run_id: 'run-1',
|
||||
created_at: '2026-03-09T10:00:00.000Z',
|
||||
updated_at: '2026-03-09T10:05:00.000Z',
|
||||
finished_at: null,
|
||||
...overrides
|
||||
};
|
||||
}
|
||||
|
||||
describe('task notification builder', () => {
|
||||
it('builds progress-driven notifications for running sync jobs', () => {
|
||||
const notification = buildTaskNotification(baseTask());
|
||||
|
||||
expect(notification.title).toBe('Filing sync');
|
||||
expect(notification.statusLine).toContain('Running');
|
||||
expect(notification.progress?.percent).toBe(40);
|
||||
expect(notification.stats.some((stat) => stat.label === 'Hydrated' && stat.value === '1')).toBe(true);
|
||||
expect(notification.actions[0]).toMatchObject({
|
||||
id: 'open_filings',
|
||||
primary: true,
|
||||
href: '/filings?ticker=AAPL'
|
||||
});
|
||||
});
|
||||
|
||||
it('builds report actions for completed analyze jobs', () => {
|
||||
const notification = buildTaskNotification(baseTask({
|
||||
task_type: 'analyze_filing',
|
||||
status: 'completed',
|
||||
stage: 'completed',
|
||||
stage_detail: 'Analysis report generated for AAPL 10-Q 0000320193-26-000001.',
|
||||
stage_context: {
|
||||
subject: {
|
||||
ticker: 'AAPL',
|
||||
accessionNumber: '0000320193-26-000001',
|
||||
label: '10-Q'
|
||||
}
|
||||
},
|
||||
payload: {
|
||||
accessionNumber: '0000320193-26-000001'
|
||||
},
|
||||
result: {
|
||||
ticker: 'AAPL',
|
||||
accessionNumber: '0000320193-26-000001',
|
||||
filingType: '10-Q',
|
||||
model: 'test-model'
|
||||
},
|
||||
finished_at: '2026-03-09T10:06:00.000Z'
|
||||
}));
|
||||
|
||||
expect(notification.tone).toBe('success');
|
||||
expect(notification.actions[0]).toMatchObject({
|
||||
id: 'open_analysis_report',
|
||||
label: 'Open summary',
|
||||
primary: true
|
||||
});
|
||||
expect(notification.actions[0]?.href).toContain('/analysis/reports/AAPL/0000320193-26-000001');
|
||||
expect(notification.stats.some((stat) => stat.label === 'Form' && stat.value === '10-Q')).toBe(true);
|
||||
});
|
||||
|
||||
it('keeps filings navigation available for failed analyze jobs', () => {
|
||||
const notification = buildTaskNotification(baseTask({
|
||||
task_type: 'analyze_filing',
|
||||
status: 'failed',
|
||||
stage: 'failed',
|
||||
stage_detail: 'Primary filing document fetch failed.',
|
||||
error: 'Primary filing document fetch failed.',
|
||||
stage_context: {
|
||||
subject: {
|
||||
ticker: 'AAPL',
|
||||
accessionNumber: '0000320193-26-000001'
|
||||
}
|
||||
},
|
||||
payload: {
|
||||
accessionNumber: '0000320193-26-000001'
|
||||
},
|
||||
result: null,
|
||||
finished_at: '2026-03-09T10:06:00.000Z'
|
||||
}));
|
||||
|
||||
expect(notification.tone).toBe('error');
|
||||
expect(notification.detailLine).toBe('Primary filing document fetch failed.');
|
||||
expect(notification.actions.some((action) => action.id === 'open_filings')).toBe(true);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user