Add PostComponent tests involving thread footer (#23679)

Этот коммит содержится в:
Harrison Healey
2023-06-14 16:33:48 -04:00
коммит произвёл GitHub
родитель c7895c6f41
Коммит f386ef1ea8
2 изменённых файлов: 245 добавлений и 47 удалений

Просмотреть файл

@@ -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[];