Add case follow-up queues and personal update notifications

This commit is contained in:
2026-10-17 20:00:13 -04:00
parent 90b94911c5
commit b678de2f6f
19 changed files with 1408 additions and 16 deletions
+48 -3
View File
@@ -324,13 +324,21 @@ it('opens a newly created case page after preserving selected evidence', async (
it('links case records to workspaces and preserves case filters while paging', () => {
const data = overview('cases');
data.query = { ...data.query, caseStatus: 'active', priority: 'high', assignedTo: 'me' };
data.query = {
...data.query,
caseStatus: 'active',
priority: 'high',
assignedTo: 'me',
review: 'due'
};
data.cases = [
{
id: 'case-1',
game: 't5',
guid,
title: 'Chat investigation',
reviewAt: '2026-10-14T12:00:00Z',
unreadUpdates: 2,
assessment: {
revision: 3,
summary: 'The threat remains ambiguous.',
@@ -357,7 +365,7 @@ it('links case records to workspaces and preserves case filters while paging', (
}
];
data.total = 40;
show(data, 'moderator', '&caseStatus=active&priority=high&assignedTo=me');
show(data, 'moderator', '&caseStatus=active&priority=high&assignedTo=me&review=due');
expect(document.querySelector('a[href="/moderation/cases/case-1"]')?.textContent).toBe(
'Chat investigation'
);
@@ -374,9 +382,46 @@ it('links case records to workspaces and preserves case filters while paging', (
expect(destination.searchParams.get('caseStatus')).toBe('active');
expect(destination.searchParams.get('priority')).toBe('high');
expect(destination.searchParams.get('assignedTo')).toBe('me');
expect(destination.searchParams.get('review')).toBe('due');
expect(document.querySelector('#moderation-results')?.textContent).toContain('Overdue review');
expect(document.querySelector('#moderation-results')?.textContent).toContain(
'2 unread updates'
);
expect(destination.searchParams.get('offset')).toBe('25');
button('Reset').click();
const reset = new URL(navigation.goto.mock.calls.at(-1)![0], 'http://localhost');
for (const filter of ['caseStatus', 'priority', 'assignedTo', 'offset'])
for (const filter of ['caseStatus', 'priority', 'assignedTo', 'review', 'offset'])
expect(reset.searchParams.has(filter)).toBe(false);
});
it('shows personal evidence and assignment notifications with links into the actionable queue', () => {
const data = overview('cases');
data.unreadCount = 2;
data.notifications = [
{
id: 1,
caseId: 'follow-up',
caseTitle: 'Review context',
kind: 'evidence',
createdAt: data.checkedAt,
readAt: null
},
{
id: 2,
caseId: 'appeal',
caseTitle: 'Review appeal',
kind: 'assignment',
createdAt: data.checkedAt,
readAt: null
}
];
show(data);
const notifications = document.querySelector('[aria-label="Your case notifications"]')!;
expect(notifications.textContent).toContain('Evidence or note added');
expect(notifications.textContent).toContain('Assignment changed');
expect(notifications.querySelector('a[href="/moderation/cases/follow-up"]')).not.toBeNull();
expect(
document.querySelector('a[href="/moderation?view=cases&review=updates"]')
).not.toBeNull();
expect(document.querySelector('a[href="/moderation?view=cases&review=due"]')).not.toBeNull();
});