fixed: tag api being called on every click in create glossary and create glossary term page (#10126)

* fixed: tag api being called on every click in create glossary and create glossary term page

* added unit test and optimise the code
This commit is contained in:
Shailesh Parmar 2023-02-07 19:39:56 +05:30 committed by GitHub
parent 8d6a8938ad
commit b8e15bd969
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 151 additions and 10 deletions

View File

@ -0,0 +1,73 @@
/*
* 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 userEvent from '@testing-library/user-event';
import { mockTagsApiResponse } from 'mocks/Tags.mock';
import React from 'react';
import { getAllTagsForOptions } from 'utils/TagsUtils';
import { AddTags } from './add-tags.component';
const mockSetTags = jest.fn();
jest.mock('../../utils/TagsUtils', () => ({
...jest.requireActual('../../utils/TagsUtils'),
getAllTagsForOptions: jest
.fn()
.mockImplementation(() => Promise.resolve(mockTagsApiResponse.data)),
}));
describe('AddTags Component', () => {
it('component should render', async () => {
const mockGetAllTagsForOptions = getAllTagsForOptions as jest.Mock;
await act(async () => {
render(<AddTags setTags={mockSetTags} />);
});
expect(await screen.findByRole('combobox')).toBeInTheDocument();
expect(mockGetAllTagsForOptions).not.toHaveBeenCalled();
});
it('Tags api should call once', async () => {
const mockGetAllTagsForOptions = getAllTagsForOptions as jest.Mock;
const flushPromises = () => new Promise(setImmediate);
await act(async () => {
render(<AddTags setTags={mockSetTags} />);
});
const selectBox = await screen.findByRole('combobox');
// There should not be any call at 1st render
expect(mockGetAllTagsForOptions.mock.calls).toHaveLength(0);
expect(selectBox).toBeInTheDocument();
await act(async () => {
// Click on select element
userEvent.click(selectBox);
await flushPromises();
expect(
await mockGetAllTagsForOptions.mock.results[0].value
).toStrictEqual(mockTagsApiResponse.data);
});
const options = await screen.findAllByRole('option');
expect(options).toHaveLength(2);
await act(async () => {
userEvent.click(options[0]);
});
expect(mockGetAllTagsForOptions.mock.calls).toHaveLength(1);
});
});

View File

@ -12,16 +12,17 @@
*/
import { Select } from 'antd';
import { AxiosError } from 'axios';
import { EntityTags, TagOption } from 'Models';
import React, { useCallback, useEffect, useMemo, useState } from 'react';
import { useTranslation } from 'react-i18next';
import { showErrorToast } from 'utils/ToastUtils';
import { FQN_SEPARATOR_CHAR } from '../../constants/char.constants';
import { getAllTagsForOptions, getTagOptions } from '../../utils/TagsUtils';
export const AddTags = ({
setTags,
}: {
selectedTags?: Array<EntityTags>;
setTags?: (tags: EntityTags[]) => void;
}) => {
const [isTagLoading, setIsTagLoading] = useState<boolean>(false);
@ -33,10 +34,14 @@ export const AddTags = ({
const fetchTags = async () => {
setIsTagLoading(true);
const tags = await getAllTagsForOptions();
setTagList(tags.map((t) => t.fullyQualifiedName || t.name));
setIsTagLoading(false);
try {
const tags = await getAllTagsForOptions();
setTagList(tags.map((t) => t.fullyQualifiedName || t.name));
} catch (error) {
showErrorToast(error as AxiosError);
} finally {
setIsTagLoading(false);
}
};
const tagsList = useMemo(() => {
@ -53,12 +58,17 @@ export const AddTags = ({
}, [tagList]);
const onClickSelect = useCallback(() => {
fetchTags();
}, []);
if (tagList.length === 0) {
fetchTags();
}
}, [tagList]);
const handleChange = useCallback((value: string[]) => {
setSelectedTags && setSelectedTags(value);
}, []);
const handleChange = useCallback(
(value: string[]) => {
setSelectedTags(value);
},
[setSelectedTags]
);
tagsList.forEach((tag) =>
options.push(<Select.Option key={tag.label}>{tag.value}</Select.Option>)
@ -72,6 +82,8 @@ export const AddTags = ({
return (
<Select
allowClear
id="select-tags"
loading={isTagLoading}
mode="multiple"
placeholder={t('label.add-entity', {

View File

@ -26,3 +26,59 @@ export const mockTagList = [
mutuallyExclusive: true,
},
];
export const mockTagsApiResponse = {
data: [
{
id: '0897311f-1321-4e1c-a857-aab7dedc632d',
name: 'Personal',
fullyQualifiedName: 'PersonalData.Personal',
description:
'Data that can be used to directly or indirectly identify a person.',
classification: {
id: '5ce3825b-3227-4326-8beb-37ed2784149e',
type: 'classification',
name: 'PersonalData',
fullyQualifiedName: 'PersonalData',
description:
'Tags related classifying **Personal data** as defined by **GDPR.**<br/><br/>',
deleted: false,
href: 'http://localhost:8585/api/v1/classifications/5ce3825b-3227-4326-8beb-37ed2784149e',
},
version: 0.1,
updatedAt: 1675078969456,
updatedBy: 'admin',
href: 'http://localhost:8585/api/v1/tags/0897311f-1321-4e1c-a857-aab7dedc632d',
deprecated: false,
deleted: false,
provider: 'system',
mutuallyExclusive: false,
},
{
id: '68a9fa7f-9342-404a-b31a-112dea0e0f81',
name: 'SpecialCategory',
fullyQualifiedName: 'PersonalData.SpecialCategory',
description:
'GDPR special category data is personal information of data subjects that is especially sensitive',
classification: {
id: '5ce3825b-3227-4326-8beb-37ed2784149e',
type: 'classification',
name: 'PersonalData',
fullyQualifiedName: 'PersonalData',
description:
'Tags related classifying **Personal data** as defined by **GDPR.**<br/><br/>',
deleted: false,
href: 'http://localhost:8585/api/v1/classifications/5ce3825b-3227-4326-8beb-37ed2784149e',
},
version: 0.1,
updatedAt: 1675078969475,
updatedBy: 'admin',
href: 'http://localhost:8585/api/v1/tags/68a9fa7f-9342-404a-b31a-112dea0e0f81',
deprecated: false,
deleted: false,
provider: 'system',
mutuallyExclusive: false,
},
],
paging: { total: 2 },
};