UI: Refector Landing page (#934)

* UI: refactor explore page

* rename index to exlore.component for mock file and test file

* UI: refactore landing page

* Merge Main

* re-name test files and my-data folder and miner fix

* re-name LandingPage folder to MyData

* miner fix
This commit is contained in:
Shailesh Parmar 2021-10-26 17:27:06 +05:30 committed by GitHub
parent 6f46ebbfef
commit e60986e70a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
23 changed files with 504 additions and 356 deletions

View File

@ -38,6 +38,10 @@ import {
tableSortingFields,
visibleFilters,
} from '../../constants/constants';
import {
getAggrWithDefaultValue,
tabsInfo,
} from '../../constants/explore.constants';
import { SearchIndex } from '../../enums/search.enum';
import { usePrevious } from '../../hooks/usePrevious';
import { getAggregationList } from '../../utils/AggregationUtils';
@ -46,7 +50,6 @@ import { getCountBadge } from '../../utils/CommonUtils';
import { getFilterString } from '../../utils/FilterUtils';
import { dropdownIcon as DropDownIcon } from '../../utils/svgconstant';
import SVGIcons from '../../utils/SvgUtils';
import { getAggrWithDefaultValue, tabsInfo } from './explore.constants';
import { ExploreProps } from './explore.interface';
const getQueryParam = (urlSearchQuery = ''): FilterObject => {

View File

@ -15,28 +15,13 @@
* limitations under the License.
*/
import { SearchResponse } from 'Models';
import { SearchDataFunctionType, SearchResponse } from 'Models';
export type Params = {
export type UrlParams = {
searchQuery: string;
tab: string;
};
export type Service = {
collection: {
name: string;
documentation: string;
href: string;
};
};
export type Team = {
id: string;
name: string;
displayName: string;
description: string;
href: string;
};
export type ExploreSearchData = {
resSearchResults: SearchResponse;
resAggServiceType: SearchResponse;
@ -44,16 +29,6 @@ export type ExploreSearchData = {
resAggTag: SearchResponse;
};
export interface FetchData {
queryString: string;
from: number;
size: number;
filters: string;
sortField: string;
sortOrder: string;
searchIndex: string;
}
export interface ExploreProps {
tabCounts: {
table: number;
@ -71,6 +46,6 @@ export interface ExploreProps {
updateTopicCount: (count: number) => void;
updateDashboardCount: (count: number) => void;
updatePipelineCount: (count: number) => void;
fetchData: (value: FetchData[]) => void;
fetchData: (value: SearchDataFunctionType[]) => void;
searchResult: ExploreSearchData | undefined;
}

View File

@ -15,54 +15,50 @@
* limitations under the License.
*/
import { AxiosError } from 'axios';
import { isEmpty } from 'lodash';
import { observer } from 'mobx-react';
import { Bucket, FormatedTableData, SearchResponse, Sterm } from 'Models';
import { Bucket, FormatedTableData, Sterm } from 'Models';
import React, { useEffect, useRef, useState } from 'react';
import AppState from '../../AppState';
import { searchData } from '../../axiosAPIs/miscAPI';
import ErrorPlaceHolderES from '../../components/common/error-with-placeholder/ErrorPlaceHolderES';
import PageContainer from '../../components/containers/PageContainer';
import Loader from '../../components/Loader/Loader';
import MyDataHeader from '../../components/my-data/MyDataHeader';
import RecentlyViewed from '../../components/recently-viewed/RecentlyViewed';
import SearchedData from '../../components/searched-data/SearchedData';
import { ERROR500, PAGE_SIZE } from '../../constants/constants';
import { Ownership } from '../../enums/mydata.enum';
import useToastContext from '../../hooks/useToastContext';
import { formatDataResponse } from '../../utils/APIUtils';
import { getCurrentUserId } from '../../utils/CommonUtils';
import {
getAllServices,
getEntityCountByService,
} from '../../utils/ServiceUtils';
import { getEntityCountByService } from '../../utils/ServiceUtils';
import ErrorPlaceHolderES from '../common/error-with-placeholder/ErrorPlaceHolderES';
import PageContainer from '../containers/PageContainer';
import Loader from '../Loader/Loader';
import MyDataHeader from '../my-data/MyDataHeader';
import RecentlyViewed from '../recently-viewed/RecentlyViewed';
import SearchedData from '../searched-data/SearchedData';
import { MyDataProps } from './MyData.interface';
const MyDataPage: React.FC = (): React.ReactElement => {
const showToast = useToastContext();
const MyData: React.FC<MyDataProps> = ({
countServices,
userDetails,
searchResult,
fetchData,
error,
}: MyDataProps): React.ReactElement => {
const [data, setData] = useState<Array<FormatedTableData>>([]);
const [currentPage, setCurrentPage] = useState<number>(1);
const [totalNumberOfValue, setTotalNumberOfValues] = useState<number>(0);
const [isLoading, setIsLoading] = useState<boolean>(true);
const [isEntityLoading, setIsEntityLoading] = useState<boolean>(true);
const [currentTab, setCurrentTab] = useState<number>(1);
const [error, setError] = useState<string>('');
const [filter, setFilter] = useState<string>('');
const [aggregations, setAggregations] = useState<Record<string, Sterm>>();
const [searchIndex] = useState<string>(
'dashboard_search_index,topic_search_index,table_search_index,pipeline_search_index'
);
const [countServices, setCountServices] = useState<number>(0);
const isMounted = useRef<boolean>(false);
const setAssetCount = useRef<boolean>(true);
const getActiveTabClass = (tab: number) => {
return tab === currentTab ? 'active' : '';
};
const getFilters = (): string => {
if (filter === 'owner' && AppState.userDetails.teams) {
const userTeams = !isEmpty(AppState.userDetails)
? AppState.userDetails.teams.map((team) => `${filter}:${team.id}`)
if (filter === 'owner' && userDetails.teams) {
const userTeams = !isEmpty(userDetails)
? userDetails.teams.map((team) => `${filter}:${team.id}`)
: [];
const ownerIds = [...userTeams, `${filter}:${getCurrentUserId()}`];
@ -72,45 +68,19 @@ const MyDataPage: React.FC = (): React.ReactElement => {
return `${filter}:${getCurrentUserId()}`;
};
const fetchTableData = (setAssetCount = false) => {
const fetchTableData = () => {
if (!isEntityLoading) {
setIsLoading(true);
}
searchData(
'',
currentPage,
PAGE_SIZE,
filter ? getFilters() : '',
'',
'',
searchIndex
)
.then((res: SearchResponse) => {
const hits = res.data.hits.hits;
if (hits.length > 0) {
setTotalNumberOfValues(res.data.hits.total.value);
setData(formatDataResponse(hits));
if (setAssetCount) {
setAggregations(res.data.aggregations);
}
setIsLoading(false);
setIsEntityLoading(false);
} else {
setData([]);
setTotalNumberOfValues(0);
setIsLoading(false);
setIsEntityLoading(false);
}
})
.catch((err: AxiosError) => {
setError(err.response?.data?.responseMessage);
showToast({
variant: 'error',
body: err.response?.data?.responseMessage ?? ERROR500,
});
setIsLoading(false);
setIsEntityLoading(false);
});
fetchData({
queryString: '',
from: currentPage,
filters: filter ? getFilters() : '',
sortField: '',
sortOrder: '',
searchIndex: searchIndex,
});
};
const getTabs = () => {
@ -163,14 +133,36 @@ const MyDataPage: React.FC = (): React.ReactElement => {
};
useEffect(() => {
fetchTableData(!isMounted.current);
setAssetCount.current = !isMounted.current;
fetchTableData();
}, [currentPage, filter]);
useEffect(() => {
if (searchResult) {
const hits = searchResult.data.hits.hits;
if (hits.length > 0) {
setTotalNumberOfValues(searchResult.data.hits.total.value);
setData(formatDataResponse(hits));
if (setAssetCount.current) {
setAggregations(searchResult.data.aggregations);
}
setIsLoading(false);
setIsEntityLoading(false);
} else {
setData([]);
setTotalNumberOfValues(0);
setIsLoading(false);
setIsEntityLoading(false);
}
} else {
setIsLoading(false);
setIsEntityLoading(false);
}
}, [searchResult]);
useEffect(() => {
isMounted.current = true;
getAllServices()
.then((res) => setCountServices(res.length))
.catch(() => setCountServices(0));
setAssetCount.current = true;
}, []);
return (
@ -212,4 +204,4 @@ const MyDataPage: React.FC = (): React.ReactElement => {
);
};
export default observer(MyDataPage);
export default MyData;

View File

@ -0,0 +1,10 @@
import { SearchDataFunctionType, SearchResponse } from 'Models';
import { User } from '../../generated/entity/teams/user';
export interface MyDataProps {
countServices: number;
userDetails: User;
error: string;
searchResult: SearchResponse | undefined;
fetchData: (value: SearchDataFunctionType) => void;
}

View File

@ -0,0 +1,282 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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.
*/
/* eslint-disable @typescript-eslint/camelcase */
import {
findAllByTestId,
findByTestId,
findByText,
render,
} from '@testing-library/react';
import { SearchResponse } from 'Models';
import React from 'react';
import { MemoryRouter } from 'react-router-dom';
import { User } from '../../generated/entity/teams/user';
import MyDataPage from './MyData.component';
const mockData = {
data: {
took: 50,
timed_out: false,
_shards: {
total: 1,
successful: 1,
skipped: 0,
failed: 0,
},
hits: {
total: {
value: 12,
relation: 'eq',
},
max_score: 5,
hits: [
{
_index: 'table_search_indexcb2cac4c-735e-474e-a968-da8d8e0b218c',
_type: '_doc',
_id: '53761de6-6c41-431f-9c4e-62d39cf4aba9',
_score: 5,
_source: {
table_id: '53761de6-6c41-431f-9c4e-62d39cf4aba9',
database: 'shopify',
service: 'bigquery',
service_type: 'BigQuery',
table_name: 'dim_address',
suggest: [
{
input: ['bigquery.shopify.dim_address'],
weight: 5,
},
{
input: ['dim_address'],
weight: 10,
},
],
description: 'test description',
table_type: null,
last_updated_timestamp: 1628498201,
column_names: ['address_id', 'shop_id'],
column_descriptions: [
'Unique identifier for the address.',
'The ID of the store. This column is a foreign key reference to the shop_id column in the shops table.',
],
monthly_stats: 0,
weekly_stats: 0,
daily_stats: 0,
tags: ['User.Phone'],
fqdn: 'bigquery.shopify.dim_address',
tier: null,
schema_description: null,
owner: '',
followers: [],
table_entity: {
id: '53761de6-6c41-431f-9c4e-62d39cf4aba9',
name: 'dim_address',
description: 'test table description',
href: 'http://test',
tableType: null,
fullyQualifiedName: 'bigquery.shopify.dim_address',
columns: [
{
name: 'address_id',
columnDataType: 'NUMERIC',
description: 'Unique identifier for the address.',
fullyQualifiedName: 'bigquery.shopify.dim_address.address_id',
tags: [
{
tagFQN: 'PersonalData.Personal',
labelType: 'Derived',
state: 'Suggested',
href: null,
},
{
tagFQN: 'PII.Sensitive',
labelType: 'Derived',
state: 'Suggested',
href: null,
},
{
tagFQN: 'User.Address',
labelType: 'Automated',
state: 'Suggested',
href: null,
},
],
columnConstraint: 'PRIMARY_KEY',
ordinalPosition: 1,
},
],
tableConstraints: null,
usageSummary: {
dailyStats: {
count: 0,
percentileRank: 0,
},
weeklyStats: {
count: 0,
percentileRank: 0,
},
monthlyStats: {
count: 0,
percentileRank: 0,
},
date: '2021-08-09',
},
owner: null,
followers: [],
database: {
id: '2d04ddc1-4c9b-43a3-85fb-3de204d67f32',
type: 'database',
name: 'shopify',
description:
'This database contains tables related to shopify order and related dimensions',
href: 'http://test/test',
},
tags: [],
joins: null,
sampleData: null,
},
},
highlight: {
description: ['data test'],
table_name: ['<b>dim_address</b>'],
},
},
],
},
aggregations: {
'sterms#Tier': {
doc_count_error_upper_bound: 0,
sum_other_doc_count: 0,
buckets: [],
},
'sterms#Tags': {
doc_count_error_upper_bound: 0,
sum_other_doc_count: 0,
buckets: [
{
key: 'PII.Sensitive',
doc_count: 7,
},
],
},
'sterms#Service Type': {
doc_count_error_upper_bound: 0,
sum_other_doc_count: 0,
buckets: [
{
key: 'BigQuery',
doc_count: 12,
},
],
},
},
},
};
const mockUserDetails = {
data: [
{
id: 'e8672538-d479-4390-b81d-a85eb19c8221',
name: 'Cloud_Infra',
displayName: 'Cloud Infra',
description: '',
version: 0.1,
updatedAt: 1634886222355,
updatedBy: 'anonymous',
href: 'http://localhost:8585/api/v1/teams/e8672538-d479-4390-b81d-a85eb19c8221',
},
{
id: '1fffc9a9-33fd-42ca-a605-ab87055bed96',
name: 'Customer_Support',
displayName: 'Customer Support',
description: '',
version: 0.1,
updatedAt: 1634886221511,
updatedBy: 'anonymous',
href: 'http://localhost:8585/api/v1/teams/1fffc9a9-33fd-42ca-a605-ab87055bed96',
},
],
paging: {
total: 2,
},
};
jest.mock('../../axiosAPIs/miscAPI', () => ({
searchData: jest
.fn()
.mockImplementation(() => Promise.resolve({ data: mockData })),
}));
jest.mock('../../components/searched-data/SearchedData', () => {
return jest
.fn()
.mockImplementation(({ children }: { children: React.ReactNode }) => (
<div data-testid="search-data">
<div data-testid="wrapped-content">{children}</div>
</div>
));
});
jest.mock('../../components/recently-viewed/RecentlyViewed', () => {
return jest.fn().mockReturnValue(<p>RecentlyViewed</p>);
});
jest.mock('../../components/my-data/MyDataHeader', () => {
return jest.fn().mockReturnValue(<p>MyDataHeader</p>);
});
jest.mock('../../utils/ServiceUtils', () => ({
getAllServices: jest
.fn()
.mockImplementation(() => Promise.resolve(['test', 'test2', 'test3'])),
getEntityCountByService: jest
.fn()
.mockReturnValue({ tableCount: 4, topicCount: 5, dashboardCount: 6 }),
getTotalEntityCountByService: jest.fn().mockReturnValue(2),
}));
const fetchData = jest.fn();
describe('Test MyData page', () => {
it('Check if there is an element in the page', async () => {
const { container } = render(
<MyDataPage
countServices={0}
error=""
fetchData={fetchData}
searchResult={mockData as unknown as SearchResponse}
userDetails={mockUserDetails as unknown as User}
/>,
{
wrapper: MemoryRouter,
}
);
const pageContainer = await findByTestId(container, 'fluid-container');
const searchData = await findByTestId(container, 'search-data');
const wrappedContent = await findByTestId(container, 'wrapped-content');
const tabs = await findAllByTestId(container, 'tab');
const myDataHeader = await findByText(container, /MyDataHeader/i);
expect(pageContainer).toBeInTheDocument();
expect(searchData).toBeInTheDocument();
expect(wrappedContent).toBeInTheDocument();
expect(myDataHeader).toBeInTheDocument();
expect(tabs.length).toBe(3);
});
});

View File

@ -17,7 +17,7 @@
import { getAllByTestId, getByTestId, render } from '@testing-library/react';
import React from 'react';
import { descriptionData } from '../../pages/my-data/index.mock';
import { descriptionData } from '../MyData/MyData.mock';
import Description from './Description';
describe('Test Description Component', () => {

View File

@ -17,7 +17,7 @@
import { getByTestId, render } from '@testing-library/react';
import React from 'react';
import { miscDetailsData } from '../../pages/my-data/index.mock';
import { miscDetailsData } from '../MyData/MyData.mock';
import MiscDetails from './MiscDetails';
describe('Test MiscDetails Component', () => {

View File

@ -19,7 +19,7 @@ import PropTypes from 'prop-types';
import React from 'react';
import { Link } from 'react-router-dom';
import { getDatasetDetailsPath } from '../../constants/constants';
import { dummyData } from '../../pages/my-data/index.mock';
import { dummyData } from '../MyData/MyData.mock';
import Description from './Description';
import QueryDetails from './QueryDetails';

View File

@ -18,7 +18,7 @@
import { getByTestId, render } from '@testing-library/react';
import React from 'react';
import { MemoryRouter } from 'react-router-dom';
import { dataDetails } from '../../pages/my-data/index.mock';
import { dataDetails } from '../MyData/MyData.mock';
import MyData from './MyData';
describe('Test MyData Component', () => {

View File

@ -17,7 +17,7 @@
import { getByTestId, render } from '@testing-library/react';
import React from 'react';
import { queryDetailsData } from '../../pages/my-data/index.mock';
import { queryDetailsData } from '../MyData/MyData.mock';
import QueryDetails from './QueryDetails';
describe('Test QueryDetails Component', () => {

View File

@ -18,7 +18,7 @@
import { findByTestId, render } from '@testing-library/react';
import React from 'react';
import { MemoryRouter } from 'react-router-dom';
import { statData } from '../../pages/my-data/index.mock';
import { statData } from '../MyData/MyData.mock';
import Stats from './Stats';
describe('Test Stats Component', () => {

View File

@ -16,8 +16,8 @@
*/
import { FilterObject } from 'Models';
import { getCurrentUserId } from '../../utils/CommonUtils';
import { getFilterString } from '../../utils/FilterUtils';
import { getCurrentUserId } from '../utils/CommonUtils';
import { getFilterString } from '../utils/FilterUtils';
export const myDataFilterType = [
{ key: 'Owned', value: 'owner' },

View File

@ -17,13 +17,9 @@
import { lowerCase } from 'lodash';
import { AggregationType, Bucket } from 'Models';
import {
tableSortingFields,
tiers,
topicSortingFields,
} from '../../constants/constants';
import { SearchIndex } from '../../enums/search.enum';
import { Icons } from '../../utils/SvgUtils';
import { SearchIndex } from '../enums/search.enum';
import { Icons } from '../utils/SvgUtils';
import { tableSortingFields, tiers, topicSortingFields } from './constants';
export const getBucketList = (buckets: Array<Bucket>) => {
let bucketList: Array<Bucket> = [...tiers];

View File

@ -324,6 +324,16 @@ declare module 'Models' {
rows: Array<Array<string>>;
};
export type SearchDataFunctionType = {
queryString: string;
from: number;
size?: number;
filters: string;
sortField: string;
sortOrder: string;
searchIndex: string;
};
// topic interface start
export interface Topic {
cleanupPolicies: string[];

View File

@ -0,0 +1,83 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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 { observer } from 'mobx-react';
import { SearchDataFunctionType, SearchResponse } from 'Models';
import React, { useEffect, useState } from 'react';
import AppState from '../../AppState';
import { searchData } from '../../axiosAPIs/miscAPI';
import Loader from '../../components/Loader/Loader';
import MyData from '../../components/MyData/MyData.component';
import { ERROR500, PAGE_SIZE } from '../../constants/constants';
import useToastContext from '../../hooks/useToastContext';
import { getAllServices } from '../../utils/ServiceUtils';
const MyDataPage = () => {
const showToast = useToastContext();
const [error, setError] = useState<string>('');
const [countServices, setCountServices] = useState<number>(0);
const [isLoading, setIsLoading] = useState<boolean>(true);
const [searchResult, setSearchResult] = useState<SearchResponse>();
const fetchData = (value: SearchDataFunctionType) => {
searchData(
value.queryString,
value.from,
PAGE_SIZE,
value.filters,
value.sortField,
value.sortOrder,
value.searchIndex
)
.then((res: SearchResponse) => {
setSearchResult(res);
})
.catch((err: AxiosError) => {
setError(err.response?.data?.responseMessage);
showToast({
variant: 'error',
body: err.response?.data?.responseMessage ?? ERROR500,
});
});
};
useEffect(() => {
getAllServices()
.then((res) => setCountServices(res.length))
.catch(() => setCountServices(0));
setIsLoading(false);
}, []);
return (
<div data-testid="my-data-page-conatiner">
{isLoading ? (
<Loader />
) : (
<MyData
countServices={countServices}
error={error}
fetchData={fetchData}
searchResult={searchResult}
userDetails={AppState.userDetails}
/>
)}
</div>
);
};
export default observer(MyDataPage);

View File

@ -0,0 +1,37 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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 { findByTestId, render } from '@testing-library/react';
import React from 'react';
import MyDataPageComponent from './MyDataPage.component';
jest.mock('../../components/LandingPage/MyData.component', () => {
return jest.fn().mockReturnValue(<p>Mydata component</p>);
});
describe('Test MyData page component', () => {
it('Component should render', async () => {
const { container } = render(<MyDataPageComponent />);
const myDataPageContainer = await findByTestId(
container,
'my-data-page-conatiner'
);
expect(myDataPageContainer).toBeInTheDocument();
});
});

View File

@ -16,15 +16,14 @@
*/
import { AxiosError } from 'axios';
import { Bucket, SearchResponse } from 'Models';
import { Bucket, SearchDataFunctionType, SearchResponse } from 'Models';
import React, { FunctionComponent, useEffect, useState } from 'react';
import { useParams } from 'react-router-dom';
import { searchData } from '../../axiosAPIs/miscAPI';
import Explore from '../../components/Explore/Explore.component';
import {
ExploreSearchData,
FetchData,
Params,
UrlParams,
} from '../../components/Explore/explore.interface';
import Loader from '../../components/Loader/Loader';
import { ERROR500 } from '../../constants/constants';
@ -36,7 +35,7 @@ const ExplorePage: FunctionComponent = () => {
const showToast = useToastContext();
const [isLoading, setIsLoading] = useState(false);
const [error, setError] = useState<string>('');
const { searchQuery, tab } = useParams<Params>();
const { searchQuery, tab } = useParams<UrlParams>();
const [searchText, setSearchText] = useState<string>(searchQuery || '');
const [tableCount, setTableCount] = useState<number>(0);
const [topicCount, setTopicCount] = useState<number>(0);
@ -151,7 +150,7 @@ const ExplorePage: FunctionComponent = () => {
);
};
const fetchData = (value: FetchData[]) => {
const fetchData = (value: SearchDataFunctionType[]) => {
setIsLoading(true);
const promiseValue = value.map((d) => {
return searchData(

View File

@ -1,239 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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.
*/
/* eslint-disable @typescript-eslint/camelcase */
import {
findAllByTestId,
findByTestId,
findByText,
render,
} from '@testing-library/react';
import React from 'react';
import { MemoryRouter } from 'react-router-dom';
import MyDataPage from './index';
const mockData = {
took: 50,
timed_out: false,
_shards: {
total: 1,
successful: 1,
skipped: 0,
failed: 0,
},
hits: {
total: {
value: 12,
relation: 'eq',
},
max_score: 5,
hits: [
{
_index: 'table_search_indexcb2cac4c-735e-474e-a968-da8d8e0b218c',
_type: '_doc',
_id: '53761de6-6c41-431f-9c4e-62d39cf4aba9',
_score: 5,
_source: {
table_id: '53761de6-6c41-431f-9c4e-62d39cf4aba9',
database: 'shopify',
service: 'bigquery',
service_type: 'BigQuery',
table_name: 'dim_address',
suggest: [
{
input: ['bigquery.shopify.dim_address'],
weight: 5,
},
{
input: ['dim_address'],
weight: 10,
},
],
description: 'test description',
table_type: null,
last_updated_timestamp: 1628498201,
column_names: ['address_id', 'shop_id'],
column_descriptions: [
'Unique identifier for the address.',
'The ID of the store. This column is a foreign key reference to the shop_id column in the shops table.',
],
monthly_stats: 0,
weekly_stats: 0,
daily_stats: 0,
tags: ['User.Phone'],
fqdn: 'bigquery.shopify.dim_address',
tier: null,
schema_description: null,
owner: '',
followers: [],
table_entity: {
id: '53761de6-6c41-431f-9c4e-62d39cf4aba9',
name: 'dim_address',
description: 'test table description',
href: 'http://test',
tableType: null,
fullyQualifiedName: 'bigquery.shopify.dim_address',
columns: [
{
name: 'address_id',
columnDataType: 'NUMERIC',
description: 'Unique identifier for the address.',
fullyQualifiedName: 'bigquery.shopify.dim_address.address_id',
tags: [
{
tagFQN: 'PersonalData.Personal',
labelType: 'Derived',
state: 'Suggested',
href: null,
},
{
tagFQN: 'PII.Sensitive',
labelType: 'Derived',
state: 'Suggested',
href: null,
},
{
tagFQN: 'User.Address',
labelType: 'Automated',
state: 'Suggested',
href: null,
},
],
columnConstraint: 'PRIMARY_KEY',
ordinalPosition: 1,
},
],
tableConstraints: null,
usageSummary: {
dailyStats: {
count: 0,
percentileRank: 0,
},
weeklyStats: {
count: 0,
percentileRank: 0,
},
monthlyStats: {
count: 0,
percentileRank: 0,
},
date: '2021-08-09',
},
owner: null,
followers: [],
database: {
id: '2d04ddc1-4c9b-43a3-85fb-3de204d67f32',
type: 'database',
name: 'shopify',
description:
'This database contains tables related to shopify order and related dimensions',
href: 'http://test/test',
},
tags: [],
joins: null,
sampleData: null,
},
},
highlight: {
description: ['data test'],
table_name: ['<b>dim_address</b>'],
},
},
],
},
aggregations: {
'sterms#Tier': {
doc_count_error_upper_bound: 0,
sum_other_doc_count: 0,
buckets: [],
},
'sterms#Tags': {
doc_count_error_upper_bound: 0,
sum_other_doc_count: 0,
buckets: [
{
key: 'PII.Sensitive',
doc_count: 7,
},
],
},
'sterms#Service Type': {
doc_count_error_upper_bound: 0,
sum_other_doc_count: 0,
buckets: [
{
key: 'BigQuery',
doc_count: 12,
},
],
},
},
};
jest.mock('../../axiosAPIs/miscAPI', () => ({
searchData: jest
.fn()
.mockImplementation(() => Promise.resolve({ data: mockData })),
}));
jest.mock('../../components/searched-data/SearchedData', () => {
return jest
.fn()
.mockImplementation(({ children }: { children: React.ReactNode }) => (
<div data-testid="search-data">
<div data-testid="wrapped-content">{children}</div>
</div>
));
});
jest.mock('../../components/recently-viewed/RecentlyViewed', () => {
return jest.fn().mockReturnValue(<p>RecentlyViewed</p>);
});
jest.mock('../../components/my-data/MyDataHeader', () => {
return jest.fn().mockReturnValue(<p>MyDataHeader</p>);
});
jest.mock('../../utils/ServiceUtils', () => ({
getAllServices: jest
.fn()
.mockImplementation(() => Promise.resolve(['test', 'test2', 'test3'])),
getEntityCountByService: jest
.fn()
.mockReturnValue({ tableCount: 4, topicCount: 5, dashboardCount: 6 }),
getTotalEntityCountByService: jest.fn().mockReturnValue(2),
}));
describe('Test MyData page', () => {
it('Check if there is an element in the page', async () => {
const { container } = render(<MyDataPage />, {
wrapper: MemoryRouter,
});
const pageContainer = await findByTestId(container, 'fluid-container');
const searchData = await findByTestId(container, 'search-data');
const wrappedContent = await findByTestId(container, 'wrapped-content');
const tabs = await findAllByTestId(container, 'tab');
const myDataHeader = await findByText(container, /MyDataHeader/i);
expect(pageContainer).toBeInTheDocument();
expect(searchData).toBeInTheDocument();
expect(wrappedContent).toBeInTheDocument();
expect(myDataHeader).toBeInTheDocument();
expect(tabs.length).toBe(3);
});
});

View File

@ -1,7 +1,7 @@
import React, { useEffect, useState } from 'react';
import { FirstTimeUserModal } from '../../components/Modals/FirstTimeUserModal/FirstTimeUserModal';
import { useTour } from '../../hooks/useTour';
import MyDataPage from '../my-data';
// import MyDataPage from '../../components/LandingPage/MyData.component';
const TourPage = () => {
const [showFirstTimeUserModal, setShowFirstTimeUserModal] = useState(true);
@ -17,7 +17,7 @@ const TourPage = () => {
return (
<div>
<MyDataPage />
{/* <MyDataPage /> */}
{showFirstTimeUserModal && (
<FirstTimeUserModal
onCancel={() => setShowFirstTimeUserModal(true)}

View File

@ -25,7 +25,7 @@ import MyDashBoardPage from '../pages/dashboard-details';
import DatabaseDetails from '../pages/database-details/index';
import DatasetDetailsPage from '../pages/DatasetDetailsPage/DatasetDetailsPage.component';
import ExplorePage from '../pages/explore/ExplorePage.component';
import MyDataPage from '../pages/my-data';
import MyDataPage from '../pages/MyDataPage/MyDataPage.component';
import MyPipelinePage from '../pages/Pipeline-details';
import ReportsPage from '../pages/reports';
import Scorecard from '../pages/scorecard';