mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Tempo: Virtualized search dropdowns for attribute values (#88569)
* TraceQL: Make the search field component use the virtualized prop for performance gains * Use act on timers to eliminate warningsd * Update more timers to use act to fix testing library warnings * Fix linting failure * Run make commands --------- Co-authored-by: Joey Tawadrous <joey.tawadrous@grafana.com>
This commit is contained in:
parent
ea7f6ea32f
commit
3c5f07201e
@ -19970,7 +19970,6 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"State": {
|
"State": {
|
||||||
"description": "+enum",
|
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
"Status": {
|
"Status": {
|
||||||
@ -20730,7 +20729,6 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"Type": {
|
"Type": {
|
||||||
"description": "+enum",
|
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
"TypeMeta": {
|
"TypeMeta": {
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { render, screen, waitFor } from '@testing-library/react';
|
import { act, render, screen, waitFor } from '@testing-library/react';
|
||||||
import userEvent from '@testing-library/user-event';
|
import userEvent from '@testing-library/user-event';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
@ -86,20 +86,30 @@ describe('SearchField', () => {
|
|||||||
if (select) {
|
if (select) {
|
||||||
// Add first value
|
// Add first value
|
||||||
await user.click(select);
|
await user.click(select);
|
||||||
jest.advanceTimersByTime(1000);
|
await act(async () => {
|
||||||
|
jest.advanceTimersByTime(1000);
|
||||||
|
});
|
||||||
const driverVal = await screen.findByText('driver');
|
const driverVal = await screen.findByText('driver');
|
||||||
await user.click(driverVal);
|
|
||||||
|
await act(async () => {
|
||||||
|
await user.click(driverVal);
|
||||||
|
});
|
||||||
expect(updateFilter).toHaveBeenCalledWith({ ...filter, value: ['driver'] });
|
expect(updateFilter).toHaveBeenCalledWith({ ...filter, value: ['driver'] });
|
||||||
|
|
||||||
// Add a second value
|
// Add a second value
|
||||||
await user.click(select);
|
await user.click(select);
|
||||||
jest.advanceTimersByTime(1000);
|
|
||||||
|
await act(async () => {
|
||||||
|
jest.advanceTimersByTime(1000);
|
||||||
|
});
|
||||||
const customerVal = await screen.findByText('customer');
|
const customerVal = await screen.findByText('customer');
|
||||||
|
|
||||||
await user.click(customerVal);
|
await user.click(customerVal);
|
||||||
expect(updateFilter).toHaveBeenCalledWith({ ...filter, value: ['driver', 'customer'] });
|
expect(updateFilter).toHaveBeenCalledWith({ ...filter, value: ['driver', 'customer'] });
|
||||||
|
|
||||||
// Remove the first value
|
// Remove the first value
|
||||||
const firstValRemove = await screen.findAllByLabelText('Remove');
|
const firstValRemove = await screen.findAllByLabelText('Remove');
|
||||||
|
|
||||||
await user.click(firstValRemove[0]);
|
await user.click(firstValRemove[0]);
|
||||||
expect(updateFilter).toHaveBeenCalledWith({ ...filter, value: ['customer'] });
|
expect(updateFilter).toHaveBeenCalledWith({ ...filter, value: ['customer'] });
|
||||||
}
|
}
|
||||||
|
@ -183,6 +183,12 @@ const SearchField = ({
|
|||||||
/>
|
/>
|
||||||
{!hideValue && (
|
{!hideValue && (
|
||||||
<Select
|
<Select
|
||||||
|
/**
|
||||||
|
* Trace cardinality means we need to use the virtualized variant of the Select component.
|
||||||
|
* For example the number of span names being returned can easily reach 10s of thousands,
|
||||||
|
* which is enough to cause a user's web browser to seize up
|
||||||
|
*/
|
||||||
|
virtualized
|
||||||
className={styles.dropdown}
|
className={styles.dropdown}
|
||||||
inputId={`${filter.id}-value`}
|
inputId={`${filter.id}-value`}
|
||||||
isLoading={isLoadingValues}
|
isLoading={isLoadingValues}
|
||||||
|
@ -114,25 +114,37 @@ describe('TraceQLSearch', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
await user.click(screen.getByText('Select tag'));
|
await user.click(screen.getByText('Select tag'));
|
||||||
jest.advanceTimersByTime(1000);
|
await act(async () => {
|
||||||
|
jest.advanceTimersByTime(1000);
|
||||||
|
});
|
||||||
await user.click(screen.getByText('foo'));
|
await user.click(screen.getByText('foo'));
|
||||||
jest.advanceTimersByTime(1000);
|
await act(async () => {
|
||||||
|
jest.advanceTimersByTime(1000);
|
||||||
|
});
|
||||||
await user.click(screen.getAllByText('Select value')[2]);
|
await user.click(screen.getAllByText('Select value')[2]);
|
||||||
jest.advanceTimersByTime(1000);
|
await act(async () => {
|
||||||
|
jest.advanceTimersByTime(1000);
|
||||||
|
});
|
||||||
await user.click(screen.getByText('driver'));
|
await user.click(screen.getByText('driver'));
|
||||||
jest.advanceTimersByTime(1000);
|
await act(async () => {
|
||||||
|
jest.advanceTimersByTime(1000);
|
||||||
|
});
|
||||||
await act(async () => {
|
await act(async () => {
|
||||||
expect(screen.getAllByLabelText('Add tag').length).toBe(1);
|
expect(screen.getAllByLabelText('Add tag').length).toBe(1);
|
||||||
expect(screen.getAllByLabelText(/Remove tag/).length).toBe(1);
|
expect(screen.getAllByLabelText(/Remove tag/).length).toBe(1);
|
||||||
});
|
});
|
||||||
|
|
||||||
await user.click(screen.getByLabelText('Add tag'));
|
await user.click(screen.getByLabelText('Add tag'));
|
||||||
jest.advanceTimersByTime(1000);
|
await act(async () => {
|
||||||
|
jest.advanceTimersByTime(1000);
|
||||||
|
});
|
||||||
expect(screen.queryAllByLabelText('Add tag').length).toBe(0); // not filled in the new tag, so no need to add another one
|
expect(screen.queryAllByLabelText('Add tag').length).toBe(0); // not filled in the new tag, so no need to add another one
|
||||||
expect(screen.getAllByLabelText(/Remove tag/).length).toBe(2); // one for each tag
|
expect(screen.getAllByLabelText(/Remove tag/).length).toBe(2); // one for each tag
|
||||||
|
|
||||||
await user.click(screen.getAllByLabelText(/Remove tag/)[1]);
|
await user.click(screen.getAllByLabelText(/Remove tag/)[1]);
|
||||||
jest.advanceTimersByTime(1000);
|
await act(async () => {
|
||||||
|
jest.advanceTimersByTime(1000);
|
||||||
|
});
|
||||||
expect(screen.queryAllByLabelText('Add tag').length).toBe(1); // filled in the default tag, so can add another one
|
expect(screen.queryAllByLabelText('Add tag').length).toBe(1); // filled in the default tag, so can add another one
|
||||||
expect(screen.queryAllByLabelText(/Remove tag/).length).toBe(1); // filled in the default tag, so can remove values
|
expect(screen.queryAllByLabelText(/Remove tag/).length).toBe(1); // filled in the default tag, so can remove values
|
||||||
|
|
||||||
@ -155,7 +167,9 @@ describe('TraceQLSearch', () => {
|
|||||||
|
|
||||||
if (minDurationOperator) {
|
if (minDurationOperator) {
|
||||||
await user.click(minDurationOperator);
|
await user.click(minDurationOperator);
|
||||||
jest.advanceTimersByTime(1000);
|
await act(async () => {
|
||||||
|
jest.advanceTimersByTime(1000);
|
||||||
|
});
|
||||||
const regexOp = await screen.findByText('>=');
|
const regexOp = await screen.findByText('>=');
|
||||||
await user.click(regexOp);
|
await user.click(regexOp);
|
||||||
const minDurationFilter = query.filters.find((f) => f.id === 'min-duration');
|
const minDurationFilter = query.filters.find((f) => f.id === 'min-duration');
|
||||||
@ -176,7 +190,9 @@ describe('TraceQLSearch', () => {
|
|||||||
|
|
||||||
if (serviceNameValue) {
|
if (serviceNameValue) {
|
||||||
await user.click(serviceNameValue);
|
await user.click(serviceNameValue);
|
||||||
jest.advanceTimersByTime(1000);
|
await act(async () => {
|
||||||
|
jest.advanceTimersByTime(1000);
|
||||||
|
});
|
||||||
const customerValue = await screen.findByText('customer');
|
const customerValue = await screen.findByText('customer');
|
||||||
await user.click(customerValue);
|
await user.click(customerValue);
|
||||||
const nameFilter = query.filters.find((f) => f.id === 'service-name');
|
const nameFilter = query.filters.find((f) => f.id === 'service-name');
|
||||||
|
@ -10349,7 +10349,6 @@
|
|||||||
"type": "object"
|
"type": "object"
|
||||||
},
|
},
|
||||||
"State": {
|
"State": {
|
||||||
"description": "+enum",
|
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
"Status": {
|
"Status": {
|
||||||
@ -11109,7 +11108,6 @@
|
|||||||
"type": "array"
|
"type": "array"
|
||||||
},
|
},
|
||||||
"Type": {
|
"Type": {
|
||||||
"description": "+enum",
|
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
"TypeMeta": {
|
"TypeMeta": {
|
||||||
|
Loading…
Reference in New Issue
Block a user