mirror of
https://github.com/open-metadata/OpenMetadata.git
synced 2025-09-26 09:22:14 +00:00
ui: added unit test for data quality component part 2 (#12279)
* ui: added unit test for data quality component part 2 * added unit test for testSuitePage and editTestCaseModal * updated test with findByLabelText function * updated test for editTestCaseModal * fixed redirection spec in cypress
This commit is contained in:
parent
56ac4157e6
commit
c3e37f4f55
@ -63,7 +63,7 @@ export const LEFT_PANEL_DETAILS = {
|
||||
export const NAVBAR_DETAILS = {
|
||||
explore: {
|
||||
testid: '[data-testid="appbar-item-explore"]',
|
||||
url: `${BASE_URL}/explore/tables?page=1`,
|
||||
url: `${BASE_URL}/explore/tables`,
|
||||
},
|
||||
quality: {
|
||||
testid: '[data-testid="appbar-item-data-quality"]',
|
||||
|
@ -0,0 +1,121 @@
|
||||
/*
|
||||
* Copyright 2023 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 {
|
||||
MOCK_TEST_CASE,
|
||||
MOCK_TEST_DEFINITION_COLUMN_VALUES_TO_MATCH_REGEX,
|
||||
} from 'mocks/TestSuite.mock';
|
||||
import React, { forwardRef } from 'react';
|
||||
import { EditTestCaseModalProps } from './AddDataQualityTest.interface';
|
||||
import EditTestCaseModal from './EditTestCaseModal';
|
||||
|
||||
const mockProps: EditTestCaseModalProps = {
|
||||
visible: true,
|
||||
testCase: MOCK_TEST_CASE[0],
|
||||
onCancel: jest.fn(),
|
||||
onUpdate: jest.fn(),
|
||||
};
|
||||
|
||||
jest.mock('../common/rich-text-editor/RichTextEditor', () => {
|
||||
return forwardRef(
|
||||
jest.fn().mockImplementation(() => <div>RichTextEditor.component</div>)
|
||||
);
|
||||
});
|
||||
jest.mock('./components/ParameterForm', () => {
|
||||
return jest.fn().mockImplementation(() => <div>ParameterForm.component</div>);
|
||||
});
|
||||
jest.mock('rest/testAPI', () => {
|
||||
return {
|
||||
getTestDefinitionById: jest
|
||||
.fn()
|
||||
.mockImplementation(() =>
|
||||
Promise.resolve(MOCK_TEST_DEFINITION_COLUMN_VALUES_TO_MATCH_REGEX)
|
||||
),
|
||||
updateTestCaseById: jest.fn().mockImplementation(() => Promise.resolve()),
|
||||
};
|
||||
});
|
||||
|
||||
describe('EditTestCaseModal Component', () => {
|
||||
it('component should render', async () => {
|
||||
render(<EditTestCaseModal {...mockProps} />);
|
||||
|
||||
expect(await screen.findByTestId('edit-test-form')).toBeInTheDocument();
|
||||
expect(await screen.findByLabelText('label.table')).toBeInTheDocument();
|
||||
expect(await screen.findByLabelText('label.column')).toBeInTheDocument();
|
||||
expect(await screen.findByLabelText('label.name')).toBeInTheDocument();
|
||||
expect(
|
||||
await screen.findByLabelText('label.display-name')
|
||||
).toBeInTheDocument();
|
||||
expect(
|
||||
await screen.findByLabelText('label.test-entity')
|
||||
).toBeInTheDocument();
|
||||
expect(
|
||||
await screen.findByText('RichTextEditor.component')
|
||||
).toBeInTheDocument();
|
||||
expect(
|
||||
await screen.findByText('ParameterForm.component')
|
||||
).toBeInTheDocument();
|
||||
expect(await screen.findByText('label.cancel')).toBeInTheDocument();
|
||||
expect(await screen.findByText('label.submit')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('table, name, test definition, should be disabled', async () => {
|
||||
render(<EditTestCaseModal {...mockProps} />);
|
||||
|
||||
expect(await screen.findByLabelText('label.name')).toBeDisabled();
|
||||
expect(await screen.findByLabelText('label.column')).toBeDisabled();
|
||||
expect(await screen.findByLabelText('label.table')).toBeDisabled();
|
||||
expect(await screen.findByLabelText('label.test-entity')).toBeDisabled();
|
||||
});
|
||||
|
||||
it('fields should have data based on testCase value', async () => {
|
||||
render(<EditTestCaseModal {...mockProps} />);
|
||||
|
||||
expect(await screen.findByLabelText('label.table')).toHaveValue(
|
||||
'dim_address'
|
||||
);
|
||||
expect(await screen.findByLabelText('label.column')).toHaveValue(
|
||||
'last_name'
|
||||
);
|
||||
expect(await screen.findByLabelText('label.name')).toHaveValue(
|
||||
'column_values_to_match_regex'
|
||||
);
|
||||
expect(await screen.findByLabelText('label.test-entity')).toHaveValue(
|
||||
'columnValuesToMatchRegex'
|
||||
);
|
||||
});
|
||||
|
||||
it('should call onCancel function, on click of cancel button', async () => {
|
||||
render(<EditTestCaseModal {...mockProps} />);
|
||||
|
||||
const cancelBtn = await screen.findByText('label.cancel');
|
||||
|
||||
await act(async () => {
|
||||
fireEvent.click(cancelBtn);
|
||||
});
|
||||
|
||||
expect(mockProps.onCancel).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should call onUpdate function, on click of submit button', async () => {
|
||||
render(<EditTestCaseModal {...mockProps} />);
|
||||
|
||||
const submitBtn = await screen.findByText('label.submit');
|
||||
|
||||
await act(async () => {
|
||||
fireEvent.click(submitBtn);
|
||||
});
|
||||
|
||||
expect(mockProps.onUpdate).toHaveBeenCalled();
|
||||
});
|
||||
});
|
@ -198,6 +198,7 @@ const EditTestCaseModal: React.FC<EditTestCaseModalProps> = ({
|
||||
form.resetFields();
|
||||
onCancel();
|
||||
}}
|
||||
cancelText={t('label.cancel')}
|
||||
closable={false}
|
||||
confirmLoading={isLoadingOnSave}
|
||||
maskClosable={false}
|
||||
@ -212,21 +213,22 @@ const EditTestCaseModal: React.FC<EditTestCaseModalProps> = ({
|
||||
) : (
|
||||
<Form
|
||||
className="tw-h-70vh tw-overflow-auto"
|
||||
data-testid="edit-test-form"
|
||||
form={form}
|
||||
layout="vertical"
|
||||
name="tableTestForm"
|
||||
onFinish={handleFormSubmit}>
|
||||
<Form.Item required label={`${t('label.table')}`} name="table">
|
||||
<Form.Item required label={t('label.table')} name="table">
|
||||
<Input disabled />
|
||||
</Form.Item>
|
||||
{isColumn && (
|
||||
<Form.Item required label={`${t('label.column')}`} name="column">
|
||||
<Form.Item required label={t('label.column')} name="column">
|
||||
<Input disabled />
|
||||
</Form.Item>
|
||||
)}
|
||||
<Form.Item
|
||||
required
|
||||
label={`${t('label.name')}`}
|
||||
label={t('label.name')}
|
||||
name="name"
|
||||
rules={[
|
||||
{
|
||||
@ -241,16 +243,16 @@ const EditTestCaseModal: React.FC<EditTestCaseModalProps> = ({
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
required
|
||||
label={`${t('label.test-entity', {
|
||||
label={t('label.test-entity', {
|
||||
entity: t('label.type'),
|
||||
})}:`}
|
||||
})}
|
||||
name="testDefinition">
|
||||
<Input disabled placeholder={t('message.enter-test-case-name')} />
|
||||
</Form.Item>
|
||||
|
||||
{GenerateParamsField()}
|
||||
|
||||
<Form.Item label={`${t('label.description')}`} name="description">
|
||||
<Form.Item label={t('label.description')} name="description">
|
||||
<RichTextEditor
|
||||
height="200px"
|
||||
initialValue={testCase?.description || ''}
|
||||
|
@ -14,12 +14,12 @@ import { Col, Row } from 'antd';
|
||||
import { AxiosError } from 'axios';
|
||||
import { SummaryCard } from 'components/common/SummaryCard/SummaryCard.component';
|
||||
import { usePermissionProvider } from 'components/PermissionProvider/PermissionProvider';
|
||||
import { INITIAL_TEST_SUMMARY } from 'constants/TestSuite.constant';
|
||||
import { TestSummary } from 'generated/tests/testSuite';
|
||||
import { isUndefined } from 'lodash';
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { getTestCaseExecutionSummary } from 'rest/testAPI';
|
||||
import {} from 'utils/CommonUtils';
|
||||
import { showErrorToast } from 'utils/ToastUtils';
|
||||
import { SummaryPanelProps } from './SummaryPanel.interface';
|
||||
|
||||
@ -44,12 +44,13 @@ export const SummaryPanel = ({ testSummary }: SummaryPanelProps) => {
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (isUndefined(testSummary)) {
|
||||
if (testCasePermission?.ViewAll || testCasePermission?.ViewBasic) {
|
||||
fetchTestSummary();
|
||||
}
|
||||
if (
|
||||
isUndefined(testSummary) &&
|
||||
(testCasePermission?.ViewAll || testCasePermission?.ViewBasic)
|
||||
) {
|
||||
fetchTestSummary();
|
||||
} else {
|
||||
setSummary(testSummary);
|
||||
setSummary(testSummary ?? INITIAL_TEST_SUMMARY);
|
||||
setIsLoading(false);
|
||||
}
|
||||
}, [testCasePermission]);
|
||||
|
@ -0,0 +1,89 @@
|
||||
/*
|
||||
* Copyright 2023 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 } from '@testing-library/react';
|
||||
import React from 'react';
|
||||
import { getTestCaseExecutionSummary } from 'rest/testAPI';
|
||||
import { SummaryPanel } from './SummaryPanel.component';
|
||||
|
||||
const testCasePermission = {
|
||||
Create: true,
|
||||
Delete: true,
|
||||
ViewAll: true,
|
||||
EditAll: true,
|
||||
EditDescription: true,
|
||||
EditDisplayName: true,
|
||||
EditCustomFields: true,
|
||||
};
|
||||
const mockSummary = {
|
||||
total: 10,
|
||||
success: 7,
|
||||
aborted: 2,
|
||||
failed: 1,
|
||||
};
|
||||
|
||||
jest.mock('components/PermissionProvider/PermissionProvider', () => ({
|
||||
usePermissionProvider: jest.fn().mockImplementation(() => ({
|
||||
permissions: {
|
||||
testCase: testCasePermission,
|
||||
},
|
||||
})),
|
||||
}));
|
||||
jest.mock('components/common/SummaryCard/SummaryCard.component', () => {
|
||||
return {
|
||||
SummaryCard: jest
|
||||
.fn()
|
||||
.mockImplementation(() => <div>SummaryCard.component</div>),
|
||||
};
|
||||
});
|
||||
jest.mock('rest/testAPI', () => {
|
||||
return {
|
||||
getTestCaseExecutionSummary: jest
|
||||
.fn()
|
||||
.mockImplementation(() => Promise.resolve(mockSummary)),
|
||||
};
|
||||
});
|
||||
|
||||
describe('SummaryPanel component', () => {
|
||||
it('component should render', async () => {
|
||||
render(<SummaryPanel />);
|
||||
|
||||
const summaryCards = await screen.findAllByText('SummaryCard.component');
|
||||
|
||||
expect(summaryCards).toHaveLength(4);
|
||||
});
|
||||
|
||||
it('on page load getTestCaseExecutionSummary API should call', async () => {
|
||||
const mockGetTestCaseExecutionSummary =
|
||||
getTestCaseExecutionSummary as jest.Mock;
|
||||
render(<SummaryPanel />);
|
||||
|
||||
expect(mockGetTestCaseExecutionSummary).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should not call getTestCaseExecutionSummary API, if testSummary data is provided', async () => {
|
||||
const mockGetTestCaseExecutionSummary =
|
||||
getTestCaseExecutionSummary as jest.Mock;
|
||||
render(<SummaryPanel testSummary={mockSummary} />);
|
||||
|
||||
expect(mockGetTestCaseExecutionSummary).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should not call getTestCaseExecutionSummary API, if there is no permission', async () => {
|
||||
const mockGetTestCaseExecutionSummary =
|
||||
getTestCaseExecutionSummary as jest.Mock;
|
||||
testCasePermission.ViewAll = false;
|
||||
render(<SummaryPanel />);
|
||||
|
||||
expect(mockGetTestCaseExecutionSummary).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
@ -51,6 +51,7 @@ export const TestCaseStatusModal = ({
|
||||
|
||||
return (
|
||||
<Modal
|
||||
cancelText={t('label.cancel')}
|
||||
closable={false}
|
||||
okButtonProps={{
|
||||
form: 'update-status-form',
|
||||
@ -63,6 +64,7 @@ export const TestCaseStatusModal = ({
|
||||
width={750}
|
||||
onCancel={onCancel}>
|
||||
<Form<TestCaseFailureStatus>
|
||||
data-testid="update-status-form"
|
||||
form={form}
|
||||
id="update-status-form"
|
||||
initialValues={data}
|
||||
|
@ -0,0 +1,97 @@
|
||||
/*
|
||||
* Copyright 2023 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 { TestCaseFailureStatusType } from 'generated/tests/testCase';
|
||||
import React, { forwardRef } from 'react';
|
||||
import { TestCaseStatusModal } from './TestCaseStatusModal.component';
|
||||
import { TestCaseStatusModalProps } from './TestCaseStatusModal.interface';
|
||||
|
||||
const mockProps: TestCaseStatusModalProps = {
|
||||
open: true,
|
||||
onCancel: jest.fn(),
|
||||
onSubmit: jest.fn().mockImplementation(() => Promise.resolve()),
|
||||
};
|
||||
|
||||
jest.mock('components/common/rich-text-editor/RichTextEditor', () => {
|
||||
return forwardRef(jest.fn().mockReturnValue(<div>RichTextEditor</div>));
|
||||
});
|
||||
jest.mock('generated/tests/testCase', () => ({
|
||||
...jest.requireActual('generated/tests/testCase'),
|
||||
TestCaseFailureStatusType: {
|
||||
ACK: 'Ack',
|
||||
New: 'New',
|
||||
Resolved: 'Resolved',
|
||||
},
|
||||
}));
|
||||
|
||||
describe('TestCaseStatusModal component', () => {
|
||||
it('component should render', async () => {
|
||||
render(<TestCaseStatusModal {...mockProps} />);
|
||||
|
||||
expect(await screen.findByTestId('update-status-form')).toBeInTheDocument();
|
||||
expect(await screen.findByLabelText('label.status')).toBeInTheDocument();
|
||||
expect(await screen.findByText('label.cancel')).toBeInTheDocument();
|
||||
expect(await screen.findByText('label.submit')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should render test case reason and comment field, if status is resolved', async () => {
|
||||
render(
|
||||
<TestCaseStatusModal
|
||||
{...mockProps}
|
||||
data={{ testCaseFailureStatusType: TestCaseFailureStatusType.Resolved }}
|
||||
/>
|
||||
);
|
||||
|
||||
expect(await screen.findByLabelText('label.status')).toBeInTheDocument();
|
||||
expect(await screen.findByLabelText('label.reason')).toBeInTheDocument();
|
||||
expect(await screen.findByText('RichTextEditor')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should call onCancel function, on click of cancel button', async () => {
|
||||
render(
|
||||
<TestCaseStatusModal
|
||||
{...mockProps}
|
||||
data={{ testCaseFailureStatusType: TestCaseFailureStatusType.Resolved }}
|
||||
/>
|
||||
);
|
||||
const cancelBtn = await screen.findByText('label.cancel');
|
||||
await act(async () => {
|
||||
fireEvent.click(cancelBtn);
|
||||
});
|
||||
|
||||
expect(mockProps.onCancel).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should call onSubmit function, on click of save button', async () => {
|
||||
render(<TestCaseStatusModal {...mockProps} />);
|
||||
const submitBtn = await screen.findByText('label.submit');
|
||||
const status = await screen.findByLabelText('label.status');
|
||||
|
||||
await act(async () => {
|
||||
userEvent.click(status);
|
||||
});
|
||||
|
||||
const statusOption = await screen.findAllByText('New');
|
||||
|
||||
await act(async () => {
|
||||
fireEvent.click(statusOption[1]);
|
||||
});
|
||||
|
||||
await act(async () => {
|
||||
fireEvent.click(submitBtn);
|
||||
});
|
||||
|
||||
expect(mockProps.onSubmit).toHaveBeenCalled();
|
||||
});
|
||||
});
|
@ -40,11 +40,11 @@ export const OwnerLabel = ({
|
||||
|
||||
const profilePicture = useMemo(() => {
|
||||
if (isUndefined(owner)) {
|
||||
return <IconUser height={18} width={18} />;
|
||||
return <IconUser data-testid="no-owner-icon" height={18} width={18} />;
|
||||
}
|
||||
|
||||
return owner.type === OwnerType.TEAM ? (
|
||||
<IconTeamsGrey height={18} width={18} />
|
||||
<IconTeamsGrey data-testid="team-owner-icon" height={18} width={18} />
|
||||
) : (
|
||||
<ProfilePicture
|
||||
displayName={displayName}
|
||||
|
@ -0,0 +1,100 @@
|
||||
/*
|
||||
* Copyright 2023 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 } from '@testing-library/react';
|
||||
import React from 'react';
|
||||
import { MemoryRouter } from 'react-router-dom';
|
||||
import { OwnerLabel } from './OwnerLabel.component';
|
||||
|
||||
const mockOwner = {
|
||||
id: 'id',
|
||||
type: 'user',
|
||||
name: 'Test Name',
|
||||
};
|
||||
const mockTeamOwner = {
|
||||
id: 'id',
|
||||
type: 'team',
|
||||
name: 'Team Name',
|
||||
};
|
||||
|
||||
jest.mock('../ProfilePicture/ProfilePicture', () => {
|
||||
return jest.fn().mockReturnValue(<div>ProfilePicture.component</div>);
|
||||
});
|
||||
jest.mock('../UserTeamSelectableList/UserTeamSelectableList.component', () => {
|
||||
return {
|
||||
UserTeamSelectableList: jest
|
||||
.fn()
|
||||
.mockReturnValue(<div>UserTeamSelectableList.component</div>),
|
||||
};
|
||||
});
|
||||
|
||||
describe('OwnerLabel component', () => {
|
||||
it('owner name with profile picture should render', async () => {
|
||||
render(<OwnerLabel owner={mockOwner} />, { wrapper: MemoryRouter });
|
||||
|
||||
expect(
|
||||
await screen.findByText('ProfilePicture.component')
|
||||
).toBeInTheDocument();
|
||||
expect(await screen.findByText(mockOwner.name)).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should render displayName if provided', async () => {
|
||||
render(
|
||||
<OwnerLabel
|
||||
owner={{ id: 'id', type: 'user', displayName: 'displayName' }}
|
||||
/>,
|
||||
{ wrapper: MemoryRouter }
|
||||
);
|
||||
|
||||
expect(
|
||||
await screen.findByText('ProfilePicture.component')
|
||||
).toBeInTheDocument();
|
||||
expect(await screen.findByText('displayName')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should render ownerDisplayName if provided', async () => {
|
||||
render(
|
||||
<OwnerLabel owner={mockOwner} ownerDisplayName="ownerDisplayName" />,
|
||||
{ wrapper: MemoryRouter }
|
||||
);
|
||||
|
||||
expect(
|
||||
await screen.findByText('ProfilePicture.component')
|
||||
).toBeInTheDocument();
|
||||
expect(await screen.findByText('ownerDisplayName')).toBeInTheDocument();
|
||||
expect(screen.queryByText(mockOwner.name)).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should render no owner if owner is undefined', async () => {
|
||||
render(<OwnerLabel />, { wrapper: MemoryRouter });
|
||||
|
||||
expect(await screen.findByText('label.no-entity')).toBeInTheDocument();
|
||||
expect(await screen.findByTestId('no-owner-icon')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should render team icon and team name if owner is team', async () => {
|
||||
render(<OwnerLabel owner={mockTeamOwner} />, { wrapper: MemoryRouter });
|
||||
|
||||
expect(await screen.findByText(mockTeamOwner.name)).toBeInTheDocument();
|
||||
expect(await screen.findByTestId('team-owner-icon')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should render UserTeamSelectableList if onUpdate function is provided', async () => {
|
||||
render(<OwnerLabel owner={mockTeamOwner} onUpdate={jest.fn()} />, {
|
||||
wrapper: MemoryRouter,
|
||||
});
|
||||
|
||||
expect(
|
||||
await screen.findByText('UserTeamSelectableList.component')
|
||||
).toBeInTheDocument();
|
||||
});
|
||||
});
|
@ -37,19 +37,27 @@ export const SummaryCard = ({
|
||||
|
||||
if (isLoading) {
|
||||
return (
|
||||
<div className={classNames('summary-card', className)}>
|
||||
<div
|
||||
className={classNames('summary-card', className)}
|
||||
data-testid="skeleton-loading">
|
||||
<Skeleton active loading />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<Space className={classNames('summary-card', className)}>
|
||||
<Space
|
||||
className={classNames('summary-card', className)}
|
||||
data-testid="summary-card-container">
|
||||
<div>
|
||||
<Typography.Paragraph className="summary-card-title">
|
||||
<Typography.Paragraph
|
||||
className="summary-card-title"
|
||||
data-testid="summary-card-title">
|
||||
{title}
|
||||
</Typography.Paragraph>
|
||||
<Typography.Paragraph className="summary-card-description">
|
||||
<Typography.Paragraph
|
||||
className="summary-card-description"
|
||||
data-testid="summary-card-description">
|
||||
{isNumber(value) ? formatNumberWithComma(value) : value}
|
||||
</Typography.Paragraph>
|
||||
</div>
|
||||
@ -57,6 +65,7 @@ export const SummaryCard = ({
|
||||
{showProgressBar && (
|
||||
<Progress
|
||||
className={type}
|
||||
data-testid="progress-bar"
|
||||
format={(percent) => `${percent}%`}
|
||||
percent={percent}
|
||||
type="circle"
|
||||
|
@ -0,0 +1,70 @@
|
||||
/*
|
||||
* Copyright 2023 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 } from '@testing-library/react';
|
||||
import React from 'react';
|
||||
import { SummaryCard } from './SummaryCard.component';
|
||||
import { SummaryCardProps } from './SummaryCard.interface';
|
||||
|
||||
const mockProps: SummaryCardProps = {
|
||||
title: 'title',
|
||||
value: 10,
|
||||
total: 100,
|
||||
};
|
||||
|
||||
describe('SummaryCard component', () => {
|
||||
it('component should render', async () => {
|
||||
render(<SummaryCard {...mockProps} />);
|
||||
|
||||
expect(
|
||||
await screen.findByTestId('summary-card-container')
|
||||
).toBeInTheDocument();
|
||||
expect(await screen.findByTestId('summary-card-title')).toBeInTheDocument();
|
||||
expect(
|
||||
await screen.findByTestId('summary-card-description')
|
||||
).toBeInTheDocument();
|
||||
expect(await screen.findByRole('presentation')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should not render progress bar, if showProgressBar is false', async () => {
|
||||
render(<SummaryCard {...mockProps} showProgressBar={false} />);
|
||||
|
||||
expect(screen.queryByRole('presentation')).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should not render skeleton loader, if isLoading is true', async () => {
|
||||
render(<SummaryCard {...mockProps} isLoading />);
|
||||
|
||||
expect(await screen.findByTestId('skeleton-loading')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should render progress bar based on type', async () => {
|
||||
render(<SummaryCard {...mockProps} type="success" />);
|
||||
|
||||
const progressBar = await screen.findByTestId('progress-bar');
|
||||
|
||||
expect(progressBar).toBeInTheDocument();
|
||||
expect(progressBar).toHaveClass('success');
|
||||
});
|
||||
|
||||
it('should render title and description based on props', async () => {
|
||||
render(<SummaryCard title="summary title" total={0} value="description" />);
|
||||
|
||||
const title = await screen.findByTestId('summary-card-title');
|
||||
const description = await screen.findByTestId('summary-card-description');
|
||||
|
||||
expect(title).toBeInTheDocument();
|
||||
expect(description).toBeInTheDocument();
|
||||
expect(title.textContent).toStrictEqual('summary title');
|
||||
expect(description.textContent).toStrictEqual('description');
|
||||
});
|
||||
});
|
@ -673,6 +673,41 @@ export const MOCK_SQL_TEST_CASE = {
|
||||
deleted: false,
|
||||
} as TestCase;
|
||||
|
||||
export const MOCK_TEST_DEFINITION_COLUMN_VALUES_TO_MATCH_REGEX = {
|
||||
id: '4c69c0d7-c173-4f17-b939-737ce0510f66',
|
||||
name: 'columnValuesToMatchRegex',
|
||||
displayName: 'Column Values To Match Regex Pattern',
|
||||
fullyQualifiedName: 'columnValuesToMatchRegex',
|
||||
description:
|
||||
'This schema defines the test ColumnValuesToMatchRegex. Test the values in a column to match a given regular expression. ',
|
||||
entityType: 'COLUMN',
|
||||
testPlatforms: ['OpenMetadata'],
|
||||
supportedDataTypes: [
|
||||
'BYTES',
|
||||
'STRING',
|
||||
'MEDIUMTEXT',
|
||||
'TEXT',
|
||||
'CHAR',
|
||||
'VARCHAR',
|
||||
],
|
||||
parameterDefinition: [
|
||||
{
|
||||
name: 'regex',
|
||||
displayName: 'RegEx Pattern',
|
||||
dataType: 'STRING',
|
||||
description:
|
||||
'The regular expression the column entries should match. For database without regex support (i.e. MSSQL, AzureSQL) this test will use `LIKE`.',
|
||||
required: true,
|
||||
optionValues: [],
|
||||
},
|
||||
],
|
||||
version: 0.1,
|
||||
updatedAt: 1682571176093,
|
||||
updatedBy: 'admin',
|
||||
href: 'href',
|
||||
deleted: false,
|
||||
};
|
||||
|
||||
export const MOCK_CHART_COLLECTION_DATA = {
|
||||
data: [
|
||||
{
|
||||
|
@ -332,6 +332,7 @@ const TestSuiteDetailsPage = () => {
|
||||
{(testSuitePermissions.EditAll ||
|
||||
testSuitePermissions.EditTests) && (
|
||||
<Button
|
||||
data-testid="add-test-case-btn"
|
||||
type="primary"
|
||||
onClick={() => setIsTestCaseModalOpen(true)}>
|
||||
{t('label.add-entity', {
|
||||
|
@ -0,0 +1,151 @@
|
||||
/*
|
||||
* Copyright 2023 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 { usePermissionProvider } from 'components/PermissionProvider/PermissionProvider';
|
||||
import { mockEntityPermissions } from 'pages/DatabaseSchemaPage/mocks/DatabaseSchemaPage.mock';
|
||||
import React from 'react';
|
||||
import { getTestSuiteByName } from 'rest/testAPI';
|
||||
import TestSuiteDetailsPage from './TestSuiteDetailsPage.component';
|
||||
|
||||
jest.mock('components/containers/PageLayoutV1', () => {
|
||||
return jest.fn().mockImplementation(({ children }) => <div>{children}</div>);
|
||||
});
|
||||
jest.mock('components/Loader/Loader', () => {
|
||||
return jest.fn().mockImplementation(() => <div>Loader.component</div>);
|
||||
});
|
||||
jest.mock(
|
||||
'components/common/title-breadcrumb/title-breadcrumb.component',
|
||||
() => {
|
||||
return jest
|
||||
.fn()
|
||||
.mockImplementation(() => <div>TitleBreadcrumb.component</div>);
|
||||
}
|
||||
);
|
||||
jest.mock('components/common/error-with-placeholder/ErrorPlaceHolder', () => {
|
||||
return jest
|
||||
.fn()
|
||||
.mockImplementation(() => <div>ErrorPlaceHolder.component</div>);
|
||||
});
|
||||
jest.mock('components/common/EntitySummaryDetails/EntitySummaryDetails', () => {
|
||||
return jest
|
||||
.fn()
|
||||
.mockImplementation(() => <div>EntitySummaryDetails.component</div>);
|
||||
});
|
||||
jest.mock('components/common/entityPageInfo/ManageButton/ManageButton', () => {
|
||||
return jest.fn().mockImplementation(() => <div>ManageButton.component</div>);
|
||||
});
|
||||
jest.mock('components/common/description/Description', () => {
|
||||
return jest.fn().mockImplementation(() => <div>Description.component</div>);
|
||||
});
|
||||
jest.mock('components/ProfilerDashboard/component/DataQualityTab', () => {
|
||||
return jest
|
||||
.fn()
|
||||
.mockImplementation(() => <div>DataQualityTab.component</div>);
|
||||
});
|
||||
jest.mock('components/authentication/auth-provider/AuthProvider', () => {
|
||||
return {
|
||||
useAuthContext: jest
|
||||
.fn()
|
||||
.mockImplementation(() => ({ isAuthDisabled: true })),
|
||||
};
|
||||
});
|
||||
jest.mock('hooks/authHooks', () => {
|
||||
return {
|
||||
useAuth: jest.fn().mockImplementation(() => ({ isAdminUser: true })),
|
||||
};
|
||||
});
|
||||
jest.mock('react-router-dom', () => {
|
||||
return {
|
||||
useHistory: jest.fn().mockImplementation(() => ({ push: jest.fn() })),
|
||||
useParams: jest
|
||||
.fn()
|
||||
.mockImplementation(() => ({ testSuiteFQN: 'testSuiteFQN' })),
|
||||
};
|
||||
});
|
||||
jest.mock('rest/testAPI', () => {
|
||||
return {
|
||||
getTestSuiteByName: jest.fn().mockImplementation(() => Promise.resolve()),
|
||||
updateTestSuiteById: jest.fn().mockImplementation(() => Promise.resolve()),
|
||||
addTestCaseToLogicalTestSuite: jest
|
||||
.fn()
|
||||
.mockImplementation(() => Promise.resolve()),
|
||||
getListTestCase: jest
|
||||
.fn()
|
||||
.mockImplementation(() => Promise.resolve({ data: [] })),
|
||||
ListTestCaseParams: jest
|
||||
.fn()
|
||||
.mockImplementation(() => Promise.resolve({ data: [] })),
|
||||
};
|
||||
});
|
||||
jest.mock('components/PermissionProvider/PermissionProvider', () => ({
|
||||
usePermissionProvider: jest.fn().mockImplementation(() => ({
|
||||
getEntityPermissionByFqn: jest
|
||||
.fn()
|
||||
.mockImplementation(() => Promise.resolve(mockEntityPermissions)),
|
||||
})),
|
||||
}));
|
||||
|
||||
describe('TestSuiteDetailsPage component', () => {
|
||||
it('component should render', async () => {
|
||||
render(<TestSuiteDetailsPage />);
|
||||
|
||||
expect(
|
||||
await screen.findByText('TitleBreadcrumb.component')
|
||||
).toBeInTheDocument();
|
||||
expect(
|
||||
await screen.findByText('ManageButton.component')
|
||||
).toBeInTheDocument();
|
||||
expect(
|
||||
await screen.findByText('EntitySummaryDetails.component')
|
||||
).toBeInTheDocument();
|
||||
expect(
|
||||
await screen.findByText('Description.component')
|
||||
).toBeInTheDocument();
|
||||
expect(
|
||||
await screen.findByText('DataQualityTab.component')
|
||||
).toBeInTheDocument();
|
||||
expect(await screen.findByTestId('add-test-case-btn')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should call test suite API on page load', async () => {
|
||||
const mockGetTestSuiteByName = getTestSuiteByName as jest.Mock;
|
||||
await act(async () => {
|
||||
render(<TestSuiteDetailsPage />);
|
||||
});
|
||||
|
||||
expect(mockGetTestSuiteByName).toHaveBeenCalledWith('testSuiteFQN', {
|
||||
fields: 'owner,tests',
|
||||
include: 'all',
|
||||
});
|
||||
});
|
||||
|
||||
it('should show no permission error if there is no permission', async () => {
|
||||
(usePermissionProvider as jest.Mock).mockImplementationOnce(() => ({
|
||||
getEntityPermissionByFqn: jest.fn().mockImplementation(() =>
|
||||
Promise.resolve({
|
||||
...mockEntityPermissions,
|
||||
ViewAll: false,
|
||||
ViewBasic: false,
|
||||
})
|
||||
),
|
||||
}));
|
||||
|
||||
await act(async () => {
|
||||
render(<TestSuiteDetailsPage />);
|
||||
});
|
||||
|
||||
expect(
|
||||
await screen.findByText('ErrorPlaceHolder.component')
|
||||
).toBeInTheDocument();
|
||||
});
|
||||
});
|
Loading…
x
Reference in New Issue
Block a user