From 32619869e74b2b0a1bc3cb5867d60b9dcb358d83 Mon Sep 17 00:00:00 2001 From: Aditya Singh Date: Fri, 30 Jan 2026 15:59:09 +0530 Subject: [PATCH] Show both tag/resource variants for identical keys in pipeline filter options (#10150) * feat: show multiple labels with differing tags and types in filter options * feat: test fix --- .../tests/PipelineListsView.test.tsx | 75 ++++++++++++++++++- .../filters/QueryBuilderSearch/index.tsx | 11 ++- frontend/src/hooks/queryBuilder/useOptions.ts | 6 +- 3 files changed, 87 insertions(+), 5 deletions(-) diff --git a/frontend/src/container/PipelinePage/tests/PipelineListsView.test.tsx b/frontend/src/container/PipelinePage/tests/PipelineListsView.test.tsx index 43884893af..23a5d7f993 100644 --- a/frontend/src/container/PipelinePage/tests/PipelineListsView.test.tsx +++ b/frontend/src/container/PipelinePage/tests/PipelineListsView.test.tsx @@ -1,7 +1,17 @@ /* eslint-disable sonarjs/no-duplicate-string */ -import { screen } from '@testing-library/react'; +import { screen, within } from '@testing-library/react'; +import { ENVIRONMENT } from 'constants/env'; +import { server } from 'mocks-server/server'; +import { rest } from 'msw'; import { PreferenceContextProvider } from 'providers/preferences/context/PreferenceContextProvider'; -import { findByText, fireEvent, render, waitFor } from 'tests/test-utils'; +import { + findByText, + fireEvent, + render, + userEvent, + waitFor, +} from 'tests/test-utils'; +import { DataTypes } from 'types/api/queryBuilder/queryAutocompleteResponse'; import { pipelineApiResponseMockData } from '../mocks/pipeline'; import PipelineListsView from '../PipelineListsView'; @@ -75,7 +85,20 @@ jest.mock('providers/preferences/sync/usePreferenceSync', () => ({ }), })); +const BASE_URL = ENVIRONMENT.baseURL; +const attributeKeysURL = `${BASE_URL}/api/v3/autocomplete/attribute_keys`; + describe('PipelinePage container test', () => { + beforeAll(() => { + server.listen(); + }); + afterEach(() => { + server.resetHandlers(); + jest.clearAllMocks(); + }); + afterAll(() => { + server.close(); + }); it('should render PipelineListsView section', () => { const { getByText, container } = render( @@ -272,6 +295,7 @@ describe('PipelinePage container test', () => { }); it('should have populated form fields when edit pipeline is clicked', async () => { + const user = userEvent.setup({ pointerEventsCheck: 0 }); render( { // to have length 2 expect(screen.queryAllByText('source = nginx').length).toBe(2); + + server.use( + rest.get(attributeKeysURL, (_req, res, ctx) => + res( + ctx.status(200), + ctx.json({ + status: 'success', + data: { + attributeKeys: [ + { + key: 'otelServiceName', + dataType: DataTypes.String, + type: 'tag', + }, + { + key: 'service.instance.id', + dataType: DataTypes.String, + type: 'resource', + }, + { + key: 'service.name', + dataType: DataTypes.String, + type: 'resource', + }, + { + key: 'service.name', + dataType: DataTypes.String, + type: 'tag', + }, + ], + }, + }), + ), + ), + ); + + // Open Filter input and type to trigger suggestions + const filterSelect = screen.getByTestId('qb-search-select'); + const input = within(filterSelect).getByRole('combobox') as HTMLInputElement; + + await user.click(input); + await waitFor(() => + expect(screen.getByText('otelServiceName')).toBeInTheDocument(), + ); + + const serviceNameOccurences = await screen.findAllByText('service.name'); + expect(serviceNameOccurences.length).toBeGreaterThanOrEqual(2); }); }); diff --git a/frontend/src/container/QueryBuilder/filters/QueryBuilderSearch/index.tsx b/frontend/src/container/QueryBuilder/filters/QueryBuilderSearch/index.tsx index 14a08be174..f92a2e7467 100644 --- a/frontend/src/container/QueryBuilder/filters/QueryBuilderSearch/index.tsx +++ b/frontend/src/container/QueryBuilder/filters/QueryBuilderSearch/index.tsx @@ -356,7 +356,10 @@ function QueryBuilderSearch({ // conditional changes here to use a seperate component to render the example queries based on the option group label const customRendererForLogsExplorer = options.map((option) => ( - +