Skip to content

Commit 094b997

Browse files
committed
test: add tests for useGetKeyValues
1 parent b1ba610 commit 094b997

File tree

1 file changed

+220
-1
lines changed

1 file changed

+220
-1
lines changed

packages/app/src/hooks/__tests__/useMetadata.test.tsx

Lines changed: 220 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,223 @@
1-
import { deduplicate2dArray } from '../useMetadata';
1+
import React from 'react';
2+
import { deduplicate2dArray, useGetKeyValues } from '../useMetadata';
3+
import { renderHook, waitFor } from '@testing-library/react';
4+
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
5+
import { ChartConfigWithDateRange } from '@hyperdx/common-utils/dist/types';
6+
import { Metadata, MetadataCache } from '@hyperdx/common-utils/dist/metadata';
7+
import { ClickhouseClient } from '@hyperdx/common-utils/dist/clickhouse';
8+
import * as metadataModule from '@hyperdx/app/src/metadata';
9+
10+
// Create a mock ChartConfig based on the Zod schema
11+
const createMockChartConfig = (
12+
overrides: Partial<ChartConfigWithDateRange> = {},
13+
): ChartConfigWithDateRange =>
14+
({
15+
timestampValueExpression: '',
16+
connection: 'foo',
17+
from: {
18+
databaseName: 'telemetry',
19+
tableName: 'traces',
20+
},
21+
...overrides,
22+
}) as ChartConfigWithDateRange;
23+
24+
describe('useGetKeyValues', () => {
25+
let queryClient: QueryClient;
26+
let wrapper: React.ComponentType<{ children: any }>;
27+
let mockMetadata: Metadata;
28+
29+
beforeEach(() => {
30+
// Reset mocks
31+
jest.clearAllMocks();
32+
33+
// initialize metadata object
34+
mockMetadata = new Metadata({} as ClickhouseClient, {} as MetadataCache);
35+
jest.spyOn(metadataModule, 'getMetadata').mockReturnValue(mockMetadata);
36+
37+
// Create a new QueryClient for each test
38+
queryClient = new QueryClient({
39+
defaultOptions: {
40+
queries: {
41+
retry: false,
42+
},
43+
},
44+
});
45+
46+
// Create a wrapper component with QueryClientProvider
47+
wrapper = ({ children }) => (
48+
<QueryClientProvider client={queryClient}>{children}</QueryClientProvider>
49+
);
50+
});
51+
52+
// Test case: Basic functionality with single chart config
53+
it('should fetch key values for a single chart config', async () => {
54+
// Arrange
55+
const mockChartConfig = createMockChartConfig();
56+
const mockKeys = ["ResourceAttributes['service.name']"];
57+
58+
const mockKeyValues = [
59+
{
60+
key: "ResourceAttributes['service.name']",
61+
value: ['frontend', 'backend', 'database'],
62+
},
63+
];
64+
65+
jest.spyOn(mockMetadata, 'getKeyValues').mockResolvedValue(mockKeyValues);
66+
67+
// Act
68+
const { result } = renderHook(
69+
() =>
70+
useGetKeyValues({
71+
chartConfigs: mockChartConfig,
72+
keys: mockKeys,
73+
}),
74+
{ wrapper },
75+
);
76+
77+
// Assert
78+
await waitFor(() => expect(result.current.isSuccess).toBe(true));
79+
80+
//console.log(result.current.data);
81+
expect(result.current.data).toEqual(mockKeyValues);
82+
});
83+
84+
// Test case: Multiple chart configs with different configurations
85+
it('should fetch key values for multiple chart configs', async () => {
86+
// Arrange
87+
const mockChartConfigs = [
88+
createMockChartConfig({
89+
from: { databaseName: 'telemetry', tableName: 'traces' },
90+
groupBy: "ResourceAttributes['service.name']",
91+
}),
92+
createMockChartConfig({
93+
from: { databaseName: 'logs', tableName: 'application_logs' },
94+
orderBy: '"timestamp" DESC',
95+
}),
96+
];
97+
const mockKeys = [
98+
'ResourceAttributes.service.name',
99+
'ResourceAttributes.environment',
100+
];
101+
102+
jest
103+
.spyOn(mockMetadata, 'getKeyValues')
104+
.mockResolvedValueOnce([
105+
{
106+
key: "ResourceAttributes['service.name']",
107+
value: ['frontend', 'backend'],
108+
},
109+
])
110+
.mockResolvedValueOnce([
111+
{
112+
key: "ResourceAttributes['environment']",
113+
value: ['production', 'staging'],
114+
},
115+
]);
116+
117+
// Act
118+
const { result } = renderHook(
119+
() =>
120+
useGetKeyValues({
121+
chartConfigs: mockChartConfigs,
122+
keys: mockKeys,
123+
}),
124+
{ wrapper },
125+
);
126+
127+
// Assert
128+
await waitFor(() => expect(result.current.isSuccess).toBe(true));
129+
130+
expect(result.current.data).toEqual([
131+
{
132+
key: "ResourceAttributes['service.name']",
133+
value: ['frontend', 'backend'],
134+
},
135+
{
136+
key: "ResourceAttributes['environment']",
137+
value: ['production', 'staging'],
138+
},
139+
]);
140+
expect(jest.spyOn(mockMetadata, 'getKeyValues')).toHaveBeenCalledTimes(2);
141+
});
142+
143+
// Test case: Handling empty keys
144+
it('should not fetch when keys array is empty', () => {
145+
// Arrange
146+
const mockChartConfig = createMockChartConfig();
147+
148+
// Act
149+
const { result } = renderHook(
150+
() =>
151+
useGetKeyValues({
152+
chartConfigs: mockChartConfig,
153+
keys: [],
154+
}),
155+
{ wrapper },
156+
);
157+
158+
// Assert
159+
expect(result.current.isFetched).toBe(false);
160+
expect(jest.spyOn(mockMetadata, 'getKeyValues')).not.toHaveBeenCalled();
161+
});
162+
163+
// Test case: Custom limit and disableRowLimit
164+
it('should pass custom limit and disableRowLimit', async () => {
165+
// Arrange
166+
const mockChartConfig = createMockChartConfig();
167+
const mockKeys = ['ResourceAttributes.service.name'];
168+
169+
const mockKeyValues = [
170+
{
171+
key: "ResourceAttributes['service.name']",
172+
value: ['frontend', 'backend'],
173+
},
174+
];
175+
176+
jest.spyOn(mockMetadata, 'getKeyValues').mockResolvedValue(mockKeyValues);
177+
178+
// Act
179+
const { result } = renderHook(
180+
() =>
181+
useGetKeyValues({
182+
chartConfigs: mockChartConfig,
183+
keys: mockKeys,
184+
limit: 50,
185+
disableRowLimit: true,
186+
}),
187+
{ wrapper },
188+
);
189+
190+
// Assert
191+
await waitFor(() => expect(result.current.isSuccess).toBe(true));
192+
});
193+
194+
// Test case: Error handling
195+
it('should handle errors when fetching key values', async () => {
196+
// Arrange
197+
const mockChartConfig = createMockChartConfig();
198+
const mockKeys = ['ResourceAttributes.service.name'];
199+
200+
jest
201+
.spyOn(mockMetadata, 'getKeyValues')
202+
.mockRejectedValue(new Error('Fetch failed'));
203+
204+
// Act
205+
const { result } = renderHook(
206+
() =>
207+
useGetKeyValues({
208+
chartConfigs: mockChartConfig,
209+
keys: mockKeys,
210+
}),
211+
{ wrapper },
212+
);
213+
214+
// Assert
215+
await waitFor(() => expect(result.current.isError).toBe(true));
216+
217+
expect(result.current.error).toEqual(expect.any(Error));
218+
expect(result.current.error!.message).toBe('Fetch failed');
219+
});
220+
});
2221

3222
describe('deduplicate2dArray', () => {
4223
// Test basic deduplication

0 commit comments

Comments
 (0)