From 2c3f31b2ba738c2f997bff0ddf229a1dc3cdde83 Mon Sep 17 00:00:00 2001
From: Aaron Knudtson <87577305+knudtty@users.noreply.github.com>
Date: Wed, 17 Dec 2025 09:59:26 -0500
Subject: [PATCH] test: add test to ensure querykey matches for
searchtotalcount & DBSearchPage histogram chart (#1491)
Closes HDX-3054
---
CLAUDE.md | 2 +-
.../__tests__/DBSearchPageQueryKey.test.tsx | 178 ++++++++++++++++++
2 files changed, 179 insertions(+), 1 deletion(-)
create mode 100644 packages/app/src/__tests__/DBSearchPageQueryKey.test.tsx
diff --git a/CLAUDE.md b/CLAUDE.md
index 45ec90f4..ab1e7773 100644
--- a/CLAUDE.md
+++ b/CLAUDE.md
@@ -42,7 +42,7 @@ The project uses **Yarn 4.5.1** workspaces. Docker Compose manages ClickHouse, M
2. **Type safety**: Use TypeScript strictly; Zod schemas for validation
3. **Existing patterns**: Follow established patterns in the codebase - explore similar files before implementing
4. **Component size**: Keep files under 300 lines; break down large components
-5. **Testing**: Tests live in `__tests__/` directories; use Jest for unit/integration tests
+5. **Testing**: Tests live in `__tests__/` directories; use Jest for unit/integration tests, `cd packages/app && yarn ci:unit` for unit tests, and `cd packages/app && yarn ci:int` for integration tests
## Important Context
diff --git a/packages/app/src/__tests__/DBSearchPageQueryKey.test.tsx b/packages/app/src/__tests__/DBSearchPageQueryKey.test.tsx
new file mode 100644
index 00000000..02515839
--- /dev/null
+++ b/packages/app/src/__tests__/DBSearchPageQueryKey.test.tsx
@@ -0,0 +1,178 @@
+import React from 'react';
+import objectHash from 'object-hash';
+import {
+ ChartConfigWithDateRange,
+ DisplayType,
+} from '@hyperdx/common-utils/dist/types';
+import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
+
+import { DBTimeChart } from '@/components/DBTimeChart';
+import SearchTotalCountChart from '@/components/SearchTotalCountChart';
+
+// Mock the API and hooks
+jest.mock('@/api', () => ({
+ __esModule: true,
+ default: {
+ useMe: () => ({
+ data: { team: { parallelizeWhenPossible: false } },
+ isLoading: false,
+ }),
+ },
+}));
+
+jest.mock('@/hooks/useChartConfig', () => ({
+ useQueriedChartConfig: jest.fn(() => ({
+ data: { data: [], isComplete: true },
+ isLoading: false,
+ isError: false,
+ isPlaceholderData: false,
+ isSuccess: true,
+ })),
+}));
+
+jest.mock('@/source', () => ({
+ useSource: () => ({ data: null, isLoading: false }),
+}));
+
+jest.mock('@/ChartUtils', () => ({
+ useTimeChartSettings: () => ({
+ displayType: DisplayType.StackedBar,
+ dateRange: [new Date('2024-01-01'), new Date('2024-01-02')],
+ granularity: 'auto',
+ fillNulls: true,
+ }),
+ formatResponseForTimeChart: () => ({
+ graphResults: [],
+ timestampColumn: undefined,
+ lineData: [],
+ groupColumns: [],
+ valueColumns: [],
+ isSingleValueColumn: true,
+ }),
+ getPreviousDateRange: (dateRange: [Date, Date]) => [
+ new Date('2023-12-31'),
+ new Date('2024-01-01'),
+ ],
+ getPreviousPeriodOffsetSeconds: () => 86400,
+}));
+
+describe('DBSearchPage QueryKey Consistency', () => {
+ let queryClient: QueryClient;
+ let mockUseQueriedChartConfig: jest.Mock;
+
+ beforeEach(async () => {
+ queryClient = new QueryClient({
+ defaultOptions: {
+ queries: {
+ retry: false,
+ },
+ },
+ });
+
+ mockUseQueriedChartConfig = (await import('@/hooks/useChartConfig'))
+ .useQueriedChartConfig as any;
+ mockUseQueriedChartConfig.mockClear();
+ });
+
+ it('should use matching queryKeys between SearchTotalCountChart and DBTimeChart', () => {
+ const config: ChartConfigWithDateRange = {
+ select: 'count()',
+ from: { databaseName: 'test', tableName: 'logs' },
+ where: '',
+ timestampValueExpression: 'timestamp',
+ connection: 'test-connection',
+ displayType: DisplayType.StackedBar,
+ dateRange: [new Date('2024-01-01'), new Date('2024-01-02')],
+ };
+
+ const queryKeyPrefix = 'search';
+
+ // Render SearchTotalCountChart
+ renderWithMantine(
+ ,
+ );
+
+ // Render DBTimeChart
+ renderWithMantine(
+ ,
+ );
+
+ // Get all calls to useQueriedChartConfig
+ const calls = mockUseQueriedChartConfig.mock.calls;
+
+ // Should have at least 2 calls (one for each component)
+ expect(calls.length).toBeGreaterThanOrEqual(2);
+
+ // Extract queryKey from each call
+ const searchTotalCountQueryKey = calls[0][1]?.queryKey;
+ const dbTimeChartQueryKey = calls[1][1]?.queryKey;
+
+ // Both should exist
+ expect(searchTotalCountQueryKey).toBeDefined();
+ expect(dbTimeChartQueryKey).toBeDefined();
+
+ // The key structure should be identical for both components
+ // This ensures React Query can properly dedupe the queries
+ expect(searchTotalCountQueryKey).toEqual(dbTimeChartQueryKey);
+
+ // Additional object hash check for deep equality verification
+ const searchQueryKeyHash = objectHash(searchTotalCountQueryKey);
+ const chartQueryKeyHash = objectHash(dbTimeChartQueryKey);
+ expect(searchQueryKeyHash).toBe(chartQueryKeyHash);
+ });
+
+ it('should use consistent queryKeys when disableQueryChunking is set', () => {
+ const config: ChartConfigWithDateRange = {
+ select: 'count()',
+ from: { databaseName: 'test', tableName: 'logs' },
+ where: '',
+ timestampValueExpression: 'timestamp',
+ connection: 'test-connection',
+ displayType: DisplayType.StackedBar,
+ dateRange: [new Date('2024-01-01'), new Date('2024-01-02')],
+ };
+
+ const queryKeyPrefix = 'search';
+
+ // Render both components with disableQueryChunking
+ renderWithMantine(
+ ,
+ );
+
+ renderWithMantine(
+ ,
+ );
+
+ const calls = mockUseQueriedChartConfig.mock.calls;
+ const searchQueryKey = calls[0][1]?.queryKey;
+ const chartQueryKey = calls[1][1]?.queryKey;
+
+ // Verify the options include disableQueryChunking
+ expect(searchQueryKey[3]).toHaveProperty('disableQueryChunking', true);
+ expect(chartQueryKey[3]).toHaveProperty('disableQueryChunking', true);
+
+ // Keys should still match
+ expect(searchQueryKey).toEqual(chartQueryKey);
+
+ // Additional object hash check for deep equality verification
+ const searchQueryKeyHash = objectHash(searchQueryKey);
+ const chartQueryKeyHash = objectHash(chartQueryKey);
+ expect(searchQueryKeyHash).toBe(chartQueryKeyHash);
+ });
+});