Skip to content

Commit b6d0c82

Browse files
Copilothotlong
andcommitted
Add tests for useDiscovery hook
Co-authored-by: hotlong <50353452+hotlong@users.noreply.github.com>
1 parent 6f89ff1 commit b6d0c82

1 file changed

Lines changed: 149 additions & 0 deletions

File tree

Lines changed: 149 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,149 @@
1+
/**
2+
* Tests for useDiscovery hook
3+
*/
4+
5+
import React from 'react';
6+
import { describe, it, expect, vi } from 'vitest';
7+
import { renderHook, waitFor } from '@testing-library/react';
8+
import { useDiscovery } from '../useDiscovery';
9+
import { SchemaRendererContext } from '../../context/SchemaRendererContext';
10+
11+
function createWrapper(dataSource: any) {
12+
return ({ children }: { children: React.ReactNode }) =>
13+
React.createElement(
14+
SchemaRendererContext.Provider,
15+
{ value: { dataSource } },
16+
children,
17+
);
18+
}
19+
20+
describe('useDiscovery', () => {
21+
it('returns isLoading false and null discovery when no context is provided', async () => {
22+
const { result } = renderHook(() => useDiscovery());
23+
24+
await waitFor(() => {
25+
expect(result.current.isLoading).toBe(false);
26+
});
27+
28+
expect(result.current.discovery).toBeNull();
29+
expect(result.current.error).toBeNull();
30+
});
31+
32+
it('returns isLoading false and null discovery when dataSource has no getDiscovery method', async () => {
33+
const dataSource = { someOtherMethod: vi.fn() };
34+
35+
const { result } = renderHook(() => useDiscovery(), {
36+
wrapper: createWrapper(dataSource),
37+
});
38+
39+
await waitFor(() => {
40+
expect(result.current.isLoading).toBe(false);
41+
});
42+
43+
expect(result.current.discovery).toBeNull();
44+
expect(result.current.error).toBeNull();
45+
});
46+
47+
it('successfully fetches discovery data from dataSource.getDiscovery()', async () => {
48+
const discoveryData = {
49+
name: 'test-server',
50+
version: '1.0.0',
51+
services: {
52+
auth: { enabled: true, status: 'available' as const },
53+
data: { enabled: true, status: 'available' as const },
54+
},
55+
};
56+
57+
const dataSource = {
58+
getDiscovery: vi.fn().mockResolvedValue(discoveryData),
59+
};
60+
61+
const { result } = renderHook(() => useDiscovery(), {
62+
wrapper: createWrapper(dataSource),
63+
});
64+
65+
expect(result.current.isLoading).toBe(true);
66+
67+
await waitFor(() => {
68+
expect(result.current.isLoading).toBe(false);
69+
});
70+
71+
expect(result.current.discovery).toEqual(discoveryData);
72+
expect(result.current.error).toBeNull();
73+
expect(dataSource.getDiscovery).toHaveBeenCalled();
74+
});
75+
76+
it('handles errors from getDiscovery gracefully', async () => {
77+
const dataSource = {
78+
getDiscovery: vi.fn().mockRejectedValue(new Error('Network error')),
79+
};
80+
81+
const { result } = renderHook(() => useDiscovery(), {
82+
wrapper: createWrapper(dataSource),
83+
});
84+
85+
await waitFor(() => {
86+
expect(result.current.isLoading).toBe(false);
87+
});
88+
89+
expect(result.current.discovery).toBeNull();
90+
expect(result.current.error?.message).toBe('Network error');
91+
});
92+
93+
it('isAuthEnabled defaults to true when no discovery', async () => {
94+
const { result } = renderHook(() => useDiscovery());
95+
96+
await waitFor(() => {
97+
expect(result.current.isLoading).toBe(false);
98+
});
99+
100+
expect(result.current.isAuthEnabled).toBe(true);
101+
});
102+
103+
it('isAuthEnabled reflects the auth service enabled state', async () => {
104+
const discoveryData = {
105+
services: {
106+
auth: { enabled: false },
107+
},
108+
};
109+
110+
const dataSource = {
111+
getDiscovery: vi.fn().mockResolvedValue(discoveryData),
112+
};
113+
114+
const { result } = renderHook(() => useDiscovery(), {
115+
wrapper: createWrapper(dataSource),
116+
});
117+
118+
await waitFor(() => {
119+
expect(result.current.isLoading).toBe(false);
120+
});
121+
122+
expect(result.current.isAuthEnabled).toBe(false);
123+
});
124+
125+
it('cleans up on unmount (cancelled flag)', async () => {
126+
let resolveDiscovery: (value: any) => void;
127+
const discoveryPromise = new Promise((resolve) => {
128+
resolveDiscovery = resolve;
129+
});
130+
131+
const dataSource = {
132+
getDiscovery: vi.fn().mockReturnValue(discoveryPromise),
133+
};
134+
135+
const { result, unmount } = renderHook(() => useDiscovery(), {
136+
wrapper: createWrapper(dataSource),
137+
});
138+
139+
expect(result.current.isLoading).toBe(true);
140+
141+
unmount();
142+
143+
// Resolve after unmount — state should not update
144+
resolveDiscovery!({ name: 'late-response' });
145+
146+
// Discovery should remain null since the component was unmounted
147+
expect(result.current.discovery).toBeNull();
148+
});
149+
});

0 commit comments

Comments
 (0)