From 03ddcdd20ed68365c003f58169e98c9c5e914b19 Mon Sep 17 00:00:00 2001
From: SagarRajput-7 <162284829+SagarRajput-7@users.noreply.github.com>
Date: Wed, 1 May 2024 18:49:04 +0530
Subject: [PATCH] feat: added test cases for pipeline pages (#4872)
* feat: added test cases for pipeline pages
* feat: added test cases for changeHistory
* chore: change history table test case added
* chore: added create pipeline button test cases
* chore: updated useAnalytics mocking
---
.../tests/ChangeHistory.test.tsx | 87 +++++++
.../Layouts/ChangeHistory/tests/testUtils.ts | 240 ++++++++++++++++++
.../tests/CreatePipelineButton.test.tsx | 66 ++++-
.../tests/PipelinesSearchSection.test.tsx | 42 ++-
4 files changed, 433 insertions(+), 2 deletions(-)
create mode 100644 frontend/src/container/PipelinePage/Layouts/ChangeHistory/tests/ChangeHistory.test.tsx
create mode 100644 frontend/src/container/PipelinePage/Layouts/ChangeHistory/tests/testUtils.ts
diff --git a/frontend/src/container/PipelinePage/Layouts/ChangeHistory/tests/ChangeHistory.test.tsx b/frontend/src/container/PipelinePage/Layouts/ChangeHistory/tests/ChangeHistory.test.tsx
new file mode 100644
index 0000000000..194acbea0a
--- /dev/null
+++ b/frontend/src/container/PipelinePage/Layouts/ChangeHistory/tests/ChangeHistory.test.tsx
@@ -0,0 +1,87 @@
+import { render } from '@testing-library/react';
+import { I18nextProvider } from 'react-i18next';
+import { QueryClient, QueryClientProvider } from 'react-query';
+import { Provider } from 'react-redux';
+import { MemoryRouter } from 'react-router-dom';
+import i18n from 'ReactI18';
+import store from 'store';
+
+import ChangeHistory from '../index';
+import { pipelineData, pipelineDataHistory } from './testUtils';
+
+const queryClient = new QueryClient({
+ defaultOptions: {
+ queries: {
+ refetchOnWindowFocus: false,
+ },
+ },
+});
+
+describe('ChangeHistory test', () => {
+ it('should render changeHistory correctly', () => {
+ const { getAllByText, getByText } = render(
+
+
+
+
+
+
+
+
+ ,
+ );
+
+ // change History table headers
+ [
+ 'Version',
+ 'Deployment Stage',
+ 'Last Deploy Message',
+ 'Last Deployed Time',
+ 'Edited by',
+ ].forEach((text) => expect(getByText(text)).toBeInTheDocument());
+
+ // table content
+ expect(getAllByText('test-user').length).toBe(2);
+ expect(getAllByText('Deployment was successful').length).toBe(2);
+ });
+
+ it('test deployment stage and icon based on history data', () => {
+ const { getByText, container } = render(
+
+
+
+
+
+
+
+
+ ,
+ );
+
+ // assertion for different deployment stages
+ expect(container.querySelector('[data-icon="loading"]')).toBeInTheDocument();
+ expect(getByText('In Progress')).toBeInTheDocument();
+
+ expect(
+ container.querySelector('[data-icon="exclamation-circle"]'),
+ ).toBeInTheDocument();
+ expect(getByText('Dirty')).toBeInTheDocument();
+
+ expect(
+ container.querySelector('[data-icon="close-circle"]'),
+ ).toBeInTheDocument();
+ expect(getByText('Failed')).toBeInTheDocument();
+
+ expect(
+ container.querySelector('[data-icon="minus-circle"]'),
+ ).toBeInTheDocument();
+ expect(getByText('Unknown')).toBeInTheDocument();
+
+ expect(container.querySelectorAll('.ant-table-row').length).toBe(5);
+ });
+});
diff --git a/frontend/src/container/PipelinePage/Layouts/ChangeHistory/tests/testUtils.ts b/frontend/src/container/PipelinePage/Layouts/ChangeHistory/tests/testUtils.ts
new file mode 100644
index 0000000000..900cb4f12d
--- /dev/null
+++ b/frontend/src/container/PipelinePage/Layouts/ChangeHistory/tests/testUtils.ts
@@ -0,0 +1,240 @@
+/* eslint-disable sonarjs/no-duplicate-string */
+import { Pipeline } from 'types/api/pipeline/def';
+import { DataTypes } from 'types/api/queryBuilder/queryAutocompleteResponse';
+
+export const pipelineData: Pipeline = {
+ id: 'test-id-1',
+ version: 24,
+ elementType: 'log_pipelines',
+ active: false,
+ is_valid: false,
+ disabled: false,
+ deployStatus: 'DEPLOYED',
+ deployResult: 'Deployment was successful',
+ lastHash: 'log_pipelines:24',
+ lastConf: 'oiwernveroi',
+ createdBy: 'test-created-by',
+ pipelines: [
+ {
+ id: 'test-id-2',
+ orderId: 1,
+ name: 'hotrod logs parser',
+ alias: 'hotrodlogsparser',
+ description: 'Trying to test Logs Pipeline feature',
+ enabled: true,
+ filter: {
+ op: 'AND',
+ items: [
+ {
+ key: {
+ key: 'container_name',
+ dataType: DataTypes.String,
+ type: 'tag',
+ isColumn: false,
+ isJSON: false,
+ },
+ id: 'sampleid',
+ value: 'hotrod',
+ op: '=',
+ },
+ ],
+ },
+ config: [
+ {
+ type: 'regex_parser',
+ id: 'parsetext(regex)',
+ output: 'parseattribsjson',
+ on_error: 'send',
+ orderId: 1,
+ enabled: true,
+ name: 'parse text (regex)',
+ parse_to: 'attributes',
+ regex:
+ '.+\\t+(?P.+)\\t+(?P.+)\\t+(?P.+)\\t+(?P.+)',
+ parse_from: 'body',
+ },
+ {
+ type: 'json_parser',
+ id: 'parseattribsjson',
+ output: 'removetempattribs_json',
+ orderId: 2,
+ enabled: true,
+ name: 'parse attribs json',
+ parse_to: 'attributes',
+ parse_from: 'attributes.attribs_json',
+ },
+ {
+ type: 'remove',
+ id: 'removetempattribs_json',
+ output: 'c2062723-895e-4614-ba38-29c5d5ee5927',
+ orderId: 3,
+ enabled: true,
+ name: 'remove temp attribs_json',
+ field: 'attributes.attribs_json',
+ },
+ {
+ type: 'add',
+ id: 'c2062723-895e-4614-ba38-29c5d5ee5927',
+ orderId: 4,
+ enabled: true,
+ name: 'test add ',
+ field: 'resource["container.name"]',
+ value: 'hotrod',
+ },
+ ],
+ createdBy: 'test@email',
+ createdAt: '2024-01-02T13:56:02.858300964Z',
+ },
+ {
+ id: 'tes-id-1',
+ orderId: 2,
+ name: 'Logs Parser - test - Customer Service',
+ alias: 'LogsParser-test-CustomerService',
+ description: 'Trying to test Logs Pipeline feature',
+ enabled: true,
+ filter: {
+ op: 'AND',
+ items: [
+ {
+ key: {
+ key: 'service',
+ dataType: DataTypes.String,
+ type: 'tag',
+ isColumn: false,
+ isJSON: false,
+ },
+ id: 'sample-test-1',
+ value: 'customer',
+ op: '=',
+ },
+ ],
+ },
+ config: [
+ {
+ type: 'grok_parser',
+ id: 'Testtest',
+ on_error: 'send',
+ orderId: 1,
+ enabled: true,
+ name: 'Test test',
+ parse_to: 'attributes',
+ pattern:
+ '^%{DATE:date}Z INFO customer/database.go:73 Loading customer {"service": "customer", "component": "mysql", "trace_id": "test-id", "span_id": "1427a3fcad8b1514", "customer_id": "567"}',
+ parse_from: 'body',
+ },
+ ],
+ createdBy: 'test@email',
+ createdAt: '2024-01-02T13:56:02.863764227Z',
+ },
+ ],
+ history: [
+ {
+ id: 'test-id-4',
+ version: 24,
+ elementType: 'log_pipelines',
+ active: false,
+ isValid: false,
+ disabled: false,
+ deployStatus: 'DEPLOYED',
+ deployResult: 'Deployment was successful',
+ lastHash: 'log_pipelines:24',
+ lastConf: 'eovineroiv',
+ createdBy: 'test-created-by',
+ createdByName: 'test-user',
+ createdAt: '2024-01-02T13:56:02Z',
+ },
+ {
+ id: 'test-4',
+ version: 23,
+ elementType: 'log_pipelines',
+ active: false,
+ isValid: false,
+ disabled: false,
+ deployStatus: 'DEPLOYED',
+ deployResult: 'Deployment was successful',
+ lastHash: 'log_pipelines:23',
+ lastConf: 'eivrounreovi',
+ createdBy: 'test-created-by',
+ createdByName: 'test-user',
+ createdAt: '2023-12-29T12:59:20Z',
+ },
+ ],
+};
+
+export const pipelineDataHistory: Pipeline['history'] = [
+ {
+ id: 'test-id-4',
+ version: 24,
+ elementType: 'log_pipelines',
+ active: false,
+ isValid: false,
+ disabled: false,
+ deployStatus: 'DEPLOYED',
+ deployResult: 'Deployment was successful',
+ lastHash: 'log_pipelines:24',
+ lastConf: 'eovineroiv',
+ createdBy: 'test-created-by',
+ createdByName: 'test-user',
+ createdAt: '2024-01-02T13:56:02Z',
+ },
+ {
+ id: 'test-4',
+ version: 23,
+ elementType: 'log_pipelines',
+ active: false,
+ isValid: false,
+ disabled: false,
+ deployStatus: 'IN_PROGRESS',
+ deployResult: 'Deployment is in progress',
+ lastHash: 'log_pipelines:23',
+ lastConf: 'eivrounreovi',
+ createdBy: 'test-created-by',
+ createdByName: 'test-user',
+ createdAt: '2023-12-29T12:59:20Z',
+ },
+ {
+ id: 'test-4-1',
+ version: 25,
+ elementType: 'log_pipelines',
+ active: false,
+ isValid: false,
+ disabled: false,
+ deployStatus: 'DIRTY',
+ deployResult: 'Deployment is dirty',
+ lastHash: 'log_pipelines:23',
+ lastConf: 'eivrounreovi',
+ createdBy: 'test-created-by',
+ createdByName: 'test-user',
+ createdAt: '2023-12-29T12:59:20Z',
+ },
+ {
+ id: 'test-4-2',
+ version: 26,
+ elementType: 'log_pipelines',
+ active: false,
+ isValid: false,
+ disabled: false,
+ deployStatus: 'FAILED',
+ deployResult: 'Deployment failed',
+ lastHash: 'log_pipelines:23',
+ lastConf: 'eivrounreovi',
+ createdBy: 'test-created-by',
+ createdByName: 'test-user',
+ createdAt: '2023-12-29T12:59:20Z',
+ },
+ {
+ id: 'test-4-3',
+ version: 27,
+ elementType: 'log_pipelines',
+ active: false,
+ isValid: false,
+ disabled: false,
+ deployStatus: 'UNKNOWN',
+ deployResult: '',
+ lastHash: 'log_pipelines:23',
+ lastConf: 'eivrounreovi',
+ createdBy: 'test-created-by',
+ createdByName: 'test-user',
+ createdAt: '2023-12-29T12:59:20Z',
+ },
+];
diff --git a/frontend/src/container/PipelinePage/tests/CreatePipelineButton.test.tsx b/frontend/src/container/PipelinePage/tests/CreatePipelineButton.test.tsx
index fd9d546db7..49d0a132ea 100644
--- a/frontend/src/container/PipelinePage/tests/CreatePipelineButton.test.tsx
+++ b/frontend/src/container/PipelinePage/tests/CreatePipelineButton.test.tsx
@@ -1,4 +1,5 @@
import { render } from '@testing-library/react';
+import userEvent from '@testing-library/user-event';
import { I18nextProvider } from 'react-i18next';
import { Provider } from 'react-redux';
import { MemoryRouter } from 'react-router-dom';
@@ -8,8 +9,17 @@ import store from 'store';
import CreatePipelineButton from '../Layouts/Pipeline/CreatePipelineButton';
import { pipelineApiResponseMockData } from '../mocks/pipeline';
+const trackEventVar = jest.fn();
+jest.mock('hooks/analytics/useAnalytics', () => ({
+ __esModule: true,
+ default: jest.fn().mockImplementation(() => ({
+ trackEvent: trackEventVar,
+ trackPageView: jest.fn(),
+ })),
+}));
+
describe('PipelinePage container test', () => {
- it('should render CreatePipelineButton section', () => {
+ it('should render CreatePipelineButton section', async () => {
const { asFragment } = render(
@@ -26,4 +36,58 @@ describe('PipelinePage container test', () => {
);
expect(asFragment()).toMatchSnapshot();
});
+
+ it('CreatePipelineButton - edit mode & tracking', async () => {
+ const { getByText } = render(
+
+
+
+
+
+
+ ,
+ );
+
+ // enter_edit_mode click and track event data
+ const editButton = getByText('enter_edit_mode');
+ expect(editButton).toBeInTheDocument();
+ await userEvent.click(editButton);
+
+ expect(trackEventVar).toBeCalledWith('Logs: Pipelines: Entered Edit Mode', {
+ source: 'signoz-ui',
+ });
+ });
+
+ it('CreatePipelineButton - add new mode & tracking', async () => {
+ const { getByText } = render(
+
+
+
+
+
+
+ ,
+ );
+ // new_pipeline click and track event data
+ const editButton = getByText('new_pipeline');
+ expect(editButton).toBeInTheDocument();
+ await userEvent.click(editButton);
+
+ expect(trackEventVar).toBeCalledWith(
+ 'Logs: Pipelines: Clicked Add New Pipeline',
+ {
+ source: 'signoz-ui',
+ },
+ );
+ });
});
diff --git a/frontend/src/container/PipelinePage/tests/PipelinesSearchSection.test.tsx b/frontend/src/container/PipelinePage/tests/PipelinesSearchSection.test.tsx
index 10627e3a18..bfe69adcd1 100644
--- a/frontend/src/container/PipelinePage/tests/PipelinesSearchSection.test.tsx
+++ b/frontend/src/container/PipelinePage/tests/PipelinesSearchSection.test.tsx
@@ -1,4 +1,5 @@
-import { render } from '@testing-library/react';
+import { fireEvent, render, waitFor } from '@testing-library/react';
+import userEvent from '@testing-library/user-event';
import { I18nextProvider } from 'react-i18next';
import { Provider } from 'react-redux';
import { MemoryRouter } from 'react-router-dom';
@@ -20,4 +21,43 @@ describe('PipelinePage container test', () => {
);
expect(asFragment()).toMatchSnapshot();
});
+
+ it('should handle search', async () => {
+ const setPipelineValue = jest.fn();
+ const { getByPlaceholderText, container } = render(
+
+
+
+
+
+
+ ,
+ );
+
+ const searchInput = getByPlaceholderText('search_pipeline_placeholder');
+
+ // Type into the search input
+ userEvent.type(searchInput, 'sample_pipeline');
+
+ jest.advanceTimersByTime(299);
+ expect(setPipelineValue).not.toHaveBeenCalled();
+
+ // Wait for the debounce delay to pass
+ await waitFor(() => {
+ // Expect the callback to be called after debounce delay
+ expect(setPipelineValue).toHaveBeenCalledWith('sample_pipeline');
+ });
+
+ // clear button
+ fireEvent.click(
+ container.querySelector(
+ 'span[class*="ant-input-clear-icon"]',
+ ) as HTMLElement,
+ );
+
+ // Wait for the debounce delay to pass
+ await waitFor(() => {
+ expect(setPipelineValue).toHaveBeenCalledWith('');
+ });
+ });
});