Squash merge feat/expo-app: app-expo, .cursor, workflows, package.json, .husky; remove app-android, app-ios, react-app
This commit is contained in:
134
app-expo/tests/features/conversation/hooks.test.tsx
Normal file
134
app-expo/tests/features/conversation/hooks.test.tsx
Normal file
@@ -0,0 +1,134 @@
|
||||
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
|
||||
import { renderHook, waitFor } from '@testing-library/react-native';
|
||||
import React, { type PropsWithChildren } from 'react';
|
||||
|
||||
import {
|
||||
useConversations,
|
||||
useCreateConversation,
|
||||
useDeleteConversation,
|
||||
} from '@/features/conversation/hooks';
|
||||
import { conversationKeys } from '@/features/conversation/query-keys';
|
||||
|
||||
// ─── Mocks ───
|
||||
|
||||
const mockList = jest.fn();
|
||||
const mockCreate = jest.fn();
|
||||
const mockDelete = jest.fn();
|
||||
|
||||
jest.mock('@/features/conversation/api', () => ({
|
||||
conversationApi: {
|
||||
list: () => mockList(),
|
||||
create: () => mockCreate(),
|
||||
delete: (id: string) => mockDelete(id),
|
||||
detail: jest.fn(),
|
||||
end: jest.fn(),
|
||||
messages: jest.fn(),
|
||||
organize: jest.fn(),
|
||||
},
|
||||
}));
|
||||
|
||||
// ─── Helpers ───
|
||||
|
||||
let queryClient: QueryClient;
|
||||
|
||||
function createWrapper() {
|
||||
queryClient = new QueryClient({
|
||||
defaultOptions: {
|
||||
queries: { retry: false, gcTime: Infinity },
|
||||
mutations: { retry: false },
|
||||
},
|
||||
});
|
||||
|
||||
return function Wrapper({ children }: PropsWithChildren) {
|
||||
return (
|
||||
<QueryClientProvider client={queryClient}>{children}</QueryClientProvider>
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
afterEach(async () => {
|
||||
await queryClient?.cancelQueries();
|
||||
queryClient?.clear();
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
|
||||
const fakeConversations = [
|
||||
{
|
||||
id: 'c1',
|
||||
title: '第一次对话',
|
||||
avatarUrl: null,
|
||||
latestMessagePreview: '你好',
|
||||
latestMessageTime: 1000,
|
||||
unreadCount: 0,
|
||||
isDefaultAssistant: false,
|
||||
},
|
||||
];
|
||||
|
||||
// ─── Tests ───
|
||||
|
||||
describe('useConversations', () => {
|
||||
test('fetches conversation list', async () => {
|
||||
mockList.mockResolvedValue(fakeConversations);
|
||||
|
||||
const { result } = renderHook(() => useConversations(), {
|
||||
wrapper: createWrapper(),
|
||||
});
|
||||
|
||||
await waitFor(() => {
|
||||
expect(result.current.isSuccess).toBe(true);
|
||||
});
|
||||
|
||||
expect(result.current.data).toEqual(fakeConversations);
|
||||
});
|
||||
});
|
||||
|
||||
describe('useCreateConversation', () => {
|
||||
test('adds new conversation to list cache on success', async () => {
|
||||
const newConversation = {
|
||||
id: 'c2',
|
||||
user_id: 'u1',
|
||||
started_at: '2026-01-01T00:00:00Z',
|
||||
status: 'active',
|
||||
};
|
||||
mockCreate.mockResolvedValue(newConversation);
|
||||
|
||||
const wrapper = createWrapper();
|
||||
queryClient.setQueryData(conversationKeys.lists(), fakeConversations);
|
||||
|
||||
const { result } = renderHook(() => useCreateConversation(), { wrapper });
|
||||
|
||||
await result.current.mutateAsync();
|
||||
|
||||
await waitFor(() => {
|
||||
expect(result.current.isSuccess).toBe(true);
|
||||
});
|
||||
|
||||
const list = queryClient.getQueryData(conversationKeys.lists()) as Array<{
|
||||
id: string;
|
||||
}>;
|
||||
expect(list[0].id).toBe('c2');
|
||||
expect(list).toHaveLength(2);
|
||||
});
|
||||
});
|
||||
|
||||
describe('useDeleteConversation', () => {
|
||||
test('removes conversation from list cache on success', async () => {
|
||||
mockDelete.mockResolvedValue({ message: 'ok' });
|
||||
|
||||
const wrapper = createWrapper();
|
||||
queryClient.setQueryData(conversationKeys.lists(), fakeConversations);
|
||||
|
||||
const { result } = renderHook(() => useDeleteConversation(), { wrapper });
|
||||
|
||||
await result.current.mutateAsync('c1');
|
||||
|
||||
await waitFor(() => {
|
||||
expect(result.current.isSuccess).toBe(true);
|
||||
});
|
||||
|
||||
const list = queryClient.getQueryData(conversationKeys.lists()) as Array<{
|
||||
id: string;
|
||||
}>;
|
||||
expect(list).toHaveLength(0);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user