Add PostComponent tests involving thread footer (#23679)
Этот коммит содержится в:
коммит произвёл
GitHub
родитель
c7895c6f41
Коммит
f386ef1ea8
@@ -5,30 +5,39 @@ import React from 'react';
|
|||||||
|
|
||||||
import {DeepPartial} from '@mattermost/types/utilities';
|
import {DeepPartial} from '@mattermost/types/utilities';
|
||||||
|
|
||||||
import {renderWithFullContext, screen} from 'tests/react_testing_utils';
|
import mergeObjects from 'packages/mattermost-redux/test/merge_objects';
|
||||||
|
|
||||||
|
import {renderWithFullContext, screen, userEvent} from 'tests/react_testing_utils';
|
||||||
|
|
||||||
import {GlobalState} from 'types/store';
|
import {GlobalState} from 'types/store';
|
||||||
|
|
||||||
|
import {getHistory} from 'utils/browser_history';
|
||||||
import {Locations} from 'utils/constants';
|
import {Locations} from 'utils/constants';
|
||||||
import {TestHelper} from 'utils/test_helper';
|
import {TestHelper} from 'utils/test_helper';
|
||||||
|
|
||||||
import PostComponent from './post_component';
|
import PostComponent, {Props} from './post_component';
|
||||||
import mergeObjects from 'packages/mattermost-redux/test/merge_objects';
|
|
||||||
|
|
||||||
describe('PostComponent', () => {
|
describe('PostComponent', () => {
|
||||||
const baseProps = {
|
const currentTeam = TestHelper.getTeamMock();
|
||||||
|
const channel = TestHelper.getChannelMock({team_id: currentTeam.id});
|
||||||
|
|
||||||
|
const baseProps: Props = {
|
||||||
center: false,
|
center: false,
|
||||||
currentTeam: TestHelper.getTeamMock(),
|
currentTeam,
|
||||||
currentUserId: 'currentUserId',
|
currentUserId: 'currentUserId',
|
||||||
displayName: '',
|
displayName: '',
|
||||||
|
hasReplies: false,
|
||||||
isBot: false,
|
isBot: false,
|
||||||
|
isCollapsedThreadsEnabled: true,
|
||||||
isFlagged: false,
|
isFlagged: false,
|
||||||
isMobileView: false,
|
isMobileView: false,
|
||||||
isPostAcknowledgementsEnabled: false,
|
isPostAcknowledgementsEnabled: false,
|
||||||
isPostPriorityEnabled: false,
|
isPostPriorityEnabled: false,
|
||||||
location: Locations.CENTER,
|
location: Locations.CENTER,
|
||||||
post: TestHelper.getPostMock(),
|
post: TestHelper.getPostMock({channel_id: channel.id}),
|
||||||
recentEmojis: [],
|
recentEmojis: [],
|
||||||
|
replyCount: 0,
|
||||||
|
team: currentTeam,
|
||||||
actions: {
|
actions: {
|
||||||
markPostAsUnread: jest.fn(),
|
markPostAsUnread: jest.fn(),
|
||||||
emitShortcutReactToLastPostFrom: jest.fn(),
|
emitShortcutReactToLastPostFrom: jest.fn(),
|
||||||
@@ -56,12 +65,7 @@ describe('PostComponent', () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
test('should show reactions in the center channel', () => {
|
test('should show reactions in the center channel', () => {
|
||||||
renderWithFullContext(
|
renderWithFullContext(<PostComponent {...baseProps}/>, baseState);
|
||||||
<PostComponent
|
|
||||||
{...baseProps}
|
|
||||||
/>,
|
|
||||||
baseState,
|
|
||||||
);
|
|
||||||
|
|
||||||
expect(screen.getByLabelText('reactions')).toBeInTheDocument();
|
expect(screen.getByLabelText('reactions')).toBeInTheDocument();
|
||||||
});
|
});
|
||||||
@@ -75,56 +79,250 @@ describe('PostComponent', () => {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const {rerender} = renderWithFullContext(
|
let props: Props = {
|
||||||
<PostComponent
|
...baseProps,
|
||||||
{...baseProps}
|
location: Locations.RHS_ROOT,
|
||||||
location={Locations.RHS_ROOT}
|
};
|
||||||
/>,
|
const {rerender} = renderWithFullContext(<PostComponent {...props}/>, state);
|
||||||
state,
|
|
||||||
);
|
|
||||||
|
|
||||||
expect(screen.getByLabelText('reactions')).toBeInTheDocument();
|
expect(screen.getByLabelText('reactions')).toBeInTheDocument();
|
||||||
|
|
||||||
rerender(
|
props = {
|
||||||
<PostComponent
|
...baseProps,
|
||||||
{...baseProps}
|
location: Locations.RHS_COMMENT,
|
||||||
location={Locations.RHS_COMMENT}
|
};
|
||||||
/>,
|
rerender(<PostComponent {...props}/>);
|
||||||
);
|
|
||||||
|
|
||||||
expect(screen.getByLabelText('reactions')).toBeInTheDocument();
|
expect(screen.getByLabelText('reactions')).toBeInTheDocument();
|
||||||
});
|
});
|
||||||
|
|
||||||
test('should show only show reactions in search results with pinned/saved posts visible', () => {
|
test('should show only show reactions in search results with pinned/saved posts visible', () => {
|
||||||
const {rerender} = renderWithFullContext(
|
let props = {
|
||||||
<PostComponent
|
...baseProps,
|
||||||
{...baseProps}
|
location: Locations.SEARCH,
|
||||||
location={Locations.SEARCH}
|
};
|
||||||
/>,
|
const {rerender} = renderWithFullContext(<PostComponent {...props}/>, baseState);
|
||||||
baseState,
|
|
||||||
);
|
|
||||||
|
|
||||||
expect(screen.queryByLabelText('reactions')).not.toBeInTheDocument();
|
expect(screen.queryByLabelText('reactions')).not.toBeInTheDocument();
|
||||||
|
|
||||||
rerender(
|
props = {
|
||||||
<PostComponent
|
...baseProps,
|
||||||
{...baseProps}
|
location: Locations.SEARCH,
|
||||||
location={Locations.SEARCH}
|
isPinnedPosts: true,
|
||||||
isPinnedPosts={true}
|
};
|
||||||
/>,
|
rerender(<PostComponent {...props}/>);
|
||||||
);
|
|
||||||
|
|
||||||
expect(screen.getByLabelText('reactions')).toBeInTheDocument();
|
expect(screen.getByLabelText('reactions')).toBeInTheDocument();
|
||||||
|
|
||||||
rerender(
|
props = {
|
||||||
<PostComponent
|
...baseProps,
|
||||||
{...baseProps}
|
location: Locations.SEARCH,
|
||||||
location={Locations.SEARCH}
|
isFlaggedPosts: true,
|
||||||
isFlaggedPosts={true}
|
};
|
||||||
/>,
|
rerender(<PostComponent {...props}/>);
|
||||||
);
|
|
||||||
|
|
||||||
expect(screen.getByLabelText('reactions')).toBeInTheDocument();
|
expect(screen.getByLabelText('reactions')).toBeInTheDocument();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('thread footer', () => {
|
||||||
|
test('should never show thread footer for a post that isn\'t part of a thread', () => {
|
||||||
|
let props: Props = baseProps;
|
||||||
|
const {rerender} = renderWithFullContext(<PostComponent {...props}/>);
|
||||||
|
|
||||||
|
expect(screen.queryByText(/Follow|Following/)).not.toBeInTheDocument();
|
||||||
|
|
||||||
|
props = {
|
||||||
|
...baseProps,
|
||||||
|
location: Locations.SEARCH,
|
||||||
|
};
|
||||||
|
rerender(<PostComponent {...props}/>);
|
||||||
|
|
||||||
|
expect(screen.queryByText(/Follow|Following/)).not.toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
|
// This probably shouldn't appear in the search results https://mattermost.atlassian.net/browse/MM-53078
|
||||||
|
test('should only show thread footer for a root post in the center channel and search results', () => {
|
||||||
|
const rootPost = TestHelper.getPostMock({
|
||||||
|
id: 'rootPost',
|
||||||
|
channel_id: channel.id,
|
||||||
|
reply_count: 1,
|
||||||
|
});
|
||||||
|
const state: DeepPartial<GlobalState> = {
|
||||||
|
entities: {
|
||||||
|
posts: {
|
||||||
|
posts: {
|
||||||
|
rootPost,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
let props = {
|
||||||
|
...baseProps,
|
||||||
|
hasReplies: true,
|
||||||
|
post: rootPost,
|
||||||
|
replyCount: 1,
|
||||||
|
};
|
||||||
|
const {rerender} = renderWithFullContext(<PostComponent {...props}/>, state);
|
||||||
|
|
||||||
|
expect(screen.queryByText(/Follow|Following/)).toBeInTheDocument();
|
||||||
|
|
||||||
|
props = {
|
||||||
|
...props,
|
||||||
|
location: Locations.RHS_ROOT,
|
||||||
|
};
|
||||||
|
rerender(<PostComponent {...props}/>);
|
||||||
|
|
||||||
|
expect(screen.queryByText(/Follow|Following/)).not.toBeInTheDocument();
|
||||||
|
|
||||||
|
props = {
|
||||||
|
...props,
|
||||||
|
location: Locations.SEARCH,
|
||||||
|
};
|
||||||
|
rerender(<PostComponent {...props}/>);
|
||||||
|
|
||||||
|
expect(screen.queryByText(/Follow|Following/)).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should never show thread footer for a comment', () => {
|
||||||
|
let props = {
|
||||||
|
...baseProps,
|
||||||
|
hasReplies: true,
|
||||||
|
post: {
|
||||||
|
...baseProps.post,
|
||||||
|
root_id: 'some_other_post_id',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
const {rerender} = renderWithFullContext(<PostComponent {...props}/>);
|
||||||
|
|
||||||
|
expect(screen.queryByText(/Follow|Following/)).not.toBeInTheDocument();
|
||||||
|
|
||||||
|
props = {
|
||||||
|
...props,
|
||||||
|
location: Locations.RHS_COMMENT,
|
||||||
|
};
|
||||||
|
rerender(<PostComponent {...props}/>);
|
||||||
|
|
||||||
|
expect(screen.queryByText(/Follow|Following/)).not.toBeInTheDocument();
|
||||||
|
|
||||||
|
props = {
|
||||||
|
...props,
|
||||||
|
location: Locations.SEARCH,
|
||||||
|
};
|
||||||
|
rerender(<PostComponent {...props}/>);
|
||||||
|
|
||||||
|
expect(screen.queryByText(/Follow|Following/)).not.toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should not show thread footer with CRT disabled', () => {
|
||||||
|
const rootPost = TestHelper.getPostMock({
|
||||||
|
id: 'rootPost',
|
||||||
|
channel_id: channel.id,
|
||||||
|
reply_count: 1,
|
||||||
|
});
|
||||||
|
const state: DeepPartial<GlobalState> = {
|
||||||
|
entities: {
|
||||||
|
posts: {
|
||||||
|
posts: {
|
||||||
|
rootPost,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
let props = {
|
||||||
|
...baseProps,
|
||||||
|
hasReplies: true,
|
||||||
|
isCollapsedThreadsEnabled: false,
|
||||||
|
post: rootPost,
|
||||||
|
replyCount: 1,
|
||||||
|
};
|
||||||
|
const {rerender} = renderWithFullContext(<PostComponent {...props}/>, state);
|
||||||
|
|
||||||
|
expect(screen.queryByText(/Follow|Following/)).not.toBeInTheDocument();
|
||||||
|
|
||||||
|
props = {
|
||||||
|
...props,
|
||||||
|
location: Locations.SEARCH,
|
||||||
|
};
|
||||||
|
rerender(<PostComponent {...props}/>);
|
||||||
|
|
||||||
|
expect(screen.queryByText(/Follow|Following/)).not.toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('reply/X replies link', () => {
|
||||||
|
const rootPost = TestHelper.getPostMock({
|
||||||
|
id: 'rootPost',
|
||||||
|
channel_id: channel.id,
|
||||||
|
reply_count: 1,
|
||||||
|
});
|
||||||
|
const state: DeepPartial<GlobalState> = {
|
||||||
|
entities: {
|
||||||
|
posts: {
|
||||||
|
posts: {
|
||||||
|
rootPost,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const propsForRootPost = {
|
||||||
|
...baseProps,
|
||||||
|
hasReplies: true,
|
||||||
|
post: rootPost,
|
||||||
|
replyCount: 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
test('should select post in RHS when clicked in center channel', () => {
|
||||||
|
renderWithFullContext(<PostComponent {...propsForRootPost}/>, state);
|
||||||
|
|
||||||
|
userEvent.click(screen.getByText('1 reply'));
|
||||||
|
|
||||||
|
// Yes, this action has a different name than the one you'd expect
|
||||||
|
expect(propsForRootPost.actions.selectPostFromRightHandSideSearch).toHaveBeenCalledWith(rootPost);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should select post in RHS when clicked in center channel in a DM/GM', () => {
|
||||||
|
const props = {
|
||||||
|
...propsForRootPost,
|
||||||
|
team: undefined,
|
||||||
|
};
|
||||||
|
renderWithFullContext(<PostComponent {...props}/>, state);
|
||||||
|
|
||||||
|
userEvent.click(screen.getByText('1 reply'));
|
||||||
|
|
||||||
|
// Yes, this action has a different name than the one you'd expect
|
||||||
|
expect(propsForRootPost.actions.selectPostFromRightHandSideSearch).toHaveBeenCalledWith(rootPost);
|
||||||
|
expect(getHistory().push).not.toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should select post in RHS when clicked in a search result on the current team', () => {
|
||||||
|
const props = {
|
||||||
|
...propsForRootPost,
|
||||||
|
location: Locations.SEARCH,
|
||||||
|
};
|
||||||
|
renderWithFullContext(<PostComponent {...props}/>, state);
|
||||||
|
|
||||||
|
userEvent.click(screen.getByText('1 reply'));
|
||||||
|
|
||||||
|
expect(propsForRootPost.actions.selectPostFromRightHandSideSearch).toHaveBeenCalledWith(rootPost);
|
||||||
|
expect(getHistory().push).not.toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should jump to post when clicked in a search result on another team', () => {
|
||||||
|
const props = {
|
||||||
|
...propsForRootPost,
|
||||||
|
location: Locations.SEARCH,
|
||||||
|
team: TestHelper.getTeamMock({id: 'another_team'}),
|
||||||
|
};
|
||||||
|
renderWithFullContext(<PostComponent {...props}/>, state);
|
||||||
|
|
||||||
|
userEvent.click(screen.getByText('1 reply'));
|
||||||
|
|
||||||
|
expect(propsForRootPost.actions.selectPostFromRightHandSideSearch).not.toHaveBeenCalled();
|
||||||
|
expect(getHistory().push).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -82,7 +82,7 @@ export type Props = {
|
|||||||
channelType?: string;
|
channelType?: string;
|
||||||
a11yIndex?: number;
|
a11yIndex?: number;
|
||||||
isBot: boolean;
|
isBot: boolean;
|
||||||
hasReplies?: boolean;
|
hasReplies: boolean;
|
||||||
isFirstReply?: boolean;
|
isFirstReply?: boolean;
|
||||||
previousPostIsComment?: boolean;
|
previousPostIsComment?: boolean;
|
||||||
matches?: string[];
|
matches?: string[];
|
||||||
|
|||||||
Ссылка в новой задаче
Block a user