mirror of
https://github.com/open-metadata/OpenMetadata.git
synced 2025-10-26 08:13:11 +00:00
test(ui): e2e tests for recently viewed (#12506)
This commit is contained in:
parent
0c6435ae9b
commit
2260b8da32
@ -1207,7 +1207,7 @@ export const followAndOwnTheEntity = (termObj) => {
|
|||||||
|
|
||||||
// Check followed entity on mydata page
|
// Check followed entity on mydata page
|
||||||
cy.get('[data-testid="following-data-container"]')
|
cy.get('[data-testid="following-data-container"]')
|
||||||
.find(`[data-testid="Following data-${termObj.displayName}"]`)
|
.find(`[data-testid="following-${termObj.displayName}"]`)
|
||||||
.should('be.visible');
|
.should('be.visible');
|
||||||
|
|
||||||
// Check owned entity
|
// Check owned entity
|
||||||
|
|||||||
@ -132,6 +132,7 @@ export const SEARCH_ENTITY_MLMODEL = {
|
|||||||
term: 'eta_predictions',
|
term: 'eta_predictions',
|
||||||
entity: MYDATA_SUMMARY_OPTIONS.mlmodels,
|
entity: MYDATA_SUMMARY_OPTIONS.mlmodels,
|
||||||
serviceName: 'mlflow_svc',
|
serviceName: 'mlflow_svc',
|
||||||
|
displayName: 'ETA Predictions',
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -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)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
@ -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);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
@ -125,7 +125,7 @@ const RightSidebar = ({
|
|||||||
headerTextLabel={t('label.following')}
|
headerTextLabel={t('label.following')}
|
||||||
loading={isLoadingOwnedData}
|
loading={isLoadingOwnedData}
|
||||||
noDataPlaceholder={t('message.not-followed-anything')}
|
noDataPlaceholder={t('message.not-followed-anything')}
|
||||||
testIDText="Following data"
|
testIDText="following"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className="p-md" data-testid="recently-viewed-container">
|
<div className="p-md" data-testid="recently-viewed-container">
|
||||||
|
|||||||
@ -77,7 +77,6 @@ import { ResourceEntity } from '../PermissionProvider/PermissionProvider.interfa
|
|||||||
import { PipeLineDetailsProp } from './PipelineDetails.interface';
|
import { PipeLineDetailsProp } from './PipelineDetails.interface';
|
||||||
|
|
||||||
const PipelineDetails = ({
|
const PipelineDetails = ({
|
||||||
followers,
|
|
||||||
pipelineDetails,
|
pipelineDetails,
|
||||||
fetchPipeline,
|
fetchPipeline,
|
||||||
descriptionUpdateHandler,
|
descriptionUpdateHandler,
|
||||||
@ -93,6 +92,7 @@ const PipelineDetails = ({
|
|||||||
const { tab } = useParams<{ tab: EntityTabs }>();
|
const { tab } = useParams<{ tab: EntityTabs }>();
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const { postFeed, deleteFeed, updateFeed } = useActivityFeedProvider();
|
const { postFeed, deleteFeed, updateFeed } = useActivityFeedProvider();
|
||||||
|
const userID = getCurrentUserId();
|
||||||
const {
|
const {
|
||||||
deleted,
|
deleted,
|
||||||
owner,
|
owner,
|
||||||
@ -102,6 +102,7 @@ const PipelineDetails = ({
|
|||||||
tier,
|
tier,
|
||||||
tags,
|
tags,
|
||||||
entityFqn,
|
entityFqn,
|
||||||
|
followers,
|
||||||
} = useMemo(() => {
|
} = useMemo(() => {
|
||||||
return {
|
return {
|
||||||
deleted: pipelineDetails.deleted,
|
deleted: pipelineDetails.deleted,
|
||||||
@ -114,6 +115,7 @@ const PipelineDetails = ({
|
|||||||
tags: getTagsWithoutTier(pipelineDetails.tags ?? []),
|
tags: getTagsWithoutTier(pipelineDetails.tags ?? []),
|
||||||
entityName: getEntityName(pipelineDetails),
|
entityName: getEntityName(pipelineDetails),
|
||||||
entityFqn: pipelineDetails.fullyQualifiedName ?? '',
|
entityFqn: pipelineDetails.fullyQualifiedName ?? '',
|
||||||
|
followers: pipelineDetails.followers ?? [],
|
||||||
};
|
};
|
||||||
}, [pipelineDetails]);
|
}, [pipelineDetails]);
|
||||||
|
|
||||||
@ -193,8 +195,8 @@ const PipelineDetails = ({
|
|||||||
}, [pipelineDetails.id]);
|
}, [pipelineDetails.id]);
|
||||||
|
|
||||||
const isFollowing = useMemo(
|
const isFollowing = useMemo(
|
||||||
() => followers.some(({ id }: { id: string }) => id === getCurrentUserId()),
|
() => followers.some(({ id }: { id: string }) => id === userID),
|
||||||
[followers]
|
[followers, userID]
|
||||||
);
|
);
|
||||||
|
|
||||||
const onTaskUpdate = async (taskDescription: string) => {
|
const onTaskUpdate = async (taskDescription: string) => {
|
||||||
@ -297,13 +299,13 @@ const PipelineDetails = ({
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const followPipeline = async () => {
|
const followPipeline = useCallback(async () => {
|
||||||
if (isFollowing) {
|
if (isFollowing) {
|
||||||
await unFollowPipelineHandler(getEntityFeedCount);
|
await unFollowPipelineHandler(getEntityFeedCount);
|
||||||
} else {
|
} else {
|
||||||
await followPipelineHandler(getEntityFeedCount);
|
await followPipelineHandler(getEntityFeedCount);
|
||||||
}
|
}
|
||||||
};
|
}, [isFollowing, followPipelineHandler, unFollowPipelineHandler]);
|
||||||
|
|
||||||
const onThreadLinkSelect = (link: string, threadType?: ThreadType) => {
|
const onThreadLinkSelect = (link: string, threadType?: ThreadType) => {
|
||||||
setThreadLink(link);
|
setThreadLink(link);
|
||||||
|
|||||||
@ -13,13 +13,11 @@
|
|||||||
|
|
||||||
import { Operation } from 'fast-json-patch';
|
import { Operation } from 'fast-json-patch';
|
||||||
import { Pipeline } from '../../generated/entity/data/pipeline';
|
import { Pipeline } from '../../generated/entity/data/pipeline';
|
||||||
import { EntityReference } from '../../generated/type/entityReference';
|
|
||||||
import { Paging } from '../../generated/type/paging';
|
import { Paging } from '../../generated/type/paging';
|
||||||
|
|
||||||
export interface PipeLineDetailsProp {
|
export interface PipeLineDetailsProp {
|
||||||
pipelineFQN: string;
|
pipelineFQN: string;
|
||||||
pipelineDetails: Pipeline;
|
pipelineDetails: Pipeline;
|
||||||
followers: Array<EntityReference>;
|
|
||||||
paging: Paging;
|
paging: Paging;
|
||||||
fetchPipeline: () => void;
|
fetchPipeline: () => void;
|
||||||
followPipelineHandler: (fetchCount: () => void) => Promise<void>;
|
followPipelineHandler: (fetchCount: () => void) => Promise<void>;
|
||||||
|
|||||||
@ -33,7 +33,6 @@ import {
|
|||||||
import { getVersionPath } from '../../constants/constants';
|
import { getVersionPath } from '../../constants/constants';
|
||||||
import { EntityType } from '../../enums/entity.enum';
|
import { EntityType } from '../../enums/entity.enum';
|
||||||
import { Pipeline } from '../../generated/entity/data/pipeline';
|
import { Pipeline } from '../../generated/entity/data/pipeline';
|
||||||
import { EntityReference } from '../../generated/type/entityReference';
|
|
||||||
import { Paging } from '../../generated/type/paging';
|
import { Paging } from '../../generated/type/paging';
|
||||||
import {
|
import {
|
||||||
addToRecentViewed,
|
addToRecentViewed,
|
||||||
@ -59,7 +58,6 @@ const PipelineDetailsPage = () => {
|
|||||||
);
|
);
|
||||||
|
|
||||||
const [isLoading, setLoading] = useState<boolean>(true);
|
const [isLoading, setLoading] = useState<boolean>(true);
|
||||||
const [followers, setFollowers] = useState<Array<EntityReference>>([]);
|
|
||||||
|
|
||||||
const [isError, setIsError] = useState(false);
|
const [isError, setIsError] = useState(false);
|
||||||
|
|
||||||
@ -71,6 +69,8 @@ const PipelineDetailsPage = () => {
|
|||||||
|
|
||||||
const { getEntityPermissionByFqn } = usePermissionProvider();
|
const { getEntityPermissionByFqn } = usePermissionProvider();
|
||||||
|
|
||||||
|
const { followers = [] } = pipelineDetails;
|
||||||
|
|
||||||
const fetchResourcePermission = async (entityFqn: string) => {
|
const fetchResourcePermission = async (entityFqn: string) => {
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
try {
|
try {
|
||||||
@ -143,11 +143,16 @@ const PipelineDetailsPage = () => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const followPipeline = async (fetchCount: () => void) => {
|
const followPipeline = useCallback(
|
||||||
|
async (fetchCount: () => void) => {
|
||||||
try {
|
try {
|
||||||
const res = await addFollower(pipelineId, USERId);
|
const res = await addFollower(pipelineId, USERId);
|
||||||
const { newValue } = res.changeDescription.fieldsAdded[0];
|
const { newValue } = res.changeDescription.fieldsAdded[0];
|
||||||
setFollowers([...followers, ...newValue]);
|
const newFollowers = [...(followers ?? []), ...newValue];
|
||||||
|
setPipelineDetails((prev) => {
|
||||||
|
return { ...prev, followers: newFollowers };
|
||||||
|
});
|
||||||
|
|
||||||
fetchCount();
|
fetchCount();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
showErrorToast(
|
showErrorToast(
|
||||||
@ -157,15 +162,22 @@ const PipelineDetailsPage = () => {
|
|||||||
})
|
})
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
};
|
},
|
||||||
|
[followers, USERId]
|
||||||
|
);
|
||||||
|
|
||||||
const unFollowPipeline = async (fetchCount: () => void) => {
|
const unFollowPipeline = useCallback(
|
||||||
|
async (fetchCount: () => void) => {
|
||||||
try {
|
try {
|
||||||
const res = await removeFollower(pipelineId, USERId);
|
const res = await removeFollower(pipelineId, USERId);
|
||||||
const { oldValue } = res.changeDescription.fieldsDeleted[0];
|
const { oldValue } = res.changeDescription.fieldsDeleted[0];
|
||||||
setFollowers(
|
setPipelineDetails((prev) => ({
|
||||||
followers.filter((follower) => follower.id !== oldValue[0].id)
|
...prev,
|
||||||
);
|
followers: followers.filter(
|
||||||
|
(follower) => follower.id !== oldValue[0].id
|
||||||
|
),
|
||||||
|
}));
|
||||||
|
|
||||||
fetchCount();
|
fetchCount();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
showErrorToast(
|
showErrorToast(
|
||||||
@ -175,7 +187,9 @@ const PipelineDetailsPage = () => {
|
|||||||
})
|
})
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
};
|
},
|
||||||
|
[followers, USERId]
|
||||||
|
);
|
||||||
|
|
||||||
const descriptionUpdateHandler = async (updatedPipeline: Pipeline) => {
|
const descriptionUpdateHandler = async (updatedPipeline: Pipeline) => {
|
||||||
try {
|
try {
|
||||||
@ -261,7 +275,6 @@ const PipelineDetailsPage = () => {
|
|||||||
descriptionUpdateHandler={descriptionUpdateHandler}
|
descriptionUpdateHandler={descriptionUpdateHandler}
|
||||||
fetchPipeline={() => fetchPipelineDetail(pipelineFQN)}
|
fetchPipeline={() => fetchPipelineDetail(pipelineFQN)}
|
||||||
followPipelineHandler={followPipeline}
|
followPipelineHandler={followPipeline}
|
||||||
followers={followers}
|
|
||||||
paging={paging}
|
paging={paging}
|
||||||
pipelineDetails={pipelineDetails}
|
pipelineDetails={pipelineDetails}
|
||||||
pipelineFQN={pipelineFQN}
|
pipelineFQN={pipelineFQN}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user