feat(comments) : show heart giver profiles on comments and notifications

This commit is contained in:
2026-10-13 00:45:02 +07:00 Unverified
parent f8ef86cb5e
commit d1dff1a763
8 changed files with 135 additions and 23 deletions
+16 -2
View File
@@ -2,7 +2,7 @@ import { beforeEach, describe, expect, it, vi } from 'vitest';
import { PgDialect } from 'drizzle-orm/pg-core';
import type { SQL } from 'drizzle-orm';
const state = vi.hoisted(() => ({ rows: [] as unknown[][], filters: [] as unknown[], select: vi.fn() }));
const state = vi.hoisted(() => ({ rows: [] as unknown[][], filters: [] as unknown[], joins: [] as unknown[], select: vi.fn() }));
vi.mock('server-only', () => ({}));
vi.mock('./events', () => ({ notifyNotificationChange: vi.fn() }));
vi.mock('@/lib/media/storage', () => ({ publicMediaUrl: (key: string) => `https://cdn.example/${key}` }));
@@ -20,10 +20,11 @@ function row(kind: string, eventKey: string) {
beforeEach(() => {
state.rows = [];
state.filters = [];
state.joins = [];
state.select.mockReset().mockImplementation(() => {
const rows = state.rows.shift() ?? [];
const query = {
from: () => query, leftJoin: () => query, innerJoin: () => query,
from: () => query, leftJoin: (_table: unknown, condition: unknown) => { state.joins.push(condition); return query; }, innerJoin: () => query,
where: (filter: unknown) => { state.filters.push(filter); return query; }, orderBy: () => query, limit: () => query,
then: (resolve: (value: unknown[]) => unknown) => Promise.resolve(rows).then(resolve),
};
@@ -61,4 +62,17 @@ describe('guide overview images in notification feeds', () => {
state.rows = [[row('guide_published', `guide:${guideId}:published`)], [{ count: 1 }], []];
expect((await listNotifications(user)).items[0].imageUrl).toBeNull();
});
it('uses the heart giver for heart notifications and the author for new comments and replies', async () => {
state.rows = [[{ ...row('comment_heart', 'comment:1:heart'), authorName: 'Admin', authorImage: 'https://profile.example/admin.png' }], [{ count: 1 }]];
const result = await listNotifications(user);
expect(result.items[0]).toMatchObject({ authorName: 'Admin', authorImage: 'https://profile.example/admin.png', imageUrl: null });
const joins = state.joins.map(condition => new PgDialect().sqlToQuery(condition as SQL));
const profileJoin = joins.find(join => join.sql.includes('case when'))!;
expect(profileJoin.sql).toContain("= 'comment_heart' then");
expect(profileJoin.sql).toContain('"hearted_by_id" else');
expect(profileJoin.sql).toContain('"author_id" end');
expect(profileJoin.params).toContain('comment_heart');
expect(state.select).toHaveBeenCalledTimes(2);
});
});