test(ui): e2e tests for recently viewed (#12506)

This commit is contained in:
Chirag Madlani 2023-07-19 21:24:02 +05:30 committed by GitHub
parent 0c6435ae9b
commit 2260b8da32
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 259 additions and 44 deletions

View File

@ -1207,7 +1207,7 @@ export const followAndOwnTheEntity = (termObj) => {
// Check followed entity on mydata page
cy.get('[data-testid="following-data-container"]')
.find(`[data-testid="Following data-${termObj.displayName}"]`)
.find(`[data-testid="following-${termObj.displayName}"]`)
.should('be.visible');
// Check owned entity

View File

@ -132,6 +132,7 @@ export const SEARCH_ENTITY_MLMODEL = {
term: 'eta_predictions',
entity: MYDATA_SUMMARY_OPTIONS.mlmodels,
serviceName: 'mlflow_svc',
displayName: 'ETA Predictions',
},
};

View File

@ -0,0 +1,125 @@
/*
* 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 {
interceptURL,
verifyResponseStatusCode,
visitEntityDetailsPage,
} from '../../common/common';
import {
SEARCH_ENTITY_DASHBOARD,
SEARCH_ENTITY_MLMODEL,
SEARCH_ENTITY_PIPELINE,
SEARCH_ENTITY_TABLE,
SEARCH_ENTITY_TOPIC,
} from '../../constants/constants';
// eslint-disable-next-line spaced-comment
/// <reference types="cypress" />
// Update list if we support this for other entities too
const FOLLOWING_ENTITIES = [
SEARCH_ENTITY_TABLE.table_2,
SEARCH_ENTITY_DASHBOARD.dashboard_1,
SEARCH_ENTITY_TOPIC.topic_1,
SEARCH_ENTITY_PIPELINE.pipeline_1,
SEARCH_ENTITY_MLMODEL.mlmodel_2,
];
const followEntity = ({ term, serviceName, entity }, isUnfollow) => {
visitEntityDetailsPage(term, serviceName, entity);
interceptURL(
isUnfollow ? 'DELETE' : 'PUT',
isUnfollow ? '/api/v1/*/*/followers/*' : '/api/v1/*/*/followers',
'waitAfterFollow'
);
cy.get('[data-testid="entity-follow-button"]')
.scrollIntoView()
.should('be.visible')
.click();
verifyResponseStatusCode('@waitAfterFollow', 200);
};
describe('Following data assets', () => {
beforeEach(() => {
cy.login();
});
it('following section should be present', () => {
cy.get('[data-testid="following-data-container"]')
.scrollIntoView()
.should('be.visible');
cy.get('[data-testid="following-data-container"]').contains(
'You have not followed anything yet.'
);
cy.get(
`[data-testid="following-data-container"] .right-panel-list-item`
).should('have.length', 0);
});
// Follow entity
FOLLOWING_ENTITIES.map((entity, index) => {
it(`following section should have ${entity.term} followed`, () => {
followEntity(entity);
interceptURL(
'GET',
'/api/v1/feed?type=Announcement&activeAnnouncement=true',
'getAnnoucemenets'
);
cy.clickOnLogo();
verifyResponseStatusCode('@getAnnoucemenets', 200);
cy.get(`[data-testid="following-${entity.displayName}"]`).should(
'be.visible'
);
// Checking count of following
cy.get(`[data-testid="following-data"]`).should('contain', index + 1);
});
});
// UnFollow entity
FOLLOWING_ENTITIES.map((entity, index) => {
it(`unfollowing entity ${entity.term} should removed from following section`, () => {
followEntity(entity, true);
interceptURL(
'GET',
'/api/v1/feed?type=Announcement&activeAnnouncement=true',
'getAnnoucemenets'
);
cy.clickOnLogo();
verifyResponseStatusCode('@getAnnoucemenets', 200);
cy.get(`[data-testid="following-${entity.displayName}"]`).should(
'not.exist'
);
if (index === FOLLOWING_ENTITIES.length - 1) {
// Checking count of following
cy.get(`[data-testid="following-data"]`).should('not.exist');
} else {
// Checking count of following
cy.get(`[data-testid="following-data"]`).should(
'contain',
FOLLOWING_ENTITIES.length - (index + 1)
);
}
});
});
});

View File

@ -0,0 +1,76 @@
/*
* 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 {
interceptURL,
verifyResponseStatusCode,
visitEntityDetailsPage,
} from '../../common/common';
import {
SEARCH_ENTITY_DASHBOARD,
SEARCH_ENTITY_MLMODEL,
SEARCH_ENTITY_PIPELINE,
SEARCH_ENTITY_TABLE,
SEARCH_ENTITY_TOPIC,
} from '../../constants/constants';
// eslint-disable-next-line spaced-comment
/// <reference types="cypress" />
// Update list if we support this for other entities too
const RECENTLY_VIEW_ENTITIES = [
SEARCH_ENTITY_TABLE.table_2,
SEARCH_ENTITY_DASHBOARD.dashboard_1,
SEARCH_ENTITY_TOPIC.topic_1,
SEARCH_ENTITY_PIPELINE.pipeline_1,
SEARCH_ENTITY_MLMODEL.mlmodel_2,
];
describe('Recently viwed data assets', () => {
beforeEach(() => {
cy.login();
});
it('recently view section should be present', () => {
cy.get('[data-testid="recently-viewed-container"]')
.scrollIntoView()
.should('be.visible');
cy.get(
`[data-testid="recently-viewed-container"] .right-panel-list-item`
).should('have.length', 0);
});
it(`recently view section should have at max list of 5 entity`, () => {
RECENTLY_VIEW_ENTITIES.map((entity, index) => {
visitEntityDetailsPage(entity.term, entity.serviceName, entity.entity);
interceptURL(
'GET',
'/api/v1/feed?type=Announcement&activeAnnouncement=true',
'getAnnoucemenets'
);
cy.clickOnLogo();
verifyResponseStatusCode('@getAnnoucemenets', 200);
cy.get(
`[data-testid="recently-viewed-container"] [title="${entity.displayName}"]`
).should('be.visible');
// Checking count since we will only show max 5 not more than that
cy.get(
`[data-testid="recently-viewed-container"] .right-panel-list-item`
).should('have.length', index > 4 ? 5 : index + 1);
});
});
});

View File

@ -125,7 +125,7 @@ const RightSidebar = ({
headerTextLabel={t('label.following')}
loading={isLoadingOwnedData}
noDataPlaceholder={t('message.not-followed-anything')}
testIDText="Following data"
testIDText="following"
/>
</div>
<div className="p-md" data-testid="recently-viewed-container">

View File

@ -77,7 +77,6 @@ import { ResourceEntity } from '../PermissionProvider/PermissionProvider.interfa
import { PipeLineDetailsProp } from './PipelineDetails.interface';
const PipelineDetails = ({
followers,
pipelineDetails,
fetchPipeline,
descriptionUpdateHandler,
@ -93,6 +92,7 @@ const PipelineDetails = ({
const { tab } = useParams<{ tab: EntityTabs }>();
const { t } = useTranslation();
const { postFeed, deleteFeed, updateFeed } = useActivityFeedProvider();
const userID = getCurrentUserId();
const {
deleted,
owner,
@ -102,6 +102,7 @@ const PipelineDetails = ({
tier,
tags,
entityFqn,
followers,
} = useMemo(() => {
return {
deleted: pipelineDetails.deleted,
@ -114,6 +115,7 @@ const PipelineDetails = ({
tags: getTagsWithoutTier(pipelineDetails.tags ?? []),
entityName: getEntityName(pipelineDetails),
entityFqn: pipelineDetails.fullyQualifiedName ?? '',
followers: pipelineDetails.followers ?? [],
};
}, [pipelineDetails]);
@ -193,8 +195,8 @@ const PipelineDetails = ({
}, [pipelineDetails.id]);
const isFollowing = useMemo(
() => followers.some(({ id }: { id: string }) => id === getCurrentUserId()),
[followers]
() => followers.some(({ id }: { id: string }) => id === userID),
[followers, userID]
);
const onTaskUpdate = async (taskDescription: string) => {
@ -297,13 +299,13 @@ const PipelineDetails = ({
}
};
const followPipeline = async () => {
const followPipeline = useCallback(async () => {
if (isFollowing) {
await unFollowPipelineHandler(getEntityFeedCount);
} else {
await followPipelineHandler(getEntityFeedCount);
}
};
}, [isFollowing, followPipelineHandler, unFollowPipelineHandler]);
const onThreadLinkSelect = (link: string, threadType?: ThreadType) => {
setThreadLink(link);

View File

@ -13,13 +13,11 @@
import { Operation } from 'fast-json-patch';
import { Pipeline } from '../../generated/entity/data/pipeline';
import { EntityReference } from '../../generated/type/entityReference';
import { Paging } from '../../generated/type/paging';
export interface PipeLineDetailsProp {
pipelineFQN: string;
pipelineDetails: Pipeline;
followers: Array<EntityReference>;
paging: Paging;
fetchPipeline: () => void;
followPipelineHandler: (fetchCount: () => void) => Promise<void>;

View File

@ -33,7 +33,6 @@ import {
import { getVersionPath } from '../../constants/constants';
import { EntityType } from '../../enums/entity.enum';
import { Pipeline } from '../../generated/entity/data/pipeline';
import { EntityReference } from '../../generated/type/entityReference';
import { Paging } from '../../generated/type/paging';
import {
addToRecentViewed,
@ -59,7 +58,6 @@ const PipelineDetailsPage = () => {
);
const [isLoading, setLoading] = useState<boolean>(true);
const [followers, setFollowers] = useState<Array<EntityReference>>([]);
const [isError, setIsError] = useState(false);
@ -71,6 +69,8 @@ const PipelineDetailsPage = () => {
const { getEntityPermissionByFqn } = usePermissionProvider();
const { followers = [] } = pipelineDetails;
const fetchResourcePermission = async (entityFqn: string) => {
setLoading(true);
try {
@ -143,39 +143,53 @@ const PipelineDetailsPage = () => {
}
};
const followPipeline = async (fetchCount: () => void) => {
try {
const res = await addFollower(pipelineId, USERId);
const { newValue } = res.changeDescription.fieldsAdded[0];
setFollowers([...followers, ...newValue]);
fetchCount();
} catch (error) {
showErrorToast(
error as AxiosError,
t('server.entity-follow-error', {
entity: getEntityName(pipelineDetails),
})
);
}
};
const followPipeline = useCallback(
async (fetchCount: () => void) => {
try {
const res = await addFollower(pipelineId, USERId);
const { newValue } = res.changeDescription.fieldsAdded[0];
const newFollowers = [...(followers ?? []), ...newValue];
setPipelineDetails((prev) => {
return { ...prev, followers: newFollowers };
});
const unFollowPipeline = async (fetchCount: () => void) => {
try {
const res = await removeFollower(pipelineId, USERId);
const { oldValue } = res.changeDescription.fieldsDeleted[0];
setFollowers(
followers.filter((follower) => follower.id !== oldValue[0].id)
);
fetchCount();
} catch (error) {
showErrorToast(
error as AxiosError,
t('server.entity-unfollow-error', {
entity: getEntityName(pipelineDetails),
})
);
}
};
fetchCount();
} catch (error) {
showErrorToast(
error as AxiosError,
t('server.entity-follow-error', {
entity: getEntityName(pipelineDetails),
})
);
}
},
[followers, USERId]
);
const unFollowPipeline = useCallback(
async (fetchCount: () => void) => {
try {
const res = await removeFollower(pipelineId, USERId);
const { oldValue } = res.changeDescription.fieldsDeleted[0];
setPipelineDetails((prev) => ({
...prev,
followers: followers.filter(
(follower) => follower.id !== oldValue[0].id
),
}));
fetchCount();
} catch (error) {
showErrorToast(
error as AxiosError,
t('server.entity-unfollow-error', {
entity: getEntityName(pipelineDetails),
})
);
}
},
[followers, USERId]
);
const descriptionUpdateHandler = async (updatedPipeline: Pipeline) => {
try {
@ -261,7 +275,6 @@ const PipelineDetailsPage = () => {
descriptionUpdateHandler={descriptionUpdateHandler}
fetchPipeline={() => fetchPipelineDetail(pipelineFQN)}
followPipelineHandler={followPipeline}
followers={followers}
paging={paging}
pipelineDetails={pipelineDetails}
pipelineFQN={pipelineFQN}