From 0659e02f6fc66792b5ad4bc49a360fd826a146dc Mon Sep 17 00:00:00 2001
From: Harsh Vador <58542468+harsh-vador@users.noreply.github.com>
Date: Tue, 6 Feb 2024 19:32:30 +0530
Subject: [PATCH] Add unit test cases (#14981)
* unit test case of welcome screen & recently viewed
* add team type select unit test
* add unit test case for resizable panels
* add unit test case for Panel Container
* unit test case for CmdKIcon
* add unit test case for feed filter popover
* add unit test fir feeds widget
* add unit test case for form builder
* add unit test case for form builder
* add unit test case of teams heading label
* unit test case of teams info
* unit test case of teams subscription
* unit test case of add data quality test page
* unit test of add ingestion page
* code refactor
---
.../TeamsHeadingLabel.test.tsx | 123 ++++++++++++++
.../TeamsHeaderSection/TeamsInfo.test.tsx | 142 ++++++++++++++++
.../TeamsSubscription.test.tsx | 81 ++++++++++
.../WelcomeScreen/WelcomScreen.test.tsx | 60 +++++++
.../Widgets/FeedsWidget/FeedsWidget.test.tsx | 152 ++++++++++++++++++
.../RecentlyViewed/RecentlyViewed.test.tsx | 92 +++++++++++
.../common/CmdKIcon/CmdKIcon.component.tsx | 5 +-
.../common/CmdKIcon/CmdKIcon.test.tsx | 48 ++++++
.../FeedsFilterPopover.component.tsx | 6 +-
.../FeedsFilterPopover.test.tsx | 91 +++++++++++
.../common/FormBuilder/FormBuilder.test.tsx | 121 ++++++++++++++
.../common/FormBuilder/FormBuilder.tsx | 2 +-
.../PanelContainer/PanelContainer.test.tsx | 72 +++++++++
.../PanelContainer/PanelContainer.tsx | 4 +-
.../ResizablePanels/ResizablePanels.tsx | 2 +
.../ResizablePanels/ResziablePanels.test.tsx | 94 +++++++++++
.../TeamTypeSelect/TeamTypeSelect.test.tsx | 59 +++++++
.../AddDataQualityTestPage.test.tsx | 83 ++++++++++
.../AddDataQualityTestPage.tsx | 2 +-
.../AddIngestionPage.test.tsx | 136 ++++++++++++++++
20 files changed, 1370 insertions(+), 5 deletions(-)
create mode 100644 openmetadata-ui/src/main/resources/ui/src/components/Team/TeamDetails/TeamsHeaderSection/TeamsHeadingLabel.test.tsx
create mode 100644 openmetadata-ui/src/main/resources/ui/src/components/Team/TeamDetails/TeamsHeaderSection/TeamsInfo.test.tsx
create mode 100644 openmetadata-ui/src/main/resources/ui/src/components/Team/TeamDetails/TeamsHeaderSection/TeamsSubscription.test.tsx
create mode 100644 openmetadata-ui/src/main/resources/ui/src/components/WelcomeScreen/WelcomScreen.test.tsx
create mode 100644 openmetadata-ui/src/main/resources/ui/src/components/Widgets/FeedsWidget/FeedsWidget.test.tsx
create mode 100644 openmetadata-ui/src/main/resources/ui/src/components/Widgets/RecentlyViewed/RecentlyViewed.test.tsx
create mode 100644 openmetadata-ui/src/main/resources/ui/src/components/common/CmdKIcon/CmdKIcon.test.tsx
create mode 100644 openmetadata-ui/src/main/resources/ui/src/components/common/FeedsFilterPopover/FeedsFilterPopover.test.tsx
create mode 100644 openmetadata-ui/src/main/resources/ui/src/components/common/FormBuilder/FormBuilder.test.tsx
create mode 100644 openmetadata-ui/src/main/resources/ui/src/components/common/ResizablePanels/PanelContainer/PanelContainer.test.tsx
create mode 100644 openmetadata-ui/src/main/resources/ui/src/components/common/ResizablePanels/ResziablePanels.test.tsx
create mode 100644 openmetadata-ui/src/main/resources/ui/src/components/common/TeamTypeSelect/TeamTypeSelect.test.tsx
create mode 100644 openmetadata-ui/src/main/resources/ui/src/pages/AddDataQualityTestPage/AddDataQualityTestPage.test.tsx
create mode 100644 openmetadata-ui/src/main/resources/ui/src/pages/AddIngestionPage/AddIngestionPage.test.tsx
diff --git a/openmetadata-ui/src/main/resources/ui/src/components/Team/TeamDetails/TeamsHeaderSection/TeamsHeadingLabel.test.tsx b/openmetadata-ui/src/main/resources/ui/src/components/Team/TeamDetails/TeamsHeaderSection/TeamsHeadingLabel.test.tsx
new file mode 100644
index 00000000000..a6773cc90b5
--- /dev/null
+++ b/openmetadata-ui/src/main/resources/ui/src/components/Team/TeamDetails/TeamsHeaderSection/TeamsHeadingLabel.test.tsx
@@ -0,0 +1,123 @@
+/*
+ * Copyright 2024 Collate.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+import { act, fireEvent, render, screen } from '@testing-library/react';
+import userEvent from '@testing-library/user-event';
+import React from 'react';
+import { TeamType } from '../../../../generated/entity/teams/team';
+import { useAuth } from '../../../../hooks/authHooks';
+import { ENTITY_PERMISSIONS } from '../../../../mocks/Permissions.mock';
+import TeamsHeadingLabel from './TeamsHeadingLabel.component';
+
+jest.mock('../../../../hooks/authHooks', () => ({
+ useAuth: jest.fn().mockReturnValue({ isAdminUser: true }),
+}));
+
+jest.mock('../../../Auth/AuthProviders/AuthProvider', () => ({
+ useAuthContext: jest.fn().mockReturnValue({
+ currentUser: { userId: 'test-user' },
+ }),
+}));
+const mockUpdateTeamHandler = jest.fn();
+
+const teamProps = {
+ currentTeam: {
+ changeDescription: {},
+ children: [],
+ childrenCount: 0,
+ defaultRoles: [],
+ deleted: false,
+ description: 'Test team description',
+ displayName: 'Test Team',
+ domain: { id: 'test-domain', type: 'domain' },
+ email: 'test-team@test.com',
+ fullyQualifiedName: 'test-team',
+ href: '/test-team',
+ id: 'test-team',
+ inheritedRoles: [],
+ isJoinable: true,
+ name: 'test-team',
+ owner: { id: 'test-user', type: 'user' },
+ owns: [],
+ parents: [],
+ policies: [],
+ profile: {},
+ teamType: TeamType.Organization,
+ updatedAt: Date.now(),
+ updatedBy: 'test-user',
+ userCount: 1,
+ users: [{ id: 'test-user', type: 'user' }],
+ version: 1,
+ },
+ updateTeamHandler: mockUpdateTeamHandler,
+ entityPermissions: ENTITY_PERMISSIONS,
+};
+
+describe('TeamsHeadingLabel', () => {
+ it('should render Teams Heading Label', async () => {
+ await act(async () => {
+ render( );
+ });
+ const teamHeading = screen.getByTestId('team-heading');
+
+ expect(teamHeading).toHaveTextContent('Test Team');
+ });
+
+ it('should handle edit team name', () => {
+ const { getByTestId } = render( );
+ const editButton = getByTestId('edit-team-name');
+ fireEvent.click(editButton);
+ const teamNameInput = getByTestId('team-name-input');
+
+ expect(teamNameInput).toBeInTheDocument();
+ });
+
+ it('should handle save team name', async () => {
+ const { getByTestId } = render( );
+ const editButton = getByTestId('edit-team-name');
+ await act(async () => {
+ userEvent.click(editButton);
+ });
+
+ const saveButton = getByTestId('saveAssociatedTag');
+ await act(async () => {
+ userEvent.click(saveButton);
+ });
+
+ expect(mockUpdateTeamHandler).toHaveBeenCalled();
+ });
+
+ it('should handle cancel team name edit', async () => {
+ const { getByTestId, queryByTestId } = render(
+
+ );
+ const editButton = getByTestId('edit-team-name');
+ await act(async () => {
+ userEvent.click(editButton);
+ });
+
+ const cancelButton = getByTestId('cancelAssociatedTag');
+ await act(async () => {
+ userEvent.click(cancelButton);
+ });
+
+ expect(queryByTestId('team-name-input')).not.toBeInTheDocument();
+ });
+
+ it('should not allow editing team name if user does not have permission', () => {
+ (useAuth as jest.Mock).mockReturnValue({ isAdminUser: false });
+ const { queryByTestId } = render( );
+ const editButton = queryByTestId('edit-team-name');
+
+ expect(editButton).not.toBeInTheDocument();
+ });
+});
diff --git a/openmetadata-ui/src/main/resources/ui/src/components/Team/TeamDetails/TeamsHeaderSection/TeamsInfo.test.tsx b/openmetadata-ui/src/main/resources/ui/src/components/Team/TeamDetails/TeamsHeaderSection/TeamsInfo.test.tsx
new file mode 100644
index 00000000000..95e799f8ed0
--- /dev/null
+++ b/openmetadata-ui/src/main/resources/ui/src/components/Team/TeamDetails/TeamsHeaderSection/TeamsInfo.test.tsx
@@ -0,0 +1,142 @@
+/*
+ * Copyright 2024 Collate.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+import { act, fireEvent, render, screen } from '@testing-library/react';
+import React from 'react';
+import { TeamType } from '../../../../generated/entity/teams/team';
+import { useAuth } from '../../../../hooks/authHooks';
+import { ENTITY_PERMISSIONS } from '../../../../mocks/Permissions.mock';
+import TeamsInfo from './TeamsInfo.component';
+
+const mockTeam = {
+ changeDescription: {},
+ children: [],
+ childrenCount: 0,
+ defaultRoles: [],
+ deleted: false,
+ description: 'Test team description',
+ displayName: 'Test Team',
+ domain: { id: 'test-domain', type: 'domain' },
+ email: 'test-team@test.com',
+ fullyQualifiedName: 'test-team',
+ href: '/test-team',
+ id: 'test-team',
+ inheritedRoles: [],
+ isJoinable: true,
+ name: 'test-team',
+ owner: { id: 'test-user', type: 'user' },
+ owns: [],
+ parents: [],
+ policies: [],
+ profile: {},
+ teamType: TeamType.Organization,
+ updatedAt: Date.now(),
+ updatedBy: 'test-user',
+ userCount: 1,
+ users: [{ id: 'test-user', type: 'user' }],
+ version: 1,
+};
+
+jest.mock('../../../../hooks/authHooks', () => ({
+ useAuth: jest.fn().mockReturnValue({ isAdminUser: true }),
+}));
+
+jest.mock('../../../common/OwnerLabel/OwnerLabel.component', () => ({
+ OwnerLabel: jest.fn().mockImplementation(() =>
OwnerLabel
),
+}));
+
+jest.mock('../../../common/DomainLabel/DomainLabel.component', () => ({
+ DomainLabel: jest.fn().mockImplementation(() => DomainLabel
),
+}));
+
+jest.mock('./TeamsSubscription.component', () => ({
+ __esModule: true,
+ default: jest.fn().mockImplementation(() => TeamsSubscription
),
+}));
+
+jest.mock('../../../common/TeamTypeSelect/TeamTypeSelect.component', () => ({
+ __esModule: true,
+ default: jest.fn().mockImplementation(() => TeamTypeSelect
),
+}));
+
+jest.mock('../../../Auth/AuthProviders/AuthProvider', () => ({
+ useAuthContext: jest.fn().mockReturnValue({
+ currentUser: { id: 'test-user' },
+ }),
+}));
+
+const mockEntityPermissions = { ...ENTITY_PERMISSIONS };
+
+const mockUpdateTeamHandler = jest.fn();
+const teamProps = {
+ parentTeams: [],
+ isGroupType: false,
+ childTeamsCount: 0,
+ currentTeam: mockTeam,
+ entityPermissions: mockEntityPermissions,
+ isTeamDeleted: false,
+ updateTeamHandler: mockUpdateTeamHandler,
+};
+
+describe('TeamsInfo', () => {
+ it('should render TeamsInfo', async () => {
+ await act(async () => {
+ render( );
+ });
+ const domainLabel = screen.getByText('DomainLabel');
+
+ expect(domainLabel).toBeInTheDocument();
+ });
+
+ it('should handle edit team email', () => {
+ const { getByTestId } = render( );
+ const editButton = getByTestId('edit-email');
+ fireEvent.click(editButton);
+ const teamEmailInput = getByTestId('email-input');
+
+ expect(teamEmailInput).toBeInTheDocument();
+ });
+
+ it('should handle save team email', async () => {
+ const { getByTestId } = render( );
+ const editButton = getByTestId('edit-email');
+ fireEvent.click(editButton);
+ const saveButton = getByTestId('save-edit-email');
+ await act(async () => {
+ fireEvent.click(saveButton);
+ });
+
+ expect(mockUpdateTeamHandler).toHaveBeenCalled();
+ });
+
+ it('should handle cancel team email edit', async () => {
+ const { getByTestId } = render( );
+ const editButton = getByTestId('edit-email');
+ fireEvent.click(editButton);
+ const cancelButton = getByTestId('cancel-edit-email');
+ await act(async () => {
+ fireEvent.click(cancelButton);
+ });
+
+ expect(screen.queryByTestId('email-input')).not.toBeInTheDocument();
+ });
+
+ it('should not show edit button if user does not have permission', () => {
+ (useAuth as jest.Mock).mockReturnValue({ isAdminUser: false });
+
+ mockEntityPermissions.EditAll = false;
+ const { queryByTestId } = render( );
+ const ownerLabel = queryByTestId('edit-email');
+
+ expect(ownerLabel).not.toBeInTheDocument();
+ });
+});
diff --git a/openmetadata-ui/src/main/resources/ui/src/components/Team/TeamDetails/TeamsHeaderSection/TeamsSubscription.test.tsx b/openmetadata-ui/src/main/resources/ui/src/components/Team/TeamDetails/TeamsHeaderSection/TeamsSubscription.test.tsx
new file mode 100644
index 00000000000..f5ea5527ae6
--- /dev/null
+++ b/openmetadata-ui/src/main/resources/ui/src/components/Team/TeamDetails/TeamsHeaderSection/TeamsSubscription.test.tsx
@@ -0,0 +1,81 @@
+/*
+ * Copyright 2024 Collate.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+import { act, fireEvent, render, screen } from '@testing-library/react';
+import React from 'react';
+import TeamsSubscription from './TeamsSubscription.component';
+
+describe('TeamsSubscription', () => {
+ const mockUpdateTeamSubscription = jest.fn();
+
+ const teamProps = {
+ hasEditPermission: true,
+ updateTeamSubscription: mockUpdateTeamSubscription,
+ };
+
+ it('renders Teams Subscription', async () => {
+ await act(async () => {
+ render( );
+ });
+ const subscription = screen.getByTestId('teams-subscription');
+
+ expect(subscription).toBeInTheDocument();
+ });
+
+ it('should handle edit team subscription', () => {
+ const { getByTestId } = render( );
+ const editButton = getByTestId('edit-team-subscription');
+ fireEvent.click(editButton);
+ const subscriptionModal = getByTestId('subscription-modal');
+
+ expect(subscriptionModal).toBeInTheDocument();
+ });
+
+ it('should handle save team subscription', async () => {
+ const { getByTestId, getByText } = render(
+
+ );
+ const editButton = getByTestId('edit-team-subscription');
+ await act(async () => {
+ fireEvent.click(editButton);
+ });
+ const saveButton = getByText('label.confirm');
+ await act(async () => {
+ fireEvent.click(saveButton);
+ });
+
+ expect(mockUpdateTeamSubscription).toHaveBeenCalled();
+ });
+
+ it('should render no data when no subscription', async () => {
+ const { getByTestId } = render( );
+ const noData = getByTestId('subscription-no-data');
+
+ expect(noData).toBeInTheDocument();
+ });
+
+ it('should not render subscriptionRenderElement when no edit permission', async () => {
+ teamProps.hasEditPermission = false;
+
+ const { queryByTestId } = render(
+
+ );
+ const noData = queryByTestId('subscription-no-data');
+
+ expect(noData).not.toBeInTheDocument();
+ });
+});
diff --git a/openmetadata-ui/src/main/resources/ui/src/components/WelcomeScreen/WelcomScreen.test.tsx b/openmetadata-ui/src/main/resources/ui/src/components/WelcomeScreen/WelcomScreen.test.tsx
new file mode 100644
index 00000000000..606abb88782
--- /dev/null
+++ b/openmetadata-ui/src/main/resources/ui/src/components/WelcomeScreen/WelcomScreen.test.tsx
@@ -0,0 +1,60 @@
+/*
+ * Copyright 2024 Collate.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+import { act, fireEvent, render, screen } from '@testing-library/react';
+import React from 'react';
+import { MemoryRouter } from 'react-router-dom';
+import WelcomeScreen from './WelcomeScreen.component';
+
+const mockProps = {
+ onCloseMock: jest.fn(),
+};
+
+describe('WelcomeScreen', () => {
+ it('should render WelcomeScreen', async () => {
+ await act(async () => {
+ render( , {
+ wrapper: MemoryRouter,
+ });
+ });
+ const welcomeImg = screen.getByTestId('welcome-screen-img');
+
+ expect(welcomeImg).toBeInTheDocument();
+ });
+
+ it('should call onClose when the close button is clicked', () => {
+ const { getByTestId } = render(
+ ,
+ {
+ wrapper: MemoryRouter,
+ }
+ );
+
+ const closeButton = getByTestId('welcome-screen-close-btn');
+ fireEvent.click(closeButton);
+
+ expect(mockProps.onCloseMock).toHaveBeenCalled();
+ });
+
+ it('should display the correct welcome message', () => {
+ const { getByText } = render(
+ ,
+ {
+ wrapper: MemoryRouter,
+ }
+ );
+
+ const welcomeMessage = getByText('message.welcome-screen-message');
+
+ expect(welcomeMessage).toBeInTheDocument();
+ });
+});
diff --git a/openmetadata-ui/src/main/resources/ui/src/components/Widgets/FeedsWidget/FeedsWidget.test.tsx b/openmetadata-ui/src/main/resources/ui/src/components/Widgets/FeedsWidget/FeedsWidget.test.tsx
new file mode 100644
index 00000000000..168332b7575
--- /dev/null
+++ b/openmetadata-ui/src/main/resources/ui/src/components/Widgets/FeedsWidget/FeedsWidget.test.tsx
@@ -0,0 +1,152 @@
+/*
+ * Copyright 2024 Collate.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+import { act, fireEvent, render, screen } from '@testing-library/react';
+import React from 'react';
+import FeedsWidget from './FeedsWidget.component';
+
+const mockHandleRemoveWidget = jest.fn();
+
+const mockThread = [
+ {
+ id: '33873393-bd68-46e9-bccc-7701c1c41ad6',
+ type: 'Task',
+ threadTs: 1703570590556,
+ about: 'test',
+ entityId: '6206a003-281c-4984-9728-4e949a4e4023',
+ posts: [
+ {
+ id: '12345',
+ message: 'Resolved the Task.',
+ postTs: 1703570590652,
+ from: 'admin',
+ reactions: [],
+ },
+ ],
+ task: {
+ id: 6,
+ type: 'RequestTestCaseFailureResolution',
+ assignees: [
+ {
+ id: '2345rt',
+ type: 'user',
+ name: 'aaron_johnson0',
+ fullyQualifiedName: 'aaron_johnson0',
+ displayName: 'Aaron Johnson',
+ deleted: false,
+ },
+ ],
+ status: 'Closed',
+ closedBy: 'admin',
+ closedAt: 1703570590648,
+ newValue: 'Resolution comment',
+ testCaseResolutionStatusId: 'f93d08e9-2d38-4d01-a294-f8b44fbb0f4a',
+ },
+ },
+];
+
+const mockUseActivityFeedProviderValue = {
+ entityPaging: { total: 4 },
+ entityThread: mockThread,
+ getFeedData: jest.fn().mockImplementation(() => Promise.resolve()),
+ loading: false,
+ selectedThread: mockThread[0],
+ setActiveThread: jest.fn(),
+};
+
+const widgetProps = {
+ selectedGridSize: 10,
+ isEditView: true,
+ widgetKey: 'testWidgetKey',
+ handleRemoveWidget: mockHandleRemoveWidget,
+};
+
+const tabs = ['All', 'Mentions', 'Tasks'];
+
+jest.mock(
+ '../../../components/ActivityFeed/ActivityFeedList/ActivityFeedListV1.component',
+ () => jest.fn().mockImplementation(({ children }) => {children}
)
+);
+
+jest.mock('../../common/FeedsFilterPopover/FeedsFilterPopover.component', () =>
+ jest.fn().mockImplementation(({ children }) => {children}
)
+);
+
+jest.mock('../../../rest/feedsAPI', () => ({
+ getFeedsWithFilter: jest.fn().mockReturnValue(Promise.resolve(mockThread)),
+}));
+
+jest.mock('../../../utils/CommonUtils', () => ({
+ getCountBadge: jest.fn(),
+ getEntityDetailLink: jest.fn(),
+ Transi18next: jest.fn(),
+}));
+
+jest.mock('quilljs-markdown', () => {
+ class MockQuillMarkdown {
+ constructor() {
+ // eslint-disable-next-line no-console
+ console.log('Markdown constructor');
+ }
+ }
+
+ const instance = new MockQuillMarkdown();
+
+ return instance;
+});
+
+jest.mock(
+ '../../../components/ActivityFeed/ActivityFeedProvider/ActivityFeedProvider',
+ () => ({
+ useActivityFeedProvider: jest
+ .fn()
+ .mockImplementation(() => mockUseActivityFeedProviderValue),
+ })
+);
+
+describe('FeedsWidget', () => {
+ it('should render FeedsWidget', async () => {
+ await act(async () => {
+ render( );
+ });
+ const activityFeedWidget = screen.getByTestId('activity-feed-widget');
+
+ expect(activityFeedWidget).toBeInTheDocument();
+ });
+
+ it('should render All tab by default', () => {
+ const { getAllByRole } = render( );
+ const tabs = getAllByRole('tab');
+ const allTab = tabs[0];
+
+ expect(allTab).toHaveAttribute('aria-selected', 'true');
+ });
+
+ tabs.map((tab, index) => {
+ it(`should select ${tab} tab`, () => {
+ const { getAllByRole } = render( );
+ const tabs = getAllByRole('tab');
+ const selectedTab = tabs[index];
+ selectedTab.click();
+
+ expect(selectedTab.getAttribute('aria-selected')).toBe('true');
+ });
+ });
+
+ it('should handle close click when in edit view', () => {
+ const { getByTestId } = render( );
+ const closeButton = getByTestId('remove-widget-button');
+ fireEvent.click(closeButton);
+
+ expect(mockHandleRemoveWidget).toHaveBeenCalledWith(widgetProps.widgetKey);
+ });
+});
diff --git a/openmetadata-ui/src/main/resources/ui/src/components/Widgets/RecentlyViewed/RecentlyViewed.test.tsx b/openmetadata-ui/src/main/resources/ui/src/components/Widgets/RecentlyViewed/RecentlyViewed.test.tsx
new file mode 100644
index 00000000000..e37a9d8d9c9
--- /dev/null
+++ b/openmetadata-ui/src/main/resources/ui/src/components/Widgets/RecentlyViewed/RecentlyViewed.test.tsx
@@ -0,0 +1,92 @@
+/*
+ * Copyright 2024 Collate.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+import { act, fireEvent, render, screen } from '@testing-library/react';
+import React from 'react';
+import { getRecentlyViewedData } from '../../../utils/CommonUtils';
+import RecentlyViewed from './RecentlyViewed';
+
+const mockProp = {
+ widgetKey: 'testKey',
+};
+
+jest.mock(
+ '../../Skeleton/MyData/EntityListSkeleton/EntityListSkeleton.component',
+ () => {
+ return jest
+ .fn()
+ .mockImplementation(({ children }) => {children}
);
+ }
+);
+jest.mock('react-router-dom', () => ({
+ useLocation: jest.fn().mockImplementation(() => ({ pathname: '' })),
+
+ Link: jest.fn().mockImplementation(() => Link
),
+}));
+
+jest.mock('../../../utils/CommonUtils', () => ({
+ getRecentlyViewedData: jest.fn().mockReturnValue([
+ {
+ displayName: 'test',
+ entityType: 'table',
+ fqn: 'test',
+ id: '1',
+ serviceType: 'BigQuery',
+ name: 'Test Item',
+ fullyQualifiedName: 'test.item',
+ type: 'test',
+ timestamp: 1706533046620,
+ },
+ ]),
+ prepareLabel: jest.fn(),
+}));
+
+describe('RecentlyViewed', () => {
+ it('should render RecentlyViewed', async () => {
+ await act(async () => {
+ render( );
+ });
+
+ expect(screen.getByTestId('recently-viewed-widget')).toBeInTheDocument();
+ });
+
+ it('should call handleCloseClick when close button is clicked', async () => {
+ const handleRemoveWidget = jest.fn();
+ const { getByTestId } = render(
+
+ );
+ fireEvent.click(getByTestId('remove-widget-button'));
+
+ expect(handleRemoveWidget).toHaveBeenCalled();
+ });
+
+ it('renders list item when data is not empty', async () => {
+ await act(async () => {
+ render( );
+ });
+
+ expect(screen.getByTestId('Recently Viewed-test')).toBeInTheDocument();
+ });
+
+ it('should render no data placeholder when data is empty', async () => {
+ (getRecentlyViewedData as jest.Mock).mockReturnValue([]),
+ await act(async () => {
+ render( );
+ });
+
+ expect(screen.getByTestId('no-data-placeholder')).toBeInTheDocument();
+ });
+});
diff --git a/openmetadata-ui/src/main/resources/ui/src/components/common/CmdKIcon/CmdKIcon.component.tsx b/openmetadata-ui/src/main/resources/ui/src/components/common/CmdKIcon/CmdKIcon.component.tsx
index dba0f0f1cb3..41304336042 100644
--- a/openmetadata-ui/src/main/resources/ui/src/components/common/CmdKIcon/CmdKIcon.component.tsx
+++ b/openmetadata-ui/src/main/resources/ui/src/components/common/CmdKIcon/CmdKIcon.component.tsx
@@ -19,21 +19,24 @@ import { NavigatorHelper } from '../../../utils/NavigatorUtils';
const CmdKIcon = () => {
return (
-
+
{NavigatorHelper.isMacOs() ? (
) : (
)}
({
+ NavigatorHelper: {
+ isMacOs: jest.fn(),
+ },
+}));
+
+describe('CmdKIcon', () => {
+ it('should render CmdKIcon', async () => {
+ await act(async () => {
+ render( );
+ });
+
+ expect(screen.getByTestId('cmdicon-container')).toBeInTheDocument();
+ });
+
+ it('should render CmdButton when isMacOs is true', () => {
+ (NavigatorHelper.isMacOs as jest.Mock).mockReturnValue(true);
+ const { getByTestId, queryByTestId } = render( );
+
+ expect(getByTestId('cmd-button')).toBeInTheDocument();
+ expect(queryByTestId('ctrl-button')).toBeNull();
+ });
+
+ it('should render CtrlButton when isMacOs is false', () => {
+ (NavigatorHelper.isMacOs as jest.Mock).mockReturnValue(false);
+ const { getByTestId, queryByTestId } = render( );
+
+ expect(getByTestId('ctrl-button')).toBeInTheDocument();
+ expect(queryByTestId('cmd-button')).toBeNull();
+ });
+});
diff --git a/openmetadata-ui/src/main/resources/ui/src/components/common/FeedsFilterPopover/FeedsFilterPopover.component.tsx b/openmetadata-ui/src/main/resources/ui/src/components/common/FeedsFilterPopover/FeedsFilterPopover.component.tsx
index 55e9a03c603..6cecbe73d5a 100644
--- a/openmetadata-ui/src/main/resources/ui/src/components/common/FeedsFilterPopover/FeedsFilterPopover.component.tsx
+++ b/openmetadata-ui/src/main/resources/ui/src/components/common/FeedsFilterPopover/FeedsFilterPopover.component.tsx
@@ -123,7 +123,11 @@ const FeedsFilterPopover = ({
showArrow={false}
trigger="click"
onOpenChange={setPopupVisible}>
- } />
+ }
+ />
);
};
diff --git a/openmetadata-ui/src/main/resources/ui/src/components/common/FeedsFilterPopover/FeedsFilterPopover.test.tsx b/openmetadata-ui/src/main/resources/ui/src/components/common/FeedsFilterPopover/FeedsFilterPopover.test.tsx
new file mode 100644
index 00000000000..c809f7be6be
--- /dev/null
+++ b/openmetadata-ui/src/main/resources/ui/src/components/common/FeedsFilterPopover/FeedsFilterPopover.test.tsx
@@ -0,0 +1,91 @@
+/*
+ * Copyright 2024 Collate.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+import { act, fireEvent, render, screen } from '@testing-library/react';
+import React from 'react';
+import { FeedFilter } from '../../../enums/mydata.enum';
+import FeedsFilterPopover from './FeedsFilterPopover.component';
+
+const onUpdateMock = jest.fn();
+const mockProps = {
+ defaultFilter: FeedFilter.ALL,
+ onUpdate: onUpdateMock,
+};
+
+jest.mock('../../Auth/AuthProviders/AuthProvider', () => ({
+ useAuthContext: jest.fn(() => ({
+ currentUser: {
+ isAdmin: true,
+ },
+ })),
+}));
+
+describe('FeedsFilterPopover', () => {
+ it('should render Feeds Filter Popover', async () => {
+ await act(async () => {
+ render( );
+ });
+
+ const filterButton = screen.getByTestId('filter-button');
+ fireEvent.click(
+ filterButton,
+ new MouseEvent('hover', {
+ bubbles: true,
+ cancelable: true,
+ })
+ );
+
+ expect(screen.getByTestId('cancel-button')).toBeInTheDocument();
+ expect(
+ screen.getByTestId('selectable-list-update-btn')
+ ).toBeInTheDocument();
+ });
+
+ it('should update filter when an item is clicked', async () => {
+ await act(async () => {
+ render( );
+ });
+
+ const filterButton = screen.getByTestId('filter-button');
+ fireEvent.click(
+ filterButton,
+ new MouseEvent('hover', {
+ bubbles: true,
+ cancelable: true,
+ })
+ );
+ const listItem = screen.getByText('message.feed-filter-all');
+ fireEvent.click(listItem);
+ fireEvent.click(screen.getByTestId('selectable-list-update-btn'));
+
+ expect(onUpdateMock).toHaveBeenCalledWith(FeedFilter.ALL);
+ });
+
+ it('should close popover when cancel button is clicked', async () => {
+ await act(async () => {
+ render( );
+ });
+
+ const filterButton = screen.getByTestId('filter-button');
+ fireEvent.click(
+ filterButton,
+ new MouseEvent('hover', {
+ bubbles: true,
+ cancelable: true,
+ })
+ );
+ const cancelButton = screen.getByTestId('cancel-button');
+ fireEvent.click(cancelButton);
+
+ expect(screen.queryByTestId('cancel-button')).not.toBeInTheDocument();
+ });
+});
diff --git a/openmetadata-ui/src/main/resources/ui/src/components/common/FormBuilder/FormBuilder.test.tsx b/openmetadata-ui/src/main/resources/ui/src/components/common/FormBuilder/FormBuilder.test.tsx
new file mode 100644
index 00000000000..8a5a1cc10f3
--- /dev/null
+++ b/openmetadata-ui/src/main/resources/ui/src/components/common/FormBuilder/FormBuilder.test.tsx
@@ -0,0 +1,121 @@
+/*
+ * Copyright 2024 Collate.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+import validator from '@rjsf/validator-ajv8';
+import { fireEvent, render, screen } from '@testing-library/react';
+import React from 'react';
+import { LOADING_STATE } from '../../../enums/common.enum';
+import { ServiceCategory } from '../../../enums/service.enum';
+import { transformErrors } from '../../../utils/formUtils';
+import FormBuilder, { Props } from './FormBuilder';
+
+describe('FormBuilder', () => {
+ const mockOnSubmit = jest.fn();
+ const mockOnCancel = jest.fn();
+
+ const props = {
+ okText: 'Submit',
+ cancelText: 'Cancel',
+ serviceCategory: ServiceCategory.DASHBOARD_SERVICES,
+ showFormHeader: true,
+ status: 'initial',
+ onCancel: mockOnCancel,
+ onSubmit: mockOnSubmit,
+ useSelectWidget: true,
+ schema: {},
+ formData: {},
+ uiSchema: {},
+ validator: validator,
+ } as Props;
+
+ it('should render Form Builder', () => {
+ const { getByTestId } = render(
+
+ );
+
+ expect(getByTestId('buttons')).toBeInTheDocument();
+ expect(getByTestId('submit-btn')).toBeInTheDocument();
+ });
+
+ it('should call onSubmit when submit button is clicked', () => {
+ render( );
+ fireEvent.click(screen.getByText('Submit'));
+
+ expect(mockOnSubmit).toHaveBeenCalled();
+ });
+
+ it('should handle cancel button click', () => {
+ const { getByText } = render(
+
+ );
+ const cancelButton = getByText('Close');
+ fireEvent.click(cancelButton);
+
+ expect(mockOnCancel).toHaveBeenCalled();
+ });
+
+ it('should display loader when status is waiting', () => {
+ const { getByTestId } = render(
+
+ );
+
+ expect(getByTestId('loader')).toBeInTheDocument();
+ });
+
+ it('should display check icon when status is success', () => {
+ const { getByRole } = render(
+
+ );
+
+ expect(getByRole('img')).toBeInTheDocument();
+ });
+
+ it('does not show form header when showFormHeader is false', () => {
+ const newProps = { ...props, showFormHeader: false };
+ render( );
+
+ expect(screen.queryByText('Form Header')).toBeNull();
+ });
+});
diff --git a/openmetadata-ui/src/main/resources/ui/src/components/common/FormBuilder/FormBuilder.tsx b/openmetadata-ui/src/main/resources/ui/src/components/common/FormBuilder/FormBuilder.tsx
index 6cde9dd97e9..f504b1c61f9 100644
--- a/openmetadata-ui/src/main/resources/ui/src/components/common/FormBuilder/FormBuilder.tsx
+++ b/openmetadata-ui/src/main/resources/ui/src/components/common/FormBuilder/FormBuilder.tsx
@@ -30,7 +30,7 @@ import MultiSelectWidget from '../../JsonSchemaWidgets/MultiSelectWidget';
import PasswordWidget from '../../JsonSchemaWidgets/PasswordWidget';
import Loader from '../../Loader/Loader';
-interface Props extends FormProps {
+export interface Props extends FormProps {
okText: string;
cancelText: string;
serviceCategory: ServiceCategory;
diff --git a/openmetadata-ui/src/main/resources/ui/src/components/common/ResizablePanels/PanelContainer/PanelContainer.test.tsx b/openmetadata-ui/src/main/resources/ui/src/components/common/ResizablePanels/PanelContainer/PanelContainer.test.tsx
new file mode 100644
index 00000000000..c699766e2ed
--- /dev/null
+++ b/openmetadata-ui/src/main/resources/ui/src/components/common/ResizablePanels/PanelContainer/PanelContainer.test.tsx
@@ -0,0 +1,72 @@
+/*
+ * Copyright 2024 Collate.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+import { render } from '@testing-library/react';
+import React from 'react';
+import PanelContainer from './PanelContainer';
+
+const mockProps = {
+ className: 'test-class',
+ dimensions: { width: 500, height: 500 },
+ overlay: {
+ displayThreshold: 400,
+ header: 'Test Header',
+ },
+};
+
+describe('PanelContainer', () => {
+ it('should renders PanelContainer', () => {
+ const { getByTestId } = render(
+
+ Child Component
+
+ );
+
+ expect(getByTestId('panel-container')).toBeInTheDocument();
+ });
+
+ it('should render overlay when dimensions width is less than displayThreshold', () => {
+ const overlay = {
+ displayThreshold: 500,
+ header: 'Test Header',
+ };
+ const dimensions = { width: 400, height: 500 };
+
+ const { getByText } = render(
+
+ Child Component
+
+ );
+
+ expect(getByText('Test Header')).toBeInTheDocument();
+ });
+
+ it('should not render overlay when width is greater than displayThreshold', () => {
+ const { queryByText } = render(
+
+ Child Component
+
+ );
+
+ expect(queryByText('Test Header')).toBeNull();
+ });
+
+ it('should pass className to div', () => {
+ const { container } = render(
+
+ Child Component
+
+ );
+
+ expect(container.querySelector('.test-class')).toBeInTheDocument();
+ });
+});
diff --git a/openmetadata-ui/src/main/resources/ui/src/components/common/ResizablePanels/PanelContainer/PanelContainer.tsx b/openmetadata-ui/src/main/resources/ui/src/components/common/ResizablePanels/PanelContainer/PanelContainer.tsx
index e4e78274b5b..2c317bf48ed 100644
--- a/openmetadata-ui/src/main/resources/ui/src/components/common/ResizablePanels/PanelContainer/PanelContainer.tsx
+++ b/openmetadata-ui/src/main/resources/ui/src/components/common/ResizablePanels/PanelContainer/PanelContainer.tsx
@@ -20,7 +20,9 @@ const PanelContainer: React.FC> =
const width = dimensions?.width ?? 0;
return (
-
+
{overlay && width <= overlay.displayThreshold && (
= ({
className={classNames(firstPanel.className, {
'full-width': hideSecondPanel,
})}
+ data-testid={firstPanel.className}
flex={firstPanel.flex}
minSize={firstPanel.minWidth}
onStopResize={(args) => {
@@ -69,6 +70,7 @@ const ResizablePanels: React.FC = ({
className={classNames(secondPanel.className, {
hidden: hideSecondPanel,
})}
+ data-testid={secondPanel.className}
flex={secondPanel.flex}
minSize={secondPanel.minWidth}
onStopResize={(args) => {
diff --git a/openmetadata-ui/src/main/resources/ui/src/components/common/ResizablePanels/ResziablePanels.test.tsx b/openmetadata-ui/src/main/resources/ui/src/components/common/ResizablePanels/ResziablePanels.test.tsx
new file mode 100644
index 00000000000..6f1d5dc626d
--- /dev/null
+++ b/openmetadata-ui/src/main/resources/ui/src/components/common/ResizablePanels/ResziablePanels.test.tsx
@@ -0,0 +1,94 @@
+/*
+ * Copyright 2024 Collate.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+import { act, render, screen } from '@testing-library/react';
+import React from 'react';
+import ResizablePanels from './ResizablePanels';
+jest.mock('../../../components/DocumentTitle/DocumentTitle', () =>
+ jest.fn().mockImplementation(() => DocumentTitle
)
+);
+const firstPanel = {
+ children: First Panel
,
+ minWidth: 100,
+ className: 'first-panel',
+ flex: 0.5,
+ onStopResize: jest.fn(),
+};
+
+const secondPanel = {
+ children: Second Panel
,
+ minWidth: 100,
+ className: 'second-panel',
+ flex: 0.5,
+ onStopResize: jest.fn(),
+};
+
+describe('ResizablePanels', () => {
+ it('should render ResizablePanels', () => {
+ const { getByTestId } = render(
+
+ );
+
+ expect(getByTestId(firstPanel.className)).toBeInTheDocument();
+ expect(getByTestId(secondPanel.className)).toBeInTheDocument();
+ });
+
+ it('should hide the second panel when hideSecondPanel is true', async () => {
+ await act(async () => {
+ render(
+
+ );
+ });
+
+ expect(screen.getByTestId('second-panel')).toHaveClass('hidden');
+ });
+
+ it('should set the orientation of the panels to horizontal', () => {
+ const { container } = render(
+
+ );
+
+ expect(
+ container.querySelector('.reflex-container.horizontal')
+ ).toBeInTheDocument();
+ });
+
+ it('should pass className to ReflexContainer', () => {
+ const { container } = render(
+
+ );
+
+ expect(container.querySelector('.test-class')).toBeInTheDocument();
+ });
+});
diff --git a/openmetadata-ui/src/main/resources/ui/src/components/common/TeamTypeSelect/TeamTypeSelect.test.tsx b/openmetadata-ui/src/main/resources/ui/src/components/common/TeamTypeSelect/TeamTypeSelect.test.tsx
new file mode 100644
index 00000000000..195021abd59
--- /dev/null
+++ b/openmetadata-ui/src/main/resources/ui/src/components/common/TeamTypeSelect/TeamTypeSelect.test.tsx
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2024 Collate.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+import { fireEvent, render } from '@testing-library/react';
+import React from 'react';
+import { TeamType } from '../../../generated/entity/teams/team';
+import TeamTypeSelect from './TeamTypeSelect.component';
+
+const handleShowTypeSelector = jest.fn();
+const updateTeamType = jest.fn();
+
+const mockProps = {
+ showGroupOption: true,
+ handleShowTypeSelector: handleShowTypeSelector,
+ parentTeamType: TeamType.Organization,
+ teamType: TeamType.Department,
+ updateTeamType: updateTeamType,
+};
+
+jest.mock('../../../utils/TeamUtils', () => ({
+ getTeamOptionsFromType: jest.fn().mockReturnValue([
+ { label: 'BusinessUnit', value: 'BusinessUnit' },
+ { label: 'Division', value: 'Division' },
+ { label: 'Department', value: 'Department' },
+ { label: 'Group', value: 'Group' },
+ ]),
+}));
+
+describe('TeamTypeSelect', () => {
+ it('should render TeamTypeSelect', () => {
+ const { getByTestId } = render( );
+
+ expect(getByTestId('team-type-select')).toBeInTheDocument();
+ });
+
+ it('should call handleCancel when cancel button is clicked', () => {
+ const { getByTestId } = render( );
+ fireEvent.click(getByTestId('cancel-btn'));
+
+ expect(handleShowTypeSelector).toHaveBeenCalledWith(false);
+ expect(updateTeamType).not.toHaveBeenCalled();
+ });
+
+ it('should call handleSubmit when save button is clicked', () => {
+ const { getByTestId } = render( );
+ fireEvent.click(getByTestId('save-btn'));
+
+ expect(updateTeamType).toHaveBeenCalled();
+ });
+});
diff --git a/openmetadata-ui/src/main/resources/ui/src/pages/AddDataQualityTestPage/AddDataQualityTestPage.test.tsx b/openmetadata-ui/src/main/resources/ui/src/pages/AddDataQualityTestPage/AddDataQualityTestPage.test.tsx
new file mode 100644
index 00000000000..9ad412f91a3
--- /dev/null
+++ b/openmetadata-ui/src/main/resources/ui/src/pages/AddDataQualityTestPage/AddDataQualityTestPage.test.tsx
@@ -0,0 +1,83 @@
+/*
+ * Copyright 2024 Collate.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+import { act, render, screen } from '@testing-library/react';
+import React from 'react';
+import { ProfilerDashboardType } from '../../enums/table.enum';
+import { getTableDetailsByFQN } from '../../rest/tableAPI';
+import { showErrorToast } from '../../utils/ToastUtils';
+import AddDataQualityTestPage from './AddDataQualityTestPage';
+
+const mockTable = {
+ displayName: 'Test Table',
+ name: 'test-table',
+};
+
+const mockParams = {
+ fqn: 'sample_data.ecommerce_db.shopify.dim_address',
+ dashboardType: ProfilerDashboardType.TABLE,
+};
+
+jest.mock('react-router-dom', () => ({
+ useHistory: jest.fn(),
+ useParams: jest.fn().mockImplementation(() => mockParams),
+}));
+
+jest.mock('../../rest/tableAPI', () => ({
+ getTableDetailsByFQN: jest
+ .fn()
+ .mockImplementation(() => Promise.resolve(mockTable)),
+}));
+
+jest.mock('../../hooks/useFqn', () => ({
+ useFqn: jest.fn().mockReturnValue({ fqn: 'test-fqn' }),
+}));
+
+jest.mock('../../components/AddDataQualityTest/AddDataQualityTestV1', () => ({
+ __esModule: true,
+ default: jest
+ .fn()
+ .mockImplementation(() => (
+ AddDataQualityTestV1
+ )),
+}));
+
+describe('AddDataQualityTestPage', () => {
+ it('renders Add DataQuality Test Page', async () => {
+ await act(async () => {
+ render( );
+ });
+
+ const testContainer = screen.getByTestId('testv1-container');
+
+ expect(testContainer).toBeInTheDocument();
+ });
+
+ it('should fetch table data on mount', () => {
+ render( );
+
+ expect(getTableDetailsByFQN).toHaveBeenCalledWith('test-fqn', {
+ fields: 'testSuite,customMetrics,columns',
+ });
+ });
+
+ it('should display error toast when fetch fails', async () => {
+ (getTableDetailsByFQN as jest.Mock).mockRejectedValue(
+ new Error('Fetch failed')
+ );
+ await act(async () => {
+ render( );
+ });
+
+ expect(showErrorToast).toHaveBeenCalled();
+ });
+});
diff --git a/openmetadata-ui/src/main/resources/ui/src/pages/AddDataQualityTestPage/AddDataQualityTestPage.tsx b/openmetadata-ui/src/main/resources/ui/src/pages/AddDataQualityTestPage/AddDataQualityTestPage.tsx
index 899901354e3..b0fd09e897e 100644
--- a/openmetadata-ui/src/main/resources/ui/src/pages/AddDataQualityTestPage/AddDataQualityTestPage.tsx
+++ b/openmetadata-ui/src/main/resources/ui/src/pages/AddDataQualityTestPage/AddDataQualityTestPage.tsx
@@ -48,7 +48,7 @@ const AddDataQualityTestPage = () => {
}
return (
-
+
);
diff --git a/openmetadata-ui/src/main/resources/ui/src/pages/AddIngestionPage/AddIngestionPage.test.tsx b/openmetadata-ui/src/main/resources/ui/src/pages/AddIngestionPage/AddIngestionPage.test.tsx
new file mode 100644
index 00000000000..c8d0cd01334
--- /dev/null
+++ b/openmetadata-ui/src/main/resources/ui/src/pages/AddIngestionPage/AddIngestionPage.test.tsx
@@ -0,0 +1,136 @@
+/*
+ * Copyright 2024 Collate.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+import {
+ render,
+ screen,
+ waitForElementToBeRemoved,
+} from '@testing-library/react';
+import React from 'react';
+import { MemoryRouter, Route } from 'react-router-dom';
+import { useAirflowStatus } from '../../hooks/useAirflowStatus';
+import { useFqn } from '../../hooks/useFqn';
+import AddIngestionPage from './AddIngestionPage.component';
+const mockShowErrorToast = jest.fn();
+jest.mock('react-router-dom', () => ({
+ ...jest.requireActual('react-router-dom'),
+ useParams: jest.fn().mockImplementation(() => ({
+ ingestionType: 'fqn',
+ serviceCategory: 'databaseServices',
+ })),
+}));
+
+jest.mock('../../hooks/useFqn', () => ({
+ useFqn: jest.fn().mockImplementation(() => ({ fqn: 'testFqn' })),
+}));
+
+jest.mock('../../hooks/useAirflowStatus', () => ({
+ useAirflowStatus: jest.fn().mockImplementation(() => ({
+ fetchAirflowStatus: jest.fn().mockImplementation(() => Promise.resolve()),
+ })),
+}));
+
+jest.mock('../../rest/serviceAPI', () => ({
+ getServiceByFQN: jest.fn().mockImplementation(() =>
+ Promise.resolve({
+ deleted: false,
+ fullyQualifiedName: 'sample_data',
+ href: 'http://localhost:8585/api/v1/services/databaseServices/0f74bba0-b34b-48e9-a68e-19f165adbeb6',
+ id: '0f74bba0-b34b-48e9-a68e-19f165adbeb6',
+ name: 'sample_data',
+ serviceType: 'BigQuery',
+ updatedAt: 1706852930787,
+ updatedBy: 'admin',
+ version: 0.1,
+ })
+ ),
+}));
+
+jest.mock('../../components/common/ServiceDocPanel/ServiceDocPanel', () =>
+ jest.fn().mockImplementation(() =>
ServiceDocPanel
)
+);
+
+jest.mock('../../utils/ServiceUtils', () => ({
+ getServiceType: jest.fn(),
+}));
+
+jest.mock(
+ '../../components/common/TitleBreadcrumb/TitleBreadcrumb.component',
+ () => jest.fn().mockImplementation(() =>
TitleBreadcrumb
)
+);
+
+jest.mock('../../components/AddIngestion/AddIngestion.component', () =>
+ jest.fn().mockImplementation(() =>
AddIngestion
)
+);
+
+jest.mock('../../rest/ingestionPipelineAPI', () => ({
+ addIngestionPipeline: jest.fn().mockReturnValue(() => Promise.resolve({})),
+ deployIngestionPipelineById: jest
+ .fn()
+ .mockReturnValue(() => Promise.resolve({})),
+ getIngestionPipelineByFqn: jest
+ .fn()
+ .mockReturnValue(() => Promise.resolve({})),
+}));
+
+jest.mock('../../utils/IngestionUtils', () => ({
+ getBreadCrumbsArray: jest.fn().mockImplementation(() => [{ name: '' }]),
+ getIngestionHeadingName: jest.fn().mockImplementation(() => 'Ingestion'),
+ getSettingsPathFromPipelineType: jest.fn().mockImplementation(() => ''),
+}));
+
+jest.mock('../../utils/CommonUtils', () => ({
+ getEntityMissingError: jest.fn().mockImplementation(() =>
Error
),
+}));
+
+jest.mock('../../components/common/ResizablePanels/ResizablePanels', () =>
+ jest.fn().mockImplementation(({ firstPanel, secondPanel }) => (
+ <>
+
{firstPanel.children}
+
{secondPanel.children}
+ >
+ ))
+);
+jest.mock('../../utils/ToastUtils', () => ({
+ showErrorToast: jest.fn().mockImplementation(() => mockShowErrorToast),
+}));
+
+describe('Test AddIngestionPage component', () => {
+ beforeEach(() => {
+ (useAirflowStatus as jest.Mock).mockReturnValue({
+ fetchAirflowStatus: jest
+ .fn()
+ .mockImplementation(() => Promise.resolve({})),
+ });
+
+ (useFqn as jest.Mock).mockReturnValue({
+ fqn: 'testFqn',
+ });
+ });
+
+ it('AddIngestionPage component should render', async () => {
+ render(
+
+
+
+
+
+ );
+
+ await waitForElementToBeRemoved(() => screen.getByTestId('loader'));
+
+ expect(screen.getByText('TitleBreadcrumb')).toBeInTheDocument();
+ expect(screen.getByText('AddIngestion')).toBeInTheDocument();
+ expect(screen.getByText('ServiceDocPanel')).toBeInTheDocument();
+ });
+});