Improve messaging and dashboard reliability

This commit is contained in:
jjbrunton committed 2026-08-08 21:09:20 +01:00
1 parent 345ec99348
commit 5a5a30a1d4
20 files changed
+406 -56

No files matched your search

+32 -1
View File
@@ -12,6 +12,7 @@ import { ConversationsPage } from '../../apps/dashboard/src/features/conversatio
interface ChatFixtureOptions {
username: string;
roomId: string;
lastMessageTime?: number;
unread?: boolean;
isFromUs?: boolean;
lastMessageSnippet?: string;
@@ -24,7 +25,7 @@ function chatFixture(options: ChatFixtureOptions) {
roomName: options.username,
roomId: options.roomId,
url: `https://chat.reddit.com/room/${options.roomId}`,
lastMessageTime: 1_786_000_000_000,
lastMessageTime: options.lastMessageTime ?? 1_786_000_000_000,
lastMessageSnippet: options.lastMessageSnippet ?? `Latest from ${options.username}`,
isFromUs: options.isFromUs ?? false,
unread: options.unread ?? false,
@@ -141,6 +142,36 @@ describe('ConversationsPage', () => {
);
});
it('orders conversations by latest message activity', async () => {
const oldest = chatFixture({ username: 'oldest', roomId: 'room-oldest', lastMessageTime: 100 });
const newest = chatFixture({ username: 'newest', roomId: 'room-newest', lastMessageTime: 300 });
const middle = chatFixture({ username: 'middle', roomId: 'room-middle', lastMessageTime: 200 });
server.use(http.get('/api/conversations', () => HttpResponse.json([oldest, newest, middle])));
renderConversations();
await screen.findByRole('button', { name: /u\/newest/ });
expect(screen.getAllByRole('button', { name: /u\/(?:oldest|newest|middle)/ }).map((button) => button.getAttribute('aria-label')))
.toEqual([
expect.stringContaining('u/newest'),
expect.stringContaining('u/middle'),
expect.stringContaining('u/oldest'),
]);
});
it('shows short relative times for the latest message', async () => {
const now = Date.now();
const minutesAgo = chatFixture({ username: 'minutes', roomId: 'room-minutes', lastMessageTime: now - (5 * 60_000) });
const daysAgo = chatFixture({ username: 'days', roomId: 'room-days', lastMessageTime: now - (2 * 86_400_000) });
server.use(http.get('/api/conversations', () => HttpResponse.json([daysAgo, minutesAgo])));
renderConversations();
const recentTime = await screen.findByText('5m ago');
expect(recentTime.tagName).toBe('TIME');
expect(recentTime).toHaveAttribute('dateTime', new Date(minutesAgo.lastMessageTime).toISOString());
expect(recentTime).toHaveAttribute('title');
expect(screen.getByText('2d ago')).toBeInTheDocument();
});
it('marks and filters conversations with received images and renders the images in chat', async () => {
const imageChat = chatFixture({
username: 'alice',
+14
View File
@@ -150,6 +150,20 @@ describe('media page', () => {
expect(screen.getByText('No media matches these filters.')).toBeInTheDocument();
});
it('orders media by received time', async () => {
server.use(
http.get('/api/media', () => HttpResponse.json([mediaItems[2], mediaItems[0], mediaItems[1]])),
http.get('/api/media/sync', () => HttpResponse.json(idleStatus)),
);
renderMedia();
expect((await screen.findAllByRole('img')).map((item) => item.getAttribute('alt'))).toEqual([
'Media from alice',
'Media from charlie',
'Media from dave',
]);
});
it('shows empty and recoverable error states', async () => {
let requests = 0;
server.use(