From ffb1dd0ca4771f2404b0ccf8f7b7582ebd68a04c Mon Sep 17 00:00:00 2001 From: Chenyang Ji Date: Wed, 6 Nov 2024 14:55:23 -0800 Subject: [PATCH 1/2] Fix table strings and add unit tests Signed-off-by: Chenyang Ji --- common/constants.ts | 6 +- .../__snapshots__/app.test.tsx.snap | 24 ++-- .../Configuration/Configuration.test.tsx | 128 ++++++++++++++++++ .../QueryInsights/QueryInsights.test.tsx | 82 +++++++++++ test/testUtils.ts | 99 ++++++++++++++ types/types.ts | 5 +- 6 files changed, 326 insertions(+), 18 deletions(-) create mode 100644 public/pages/Configuration/Configuration.test.tsx create mode 100644 public/pages/QueryInsights/QueryInsights.test.tsx create mode 100644 test/testUtils.ts diff --git a/common/constants.ts b/common/constants.ts index 2186516..c685599 100644 --- a/common/constants.ts +++ b/common/constants.ts @@ -8,6 +8,6 @@ export const LATENCY = 'Latency'; export const CPU_TIME = 'CPU Time'; export const MEMORY_USAGE = 'Memory Usage'; export const INDICES = 'Indices'; -export const SEARCH_TYPE = 'Search type'; -export const NODE_ID = 'Coordinator node ID'; -export const TOTAL_SHARDS = 'Total shards'; +export const SEARCH_TYPE = 'Search Type'; +export const NODE_ID = 'Coordinator Node ID'; +export const TOTAL_SHARDS = 'Total Shards'; diff --git a/public/components/__snapshots__/app.test.tsx.snap b/public/components/__snapshots__/app.test.tsx.snap index 3571697..36c6673 100644 --- a/public/components/__snapshots__/app.test.tsx.snap +++ b/public/components/__snapshots__/app.test.tsx.snap @@ -172,10 +172,10 @@ exports[` spec renders the component 1`] = ` > - Search type + Search Type @@ -215,10 +215,10 @@ exports[` spec renders the component 1`] = ` > - Coordinator node ID + Coordinator Node ID @@ -566,9 +566,9 @@ exports[` spec renders the component 1`] = ` > - Search type + Search Type @@ -591,9 +591,9 @@ exports[` spec renders the component 1`] = ` > - Coordinator node ID + Coordinator Node ID @@ -616,9 +616,9 @@ exports[` spec renders the component 1`] = ` > - Total shards + Total Shards diff --git a/public/pages/Configuration/Configuration.test.tsx b/public/pages/Configuration/Configuration.test.tsx new file mode 100644 index 0000000..1a3948b --- /dev/null +++ b/public/pages/Configuration/Configuration.test.tsx @@ -0,0 +1,128 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +import React from 'react'; +import { render, screen, fireEvent, waitFor } from '@testing-library/react'; +import '@testing-library/jest-dom/extend-expect'; +import { MemoryRouter } from 'react-router-dom'; +import Configuration from './Configuration'; + +const mockConfigInfo = jest.fn(); +const mockCoreStart = { + chrome: { + setBreadcrumbs: jest.fn(), + }, +}; + +const defaultLatencySettings = { + isEnabled: true, + currTopN: '5', + currWindowSize: '10', + currTimeUnit: 'MINUTES', +}; +const defaultCpuSettings = { + isEnabled: false, + currTopN: '10', + currWindowSize: '1', + currTimeUnit: 'HOURS', +}; +const defaultMemorySettings = { + isEnabled: false, + currTopN: '15', + currWindowSize: '2', + currTimeUnit: 'HOURS', +}; + +const renderConfiguration = (overrides = {}) => { + render( + + + + ); +}; + +const getWindowSizeConfigurations = () => screen.getAllByRole('combobox'); +const getTopNSizeConfiguration = () => screen.getByRole('spinbutton'); +const getEnableToggle = () => screen.getByRole('switch'); + +describe('Configuration Component', () => { + beforeEach(() => { + jest.clearAllMocks(); + }); + + it('renders with default settings', () => { + renderConfiguration(); + // main header + expect( + screen.getByRole('heading', { name: /Top n queries monitoring configuration settings/i }) + ).toBeInTheDocument(); + // section headers + expect(screen.getByRole('heading', { name: /Metric Type/i })).toBeInTheDocument(); + expect(screen.getByRole('heading', { name: /Enabled/i })).toBeInTheDocument(); + expect(screen.getByRole('heading', { name: /Value of N/i })).toBeInTheDocument(); + expect(screen.getByRole('heading', { name: /Window size/i })).toBeInTheDocument(); + // Check values for window size configurations + const selectBoxes = getWindowSizeConfigurations(); + expect(selectBoxes[0]).toHaveValue('latency'); + expect(selectBoxes[1]).toHaveValue('10'); + expect(selectBoxes[2]).toHaveValue('MINUTES'); + // Check the value for top n size configurations + expect(getTopNSizeConfiguration()).toHaveValue(5); + // Check the value for enabled switch + const enableBox = getEnableToggle(); + expect(enableBox).toBeInTheDocument(); + expect(enableBox).toBeChecked(); + }); + + it('updates state when toggling metrics and enables Save button when changes are made', () => { + renderConfiguration(); + // before toggling the metric + expect(getWindowSizeConfigurations()[0]).toHaveValue('latency'); + expect(getEnableToggle()).toBeChecked(); + // toggle the metric + fireEvent.change(getWindowSizeConfigurations()[0], { target: { value: 'cpu' } }); + // after toggling the metric + expect(getWindowSizeConfigurations()[0]).toHaveValue('cpu'); + // the enabled box should be disabled by default based on our configuration + const cpuEnableBox = getEnableToggle(); + expect(cpuEnableBox).toBeInTheDocument(); + expect(cpuEnableBox).not.toBeChecked(); + + fireEvent.click(getEnableToggle()); + expect(getEnableToggle()).toBeChecked(); + expect(screen.getByText('Save')).toBeEnabled(); + }); + + it('validates topNSize and windowSize inputs and disables Save button for invalid input', () => { + renderConfiguration(); + fireEvent.change(getTopNSizeConfiguration(), { target: { value: '101' } }); + expect(screen.queryByText('Save')).not.toBeInTheDocument(); + fireEvent.change(getWindowSizeConfigurations()[1], { target: { value: '999' } }); + expect(screen.queryByText('Save')).not.toBeInTheDocument(); + }); + + it('calls configInfo and navigates on Save button click', async () => { + renderConfiguration(); + fireEvent.change(getTopNSizeConfiguration(), { target: { value: '7' } }); + fireEvent.click(screen.getByText('Save')); + await waitFor(() => { + expect(mockConfigInfo).toHaveBeenCalledWith(false, true, 'latency', '7', '10', 'MINUTES'); + }); + }); + + it('resets state on Cancel button click', async () => { + renderConfiguration(); + fireEvent.change(getTopNSizeConfiguration(), { target: { value: '7' } }); + fireEvent.click(screen.getByText('Cancel')); + expect(getTopNSizeConfiguration()).toHaveValue(5); // Resets to initial value + }); +}); diff --git a/public/pages/QueryInsights/QueryInsights.test.tsx b/public/pages/QueryInsights/QueryInsights.test.tsx new file mode 100644 index 0000000..7812b12 --- /dev/null +++ b/public/pages/QueryInsights/QueryInsights.test.tsx @@ -0,0 +1,82 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +import React from 'react'; +import { render, screen, fireEvent } from '@testing-library/react'; +import '@testing-library/jest-dom/extend-expect'; +import QueryInsights from './QueryInsights'; +import { MemoryRouter } from 'react-router-dom'; +import { MockQueries } from '../../../test/testUtils'; + +// Mock functions and data +const mockOnTimeChange = jest.fn(); +const mockCore = { + chrome: { + setBreadcrumbs: jest.fn(), + }, +}; + +// TODO: change to use MockQueries once https://github.com/opensearch-project/query-insights-dashboards/pull/21/files is merged +const sampleQueries = MockQueries(); + +const renderQueryInsights = () => { + render( + + + + ); +}; + +describe('QueryInsights Component', () => { + beforeEach(() => { + jest.clearAllMocks(); + }); + + it('renders the table with the correct columns and data', () => { + renderQueryInsights(); + + // Check that the table and columns render correctly + expect(document.querySelector('span[title="Timestamp"]')).toBeInTheDocument(); + expect(document.querySelector('span[title="Latency"]')).toBeInTheDocument(); + expect(document.querySelector('span[title="CPU Time"]')).toBeInTheDocument(); + expect(document.querySelector('span[title="Memory Usage"]')).toBeInTheDocument(); + expect(document.querySelector('span[title="Indices"]')).toBeInTheDocument(); + expect(document.querySelector('span[title="Search Type"]')).toBeInTheDocument(); + expect(document.querySelector('span[title="Coordinator Node ID"]')).toBeInTheDocument(); + expect(document.querySelector('span[title="Total Shards"]')).toBeInTheDocument(); + // TODO add tests for the values + }); + + it('calls setBreadcrumbs on mount', () => { + renderQueryInsights(); + expect(mockCore.chrome.setBreadcrumbs).toHaveBeenCalledWith([ + { + text: 'Query insights', + href: '/queryInsights', + onClick: expect.any(Function), + }, + ]); + }); + + it('triggers onTimeChange when the date picker changes', () => { + renderQueryInsights(); + + // Find the date picker update button + const updateButton = screen.getByRole('button', { name: /Refresh/i }); + fireEvent.click(updateButton); + + // Verify the onTimeChange callback is triggered + expect(mockOnTimeChange).toHaveBeenCalled(); + }); +}); diff --git a/test/testUtils.ts b/test/testUtils.ts new file mode 100644 index 0000000..55ad71d --- /dev/null +++ b/test/testUtils.ts @@ -0,0 +1,99 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +import { SearchQueryRecord } from '../types/types'; + +export const MockQueries = (): SearchQueryRecord[] => { + return [ + { + timestamp: 1726178995210, + task_resource_usages: [ + { + action: 'indices:data/read/search[phase/query]', + taskId: 18809, + parentTaskId: 18808, + nodeId: 'Q36D2z_NRGKim6EZZMgi6A', + taskResourceUsage: { + cpu_time_in_nanos: 3612000, + memory_in_bytes: 123944, + }, + }, + { + action: 'indices:data/read/search', + taskId: 18808, + parentTaskId: -1, + nodeId: 'Q36D2z_NRGKim6EZZMgi6A', + taskResourceUsage: { + cpu_time_in_nanos: 1898000, + memory_in_bytes: 24176, + }, + }, + ], + source: { + query: { + bool: { + must: [ + { + range: { + timestamp: { + from: 1726092595177, + to: 1726178995177, + include_lower: true, + include_upper: true, + boost: 1.0, + }, + }, + }, + ], + must_not: [ + { + match: { + indices: { + query: 'top_queries*', + operator: 'OR', + prefix_length: 0, + max_expansions: 50, + fuzzy_transpositions: true, + lenient: false, + zero_terms_query: 'NONE', + auto_generate_synonyms_phrase_query: true, + boost: 1.0, + }, + }, + }, + ], + adjust_pure_negative: true, + boost: 1.0, + }, + }, + }, + query_hashcode: '80a17984b847133b8bf5e7d5dfbfa96c', + phase_latency_map: { + expand: 0, + query: 5, + fetch: 0, + }, + labels: { + 'X-Opaque-Id': 'ae6c1170-5f98-47f4-b7fc-09ebcf574b81', + }, + total_shards: 1, + search_type: 'query_then_fetch', + node_id: 'Q36D2z_NRGKim6EZZMgi6A', + indices: ['top_queries-2024.09.12'], + measurements: { + latency: { + number: 8, + count: 1, + aggregationType: 'NONE', + }, + cpu: { + number: 5510000, + count: 1, + aggregationType: 'NONE', + }, + }, + }, + ]; +}; diff --git a/types/types.ts b/types/types.ts index 01f2f59..ca4ec71 100644 --- a/types/types.ts +++ b/types/types.ts @@ -3,8 +3,6 @@ * SPDX-License-Identifier: Apache-2.0 */ -import { ISearchSource } from 'src/plugins/data/public'; - export interface SearchQueryRecord { timestamp: number; measurements: { @@ -14,12 +12,13 @@ export interface SearchQueryRecord { }; total_shards: number; node_id: string; - source: ISearchSource; + source: Record; labels: Record; search_type: string; indices: string[]; phase_latency_map: PhaseLatencyMap; task_resource_usages: Task[]; + query_hashcode: string; } export interface Measurement { From df66313d571ff8451658e1ee9987ef5996870eb3 Mon Sep 17 00:00:00 2001 From: Chenyang Ji Date: Mon, 13 Jan 2025 17:51:29 -0800 Subject: [PATCH 2/2] update snapshots Signed-off-by: Chenyang Ji --- package.json | 1 + .../Configuration/Configuration.test.tsx | 31 +- .../__snapshots__/Configuration.test.tsx.snap | 1220 +++++++++++++++++ .../pages/QueryDetails/QueryDetails.test.tsx | 54 + public/pages/QueryDetails/QueryDetails.tsx | 68 +- .../__snapshots__/QueryDetails.test.tsx.snap | 1155 ++++++++++++++++ .../QueryInsights/QueryInsights.test.tsx | 18 +- .../__snapshots__/QueryInsights.test.tsx.snap | 856 ++++++++++++ public/pages/TopNQueries/TopNQueries.test.tsx | 38 +- .../__snapshots__/TopNQueries.test.tsx.snap | 629 +++++++++ yarn.lock | 78 +- 11 files changed, 4050 insertions(+), 98 deletions(-) create mode 100644 public/pages/Configuration/__snapshots__/Configuration.test.tsx.snap create mode 100644 public/pages/QueryDetails/QueryDetails.test.tsx create mode 100644 public/pages/QueryDetails/__snapshots__/QueryDetails.test.tsx.snap create mode 100644 public/pages/QueryInsights/__snapshots__/QueryInsights.test.tsx.snap create mode 100644 public/pages/TopNQueries/__snapshots__/TopNQueries.test.tsx.snap diff --git a/package.json b/package.json index 1682cc8..25fd4b2 100644 --- a/package.json +++ b/package.json @@ -42,6 +42,7 @@ "@elastic/elastic-eslint-config-kibana": "link:../../packages/opensearch-eslint-config-opensearch-dashboards", "@elastic/eslint-import-resolver-kibana": "link:../../packages/osd-eslint-import-resolver-opensearch-dashboards", "@testing-library/dom": "^8.11.3", + "@testing-library/jest-dom": "^5.16.2", "@testing-library/user-event": "^14.4.3", "@types/react-dom": "^16.9.8", "@types/object-hash": "^3.0.0", diff --git a/public/pages/Configuration/Configuration.test.tsx b/public/pages/Configuration/Configuration.test.tsx index 1a3948b..0f9360d 100644 --- a/public/pages/Configuration/Configuration.test.tsx +++ b/public/pages/Configuration/Configuration.test.tsx @@ -35,7 +35,7 @@ const defaultMemorySettings = { currTimeUnit: 'HOURS', }; -const renderConfiguration = (overrides = {}) => { +const renderConfiguration = (overrides = {}) => render( { cpuSettings={defaultCpuSettings} memorySettings={defaultMemorySettings} configInfo={mockConfigInfo} - // @ts-ignore core={mockCoreStart} /> ); -}; const getWindowSizeConfigurations = () => screen.getAllByRole('combobox'); const getTopNSizeConfiguration = () => screen.getByRole('spinbutton'); @@ -60,31 +58,13 @@ describe('Configuration Component', () => { }); it('renders with default settings', () => { - renderConfiguration(); - // main header - expect( - screen.getByRole('heading', { name: /Top n queries monitoring configuration settings/i }) - ).toBeInTheDocument(); - // section headers - expect(screen.getByRole('heading', { name: /Metric Type/i })).toBeInTheDocument(); - expect(screen.getByRole('heading', { name: /Enabled/i })).toBeInTheDocument(); - expect(screen.getByRole('heading', { name: /Value of N/i })).toBeInTheDocument(); - expect(screen.getByRole('heading', { name: /Window size/i })).toBeInTheDocument(); - // Check values for window size configurations - const selectBoxes = getWindowSizeConfigurations(); - expect(selectBoxes[0]).toHaveValue('latency'); - expect(selectBoxes[1]).toHaveValue('10'); - expect(selectBoxes[2]).toHaveValue('MINUTES'); - // Check the value for top n size configurations - expect(getTopNSizeConfiguration()).toHaveValue(5); - // Check the value for enabled switch - const enableBox = getEnableToggle(); - expect(enableBox).toBeInTheDocument(); - expect(enableBox).toBeChecked(); + const { container } = renderConfiguration(); + expect(container).toMatchSnapshot('should match default settings snapshot'); }); + // The following tests test the interactions on the frontend with Mocks. it('updates state when toggling metrics and enables Save button when changes are made', () => { - renderConfiguration(); + const { container } = renderConfiguration(); // before toggling the metric expect(getWindowSizeConfigurations()[0]).toHaveValue('latency'); expect(getEnableToggle()).toBeChecked(); @@ -100,6 +80,7 @@ describe('Configuration Component', () => { fireEvent.click(getEnableToggle()); expect(getEnableToggle()).toBeChecked(); expect(screen.getByText('Save')).toBeEnabled(); + expect(container).toMatchSnapshot('should match settings snapshot after toggling'); }); it('validates topNSize and windowSize inputs and disables Save button for invalid input', () => { diff --git a/public/pages/Configuration/__snapshots__/Configuration.test.tsx.snap b/public/pages/Configuration/__snapshots__/Configuration.test.tsx.snap new file mode 100644 index 0000000..4034199 --- /dev/null +++ b/public/pages/Configuration/__snapshots__/Configuration.test.tsx.snap @@ -0,0 +1,1220 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Configuration Component renders with default settings: should match default settings snapshot 1`] = ` +
+
+
+
+
+
+
+
+

+ Top n queries monitoring configuration settings +

+
+
+
+
+
+
+

+ Metric Type +

+
+
+ Specify the metric type to set settings for. +
+
+
+
+
+
+
+ +
+ + + +
+
+
+
+
+
+
+
+

+ Enabled +

+
+
+ Enable/disable top N query monitoring by latency. +
+
+
+
+
+
+
+
+ + +
+
+
+
+
+
+
+

+ Value of N (count) +

+
+
+ Specify the value of N. N is the number of queries to be collected within the window size. +
+
+
+
+
+ +
+
+
+
+ +
+
+
+ Max allowed limit 100. +
+
+
+
+
+
+

+ Window size +

+
+
+ The duration during which the Top N queries are collected. +
+
+
+
+
+ +
+
+
+
+
+
+ +
+ + + +
+
+
+
+
+
+
+ +
+ + + +
+
+
+
+
+
+ Max allowed limit 24 hours. +
+
+
+
+
+
+
+
+
+
+
+
+
+

+ Statuses for configuration metrics +

+
+
+
+
+
+
+ Latency +
+
+
+
+
+
+
+ +
+
+ Enabled +
+
+
+
+
+
+
+
+ CPU Usage +
+
+
+
+
+
+
+ +
+
+ Disabled +
+
+
+
+
+
+
+
+ Memory +
+
+
+
+
+
+
+ +
+
+ Disabled +
+
+
+
+
+
+
+
+
+
+
+`; + +exports[`Configuration Component updates state when toggling metrics and enables Save button when changes are made: should match settings snapshot after toggling 1`] = ` +
+
+
+
+
+
+
+
+

+ Top n queries monitoring configuration settings +

+
+
+
+
+
+
+

+ Metric Type +

+
+
+ Specify the metric type to set settings for. +
+
+
+
+
+
+
+ +
+ + + +
+
+
+
+
+
+
+
+

+ Enabled +

+
+
+ Enable/disable top N query monitoring by cpu. +
+
+
+
+
+
+
+
+ + +
+
+
+
+
+
+
+

+ Value of N (count) +

+
+
+ Specify the value of N. N is the number of queries to be collected within the window size. +
+
+
+
+
+ +
+
+
+
+ +
+
+
+ Max allowed limit 100. +
+
+
+
+
+
+

+ Window size +

+
+
+ The duration during which the Top N queries are collected. +
+
+
+
+
+ +
+
+
+
+
+
+ +
+
+
+
+
+
+ +
+ + + +
+
+
+
+
+
+ Max allowed limit 24 hours. +
+
+
+
+
+
+
+
+
+
+
+
+
+

+ Statuses for configuration metrics +

+
+
+
+
+
+
+ Latency +
+
+
+
+
+
+
+ +
+
+ Enabled +
+
+
+
+
+
+
+
+ CPU Usage +
+
+
+
+
+
+
+ +
+
+ Disabled +
+
+
+
+
+
+
+
+ Memory +
+
+
+
+
+
+
+ +
+
+ Disabled +
+
+
+
+
+
+
+
+
+
+
+`; diff --git a/public/pages/QueryDetails/QueryDetails.test.tsx b/public/pages/QueryDetails/QueryDetails.test.tsx new file mode 100644 index 0000000..196f267 --- /dev/null +++ b/public/pages/QueryDetails/QueryDetails.test.tsx @@ -0,0 +1,54 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +import React from 'react'; +import { render, screen } from '@testing-library/react'; +import QueryDetails from './QueryDetails'; +import Plotly from 'plotly.js-dist'; +import { MockQueries } from '../../../test/testUtils'; +import '@testing-library/jest-dom'; +import { MemoryRouter, Route } from 'react-router-dom'; +import hash from 'object-hash'; +// Mock the external dependencies +jest.mock('plotly.js-dist', () => ({ + newPlot: jest.fn(), +})); + +const mockCoreStart = { + chrome: { + setBreadcrumbs: jest.fn(), + }, +}; +const mockQuery = MockQueries()[0]; +const mockParams = { hashedQuery: hash(mockQuery) }; + +describe('QueryDetails component', () => { + beforeEach(() => { + jest.clearAllMocks(); // Clear all mock calls and instances before each test + }); + + const renderComponent = () => + render( + + + + + + ); + + it('renders the QueryDetails page', () => { + const { container } = renderComponent(); + // Check if the query details are displayed correctly + expect(screen.getByText('Query details')).toBeInTheDocument(); + expect(screen.getByText('Query')).toBeInTheDocument(); + + // Verify that the Plotly chart is rendered + expect(Plotly.newPlot).toHaveBeenCalledTimes(1); + // Verify the breadcrumbs were set correctly + expect(mockCoreStart.chrome.setBreadcrumbs).toHaveBeenCalled(); + + expect(container).toMatchSnapshot(); + }); +}); diff --git a/public/pages/QueryDetails/QueryDetails.tsx b/public/pages/QueryDetails/QueryDetails.tsx index c7cf406..5335376 100644 --- a/public/pages/QueryDetails/QueryDetails.tsx +++ b/public/pages/QueryDetails/QueryDetails.tsx @@ -3,7 +3,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -import React, { useEffect } from 'react'; +import React, { useCallback, useEffect } from 'react'; import Plotly from 'plotly.js-dist'; import { EuiButton, @@ -18,53 +18,37 @@ import { EuiTitle, } from '@elastic/eui'; import hash from 'object-hash'; -import { useParams, useHistory, useLocation } from 'react-router-dom'; +import { useParams, useHistory } from 'react-router-dom'; import { CoreStart } from 'opensearch-dashboards/public'; import QuerySummary from './Components/QuerySummary'; import { QUERY_INSIGHTS } from '../TopNQueries/TopNQueries'; +import { SearchQueryRecord } from '../../../types/types'; const QueryDetails = ({ queries, core }: { queries: any; core: CoreStart }) => { const { hashedQuery } = useParams<{ hashedQuery: string }>(); - const query = queries.find((q: any) => hash(q) === hashedQuery); - - const convertTime = (unixTime: number) => { - const date = new Date(unixTime); - const loc = date.toDateString().split(' '); - return loc[1] + ' ' + loc[2] + ', ' + loc[3] + ' @ ' + date.toLocaleTimeString('en-US'); - }; - + const query = queries.find((q: SearchQueryRecord) => hash(q) === hashedQuery); const history = useHistory(); - const location = useLocation(); - useEffect(() => { - core.chrome.setBreadcrumbs([ - { - text: 'Query insights', - href: QUERY_INSIGHTS, - onClick: (e) => { - e.preventDefault(); - history.push(QUERY_INSIGHTS); - }, - }, - { text: `Query details: ${convertTime(query.timestamp)}` }, - ]); - }, [core.chrome, history, location, query.timestamp]); + // Convert UNIX time to a readable format + const convertTime = useCallback((unixTime: number) => { + const date = new Date(unixTime); + const [_weekDay, month, day, year] = date.toDateString().split(' '); + return `${month} ${day}, ${year} @ ${date.toLocaleTimeString('en-US')}`; + }, []); - useEffect(() => { - let x: number[] = Object.values(query.phase_latency_map); - if (x.length < 3) { - x = [0, 0, 0]; - } + // Initialize the Plotly chart + const initPlotlyChart = useCallback(() => { + const latencies: number[] = Object.values(query?.phase_latency_map || [0, 0, 0]); const data = [ { - x: x.reverse(), + x: latencies.reverse(), y: ['Fetch ', 'Query ', 'Expand '], type: 'bar', orientation: 'h', width: 0.5, marker: { color: ['#F990C0', '#1BA9F5', '#7DE2D1'] }, - base: [x[2] + x[1], x[2], 0], - text: x.map((value) => `${value}ms`), + base: [latencies[2] + latencies[1], latencies[2], 0], + text: latencies.map((value) => `${value}ms`), textposition: 'outside', cliponaxis: false, }, @@ -72,7 +56,6 @@ const QueryDetails = ({ queries, core }: { queries: any; core: CoreStart }) => { const layout = { autosize: true, margin: { l: 80, r: 80, t: 25, b: 15, pad: 0 }, - autorange: true, height: 120, xaxis: { side: 'top', @@ -89,7 +72,22 @@ const QueryDetails = ({ queries, core }: { queries: any; core: CoreStart }) => { Plotly.newPlot('latency', data, layout, config); }, [query]); - const queryString = JSON.stringify(JSON.parse(JSON.stringify(query.source)), null, 2); + useEffect(() => { + core.chrome.setBreadcrumbs([ + { + text: 'Query insights', + href: QUERY_INSIGHTS, + onClick: (e) => { + e.preventDefault(); + history.push(QUERY_INSIGHTS); + }, + }, + { text: `Query details: ${convertTime(query.timestamp)}` }, + ]); + initPlotlyChart(); + }, [query, history, core.chrome, convertTime, initPlotlyChart]); + + const queryString = JSON.stringify(query.source, null, 2); const queryDisplay = `{\n "query": ${queryString ? queryString.replace(/\n/g, '\n ') : ''}\n}`; return ( @@ -117,7 +115,7 @@ const QueryDetails = ({ queries, core }: { queries: any; core: CoreStart }) => { target="_blank" href="https://playground.opensearch.org/app/searchRelevance#/" > - Open in search comparision + Open in search comparison diff --git a/public/pages/QueryDetails/__snapshots__/QueryDetails.test.tsx.snap b/public/pages/QueryDetails/__snapshots__/QueryDetails.test.tsx.snap new file mode 100644 index 0000000..912f011 --- /dev/null +++ b/public/pages/QueryDetails/__snapshots__/QueryDetails.test.tsx.snap @@ -0,0 +1,1155 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`QueryDetails component renders the QueryDetails page 1`] = ` +
+
+

+ Query details +

+
+
+
+
+

+ Summary +

+
+
+
+
+
+

+ Timestamp +

+
+
+ Sep 12, 2024 @ 3:09:55 PM +
+
+
+
+

+ Latency +

+
+
+ 8 ms +
+
+
+
+

+ CPU Time +

+
+
+ 5.51 ms +
+
+
+
+

+ Memory Usage +

+
+
+ N/A B +
+
+
+
+

+ Indices +

+
+
+ top_queries-2024.09.12 +
+
+
+
+

+ Search Type +

+
+
+ query then fetch +
+
+
+
+

+ Coordinator Node ID +

+
+
+ Q36D2z_NRGKim6EZZMgi6A +
+
+
+
+

+ Total Shards +

+
+
+ 1 +
+
+
+
+
+
+
+
+ +
+
+
+
+                
+                  
+                    
+                      {
+                    
+                    
+
+                  
+                  
+                      
+                    
+                      "query"
+                    
+                    
+                      :
+                    
+                     
+                    
+                      {
+                    
+                    
+
+                  
+                  
+                        
+                    
+                      "query"
+                    
+                    
+                      :
+                    
+                     
+                    
+                      {
+                    
+                    
+
+                  
+                  
+                          
+                    
+                      "bool"
+                    
+                    
+                      :
+                    
+                     
+                    
+                      {
+                    
+                    
+
+                  
+                  
+                            
+                    
+                      "must"
+                    
+                    
+                      :
+                    
+                     
+                    
+                      [
+                    
+                    
+
+                  
+                  
+                              
+                    
+                      {
+                    
+                    
+
+                  
+                  
+                                
+                    
+                      "range"
+                    
+                    
+                      :
+                    
+                     
+                    
+                      {
+                    
+                    
+
+                  
+                  
+                                  
+                    
+                      "timestamp"
+                    
+                    
+                      :
+                    
+                     
+                    
+                      {
+                    
+                    
+
+                  
+                  
+                                    
+                    
+                      "from"
+                    
+                    
+                      :
+                    
+                     
+                    
+                      1726092595177
+                    
+                    
+                      ,
+                    
+                    
+
+                  
+                  
+                                    
+                    
+                      "to"
+                    
+                    
+                      :
+                    
+                     
+                    
+                      1726178995177
+                    
+                    
+                      ,
+                    
+                    
+
+                  
+                  
+                                    
+                    
+                      "include_lower"
+                    
+                    
+                      :
+                    
+                     
+                    
+                      true
+                    
+                    
+                      ,
+                    
+                    
+
+                  
+                  
+                                    
+                    
+                      "include_upper"
+                    
+                    
+                      :
+                    
+                     
+                    
+                      true
+                    
+                    
+                      ,
+                    
+                    
+
+                  
+                  
+                                    
+                    
+                      "boost"
+                    
+                    
+                      :
+                    
+                     
+                    
+                      1
+                    
+                    
+
+                  
+                  
+                                  
+                    
+                      }
+                    
+                    
+
+                  
+                  
+                                
+                    
+                      }
+                    
+                    
+
+                  
+                  
+                              
+                    
+                      }
+                    
+                    
+
+                  
+                  
+                            
+                    
+                      ]
+                    
+                    
+                      ,
+                    
+                    
+
+                  
+                  
+                            
+                    
+                      "must_not"
+                    
+                    
+                      :
+                    
+                     
+                    
+                      [
+                    
+                    
+
+                  
+                  
+                              
+                    
+                      {
+                    
+                    
+
+                  
+                  
+                                
+                    
+                      "match"
+                    
+                    
+                      :
+                    
+                     
+                    
+                      {
+                    
+                    
+
+                  
+                  
+                                  
+                    
+                      "indices"
+                    
+                    
+                      :
+                    
+                     
+                    
+                      {
+                    
+                    
+
+                  
+                  
+                                    
+                    
+                      "query"
+                    
+                    
+                      :
+                    
+                     
+                    
+                      "top_queries*"
+                    
+                    
+                      ,
+                    
+                    
+
+                  
+                  
+                                    
+                    
+                      "operator"
+                    
+                    
+                      :
+                    
+                     
+                    
+                      "OR"
+                    
+                    
+                      ,
+                    
+                    
+
+                  
+                  
+                                    
+                    
+                      "prefix_length"
+                    
+                    
+                      :
+                    
+                     
+                    
+                      0
+                    
+                    
+                      ,
+                    
+                    
+
+                  
+                  
+                                    
+                    
+                      "max_expansions"
+                    
+                    
+                      :
+                    
+                     
+                    
+                      50
+                    
+                    
+                      ,
+                    
+                    
+
+                  
+                  
+                                    
+                    
+                      "fuzzy_transpositions"
+                    
+                    
+                      :
+                    
+                     
+                    
+                      true
+                    
+                    
+                      ,
+                    
+                    
+
+                  
+                  
+                                    
+                    
+                      "lenient"
+                    
+                    
+                      :
+                    
+                     
+                    
+                      false
+                    
+                    
+                      ,
+                    
+                    
+
+                  
+                  
+                                    
+                    
+                      "zero_terms_query"
+                    
+                    
+                      :
+                    
+                     
+                    
+                      "NONE"
+                    
+                    
+                      ,
+                    
+                    
+
+                  
+                  
+                                    
+                    
+                      "auto_generate_synonyms_phrase_query"
+                    
+                    
+                      :
+                    
+                     
+                    
+                      true
+                    
+                    
+                      ,
+                    
+                    
+
+                  
+                  
+                                    
+                    
+                      "boost"
+                    
+                    
+                      :
+                    
+                     
+                    
+                      1
+                    
+                    
+
+                  
+                  
+                                  
+                    
+                      }
+                    
+                    
+
+                  
+                  
+                                
+                    
+                      }
+                    
+                    
+
+                  
+                  
+                              
+                    
+                      }
+                    
+                    
+
+                  
+                  
+                            
+                    
+                      ]
+                    
+                    
+                      ,
+                    
+                    
+
+                  
+                  
+                            
+                    
+                      "adjust_pure_negative"
+                    
+                    
+                      :
+                    
+                     
+                    
+                      true
+                    
+                    
+                      ,
+                    
+                    
+
+                  
+                  
+                            
+                    
+                      "boost"
+                    
+                    
+                      :
+                    
+                     
+                    
+                      1
+                    
+                    
+
+                  
+                  
+                          
+                    
+                      }
+                    
+                    
+
+                  
+                  
+                        
+                    
+                      }
+                    
+                    
+
+                  
+                  
+                      
+                    
+                      }
+                    
+                    
+
+                  
+                  
+                    
+                    
+                      }
+                    
+                  
+                
+              
+
+ +
+ + + +
+
+
+
+
+
+
+
+

+ Latency +

+
+
+
+
+
+
+
+
+
+`; diff --git a/public/pages/QueryInsights/QueryInsights.test.tsx b/public/pages/QueryInsights/QueryInsights.test.tsx index 7812b12..9740d7b 100644 --- a/public/pages/QueryInsights/QueryInsights.test.tsx +++ b/public/pages/QueryInsights/QueryInsights.test.tsx @@ -18,10 +18,9 @@ const mockCore = { }, }; -// TODO: change to use MockQueries once https://github.com/opensearch-project/query-insights-dashboards/pull/21/files is merged const sampleQueries = MockQueries(); -const renderQueryInsights = () => { +const renderQueryInsights = () => render( { /> ); -}; describe('QueryInsights Component', () => { beforeEach(() => { @@ -44,18 +42,8 @@ describe('QueryInsights Component', () => { }); it('renders the table with the correct columns and data', () => { - renderQueryInsights(); - - // Check that the table and columns render correctly - expect(document.querySelector('span[title="Timestamp"]')).toBeInTheDocument(); - expect(document.querySelector('span[title="Latency"]')).toBeInTheDocument(); - expect(document.querySelector('span[title="CPU Time"]')).toBeInTheDocument(); - expect(document.querySelector('span[title="Memory Usage"]')).toBeInTheDocument(); - expect(document.querySelector('span[title="Indices"]')).toBeInTheDocument(); - expect(document.querySelector('span[title="Search Type"]')).toBeInTheDocument(); - expect(document.querySelector('span[title="Coordinator Node ID"]')).toBeInTheDocument(); - expect(document.querySelector('span[title="Total Shards"]')).toBeInTheDocument(); - // TODO add tests for the values + const { container } = renderQueryInsights(); + expect(container).toMatchSnapshot(); }); it('calls setBreadcrumbs on mount', () => { diff --git a/public/pages/QueryInsights/__snapshots__/QueryInsights.test.tsx.snap b/public/pages/QueryInsights/__snapshots__/QueryInsights.test.tsx.snap new file mode 100644 index 0000000..d511a12 --- /dev/null +++ b/public/pages/QueryInsights/__snapshots__/QueryInsights.test.tsx.snap @@ -0,0 +1,856 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`QueryInsights Component renders the table with the correct columns and data 1`] = ` +
+
+
+
+
+
+ +
+ + + +
+
+
+
+
+
+
+
+ +
+
+
+
+ +
+
+
+
+ +
+
+
+
+
+
+
+
+
+
+ +
+
+
+
+ +
+
+
+
+
+ + + +
+
+
+
+
+
+
+
+
+
+
+
+
+
+ +
+
+
+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + + + + + + + + + + + + + +
+
+ Timestamp +
+
+ + + +
+
+
+ Latency +
+
+ 8 ms +
+
+
+ CPU Time +
+
+ 5.51 ms +
+
+
+ Memory Usage +
+
+ Not enabled +
+
+
+ Indices +
+
+ top_queries-2024.09.12 +
+
+
+ Search Type +
+
+ query then fetch +
+
+
+ Coordinator Node ID +
+
+ + Q36D2z_NRGKim6EZZMgi6A + +
+
+
+ Total Shards +
+
+ + 1 + +
+
+
+
+
+
+
+
+
+ +
+
+
+
+ +
+
+
+
+
+
+`; diff --git a/public/pages/TopNQueries/TopNQueries.test.tsx b/public/pages/TopNQueries/TopNQueries.test.tsx index f642c39..a8fabf1 100644 --- a/public/pages/TopNQueries/TopNQueries.test.tsx +++ b/public/pages/TopNQueries/TopNQueries.test.tsx @@ -51,22 +51,26 @@ const setUpDefaultEnabledSettings = () => { (mockCore.http.get as jest.Mock).mockResolvedValueOnce(mockSettingsResponse); }; +const renderTopNQueries = (type: string) => + render( + + + + ); + describe('TopNQueries Component', () => { beforeEach(() => { jest.clearAllMocks(); }); it('renders and switches tabs correctly', () => { - render( - - - - ); + const container = renderTopNQueries(QUERY_INSIGHTS); // Check for Query Insights tab content expect(screen.getByText('Mocked QueryInsights')).toBeInTheDocument(); expect(screen.getByText('Top N queries')).toBeInTheDocument(); expect(screen.getByText('Configuration')).toBeInTheDocument(); + expect(container).toMatchSnapshot(); // Switch to Configuration tab fireEvent.click(screen.getByText('Configuration')); @@ -90,24 +94,17 @@ describe('TopNQueries Component', () => { }, }; (mockCore.http.get as jest.Mock).mockResolvedValueOnce(mockSettingsResponse); - render( - - - - ); + const container = renderTopNQueries(CONFIGURATION); await waitFor(() => { expect(mockCore.http.get).toHaveBeenCalledWith('/api/settings'); expect(screen.getByText('Mocked Configuration')).toBeInTheDocument(); + expect(container).toMatchSnapshot(); }); }); it('fetches queries for all metrics in retrieveQueries', async () => { setUpDefaultEnabledSettings(); - render( - - - - ); + const container = renderTopNQueries(QUERY_INSIGHTS); await waitFor(() => { // Verify each endpoint is called expect(mockCore.http.get).toHaveBeenCalledWith('/api/settings'); @@ -119,6 +116,8 @@ describe('TopNQueries Component', () => { expect(mockCore.http.get).toHaveBeenCalledWith('/api/top_queries/memory', expect.any(Object)); // Check that deduplicated queries would be displayed in QueryInsights expect(screen.getByText('Mocked QueryInsights')).toBeInTheDocument(); + + expect(container).toMatchSnapshot(); }); }); @@ -148,11 +147,7 @@ describe('TopNQueries Component', () => { }, }; (mockCore.http.get as jest.Mock).mockResolvedValueOnce(mockSettingsResponse); - render( - - - - ); + const container = renderTopNQueries(QUERY_INSIGHTS); await waitFor(() => { // Verify each endpoint is called expect(mockCore.http.get).toHaveBeenCalledWith('/api/settings'); @@ -170,6 +165,8 @@ describe('TopNQueries Component', () => { ); // Check that deduplicated queries would be displayed in QueryInsights expect(screen.getByText('Mocked QueryInsights')).toBeInTheDocument(); + + expect(container).toMatchSnapshot(); }); }); @@ -186,6 +183,7 @@ describe('TopNQueries Component', () => { (mockCore.http.get as jest.Mock).mockResolvedValueOnce({ response: { top_queries: [{ id: 'newQuery' }] }, }); + // Re-render with updated time range to simulate a change rerender( diff --git a/public/pages/TopNQueries/__snapshots__/TopNQueries.test.tsx.snap b/public/pages/TopNQueries/__snapshots__/TopNQueries.test.tsx.snap new file mode 100644 index 0000000..804c1e1 --- /dev/null +++ b/public/pages/TopNQueries/__snapshots__/TopNQueries.test.tsx.snap @@ -0,0 +1,629 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`TopNQueries Component fetches queries for all metrics in retrieveQueries 1`] = ` +Object { + "asFragment": [Function], + "baseElement": +
+
+

+ Query insights - Top N queries +

+
+
+ + +
+
+
+ Mocked QueryInsights +
+
+
+ , + "container":
+
+

+ Query insights - Top N queries +

+
+
+ + +
+
+
+ Mocked QueryInsights +
+
+
, + "debug": [Function], + "findAllByAltText": [Function], + "findAllByDisplayValue": [Function], + "findAllByLabelText": [Function], + "findAllByPlaceholderText": [Function], + "findAllByRole": [Function], + "findAllByTestId": [Function], + "findAllByText": [Function], + "findAllByTitle": [Function], + "findByAltText": [Function], + "findByDisplayValue": [Function], + "findByLabelText": [Function], + "findByPlaceholderText": [Function], + "findByRole": [Function], + "findByTestId": [Function], + "findByText": [Function], + "findByTitle": [Function], + "getAllByAltText": [Function], + "getAllByDisplayValue": [Function], + "getAllByLabelText": [Function], + "getAllByPlaceholderText": [Function], + "getAllByRole": [Function], + "getAllByTestId": [Function], + "getAllByText": [Function], + "getAllByTitle": [Function], + "getByAltText": [Function], + "getByDisplayValue": [Function], + "getByLabelText": [Function], + "getByPlaceholderText": [Function], + "getByRole": [Function], + "getByTestId": [Function], + "getByText": [Function], + "getByTitle": [Function], + "queryAllByAltText": [Function], + "queryAllByDisplayValue": [Function], + "queryAllByLabelText": [Function], + "queryAllByPlaceholderText": [Function], + "queryAllByRole": [Function], + "queryAllByTestId": [Function], + "queryAllByText": [Function], + "queryAllByTitle": [Function], + "queryByAltText": [Function], + "queryByDisplayValue": [Function], + "queryByLabelText": [Function], + "queryByPlaceholderText": [Function], + "queryByRole": [Function], + "queryByTestId": [Function], + "queryByText": [Function], + "queryByTitle": [Function], + "rerender": [Function], + "unmount": [Function], +} +`; + +exports[`TopNQueries Component fetches queries for only enabled metrics in retrieveQueries 1`] = ` +Object { + "asFragment": [Function], + "baseElement": +
+
+

+ Query insights - Top N queries +

+
+
+ + +
+
+
+ Mocked QueryInsights +
+
+
+ , + "container":
+
+

+ Query insights - Top N queries +

+
+
+ + +
+
+
+ Mocked QueryInsights +
+
+
, + "debug": [Function], + "findAllByAltText": [Function], + "findAllByDisplayValue": [Function], + "findAllByLabelText": [Function], + "findAllByPlaceholderText": [Function], + "findAllByRole": [Function], + "findAllByTestId": [Function], + "findAllByText": [Function], + "findAllByTitle": [Function], + "findByAltText": [Function], + "findByDisplayValue": [Function], + "findByLabelText": [Function], + "findByPlaceholderText": [Function], + "findByRole": [Function], + "findByTestId": [Function], + "findByText": [Function], + "findByTitle": [Function], + "getAllByAltText": [Function], + "getAllByDisplayValue": [Function], + "getAllByLabelText": [Function], + "getAllByPlaceholderText": [Function], + "getAllByRole": [Function], + "getAllByTestId": [Function], + "getAllByText": [Function], + "getAllByTitle": [Function], + "getByAltText": [Function], + "getByDisplayValue": [Function], + "getByLabelText": [Function], + "getByPlaceholderText": [Function], + "getByRole": [Function], + "getByTestId": [Function], + "getByText": [Function], + "getByTitle": [Function], + "queryAllByAltText": [Function], + "queryAllByDisplayValue": [Function], + "queryAllByLabelText": [Function], + "queryAllByPlaceholderText": [Function], + "queryAllByRole": [Function], + "queryAllByTestId": [Function], + "queryAllByText": [Function], + "queryAllByTitle": [Function], + "queryByAltText": [Function], + "queryByDisplayValue": [Function], + "queryByLabelText": [Function], + "queryByPlaceholderText": [Function], + "queryByRole": [Function], + "queryByTestId": [Function], + "queryByText": [Function], + "queryByTitle": [Function], + "rerender": [Function], + "unmount": [Function], +} +`; + +exports[`TopNQueries Component renders and switches tabs correctly 1`] = ` +Object { + "asFragment": [Function], + "baseElement": +
+
+

+ Query insights - Top N queries +

+
+
+ + +
+
+
+ Mocked QueryInsights +
+
+
+ , + "container":
+
+

+ Query insights - Top N queries +

+
+
+ + +
+
+
+ Mocked QueryInsights +
+
+
, + "debug": [Function], + "findAllByAltText": [Function], + "findAllByDisplayValue": [Function], + "findAllByLabelText": [Function], + "findAllByPlaceholderText": [Function], + "findAllByRole": [Function], + "findAllByTestId": [Function], + "findAllByText": [Function], + "findAllByTitle": [Function], + "findByAltText": [Function], + "findByDisplayValue": [Function], + "findByLabelText": [Function], + "findByPlaceholderText": [Function], + "findByRole": [Function], + "findByTestId": [Function], + "findByText": [Function], + "findByTitle": [Function], + "getAllByAltText": [Function], + "getAllByDisplayValue": [Function], + "getAllByLabelText": [Function], + "getAllByPlaceholderText": [Function], + "getAllByRole": [Function], + "getAllByTestId": [Function], + "getAllByText": [Function], + "getAllByTitle": [Function], + "getByAltText": [Function], + "getByDisplayValue": [Function], + "getByLabelText": [Function], + "getByPlaceholderText": [Function], + "getByRole": [Function], + "getByTestId": [Function], + "getByText": [Function], + "getByTitle": [Function], + "queryAllByAltText": [Function], + "queryAllByDisplayValue": [Function], + "queryAllByLabelText": [Function], + "queryAllByPlaceholderText": [Function], + "queryAllByRole": [Function], + "queryAllByTestId": [Function], + "queryAllByText": [Function], + "queryAllByTitle": [Function], + "queryByAltText": [Function], + "queryByDisplayValue": [Function], + "queryByLabelText": [Function], + "queryByPlaceholderText": [Function], + "queryByRole": [Function], + "queryByTestId": [Function], + "queryByText": [Function], + "queryByTitle": [Function], + "rerender": [Function], + "unmount": [Function], +} +`; + +exports[`TopNQueries Component updates settings in retrieveConfigInfo based on API response 1`] = ` +Object { + "asFragment": [Function], + "baseElement": +
+
+

+ Query insights - Configuration +

+
+
+ + +
+
+
+ Mocked Configuration +
+
+
+ , + "container":
+
+

+ Query insights - Configuration +

+
+
+ + +
+
+
+ Mocked Configuration +
+
+
, + "debug": [Function], + "findAllByAltText": [Function], + "findAllByDisplayValue": [Function], + "findAllByLabelText": [Function], + "findAllByPlaceholderText": [Function], + "findAllByRole": [Function], + "findAllByTestId": [Function], + "findAllByText": [Function], + "findAllByTitle": [Function], + "findByAltText": [Function], + "findByDisplayValue": [Function], + "findByLabelText": [Function], + "findByPlaceholderText": [Function], + "findByRole": [Function], + "findByTestId": [Function], + "findByText": [Function], + "findByTitle": [Function], + "getAllByAltText": [Function], + "getAllByDisplayValue": [Function], + "getAllByLabelText": [Function], + "getAllByPlaceholderText": [Function], + "getAllByRole": [Function], + "getAllByTestId": [Function], + "getAllByText": [Function], + "getAllByTitle": [Function], + "getByAltText": [Function], + "getByDisplayValue": [Function], + "getByLabelText": [Function], + "getByPlaceholderText": [Function], + "getByRole": [Function], + "getByTestId": [Function], + "getByText": [Function], + "getByTitle": [Function], + "queryAllByAltText": [Function], + "queryAllByDisplayValue": [Function], + "queryAllByLabelText": [Function], + "queryAllByPlaceholderText": [Function], + "queryAllByRole": [Function], + "queryAllByTestId": [Function], + "queryAllByText": [Function], + "queryAllByTitle": [Function], + "queryByAltText": [Function], + "queryByDisplayValue": [Function], + "queryByLabelText": [Function], + "queryByPlaceholderText": [Function], + "queryByRole": [Function], + "queryByTestId": [Function], + "queryByText": [Function], + "queryByTitle": [Function], + "rerender": [Function], + "unmount": [Function], +} +`; diff --git a/yarn.lock b/yarn.lock index 721ae91..a3d79cd 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2,6 +2,11 @@ # yarn lockfile v1 +"@adobe/css-tools@^4.0.1": + version "4.4.1" + resolved "https://registry.yarnpkg.com/@adobe/css-tools/-/css-tools-4.4.1.tgz#2447a230bfe072c1659e6815129c03cf170710e3" + integrity sha512-12WGKBQzjUAI4ayyF4IAtfw2QR/IDoqk6jTddXDhtYTJF9ASmoE1zst7cVtP0aL/F1jUJL5r+JxKXKEgHNbEUQ== + "@ampproject/remapping@^2.2.0": version "2.3.0" resolved "https://registry.yarnpkg.com/@ampproject/remapping/-/remapping-2.3.0.tgz#ed441b6fa600072520ce18b43d2c8cc8caecc7f4" @@ -255,6 +260,13 @@ dependencies: regenerator-runtime "^0.14.0" +"@babel/runtime@^7.9.2": + version "7.26.0" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.26.0.tgz#8600c2f595f277c60815256418b85356a65173c1" + integrity sha512-FDSOghenHTiToteC/QRlv2q3DhPZ/oOXTBoirfWNx1Cx3TMVcGWQtMMmQcSvb/JjpNeGzx8Pq/b4fKEJuWm1sw== + dependencies: + regenerator-runtime "^0.14.0" + "@babel/template@^7.25.0", "@babel/template@^7.3.3": version "7.25.0" resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.25.0.tgz#e733dc3134b4fede528c15bc95e89cb98c52592a" @@ -744,6 +756,21 @@ lz-string "^1.5.0" pretty-format "^27.0.2" +"@testing-library/jest-dom@^5.16.2": + version "5.17.0" + resolved "https://registry.yarnpkg.com/@testing-library/jest-dom/-/jest-dom-5.17.0.tgz#5e97c8f9a15ccf4656da00fecab505728de81e0c" + integrity sha512-ynmNeT7asXyH3aSVv4vvX4Rb+0qjOhdNHnO/3vuZNqPmhDpV/+rCSGwQ7bLcmU2cJ4dvoheIO85LQj0IbJHEtg== + dependencies: + "@adobe/css-tools" "^4.0.1" + "@babel/runtime" "^7.9.2" + "@types/testing-library__jest-dom" "^5.9.1" + aria-query "^5.0.0" + chalk "^3.0.0" + css.escape "^1.5.1" + dom-accessibility-api "^0.5.6" + lodash "^4.17.15" + redent "^3.0.0" + "@testing-library/user-event@^14.4.3": version "14.5.2" resolved "https://registry.yarnpkg.com/@testing-library/user-event/-/user-event-14.5.2.tgz#db7257d727c891905947bd1c1a99da20e03c2ebd" @@ -830,7 +857,7 @@ dependencies: "@types/istanbul-lib-report" "*" -"@types/jest@^29.3.1": +"@types/jest@*", "@types/jest@^29.3.1": version "29.5.12" resolved "https://registry.yarnpkg.com/@types/jest/-/jest-29.5.12.tgz#7f7dc6eb4cf246d2474ed78744b05d06ce025544" integrity sha512-eDC8bTvT/QhYdxJAulQikueigY5AsdBRH2yDKW3yveW7svY3+DzN84/2NUgkw10RTiJbWqZrTtoGVdYlvFJdLw== @@ -923,6 +950,13 @@ resolved "https://registry.yarnpkg.com/@types/stack-utils/-/stack-utils-2.0.3.tgz#6209321eb2c1712a7e7466422b8cb1fc0d9dd5d8" integrity sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw== +"@types/testing-library__jest-dom@^5.9.1": + version "5.14.9" + resolved "https://registry.yarnpkg.com/@types/testing-library__jest-dom/-/testing-library__jest-dom-5.14.9.tgz#0fb1e6a0278d87b6737db55af5967570b67cb466" + integrity sha512-FSYhIjFlfOpGSRyVoMBMuS3ws5ehFQODymf3vlI7U1K8c7PHwWwFY7VREfmsuzHSOnoKs/9/Y983ayOs7eRzqw== + dependencies: + "@types/jest" "*" + "@types/yargs-parser@*": version "21.0.3" resolved "https://registry.yarnpkg.com/@types/yargs-parser/-/yargs-parser-21.0.3.tgz#815e30b786d2e8f0dcd85fd5bcf5e1a04d008f15" @@ -1248,6 +1282,11 @@ aria-query@5.1.3: dependencies: deep-equal "^2.0.5" +aria-query@^5.0.0: + version "5.3.2" + resolved "https://registry.yarnpkg.com/aria-query/-/aria-query-5.3.2.tgz#93f81a43480e33a338f19163a3d10a50c01dcd59" + integrity sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw== + arr-diff@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-4.0.0.tgz#d6461074febfec71e7e15235761a329a5dc7c520" @@ -1814,6 +1853,14 @@ chalk@^2.3.0, chalk@^2.4.2: escape-string-regexp "^1.0.5" supports-color "^5.3.0" +chalk@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-3.0.0.tgz#3f73c2bf526591f574cc492c51e2456349f844e4" + integrity sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg== + dependencies: + ansi-styles "^4.1.0" + supports-color "^7.1.0" + chalk@^4.0.0, chalk@^4.1.0: version "4.1.2" resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" @@ -2161,6 +2208,11 @@ crypto-browserify@^3.11.0: randombytes "^2.1.0" randomfill "^1.0.4" +css.escape@^1.5.1: + version "1.5.1" + resolved "https://registry.yarnpkg.com/css.escape/-/css.escape-1.5.1.tgz#42e27d4fa04ae32f931a4b4d4191fa9cddee97cb" + integrity sha512-YUifsXXuknHlUsmlgyY0PKzgPOr7/FjCePfHNt0jxm83wHZi44VDMQ7/fGNkjY3/jV1MC+1CmZbaHzugyeRtpg== + cssom@^0.4.4: version "0.4.4" resolved "https://registry.yarnpkg.com/cssom/-/cssom-0.4.4.tgz#5a66cf93d2d0b661d80bf6a44fb65f5c2e4e0a10" @@ -2478,7 +2530,7 @@ diffie-hellman@^5.0.3: miller-rabin "^4.0.0" randombytes "^2.0.0" -dom-accessibility-api@^0.5.9: +dom-accessibility-api@^0.5.6, dom-accessibility-api@^0.5.9: version "0.5.16" resolved "https://registry.yarnpkg.com/dom-accessibility-api/-/dom-accessibility-api-0.5.16.tgz#5a7429e6066eb3664d911e33fb0e45de8eb08453" integrity sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg== @@ -4925,7 +4977,7 @@ lodash.once@^4.1.1: resolved "https://registry.yarnpkg.com/lodash.once/-/lodash.once-4.1.1.tgz#0dd3971213c7c56df880977d504c88fb471a97ac" integrity sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg== -lodash@^4.17.20, lodash@^4.17.21, lodash@^4.7.0: +lodash@^4.17.15, lodash@^4.17.20, lodash@^4.17.21, lodash@^4.7.0: version "4.17.21" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== @@ -5094,6 +5146,11 @@ mimic-fn@^2.1.0: resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg== +min-indent@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/min-indent/-/min-indent-1.0.1.tgz#a63f681673b30571fbe8bc25686ae746eefa9869" + integrity sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg== + minimalistic-assert@^1.0.0, minimalistic-assert@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz#2e194de044626d4a10e7f7fbc00ce73e83e4d5c7" @@ -5783,6 +5840,14 @@ readdirp@~3.6.0: dependencies: picomatch "^2.2.1" +redent@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/redent/-/redent-3.0.0.tgz#e557b7998316bb53c9f1f56fa626352c6963059f" + integrity sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg== + dependencies: + indent-string "^4.0.0" + strip-indent "^3.0.0" + reflect.getprototypeof@^1.0.6, reflect.getprototypeof@^1.0.9: version "1.0.10" resolved "https://registry.yarnpkg.com/reflect.getprototypeof/-/reflect.getprototypeof-1.0.10.tgz#c629219e78a3316d8b604c765ef68996964e7bf9" @@ -6530,6 +6595,13 @@ strip-final-newline@^2.0.0: resolved "https://registry.yarnpkg.com/strip-final-newline/-/strip-final-newline-2.0.0.tgz#89b852fb2fcbe936f6f4b3187afb0a12c1ab58ad" integrity sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA== +strip-indent@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/strip-indent/-/strip-indent-3.0.0.tgz#c32e1cee940b6b3432c771bc2c54bcce73cd3001" + integrity sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ== + dependencies: + min-indent "^1.0.0" + strip-json-comments@^3.1.1: version "3.1.1" resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006"