-
Notifications
You must be signed in to change notification settings - Fork 9
Expand file tree
/
Copy pathuseReconcileDeletedMonitors.test.tsx
More file actions
114 lines (95 loc) · 4.17 KB
/
Copy pathuseReconcileDeletedMonitors.test.tsx
File metadata and controls
114 lines (95 loc) · 4.17 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
import { describe, it, expect, beforeEach, vi } from 'vitest';
import { renderHook, waitFor } from '@testing-library/react';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import type { ReactNode } from 'react';
import { useReconcileDeletedMonitors } from '../useReconcileDeletedMonitors';
import { useSettingsStore, DEFAULT_MONTAGE_GROUP_LAYOUT } from '../../stores/settings';
import { useDashboardStore } from '../../stores/dashboard';
import { getMonitors } from '../../api/monitors';
vi.mock('../../api/monitors', () => ({ getMonitors: vi.fn() }));
vi.mock('../useCurrentProfile', () => ({
useCurrentProfile: () => ({ currentProfile: { id: 'p1' }, settings: {} }),
}));
vi.mock('../../stores/auth', () => ({
useAuthStore: (selector: (s: { isAuthenticated: boolean }) => unknown) =>
selector({ isAuthenticated: true }),
}));
const mockGetMonitors = vi.mocked(getMonitors);
function monitorList(ids: string[]) {
return { monitors: ids.map((Id) => ({ Monitor: { Id }, Monitor_Status: undefined })) } as never;
}
function wrapper({ children }: { children: ReactNode }) {
const client = new QueryClient({ defaultOptions: { queries: { retry: false } } });
return <QueryClientProvider client={client}>{children}</QueryClientProvider>;
}
function seedProfile() {
useSettingsStore.setState({
profileSettings: {
p1: {
excludedMonitorIds: ['1', '99'],
montageByGroup: {
all: { ...DEFAULT_MONTAGE_GROUP_LAYOUT, hiddenMonitorIds: ['99'] },
},
},
} as never,
});
useDashboardStore.setState({
widgets: {
p1: [
{
id: 'w1',
type: 'monitor',
settings: { monitorIds: ['1', '99'] },
layout: { i: 'w1', x: 0, y: 0, w: 4, h: 4 },
},
],
},
});
}
function storedState() {
return {
excluded: useSettingsStore.getState().getProfileSettings('p1').excludedMonitorIds,
montageHidden:
useSettingsStore.getState().getProfileSettings('p1').montageByGroup?.all?.hiddenMonitorIds,
widgetIds: useDashboardStore.getState().widgets.p1?.[0].settings.monitorIds,
};
}
describe('useReconcileDeletedMonitors', () => {
beforeEach(() => {
mockGetMonitors.mockReset();
seedProfile();
});
it('drops ids for monitors ZoneMinder no longer has, everywhere they are stored', async () => {
mockGetMonitors.mockResolvedValue(monitorList(['1']));
renderHook(() => useReconcileDeletedMonitors(), { wrapper });
await waitFor(() => expect(storedState().excluded).toEqual(['1']));
expect(storedState().montageHidden).toEqual([]);
expect(storedState().widgetIds).toEqual(['1']);
});
it('keeps a hidden monitor that still exists, which the ordinary monitor list omits', async () => {
// '99' is hidden, so getMonitors() without includeExcluded would not return
// it. Reconciling against that list would delete the user's own hidden
// entry, so the hook must ask for the list that includes it.
mockGetMonitors.mockResolvedValue(monitorList(['1', '99']));
renderHook(() => useReconcileDeletedMonitors(), { wrapper });
await waitFor(() => expect(mockGetMonitors).toHaveBeenCalled());
expect(mockGetMonitors).toHaveBeenCalledWith({ includeExcluded: true });
expect(storedState().excluded).toEqual(['1', '99']);
expect(storedState().widgetIds).toEqual(['1', '99']);
});
it('changes nothing when the fetch fails: an error is not proof of deletion', async () => {
mockGetMonitors.mockRejectedValue(new Error('offline'));
renderHook(() => useReconcileDeletedMonitors(), { wrapper });
await waitFor(() => expect(mockGetMonitors).toHaveBeenCalled());
expect(storedState().excluded).toEqual(['1', '99']);
expect(storedState().widgetIds).toEqual(['1', '99']);
});
it('changes nothing when the server returns no monitors at all', async () => {
mockGetMonitors.mockResolvedValue(monitorList([]));
renderHook(() => useReconcileDeletedMonitors(), { wrapper });
await waitFor(() => expect(mockGetMonitors).toHaveBeenCalled());
expect(storedState().excluded).toEqual(['1', '99']);
expect(storedState().montageHidden).toEqual(['99']);
expect(storedState().widgetIds).toEqual(['1', '99']);
});
});