import { InfiniteData, QueryClient } from '@tanstack/react-query' import { buildTestQueryClient } from '../../../__utils__/query_client' import type { ApiCollection, ApiResource, MessageResource } from '../../../types' import type { PersonResource } from '../../../types/resources/person' import { getMessageQueryKey } from '../../request/get_message' import { getMessagesQueryKey } from '../../request/get_messages' import { applyMessageDeletionToCaches, getThreadedMessagesQueryKey } from '../messages_cache' type MessagesQueryData = InfiniteData> const conversation_id = 7 const author = { id: 1, type: 'Person', name: 'Gina', avatar: null } as unknown as PersonResource const message = (id: string, overrides: Partial = {}): MessageResource => ({ type: 'Message', id, text: `msg ${id}`, html: '', createdAt: '2026-01-01T00:00:00Z', deletedAt: null, textEditedAt: null, mine: true, attachments: [], author, reactionCounts: [], replyCount: 0, replyRootId: null, messageType: 'message', ...overrides, }) as MessageResource const mainKey = getMessagesQueryKey({ conversation_id }) const threadKey = getThreadedMessagesQueryKey(conversation_id, 'root') const rootKey = getMessageQueryKey({ conversation_id, messageId: 'root' }) const seedPages = (queryClient: QueryClient, queryKey: unknown[], messages: MessageResource[]) => queryClient.setQueryData(queryKey, { pageParams: [{}], pages: [{ data: messages, links: {}, meta: { count: messages.length, totalCount: 1 } }], }) const pageMessages = (queryClient: QueryClient, queryKey: unknown[]) => queryClient.getQueryData(queryKey)!.pages[0].data describe('applyMessageDeletionToCaches', () => { let queryClient: QueryClient const root = message('root', { replyRootId: 'root', replyCount: 1, text: 'What are our prayer requests?', }) const reply = message('reply', { replyRootId: 'root', replyRoot: root, text: 'Smith family' }) beforeEach(() => { queryClient = buildTestQueryClient() seedPages(queryClient, mainKey, [reply, message('other'), root]) seedPages(queryClient, threadKey, [reply, root]) queryClient.setQueryData>(rootKey, { data: root, links: {}, meta: {}, }) }) it('marks a deleted reply root as deleted everywhere it is cached and keeps its replies', () => { applyMessageDeletionToCaches(queryClient, conversation_id, root) const [threadReply, threadRoot] = pageMessages(queryClient, threadKey) expect(threadRoot.deletedAt).toEqual(expect.any(String)) expect(threadReply).toMatchObject({ id: 'reply', text: 'Smith family' }) expect(threadReply.replyRoot?.deletedAt).toEqual(expect.any(String)) const [mainReply, , mainRoot] = pageMessages(queryClient, mainKey) expect(mainRoot.deletedAt).toEqual(expect.any(String)) expect(mainReply.replyRoot?.deletedAt).toEqual(expect.any(String)) expect(queryClient.getQueryData>(rootKey)!.data.deletedAt).toEqual( expect.any(String) ) }) it('removes a deleted reply from the thread and conversation caches but leaves the root', () => { applyMessageDeletionToCaches(queryClient, conversation_id, reply) expect(pageMessages(queryClient, threadKey).map(m => m.id)).toEqual(['root']) expect(pageMessages(queryClient, mainKey).map(m => m.id)).toEqual(['other', 'root']) expect(pageMessages(queryClient, threadKey)[0].deletedAt).toBeNull() }) it('removes a plain message from the conversation cache without touching thread caches', () => { applyMessageDeletionToCaches(queryClient, conversation_id, message('other')) expect(pageMessages(queryClient, mainKey).map(m => m.id)).toEqual(['reply', 'root']) expect(pageMessages(queryClient, threadKey).map(m => m.id)).toEqual(['reply', 'root']) }) })