Tests refactor
This commit is contained in:
parent
245520fb50
commit
99134d8556
165 changed files with 911 additions and 531 deletions
107
packages/web/tests/lib/useShoppingListSync.test.ts
Normal file
107
packages/web/tests/lib/useShoppingListSync.test.ts
Normal file
|
|
@ -0,0 +1,107 @@
|
|||
import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
|
||||
import { renderHook, act } from '@testing-library/react';
|
||||
import { useShoppingListSync } from '../../src/lib/useShoppingListSync';
|
||||
|
||||
vi.mock('@/services/shopping-lists', () => ({
|
||||
getShoppingListSyncSocketUrl: vi.fn(() => 'ws://localhost/sync'),
|
||||
}));
|
||||
|
||||
class MockWebSocket {
|
||||
static OPEN = 1;
|
||||
static CONNECTING = 0;
|
||||
url: string;
|
||||
readyState = 1; // OPEN
|
||||
onopen: any = null;
|
||||
onmessage: any = null;
|
||||
onerror: any = null;
|
||||
onclose: any = null;
|
||||
send = vi.fn();
|
||||
close = vi.fn();
|
||||
|
||||
constructor(url: string) {
|
||||
this.url = url;
|
||||
}
|
||||
}
|
||||
|
||||
describe('useShoppingListSync', () => {
|
||||
let originalWebSocket: any;
|
||||
let createdSockets: MockWebSocket[] = [];
|
||||
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks();
|
||||
createdSockets = [];
|
||||
originalWebSocket = global.WebSocket;
|
||||
const MockClass = class extends MockWebSocket {
|
||||
constructor(url: string) {
|
||||
super(url);
|
||||
createdSockets.push(this);
|
||||
}
|
||||
};
|
||||
(MockClass as any).OPEN = 1;
|
||||
(MockClass as any).CONNECTING = 0;
|
||||
global.WebSocket = MockClass as any;
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
global.WebSocket = originalWebSocket;
|
||||
});
|
||||
|
||||
it('initializes and connects to the correct socket URL', () => {
|
||||
const onSync = vi.fn();
|
||||
renderHook(() => useShoppingListSync('hh1', 'list1', onSync));
|
||||
|
||||
expect(createdSockets).toHaveLength(1);
|
||||
expect(createdSockets[0].url).toBe('ws://localhost/sync');
|
||||
});
|
||||
|
||||
it('handles incoming item_updated messages correctly', () => {
|
||||
const onSync = vi.fn();
|
||||
renderHook(() => useShoppingListSync('hh1', 'list1', onSync));
|
||||
|
||||
const ws = createdSockets[0];
|
||||
act(() => { if (ws.onopen) ws.onopen(); });
|
||||
|
||||
act(() => {
|
||||
if (ws.onmessage) ws.onmessage({ data: JSON.stringify({ type: 'ITEM_UPDATED', itemId: 'item1', updates: { checked: true } }) });
|
||||
});
|
||||
|
||||
expect(onSync).toHaveBeenCalledWith({ type: 'ITEM_UPDATED', itemId: 'item1', updates: { checked: true } });
|
||||
});
|
||||
|
||||
it('broadcasts toggle item messages when connected', () => {
|
||||
const onSync = vi.fn();
|
||||
const { result } = renderHook(() => useShoppingListSync('hh1', 'list1', onSync));
|
||||
|
||||
const ws = createdSockets[0];
|
||||
act(() => { if (ws.onopen) ws.onopen(); });
|
||||
|
||||
act(() => {
|
||||
result.current.toggleItemCheck('item1', true);
|
||||
});
|
||||
|
||||
expect(ws.send).toHaveBeenCalledWith(JSON.stringify({
|
||||
type: 'TOGGLE_ITEM',
|
||||
itemId: 'item1',
|
||||
checked: true,
|
||||
}));
|
||||
});
|
||||
|
||||
it('handles disconnect and reconnect backoff', () => {
|
||||
vi.useFakeTimers();
|
||||
const onSync = vi.fn();
|
||||
const { result } = renderHook(() => useShoppingListSync('hh1', 'list1', onSync));
|
||||
|
||||
let ws = createdSockets[0];
|
||||
act(() => { if (ws.onopen) ws.onopen(); });
|
||||
expect(result.current.isConnected).toBe(true);
|
||||
|
||||
act(() => { if (ws.onclose) ws.onclose({ reason: 'test' }); });
|
||||
expect(result.current.isConnected).toBe(false);
|
||||
|
||||
// After 1000ms it should attempt reconnect
|
||||
act(() => { vi.advanceTimersByTime(1000); });
|
||||
expect(createdSockets).toHaveLength(2);
|
||||
|
||||
vi.useRealTimers();
|
||||
});
|
||||
});
|
||||
Loading…
Add table
Add a link
Reference in a new issue