mirror of
https://github.com/open-metadata/OpenMetadata.git
synced 2025-10-18 20:30:48 +00:00
fix(ui): enable no-console on eslint (#11335)
* fix(ui): enable no-console on eslint * fix console logs * fix tests
This commit is contained in:
parent
94eece76f8
commit
1d504e1122
@ -55,6 +55,8 @@ rules:
|
|||||||
- error
|
- error
|
||||||
- smart
|
- smart
|
||||||
|
|
||||||
|
no-console: 2
|
||||||
|
|
||||||
# Require a whitespace at the beginning of a comment
|
# Require a whitespace at the beginning of a comment
|
||||||
spaced-comment:
|
spaced-comment:
|
||||||
- error
|
- error
|
||||||
|
@ -15,4 +15,3 @@ tabWidth: 2
|
|||||||
jsxBracketSameLine: true
|
jsxBracketSameLine: true
|
||||||
htmlWhitespaceSensitivity: 'strict'
|
htmlWhitespaceSensitivity: 'strict'
|
||||||
singleQuote: true
|
singleQuote: true
|
||||||
endOfLine: 'auto'
|
|
||||||
|
@ -1,72 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2022 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 { useForm } from 'antd/lib/form/Form';
|
|
||||||
import AddGlossaryTermForm from 'components/AddGlossaryTermForm/AddGlossaryTermForm.component';
|
|
||||||
import { t } from 'i18next';
|
|
||||||
import React from 'react';
|
|
||||||
import { PageLayoutType } from '../../enums/layout.enum';
|
|
||||||
import TitleBreadcrumb from '../common/title-breadcrumb/title-breadcrumb.component';
|
|
||||||
import PageLayout from '../containers/PageLayout';
|
|
||||||
import { AddGlossaryTermProps } from './AddGlossaryTerm.interface';
|
|
||||||
|
|
||||||
const AddGlossaryTerm = ({
|
|
||||||
glossaryData,
|
|
||||||
onCancel,
|
|
||||||
slashedBreadcrumb,
|
|
||||||
isLoading,
|
|
||||||
}: AddGlossaryTermProps) => {
|
|
||||||
const fetchRightPanel = () => {
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<h6 className="tw-heading tw-text-base">
|
|
||||||
{t('label.configure-entity', {
|
|
||||||
entity: t('label.glossary-term'),
|
|
||||||
})}
|
|
||||||
</h6>
|
|
||||||
<div className="tw-mb-5">
|
|
||||||
{t('message.configure-glossary-term-description')}
|
|
||||||
</div>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
const [form] = useForm();
|
|
||||||
|
|
||||||
return (
|
|
||||||
<PageLayout
|
|
||||||
classes="tw-max-w-full-hd tw-h-full tw-pt-4"
|
|
||||||
header={<TitleBreadcrumb titleLinks={slashedBreadcrumb} />}
|
|
||||||
layout={PageLayoutType['2ColRTL']}
|
|
||||||
pageTitle={t('label.add-entity', { entity: t('label.glossary-term') })}
|
|
||||||
rightPanel={fetchRightPanel()}>
|
|
||||||
<div className="tw-form-container" data-testid="add-glossary-term">
|
|
||||||
<h6 className="tw-heading tw-text-base">
|
|
||||||
{t('label.add-entity', {
|
|
||||||
entity: t('label.glossary-term'),
|
|
||||||
})}
|
|
||||||
</h6>
|
|
||||||
<AddGlossaryTermForm
|
|
||||||
editMode={false}
|
|
||||||
formRef={form}
|
|
||||||
glossaryName={glossaryData.name}
|
|
||||||
glossaryReviewers={glossaryData.reviewers}
|
|
||||||
isLoading={isLoading}
|
|
||||||
onCancel={onCancel}
|
|
||||||
onSave={(data) => console.debug(data)}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</PageLayout>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default AddGlossaryTerm;
|
|
@ -1,26 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2022 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 { CreateGlossaryTerm } from '../../generated/api/data/createGlossaryTerm';
|
|
||||||
import { Glossary } from '../../generated/entity/data/glossary';
|
|
||||||
import { GlossaryTerm } from '../../generated/entity/data/glossaryTerm';
|
|
||||||
import { TitleBreadcrumbProps } from '../common/title-breadcrumb/title-breadcrumb.interface';
|
|
||||||
|
|
||||||
export interface AddGlossaryTermProps {
|
|
||||||
parentGlossaryData: GlossaryTerm | undefined;
|
|
||||||
glossaryData: Glossary;
|
|
||||||
isLoading: boolean;
|
|
||||||
onSave: (value: CreateGlossaryTerm) => void;
|
|
||||||
onCancel: () => void;
|
|
||||||
slashedBreadcrumb: TitleBreadcrumbProps['titleLinks'];
|
|
||||||
}
|
|
@ -1,98 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2022 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, getByTestId, render } from '@testing-library/react';
|
|
||||||
import React, { forwardRef } from 'react';
|
|
||||||
import {
|
|
||||||
mockedGlossaries,
|
|
||||||
mockedGlossaryTerms,
|
|
||||||
} from '../../mocks/Glossary.mock';
|
|
||||||
import AddGlossaryTerm from './AddGlossaryTerm.component';
|
|
||||||
|
|
||||||
jest.mock('rest/glossaryAPI', () => ({
|
|
||||||
addGlossaries: jest.fn().mockImplementation(() => Promise.resolve()),
|
|
||||||
}));
|
|
||||||
|
|
||||||
jest.mock('../common/rich-text-editor/RichTextEditorPreviewer', () => {
|
|
||||||
return jest.fn().mockReturnValue(<p>RichTextEditorPreviewer</p>);
|
|
||||||
});
|
|
||||||
|
|
||||||
jest.mock('../common/rich-text-editor/RichTextEditorPreviewer', () => {
|
|
||||||
return forwardRef(
|
|
||||||
jest.fn().mockImplementation(({ initialValue }, ref) => {
|
|
||||||
return <div ref={ref}>{initialValue}RichTextEditorPreviewer</div>;
|
|
||||||
})
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
jest.mock('../common/rich-text-editor/RichTextEditor', () => {
|
|
||||||
return forwardRef(
|
|
||||||
jest.fn().mockImplementation(({ initialValue }) => {
|
|
||||||
return (
|
|
||||||
<div
|
|
||||||
ref={(input) => {
|
|
||||||
return {
|
|
||||||
getEditorContent: input,
|
|
||||||
};
|
|
||||||
}}>
|
|
||||||
{initialValue}RichTextEditor
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
})
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
jest.mock('../containers/PageLayout', () =>
|
|
||||||
jest.fn().mockImplementation(({ children }) => <div>{children}</div>)
|
|
||||||
);
|
|
||||||
|
|
||||||
const mockOnCancel = jest.fn();
|
|
||||||
const mockOnSave = jest.fn();
|
|
||||||
|
|
||||||
const mockProps = {
|
|
||||||
allowAccess: true,
|
|
||||||
glossaryData: mockedGlossaries[0],
|
|
||||||
parentGlossaryData: mockedGlossaryTerms[0],
|
|
||||||
isLoading: false,
|
|
||||||
onCancel: mockOnCancel,
|
|
||||||
onSave: mockOnSave,
|
|
||||||
slashedBreadcrumb: [],
|
|
||||||
};
|
|
||||||
|
|
||||||
describe('Test AddGlossaryTerm component', () => {
|
|
||||||
it('AddGlossaryTerm component should render', async () => {
|
|
||||||
const { container } = render(<AddGlossaryTerm {...mockProps} />);
|
|
||||||
|
|
||||||
const addGlossaryTermForm = getByTestId(container, 'add-glossary-term');
|
|
||||||
|
|
||||||
expect(addGlossaryTermForm).toBeInTheDocument();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should be able to cancel', () => {
|
|
||||||
const { container } = render(<AddGlossaryTerm {...mockProps} />);
|
|
||||||
|
|
||||||
const cancelButton = getByTestId(container, 'cancel-glossary-term');
|
|
||||||
|
|
||||||
expect(cancelButton).toBeInTheDocument();
|
|
||||||
|
|
||||||
fireEvent.click(
|
|
||||||
cancelButton,
|
|
||||||
new MouseEvent('click', {
|
|
||||||
bubbles: true,
|
|
||||||
cancelable: true,
|
|
||||||
})
|
|
||||||
);
|
|
||||||
|
|
||||||
expect(mockOnCancel).toHaveBeenCalled();
|
|
||||||
});
|
|
||||||
});
|
|
@ -72,8 +72,8 @@ export const AssetSelectionModal = ({
|
|||||||
setTotalCount(res.hits.total.value ?? 0);
|
setTotalCount(res.hits.total.value ?? 0);
|
||||||
setItems(page === 1 ? hits : (prevItems) => [...prevItems, ...hits]);
|
setItems(page === 1 ? hits : (prevItems) => [...prevItems, ...hits]);
|
||||||
setPageNumber(page);
|
setPageNumber(page);
|
||||||
} catch (error) {
|
} catch (_) {
|
||||||
console.error(error);
|
// Nothing here
|
||||||
} finally {
|
} finally {
|
||||||
setIsLoading(false);
|
setIsLoading(false);
|
||||||
}
|
}
|
||||||
@ -166,8 +166,8 @@ export const AssetSelectionModal = ({
|
|||||||
await Promise.all(patchAPIPromises);
|
await Promise.all(patchAPIPromises);
|
||||||
onSave && onSave();
|
onSave && onSave();
|
||||||
onCancel();
|
onCancel();
|
||||||
} catch (error) {
|
} catch (_) {
|
||||||
console.error(error);
|
// Nothing here
|
||||||
} finally {
|
} finally {
|
||||||
setIsLoading(false);
|
setIsLoading(false);
|
||||||
}
|
}
|
||||||
|
@ -37,8 +37,8 @@ const GlossaryTermReferencesModal = ({
|
|||||||
try {
|
try {
|
||||||
await form.validateFields();
|
await form.validateFields();
|
||||||
onSave(obj.references);
|
onSave(obj.references);
|
||||||
} catch (error) {
|
} catch (_) {
|
||||||
console.log(error);
|
// Nothing here
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -181,8 +181,8 @@ const AssetsTabs = forwardRef(
|
|||||||
|
|
||||||
// Select first card to show summary right panel
|
// Select first card to show summary right panel
|
||||||
hits[0] && setSelectedCard(hits[0]._source as SourceType);
|
hits[0] && setSelectedCard(hits[0]._source as SourceType);
|
||||||
} catch (error) {
|
} catch (_) {
|
||||||
console.error(error);
|
// Nothing here
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
[activeFilter, currentPage]
|
[activeFilter, currentPage]
|
||||||
|
@ -18,7 +18,7 @@ import { LOADING_STATE } from 'enums/common.enum';
|
|||||||
import { Glossary } from 'generated/entity/data/glossary';
|
import { Glossary } from 'generated/entity/data/glossary';
|
||||||
import { GlossaryTerm } from 'generated/entity/data/glossaryTerm';
|
import { GlossaryTerm } from 'generated/entity/data/glossaryTerm';
|
||||||
import { EntityHistory } from 'generated/type/entityHistory';
|
import { EntityHistory } from 'generated/type/entityHistory';
|
||||||
import { mockFn, mockFnGlossary } from 'mocks/Glossary.mock';
|
import { noop } from 'lodash';
|
||||||
import React, { useEffect, useState } from 'react';
|
import React, { useEffect, useState } from 'react';
|
||||||
import { useHistory, useParams } from 'react-router-dom';
|
import { useHistory, useParams } from 'react-router-dom';
|
||||||
import {
|
import {
|
||||||
@ -91,16 +91,17 @@ const GlossaryVersion = ({ isGlossary = false }: GlossaryVersionProps) => {
|
|||||||
return (
|
return (
|
||||||
<PageContainer>
|
<PageContainer>
|
||||||
<div className="version-data p-l-lg p-r-sm">
|
<div className="version-data p-l-lg p-r-sm">
|
||||||
|
{/* TODO: Need to implement version component for Glossary */}
|
||||||
<GlossaryV1
|
<GlossaryV1
|
||||||
isVersionsView
|
isVersionsView
|
||||||
deleteStatus={LOADING_STATE.INITIAL}
|
deleteStatus={LOADING_STATE.INITIAL}
|
||||||
isGlossaryActive={isGlossary}
|
isGlossaryActive={isGlossary}
|
||||||
isSummaryPanelOpen={false}
|
isSummaryPanelOpen={false}
|
||||||
selectedData={selectedData as Glossary}
|
selectedData={selectedData as Glossary}
|
||||||
updateGlossary={mockFnGlossary}
|
updateGlossary={() => Promise.resolve()}
|
||||||
onGlossaryDelete={mockFn}
|
onGlossaryDelete={noop}
|
||||||
onGlossaryTermDelete={mockFn}
|
onGlossaryTermDelete={noop}
|
||||||
onGlossaryTermUpdate={mockFnGlossary}
|
onGlossaryTermUpdate={() => Promise.resolve()}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<EntityVersionTimeLine
|
<EntityVersionTimeLine
|
||||||
|
@ -35,8 +35,8 @@ const EntityNameModal: React.FC<Props> = ({
|
|||||||
try {
|
try {
|
||||||
await form.validateFields();
|
await form.validateFields();
|
||||||
onSave(obj);
|
onSave(obj);
|
||||||
} catch (error) {
|
} catch (_) {
|
||||||
console.log(error);
|
// Nothing here
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -90,8 +90,6 @@ const Appbar: React.FC = (): JSX.Element => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const handleSearchChange = (value: string) => {
|
const handleSearchChange = (value: string) => {
|
||||||
console.debug(`handleSearchChange value=${value}`);
|
|
||||||
|
|
||||||
setSearchValue(value);
|
setSearchValue(value);
|
||||||
value ? setIsOpen(true) : setIsOpen(false);
|
value ? setIsOpen(true) : setIsOpen(false);
|
||||||
};
|
};
|
||||||
|
@ -257,7 +257,11 @@ export const AuthProvider = ({
|
|||||||
const onRenewIdTokenHandlerPromise = onRenewIdTokenHandler();
|
const onRenewIdTokenHandlerPromise = onRenewIdTokenHandler();
|
||||||
onRenewIdTokenHandlerPromise && (await onRenewIdTokenHandlerPromise);
|
onRenewIdTokenHandlerPromise && (await onRenewIdTokenHandlerPromise);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error((error as AxiosError).message);
|
// eslint-disable-next-line no-console
|
||||||
|
console.error(
|
||||||
|
`Error while refreshing token: `,
|
||||||
|
(error as AxiosError).message
|
||||||
|
);
|
||||||
|
|
||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
|
@ -11,14 +11,7 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import {
|
import { findByTestId, render } from '@testing-library/react';
|
||||||
act,
|
|
||||||
findAllByText,
|
|
||||||
findByTestId,
|
|
||||||
fireEvent,
|
|
||||||
getByText,
|
|
||||||
render,
|
|
||||||
} from '@testing-library/react';
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import TierCard from './TierCard';
|
import TierCard from './TierCard';
|
||||||
|
|
||||||
@ -39,7 +32,9 @@ const mockTierData = [
|
|||||||
];
|
];
|
||||||
|
|
||||||
jest.mock('rest/tagAPI', () => ({
|
jest.mock('rest/tagAPI', () => ({
|
||||||
getTags: jest.fn().mockResolvedValue({ data: mockTierData }),
|
getTags: jest
|
||||||
|
.fn()
|
||||||
|
.mockImplementation(() => Promise.resolve({ data: mockTierData })),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
jest.mock('../../cardlist/CardListItem/CardWithListItem', () => ({
|
jest.mock('../../cardlist/CardListItem/CardWithListItem', () => ({
|
||||||
@ -60,32 +55,15 @@ jest.mock('antd', () => ({
|
|||||||
|
|
||||||
Popover: jest
|
Popover: jest
|
||||||
.fn()
|
.fn()
|
||||||
.mockImplementation(({ children }) => (
|
.mockImplementation(({ content }) => (
|
||||||
<div data-testid="tier-card-container">{children}</div>
|
<div data-testid="tier-card-container">{content}</div>
|
||||||
)),
|
)),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
const MockOnUpdate = jest.fn();
|
const MockOnUpdate = jest.fn();
|
||||||
const MockOnRemove = jest.fn();
|
const MockOnRemove = jest.fn();
|
||||||
|
|
||||||
describe.skip('Test TierCard Component', () => {
|
describe('Test TierCard Component', () => {
|
||||||
it('Component should render', async () => {
|
|
||||||
const { container } = render(
|
|
||||||
<TierCard
|
|
||||||
currentTier=""
|
|
||||||
removeTier={MockOnRemove}
|
|
||||||
updateTier={MockOnUpdate}>
|
|
||||||
<button>test</button>
|
|
||||||
</TierCard>
|
|
||||||
);
|
|
||||||
|
|
||||||
act(() => {
|
|
||||||
fireEvent.click(getByText(container, 'test'));
|
|
||||||
});
|
|
||||||
|
|
||||||
expect(await findAllByText(container, 'CardListItem')).toBeInTheDocument();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('Component should have card', async () => {
|
it('Component should have card', async () => {
|
||||||
const { container } = render(
|
const { container } = render(
|
||||||
<TierCard
|
<TierCard
|
||||||
@ -97,16 +75,4 @@ describe.skip('Test TierCard Component', () => {
|
|||||||
|
|
||||||
expect(await findByTestId(container, 'cards')).toBeInTheDocument();
|
expect(await findByTestId(container, 'cards')).toBeInTheDocument();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Card should have Clear button if item selected', async () => {
|
|
||||||
const { container } = render(
|
|
||||||
<TierCard
|
|
||||||
currentTier="Tier.Tier1"
|
|
||||||
removeTier={MockOnRemove}
|
|
||||||
updateTier={MockOnUpdate}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
|
|
||||||
expect(await findByTestId(container, 'remove-tier')).toBeInTheDocument();
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
@ -81,8 +81,6 @@ export const UserSelectableList = ({
|
|||||||
|
|
||||||
return { data: filterData, paging };
|
return { data: filterData, paging };
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(error);
|
|
||||||
|
|
||||||
return { data: [], paging: { total: 0 } };
|
return { data: [], paging: { total: 0 } };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -91,8 +91,6 @@ export const UserTeamSelectableList = ({
|
|||||||
|
|
||||||
return { data: filterData, paging };
|
return { data: filterData, paging };
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(error);
|
|
||||||
|
|
||||||
return { data: [], paging: { total: 0 } };
|
return { data: [], paging: { total: 0 } };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -160,8 +158,6 @@ export const UserTeamSelectableList = ({
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(error);
|
|
||||||
|
|
||||||
return { data: [], paging: { total: 0 } };
|
return { data: [], paging: { total: 0 } };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -12,7 +12,6 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { OperationPermission } from 'components/PermissionProvider/PermissionProvider.interface';
|
import { OperationPermission } from 'components/PermissionProvider/PermissionProvider.interface';
|
||||||
import { Glossary } from 'generated/entity/data/glossary';
|
|
||||||
import { Status } from '../generated/entity/data/glossaryTerm';
|
import { Status } from '../generated/entity/data/glossaryTerm';
|
||||||
|
|
||||||
export const mockedAssetData = {
|
export const mockedAssetData = {
|
||||||
@ -21,14 +20,6 @@ export const mockedAssetData = {
|
|||||||
total: 0,
|
total: 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
export const mockFnGlossary = async (value: Glossary) => {
|
|
||||||
console.debug('On back', value);
|
|
||||||
};
|
|
||||||
|
|
||||||
export const mockFn = () => {
|
|
||||||
console.debug('mock fn');
|
|
||||||
};
|
|
||||||
|
|
||||||
export const mockedGlossaryTerms = [
|
export const mockedGlossaryTerms = [
|
||||||
{
|
{
|
||||||
id: 'a5a97523-2229-41e5-abbe-65f61a534c34',
|
id: 'a5a97523-2229-41e5-abbe-65f61a534c34',
|
||||||
|
@ -1,201 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2022 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 { AxiosError } from 'axios';
|
|
||||||
import AddGlossaryTerm from 'components/AddGlossaryTerm/AddGlossaryTerm.component';
|
|
||||||
import { TitleBreadcrumbProps } from 'components/common/title-breadcrumb/title-breadcrumb.interface';
|
|
||||||
import PageContainerV1 from 'components/containers/PageContainerV1';
|
|
||||||
import Loader from 'components/Loader/Loader';
|
|
||||||
import { ERROR_MESSAGE } from 'constants/constants';
|
|
||||||
import { CreateGlossaryTerm } from 'generated/api/data/createGlossaryTerm';
|
|
||||||
import { cloneDeep, get, isUndefined } from 'lodash';
|
|
||||||
import React, { useEffect, useState } from 'react';
|
|
||||||
import { useTranslation } from 'react-i18next';
|
|
||||||
import { useHistory, useParams } from 'react-router-dom';
|
|
||||||
import {
|
|
||||||
addGlossaryTerm,
|
|
||||||
getGlossariesByName,
|
|
||||||
getGlossaryTermByFQN,
|
|
||||||
} from 'rest/glossaryAPI';
|
|
||||||
import { getIsErrorMatch } from 'utils/CommonUtils';
|
|
||||||
import { Glossary } from '../../generated/entity/data/glossary';
|
|
||||||
import { GlossaryTerm } from '../../generated/entity/data/glossaryTerm';
|
|
||||||
import { getGlossaryPath } from '../../utils/RouterUtils';
|
|
||||||
import { showErrorToast } from '../../utils/ToastUtils';
|
|
||||||
|
|
||||||
const AddGlossaryTermPage = () => {
|
|
||||||
const { glossaryName, glossaryTermsFQN } =
|
|
||||||
useParams<{ [key: string]: string }>();
|
|
||||||
const { t } = useTranslation();
|
|
||||||
const history = useHistory();
|
|
||||||
const [isDataLoading, setIsDataLoading] = useState<boolean>(true);
|
|
||||||
const [isLoading, setIsLoading] = useState(false);
|
|
||||||
const [glossaryData, setGlossaryData] = useState<Glossary>();
|
|
||||||
const [slashedBreadcrumb, setSlashedBreadcrumb] = useState<
|
|
||||||
TitleBreadcrumbProps['titleLinks']
|
|
||||||
>([]);
|
|
||||||
|
|
||||||
const [parentGlossaryData, setParentGlossaryData] = useState<GlossaryTerm>();
|
|
||||||
|
|
||||||
const handleCancel = () => {
|
|
||||||
history.goBack();
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleSaveFailure = (
|
|
||||||
error: AxiosError | string,
|
|
||||||
fallbackText?: string
|
|
||||||
) => {
|
|
||||||
showErrorToast(error, fallbackText);
|
|
||||||
};
|
|
||||||
|
|
||||||
const onSave = async (data: CreateGlossaryTerm) => {
|
|
||||||
setIsLoading(true);
|
|
||||||
try {
|
|
||||||
await addGlossaryTerm(data);
|
|
||||||
history.goBack();
|
|
||||||
} catch (error) {
|
|
||||||
handleSaveFailure(
|
|
||||||
getIsErrorMatch(error as AxiosError, ERROR_MESSAGE.alreadyExist)
|
|
||||||
? t('server.entity-already-exist', {
|
|
||||||
entity: t('label.glossary-term'),
|
|
||||||
name: data.name,
|
|
||||||
})
|
|
||||||
: (error as AxiosError),
|
|
||||||
t('server.add-entity-error', { entity: t('label.glossary-term') })
|
|
||||||
);
|
|
||||||
} finally {
|
|
||||||
setIsLoading(false);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const fetchGlossaryData = async () => {
|
|
||||||
try {
|
|
||||||
const res = await getGlossariesByName(glossaryName, [
|
|
||||||
'tags',
|
|
||||||
'owner',
|
|
||||||
'reviewers',
|
|
||||||
]);
|
|
||||||
setGlossaryData(res);
|
|
||||||
} catch (err) {
|
|
||||||
showErrorToast(
|
|
||||||
err as AxiosError,
|
|
||||||
t('server.entity-fetch-error', {
|
|
||||||
entity: t('label.glossary'),
|
|
||||||
})
|
|
||||||
);
|
|
||||||
} finally {
|
|
||||||
setIsDataLoading(false);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const fetchGlossaryTermsByName = (name: string) => {
|
|
||||||
getGlossaryTermByFQN(name, [
|
|
||||||
'children',
|
|
||||||
'relatedTerms',
|
|
||||||
'reviewers',
|
|
||||||
'tags',
|
|
||||||
])
|
|
||||||
.then((res) => {
|
|
||||||
if (res) {
|
|
||||||
setParentGlossaryData(res);
|
|
||||||
} else {
|
|
||||||
setParentGlossaryData(undefined);
|
|
||||||
showErrorToast(
|
|
||||||
t('server.entity-fetch-error', {
|
|
||||||
entity: t('label.glossary-term'),
|
|
||||||
})
|
|
||||||
);
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.catch((err: AxiosError) => {
|
|
||||||
setParentGlossaryData(undefined);
|
|
||||||
const errMsg = get(err, 'response.data.message', '');
|
|
||||||
showErrorToast(
|
|
||||||
errMsg ||
|
|
||||||
t('server.entity-fetch-error', {
|
|
||||||
entity: t('label.glossary-term'),
|
|
||||||
})
|
|
||||||
);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
fetchGlossaryData();
|
|
||||||
}, [glossaryName]);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (glossaryTermsFQN) {
|
|
||||||
fetchGlossaryTermsByName(glossaryTermsFQN);
|
|
||||||
}
|
|
||||||
}, [glossaryTermsFQN]);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
let breadcrumb = [];
|
|
||||||
|
|
||||||
if (isUndefined(glossaryTermsFQN)) {
|
|
||||||
breadcrumb.push({
|
|
||||||
name: glossaryName,
|
|
||||||
url: getGlossaryPath(glossaryName),
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
breadcrumb = glossaryTermsFQN.split('.').map((fqn, i, arr) => {
|
|
||||||
const cloneArr = cloneDeep(arr);
|
|
||||||
if (i === 0) {
|
|
||||||
return {
|
|
||||||
name: glossaryName,
|
|
||||||
url: getGlossaryPath(glossaryName),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
name: fqn,
|
|
||||||
url: getGlossaryPath(cloneArr.splice(0, i + 1).join('.')),
|
|
||||||
};
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
setSlashedBreadcrumb([
|
|
||||||
{
|
|
||||||
name: t('label.glossary'),
|
|
||||||
url: getGlossaryPath(),
|
|
||||||
},
|
|
||||||
...breadcrumb,
|
|
||||||
{
|
|
||||||
name: t('label.add-entity', { entity: t('label.glossary-term') }),
|
|
||||||
url: '',
|
|
||||||
activeTitle: true,
|
|
||||||
},
|
|
||||||
]);
|
|
||||||
}, [glossaryTermsFQN, glossaryName]);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<PageContainerV1>
|
|
||||||
{isDataLoading ? (
|
|
||||||
<Loader />
|
|
||||||
) : (
|
|
||||||
<div className="self-center">
|
|
||||||
<AddGlossaryTerm
|
|
||||||
glossaryData={glossaryData as Glossary}
|
|
||||||
isLoading={isLoading}
|
|
||||||
parentGlossaryData={parentGlossaryData}
|
|
||||||
slashedBreadcrumb={slashedBreadcrumb}
|
|
||||||
onCancel={handleCancel}
|
|
||||||
onSave={onSave}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</PageContainerV1>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default AddGlossaryTermPage;
|
|
@ -1,79 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2022 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 { findByText, fireEvent, render } from '@testing-library/react';
|
|
||||||
import React from 'react';
|
|
||||||
import { getGlossaryPath } from '../../utils/RouterUtils';
|
|
||||||
import AddGlossaryTermPage from './AddGlossaryTermPage.component';
|
|
||||||
|
|
||||||
const mockRedirect = jest.fn((fqn) => fqn);
|
|
||||||
|
|
||||||
jest.mock('react-router', () => ({
|
|
||||||
...jest.requireActual('react-router'),
|
|
||||||
useHistory: () => ({
|
|
||||||
push: jest.fn(),
|
|
||||||
goBack: jest.fn(),
|
|
||||||
}),
|
|
||||||
useParams: jest.fn().mockImplementation(() => ({
|
|
||||||
glossaryName: 'GlossaryName',
|
|
||||||
glossaryTermsFQN: '',
|
|
||||||
})),
|
|
||||||
}));
|
|
||||||
|
|
||||||
jest.mock('components/AddGlossaryTerm/AddGlossaryTerm.component', () => {
|
|
||||||
return jest.fn().mockImplementation(({ onCancel, onSave }) => (
|
|
||||||
<div
|
|
||||||
data-testid="add-glossary-term"
|
|
||||||
onClick={onCancel}
|
|
||||||
onMouseDown={onSave}>
|
|
||||||
AddGlossaryTerm.component
|
|
||||||
</div>
|
|
||||||
));
|
|
||||||
});
|
|
||||||
|
|
||||||
jest.mock('../../utils/RouterUtils', () => ({
|
|
||||||
getGlossaryPath: jest.fn(),
|
|
||||||
}));
|
|
||||||
|
|
||||||
jest.mock('rest/glossaryAPI', () => ({
|
|
||||||
addGlossaryTerm: jest.fn().mockImplementation(() => Promise.resolve()),
|
|
||||||
getGlossariesByName: jest.fn().mockImplementation(() => Promise.resolve()),
|
|
||||||
getGlossaryTermByFQN: jest.fn().mockImplementation(() => Promise.resolve()),
|
|
||||||
}));
|
|
||||||
|
|
||||||
describe('Test AddGlossaryTerm component page', () => {
|
|
||||||
it('AddGlossaryTerm component page should render', async () => {
|
|
||||||
const { container } = render(<AddGlossaryTermPage />);
|
|
||||||
|
|
||||||
const addGlossaryTerm = await findByText(
|
|
||||||
container,
|
|
||||||
/AddGlossaryTerm.component/i
|
|
||||||
);
|
|
||||||
|
|
||||||
expect(addGlossaryTerm).toBeInTheDocument();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('Redirect to Glossary on cancel', async () => {
|
|
||||||
(getGlossaryPath as jest.Mock).mockImplementationOnce(mockRedirect);
|
|
||||||
const { findByTestId } = render(<AddGlossaryTermPage />);
|
|
||||||
|
|
||||||
const addGlossaryTerm = await findByTestId('add-glossary-term');
|
|
||||||
|
|
||||||
fireEvent.click(
|
|
||||||
addGlossaryTerm,
|
|
||||||
new MouseEvent('click', { bubbles: true, cancelable: true })
|
|
||||||
);
|
|
||||||
|
|
||||||
expect(mockRedirect).toHaveBeenCalledWith('GlossaryName');
|
|
||||||
});
|
|
||||||
});
|
|
@ -403,9 +403,6 @@ describe('Test DatasetDetails page', () => {
|
|||||||
'entityLineageHandler'
|
'entityLineageHandler'
|
||||||
);
|
);
|
||||||
|
|
||||||
console.log('path here');
|
|
||||||
screen.debug(container);
|
|
||||||
|
|
||||||
expect(container).toBeInTheDocument();
|
expect(container).toBeInTheDocument();
|
||||||
expect(versionButton).toBeInTheDocument();
|
expect(versionButton).toBeInTheDocument();
|
||||||
expect(followButton).toBeInTheDocument();
|
expect(followButton).toBeInTheDocument();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user