mirror of
https://github.com/open-metadata/OpenMetadata.git
synced 2025-11-02 11:39:12 +00:00
test(ui): e2e activity feed tests (#12576)
* test(ui): e2e activity feed tests * support mention tests for feed widget * fix cypress and address comments * compare feed for mention * fix cypress
This commit is contained in:
parent
f7bfdd63d2
commit
e3278cb578
@ -0,0 +1,108 @@
|
||||
/*
|
||||
* 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 {
|
||||
descriptionBox,
|
||||
interceptURL,
|
||||
toastNotification,
|
||||
verifyResponseStatusCode,
|
||||
} from './common';
|
||||
|
||||
const assignee = 'admin';
|
||||
const secondAssignee = 'aaron_johnson0';
|
||||
|
||||
export const verifyTaskDetails = (regexPattern) => {
|
||||
cy.get('#task-panel').should('be.visible');
|
||||
cy.get('[data-testid="task-title"]')
|
||||
.invoke('text')
|
||||
.then((textContent) => {
|
||||
const matches = textContent.match(regexPattern);
|
||||
|
||||
expect(matches).to.not.be.null;
|
||||
});
|
||||
|
||||
cy.get('[data-testid="owner-link"]').contains(assignee);
|
||||
|
||||
cy.get(`[data-testid="assignee-${assignee}"]`).should('be.visible');
|
||||
};
|
||||
|
||||
export const editAssignee = () => {
|
||||
interceptURL('PATCH', 'api/v1/feed/*', 'editAssignee');
|
||||
|
||||
cy.get('[data-testid="edit-assignees"]').click();
|
||||
|
||||
cy.get('[data-testid="select-assignee"] > .ant-select-selector').type(
|
||||
secondAssignee
|
||||
);
|
||||
// select value from dropdown
|
||||
verifyResponseStatusCode('@suggestApi', 200);
|
||||
|
||||
cy.get(`[data-testid="assignee-option-${secondAssignee}"]`)
|
||||
.should('be.visible')
|
||||
.trigger('mouseover')
|
||||
.trigger('click');
|
||||
|
||||
cy.clickOutside();
|
||||
|
||||
cy.get('[data-testid="inline-save-btn"]').click();
|
||||
|
||||
verifyResponseStatusCode('@editAssignee', 200);
|
||||
|
||||
cy.get(`[data-testid="assignee-${assignee}"]`).should('be.visible');
|
||||
};
|
||||
|
||||
export const createDescriptionTask = (value) => {
|
||||
interceptURL('POST', 'api/v1/feed', 'createTask');
|
||||
|
||||
cy.get('#title').should(
|
||||
'have.value',
|
||||
`Update description for table ${value.term}`
|
||||
);
|
||||
|
||||
cy.get('[data-testid="select-assignee"] > .ant-select-selector').type(
|
||||
assignee
|
||||
);
|
||||
// select value from dropdown
|
||||
verifyResponseStatusCode('@suggestApi', 200);
|
||||
|
||||
cy.get(`[data-testid="assignee-option-${assignee}"]`)
|
||||
.should('be.visible')
|
||||
.trigger('mouseover')
|
||||
.trigger('click');
|
||||
|
||||
cy.clickOutside();
|
||||
|
||||
cy.get(descriptionBox).scrollIntoView().clear().type('Updated description');
|
||||
|
||||
cy.get('button[type="submit"]').click();
|
||||
verifyResponseStatusCode('@createTask', 201);
|
||||
toastNotification('Task created successfully.');
|
||||
};
|
||||
|
||||
export const createAndUpdateDescriptionTask = (value) => {
|
||||
createDescriptionTask(value);
|
||||
|
||||
// verify the task details
|
||||
verifyTaskDetails(/#(\d+) UpdateDescriptionfordescription/);
|
||||
|
||||
// edit task assignees
|
||||
editAssignee();
|
||||
|
||||
// Accept the description suggestion which is created
|
||||
cy.get('.ant-btn-compact-first-item').contains('Accept Suggestion').click();
|
||||
|
||||
verifyResponseStatusCode('@taskResolve', 200);
|
||||
|
||||
toastNotification('Task resolved successfully');
|
||||
|
||||
verifyResponseStatusCode('@entityFeed', 200);
|
||||
};
|
||||
@ -0,0 +1,254 @@
|
||||
/*
|
||||
* 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 { createDescriptionTask } from '../../common/TaskUtils';
|
||||
import { SEARCH_ENTITY_TABLE } from '../../constants/constants';
|
||||
|
||||
// eslint-disable-next-line spaced-comment
|
||||
/// <reference types="cypress" />
|
||||
|
||||
const reactOnFeed = (feedSelector, reaction) => {
|
||||
cy.get(feedSelector).within(() => {
|
||||
cy.get('[data-testid="feed-actions"]').invoke('show');
|
||||
cy.get('[data-testid="feed-actions"]').within(() => {
|
||||
cy.get('[data-testid="add-reactions"]').click();
|
||||
});
|
||||
});
|
||||
|
||||
cy.get(
|
||||
`#reaction-popover [data-testid="reaction-button"][title="${reaction}"]`
|
||||
).click();
|
||||
};
|
||||
|
||||
describe('Recently viwed data assets', () => {
|
||||
beforeEach(() => {
|
||||
cy.login();
|
||||
});
|
||||
|
||||
it('Feed widget should be visible', () => {
|
||||
cy.get('[data-testid="activity-feed-widget"]').as('feedWidget');
|
||||
cy.get('@feedWidget').should('be.visible');
|
||||
cy.get('@feedWidget').should('contain', 'All');
|
||||
cy.get('@feedWidget').should('contain', '@Mentions');
|
||||
cy.get('@feedWidget').should('contain', 'Tasks');
|
||||
cy.get('@feedWidget').should('contain', '0');
|
||||
});
|
||||
|
||||
it('Feed widget should have some feeds', () => {
|
||||
cy.get(
|
||||
'[data-testid="activity-feed-widget"] [data-testid="message-container"]'
|
||||
).should('have.length.gte', 1);
|
||||
});
|
||||
|
||||
it('Emoji reaction on feed should be working fine', () => {
|
||||
// Assign reaction for latest feed
|
||||
[
|
||||
'thumbsUp',
|
||||
'thumbsDown',
|
||||
'laugh',
|
||||
'hooray',
|
||||
'confused',
|
||||
'heart',
|
||||
'eyes',
|
||||
'rocket',
|
||||
].map((reaction) =>
|
||||
reactOnFeed(
|
||||
'[data-testid="activity-feed-widget"] [data-testid="message-container"]:first-child',
|
||||
reaction
|
||||
)
|
||||
);
|
||||
|
||||
// Verify if reaction is working or not
|
||||
cy.get(
|
||||
'[data-testid="activity-feed-widget"] [data-testid="message-container"]:first-child'
|
||||
).within(() => {
|
||||
['🚀', '😕', '👀', '❤️', '🎉', '😄', '👎', '👍'].map((reaction) =>
|
||||
cy
|
||||
.get('[data-testid="feed-reaction-container"]')
|
||||
.should('contain', reaction)
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
it('User should be able to reply to feed', () => {
|
||||
interceptURL('GET', '/api/v1/feed/*', 'fetchFeed');
|
||||
cy.get(
|
||||
'[data-testid="activity-feed-widget"] [data-testid="message-container"]:first-child'
|
||||
).within(() => {
|
||||
cy.get('[data-testid="feed-actions"]').invoke('show');
|
||||
cy.get('[data-testid="feed-actions"]').within(() => {
|
||||
cy.get('[data-testid="add-reply"]').click();
|
||||
});
|
||||
});
|
||||
verifyResponseStatusCode('@fetchFeed', 200);
|
||||
|
||||
interceptURL('POST', '/api/v1/feed/*/posts', 'postReply');
|
||||
interceptURL(
|
||||
'GET',
|
||||
'/api/v1/search/suggest?q=aa&index=user_search_index%2Cteam_search_index',
|
||||
'suggestUser'
|
||||
);
|
||||
interceptURL(
|
||||
'GET',
|
||||
// eslint-disable-next-line max-len
|
||||
'/api/v1/search/suggest?q=dim_add&index=dashboard_search_index%2Ctable_search_index%2Ctopic_search_index%2Cpipeline_search_index%2Cmlmodel_search_index%2Ccontainer_search_index%2Cglossary_search_index%2Ctag_search_index',
|
||||
'suggestAsset'
|
||||
);
|
||||
|
||||
cy.get('[data-testid="editor-wrapper"]').should('be.visible');
|
||||
cy.get(
|
||||
'[data-testid="editor-wrapper"] [contenteditable="true"].ql-editor'
|
||||
).as('editor');
|
||||
cy.get('@editor').click();
|
||||
cy.get('@editor').type('Cypress has replied here. Thanks! @aa');
|
||||
|
||||
verifyResponseStatusCode('@suggestUser', 200);
|
||||
cy.get('[data-value="@aaron_johnson0"]').click();
|
||||
cy.get('@editor').type(' #dim_add');
|
||||
verifyResponseStatusCode('@suggestAsset', 200);
|
||||
cy.get('[data-value="#table/dim_address"]').click();
|
||||
|
||||
cy.get('[data-testid="send-button"]')
|
||||
.should('be.visible')
|
||||
.and('not.be.disabled');
|
||||
cy.get('[data-testid="send-button"]').click();
|
||||
|
||||
verifyResponseStatusCode('@postReply', 201);
|
||||
|
||||
cy.get('[data-testid="replies"]').should('contain', '1 reply');
|
||||
cy.get('[data-testid="replies"] .activity-feed-card.activity-feed-card-v1')
|
||||
.children('.ant-row')
|
||||
.eq(1)
|
||||
.invoke('text')
|
||||
.should(
|
||||
'eq',
|
||||
'Cypress has replied here. Thanks! @aaron_johnson0 #table/dim_address\n'
|
||||
);
|
||||
|
||||
cy.get('[data-testid="closeDrawer"]').click();
|
||||
|
||||
cy.get(
|
||||
'[data-testid="activity-feed-widget"] [data-testid="message-container"]:first-child'
|
||||
).within(() => {
|
||||
cy.get('[data-testid="thread-count"]').should('contain', 1);
|
||||
});
|
||||
});
|
||||
|
||||
it('Mention should work for the feed reply', () => {
|
||||
interceptURL('GET', '/api/v1/feed/*', 'fetchFeed');
|
||||
cy.get(
|
||||
'[data-testid="activity-feed-widget"] [data-testid="message-container"]:first-child'
|
||||
).within(() => {
|
||||
cy.get('[data-testid="feed-actions"]').invoke('show');
|
||||
cy.get('[data-testid="feed-actions"]').within(() => {
|
||||
cy.get('[data-testid="add-reply"]').click();
|
||||
});
|
||||
});
|
||||
verifyResponseStatusCode('@fetchFeed', 200);
|
||||
|
||||
interceptURL('POST', '/api/v1/feed/*/posts', 'postReply');
|
||||
interceptURL(
|
||||
'GET',
|
||||
'/api/v1/search/suggest?q=aa&index=user_search_index%2Cteam_search_index',
|
||||
'suggestUser'
|
||||
);
|
||||
|
||||
cy.get('[data-testid="editor-wrapper"]').should('be.visible');
|
||||
cy.get(
|
||||
'[data-testid="editor-wrapper"] [contenteditable="true"].ql-editor'
|
||||
).as('editor');
|
||||
cy.get('@editor').click();
|
||||
cy.get('@editor').type('Can you resolve this thread for me? @admin');
|
||||
// verifyResponseStatusCode('@suggestUser', 200);
|
||||
cy.get('[data-value="@admin"]').click();
|
||||
|
||||
cy.get('[data-testid="send-button"]')
|
||||
.should('be.visible')
|
||||
.and('not.be.disabled');
|
||||
cy.get('[data-testid="send-button"]').click();
|
||||
|
||||
verifyResponseStatusCode('@postReply', 201);
|
||||
|
||||
cy.get('[data-testid="closeDrawer"]').click();
|
||||
|
||||
let feedText1 = '';
|
||||
cy.get(
|
||||
'[data-testid="activity-feed-widget"] [data-testid="message-container"]:first-child [data-testid="viewer-container"]'
|
||||
)
|
||||
.invoke('text')
|
||||
.then((text) => (feedText1 = text));
|
||||
|
||||
cy.get('[data-testid="activity-feed-widget"]')
|
||||
.contains('@Mentions')
|
||||
.click();
|
||||
|
||||
// Verify mentioned thread should be there int he mentioned tab
|
||||
cy.get(
|
||||
'[data-testid="message-container"] > .activity-feed-card [data-testid="viewer-container"]'
|
||||
)
|
||||
.invoke('text')
|
||||
.then((text) => expect(text).to.contain(feedText1));
|
||||
});
|
||||
|
||||
it('Assigned task should appear to task tab', () => {
|
||||
cy.get('[data-testid="activity-feed-widget"]')
|
||||
.contains('Tasks')
|
||||
.should('contain', 0);
|
||||
|
||||
cy.get('[data-testid="activity-feed-widget"]').contains('Tasks').click();
|
||||
|
||||
cy.get(
|
||||
'[data-testid="activity-feed-widget"] [data-testid="no-data-placeholder"]'
|
||||
).should('be.visible');
|
||||
|
||||
const value = SEARCH_ENTITY_TABLE.table_1;
|
||||
interceptURL('GET', `/api/v1/${value.entity}/name/*`, 'getEntityDetails');
|
||||
|
||||
visitEntityDetailsPage(value.term, value.serviceName, value.entity);
|
||||
|
||||
cy.get('[data-testid="request-description"]').click();
|
||||
|
||||
verifyResponseStatusCode('@getEntityDetails', 200);
|
||||
|
||||
interceptURL('GET', '/api/v1/search/suggest?q=*', 'suggestApi');
|
||||
|
||||
// create description task
|
||||
createDescriptionTask(value);
|
||||
|
||||
cy.clickOnLogo();
|
||||
|
||||
cy.get('[data-testid="activity-feed-widget"]')
|
||||
.contains('Tasks')
|
||||
.should('contain', 1)
|
||||
.click();
|
||||
|
||||
cy.get(
|
||||
'[data-testid="activity-feed-widget"] [data-testid="no-data-placeholder"]'
|
||||
).should('not.exist');
|
||||
|
||||
cy.get('[data-testid="message-container"]')
|
||||
.invoke('text')
|
||||
.then((textContent) => {
|
||||
const matches = textContent.match(/#(\d+) UpdateDescriptionfortable/);
|
||||
|
||||
expect(matches).to.not.be.null;
|
||||
});
|
||||
|
||||
cy.get(`[data-testid="assignee-admin"]`).should('be.visible');
|
||||
});
|
||||
});
|
||||
@ -14,12 +14,16 @@
|
||||
/// <reference types="cypress" />
|
||||
|
||||
import {
|
||||
descriptionBox,
|
||||
interceptURL,
|
||||
toastNotification,
|
||||
verifyResponseStatusCode,
|
||||
visitEntityDetailsPage,
|
||||
} from '../../common/common';
|
||||
import {
|
||||
createAndUpdateDescriptionTask,
|
||||
editAssignee,
|
||||
verifyTaskDetails,
|
||||
} from '../../common/TaskUtils';
|
||||
import { SEARCH_ENTITY_TABLE } from '../../constants/constants';
|
||||
|
||||
describe('Task flow should work', () => {
|
||||
@ -37,92 +41,8 @@ describe('Task flow should work', () => {
|
||||
});
|
||||
|
||||
const assignee = 'admin';
|
||||
const secondAssignee = 'aaron_johnson0';
|
||||
const tag = 'Personal';
|
||||
|
||||
const editAssignee = () => {
|
||||
interceptURL('PATCH', 'api/v1/feed/*', 'editAssignee');
|
||||
|
||||
cy.get('[data-testid="edit-assignees"]').click();
|
||||
|
||||
cy.get('[data-testid="select-assignee"] > .ant-select-selector').type(
|
||||
secondAssignee
|
||||
);
|
||||
// select value from dropdown
|
||||
verifyResponseStatusCode('@suggestApi', 200);
|
||||
|
||||
cy.get(`[data-testid="assignee-option-${secondAssignee}"]`)
|
||||
.should('be.visible')
|
||||
.trigger('mouseover')
|
||||
.trigger('click');
|
||||
|
||||
cy.clickOutside();
|
||||
|
||||
cy.get('[data-testid="inline-save-btn"]').click();
|
||||
|
||||
verifyResponseStatusCode('@editAssignee', 200);
|
||||
|
||||
cy.get(`[data-testid="assignee-${assignee}"]`).should('be.visible');
|
||||
};
|
||||
|
||||
const verifyTaskDetails = (regexPattern) => {
|
||||
cy.get('#task-panel').should('be.visible');
|
||||
cy.get('[data-testid="task-title"]')
|
||||
.invoke('text')
|
||||
.then((textContent) => {
|
||||
const matches = textContent.match(regexPattern);
|
||||
|
||||
expect(matches).to.not.be.null;
|
||||
});
|
||||
|
||||
cy.get('[data-testid="owner-link"]').contains(assignee);
|
||||
|
||||
cy.get(`[data-testid="assignee-${assignee}"]`).should('be.visible');
|
||||
};
|
||||
|
||||
const createDescriptionTask = (value) => {
|
||||
interceptURL('POST', 'api/v1/feed', 'createTask');
|
||||
|
||||
cy.get('#title').should(
|
||||
'have.value',
|
||||
`Update description for table ${value.term}`
|
||||
);
|
||||
|
||||
cy.get('[data-testid="select-assignee"] > .ant-select-selector').type(
|
||||
assignee
|
||||
);
|
||||
// select value from dropdown
|
||||
verifyResponseStatusCode('@suggestApi', 200);
|
||||
|
||||
cy.get(`[data-testid="assignee-option-${assignee}"]`)
|
||||
.should('be.visible')
|
||||
.trigger('mouseover')
|
||||
.trigger('click');
|
||||
|
||||
cy.clickOutside();
|
||||
|
||||
cy.get(descriptionBox).scrollIntoView().clear().type('Updated description');
|
||||
|
||||
cy.get('button[type="submit"]').click();
|
||||
verifyResponseStatusCode('@createTask', 201);
|
||||
toastNotification('Task created successfully.');
|
||||
|
||||
// verify the task details
|
||||
verifyTaskDetails(/#(\d+) UpdateDescriptionfordescription/);
|
||||
|
||||
// edit task assignees
|
||||
editAssignee();
|
||||
|
||||
// Accept the description suggestion which is created
|
||||
cy.get('.ant-btn-compact-first-item').contains('Accept Suggestion').click();
|
||||
|
||||
verifyResponseStatusCode('@taskResolve', 200);
|
||||
|
||||
toastNotification('Task resolved successfully');
|
||||
|
||||
verifyResponseStatusCode('@entityFeed', 200);
|
||||
};
|
||||
|
||||
const createTagTask = (value) => {
|
||||
interceptURL('POST', 'api/v1/feed', 'createTask');
|
||||
|
||||
@ -186,7 +106,7 @@ describe('Task flow should work', () => {
|
||||
verifyResponseStatusCode('@getEntityDetails', 200);
|
||||
|
||||
// create description task
|
||||
createDescriptionTask(value);
|
||||
createAndUpdateDescriptionTask(value);
|
||||
});
|
||||
|
||||
it('Task flow for table tags', () => {
|
||||
|
||||
@ -129,6 +129,7 @@ const ActivityFeedCardV1 = ({
|
||||
</div>
|
||||
<div
|
||||
className="d-flex items-center thread-count cursor-pointer"
|
||||
data-testid="thread-count"
|
||||
onClick={!hidePopover ? showReplies : noop}>
|
||||
<ThreadIcon width={18} />{' '}
|
||||
<span className="text-xs p-l-xss">{postLength}</span>
|
||||
|
||||
@ -139,7 +139,7 @@ const ActivityFeedActions = ({
|
||||
|
||||
return (
|
||||
<>
|
||||
<Space className="feed-actions" size={6}>
|
||||
<Space className="feed-actions" data-testid="feed-actions" size={6}>
|
||||
{feed.type !== ThreadType.Task && !isPost && (
|
||||
<Popover
|
||||
destroyTooltipOnHide
|
||||
|
||||
@ -101,6 +101,17 @@ const Emoji: FC<EmojiProps> = ({
|
||||
setIsClicked(false);
|
||||
}, [reaction]);
|
||||
|
||||
const element = React.createElement(
|
||||
'g-emoji',
|
||||
{
|
||||
alias: reactionObject?.alias,
|
||||
className: 'd-flex',
|
||||
'data-testid': 'emoji',
|
||||
'fallback-src': image,
|
||||
},
|
||||
reactionObject?.emoji
|
||||
);
|
||||
|
||||
return (
|
||||
<Popover
|
||||
content={popoverContent}
|
||||
@ -118,17 +129,7 @@ const Emoji: FC<EmojiProps> = ({
|
||||
size="small"
|
||||
onClick={handleEmojiOnClick}
|
||||
onMouseOver={() => setVisible(true)}>
|
||||
<div
|
||||
dangerouslySetInnerHTML={{
|
||||
__html: `<g-emoji
|
||||
alias={${reactionObject?.alias}}
|
||||
className="d-flex"
|
||||
data-testid="emoji"
|
||||
fallback-src={${image}}>
|
||||
${reactionObject?.emoji}
|
||||
</g-emoji>`,
|
||||
}}
|
||||
/>
|
||||
{element}
|
||||
|
||||
<span className="text-xs m-l-xss self-center" data-testid="emoji-count">
|
||||
{reactionList.length}
|
||||
|
||||
@ -51,6 +51,17 @@ const Reaction: FC<ReactionProps> = ({
|
||||
onHide();
|
||||
};
|
||||
|
||||
const element = React.createElement(
|
||||
'g-emoji',
|
||||
{
|
||||
alias: reaction?.alias,
|
||||
className: 'd-flex',
|
||||
'data-testid': 'emoji',
|
||||
'fallback-src': image,
|
||||
},
|
||||
reaction?.emoji
|
||||
);
|
||||
|
||||
return (
|
||||
<Button
|
||||
aria-label={reaction.reaction}
|
||||
@ -63,17 +74,7 @@ const Reaction: FC<ReactionProps> = ({
|
||||
title={reaction.reaction}
|
||||
type="text"
|
||||
onClick={handleOnClick}>
|
||||
<div
|
||||
dangerouslySetInnerHTML={{
|
||||
__html: `<g-emoji
|
||||
alias={${reaction.alias}}
|
||||
className="d-flex"
|
||||
data-testid="emoji"
|
||||
fallback-src={${image}}>
|
||||
${reaction.emoji}
|
||||
</g-emoji>`,
|
||||
}}
|
||||
/>
|
||||
{element}
|
||||
</Button>
|
||||
);
|
||||
};
|
||||
|
||||
@ -104,7 +104,7 @@ const Reactions: FC<ReactionsProps> = ({ reactions, onReactionSelect }) => {
|
||||
});
|
||||
|
||||
return (
|
||||
<div className="d-flex items-center">
|
||||
<div className="d-flex items-center" data-testid="feed-reaction-container">
|
||||
{emojis}
|
||||
<Popover
|
||||
align={{ targetOffset: [0, -10] }}
|
||||
|
||||
@ -95,8 +95,9 @@ const FeedsWidget = () => {
|
||||
}, [activeTab, entityThread]);
|
||||
|
||||
return (
|
||||
<div className="feeds-widget-container">
|
||||
<div className="feeds-widget-container" data-testid="activity-feed-widget">
|
||||
<Tabs
|
||||
destroyInactiveTabPane
|
||||
items={[
|
||||
{
|
||||
label: t('label.all'),
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user