Skip to content

Commit ffb1dd0

Browse files
committed
Fix table strings and add unit tests
Signed-off-by: Chenyang Ji <[email protected]>
1 parent 47383e5 commit ffb1dd0

File tree

6 files changed

+326
-18
lines changed

6 files changed

+326
-18
lines changed

Diff for: common/constants.ts

+3-3
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,6 @@ export const LATENCY = 'Latency';
88
export const CPU_TIME = 'CPU Time';
99
export const MEMORY_USAGE = 'Memory Usage';
1010
export const INDICES = 'Indices';
11-
export const SEARCH_TYPE = 'Search type';
12-
export const NODE_ID = 'Coordinator node ID';
13-
export const TOTAL_SHARDS = 'Total shards';
11+
export const SEARCH_TYPE = 'Search Type';
12+
export const NODE_ID = 'Coordinator Node ID';
13+
export const TOTAL_SHARDS = 'Total Shards';

Diff for: public/components/__snapshots__/app.test.tsx.snap

+12-12
Original file line numberDiff line numberDiff line change
@@ -172,10 +172,10 @@ exports[`<QueryInsightsDashboardsApp /> spec renders the component 1`] = `
172172
>
173173
<span
174174
class="euiFilterButton__textShift"
175-
data-text="Search type"
176-
title="Search type"
175+
data-text="Search Type"
176+
title="Search Type"
177177
>
178-
Search type
178+
Search Type
179179
</span>
180180
</span>
181181
</span>
@@ -215,10 +215,10 @@ exports[`<QueryInsightsDashboardsApp /> spec renders the component 1`] = `
215215
>
216216
<span
217217
class="euiFilterButton__textShift"
218-
data-text="Coordinator node ID"
219-
title="Coordinator node ID"
218+
data-text="Coordinator Node ID"
219+
title="Coordinator Node ID"
220220
>
221-
Coordinator node ID
221+
Coordinator Node ID
222222
</span>
223223
</span>
224224
</span>
@@ -566,9 +566,9 @@ exports[`<QueryInsightsDashboardsApp /> spec renders the component 1`] = `
566566
>
567567
<span
568568
class="euiTableCellContent__text"
569-
title="Search type"
569+
title="Search Type"
570570
>
571-
Search type
571+
Search Type
572572
</span>
573573
</span>
574574
</button>
@@ -591,9 +591,9 @@ exports[`<QueryInsightsDashboardsApp /> spec renders the component 1`] = `
591591
>
592592
<span
593593
class="euiTableCellContent__text"
594-
title="Coordinator node ID"
594+
title="Coordinator Node ID"
595595
>
596-
Coordinator node ID
596+
Coordinator Node ID
597597
</span>
598598
</span>
599599
</button>
@@ -616,9 +616,9 @@ exports[`<QueryInsightsDashboardsApp /> spec renders the component 1`] = `
616616
>
617617
<span
618618
class="euiTableCellContent__text"
619-
title="Total shards"
619+
title="Total Shards"
620620
>
621-
Total shards
621+
Total Shards
622622
</span>
623623
</span>
624624
</button>

Diff for: public/pages/Configuration/Configuration.test.tsx

+128
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
/*
2+
* Copyright OpenSearch Contributors
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
import React from 'react';
7+
import { render, screen, fireEvent, waitFor } from '@testing-library/react';
8+
import '@testing-library/jest-dom/extend-expect';
9+
import { MemoryRouter } from 'react-router-dom';
10+
import Configuration from './Configuration';
11+
12+
const mockConfigInfo = jest.fn();
13+
const mockCoreStart = {
14+
chrome: {
15+
setBreadcrumbs: jest.fn(),
16+
},
17+
};
18+
19+
const defaultLatencySettings = {
20+
isEnabled: true,
21+
currTopN: '5',
22+
currWindowSize: '10',
23+
currTimeUnit: 'MINUTES',
24+
};
25+
const defaultCpuSettings = {
26+
isEnabled: false,
27+
currTopN: '10',
28+
currWindowSize: '1',
29+
currTimeUnit: 'HOURS',
30+
};
31+
const defaultMemorySettings = {
32+
isEnabled: false,
33+
currTopN: '15',
34+
currWindowSize: '2',
35+
currTimeUnit: 'HOURS',
36+
};
37+
38+
const renderConfiguration = (overrides = {}) => {
39+
render(
40+
<MemoryRouter>
41+
<Configuration
42+
latencySettings={{ ...defaultLatencySettings, ...overrides }}
43+
cpuSettings={defaultCpuSettings}
44+
memorySettings={defaultMemorySettings}
45+
configInfo={mockConfigInfo}
46+
// @ts-ignore
47+
core={mockCoreStart}
48+
/>
49+
</MemoryRouter>
50+
);
51+
};
52+
53+
const getWindowSizeConfigurations = () => screen.getAllByRole('combobox');
54+
const getTopNSizeConfiguration = () => screen.getByRole('spinbutton');
55+
const getEnableToggle = () => screen.getByRole('switch');
56+
57+
describe('Configuration Component', () => {
58+
beforeEach(() => {
59+
jest.clearAllMocks();
60+
});
61+
62+
it('renders with default settings', () => {
63+
renderConfiguration();
64+
// main header
65+
expect(
66+
screen.getByRole('heading', { name: /Top n queries monitoring configuration settings/i })
67+
).toBeInTheDocument();
68+
// section headers
69+
expect(screen.getByRole('heading', { name: /Metric Type/i })).toBeInTheDocument();
70+
expect(screen.getByRole('heading', { name: /Enabled/i })).toBeInTheDocument();
71+
expect(screen.getByRole('heading', { name: /Value of N/i })).toBeInTheDocument();
72+
expect(screen.getByRole('heading', { name: /Window size/i })).toBeInTheDocument();
73+
// Check values for window size configurations
74+
const selectBoxes = getWindowSizeConfigurations();
75+
expect(selectBoxes[0]).toHaveValue('latency');
76+
expect(selectBoxes[1]).toHaveValue('10');
77+
expect(selectBoxes[2]).toHaveValue('MINUTES');
78+
// Check the value for top n size configurations
79+
expect(getTopNSizeConfiguration()).toHaveValue(5);
80+
// Check the value for enabled switch
81+
const enableBox = getEnableToggle();
82+
expect(enableBox).toBeInTheDocument();
83+
expect(enableBox).toBeChecked();
84+
});
85+
86+
it('updates state when toggling metrics and enables Save button when changes are made', () => {
87+
renderConfiguration();
88+
// before toggling the metric
89+
expect(getWindowSizeConfigurations()[0]).toHaveValue('latency');
90+
expect(getEnableToggle()).toBeChecked();
91+
// toggle the metric
92+
fireEvent.change(getWindowSizeConfigurations()[0], { target: { value: 'cpu' } });
93+
// after toggling the metric
94+
expect(getWindowSizeConfigurations()[0]).toHaveValue('cpu');
95+
// the enabled box should be disabled by default based on our configuration
96+
const cpuEnableBox = getEnableToggle();
97+
expect(cpuEnableBox).toBeInTheDocument();
98+
expect(cpuEnableBox).not.toBeChecked();
99+
100+
fireEvent.click(getEnableToggle());
101+
expect(getEnableToggle()).toBeChecked();
102+
expect(screen.getByText('Save')).toBeEnabled();
103+
});
104+
105+
it('validates topNSize and windowSize inputs and disables Save button for invalid input', () => {
106+
renderConfiguration();
107+
fireEvent.change(getTopNSizeConfiguration(), { target: { value: '101' } });
108+
expect(screen.queryByText('Save')).not.toBeInTheDocument();
109+
fireEvent.change(getWindowSizeConfigurations()[1], { target: { value: '999' } });
110+
expect(screen.queryByText('Save')).not.toBeInTheDocument();
111+
});
112+
113+
it('calls configInfo and navigates on Save button click', async () => {
114+
renderConfiguration();
115+
fireEvent.change(getTopNSizeConfiguration(), { target: { value: '7' } });
116+
fireEvent.click(screen.getByText('Save'));
117+
await waitFor(() => {
118+
expect(mockConfigInfo).toHaveBeenCalledWith(false, true, 'latency', '7', '10', 'MINUTES');
119+
});
120+
});
121+
122+
it('resets state on Cancel button click', async () => {
123+
renderConfiguration();
124+
fireEvent.change(getTopNSizeConfiguration(), { target: { value: '7' } });
125+
fireEvent.click(screen.getByText('Cancel'));
126+
expect(getTopNSizeConfiguration()).toHaveValue(5); // Resets to initial value
127+
});
128+
});

Diff for: public/pages/QueryInsights/QueryInsights.test.tsx

+82
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
/*
2+
* Copyright OpenSearch Contributors
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
import React from 'react';
7+
import { render, screen, fireEvent } from '@testing-library/react';
8+
import '@testing-library/jest-dom/extend-expect';
9+
import QueryInsights from './QueryInsights';
10+
import { MemoryRouter } from 'react-router-dom';
11+
import { MockQueries } from '../../../test/testUtils';
12+
13+
// Mock functions and data
14+
const mockOnTimeChange = jest.fn();
15+
const mockCore = {
16+
chrome: {
17+
setBreadcrumbs: jest.fn(),
18+
},
19+
};
20+
21+
// TODO: change to use MockQueries once https://github.com/opensearch-project/query-insights-dashboards/pull/21/files is merged
22+
const sampleQueries = MockQueries();
23+
24+
const renderQueryInsights = () => {
25+
render(
26+
<MemoryRouter>
27+
<QueryInsights
28+
queries={sampleQueries}
29+
loading={false}
30+
onTimeChange={mockOnTimeChange}
31+
recentlyUsedRanges={[]}
32+
currStart="now-15m"
33+
currEnd="now"
34+
// @ts-ignore
35+
core={mockCore}
36+
/>
37+
</MemoryRouter>
38+
);
39+
};
40+
41+
describe('QueryInsights Component', () => {
42+
beforeEach(() => {
43+
jest.clearAllMocks();
44+
});
45+
46+
it('renders the table with the correct columns and data', () => {
47+
renderQueryInsights();
48+
49+
// Check that the table and columns render correctly
50+
expect(document.querySelector('span[title="Timestamp"]')).toBeInTheDocument();
51+
expect(document.querySelector('span[title="Latency"]')).toBeInTheDocument();
52+
expect(document.querySelector('span[title="CPU Time"]')).toBeInTheDocument();
53+
expect(document.querySelector('span[title="Memory Usage"]')).toBeInTheDocument();
54+
expect(document.querySelector('span[title="Indices"]')).toBeInTheDocument();
55+
expect(document.querySelector('span[title="Search Type"]')).toBeInTheDocument();
56+
expect(document.querySelector('span[title="Coordinator Node ID"]')).toBeInTheDocument();
57+
expect(document.querySelector('span[title="Total Shards"]')).toBeInTheDocument();
58+
// TODO add tests for the values
59+
});
60+
61+
it('calls setBreadcrumbs on mount', () => {
62+
renderQueryInsights();
63+
expect(mockCore.chrome.setBreadcrumbs).toHaveBeenCalledWith([
64+
{
65+
text: 'Query insights',
66+
href: '/queryInsights',
67+
onClick: expect.any(Function),
68+
},
69+
]);
70+
});
71+
72+
it('triggers onTimeChange when the date picker changes', () => {
73+
renderQueryInsights();
74+
75+
// Find the date picker update button
76+
const updateButton = screen.getByRole('button', { name: /Refresh/i });
77+
fireEvent.click(updateButton);
78+
79+
// Verify the onTimeChange callback is triggered
80+
expect(mockOnTimeChange).toHaveBeenCalled();
81+
});
82+
});

Diff for: test/testUtils.ts

+99
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
/*
2+
* Copyright OpenSearch Contributors
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
import { SearchQueryRecord } from '../types/types';
7+
8+
export const MockQueries = (): SearchQueryRecord[] => {
9+
return [
10+
{
11+
timestamp: 1726178995210,
12+
task_resource_usages: [
13+
{
14+
action: 'indices:data/read/search[phase/query]',
15+
taskId: 18809,
16+
parentTaskId: 18808,
17+
nodeId: 'Q36D2z_NRGKim6EZZMgi6A',
18+
taskResourceUsage: {
19+
cpu_time_in_nanos: 3612000,
20+
memory_in_bytes: 123944,
21+
},
22+
},
23+
{
24+
action: 'indices:data/read/search',
25+
taskId: 18808,
26+
parentTaskId: -1,
27+
nodeId: 'Q36D2z_NRGKim6EZZMgi6A',
28+
taskResourceUsage: {
29+
cpu_time_in_nanos: 1898000,
30+
memory_in_bytes: 24176,
31+
},
32+
},
33+
],
34+
source: {
35+
query: {
36+
bool: {
37+
must: [
38+
{
39+
range: {
40+
timestamp: {
41+
from: 1726092595177,
42+
to: 1726178995177,
43+
include_lower: true,
44+
include_upper: true,
45+
boost: 1.0,
46+
},
47+
},
48+
},
49+
],
50+
must_not: [
51+
{
52+
match: {
53+
indices: {
54+
query: 'top_queries*',
55+
operator: 'OR',
56+
prefix_length: 0,
57+
max_expansions: 50,
58+
fuzzy_transpositions: true,
59+
lenient: false,
60+
zero_terms_query: 'NONE',
61+
auto_generate_synonyms_phrase_query: true,
62+
boost: 1.0,
63+
},
64+
},
65+
},
66+
],
67+
adjust_pure_negative: true,
68+
boost: 1.0,
69+
},
70+
},
71+
},
72+
query_hashcode: '80a17984b847133b8bf5e7d5dfbfa96c',
73+
phase_latency_map: {
74+
expand: 0,
75+
query: 5,
76+
fetch: 0,
77+
},
78+
labels: {
79+
'X-Opaque-Id': 'ae6c1170-5f98-47f4-b7fc-09ebcf574b81',
80+
},
81+
total_shards: 1,
82+
search_type: 'query_then_fetch',
83+
node_id: 'Q36D2z_NRGKim6EZZMgi6A',
84+
indices: ['top_queries-2024.09.12'],
85+
measurements: {
86+
latency: {
87+
number: 8,
88+
count: 1,
89+
aggregationType: 'NONE',
90+
},
91+
cpu: {
92+
number: 5510000,
93+
count: 1,
94+
aggregationType: 'NONE',
95+
},
96+
},
97+
},
98+
];
99+
};

0 commit comments

Comments
 (0)