forked from Ivasoft/mattermost-mobile
Detox/E2E: Messaging (at-mentions, channel mentions, autocomplete etc) e2e tests in Gekidou (#6428)
* Detox/E2E: Messaging (at-mentions, channel mentions, autocomplete etc) e2e tests in Gekidou * Enable other failing tests so they're visible * Detox/E2E: Messaging markdown e2e tests in Gekidou (#6450) * Detox/E2E: Messaging markdown e2e tests in Gekidou * Added zephyr test ids * Added markdown smoke test * Enable disabled tests Co-authored-by: Mattermod <mattermod@users.noreply.github.com>
This commit is contained in:
@@ -308,6 +308,7 @@ const AtMention = ({
|
||||
defaultMessage={item.defaultMessage}
|
||||
id={item.id}
|
||||
onPress={completeMention}
|
||||
testID='autocomplete.special_mention_item'
|
||||
/>
|
||||
);
|
||||
}, [completeMention]);
|
||||
@@ -319,6 +320,7 @@ const AtMention = ({
|
||||
name={item.name}
|
||||
displayName={item.displayName}
|
||||
onPress={completeMention}
|
||||
testID='autocomplete.group_mention_item'
|
||||
/>
|
||||
);
|
||||
}, [completeMention]);
|
||||
@@ -326,9 +328,9 @@ const AtMention = ({
|
||||
const renderAtMentions = useCallback((item: UserProfile | UserModel) => {
|
||||
return (
|
||||
<AtMentionItem
|
||||
testID={`autocomplete.at_mention.item.${item}`}
|
||||
onPress={completeMention}
|
||||
user={item}
|
||||
onPress={completeMention}
|
||||
testID='autocomplete.at_mention_item'
|
||||
/>
|
||||
);
|
||||
}, [completeMention]);
|
||||
|
||||
@@ -60,12 +60,14 @@ type Props = {
|
||||
name: string;
|
||||
displayName: string;
|
||||
onPress: (handle: string) => void;
|
||||
testID?: string;
|
||||
}
|
||||
|
||||
const GroupMentionItem = ({
|
||||
onPress,
|
||||
name,
|
||||
displayName,
|
||||
testID,
|
||||
}: Props) => {
|
||||
const insets = useSafeAreaInsets();
|
||||
const theme = useTheme();
|
||||
@@ -79,11 +81,14 @@ const GroupMentionItem = ({
|
||||
onPress(name);
|
||||
}, [onPress, name]);
|
||||
|
||||
const groupMentionItemTestId = `${testID}.${name}`;
|
||||
|
||||
return (
|
||||
<TouchableWithFeedback
|
||||
onPress={completeMention}
|
||||
style={touchableStyle}
|
||||
type={'opacity'}
|
||||
testID={groupMentionItemTestId}
|
||||
>
|
||||
<View style={style.rowPicture}>
|
||||
<CompassIcon
|
||||
@@ -92,8 +97,18 @@ const GroupMentionItem = ({
|
||||
/>
|
||||
</View>
|
||||
<View style={style.rowInfo}>
|
||||
<Text style={style.rowDisplayName}>{`${displayName} `}</Text>
|
||||
<Text style={style.rowName}>{`@${name}`}</Text>
|
||||
<Text
|
||||
style={style.rowDisplayName}
|
||||
testID={`${groupMentionItemTestId}.display_name`}
|
||||
>
|
||||
{`${displayName} `}
|
||||
</Text>
|
||||
<Text
|
||||
style={style.rowName}
|
||||
testID={`${groupMentionItemTestId}.name`}
|
||||
>
|
||||
{`@${name}`}
|
||||
</Text>
|
||||
</View>
|
||||
</TouchableWithFeedback>
|
||||
);
|
||||
|
||||
@@ -31,7 +31,6 @@ const AtMentionItem = ({
|
||||
|
||||
return (
|
||||
<TouchableWithFeedback
|
||||
testID={testID}
|
||||
key={user.id}
|
||||
onPress={completeMention}
|
||||
underlayColor={changeOpacity(theme.buttonBg, 0.08)}
|
||||
@@ -40,7 +39,7 @@ const AtMentionItem = ({
|
||||
>
|
||||
<UserItem
|
||||
user={user}
|
||||
testID='at_mention.user_item'
|
||||
testID={testID}
|
||||
/>
|
||||
</TouchableWithFeedback>
|
||||
);
|
||||
|
||||
@@ -285,7 +285,7 @@ const ChannelMention = ({
|
||||
<ChannelMentionItem
|
||||
channel={item}
|
||||
onPress={completeMention}
|
||||
testID={`autocomplete.channel_mention.item.${item}`}
|
||||
testID='autocomplete.channel_mention_item'
|
||||
/>
|
||||
);
|
||||
}, [completeMention]);
|
||||
|
||||
@@ -77,6 +77,7 @@ const ChannelMentionItem = ({
|
||||
let component;
|
||||
|
||||
const isArchived = ('delete_at' in channel ? channel.delete_at : channel.deleteAt) > 0;
|
||||
const channelMentionItemTestId = `${testID}.${channel.name}`;
|
||||
|
||||
if (isDMorGM(channel)) {
|
||||
if (!displayName) {
|
||||
@@ -88,15 +89,22 @@ const ChannelMentionItem = ({
|
||||
key={channel.id}
|
||||
onPress={completeMention}
|
||||
style={rowStyle}
|
||||
testID={testID}
|
||||
testID={channelMentionItemTestId}
|
||||
type={'opacity'}
|
||||
>
|
||||
<Text style={style.rowDisplayName}>{'@' + displayName}</Text>
|
||||
<Text
|
||||
style={style.rowDisplayName}
|
||||
testID={`${channelMentionItemTestId}.display_name`}
|
||||
>
|
||||
{'@' + displayName}
|
||||
</Text>
|
||||
<BotTag
|
||||
show={isBot}
|
||||
testID={`${channelMentionItemTestId}.bot.tag`}
|
||||
/>
|
||||
<GuestTag
|
||||
show={isGuest}
|
||||
testID={`${channelMentionItemTestId}.guest.tag`}
|
||||
/>
|
||||
</TouchableWithFeedback>
|
||||
);
|
||||
@@ -107,7 +115,7 @@ const ChannelMentionItem = ({
|
||||
onPress={completeMention}
|
||||
style={margins}
|
||||
underlayColor={changeOpacity(theme.buttonBg, 0.08)}
|
||||
testID={testID}
|
||||
testID={channelMentionItemTestId}
|
||||
type={'native'}
|
||||
>
|
||||
<View style={style.row}>
|
||||
@@ -120,8 +128,18 @@ const ChannelMentionItem = ({
|
||||
size={18}
|
||||
style={style.icon}
|
||||
/>
|
||||
<Text style={style.rowDisplayName}>{displayName}</Text>
|
||||
<Text style={style.rowName}>{` ~${channel.name}`}</Text>
|
||||
<Text
|
||||
style={style.rowDisplayName}
|
||||
testID={`${channelMentionItemTestId}.display_name`}
|
||||
>
|
||||
{displayName}
|
||||
</Text>
|
||||
<Text
|
||||
style={style.rowName}
|
||||
testID={`${channelMentionItemTestId}.name`}
|
||||
>
|
||||
{` ~${channel.name}`}
|
||||
</Text>
|
||||
</View>
|
||||
</TouchableWithFeedback>
|
||||
);
|
||||
|
||||
@@ -169,6 +169,7 @@ const EmojiSuggestion = ({
|
||||
|
||||
const renderItem = useCallback(({item}: {item: string}) => {
|
||||
const completeItemSuggestion = () => completeSuggestion(item);
|
||||
const emojiSuggestionItemTestId = `autocomplete.emoji_suggestion_item.${item}`;
|
||||
|
||||
return (
|
||||
<TouchableWithFeedback
|
||||
@@ -182,9 +183,15 @@ const EmojiSuggestion = ({
|
||||
emojiName={item}
|
||||
textStyle={style.emojiText}
|
||||
size={EMOJI_SIZE}
|
||||
testID={emojiSuggestionItemTestId}
|
||||
/>
|
||||
</View>
|
||||
<Text style={style.emojiName}>{`:${item}:`}</Text>
|
||||
<Text
|
||||
style={style.emojiName}
|
||||
testID={`${emojiSuggestionItemTestId}.name`}
|
||||
>
|
||||
{`:${item}:`}
|
||||
</Text>
|
||||
</View>
|
||||
</TouchableWithFeedback>
|
||||
);
|
||||
@@ -211,7 +218,6 @@ const EmojiSuggestion = ({
|
||||
|
||||
return (
|
||||
<FlatList
|
||||
testID='emoji_suggestion.list'
|
||||
keyboardShouldPersistTaps='always'
|
||||
style={flatListStyle}
|
||||
data={data}
|
||||
@@ -220,6 +226,7 @@ const EmojiSuggestion = ({
|
||||
renderItem={renderItem}
|
||||
nestedScrollEnabled={nestedScrollEnabled}
|
||||
contentContainerStyle={containerStyle}
|
||||
testID='autocomplete.emoji_suggestion.flat_list'
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -120,7 +120,7 @@ const AppSlashSuggestion = ({
|
||||
<AtMentionItem
|
||||
user={item.item as UserProfile | UserModel}
|
||||
onPress={completeIgnoringSuggestion(item.Complete)}
|
||||
testID={`autocomplete.at_mention.item.${item.item}`}
|
||||
testID='autocomplete.slash_suggestion.at_mention_item'
|
||||
/>
|
||||
);
|
||||
case COMMAND_SUGGESTION_CHANNEL:
|
||||
@@ -131,7 +131,7 @@ const AppSlashSuggestion = ({
|
||||
<ChannelMentionItem
|
||||
channel={item.item as Channel | ChannelModel}
|
||||
onPress={completeIgnoringSuggestion(item.Complete)}
|
||||
testID={`autocomplete.channel_mention.item.${item.item}`}
|
||||
testID='autocomplete.slash_suggestion.channel_mention_item'
|
||||
/>
|
||||
);
|
||||
default:
|
||||
|
||||
@@ -232,7 +232,6 @@ const SlashSuggestion = ({
|
||||
|
||||
return (
|
||||
<FlatList
|
||||
testID='slash_suggestion.list'
|
||||
keyboardShouldPersistTaps='always'
|
||||
style={listStyle}
|
||||
data={dataSource}
|
||||
@@ -240,6 +239,7 @@ const SlashSuggestion = ({
|
||||
removeClippedSubviews={true}
|
||||
renderItem={renderItem}
|
||||
nestedScrollEnabled={nestedScrollEnabled}
|
||||
testID='autocomplete.slash_suggestion.flat_list'
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -153,11 +153,14 @@ const SlashSuggestionItem = ({
|
||||
}
|
||||
}
|
||||
|
||||
const slashSuggestionItemTestId = `autocomplete.slash_suggestion_item.${suggestion}`;
|
||||
|
||||
return (
|
||||
<TouchableWithFeedback
|
||||
onPress={completeSuggestion}
|
||||
style={touchableStyle}
|
||||
underlayColor={changeOpacity(theme.buttonBg, 0.08)}
|
||||
testID={slashSuggestionItemTestId}
|
||||
type={'native'}
|
||||
>
|
||||
<View style={style.container}>
|
||||
@@ -165,12 +168,18 @@ const SlashSuggestionItem = ({
|
||||
{image}
|
||||
</View>
|
||||
<View style={style.suggestionContainer}>
|
||||
<Text style={style.suggestionName}>{`${suggestionText}`}</Text>
|
||||
<Text
|
||||
style={style.suggestionName}
|
||||
testID={`${slashSuggestionItemTestId}.name`}
|
||||
>
|
||||
{`${suggestionText}`}
|
||||
</Text>
|
||||
{Boolean(description) &&
|
||||
<Text
|
||||
ellipsizeMode='tail'
|
||||
numberOfLines={1}
|
||||
style={style.suggestionDescription}
|
||||
testID={`${slashSuggestionItemTestId}.description`}
|
||||
>
|
||||
{description}
|
||||
</Text>
|
||||
|
||||
@@ -54,12 +54,14 @@ type Props = {
|
||||
defaultMessage: string;
|
||||
id: string;
|
||||
onPress: (handle: string) => void;
|
||||
testID?: string;
|
||||
}
|
||||
const SpecialMentionItem = ({
|
||||
completeHandle,
|
||||
defaultMessage,
|
||||
id,
|
||||
onPress,
|
||||
testID,
|
||||
}: Props) => {
|
||||
const theme = useTheme();
|
||||
const style = getStyleFromTheme(theme);
|
||||
@@ -67,10 +69,13 @@ const SpecialMentionItem = ({
|
||||
onPress(completeHandle);
|
||||
}, [completeHandle, onPress]);
|
||||
|
||||
const specialMentionItemTestId = `${testID}.${id}`;
|
||||
|
||||
return (
|
||||
<TouchableWithFeedback
|
||||
onPress={completeMention}
|
||||
underlayColor={changeOpacity(theme.buttonBg, 0.08)}
|
||||
testID={specialMentionItemTestId}
|
||||
type={'native'}
|
||||
>
|
||||
<View style={style.row}>
|
||||
@@ -84,11 +89,17 @@ const SpecialMentionItem = ({
|
||||
style={style.textWrapper}
|
||||
numberOfLines={1}
|
||||
>
|
||||
<Text style={style.rowUsername}>{`@${completeHandle} - `}</Text>
|
||||
<Text
|
||||
style={style.rowUsername}
|
||||
testID={`${specialMentionItemTestId}.name`}
|
||||
>
|
||||
{`@${completeHandle} - `}
|
||||
</Text>
|
||||
<FormattedText
|
||||
id={id}
|
||||
defaultMessage={defaultMessage}
|
||||
style={style.rowFullname}
|
||||
testID={`${specialMentionItemTestId}.display_name`}
|
||||
/>
|
||||
</Text>
|
||||
</View>
|
||||
|
||||
@@ -16,6 +16,7 @@ type Props = {
|
||||
channelId: string;
|
||||
channelType?: string;
|
||||
inModal?: boolean;
|
||||
testID?: string;
|
||||
}
|
||||
|
||||
const OPTIONS_HEIGHT = 62;
|
||||
@@ -31,7 +32,7 @@ const styles = StyleSheet.create({
|
||||
},
|
||||
});
|
||||
|
||||
const ChannelActions = ({channelId, channelType, inModal = false}: Props) => {
|
||||
const ChannelActions = ({channelId, channelType, inModal = false, testID}: Props) => {
|
||||
const onCopyLinkAnimationEnd = useCallback(() => {
|
||||
if (!inModal) {
|
||||
requestAnimationFrame(async () => {
|
||||
@@ -45,17 +46,20 @@ const ChannelActions = ({channelId, channelType, inModal = false}: Props) => {
|
||||
<FavoriteBox
|
||||
channelId={channelId}
|
||||
showSnackBar={!inModal}
|
||||
testID={`${testID}.favorite.action`}
|
||||
/>
|
||||
<View style={styles.separator}/>
|
||||
<MutedBox
|
||||
channelId={channelId}
|
||||
showSnackBar={!inModal}
|
||||
testID={`${testID}.mute.action`}
|
||||
/>
|
||||
<View style={styles.separator}/>
|
||||
{channelType && DIRECT_CHANNELS.includes(channelType) &&
|
||||
<SetHeaderBox
|
||||
channelId={channelId}
|
||||
inModal={inModal}
|
||||
testID={`${testID}.set_header.action`}
|
||||
/>
|
||||
}
|
||||
{channelType && !DIRECT_CHANNELS.includes(channelType) &&
|
||||
@@ -63,11 +67,13 @@ const ChannelActions = ({channelId, channelType, inModal = false}: Props) => {
|
||||
<AddPeopleBox
|
||||
channelId={channelId}
|
||||
inModal={inModal}
|
||||
testID={`${testID}.add_people.action`}
|
||||
/>
|
||||
<View style={styles.separator}/>
|
||||
<CopyChannelLinkBox
|
||||
channelId={channelId}
|
||||
onAnimationEnd={onCopyLinkAnimationEnd}
|
||||
testID={`${testID}.copy_channel_link.action`}
|
||||
/>
|
||||
</>
|
||||
}
|
||||
|
||||
@@ -208,8 +208,8 @@ const ChannelListItem = ({
|
||||
<Text
|
||||
ellipsizeMode='tail'
|
||||
numberOfLines={1}
|
||||
testID={`${testID}.${teamDisplayName}.display_name`}
|
||||
style={[styles.teamName, isMuted && styles.teamNameMuted]}
|
||||
testID={`${testID}.${channel.name}.team_display_name`}
|
||||
>
|
||||
{teamDisplayName}
|
||||
</Text>
|
||||
@@ -225,8 +225,8 @@ const ChannelListItem = ({
|
||||
<Text
|
||||
ellipsizeMode='tail'
|
||||
numberOfLines={1}
|
||||
testID={`${testID}.${teamDisplayName}.display_name`}
|
||||
style={[styles.teamName, styles.teamNameTablet, isMuted && styles.teamNameMuted]}
|
||||
testID={`${testID}.${channel.name}.team_display_name`}
|
||||
>
|
||||
{teamDisplayName}
|
||||
</Text>
|
||||
|
||||
@@ -177,7 +177,7 @@ const Markdown = ({
|
||||
};
|
||||
|
||||
const renderBreak = () => {
|
||||
return <Text>{'\n'}</Text>;
|
||||
return <Text testID='markdown_break'>{'\n'}</Text>;
|
||||
};
|
||||
|
||||
const renderChannelLink = ({context, channelName}: MarkdownChannelMentionRenderer) => {
|
||||
@@ -197,7 +197,7 @@ const Markdown = ({
|
||||
|
||||
const renderCheckbox = ({isChecked}: {isChecked: boolean}) => {
|
||||
return (
|
||||
<Text>
|
||||
<Text testID='markdown_checkbox'>
|
||||
<CompassIcon
|
||||
name={isChecked ? 'checkbox-marked' : 'checkbox-blank-outline'}
|
||||
size={16}
|
||||
@@ -236,7 +236,14 @@ const Markdown = ({
|
||||
|
||||
const renderCodeSpan = ({context, literal}: MarkdownBaseRenderer) => {
|
||||
const {code} = textStyles;
|
||||
return <Text style={computeTextStyle(textStyles, [baseTextStyle, code], context)}>{literal}</Text>;
|
||||
return (
|
||||
<Text
|
||||
style={computeTextStyle(textStyles, [baseTextStyle, code], context)}
|
||||
testID='markdown_code_span'
|
||||
>
|
||||
{literal}
|
||||
</Text>
|
||||
);
|
||||
};
|
||||
|
||||
const renderEditedIndicator = ({context}: {context: string[]}) => {
|
||||
@@ -288,7 +295,10 @@ const Markdown = ({
|
||||
const renderHeading = ({children, level}: {children: ReactElement; level: string}) => {
|
||||
if (disableHeading) {
|
||||
return (
|
||||
<Text style={style.bold}>
|
||||
<Text
|
||||
style={style.bold}
|
||||
testID='markdown_heading'
|
||||
>
|
||||
{children}
|
||||
</Text>
|
||||
);
|
||||
@@ -301,7 +311,10 @@ const Markdown = ({
|
||||
const textStyle = textStyles[`heading${level}Text`];
|
||||
|
||||
return (
|
||||
<View style={containerStyle}>
|
||||
<View
|
||||
style={containerStyle}
|
||||
testID='markdown_heading'
|
||||
>
|
||||
<Text style={textStyle}>
|
||||
{children}
|
||||
</Text>
|
||||
@@ -314,7 +327,10 @@ const Markdown = ({
|
||||
|
||||
if (props.isBlock) {
|
||||
rendered = (
|
||||
<View style={style.block}>
|
||||
<View
|
||||
style={style.block}
|
||||
testID='markdown_html'
|
||||
>
|
||||
{rendered}
|
||||
</View>
|
||||
);
|
||||
@@ -419,7 +435,10 @@ const Markdown = ({
|
||||
}
|
||||
|
||||
return (
|
||||
<View style={blockStyle}>
|
||||
<View
|
||||
style={blockStyle}
|
||||
testID='markdown_paragraph'
|
||||
>
|
||||
<Text style={baseParagraphStyle}>
|
||||
{children}
|
||||
</Text>
|
||||
|
||||
@@ -201,6 +201,7 @@ const MarkdownCodeBlock = ({language = '', content, textStyle}: MarkdownCodeBloc
|
||||
<TouchableOpacity
|
||||
onPress={handlePress}
|
||||
onLongPress={handleLongPress}
|
||||
testID='markdown_code_block'
|
||||
>
|
||||
<View style={style.container}>
|
||||
<View>
|
||||
|
||||
@@ -235,10 +235,7 @@ const MarkdownImage = ({
|
||||
onLongPress={handleLinkLongPress}
|
||||
onPress={onGestureEvent}
|
||||
>
|
||||
<Animated.View
|
||||
style={[styles, {width, height}, style.container]}
|
||||
testID='markdown_image'
|
||||
>
|
||||
<Animated.View style={[styles, {width, height}, style.container]}>
|
||||
<ProgressiveImage
|
||||
forwardRef={ref}
|
||||
id={fileInfo.id!}
|
||||
|
||||
@@ -196,6 +196,7 @@ const LatexCodeBlock = ({content, theme}: Props) => {
|
||||
onPress={handlePress}
|
||||
onLongPress={handleLongPress}
|
||||
type={'opacity'}
|
||||
testID='markdown_latex_code_block'
|
||||
>
|
||||
<View style={styles.container}>
|
||||
<ErrorBoundary
|
||||
|
||||
@@ -57,6 +57,7 @@ const LatexInline = ({content, maxMathWidth, theme}: Props) => {
|
||||
<View
|
||||
style={style.viewStyle}
|
||||
key={content}
|
||||
testID='markdown_latex_inline'
|
||||
>
|
||||
<MathView
|
||||
style={[style.mathStyle, {maxWidth: maxMathWidth || '100%'}]}
|
||||
|
||||
@@ -159,6 +159,7 @@ const MarkdownLink = ({children, experimentalNormalizeMarkdownLinks, href, siteU
|
||||
<Text
|
||||
onPress={handlePress}
|
||||
onLongPress={handleLongPress}
|
||||
testID='markdown_link'
|
||||
>
|
||||
{renderChildren}
|
||||
</Text>
|
||||
|
||||
@@ -41,9 +41,15 @@ const MarkdownListItem = ({index, level, bulletWidth, bulletStyle, children, con
|
||||
}
|
||||
|
||||
return (
|
||||
<View style={style.container}>
|
||||
<View
|
||||
style={style.container}
|
||||
testID='markdown_list_item'
|
||||
>
|
||||
<View style={[{width: bulletWidth}, style.bullet]}>
|
||||
<Text style={bulletStyle}>
|
||||
<Text
|
||||
style={bulletStyle}
|
||||
testID='markdown_list_item.bullet'
|
||||
>
|
||||
{bullet}
|
||||
</Text>
|
||||
</View>
|
||||
|
||||
@@ -53,7 +53,10 @@ const MarkdownTableCell = ({isLastCell, align, children}: MarkdownTableCellProps
|
||||
}
|
||||
|
||||
return (
|
||||
<View style={[cellStyle, textStyle]}>
|
||||
<View
|
||||
style={[cellStyle, textStyle]}
|
||||
testID='markdown_table_cell'
|
||||
>
|
||||
{children}
|
||||
</View>
|
||||
);
|
||||
|
||||
@@ -113,10 +113,7 @@ const MarkTableImage = ({disabled, imagesMetadata, location, postId, serverURL,
|
||||
disabled={disabled}
|
||||
onPress={onGestureEvent}
|
||||
>
|
||||
<Animated.View
|
||||
style={[styles, {width, height}]}
|
||||
testID='markdown_table_image'
|
||||
>
|
||||
<Animated.View style={[styles, {width, height}]}>
|
||||
<ProgressiveImage
|
||||
id={fileId}
|
||||
defaultSource={{uri: source}}
|
||||
@@ -131,7 +128,10 @@ const MarkTableImage = ({disabled, imagesMetadata, location, postId, serverURL,
|
||||
}
|
||||
|
||||
return (
|
||||
<View style={style.container}>
|
||||
<View
|
||||
style={style.container}
|
||||
testID='markdown_table_image'
|
||||
>
|
||||
{image}
|
||||
</View>
|
||||
);
|
||||
|
||||
@@ -49,7 +49,14 @@ const MarkdownTableRow = ({isFirstRow, isLastRow, children}: MarkdownTableRowPro
|
||||
isLastCell: true,
|
||||
});
|
||||
|
||||
return <View style={rowStyle}>{renderChildren}</View>;
|
||||
return (
|
||||
<View
|
||||
style={rowStyle}
|
||||
testID='markdown_table_row'
|
||||
>
|
||||
{renderChildren}
|
||||
</View>
|
||||
);
|
||||
};
|
||||
|
||||
export default MarkdownTableRow;
|
||||
|
||||
@@ -113,7 +113,7 @@ const Avatar = ({author, enablePostIconOverride, isAutoReponse, location, post}:
|
||||
size={ViewConstant.PROFILE_PICTURE_SIZE}
|
||||
iconSize={24}
|
||||
showStatus={!isAutoReponse || author.isBot}
|
||||
testID={`post_profile_picture.${author.id}.profile_picture`}
|
||||
testID={`post_avatar.${author.id}.profile_picture`}
|
||||
/>
|
||||
);
|
||||
|
||||
|
||||
@@ -28,14 +28,14 @@ const HeaderTag = ({
|
||||
return (
|
||||
<BotTag
|
||||
style={style.tag}
|
||||
testID='post_header.bot_tag'
|
||||
testID='post_header.bot.tag'
|
||||
/>
|
||||
);
|
||||
} else if (isGuest) {
|
||||
return (
|
||||
<GuestTag
|
||||
style={style.tag}
|
||||
testID='post_header.guest_tag'
|
||||
testID='post_header.guest.tag'
|
||||
/>
|
||||
);
|
||||
} else if (isAutoResponder) {
|
||||
@@ -44,6 +44,7 @@ const HeaderTag = ({
|
||||
id={t('post_info.auto_responder')}
|
||||
defaultMessage={'Automatic Reply'}
|
||||
style={style.tag}
|
||||
testID='post_header.auto_responder.tag'
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@ exports[`renderSystemMessage uses renderer for Channel Display Name update 1`] =
|
||||
},
|
||||
]
|
||||
}
|
||||
testID="markdown_paragraph"
|
||||
>
|
||||
<Text>
|
||||
<Text
|
||||
@@ -79,6 +80,7 @@ exports[`renderSystemMessage uses renderer for Channel Header update 1`] = `
|
||||
},
|
||||
]
|
||||
}
|
||||
testID="markdown_paragraph"
|
||||
>
|
||||
<Text>
|
||||
<Text
|
||||
@@ -156,6 +158,7 @@ exports[`renderSystemMessage uses renderer for Guest added and join to channel 1
|
||||
},
|
||||
]
|
||||
}
|
||||
testID="markdown_paragraph"
|
||||
>
|
||||
<Text>
|
||||
<Text
|
||||
@@ -217,6 +220,7 @@ exports[`renderSystemMessage uses renderer for Guest added and join to channel 2
|
||||
},
|
||||
]
|
||||
}
|
||||
testID="markdown_paragraph"
|
||||
>
|
||||
<Text>
|
||||
<Text
|
||||
@@ -300,6 +304,7 @@ exports[`renderSystemMessage uses renderer for OLD archived channel without a us
|
||||
},
|
||||
]
|
||||
}
|
||||
testID="markdown_paragraph"
|
||||
>
|
||||
<Text>
|
||||
<Text
|
||||
@@ -339,6 +344,7 @@ exports[`renderSystemMessage uses renderer for archived channel 1`] = `
|
||||
},
|
||||
]
|
||||
}
|
||||
testID="markdown_paragraph"
|
||||
>
|
||||
<Text>
|
||||
<Text
|
||||
@@ -400,6 +406,7 @@ exports[`renderSystemMessage uses renderer for unarchived channel 1`] = `
|
||||
},
|
||||
]
|
||||
}
|
||||
testID="markdown_paragraph"
|
||||
>
|
||||
<Text>
|
||||
<Text
|
||||
|
||||
@@ -127,8 +127,8 @@ const UserItem = ({
|
||||
<View
|
||||
style={[style.rowInfo, {maxWidth: shared ? '75%' : '80%'}]}
|
||||
>
|
||||
{bot && <BotTag/>}
|
||||
{guest && <GuestTag/>}
|
||||
{bot && <BotTag testID={`${userItemTestId}.bot.tag`}/>}
|
||||
{guest && <GuestTag testID={`${userItemTestId}.guest.tag`}/>}
|
||||
{Boolean(name.length) &&
|
||||
<Text
|
||||
style={style.rowFullname}
|
||||
@@ -143,6 +143,7 @@ const UserItem = ({
|
||||
id='suggestion.mention.you'
|
||||
defaultMessage=' (you)'
|
||||
style={style.rowUsername}
|
||||
testID={`${userItemTestId}.current_user_indicator`}
|
||||
/>
|
||||
}
|
||||
{Boolean(user) &&
|
||||
|
||||
@@ -198,9 +198,7 @@ export default function UserListRow({
|
||||
const teammateDisplay = displayUsername(user, intl.locale, teammateNameDisplay);
|
||||
const showTeammateDisplay = teammateDisplay !== username;
|
||||
|
||||
const itemTestID = `${testID}.${id}`;
|
||||
const displayNameTestID = `${itemTestID}.display_name`;
|
||||
const profilePictureTestID = `${itemTestID}.profile_picture`;
|
||||
const userItemTestID = `${testID}.${id}`;
|
||||
|
||||
return (
|
||||
<>
|
||||
@@ -212,14 +210,14 @@ export default function UserListRow({
|
||||
<View
|
||||
ref={viewRef}
|
||||
style={style.container}
|
||||
testID={itemTestID}
|
||||
testID={userItemTestID}
|
||||
>
|
||||
<View style={style.profileContainer}>
|
||||
<ProfilePicture
|
||||
author={user}
|
||||
size={32}
|
||||
iconSize={24}
|
||||
testID={profilePictureTestID}
|
||||
testID={`${userItemTestID}.profile_picture`}
|
||||
/>
|
||||
</View>
|
||||
<View style={style.textContainer}>
|
||||
@@ -228,15 +226,17 @@ export default function UserListRow({
|
||||
style={style.username}
|
||||
ellipsizeMode='tail'
|
||||
numberOfLines={1}
|
||||
testID={displayNameTestID}
|
||||
testID={`${userItemTestID}.display_name`}
|
||||
>
|
||||
{usernameDisplay}
|
||||
</Text>
|
||||
<BotTag
|
||||
show={Boolean(user.is_bot)}
|
||||
testID={`${userItemTestID}.bot.tag`}
|
||||
/>
|
||||
<GuestTag
|
||||
show={isGuest(user.roles)}
|
||||
testID={`${userItemTestID}.guest.tag`}
|
||||
/>
|
||||
</View>
|
||||
{showTeammateDisplay &&
|
||||
@@ -245,6 +245,7 @@ export default function UserListRow({
|
||||
style={style.displayName}
|
||||
ellipsizeMode='tail'
|
||||
numberOfLines={1}
|
||||
testID={`${userItemTestID}.team_display_name`}
|
||||
>
|
||||
{teammateDisplay}
|
||||
</Text>
|
||||
@@ -254,6 +255,7 @@ export default function UserListRow({
|
||||
<View>
|
||||
<Text
|
||||
style={style.deactivated}
|
||||
testID={`${userItemTestID}.deactivated`}
|
||||
>
|
||||
{formatMessage({id: 'mobile.user_list.deactivated', defaultMessage: 'Deactivated'})}
|
||||
</Text>
|
||||
|
||||
@@ -46,27 +46,27 @@ const IntroOptions = ({channelId, header, favorite, people}: Props) => {
|
||||
<AddPeopleBox
|
||||
channelId={channelId}
|
||||
containerStyle={[styles.item, styles.margin]}
|
||||
testID='channel_post_list.intro.option_item.add_people'
|
||||
testID='channel_post_list.intro_options.add_people.option'
|
||||
/>
|
||||
}
|
||||
{header &&
|
||||
<SetHeaderBox
|
||||
channelId={channelId}
|
||||
containerStyle={[styles.item, styles.margin]}
|
||||
testID='channel_post_list.intro.option_item.set_header'
|
||||
testID='channel_post_list.intro_options.set_header.option'
|
||||
/>
|
||||
}
|
||||
{favorite &&
|
||||
<FavoriteBox
|
||||
channelId={channelId}
|
||||
containerStyle={[styles.item, styles.margin]}
|
||||
testID='channel_post_list.intro.option_item.favorite'
|
||||
testID='channel_post_list.intro_options.favorite.option'
|
||||
/>
|
||||
}
|
||||
<InfoBox
|
||||
channelId={channelId}
|
||||
containerStyle={styles.item}
|
||||
testID='channel_post_list.intro.option_item.channel_details'
|
||||
testID='channel_post_list.intro_options.channel_details.option'
|
||||
/>
|
||||
</View>
|
||||
);
|
||||
|
||||
@@ -39,14 +39,20 @@ const ChannelQuickAction = ({channelId}: Props) => {
|
||||
return (
|
||||
<View style={styles.container}>
|
||||
<View style={styles.wrapper}>
|
||||
<ChannelActions channelId={channelId}/>
|
||||
<ChannelActions
|
||||
channelId={channelId}
|
||||
testID='channel.quick_actions'
|
||||
/>
|
||||
</View>
|
||||
<InfoBox
|
||||
channelId={channelId}
|
||||
showAsLabel={true}
|
||||
/>
|
||||
<View style={styles.line}/>
|
||||
<LeaveChannelLabel channelId={channelId}/>
|
||||
<LeaveChannelLabel
|
||||
channelId={channelId}
|
||||
testID='channel.quick_actions.leave_channel.action'
|
||||
/>
|
||||
</View>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -54,11 +54,13 @@ const ChannelInfo = ({channelId, closeButtonId, componentId, type}: Props) => {
|
||||
<SafeAreaView
|
||||
edges={edges}
|
||||
style={styles.flex}
|
||||
testID='channel_info.screen'
|
||||
>
|
||||
<ScrollView
|
||||
bounces={true}
|
||||
alwaysBounceVertical={false}
|
||||
contentContainerStyle={styles.content}
|
||||
testID='channel_info.scrollview'
|
||||
>
|
||||
<Title
|
||||
channelId={channelId}
|
||||
@@ -67,6 +69,7 @@ const ChannelInfo = ({channelId, closeButtonId, componentId, type}: Props) => {
|
||||
<ChannelActions
|
||||
channelId={channelId}
|
||||
inModal={true}
|
||||
testID='channel_info.channel_actions'
|
||||
/>
|
||||
<Extra channelId={channelId}/>
|
||||
<View style={styles.separator}/>
|
||||
|
||||
@@ -130,6 +130,7 @@ const Archive = ({
|
||||
icon='archive-outline'
|
||||
destructive={true}
|
||||
type='default'
|
||||
testID='channel_info.options.archive_channel.option'
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -78,6 +78,7 @@ const ConvertPrivate = ({canConvert, channelId, displayName}: Props) => {
|
||||
label={intl.formatMessage({id: 'channel_info.convert_private', defaultMessage: 'Convert to private channel'})}
|
||||
icon='lock-outline'
|
||||
type='default'
|
||||
testID='channel_info.options.convert_private.option'
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -24,6 +24,7 @@ const DestructiveOptions = ({channelId, componentId, type}: Props) => {
|
||||
<LeaveChannelLabel
|
||||
channelId={channelId}
|
||||
isOptionItem={true}
|
||||
testID='channel_info.options.leave_channel.option'
|
||||
/>
|
||||
{type !== General.DM_CHANNEL && type !== General.GM_CHANNEL &&
|
||||
<Archive
|
||||
|
||||
@@ -28,6 +28,7 @@ const EditChannel = ({channelId}: Props) => {
|
||||
label={title}
|
||||
icon='pencil-outline'
|
||||
type={Platform.select({ios: 'arrow', default: 'default'})}
|
||||
testID='channel_info.options.edit_channel.option'
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -34,6 +34,7 @@ const IgnoreMentions = ({channelId, ignoring}: Props) => {
|
||||
icon='at'
|
||||
type='toggle'
|
||||
selected={ignored}
|
||||
testID={`channel_info.options.ignore_mentions.option.toggled.${ignored}`}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -30,6 +30,7 @@ const Members = ({channelId, count}: Props) => {
|
||||
icon='account-multiple-outline'
|
||||
type={Platform.select({ios: 'arrow', default: 'default'})}
|
||||
info={count.toString()}
|
||||
testID='channel_info.options.members.option'
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -59,6 +59,7 @@ const NotificationPreference = ({channelId, notifyLevel}: Props) => {
|
||||
icon='cellphone'
|
||||
type={Platform.select({ios: 'arrow', default: 'default'})}
|
||||
info={notificationLevelToText()}
|
||||
testID='channel_info.options.notification_preference.option'
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -45,6 +45,7 @@ const PinnedMessages = ({channelId, count, displayName}: Props) => {
|
||||
icon='pin-outline'
|
||||
type={Platform.select({ios: 'arrow', default: 'default'})}
|
||||
info={count.toString()}
|
||||
testID='channel_info.options.pinned_messages.option'
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -50,21 +50,27 @@ const getStyleSheet = makeStyleSheetFromTheme((theme: Theme) => ({
|
||||
const DirectMessage = ({displayName, user}: Props) => {
|
||||
const theme = useTheme();
|
||||
const styles = getStyleSheet(theme);
|
||||
const directMessageUserTestId = `channel_info.title.direct_message.${user?.id}`;
|
||||
|
||||
return (
|
||||
<View style={styles.container}>
|
||||
<View
|
||||
style={styles.container}
|
||||
testID={directMessageUserTestId}
|
||||
>
|
||||
<ProfilePicture
|
||||
author={user}
|
||||
size={64}
|
||||
iconSize={64}
|
||||
showStatus={true}
|
||||
statusSize={24}
|
||||
testID={`${directMessageUserTestId}.profile_picture`}
|
||||
/>
|
||||
<View style={styles.titleContainer}>
|
||||
<View style={styles.displayName}>
|
||||
<Text
|
||||
numberOfLines={1}
|
||||
style={styles.title}
|
||||
testID={`${directMessageUserTestId}.display_name`}
|
||||
>
|
||||
{displayName}
|
||||
</Text>
|
||||
@@ -72,22 +78,30 @@ const DirectMessage = ({displayName, user}: Props) => {
|
||||
<GuestTag
|
||||
textStyle={styles.tag}
|
||||
style={styles.tagContainer}
|
||||
testID={`${directMessageUserTestId}.guest.tag`}
|
||||
/>
|
||||
}
|
||||
{user?.isBot &&
|
||||
<BotTag
|
||||
textStyle={styles.tag}
|
||||
style={styles.tagContainer}
|
||||
testID={`${directMessageUserTestId}.bot.tag`}
|
||||
/>
|
||||
}
|
||||
</View>
|
||||
{Boolean(user?.position) &&
|
||||
<Text style={styles.position}>
|
||||
<Text
|
||||
style={styles.position}
|
||||
testID={`${directMessageUserTestId}.position`}
|
||||
>
|
||||
{user?.position}
|
||||
</Text>
|
||||
}
|
||||
{Boolean(user?.isBot && user.props?.bot_description) &&
|
||||
<Text style={styles.position}>
|
||||
<Text
|
||||
style={styles.position}
|
||||
testID={`${directMessageUserTestId}.bot_description`}
|
||||
>
|
||||
{user?.props?.bot_description}
|
||||
</Text>
|
||||
}
|
||||
|
||||
@@ -57,7 +57,10 @@ const GroupAvatars = ({users}: Props) => {
|
||||
});
|
||||
|
||||
return (
|
||||
<View style={[styles.container]}>
|
||||
<View
|
||||
style={[styles.container]}
|
||||
testID='channel_info.title.group_message.group_avatars'
|
||||
>
|
||||
{group}
|
||||
</View>
|
||||
);
|
||||
|
||||
@@ -40,7 +40,10 @@ const GroupMessage = ({currentUserId, displayName, members}: Props) => {
|
||||
<GroupAvatars
|
||||
userIds={userIds}
|
||||
/>
|
||||
<Text style={styles.title}>
|
||||
<Text
|
||||
style={styles.title}
|
||||
testID='channel_info.title.group_message.display_name'
|
||||
>
|
||||
{displayName}
|
||||
</Text>
|
||||
</>
|
||||
|
||||
@@ -28,14 +28,21 @@ const getStyleSheet = makeStyleSheetFromTheme((theme: Theme) => ({
|
||||
const PublicPrivate = ({displayName, purpose}: Props) => {
|
||||
const theme = useTheme();
|
||||
const styles = getStyleSheet(theme);
|
||||
const publicPrivateTestId = 'channel_info.title.public_private';
|
||||
|
||||
return (
|
||||
<>
|
||||
<Text style={styles.title}>
|
||||
<Text
|
||||
style={styles.title}
|
||||
testID={`${publicPrivateTestId}.display_name`}
|
||||
>
|
||||
{displayName}
|
||||
</Text>
|
||||
{Boolean(purpose) &&
|
||||
<Text style={styles.purpose}>
|
||||
<Text
|
||||
style={styles.purpose}
|
||||
testID={`${publicPrivateTestId}.purpose`}
|
||||
>
|
||||
{purpose}
|
||||
</Text>
|
||||
}
|
||||
|
||||
@@ -220,6 +220,7 @@ const FilteredList = ({
|
||||
<UserItem
|
||||
onPress={onOpenDirectMessage}
|
||||
user={item}
|
||||
testID='find_channels.filtered_list.user_item'
|
||||
/>
|
||||
);
|
||||
}
|
||||
@@ -229,6 +230,7 @@ const FilteredList = ({
|
||||
channel={item}
|
||||
onPress={onJoinChannel}
|
||||
showTeamName={showTeamName}
|
||||
testID='find_channels.filtered_list.remote_channel_item'
|
||||
/>
|
||||
);
|
||||
}, [onJoinChannel, onOpenDirectMessage, onSwitchToChannel, showTeamName, teammateDisplayNameSetting]);
|
||||
|
||||
@@ -101,7 +101,7 @@ const RemoteChannelItem = ({onPress, channel, teamDisplayName, testID}: Props) =
|
||||
<Text
|
||||
ellipsizeMode='tail'
|
||||
numberOfLines={1}
|
||||
testID={`${testID}.${teamDisplayName}.display_name`}
|
||||
testID={`${testID}.${channel.name}.team_display_name`}
|
||||
style={styles.teamName}
|
||||
>
|
||||
{teamDisplayName}
|
||||
@@ -112,7 +112,7 @@ const RemoteChannelItem = ({onPress, channel, teamDisplayName, testID}: Props) =
|
||||
<Text
|
||||
ellipsizeMode='tail'
|
||||
numberOfLines={1}
|
||||
testID={`${testID}.${teamDisplayName}.display_name`}
|
||||
testID={`${testID}.${channel.name}.team_display_name`}
|
||||
style={[styles.teamName, styles.teamNameTablet]}
|
||||
>
|
||||
{teamDisplayName}
|
||||
|
||||
@@ -54,6 +54,7 @@ const UserItem = ({currentUserId, onPress, teammateDisplayNameSetting, testID, u
|
||||
const styles = getStyleSheet(theme);
|
||||
const isOwnDirectMessage = currentUserId === user.id;
|
||||
const displayName = displayUsername(user, locale, teammateDisplayNameSetting);
|
||||
const userItemTestId = `${testID}.${user.id}`;
|
||||
|
||||
const handleOnPress = useCallback(() => {
|
||||
onPress(user.id, displayName);
|
||||
@@ -64,7 +65,7 @@ const UserItem = ({currentUserId, onPress, teammateDisplayNameSetting, testID, u
|
||||
<>
|
||||
<View
|
||||
style={styles.container}
|
||||
testID={`${testID}.${user.id}`}
|
||||
testID={userItemTestId}
|
||||
>
|
||||
<View style={styles.wrapper}>
|
||||
<View style={styles.avatar}>
|
||||
@@ -74,6 +75,7 @@ const UserItem = ({currentUserId, onPress, teammateDisplayNameSetting, testID, u
|
||||
showStatus={true}
|
||||
statusSize={12}
|
||||
statusStyle={styles.status}
|
||||
testID={`${userItemTestId}.profile_picture`}
|
||||
/>
|
||||
</View>
|
||||
<View>
|
||||
@@ -81,7 +83,7 @@ const UserItem = ({currentUserId, onPress, teammateDisplayNameSetting, testID, u
|
||||
ellipsizeMode='tail'
|
||||
numberOfLines={1}
|
||||
style={styles.text}
|
||||
testID={`${testID}.${user.id}.display_name`}
|
||||
testID={`${userItemTestId}.display_name`}
|
||||
>
|
||||
{isOwnDirectMessage ? formatMessage({id: 'channel_header.directchannel.you', defaultMessage: '{displayName} (you)'}, {displayName}) : displayName}
|
||||
</Text>
|
||||
|
||||
@@ -52,6 +52,7 @@ const AccountUserInfo = ({user, showFullName, theme}: Props) => {
|
||||
const nickName = user.nickname ? ` (${user.nickname})` : '';
|
||||
const title = `${user.firstName} ${user.lastName}${nickName}`;
|
||||
const userName = `@${user.username}`;
|
||||
const accountUserInfoTestId = `account_user_info.${user.id}`;
|
||||
|
||||
return (
|
||||
<View style={styles.container}>
|
||||
@@ -62,10 +63,15 @@ const AccountUserInfo = ({user, showFullName, theme}: Props) => {
|
||||
author={user}
|
||||
statusStyle={styles.statusStyle}
|
||||
statusSize={24}
|
||||
testID={`account.${user.id}.profile_picture`}
|
||||
testID={`${accountUserInfoTestId}.profile_picture`}
|
||||
/>
|
||||
{showFullName && <Text style={styles.textFullName}>{title}</Text>}
|
||||
<Text style={showFullName ? styles.textUserName : styles.textFullName}>{`${userName}`}</Text>
|
||||
<Text
|
||||
style={showFullName ? styles.textUserName : styles.textFullName}
|
||||
testID={`${accountUserInfoTestId}.username`}
|
||||
>
|
||||
{`${userName}`}
|
||||
</Text>
|
||||
</View>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -66,7 +66,7 @@ const ReactorsList = ({location, reactions}: Props) => {
|
||||
scrollEnabled={enabled}
|
||||
scrollEventThrottle={60}
|
||||
{...panResponder.panHandlers}
|
||||
testID='reactors_list.flat_list'
|
||||
testID='reactions.reactors_list.flat_list'
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -45,7 +45,7 @@ const Reactor = ({channelId, location, user}: Props) => {
|
||||
<UserItem
|
||||
containerStyle={style.container}
|
||||
user={user}
|
||||
testID='reactors_list.user_item'
|
||||
testID='reactions.reactor_item'
|
||||
/>
|
||||
</TouchableOpacity>
|
||||
);
|
||||
|
||||
@@ -11,6 +11,7 @@ import {typography} from '@utils/typography';
|
||||
type Props = {
|
||||
title: string;
|
||||
description: string;
|
||||
testID?: string;
|
||||
};
|
||||
|
||||
const getStyleSheet = makeStyleSheetFromTheme((theme: Theme) => ({
|
||||
@@ -28,14 +29,24 @@ const getStyleSheet = makeStyleSheetFromTheme((theme: Theme) => ({
|
||||
},
|
||||
}));
|
||||
|
||||
const UserProfileLabel = ({title, description}: Props) => {
|
||||
const UserProfileLabel = ({title, description, testID}: Props) => {
|
||||
const theme = useTheme();
|
||||
const styles = getStyleSheet(theme);
|
||||
|
||||
return (
|
||||
<View style={styles.container}>
|
||||
<Text style={styles.title}>{title}</Text>
|
||||
<Text style={styles.description}>{description}</Text>
|
||||
<Text
|
||||
style={styles.title}
|
||||
testID={`${testID}.title`}
|
||||
>
|
||||
{title}
|
||||
</Text>
|
||||
<Text
|
||||
style={styles.description}
|
||||
testID={`${testID}.description`}
|
||||
>
|
||||
{description}
|
||||
</Text>
|
||||
</View>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -77,12 +77,14 @@ const UserProfileOptions = ({location, type, userId, username}: Props) => {
|
||||
<OptionBox
|
||||
iconName='send'
|
||||
onPress={openChannel}
|
||||
testID='user_profile_options.send_message.option'
|
||||
text={intl.formatMessage({id: 'channel_info.send_mesasge', defaultMessage: 'Send message'})}
|
||||
/>
|
||||
<View style={styles.divider}/>
|
||||
<OptionBox
|
||||
iconName='at'
|
||||
onPress={mentionUser}
|
||||
testID='user_profile_options.mention.option'
|
||||
text={intl.formatMessage({id: 'channel_info.mention', defaultMessage: 'Mention'})}
|
||||
/>
|
||||
</View>
|
||||
@@ -94,6 +96,7 @@ const UserProfileOptions = ({location, type, userId, username}: Props) => {
|
||||
<TouchableOpacity
|
||||
style={[buttonStyle, styles.singleButton]}
|
||||
onPress={openChannel}
|
||||
testID='user_profile_options.send_message.option'
|
||||
>
|
||||
<CompassIcon
|
||||
color={theme.buttonBg}
|
||||
|
||||
@@ -43,6 +43,7 @@ const UserProfileAvatar = ({enablePostIconOverride, user, userIconOverride}: Pro
|
||||
showStatus={true}
|
||||
size={96}
|
||||
statusSize={24}
|
||||
testID={`user_profile_avatar.${user.id}.profile_picture`}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -89,6 +89,7 @@ const UserProfileTitle = ({
|
||||
<Text
|
||||
numberOfLines={1}
|
||||
style={styles.displayName}
|
||||
testID='user_profile.display_name'
|
||||
>
|
||||
{`${prefix}${displayName}`}
|
||||
</Text>
|
||||
@@ -96,6 +97,7 @@ const UserProfileTitle = ({
|
||||
<Text
|
||||
numberOfLines={1}
|
||||
style={styles.username}
|
||||
testID='user_profile.username'
|
||||
>
|
||||
{`@${user.username}`}
|
||||
</Text>
|
||||
|
||||
@@ -24,11 +24,19 @@ const styles = StyleSheet.create({
|
||||
|
||||
const UserProfileTag = ({isBot, isChannelAdmin, isGuest, isSystemAdmin, isTeamAdmin}: Props) => {
|
||||
if (isBot) {
|
||||
return (<BotTag style={styles.tag}/>);
|
||||
return (
|
||||
<BotTag
|
||||
style={styles.tag}
|
||||
testID='user_profile.bot.tag'
|
||||
/>);
|
||||
}
|
||||
|
||||
if (isGuest) {
|
||||
return (<GuestTag style={styles.tag}/>);
|
||||
return (
|
||||
<GuestTag
|
||||
style={styles.tag}
|
||||
testID='user_profile.guest.tag'
|
||||
/>);
|
||||
}
|
||||
|
||||
if (isSystemAdmin) {
|
||||
@@ -37,6 +45,7 @@ const UserProfileTag = ({isBot, isChannelAdmin, isGuest, isSystemAdmin, isTeamAd
|
||||
id='user_profile.system_admin'
|
||||
defaultMessage='System Admin'
|
||||
style={styles.tag}
|
||||
testID='user_profile.system_admin.tag'
|
||||
/>
|
||||
);
|
||||
}
|
||||
@@ -47,6 +56,7 @@ const UserProfileTag = ({isBot, isChannelAdmin, isGuest, isSystemAdmin, isTeamAd
|
||||
id='user_profile.team_admin'
|
||||
defaultMessage='Team Admin'
|
||||
style={styles.tag}
|
||||
testID='user_profile.team_admin.tag'
|
||||
/>
|
||||
);
|
||||
}
|
||||
@@ -57,6 +67,7 @@ const UserProfileTag = ({isBot, isChannelAdmin, isGuest, isSystemAdmin, isTeamAd
|
||||
id='user_profile.channel_admin'
|
||||
defaultMessage='Channel Admin'
|
||||
style={styles.tag}
|
||||
testID='user_profile.channel_admin.tag'
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -127,18 +127,21 @@ const UserProfile = ({
|
||||
{Boolean(user.nickname) && !override && !user.isBot &&
|
||||
<UserProfileLabel
|
||||
description={user.nickname}
|
||||
testID='user_profile.nickname'
|
||||
title={formatMessage({id: 'channel_info.nickname', defaultMessage: 'Nickname'})}
|
||||
/>
|
||||
}
|
||||
{Boolean(user.position) && !override && !user.isBot &&
|
||||
<UserProfileLabel
|
||||
description={user.position}
|
||||
testID='user_profile.position'
|
||||
title={formatMessage({id: 'channel_info.position', defaultMessage: 'Position'})}
|
||||
/>
|
||||
}
|
||||
{Boolean(localTime) && !override && !user.isBot &&
|
||||
<UserProfileLabel
|
||||
description={localTime!}
|
||||
testID='user_profile.local_time'
|
||||
title={formatMessage({id: 'channel_info.local_time', defaultMessage: 'Local Time'})}
|
||||
/>
|
||||
}
|
||||
@@ -153,7 +156,7 @@ const UserProfile = ({
|
||||
componentId={Screens.USER_PROFILE}
|
||||
initialSnapIndex={0}
|
||||
snapPoints={snapPoints}
|
||||
testID='post_options'
|
||||
testID='user_profile'
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -102,6 +102,23 @@ export const apiCreateGroupChannel = async (baseUrl: string, userIds: string[] =
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Delete a channel.
|
||||
* See https://api.mattermost.com/#operation/DeleteChannel
|
||||
* @param {string} baseUrl - the base server URL
|
||||
* @param {string} channelId - The channel ID to be deleted
|
||||
* @return {Object} returns {deleted} on success or {error, status} on error
|
||||
*/
|
||||
export const apiDeleteChannel = async (baseUrl: string, channelId: string): Promise<any> => {
|
||||
try {
|
||||
const response = await client.delete(`${baseUrl}/api/v4/channels/${channelId}`);
|
||||
|
||||
return {deleted: response.data};
|
||||
} catch (err) {
|
||||
return getResponseFromError(err);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Get a channel by name.
|
||||
* See https://api.mattermost.com/#operation/GetChannelByName
|
||||
@@ -172,6 +189,23 @@ export const apiGetUnreadMessages = async (baseUrl: string, userId: string, chan
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Restore a channel.
|
||||
* See https://api.mattermost.com/#operation/RestoreChannel
|
||||
* @param {string} baseUrl - the base server URL
|
||||
* @param {string} channelId - The channel ID to be restored
|
||||
* @return {Object} returns {restored} on success or {error, status} on error
|
||||
*/
|
||||
export const apiRestoreChannel = async (baseUrl: string, channelId: string): Promise<any> => {
|
||||
try {
|
||||
const response = await client.post(`${baseUrl}/api/v4/channels/${channelId}/restore`);
|
||||
|
||||
return {restored: response.data};
|
||||
} catch (err) {
|
||||
return getResponseFromError(err);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Remove user from channel.
|
||||
* See https://api.mattermost.com/#operation/RemoveUserFromChannel
|
||||
@@ -231,9 +265,11 @@ export const Channel = {
|
||||
apiCreateChannel,
|
||||
apiCreateDirectChannel,
|
||||
apiCreateGroupChannel,
|
||||
apiDeleteChannel,
|
||||
apiGetChannelByName,
|
||||
apiGetChannelsForUser,
|
||||
apiGetUnreadMessages,
|
||||
apiRestoreChannel,
|
||||
apiRemoveUserFromChannel,
|
||||
apiViewChannel,
|
||||
generateRandomChannel,
|
||||
|
||||
@@ -5,6 +5,7 @@ import {isAndroid} from '@support/utils';
|
||||
|
||||
class Alert {
|
||||
// alert titles
|
||||
confirmSendingNotificationsTitle = isAndroid() ? element(by.text('Confirm sending notifications to entire channel')) : element(by.label('Confirm sending notifications to entire channel')).atIndex(0);
|
||||
deletePostTitle = isAndroid() ? element(by.text('Delete Post')) : element(by.label('Delete Post')).atIndex(0);
|
||||
logoutTitle = (serverDisplayName: string) => {
|
||||
const title = `Are you sure you want to log out of ${serverDisplayName}?`;
|
||||
@@ -21,6 +22,7 @@ class Alert {
|
||||
|
||||
// alert buttons
|
||||
cancelButton = isAndroid() ? element(by.text('CANCEL')) : element(by.label('Cancel')).atIndex(1);
|
||||
confirmButton = isAndroid() ? element(by.text('CONFIRM')) : element(by.label('Confirm')).atIndex(1);
|
||||
deleteButton = isAndroid() ? element(by.text('DELETE')) : element(by.label('Delete')).atIndex(0);
|
||||
logoutButton = isAndroid() ? element(by.text('LOG OUT')) : element(by.label('Log out')).atIndex(1);
|
||||
markReadButton = isAndroid() ? element(by.text('MARK READ')) : element(by.label('Mark read')).atIndex(1);
|
||||
|
||||
125
detox/e2e/support/ui/component/autocomplete.ts
Normal file
125
detox/e2e/support/ui/component/autocomplete.ts
Normal file
@@ -0,0 +1,125 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
import {expect} from 'detox';
|
||||
|
||||
import ProfilePicture from './profile_picture';
|
||||
|
||||
class Autocomplete {
|
||||
testID = {
|
||||
atMentionItemPrefix: 'autocomplete.at_mention_item.',
|
||||
groupMentionItemPrefix: 'autocomplete.group_mention_item.',
|
||||
specialMentionItemPrefix: 'autocomplete.special_mention_item.',
|
||||
channelMentionItemPrefix: 'autocomplete.channel_mention_item.',
|
||||
emojiSuggestionItemPrefix: 'autocomplete.emoji_suggestion_item.',
|
||||
slashSuggestionItemPrefix: 'autocomplete.slash_suggestion_item.',
|
||||
autocomplete: 'autocomplete',
|
||||
sectionAtMentionList: 'autocomplete.at_mention.section_list',
|
||||
sectionChannelMentionList: 'autocomplete.channel_mention.section_list',
|
||||
flatEmojiSuggestionList: 'autocomplete.emoji_suggestion.flat_list',
|
||||
flatSlashSuggestionList: 'autocomplete.slash_suggestion.flat_list',
|
||||
};
|
||||
|
||||
autocomplete = element(by.id(this.testID.autocomplete));
|
||||
sectionAtMentionList = element(by.id(this.testID.sectionAtMentionList));
|
||||
sectionChannelMentionList = element(by.id(this.testID.sectionChannelMentionList));
|
||||
flatEmojiSuggestionList = element(by.id(this.testID.flatEmojiSuggestionList));
|
||||
flatSlashSuggestionList = element(by.id(this.testID.flatSlashSuggestionList));
|
||||
|
||||
getAtMentionItem = (userId: string) => {
|
||||
const atMentionItemTestId = `${this.testID.atMentionItemPrefix}${userId}`;
|
||||
const atMentionItemMatcher = by.id(atMentionItemTestId);
|
||||
const atMentionItemProfilePictureMatcher = ProfilePicture.getProfilePictureItemMatcher(this.testID.atMentionItemPrefix, userId);
|
||||
const atMentionItemBotTagMatcher = by.id(`${atMentionItemTestId}.bot.tag`);
|
||||
const atMentionItemGuestTagMatcher = by.id(`${atMentionItemTestId}.guest.tag`);
|
||||
const atMentionItemUserDisplayNameMatcher = by.id(`${atMentionItemTestId}.display_name`);
|
||||
const atMentionItemCurrentUserIndicatorMatcher = by.id(`${atMentionItemTestId}.current_user_indicator`);
|
||||
const atMentionItemUsernameMatcher = by.id(`${atMentionItemTestId}.username`);
|
||||
|
||||
return {
|
||||
atMentionItem: element(atMentionItemMatcher),
|
||||
atMentionItemProfilePicture: element(atMentionItemProfilePictureMatcher),
|
||||
atMentionItemBotTag: element(atMentionItemBotTagMatcher),
|
||||
atMentionItemGuestTag: element(atMentionItemGuestTagMatcher),
|
||||
atMentionItemUserDisplayName: element(atMentionItemUserDisplayNameMatcher),
|
||||
atMentionItemCurrentUserIndicator: element(atMentionItemCurrentUserIndicatorMatcher),
|
||||
atMentionItemUsername: element(atMentionItemUsernameMatcher),
|
||||
};
|
||||
};
|
||||
|
||||
getGrouptMentionItem = (groupName: string) => {
|
||||
const groupMentionItemTestId = `${this.testID.groupMentionItemPrefix}${groupName}`;
|
||||
const groupMentionItemMatcher = by.id(groupMentionItemTestId);
|
||||
const groupMentionItemGroupDisplayNameMatcher = by.id(`${groupMentionItemTestId}.display_name`);
|
||||
const groupMentionItemGroupNameMatcher = by.id(`${groupMentionItemTestId}.name`);
|
||||
|
||||
return {
|
||||
groupMentionItem: element(groupMentionItemMatcher),
|
||||
groupMentionItemGroupDisplayName: element(groupMentionItemGroupDisplayNameMatcher),
|
||||
groupMentionItemGroupName: element(groupMentionItemGroupNameMatcher),
|
||||
};
|
||||
};
|
||||
|
||||
getSpecialMentionItem = (handleName: string) => {
|
||||
const specialMentionItemTestId = `${this.testID.specialMentionItemPrefix}${handleName}`;
|
||||
const specialMentionItemMatcher = by.id(specialMentionItemTestId);
|
||||
const specialMentionItemGroupDisplayNameMatcher = by.id(`${specialMentionItemTestId}.display_name`);
|
||||
const specialMentionItemGroupNameMatcher = by.id(`${specialMentionItemTestId}.name`);
|
||||
|
||||
return {
|
||||
specialMentionItem: element(specialMentionItemMatcher),
|
||||
specialMentionItemGroupDisplayName: element(specialMentionItemGroupDisplayNameMatcher),
|
||||
specialMentionItemGroupName: element(specialMentionItemGroupNameMatcher),
|
||||
};
|
||||
};
|
||||
|
||||
getChannelMentionItem = (channelName: string) => {
|
||||
const channelMentionItemTestId = `${this.testID.channelMentionItemPrefix}${channelName}`;
|
||||
const channelMentionItemMatcher = by.id(channelMentionItemTestId);
|
||||
const channelMentionItemChannelDisplayNameMatcher = by.id(`${channelMentionItemTestId}.display_name`);
|
||||
const channelMentionItemChannelNameMatcher = by.id(`${channelMentionItemTestId}.name`);
|
||||
|
||||
return {
|
||||
channelMentionItem: element(channelMentionItemMatcher),
|
||||
channelMentionItemChannelDisplayName: element(channelMentionItemChannelDisplayNameMatcher),
|
||||
channelMentionItemChannelName: element(channelMentionItemChannelNameMatcher),
|
||||
};
|
||||
};
|
||||
|
||||
getEmojiSuggestionItem = (emojiName: string) => {
|
||||
const emojiSuggestionItemTestId = `${this.testID.emojiSuggestionItemPrefix}${emojiName}`;
|
||||
const emojiSuggestionItemMatcher = by.id(emojiSuggestionItemTestId);
|
||||
const emojiSuggestionItemEmojiNameMatcher = by.id(`${emojiSuggestionItemTestId}.name`);
|
||||
|
||||
return {
|
||||
emojiSuggestionItem: element(emojiSuggestionItemMatcher),
|
||||
emojiSuggestionItemEmojiName: element(emojiSuggestionItemEmojiNameMatcher),
|
||||
};
|
||||
};
|
||||
|
||||
getSlashSuggestionItem = (slashCommand: string) => {
|
||||
const slashSuggestionItemTestId = `${this.testID.slashSuggestionItemPrefix}/${slashCommand}`;
|
||||
const slashSuggestionItemMatcher = by.id(slashSuggestionItemTestId);
|
||||
const slashSuggestionItemSlashCommandNameMatcher = by.id(`${slashSuggestionItemTestId}.name`);
|
||||
const slashSuggestionItemSlashCommandDescriptionMatcher = by.id(`${slashSuggestionItemTestId}.description`);
|
||||
|
||||
return {
|
||||
slashSuggestionItem: element(slashSuggestionItemMatcher),
|
||||
slashSuggestionItemSlashCommandName: element(slashSuggestionItemSlashCommandNameMatcher),
|
||||
slashSuggestionItemSlashCommandDescription: element(slashSuggestionItemSlashCommandDescriptionMatcher),
|
||||
};
|
||||
};
|
||||
|
||||
toBeVisible = async (isVisible = true) => {
|
||||
if (isVisible) {
|
||||
await expect(this.autocomplete.atIndex(0)).toBeVisible();
|
||||
return this.autocomplete;
|
||||
}
|
||||
|
||||
await expect(this.autocomplete).not.toBeVisible();
|
||||
return null;
|
||||
};
|
||||
}
|
||||
|
||||
const autocomplete = new Autocomplete();
|
||||
export default autocomplete;
|
||||
@@ -2,6 +2,7 @@
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
import Alert from './alert';
|
||||
import Autocomplete from './autocomplete';
|
||||
import CameraQuickAction from './camera_quick_action';
|
||||
import FileQuickAction from './file_quick_action';
|
||||
import ImageQuickAction from './image_quick_action';
|
||||
@@ -18,6 +19,7 @@ import TeamSidebar from './team_sidebar';
|
||||
|
||||
export {
|
||||
Alert,
|
||||
Autocomplete,
|
||||
CameraQuickAction,
|
||||
FileQuickAction,
|
||||
ImageQuickAction,
|
||||
|
||||
@@ -5,20 +5,33 @@ import ProfilePicture from './profile_picture';
|
||||
|
||||
class Post {
|
||||
testID = {
|
||||
postProfilePicturePrefix: 'post_profile_picture.',
|
||||
postAvatarPrefix: 'post_avatar.',
|
||||
blockQuote: 'markdown_block_quote',
|
||||
break: 'markdown_break',
|
||||
checkbox: 'markdown_checkbox',
|
||||
codeBlock: 'markdown_code_block',
|
||||
codeSpan: 'markdown_code_span',
|
||||
editedIndicator: 'edited_indicator',
|
||||
emoji: 'markdown_emoji',
|
||||
heading: 'markdown_heading',
|
||||
html: 'markdown_html',
|
||||
image: 'markdown_image',
|
||||
message: 'markdown_text',
|
||||
latexCodeBlock: 'markdown_latex_code_block',
|
||||
latexInLine: 'markdown_latex_inline',
|
||||
link: 'markdown_link',
|
||||
listItem: 'markdown_list_item',
|
||||
listItemBullet: 'markdown_list_item.bullet',
|
||||
paragraph: 'markdown_paragraph',
|
||||
postFooterFollowButton: 'post_footer.follow_thread.button',
|
||||
postFooterFollowingButton: 'post_footer.following_thread.button',
|
||||
postFooterReplyCount: 'post_footer.reply_count',
|
||||
postHeaderCommentedOn: 'post_header.commented_on',
|
||||
postHeaderDateTime: 'post_header.date_time',
|
||||
postHeaderDisplayName: 'post_header.display_name',
|
||||
postHeaderBotTag: 'post_header.bot_tag',
|
||||
postHeaderGuestTag: 'post_header.guest_tag',
|
||||
postHeaderBotTag: 'post_header.bot.tag',
|
||||
postHeaderGuestTag: 'post_header.guest.tag',
|
||||
postHeaderAutoResponderTag: 'post_header.auto_responder.tag',
|
||||
postHeaderReply: 'post_header.reply',
|
||||
postHeaderReplyCount: 'post_header.reply_count',
|
||||
postPreHeaderText: 'post_pre_header.text',
|
||||
@@ -26,37 +39,70 @@ class Post {
|
||||
showLessButton: 'show_more.button.chevron-up',
|
||||
showMoreButton: 'show_more.button.chevron-down',
|
||||
table: 'markdown_table',
|
||||
tableCell: 'markdown_table_cell',
|
||||
tableExpandButton: 'markdown_table.expand.button',
|
||||
tableImage: 'markdown_table_image',
|
||||
tableRow: 'markdown_table_row',
|
||||
thematicBreak: 'markdown_thematic_break',
|
||||
};
|
||||
|
||||
getPost = (postItemSourceTestID: string, postId: string, postMessage: string, postProfileOptions: any = {}) => {
|
||||
const postItemMatcher = this.getPostItemMatcher(postItemSourceTestID, postId, postMessage);
|
||||
const postItemBlockQuoteMatcher = by.id(this.testID.blockQuote).withAncestor(postItemMatcher);
|
||||
const postItemBreakMatcher = by.id(this.testID.break).withAncestor(postItemMatcher);
|
||||
const postItemCheckboxMatcher = by.id(this.testID.checkbox).withAncestor(postItemMatcher);
|
||||
const postItemCodeBlockMatcher = by.id(this.testID.codeBlock).withAncestor(postItemMatcher);
|
||||
const postItemCodeSpanMatcher = by.id(this.testID.codeSpan).withAncestor(postItemMatcher);
|
||||
const postItemEditedIndicator = by.id(this.testID.editedIndicator).withAncestor(postItemMatcher);
|
||||
const postItemEmojiMatcher = by.id(this.testID.emoji).withAncestor(postItemMatcher);
|
||||
const postItemHeadingMatcher = by.id(this.testID.heading).withAncestor(postItemMatcher);
|
||||
const postItemHtmlMatcher = by.id(this.testID.html).withAncestor(postItemMatcher);
|
||||
const postItemImageMatcher = by.id(this.testID.image).withAncestor(postItemMatcher);
|
||||
const postItemMessageMatcher = by.id(this.testID.message).withAncestor(postItemMatcher);
|
||||
const postItemLatexCodeBlockMatcher = by.id(this.testID.latexCodeBlock).withAncestor(postItemMatcher);
|
||||
const postItemInlineLatexMatcher = by.id(this.testID.latexInLine).withAncestor(postItemMatcher);
|
||||
const postItemLinkMatcher = by.id(this.testID.link).withAncestor(postItemMatcher);
|
||||
const postItemListItemMatcher = by.id(this.testID.listItem).withAncestor(postItemMatcher);
|
||||
const postItemListItemBulletMatcher = by.id(this.testID.listItemBullet).withAncestor(postItemMatcher);
|
||||
const postItemParagraphMatcher = by.id(this.testID.paragraph).withAncestor(postItemMatcher);
|
||||
const postItemPreHeaderTextMatch = by.id(this.testID.postPreHeaderText).withAncestor(postItemMatcher);
|
||||
const postItemShowLessButtonMatcher = by.id(this.testID.showLessButton).withAncestor(postItemMatcher);
|
||||
const postItemShowMoreButtonMatcher = by.id(this.testID.showMoreButton).withAncestor(postItemMatcher);
|
||||
const postItemTableMatcher = by.id(this.testID.table).withAncestor(postItemMatcher);
|
||||
const postItemTableCellMatcher = by.id(this.testID.tableCell).withAncestor(postItemMatcher);
|
||||
const postItemTableExpandButtonMatcher = by.id(this.testID.tableExpandButton).withAncestor(postItemMatcher);
|
||||
const postItemTableImageMatcher = by.id(this.testID.tableImage).withAncestor(postItemMatcher);
|
||||
const postItemTableRowMatcher = by.id(this.testID.tableRow).withAncestor(postItemMatcher);
|
||||
const postItemThematicBreakMatcher = by.id(this.testID.thematicBreak).withAncestor(postItemMatcher);
|
||||
const postItemUnreadDotBadgeMatcher = by.id(this.testID.postUnreadDotBadge).withAncestor(postItemMatcher);
|
||||
|
||||
return {
|
||||
postItem: element(postItemMatcher),
|
||||
postItemBlockQuote: element(postItemBlockQuoteMatcher),
|
||||
postItemBreak: element(postItemBreakMatcher),
|
||||
postItemCheckbox: element(postItemCheckboxMatcher),
|
||||
postItemCodeBlock: element(postItemCodeBlockMatcher),
|
||||
postItemCodeSpan: element(postItemCodeSpanMatcher),
|
||||
postItemEditedIndicator: element(postItemEditedIndicator),
|
||||
postItemEmoji: element(postItemEmojiMatcher),
|
||||
postItemHeading: element(postItemHeadingMatcher),
|
||||
postItemHtml: element(postItemHtmlMatcher),
|
||||
postItemImage: element(postItemImageMatcher),
|
||||
postItemMessage: element(postItemMessageMatcher),
|
||||
postItemLatexCodeBlock: element(postItemLatexCodeBlockMatcher),
|
||||
postItemInlineLatex: element(postItemInlineLatexMatcher),
|
||||
postItemLink: element(postItemLinkMatcher),
|
||||
postItemListItem: element(postItemListItemMatcher),
|
||||
postItemListItemBullet: element(postItemListItemBulletMatcher),
|
||||
postItemParagraph: element(postItemParagraphMatcher),
|
||||
postItemPreHeaderText: element(postItemPreHeaderTextMatch),
|
||||
postItemShowLessButton: element(postItemShowLessButtonMatcher),
|
||||
postItemShowMoreButton: element(postItemShowMoreButtonMatcher),
|
||||
postItemTable: element(postItemTableMatcher),
|
||||
postItemTableCell: element(postItemTableCellMatcher),
|
||||
postItemTableExpandButton: element(postItemTableExpandButtonMatcher),
|
||||
postItemTableImage: element(postItemTableImageMatcher),
|
||||
postItemTableRow: element(postItemTableRowMatcher),
|
||||
postItemThematicBreak: element(postItemThematicBreakMatcher),
|
||||
postItemUnreadDotBadge: element(postItemUnreadDotBadgeMatcher),
|
||||
...this.getPostFooter(postItemMatcher),
|
||||
@@ -83,6 +129,7 @@ class Post {
|
||||
const postItemHeaderDisplayNameMatcher = by.id(this.testID.postHeaderDisplayName).withAncestor(postItemMatcher);
|
||||
const postItemHeaderBotTagMatcher = by.id(this.testID.postHeaderBotTag).withAncestor(postItemMatcher);
|
||||
const postItemHeaderGuestTagMatcher = by.id(this.testID.postHeaderGuestTag).withAncestor(postItemMatcher);
|
||||
const postItemHeaderAutoResponderTagMatcher = by.id(this.testID.postHeaderAutoResponderTag).withAncestor(postItemMatcher);
|
||||
const postItemHeaderReplyMatcher = by.id(this.testID.postHeaderReply).withAncestor(postItemMatcher);
|
||||
const postItemHeaderReplyCountMatcher = by.id(this.testID.postHeaderReplyCount).withAncestor(postItemMatcher);
|
||||
|
||||
@@ -92,6 +139,7 @@ class Post {
|
||||
postItemHeaderDisplayName: element(postItemHeaderDisplayNameMatcher),
|
||||
postItemHeaderBotTag: element(postItemHeaderBotTagMatcher),
|
||||
postItemHeaderGuestTag: element(postItemHeaderGuestTagMatcher),
|
||||
postItemHeaderAutoResponderTag: element(postItemHeaderAutoResponderTagMatcher),
|
||||
postItemHeaderReply: element(postItemHeaderReplyMatcher),
|
||||
postItemHeaderReplyCount: element(postItemHeaderReplyCountMatcher),
|
||||
};
|
||||
@@ -115,7 +163,7 @@ class Post {
|
||||
};
|
||||
}
|
||||
|
||||
const profilePictureItemMatcher = ProfilePicture.getProfilePictureItemMatcher(this.testID.postProfilePicturePrefix, postProfileOptions.userId);
|
||||
const profilePictureItemMatcher = ProfilePicture.getProfilePictureItemMatcher(this.testID.postAvatarPrefix, postProfileOptions.userId);
|
||||
const profilePictureItemUserStatusMatcher = ProfilePicture.getProfilePictureItemUserStatusMatcher(profilePictureItemMatcher, postProfileOptions.userStatus);
|
||||
const postItemProfilePictureMatcher = profilePictureItemMatcher.withAncestor(postItemMatcher);
|
||||
const postItemProfilePictureUserStatusMatcher = profilePictureItemUserStatusMatcher.withAncestor(postItemMatcher);
|
||||
|
||||
@@ -61,6 +61,10 @@ class PostList {
|
||||
const {
|
||||
postItem,
|
||||
postItemBlockQuote,
|
||||
postItemBreak,
|
||||
postItemCheckbox,
|
||||
postItemCodeBlock,
|
||||
postItemCodeSpan,
|
||||
postItemEditedIndicator,
|
||||
postItemEmoji,
|
||||
postItemFooterFollowButton,
|
||||
@@ -71,17 +75,29 @@ class PostList {
|
||||
postItemHeaderDisplayName,
|
||||
postItemHeaderBotTag,
|
||||
postItemHeaderGuestTag,
|
||||
postItemHeaderAutoResponderTag,
|
||||
postItemHeaderReply,
|
||||
postItemHeaderReplyCount,
|
||||
postItemHeading,
|
||||
postItemHtml,
|
||||
postItemImage,
|
||||
postItemMessage,
|
||||
postItemLatexCodeBlock,
|
||||
postItemInlineLatex,
|
||||
postItemLink,
|
||||
postItemListItem,
|
||||
postItemListItemBullet,
|
||||
postItemParagraph,
|
||||
postItemPreHeaderText,
|
||||
postItemProfilePicture,
|
||||
postItemProfilePictureUserStatus,
|
||||
postItemShowLessButton,
|
||||
postItemShowMoreButton,
|
||||
postItemTable,
|
||||
postItemTableCell,
|
||||
postItemTableExpandButton,
|
||||
postItemTableImage,
|
||||
postItemTableRow,
|
||||
postItemThematicBreak,
|
||||
postItemUnreadDotBadge,
|
||||
} = Post.getPost(this.testID.postListPostItem, postId, postMessage, postProfileOptions);
|
||||
@@ -89,6 +105,10 @@ class PostList {
|
||||
return {
|
||||
postListPostItem: postItem,
|
||||
postListPostItemBlockQuote: postItemBlockQuote,
|
||||
postListPostItemBreak: postItemBreak,
|
||||
postListPostItemCheckbox: postItemCheckbox,
|
||||
postListPostItemCodeBlock: postItemCodeBlock,
|
||||
postListPostItemCodeSpan: postItemCodeSpan,
|
||||
postListPostItemEditedIndicator: postItemEditedIndicator,
|
||||
postListPostItemEmoji: postItemEmoji,
|
||||
postListPostItemFooterFollowButton: postItemFooterFollowButton,
|
||||
@@ -99,17 +119,29 @@ class PostList {
|
||||
postListPostItemHeaderDisplayName: postItemHeaderDisplayName,
|
||||
postListPostItemHeaderBotTag: postItemHeaderBotTag,
|
||||
postListPostItemHeaderGuestTag: postItemHeaderGuestTag,
|
||||
postListPostItemHeaderAutoResponderTag: postItemHeaderAutoResponderTag,
|
||||
postListPostItemHeaderReply: postItemHeaderReply,
|
||||
postListPostItemHeaderReplyCount: postItemHeaderReplyCount,
|
||||
postListPostItemHeading: postItemHeading,
|
||||
postListPostItemHtml: postItemHtml,
|
||||
postListPostItemImage: postItemImage,
|
||||
postListPostItemMessage: postItemMessage,
|
||||
postListPostItemLatexCodeBlock: postItemLatexCodeBlock,
|
||||
postListPostItemInlineLatex: postItemInlineLatex,
|
||||
postListPostItemLink: postItemLink,
|
||||
postListPostItemListItem: postItemListItem,
|
||||
postListPostItemListItemBullet: postItemListItemBullet,
|
||||
postListPostItemParagraph: postItemParagraph,
|
||||
postListPostItemPreHeaderText: postItemPreHeaderText,
|
||||
postListPostItemProfilePicture: postItemProfilePicture,
|
||||
postListPostItemProfilePictureUserStatus: postItemProfilePictureUserStatus,
|
||||
postListPostItemShowLessButton: postItemShowLessButton,
|
||||
postListPostItemShowMoreButton: postItemShowMoreButton,
|
||||
postListPostItemTable: postItemTable,
|
||||
postListPostItemTableCell: postItemTableCell,
|
||||
postListPostItemTableExpandButton: postItemTableExpandButton,
|
||||
postListPostItemTableImage: postItemTableImage,
|
||||
postListPostItemTableRow: postItemTableRow,
|
||||
postListPostItemThematicBreak: postItemThematicBreak,
|
||||
postListPostItemUnreadDotBadge: postItemUnreadDotBadge,
|
||||
};
|
||||
|
||||
@@ -9,6 +9,7 @@ class BrowseChannelsScreen {
|
||||
testID = {
|
||||
browseChannelsScreen: 'browse_channels.screen',
|
||||
closeButton: 'close.browse_channels.button',
|
||||
createButton: 'browse_channels.create.button',
|
||||
searchInput: 'browse_channels.search_bar.search.input',
|
||||
searchClearButton: 'browse_channels.search_bar.search.clear.button',
|
||||
searchCancelButton: 'browse_channels.search_bar.search.cancel.button',
|
||||
@@ -21,6 +22,7 @@ class BrowseChannelsScreen {
|
||||
|
||||
browseChannelsScreen = element(by.id(this.testID.browseChannelsScreen));
|
||||
closeButton = element(by.id(this.testID.closeButton));
|
||||
createButton = element(by.id(this.testID.createButton));
|
||||
searchInput = element(by.id(this.testID.searchInput));
|
||||
searchClearButton = element(by.id(this.testID.searchClearButton));
|
||||
searchCancelButton = element(by.id(this.testID.searchCancelButton));
|
||||
|
||||
@@ -24,17 +24,19 @@ class ChannelScreen {
|
||||
channelScreenPrefix: 'channel.',
|
||||
channelScreen: 'channel.screen',
|
||||
introDisplayName: 'channel_post_list.intro.display_name',
|
||||
introOptionAddPeopleItem: 'channel_post_list.intro.option_item.add_people',
|
||||
introOptionSetHeaderItem: 'channel_post_list.intro.option_item.set_header',
|
||||
introOptionChannelDetailsItem: 'channel_post_list.intro.option_item.channel_details',
|
||||
introAddPeopleOption: 'channel_post_list.intro_options.add_people.option',
|
||||
introSetHeaderOption: 'channel_post_list.intro_options.set_header.option',
|
||||
introFavoriteOption: 'channel_post_list.intro_options.set_header.option',
|
||||
introChannelDetailsOption: 'channel_post_list.intro_options.channel_details.option',
|
||||
flatPostList: 'channel.post_list.flat_list',
|
||||
};
|
||||
|
||||
channelScreen = element(by.id(this.testID.channelScreen));
|
||||
introDisplayName = element(by.id(this.testID.introDisplayName));
|
||||
introOptionAddPeopleItem = element(by.id(this.testID.introOptionAddPeopleItem));
|
||||
introOptionSetHeaderItem = element(by.id(this.testID.introOptionSetHeaderItem));
|
||||
introOptionChannelDetailsItem = element(by.id(this.testID.introOptionChannelDetailsItem));
|
||||
introAddPeopleOption = element(by.id(this.testID.introAddPeopleOption));
|
||||
introSetHeaderOption = element(by.id(this.testID.introSetHeaderOption));
|
||||
introFavoriteOption = element(by.id(this.testID.introFavoriteOption));
|
||||
introChannelDetailsOption = element(by.id(this.testID.introChannelDetailsOption));
|
||||
flatPostList = element(by.id(this.testID.flatPostList));
|
||||
|
||||
// convenience props
|
||||
@@ -71,7 +73,7 @@ class ChannelScreen {
|
||||
return this.postList.getNewMessagesDivider();
|
||||
};
|
||||
|
||||
getPostListPostItem = (postId: string, text: string, postProfileOptions: any = {}) => {
|
||||
getPostListPostItem = (postId: string, text = '', postProfileOptions: any = {}) => {
|
||||
return this.postList.getPost(postId, text, postProfileOptions);
|
||||
};
|
||||
|
||||
|
||||
77
detox/e2e/support/ui/screen/channel_info.ts
Normal file
77
detox/e2e/support/ui/screen/channel_info.ts
Normal file
@@ -0,0 +1,77 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
import {ChannelScreen} from '@support/ui/screen';
|
||||
import {timeouts} from '@support/utils';
|
||||
import {expect} from 'detox';
|
||||
|
||||
class ChannelInfoScreen {
|
||||
testID = {
|
||||
channelInfoScreen: 'channel_info.screen',
|
||||
closeButton: 'close.channel_info.button',
|
||||
scrollView: 'channel_info.scrollview',
|
||||
favoriteAction: 'channel_info.channel_actions.favorite.action',
|
||||
muteAction: 'channel_info.channel_actions.mute.action',
|
||||
setHeaderAction: 'channel_info.channel_actions.set_header.action',
|
||||
addPeopleAction: 'channel_info.channel_actions.add_people.action',
|
||||
copyChannelLinkAction: 'channel_info.channel_actions.copy_channel_link.action',
|
||||
ignoreMentionsOptionToggledOff: 'channel_info.options.ignore_mentions.option.toggled.false',
|
||||
ignoreMentionsOptionToggledOn: 'channel_info.options.ignore_mentions.option.toggled.true',
|
||||
notificationPreferenceOption: 'channel_info.options.notification_preference.option',
|
||||
pinnedMessagesOption: 'channel_info.options.pinned_messages.option',
|
||||
membersOption: 'channel_info.options.members.option',
|
||||
editChannelOption: 'channel_info.options.edit_channel.option',
|
||||
convertPrivateOption: 'channel_info.options.convert_private.option',
|
||||
leaveChannelOption: 'channel_info.options.leave_channel.option',
|
||||
archiveChannelOption: 'channel_info.options.archive_channel.option',
|
||||
};
|
||||
|
||||
channelInfoScreen = element(by.id(this.testID.channelInfoScreen));
|
||||
closeButton = element(by.id(this.testID.closeButton));
|
||||
scrollView = element(by.id(this.testID.scrollView));
|
||||
favoriteAction = element(by.id(this.testID.favoriteAction));
|
||||
muteAction = element(by.id(this.testID.muteAction));
|
||||
setHeaderAction = element(by.id(this.testID.setHeaderAction));
|
||||
addPeopleAction = element(by.id(this.testID.addPeopleAction));
|
||||
copyChannelLinkAction = element(by.id(this.testID.copyChannelLinkAction));
|
||||
ignoreMentionsOptionToggledOff = element(by.id(this.testID.ignoreMentionsOptionToggledOff));
|
||||
ignoreMentionsOptionToggledOn = element(by.id(this.testID.ignoreMentionsOptionToggledOn));
|
||||
notificationPreferenceOption = element(by.id(this.testID.notificationPreferenceOption));
|
||||
pinnedMessagesOption = element(by.id(this.testID.pinnedMessagesOption));
|
||||
membersOption = element(by.id(this.testID.membersOption));
|
||||
editChannelOption = element(by.id(this.testID.editChannelOption));
|
||||
convertPrivateOption = element(by.id(this.testID.convertPrivateOption));
|
||||
leaveChannelOption = element(by.id(this.testID.leaveChannelOption));
|
||||
archiveChannelOption = element(by.id(this.testID.archiveChannelOption));
|
||||
|
||||
toBeVisible = async () => {
|
||||
await waitFor(this.channelInfoScreen).toExist().withTimeout(timeouts.TEN_SEC);
|
||||
|
||||
return this.channelInfoScreen;
|
||||
};
|
||||
|
||||
open = async () => {
|
||||
// # Open channel info screen
|
||||
await ChannelScreen.headerTitle.tap();
|
||||
|
||||
return this.toBeVisible();
|
||||
};
|
||||
|
||||
close = async () => {
|
||||
await this.closeButton.tap();
|
||||
await expect(this.channelInfoScreen).not.toBeVisible();
|
||||
};
|
||||
|
||||
toggleIgnoreMentionsOptionOn = async () => {
|
||||
await this.ignoreMentionsOptionToggledOff.tap();
|
||||
await expect(this.ignoreMentionsOptionToggledOn).toBeVisible();
|
||||
};
|
||||
|
||||
toggleIgnoreMentionsOff = async () => {
|
||||
await this.ignoreMentionsOptionToggledOn.tap();
|
||||
await expect(this.ignoreMentionsOptionToggledOff).toBeVisible();
|
||||
};
|
||||
}
|
||||
|
||||
const channelInfoScreen = new ChannelInfoScreen();
|
||||
export default channelInfoScreen;
|
||||
@@ -1,6 +1,7 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
import {ProfilePicture} from '@support/ui/component';
|
||||
import {ChannelListScreen} from '@support/ui/screen';
|
||||
import {timeouts} from '@support/utils';
|
||||
import {expect} from 'detox';
|
||||
@@ -45,7 +46,7 @@ class CreateDirectMessageScreen {
|
||||
};
|
||||
|
||||
getUserItemProfilePicture = (userId: string) => {
|
||||
return element(by.id(`create_direct_message.user_list.user_item.${userId}.profile_picture`));
|
||||
return element(ProfilePicture.getProfilePictureItemMatcher('create_direct_message.user_list.user_item.', userId));
|
||||
};
|
||||
|
||||
getUserItemDisplayName = (userId: string) => {
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
import {
|
||||
ChannelInfoScreen,
|
||||
ChannelScreen,
|
||||
ChannelListScreen,
|
||||
} from '@support/ui/screen';
|
||||
@@ -12,6 +13,7 @@ class CreateOrEditChannelScreen {
|
||||
testID = {
|
||||
createOrEditChannelScreen: 'create_or_edit_channel.screen',
|
||||
closeButton: 'close.create_or_edit_channel.button',
|
||||
backButton: 'screen.back.button',
|
||||
createButton: 'create_or_edit_channel.create.button',
|
||||
saveButton: 'create_or_edit_channel.save.button',
|
||||
scrollView: 'create_or_edit_channel.scrollview',
|
||||
@@ -27,6 +29,7 @@ class CreateOrEditChannelScreen {
|
||||
|
||||
createOrEditChannelScreen = element(by.id(this.testID.createOrEditChannelScreen));
|
||||
closeButton = element(by.id(this.testID.closeButton));
|
||||
backButton = element(by.id(this.testID.backButton));
|
||||
createButton = element(by.id(this.testID.createButton));
|
||||
saveButton = element(by.id(this.testID.saveButton));
|
||||
scrollView = element(by.id(this.testID.scrollView));
|
||||
@@ -55,11 +58,23 @@ class CreateOrEditChannelScreen {
|
||||
|
||||
openEditChannel = async () => {
|
||||
// # Open edit channel screen
|
||||
await ChannelScreen.introOptionSetHeaderItem.tap();
|
||||
await ChannelInfoScreen.editChannelOption.tap();
|
||||
|
||||
return this.toBeVisible();
|
||||
};
|
||||
|
||||
openEditChannelHeader = async () => {
|
||||
// # Open edit channel header screen
|
||||
await ChannelScreen.introSetHeaderOption.tap();
|
||||
|
||||
return this.toBeVisible();
|
||||
};
|
||||
|
||||
back = async () => {
|
||||
await this.backButton.tap();
|
||||
await expect(this.createOrEditChannelScreen).not.toBeVisible();
|
||||
};
|
||||
|
||||
close = async () => {
|
||||
await this.closeButton.tap();
|
||||
await expect(this.createOrEditChannelScreen).not.toBeVisible();
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
import {PostOptionsScreen} from '@support/ui/screen';
|
||||
import {timeouts} from '@support/utils';
|
||||
import {expect} from 'detox';
|
||||
|
||||
class EditPostScreen {
|
||||
testID = {
|
||||
@@ -26,6 +28,17 @@ class EditPostScreen {
|
||||
|
||||
return this.editPostScreen;
|
||||
};
|
||||
|
||||
open = async () => {
|
||||
await PostOptionsScreen.editPostOption.tap();
|
||||
|
||||
return this.toBeVisible();
|
||||
};
|
||||
|
||||
close = async () => {
|
||||
await this.closeButton.tap();
|
||||
await expect(this.editPostScreen).not.toBeVisible();
|
||||
};
|
||||
}
|
||||
|
||||
const editPostScreen = new EditPostScreen();
|
||||
|
||||
@@ -5,6 +5,7 @@ import AccountScreen from './account';
|
||||
import BrowseChannelsScreen from './browse_channels';
|
||||
import ChannelScreen from './channel';
|
||||
import ChannelDropdownMenuScreen from './channel_dropdown_menu';
|
||||
import ChannelInfoScreen from './channel_info';
|
||||
import ChannelListScreen from './channel_list';
|
||||
import CreateDirectMessageScreen from './create_direct_message';
|
||||
import CreateOrEditChannelScreen from './create_or_edit_channel';
|
||||
@@ -20,14 +21,17 @@ import PostOptionsScreen from './post_options';
|
||||
import ReactionsScreen from './reactions';
|
||||
import ServerScreen from './server';
|
||||
import ServerListScreen from './server_list';
|
||||
import TableScreen from './table';
|
||||
import ThreadScreen from './thread';
|
||||
import ThreadOptionsScreen from './thread_options';
|
||||
import UserProfileScreen from './user_profile';
|
||||
|
||||
export {
|
||||
AccountScreen,
|
||||
BrowseChannelsScreen,
|
||||
ChannelScreen,
|
||||
ChannelDropdownMenuScreen,
|
||||
ChannelInfoScreen,
|
||||
ChannelListScreen,
|
||||
CreateDirectMessageScreen,
|
||||
CreateOrEditChannelScreen,
|
||||
@@ -43,6 +47,8 @@ export {
|
||||
ReactionsScreen,
|
||||
ServerScreen,
|
||||
ServerListScreen,
|
||||
TableScreen,
|
||||
ThreadScreen,
|
||||
ThreadOptionsScreen,
|
||||
UserProfileScreen,
|
||||
};
|
||||
|
||||
@@ -18,7 +18,7 @@ class PermalinkScreen {
|
||||
|
||||
postList = new PostList(this.testID.permalinkScreenPrefix);
|
||||
|
||||
getPostListPostItem = (postId: string, text: string, postProfileOptions = {}) => {
|
||||
getPostListPostItem = (postId: string, text = '', postProfileOptions = {}) => {
|
||||
return this.postList.getPost(postId, text, postProfileOptions);
|
||||
};
|
||||
|
||||
|
||||
@@ -1,14 +1,15 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
import {ProfilePicture} from '@support/ui/component';
|
||||
import {expect} from 'detox';
|
||||
|
||||
class ReactionsScreen {
|
||||
testID = {
|
||||
reactorItemPrefix: 'reactors_list.user_item.',
|
||||
reactorItemPrefix: 'reactions.reactor_item.',
|
||||
reactionsScreen: 'reactions.screen',
|
||||
reactionsBackdrop: 'reactions.backdrop',
|
||||
flatReactorsList: 'reactors_list.flat_list',
|
||||
flatReactorsList: 'reactions.reactors_list.flat_list',
|
||||
};
|
||||
|
||||
reactionsScreen = element(by.id(this.testID.reactionsScreen));
|
||||
@@ -30,16 +31,16 @@ class ReactionsScreen {
|
||||
const reactorItemEmojiAliasesMatcher = by.id(`emoji_aliases.${emojiName}`);
|
||||
const reactorItemUserTestId = `${this.testID.reactorItemPrefix}${userId}`;
|
||||
const reactorItemUserMatcher = by.id(reactorItemUserTestId);
|
||||
const reactorItemUserProfilePictureMatcher = by.id(`${reactorItemUserTestId}.profile_picture`);
|
||||
const reactorItemUserProfilePictureMatcher = ProfilePicture.getProfilePictureItemMatcher(this.testID.reactorItemPrefix, userId);
|
||||
const reactorItemUserDisplayNameMatcher = by.id(`${reactorItemUserTestId}.display_name`);
|
||||
const reactorItemUserUsernameMatcher = by.id(`${reactorItemUserTestId}.username`);
|
||||
const reactorItemUsernameMatcher = by.id(`${reactorItemUserTestId}.username`);
|
||||
|
||||
return {
|
||||
reactorItemEmojiAliases: element(reactorItemEmojiAliasesMatcher),
|
||||
reactorItemUser: element(reactorItemUserMatcher),
|
||||
reactorItemUserProfilePicture: element(reactorItemUserProfilePictureMatcher),
|
||||
reactorItemUserDisplayName: element(reactorItemUserDisplayNameMatcher),
|
||||
reactorItemUserUsername: element(reactorItemUserUsernameMatcher),
|
||||
reactorItemUsername: element(reactorItemUsernameMatcher),
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
30
detox/e2e/support/ui/screen/table.ts
Normal file
30
detox/e2e/support/ui/screen/table.ts
Normal file
@@ -0,0 +1,30 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
import {expect} from 'detox';
|
||||
|
||||
class TableScreen {
|
||||
testID = {
|
||||
tableScreen: 'table.screen',
|
||||
tableScrollView: 'table.scroll_view',
|
||||
backButton: 'screen.back.button',
|
||||
};
|
||||
|
||||
tableScreen = element(by.id(this.testID.tableScreen));
|
||||
tableScrollView = element(by.id(this.testID.tableScrollView));
|
||||
backButton = element(by.id(this.testID.backButton));
|
||||
|
||||
toBeVisible = async () => {
|
||||
await expect(this.tableScreen).toBeVisible();
|
||||
|
||||
return this.tableScreen;
|
||||
};
|
||||
|
||||
back = async () => {
|
||||
await this.backButton.tap();
|
||||
await expect(this.tableScreen).not.toBeVisible();
|
||||
};
|
||||
}
|
||||
|
||||
const tableScreen = new TableScreen();
|
||||
export default tableScreen;
|
||||
@@ -74,7 +74,7 @@ class ThreadScreen {
|
||||
return this.postList.getThreadOverviewPostOptionsButton();
|
||||
};
|
||||
|
||||
getPostListPostItem = (postId: string, text: string, postProfileOptions: any = {}) => {
|
||||
getPostListPostItem = (postId: string, text = '', postProfileOptions: any = {}) => {
|
||||
return this.postList.getPost(postId, text, postProfileOptions);
|
||||
};
|
||||
|
||||
|
||||
58
detox/e2e/support/ui/screen/user_profile.ts
Normal file
58
detox/e2e/support/ui/screen/user_profile.ts
Normal file
@@ -0,0 +1,58 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
import {ProfilePicture} from '@support/ui/component';
|
||||
import {timeouts} from '@support/utils';
|
||||
import {expect} from 'detox';
|
||||
|
||||
class UserProfileScreen {
|
||||
testID = {
|
||||
userProfileScreen: 'user_profile.screen',
|
||||
userProfileAvatarPrefix: 'user_profile_avatar.',
|
||||
userProfileBackdrop: 'user_profile.backdrop',
|
||||
systemAdminTag: 'user_profile.system_admin.tag',
|
||||
teamAdminTag: 'user_profile.team_admin.tag',
|
||||
channelAdminTag: 'user_profile.channel_admin.tag',
|
||||
userDisplayName: 'user_profile.display_name',
|
||||
username: 'user_profile.username',
|
||||
sendMessageProfileOption: 'user_profile_options.send_message.option',
|
||||
mentionProfileOption: 'user_profile_options.mention.option',
|
||||
userNicknameTitle: 'user_profile.nickname.title',
|
||||
userNicknameDescription: 'user_profile.nickname.description',
|
||||
userPositionTitle: 'user_profile.position.title',
|
||||
userPositionDescription: 'user_profile.position.description',
|
||||
userLocalTimeTitle: 'user_profile.local_time.title',
|
||||
userLocalTimeDescription: 'user_profile.local_time.description',
|
||||
};
|
||||
|
||||
userProfileScreen = element(by.id(this.testID.userProfileScreen));
|
||||
userProfileBackdrop = element(by.id(this.testID.userProfileBackdrop));
|
||||
userDisplayName = element(by.id(this.testID.userDisplayName));
|
||||
username = element(by.id(this.testID.username));
|
||||
sendMessageProfileOption = element(by.id(this.testID.sendMessageProfileOption));
|
||||
mentionProfileOption = element(by.id(this.testID.mentionProfileOption));
|
||||
userNicknameTitle = element(by.id(this.testID.userNicknameTitle));
|
||||
userNicknameDescription = element(by.id(this.testID.userNicknameDescription));
|
||||
userPositionTitle = element(by.id(this.testID.userPositionTitle));
|
||||
userPositionDescription = element(by.id(this.testID.userPositionDescription));
|
||||
userLocalTimeTitle = element(by.id(this.testID.userLocalTimeTitle));
|
||||
userLocalTimeDescription = element(by.id(this.testID.userLocalTimeDescription));
|
||||
|
||||
getUserProfilePicture = (userId: string) => {
|
||||
return element(ProfilePicture.getProfilePictureItemMatcher(this.testID.userProfileAvatarPrefix, userId));
|
||||
};
|
||||
|
||||
toBeVisible = async () => {
|
||||
await waitFor(this.userProfileScreen).toExist().withTimeout(timeouts.TEN_SEC);
|
||||
|
||||
return this.userProfileScreen;
|
||||
};
|
||||
|
||||
close = async () => {
|
||||
await this.userProfileBackdrop.tap({x: 5, y: 10});
|
||||
await expect(this.userProfileScreen).not.toBeVisible();
|
||||
};
|
||||
}
|
||||
|
||||
const userProfileScreen = new UserProfileScreen();
|
||||
export default userProfileScreen;
|
||||
324
detox/e2e/test/autocomplete/at_mention.e2e.ts
Normal file
324
detox/e2e/test/autocomplete/at_mention.e2e.ts
Normal file
@@ -0,0 +1,324 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
// *******************************************************************
|
||||
// - [#] indicates a test step (e.g. # Go to a screen)
|
||||
// - [*] indicates an assertion (e.g. * Check the title)
|
||||
// - Use element testID when selecting an element. Create one if none.
|
||||
// *******************************************************************
|
||||
|
||||
import {
|
||||
Channel,
|
||||
Setup,
|
||||
Team,
|
||||
User,
|
||||
} from '@support/server_api';
|
||||
import {
|
||||
serverOneUrl,
|
||||
siteOneUrl,
|
||||
} from '@support/test_config';
|
||||
import {Autocomplete} from '@support/ui/component';
|
||||
import {
|
||||
ChannelListScreen,
|
||||
ChannelScreen,
|
||||
HomeScreen,
|
||||
LoginScreen,
|
||||
ServerScreen,
|
||||
} from '@support/ui/screen';
|
||||
import {getRandomId, timeouts, wait} from '@support/utils';
|
||||
import {expect} from 'detox';
|
||||
|
||||
describe('Autocomplete - At-Mention', () => {
|
||||
const serverOneDisplayName = 'Server 1';
|
||||
const channelsCategory = 'channels';
|
||||
let testChannel: any;
|
||||
let testTeam: any;
|
||||
let testUser: any;
|
||||
let testOtherUser: any;
|
||||
let userAtMentionAutocomplete: any;
|
||||
let otherUserAtMentionAutocomplete: any;
|
||||
|
||||
beforeAll(async () => {
|
||||
const {channel, team, user} = await Setup.apiInit(siteOneUrl);
|
||||
testChannel = channel;
|
||||
testTeam = team;
|
||||
testUser = user;
|
||||
({atMentionItem: userAtMentionAutocomplete} = Autocomplete.getAtMentionItem(testUser.id));
|
||||
|
||||
({user: testOtherUser} = await User.apiCreateUser(siteOneUrl));
|
||||
await Team.apiAddUserToTeam(siteOneUrl, testOtherUser.id, testTeam.id);
|
||||
await Channel.apiAddUserToChannel(siteOneUrl, testOtherUser.id, testChannel.id);
|
||||
({atMentionItem: otherUserAtMentionAutocomplete} = Autocomplete.getAtMentionItem(testOtherUser.id));
|
||||
|
||||
// # Log in to server
|
||||
await ServerScreen.connectToServer(serverOneUrl, serverOneDisplayName);
|
||||
await LoginScreen.login(testUser);
|
||||
|
||||
// * Verify on channel list screen
|
||||
await ChannelListScreen.toBeVisible();
|
||||
|
||||
// # Open a channel screen
|
||||
await ChannelScreen.open(channelsCategory, testChannel.name);
|
||||
});
|
||||
|
||||
beforeEach(async () => {
|
||||
// # Clear post input
|
||||
await ChannelScreen.postInput.clearText();
|
||||
|
||||
// * Verify autocomplete is not displayed
|
||||
await Autocomplete.toBeVisible(false);
|
||||
});
|
||||
|
||||
afterAll(async () => {
|
||||
// # Log out
|
||||
await ChannelScreen.back();
|
||||
await HomeScreen.logout();
|
||||
});
|
||||
|
||||
it('MM-T4878_1 - should suggest user based on username', async () => {
|
||||
// # Type in "@" to activate at-mention autocomplete
|
||||
await ChannelScreen.postInput.typeText('@');
|
||||
await Autocomplete.toBeVisible();
|
||||
|
||||
// * Verify at-mention list is displayed
|
||||
await expect(Autocomplete.sectionAtMentionList).toBeVisible();
|
||||
|
||||
// # Type in username
|
||||
await ChannelScreen.postInput.typeText(testUser.username);
|
||||
|
||||
// * Verify at-mention autocomplete contains associated user suggestion
|
||||
await expect(userAtMentionAutocomplete).toBeVisible();
|
||||
});
|
||||
|
||||
it('MM-T4878_2 - should suggest user based on nickname', async () => {
|
||||
// # Type in "@" to activate at-mention autocomplete
|
||||
await ChannelScreen.postInput.typeText('@');
|
||||
await Autocomplete.toBeVisible();
|
||||
|
||||
// * Verify at-mention list is displayed
|
||||
await expect(Autocomplete.sectionAtMentionList).toBeVisible();
|
||||
|
||||
// # Type in nickname
|
||||
await ChannelScreen.postInput.typeText(testUser.nickname);
|
||||
|
||||
// * Verify at-mention autocomplete contains associated user suggestion
|
||||
await expect(userAtMentionAutocomplete).toBeVisible();
|
||||
});
|
||||
|
||||
it('MM-T4878_3 - should suggest user based on first name', async () => {
|
||||
// # Type in "@" to activate at-mention autocomplete
|
||||
await ChannelScreen.postInput.typeText('@');
|
||||
await Autocomplete.toBeVisible();
|
||||
|
||||
// * Verify at-mention list is displayed
|
||||
await expect(Autocomplete.sectionAtMentionList).toBeVisible();
|
||||
|
||||
// # Type in first name
|
||||
await ChannelScreen.postInput.typeText(testUser.first_name);
|
||||
|
||||
// * Verify at-mention autocomplete contains associated user suggestion
|
||||
await expect(userAtMentionAutocomplete).toBeVisible();
|
||||
});
|
||||
|
||||
it('MM-T4878_4 - should suggest user based on last name', async () => {
|
||||
// # Type in "@" to activate at-mention autocomplete
|
||||
await ChannelScreen.postInput.typeText('@');
|
||||
await Autocomplete.toBeVisible();
|
||||
|
||||
// * Verify at-mention list is displayed
|
||||
await expect(Autocomplete.sectionAtMentionList).toBeVisible();
|
||||
|
||||
// # Type in last name
|
||||
await ChannelScreen.postInput.typeText(testUser.last_name);
|
||||
|
||||
// * Verify at-mention autocomplete contains associated user suggestion
|
||||
await expect(userAtMentionAutocomplete).toBeVisible();
|
||||
});
|
||||
|
||||
it('MM-T4878_5 - should suggest user based on lowercase first name', async () => {
|
||||
// # Type in "@" to activate at-mention autocomplete
|
||||
await ChannelScreen.postInput.typeText('@');
|
||||
await Autocomplete.toBeVisible();
|
||||
|
||||
// * Verify at-mention list is displayed
|
||||
await expect(Autocomplete.sectionAtMentionList).toBeVisible();
|
||||
|
||||
// # Type in lowercase first name
|
||||
await ChannelScreen.postInput.typeText(testUser.first_name.toLowerCase());
|
||||
|
||||
// * Verify at-mention autocomplete contains associated user suggestion
|
||||
await expect(userAtMentionAutocomplete).toBeVisible();
|
||||
});
|
||||
|
||||
it('MM-T4878_6 - should suggest user based on lowercase last name', async () => {
|
||||
// # Type in "@" to activate at-mention autocomplete
|
||||
await ChannelScreen.postInput.typeText('@');
|
||||
await Autocomplete.toBeVisible();
|
||||
|
||||
// * Verify at-mention list is displayed
|
||||
await expect(Autocomplete.sectionAtMentionList).toBeVisible();
|
||||
|
||||
// # Type in lowercase last name
|
||||
await ChannelScreen.postInput.typeText(testUser.last_name.toLowerCase());
|
||||
|
||||
// * Verify at-mention autocomplete contains associated user suggestion
|
||||
await expect(userAtMentionAutocomplete).toBeVisible();
|
||||
});
|
||||
|
||||
it('MM-T4878_7 - should suggest user based on full name with space', async () => {
|
||||
// # Type in "@" to activate at-mention autocomplete
|
||||
await ChannelScreen.postInput.typeText('@');
|
||||
await Autocomplete.toBeVisible();
|
||||
|
||||
// * Verify at-mention list is displayed
|
||||
await expect(Autocomplete.sectionAtMentionList).toBeVisible();
|
||||
|
||||
// # Type in full name with space
|
||||
await ChannelScreen.postInput.typeText(`${testUser.first_name} ${testUser.last_name}`);
|
||||
|
||||
// * Verify at-mention autocomplete contains associated user suggestion
|
||||
await expect(userAtMentionAutocomplete).toBeVisible();
|
||||
});
|
||||
|
||||
it('MM-T4878_8 - should suggest user based on partial full name with space', async () => {
|
||||
// # Type in "@" to activate at-mention autocomplete
|
||||
await ChannelScreen.postInput.typeText('@');
|
||||
await Autocomplete.toBeVisible();
|
||||
|
||||
// * Verify at-mention list is displayed
|
||||
await expect(Autocomplete.sectionAtMentionList).toBeVisible();
|
||||
|
||||
// # Type in partial full name with space
|
||||
await ChannelScreen.postInput.typeText(`${testUser.first_name} ${testUser.last_name.substring(0, testUser.last_name.length - 6)}`);
|
||||
|
||||
// * Verify at-mention autocomplete contains associated user suggestion
|
||||
await expect(userAtMentionAutocomplete).toBeVisible();
|
||||
});
|
||||
|
||||
it('MM-T4878_9 - should stop suggesting user after full name with trailing space -- KNOWN ISSUE: MM-45279', async () => {
|
||||
// # Type in "@" to activate at-mention autocomplete
|
||||
await ChannelScreen.postInput.typeText('@');
|
||||
await Autocomplete.toBeVisible();
|
||||
|
||||
// * Verify at-mention list is displayed
|
||||
await expect(Autocomplete.sectionAtMentionList).toBeVisible();
|
||||
|
||||
// # Type in full name
|
||||
await ChannelScreen.postInput.typeText(`${testUser.first_name} ${testUser.last_name}`);
|
||||
|
||||
// * Verify at-mention autocomplete contains associated user suggestion
|
||||
await expect(userAtMentionAutocomplete).toBeVisible();
|
||||
|
||||
// # Type in trailing space
|
||||
await ChannelScreen.postInput.typeText(' ');
|
||||
await wait(timeouts.ONE_SEC);
|
||||
|
||||
// * Verify at-mention autocomplete does not contain associated user suggestion
|
||||
await expect(userAtMentionAutocomplete).not.toBeVisible();
|
||||
});
|
||||
|
||||
it('MM-T4878_10 - should stop suggesting user when keyword is not associated with any user', async () => {
|
||||
// # Type in "@" to activate at-mention autocomplete
|
||||
await ChannelScreen.postInput.typeText('@');
|
||||
await Autocomplete.toBeVisible();
|
||||
|
||||
// * Verify at-mention list is displayed
|
||||
await expect(Autocomplete.sectionAtMentionList).toBeVisible();
|
||||
|
||||
// # Type in keyword not associated with any user
|
||||
await ChannelScreen.postInput.typeText(getRandomId());
|
||||
|
||||
// * Verify at-mention autocomplete does not contain associated user suggestion
|
||||
await expect(userAtMentionAutocomplete).not.toBeVisible();
|
||||
});
|
||||
|
||||
it('MM-T4878_11 - should be able to select at-mention multiple times', async () => {
|
||||
// # Type in "@" to activate at-mention autocomplete
|
||||
await expect(Autocomplete.sectionAtMentionList).not.toBeVisible();
|
||||
await ChannelScreen.postInput.typeText('@');
|
||||
|
||||
// * Verify at-mention list is displayed
|
||||
await expect(Autocomplete.sectionAtMentionList).toBeVisible();
|
||||
|
||||
// # Type in username and tap on user at-mention autocomplete
|
||||
await ChannelScreen.postInput.typeText(testUser.username);
|
||||
await userAtMentionAutocomplete.tap();
|
||||
|
||||
// * Verify at-mention list disappears
|
||||
await expect(Autocomplete.sectionAtMentionList).not.toBeVisible();
|
||||
|
||||
// # Type in "@" again to re-activate at-mention list
|
||||
await ChannelScreen.postInput.typeText('@');
|
||||
|
||||
// * Verify at-mention list is displayed
|
||||
await expect(Autocomplete.sectionAtMentionList).toBeVisible();
|
||||
});
|
||||
|
||||
it('MM-T4878_12 - should not be able to autocomplete deactivated user', async () => {
|
||||
// # Deactivate another channel member user and type in "@" to activate at-mention autocomplete
|
||||
await User.apiDeactivateUser(siteOneUrl, testOtherUser.id);
|
||||
await ChannelScreen.postInput.typeText('@');
|
||||
await Autocomplete.toBeVisible();
|
||||
|
||||
// * Verify at-mention list is displayed
|
||||
await expect(Autocomplete.sectionAtMentionList).toBeVisible();
|
||||
|
||||
// # Type in username of deactivated user
|
||||
await ChannelScreen.postInput.typeText(testOtherUser.username);
|
||||
|
||||
// * Verify at-mention autocomplete does not contain associated user suggestion
|
||||
await expect(otherUserAtMentionAutocomplete).not.toBeVisible();
|
||||
|
||||
// # Reactivate user, clear post input, and type in "@" to activate at-mention list
|
||||
await User.apiUpdateUserActiveStatus(siteOneUrl, testOtherUser.id, true);
|
||||
await ChannelScreen.postInput.clearText();
|
||||
await Autocomplete.toBeVisible(false);
|
||||
await ChannelScreen.postInput.typeText('@');
|
||||
await Autocomplete.toBeVisible();
|
||||
|
||||
// * Verify at-mention list is displayed
|
||||
await expect(Autocomplete.sectionAtMentionList).toBeVisible();
|
||||
|
||||
// # Type in username of reactivated user
|
||||
await ChannelScreen.postInput.typeText(testOtherUser.username);
|
||||
|
||||
// * Verify at-mention autocomplete contains associated user suggestion
|
||||
await expect(otherUserAtMentionAutocomplete).toBeVisible();
|
||||
});
|
||||
|
||||
it('MM-T4878_13 - should be able to autocomplete out of channel user', async () => {
|
||||
// # Type in "@" to activate at-mention autocomplete
|
||||
const {user: outOfChannelUser} = await User.apiCreateUser(siteOneUrl);
|
||||
await Team.apiAddUserToTeam(siteOneUrl, outOfChannelUser.id, testTeam.id);
|
||||
await ChannelScreen.postInput.typeText('@');
|
||||
await Autocomplete.toBeVisible();
|
||||
|
||||
// * Verify at-mention list is displayed
|
||||
await expect(Autocomplete.sectionAtMentionList).toBeVisible();
|
||||
|
||||
// # Type in username of out of channel user
|
||||
await ChannelScreen.postInput.typeText(outOfChannelUser.username);
|
||||
|
||||
// * Verify at-mention autocomplete contains associated user suggestion
|
||||
const {atMentionItem: outOfChannelUserAtMentionAutocomplete} = Autocomplete.getAtMentionItem(outOfChannelUser.id);
|
||||
await expect(outOfChannelUserAtMentionAutocomplete).toBeVisible();
|
||||
});
|
||||
|
||||
it('MM-T4878_14 - should include current user in autocomplete', async () => {
|
||||
// # Type in "@" to activate at-mention autocomplete
|
||||
await ChannelScreen.postInput.typeText('@');
|
||||
await Autocomplete.toBeVisible();
|
||||
|
||||
// * Verify at-mention list is displayed
|
||||
await expect(Autocomplete.sectionAtMentionList).toBeVisible();
|
||||
|
||||
// # Type in username of current user
|
||||
await ChannelScreen.postInput.typeText(testUser.username);
|
||||
|
||||
// * Verify at-mention autocomplete contains current user
|
||||
const {atMentionItemUserDisplayName, atMentionItemCurrentUserIndicator, atMentionItemUsername} = Autocomplete.getAtMentionItem(testUser.id);
|
||||
await expect(atMentionItemUserDisplayName).toHaveText(`${testUser.first_name} ${testUser.last_name}`);
|
||||
await expect(atMentionItemCurrentUserIndicator).toHaveText(' (you)');
|
||||
await expect(atMentionItemUsername).toHaveText(` @${testUser.username}`);
|
||||
});
|
||||
});
|
||||
266
detox/e2e/test/autocomplete/channel_mention.e2e.ts
Normal file
266
detox/e2e/test/autocomplete/channel_mention.e2e.ts
Normal file
@@ -0,0 +1,266 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
// *******************************************************************
|
||||
// - [#] indicates a test step (e.g. # Go to a screen)
|
||||
// - [*] indicates an assertion (e.g. * Check the title)
|
||||
// - Use element testID when selecting an element. Create one if none.
|
||||
// *******************************************************************
|
||||
|
||||
import {
|
||||
Channel,
|
||||
Setup,
|
||||
System,
|
||||
Team,
|
||||
} from '@support/server_api';
|
||||
import {
|
||||
serverOneUrl,
|
||||
siteOneUrl,
|
||||
} from '@support/test_config';
|
||||
import {Autocomplete} from '@support/ui/component';
|
||||
import {
|
||||
ChannelListScreen,
|
||||
ChannelScreen,
|
||||
HomeScreen,
|
||||
LoginScreen,
|
||||
ServerScreen,
|
||||
} from '@support/ui/screen';
|
||||
import {getRandomId, timeouts, wait} from '@support/utils';
|
||||
import {expect} from 'detox';
|
||||
|
||||
describe('Autocomplete - Channel Mention', () => {
|
||||
const serverOneDisplayName = 'Server 1';
|
||||
const channelsCategory = 'channels';
|
||||
let testChannel: any;
|
||||
let testOtherChannel: any;
|
||||
let testTeam: any;
|
||||
let channelMentionAutocomplete: any;
|
||||
let otherChannelMentionAutocomplete: any;
|
||||
|
||||
beforeAll(async () => {
|
||||
System.apiUpdateConfig(siteOneUrl, {
|
||||
ServiceSettings: {
|
||||
EnableAPIChannelDeletion: true,
|
||||
},
|
||||
});
|
||||
|
||||
const {channel, team, user} = await Setup.apiInit(siteOneUrl);
|
||||
testChannel = channel;
|
||||
testTeam = team;
|
||||
({channelMentionItem: channelMentionAutocomplete} = Autocomplete.getChannelMentionItem(testChannel.name));
|
||||
|
||||
({channel: testOtherChannel} = await Channel.apiCreateChannel(siteOneUrl, {teamId: testTeam.id}));
|
||||
await Channel.apiAddUserToChannel(siteOneUrl, user.id, testOtherChannel.id);
|
||||
({channelMentionItem: otherChannelMentionAutocomplete} = Autocomplete.getChannelMentionItem(testOtherChannel.name));
|
||||
|
||||
// # Log in to server
|
||||
await ServerScreen.connectToServer(serverOneUrl, serverOneDisplayName);
|
||||
await LoginScreen.login(user);
|
||||
|
||||
// * Verify on channel list screen
|
||||
await ChannelListScreen.toBeVisible();
|
||||
|
||||
// # Open a channel screen
|
||||
await ChannelScreen.open(channelsCategory, testChannel.name);
|
||||
});
|
||||
|
||||
beforeEach(async () => {
|
||||
// # Clear post input
|
||||
await ChannelScreen.postInput.clearText();
|
||||
|
||||
// * Verify autocomplete is not displayed
|
||||
await Autocomplete.toBeVisible(false);
|
||||
});
|
||||
|
||||
afterAll(async () => {
|
||||
// # Log out
|
||||
await ChannelScreen.back();
|
||||
await HomeScreen.logout();
|
||||
});
|
||||
|
||||
it('MM-T4879_1 - should suggest channel based on channel name', async () => {
|
||||
// # Type in "~" to activate channel mention autocomplete
|
||||
await ChannelScreen.postInput.typeText('~');
|
||||
await Autocomplete.toBeVisible();
|
||||
|
||||
// * Verify channel mention list is displayed
|
||||
await expect(Autocomplete.sectionChannelMentionList).toBeVisible();
|
||||
|
||||
// # Type in channel name
|
||||
await ChannelScreen.postInput.typeText(testChannel.name);
|
||||
|
||||
// * Verify channel mention autocomplete contains associated channel suggestion
|
||||
await expect(channelMentionAutocomplete).toBeVisible();
|
||||
});
|
||||
|
||||
it('MM-T4879_2 - should suggest channel based on channel display name', async () => {
|
||||
// # Type in "~" to activate channel mention autocomplete
|
||||
await ChannelScreen.postInput.typeText('~');
|
||||
await Autocomplete.toBeVisible();
|
||||
|
||||
// * Verify channel mention list is displayed
|
||||
await expect(Autocomplete.sectionChannelMentionList).toBeVisible();
|
||||
|
||||
// # Type in channel display name
|
||||
await ChannelScreen.postInput.typeText(testChannel.display_name);
|
||||
|
||||
// * Verify channel mention autocomplete contains associated channel suggestion
|
||||
await expect(channelMentionAutocomplete).toBeVisible();
|
||||
});
|
||||
|
||||
it('MM-T4879_3 - should suggest channel based on lowercase channel display name', async () => {
|
||||
// # Type in "~" to activate channel mention autocomplete
|
||||
await ChannelScreen.postInput.typeText('~');
|
||||
await Autocomplete.toBeVisible();
|
||||
|
||||
// * Verify channel mention list is displayed
|
||||
await expect(Autocomplete.sectionChannelMentionList).toBeVisible();
|
||||
|
||||
// # Type in lowercase channel display name
|
||||
await ChannelScreen.postInput.typeText(testChannel.display_name.toLowerCase());
|
||||
|
||||
// * Verify channel mention autocomplete contains associated channel suggestion
|
||||
await expect(channelMentionAutocomplete).toBeVisible();
|
||||
});
|
||||
|
||||
it('MM-T4879_4 - should suggest channel based on partial channel display name', async () => {
|
||||
// # Type in "~" to activate channel mention autocomplete
|
||||
await ChannelScreen.postInput.typeText('~');
|
||||
await Autocomplete.toBeVisible();
|
||||
|
||||
// * Verify channel mention list is displayed
|
||||
await expect(Autocomplete.sectionChannelMentionList).toBeVisible();
|
||||
|
||||
// # Type in partial channel display name
|
||||
await ChannelScreen.postInput.typeText(`${testChannel.display_name.substring(0, testChannel.display_name.length - 4)}`);
|
||||
|
||||
// * Verify channel mention autocomplete contains associated channel suggestion
|
||||
await expect(channelMentionAutocomplete).toBeVisible();
|
||||
});
|
||||
|
||||
it('MM-T4879_5 - should stop suggesting channel after channel display name with trailing space -- KNOWN ISSUE: MM-45279', async () => {
|
||||
// # Type in "~" to activate channel mention autocomplete
|
||||
await ChannelScreen.postInput.typeText('~');
|
||||
await Autocomplete.toBeVisible();
|
||||
|
||||
// * Verify channel mention list is displayed
|
||||
await expect(Autocomplete.sectionChannelMentionList).toBeVisible();
|
||||
|
||||
// # Type in channel display name
|
||||
await ChannelScreen.postInput.typeText(testChannel.display_name);
|
||||
|
||||
// * Verify channel mention autocomplete contains associated channel suggestion
|
||||
await expect(channelMentionAutocomplete).toBeVisible();
|
||||
|
||||
// # Type in trailing space
|
||||
await ChannelScreen.postInput.typeText(' ');
|
||||
await wait(timeouts.ONE_SEC);
|
||||
|
||||
// * Verify channel mention autocomplete does not contain associated channel suggestion
|
||||
await expect(channelMentionAutocomplete).not.toBeVisible();
|
||||
});
|
||||
|
||||
it('MM-T4879_6 - should stop suggesting channel when keyword is not associated with any channel', async () => {
|
||||
// # Type in "~" to activate channel mention autocomplete
|
||||
await ChannelScreen.postInput.typeText('~');
|
||||
await Autocomplete.toBeVisible();
|
||||
|
||||
// * Verify channel mention list is displayed
|
||||
await expect(Autocomplete.sectionChannelMentionList).toBeVisible();
|
||||
|
||||
// # Type in keyword not associated with any channel
|
||||
await ChannelScreen.postInput.typeText(getRandomId());
|
||||
|
||||
// * Verify channel mention autocomplete does not contain associated channel suggestion
|
||||
await expect(channelMentionAutocomplete).not.toBeVisible();
|
||||
});
|
||||
|
||||
it('MM-T4879_7 - should be able to select channel mention multiple times', async () => {
|
||||
// # Type in "~" to activate channel mention autocomplete
|
||||
await expect(Autocomplete.sectionChannelMentionList).not.toBeVisible();
|
||||
await ChannelScreen.postInput.typeText('~');
|
||||
|
||||
// * Verify channel mention list is displayed
|
||||
await expect(Autocomplete.sectionChannelMentionList).toBeVisible();
|
||||
|
||||
// # Type in channel name and tap on channel mention autocomplete
|
||||
await ChannelScreen.postInput.typeText(testChannel.name);
|
||||
await channelMentionAutocomplete.tap();
|
||||
|
||||
// * Verify channel mention list disappears
|
||||
await expect(Autocomplete.sectionChannelMentionList).not.toBeVisible();
|
||||
|
||||
// # Type in "~" again to re-activate channel mention list
|
||||
await ChannelScreen.postInput.typeText('~');
|
||||
|
||||
// * Verify channel mention list is displayed
|
||||
await expect(Autocomplete.sectionChannelMentionList).toBeVisible();
|
||||
});
|
||||
|
||||
it('MM-T4879_8 - should not be able to autocomplete archived channel', async () => {
|
||||
// # Archive another team channel and type in "~" to activate channel mention autocomplete
|
||||
await Channel.apiDeleteChannel(siteOneUrl, testOtherChannel.id);
|
||||
await ChannelScreen.postInput.typeText('~');
|
||||
await Autocomplete.toBeVisible();
|
||||
|
||||
// * Verify channel mention list is displayed
|
||||
await expect(Autocomplete.sectionChannelMentionList).toBeVisible();
|
||||
|
||||
// # Type in channel name of archived channel
|
||||
await ChannelScreen.postInput.typeText(testOtherChannel.name);
|
||||
|
||||
// * Verify channel mention autocomplete does not contain associated channel suggestion
|
||||
await expect(otherChannelMentionAutocomplete).not.toBeVisible();
|
||||
|
||||
// # Unarchive channel, clear post input, and type in "~" to activate channel mention list
|
||||
await Channel.apiRestoreChannel(siteOneUrl, testOtherChannel.id);
|
||||
await ChannelScreen.postInput.clearText();
|
||||
await Autocomplete.toBeVisible(false);
|
||||
await ChannelScreen.postInput.typeText('~');
|
||||
await Autocomplete.toBeVisible();
|
||||
|
||||
// * Verify channel mention list is displayed
|
||||
await expect(Autocomplete.sectionChannelMentionList).toBeVisible();
|
||||
|
||||
// # Type in channel name of unarchived channel
|
||||
await ChannelScreen.postInput.typeText(testOtherChannel.name);
|
||||
|
||||
// * Verify channel mention autocomplete contains associated channel suggestion
|
||||
await expect(otherChannelMentionAutocomplete).toBeVisible();
|
||||
});
|
||||
|
||||
it('MM-T4879_9 - should not be able to autocomplete out of team channel', async () => {
|
||||
// # Type in "~" to activate channel mention autocomplete
|
||||
const {team: otherTeam} = await Team.apiCreateTeam(siteOneUrl);
|
||||
const {channel: outOfTeamChannel} = await Channel.apiCreateChannel(siteOneUrl, {teamId: otherTeam.id});
|
||||
await ChannelScreen.postInput.typeText('~');
|
||||
await Autocomplete.toBeVisible();
|
||||
|
||||
// * Verify channel mention list is displayed
|
||||
await expect(Autocomplete.sectionChannelMentionList).toBeVisible();
|
||||
|
||||
// # Type in channel name of out of team channel
|
||||
await ChannelScreen.postInput.typeText(outOfTeamChannel.name);
|
||||
|
||||
// * Verify channel mention autocomplete does not contain associated channel suggestion
|
||||
const {channelMentionItem: outOfTeamChannelChannelMentionAutocomplete} = Autocomplete.getChannelMentionItem(outOfTeamChannel.name);
|
||||
await expect(outOfTeamChannelChannelMentionAutocomplete).not.toBeVisible();
|
||||
});
|
||||
|
||||
it('MM-T4879_10 - should include current channel in autocomplete', async () => {
|
||||
// # Type in "~" to activate channel mention autocomplete
|
||||
await ChannelScreen.postInput.typeText('~');
|
||||
await Autocomplete.toBeVisible();
|
||||
|
||||
// * Verify channel mention list is displayed
|
||||
await expect(Autocomplete.sectionChannelMentionList).toBeVisible();
|
||||
|
||||
// # Type in channel name of current channel
|
||||
await ChannelScreen.postInput.typeText(testChannel.name);
|
||||
|
||||
// * Verify channel mention autocomplete contains current channel
|
||||
const {channelMentionItemChannelDisplayName, channelMentionItemChannelName} = Autocomplete.getChannelMentionItem(testChannel.name);
|
||||
await expect(channelMentionItemChannelDisplayName).toHaveText(`${testChannel.display_name}`);
|
||||
await expect(channelMentionItemChannelName).toHaveText(` ~${testChannel.name}`);
|
||||
});
|
||||
});
|
||||
103
detox/e2e/test/autocomplete/edit_channel.e2e.ts
Normal file
103
detox/e2e/test/autocomplete/edit_channel.e2e.ts
Normal file
@@ -0,0 +1,103 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
// *******************************************************************
|
||||
// - [#] indicates a test step (e.g. # Go to a screen)
|
||||
// - [*] indicates an assertion (e.g. * Check the title)
|
||||
// - Use element testID when selecting an element. Create one if none.
|
||||
// *******************************************************************
|
||||
|
||||
import {Setup} from '@support/server_api';
|
||||
import {
|
||||
serverOneUrl,
|
||||
siteOneUrl,
|
||||
} from '@support/test_config';
|
||||
import {Autocomplete} from '@support/ui/component';
|
||||
import {
|
||||
ChannelInfoScreen,
|
||||
ChannelListScreen,
|
||||
ChannelScreen,
|
||||
CreateOrEditChannelScreen,
|
||||
HomeScreen,
|
||||
LoginScreen,
|
||||
ServerScreen,
|
||||
} from '@support/ui/screen';
|
||||
import {expect} from 'detox';
|
||||
|
||||
describe('Autocomplete - Edit Channel', () => {
|
||||
const serverOneDisplayName = 'Server 1';
|
||||
const channelsCategory = 'channels';
|
||||
|
||||
beforeAll(async () => {
|
||||
const {channel, user} = await Setup.apiInit(siteOneUrl);
|
||||
|
||||
// # Log in to server
|
||||
await ServerScreen.connectToServer(serverOneUrl, serverOneDisplayName);
|
||||
await LoginScreen.login(user);
|
||||
|
||||
// * Verify on channel list screen
|
||||
await ChannelListScreen.toBeVisible();
|
||||
|
||||
// # Open a channel screen, open channel info screen, and open edit channel screen
|
||||
await ChannelScreen.open(channelsCategory, channel.name);
|
||||
await ChannelInfoScreen.open();
|
||||
await CreateOrEditChannelScreen.openEditChannel();
|
||||
});
|
||||
|
||||
beforeEach(async () => {
|
||||
// # Clear header input
|
||||
await CreateOrEditChannelScreen.headerInput.clearText();
|
||||
});
|
||||
|
||||
afterAll(async () => {
|
||||
// # Log out
|
||||
await CreateOrEditChannelScreen.back();
|
||||
await ChannelInfoScreen.close();
|
||||
await ChannelScreen.back();
|
||||
await HomeScreen.logout();
|
||||
});
|
||||
|
||||
it('MM-T4885_1 - should render at-mention autocomplete in header input', async () => {
|
||||
// * Verify at-mention list is not displayed
|
||||
await expect(Autocomplete.sectionAtMentionList).not.toBeVisible();
|
||||
|
||||
// # Type in "@" to activate at-mention autocomplete
|
||||
await CreateOrEditChannelScreen.headerInput.typeText('@');
|
||||
|
||||
// * Verify at-mention list is displayed
|
||||
await expect(Autocomplete.sectionAtMentionList).toBeVisible();
|
||||
});
|
||||
|
||||
it('MM-T4885_2 - should render channel mention autocomplete in header input', async () => {
|
||||
// * Verify channel mention list is not displayed
|
||||
await expect(Autocomplete.sectionChannelMentionList).not.toBeVisible();
|
||||
|
||||
// # Type in "~" to activate channel mention autocomplete
|
||||
await CreateOrEditChannelScreen.headerInput.typeText('~');
|
||||
|
||||
// * Verify channel mention list is displayed
|
||||
await expect(Autocomplete.sectionChannelMentionList).toBeVisible();
|
||||
});
|
||||
|
||||
it('MM-T4885_3 - should render emoji suggestion autocomplete in header input', async () => {
|
||||
// * Verify emoji suggestion list is not displayed
|
||||
await expect(Autocomplete.flatEmojiSuggestionList).not.toBeVisible();
|
||||
|
||||
// # Type in ":" followed by 2 characters to activate emoji suggestion autocomplete
|
||||
await CreateOrEditChannelScreen.headerInput.typeText(':sm');
|
||||
|
||||
// * Verify emoji suggestion list is displayed
|
||||
await expect(Autocomplete.flatEmojiSuggestionList).toBeVisible();
|
||||
});
|
||||
|
||||
it('MM-T4885_4 - should not render slash suggestion autocomplete in header input', async () => {
|
||||
// * Verify slash suggestion list is not displayed
|
||||
await expect(Autocomplete.flatEmojiSuggestionList).not.toBeVisible();
|
||||
|
||||
// # Type in "/" to activate slash suggestion autocomplete
|
||||
await CreateOrEditChannelScreen.headerInput.typeText('/');
|
||||
|
||||
// * Verify slash suggestion list is still not displayed
|
||||
await expect(Autocomplete.flatEmojiSuggestionList).not.toBeVisible();
|
||||
});
|
||||
});
|
||||
100
detox/e2e/test/autocomplete/edit_channel_header.e2e.ts
Normal file
100
detox/e2e/test/autocomplete/edit_channel_header.e2e.ts
Normal file
@@ -0,0 +1,100 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
// *******************************************************************
|
||||
// - [#] indicates a test step (e.g. # Go to a screen)
|
||||
// - [*] indicates an assertion (e.g. * Check the title)
|
||||
// - Use element testID when selecting an element. Create one if none.
|
||||
// *******************************************************************
|
||||
|
||||
import {Setup} from '@support/server_api';
|
||||
import {
|
||||
serverOneUrl,
|
||||
siteOneUrl,
|
||||
} from '@support/test_config';
|
||||
import {Autocomplete} from '@support/ui/component';
|
||||
import {
|
||||
ChannelListScreen,
|
||||
ChannelScreen,
|
||||
CreateOrEditChannelScreen,
|
||||
HomeScreen,
|
||||
LoginScreen,
|
||||
ServerScreen,
|
||||
} from '@support/ui/screen';
|
||||
import {expect} from 'detox';
|
||||
|
||||
describe('Autocomplete - Edit Channel Header', () => {
|
||||
const serverOneDisplayName = 'Server 1';
|
||||
const channelsCategory = 'channels';
|
||||
|
||||
beforeAll(async () => {
|
||||
const {channel, user} = await Setup.apiInit(siteOneUrl);
|
||||
|
||||
// # Log in to server
|
||||
await ServerScreen.connectToServer(serverOneUrl, serverOneDisplayName);
|
||||
await LoginScreen.login(user);
|
||||
|
||||
// * Verify on channel list screen
|
||||
await ChannelListScreen.toBeVisible();
|
||||
|
||||
// # Open a channel screen and open edit channel header screen
|
||||
await ChannelScreen.open(channelsCategory, channel.name);
|
||||
await CreateOrEditChannelScreen.openEditChannelHeader();
|
||||
});
|
||||
|
||||
beforeEach(async () => {
|
||||
// # Clear header input
|
||||
await CreateOrEditChannelScreen.headerInput.clearText();
|
||||
});
|
||||
|
||||
afterAll(async () => {
|
||||
// # Log out
|
||||
await CreateOrEditChannelScreen.close();
|
||||
await ChannelScreen.back();
|
||||
await HomeScreen.logout();
|
||||
});
|
||||
|
||||
it('MM-T4884_1 - should render at-mention autocomplete in header input', async () => {
|
||||
// * Verify at-mention list is not displayed
|
||||
await expect(Autocomplete.sectionAtMentionList).not.toBeVisible();
|
||||
|
||||
// # Type in "@" to activate at-mention autocomplete
|
||||
await CreateOrEditChannelScreen.headerInput.typeText('@');
|
||||
|
||||
// * Verify at-mention list is displayed
|
||||
await expect(Autocomplete.sectionAtMentionList).toBeVisible();
|
||||
});
|
||||
|
||||
it('MM-T4884_2 - should render channel mention autocomplete in header input', async () => {
|
||||
// * Verify channel mention list is not displayed
|
||||
await expect(Autocomplete.sectionChannelMentionList).not.toBeVisible();
|
||||
|
||||
// # Type in "~" to activate channel mention autocomplete
|
||||
await CreateOrEditChannelScreen.headerInput.typeText('~');
|
||||
|
||||
// * Verify channel mention list is displayed
|
||||
await expect(Autocomplete.sectionChannelMentionList).toBeVisible();
|
||||
});
|
||||
|
||||
it('MM-T4884_3 - should render emoji suggestion autocomplete in header input', async () => {
|
||||
// * Verify emoji suggestion list is not displayed
|
||||
await expect(Autocomplete.flatEmojiSuggestionList).not.toBeVisible();
|
||||
|
||||
// # Type in ":" followed by 2 characters to activate emoji suggestion autocomplete
|
||||
await CreateOrEditChannelScreen.headerInput.typeText(':sm');
|
||||
|
||||
// * Verify emoji suggestion list is displayed
|
||||
await expect(Autocomplete.flatEmojiSuggestionList).toBeVisible();
|
||||
});
|
||||
|
||||
it('MM-T4884_4 - should not render slash suggestion autocomplete in header input', async () => {
|
||||
// * Verify slash suggestion list is not displayed
|
||||
await expect(Autocomplete.flatEmojiSuggestionList).not.toBeVisible();
|
||||
|
||||
// # Type in "/" to activate slash suggestion autocomplete
|
||||
await CreateOrEditChannelScreen.headerInput.typeText('/');
|
||||
|
||||
// * Verify slash suggestion list is still not displayed
|
||||
await expect(Autocomplete.flatEmojiSuggestionList).not.toBeVisible();
|
||||
});
|
||||
});
|
||||
108
detox/e2e/test/autocomplete/edit_post.e2e.ts
Normal file
108
detox/e2e/test/autocomplete/edit_post.e2e.ts
Normal file
@@ -0,0 +1,108 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
// *******************************************************************
|
||||
// - [#] indicates a test step (e.g. # Go to a screen)
|
||||
// - [*] indicates an assertion (e.g. * Check the title)
|
||||
// - Use element testID when selecting an element. Create one if none.
|
||||
// *******************************************************************
|
||||
|
||||
import {
|
||||
Post,
|
||||
Setup,
|
||||
} from '@support/server_api';
|
||||
import {
|
||||
serverOneUrl,
|
||||
siteOneUrl,
|
||||
} from '@support/test_config';
|
||||
import {Autocomplete} from '@support/ui/component';
|
||||
import {
|
||||
ChannelListScreen,
|
||||
ChannelScreen,
|
||||
EditPostScreen,
|
||||
HomeScreen,
|
||||
LoginScreen,
|
||||
ServerScreen,
|
||||
} from '@support/ui/screen';
|
||||
import {getRandomId} from '@support/utils';
|
||||
import {expect} from 'detox';
|
||||
|
||||
describe('Autocomplete - Edit Post', () => {
|
||||
const serverOneDisplayName = 'Server 1';
|
||||
const channelsCategory = 'channels';
|
||||
|
||||
beforeAll(async () => {
|
||||
const {channel, user} = await Setup.apiInit(siteOneUrl);
|
||||
|
||||
// # Log in to server
|
||||
await ServerScreen.connectToServer(serverOneUrl, serverOneDisplayName);
|
||||
await LoginScreen.login(user);
|
||||
|
||||
// * Verify on channel list screen
|
||||
await ChannelListScreen.toBeVisible();
|
||||
|
||||
// # Open a channel screen, post a message, open post options for message, and open edit post screen
|
||||
const message = `Messsage ${getRandomId()}`;
|
||||
await ChannelScreen.open(channelsCategory, channel.name);
|
||||
await ChannelScreen.postMessage(message);
|
||||
const {post} = await Post.apiGetLastPostInChannel(siteOneUrl, channel.id);
|
||||
await ChannelScreen.openPostOptionsFor(post.id, message);
|
||||
await EditPostScreen.open();
|
||||
});
|
||||
|
||||
beforeEach(async () => {
|
||||
// # Clear message input
|
||||
await EditPostScreen.messageInput.clearText();
|
||||
});
|
||||
|
||||
afterAll(async () => {
|
||||
// # Log out
|
||||
await EditPostScreen.close();
|
||||
await ChannelScreen.back();
|
||||
await HomeScreen.logout();
|
||||
});
|
||||
|
||||
it('MM-T4883_1 - should render at-mention autocomplete in message input', async () => {
|
||||
// * Verify at-mention list is not displayed
|
||||
await expect(Autocomplete.sectionAtMentionList).not.toBeVisible();
|
||||
|
||||
// # Type in "@" to activate at-mention autocomplete
|
||||
await EditPostScreen.messageInput.typeText('@');
|
||||
|
||||
// * Verify at-mention list is displayed
|
||||
await expect(Autocomplete.sectionAtMentionList).toBeVisible();
|
||||
});
|
||||
|
||||
it('MM-T4883_2 - should render channel mention autocomplete in message input', async () => {
|
||||
// * Verify channel mention list is not displayed
|
||||
await expect(Autocomplete.sectionChannelMentionList).not.toBeVisible();
|
||||
|
||||
// # Type in "~" to activate channel mention autocomplete
|
||||
await EditPostScreen.messageInput.typeText('~');
|
||||
|
||||
// * Verify channel mention list is displayed
|
||||
await expect(Autocomplete.sectionChannelMentionList).toBeVisible();
|
||||
});
|
||||
|
||||
it('MM-T4883_3 - should render emoji suggestion autocomplete in message input', async () => {
|
||||
// * Verify emoji suggestion list is not displayed
|
||||
await expect(Autocomplete.flatEmojiSuggestionList).not.toBeVisible();
|
||||
|
||||
// # Type in ":" followed by 2 characters to activate emoji suggestion autocomplete
|
||||
await EditPostScreen.messageInput.typeText(':sm');
|
||||
|
||||
// * Verify emoji suggestion list is displayed
|
||||
await expect(Autocomplete.flatEmojiSuggestionList).toBeVisible();
|
||||
});
|
||||
|
||||
it('MM-T4883_4 - should not render slash suggestion autocomplete in message input', async () => {
|
||||
// * Verify slash suggestion list is not displayed
|
||||
await expect(Autocomplete.flatEmojiSuggestionList).not.toBeVisible();
|
||||
|
||||
// # Type in "/" to activate slash suggestion autocomplete
|
||||
await EditPostScreen.messageInput.typeText('/');
|
||||
|
||||
// * Verify slash suggestion list is still not displayed
|
||||
await expect(Autocomplete.flatEmojiSuggestionList).not.toBeVisible();
|
||||
});
|
||||
});
|
||||
167
detox/e2e/test/autocomplete/emoji_suggestion.e2e.ts
Normal file
167
detox/e2e/test/autocomplete/emoji_suggestion.e2e.ts
Normal file
@@ -0,0 +1,167 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
// *******************************************************************
|
||||
// - [#] indicates a test step (e.g. # Go to a screen)
|
||||
// - [*] indicates an assertion (e.g. * Check the title)
|
||||
// - Use element testID when selecting an element. Create one if none.
|
||||
// *******************************************************************
|
||||
|
||||
import {Setup} from '@support/server_api';
|
||||
import {
|
||||
serverOneUrl,
|
||||
siteOneUrl,
|
||||
} from '@support/test_config';
|
||||
import {Autocomplete} from '@support/ui/component';
|
||||
import {
|
||||
ChannelListScreen,
|
||||
ChannelScreen,
|
||||
HomeScreen,
|
||||
LoginScreen,
|
||||
ServerScreen,
|
||||
} from '@support/ui/screen';
|
||||
import {getRandomId, timeouts, wait} from '@support/utils';
|
||||
import {expect} from 'detox';
|
||||
|
||||
describe('Autocomplete - Emoji Suggestion', () => {
|
||||
const serverOneDisplayName = 'Server 1';
|
||||
const channelsCategory = 'channels';
|
||||
const emojiName = 'fox_face';
|
||||
const emojiNameFirst2Chars = emojiName.substring(0, 2);
|
||||
const emojiName3rdToLastChars = emojiName.substring(2);
|
||||
let emojiSuggestionAutocomplete: any;
|
||||
|
||||
beforeAll(async () => {
|
||||
const {channel, user} = await Setup.apiInit(siteOneUrl);
|
||||
|
||||
({emojiSuggestionItem: emojiSuggestionAutocomplete} = Autocomplete.getEmojiSuggestionItem(emojiName));
|
||||
|
||||
// # Log in to server
|
||||
await ServerScreen.connectToServer(serverOneUrl, serverOneDisplayName);
|
||||
await LoginScreen.login(user);
|
||||
|
||||
// * Verify on channel list screen
|
||||
await ChannelListScreen.toBeVisible();
|
||||
|
||||
// # Open a channel screen
|
||||
await ChannelScreen.open(channelsCategory, channel.name);
|
||||
});
|
||||
|
||||
beforeEach(async () => {
|
||||
// # Clear post input
|
||||
await ChannelScreen.postInput.clearText();
|
||||
|
||||
// * Verify autocomplete is not displayed
|
||||
await Autocomplete.toBeVisible(false);
|
||||
});
|
||||
|
||||
afterAll(async () => {
|
||||
// # Log out
|
||||
await ChannelScreen.back();
|
||||
await HomeScreen.logout();
|
||||
});
|
||||
|
||||
it('MM-T4880_1 - should suggest emoji based on emoji name', async () => {
|
||||
// # Type in ":" then first 2 characters of emoji name to activate emoji suggestion autocomplete
|
||||
await ChannelScreen.postInput.typeText(`:${emojiNameFirst2Chars}`);
|
||||
await Autocomplete.toBeVisible();
|
||||
|
||||
// * Verify emoji suggestion list is displayed
|
||||
await expect(Autocomplete.flatEmojiSuggestionList).toBeVisible();
|
||||
|
||||
// # Type in 3rd to last characters of emoji name
|
||||
await ChannelScreen.postInput.typeText(emojiName3rdToLastChars);
|
||||
|
||||
// * Verify emoji suggestion autocomplete contains associated emoji suggestion
|
||||
await expect(emojiSuggestionAutocomplete).toBeVisible();
|
||||
});
|
||||
|
||||
it('MM-T4880_2 - should suggest emoji based on uppercase emoji name', async () => {
|
||||
// # Type in ":" then uppercase first 2 characters of emoji name to activate emoji suggestion autocomplete
|
||||
await ChannelScreen.postInput.typeText(`:${emojiNameFirst2Chars.toUpperCase()}`);
|
||||
await Autocomplete.toBeVisible();
|
||||
|
||||
// * Verify emoji suggestion list is displayed
|
||||
await expect(Autocomplete.flatEmojiSuggestionList).toBeVisible();
|
||||
|
||||
// # Type in uppercase 3rd to last characters of emoji name
|
||||
await ChannelScreen.postInput.typeText(emojiName3rdToLastChars.toUpperCase());
|
||||
|
||||
// * Verify emoji suggestion autocomplete contains associated emoji suggestion
|
||||
await expect(emojiSuggestionAutocomplete).toBeVisible();
|
||||
});
|
||||
|
||||
it('MM-T4880_3 - should suggest emoji based on partial emoji name', async () => {
|
||||
// # Type in ":" then first 2 characters of emoji name to activate emoji suggestion autocomplete
|
||||
await ChannelScreen.postInput.typeText(`:${emojiNameFirst2Chars}`);
|
||||
await Autocomplete.toBeVisible();
|
||||
|
||||
// * Verify emoji suggestion list is displayed
|
||||
await expect(Autocomplete.flatEmojiSuggestionList).toBeVisible();
|
||||
|
||||
// # Type in partial emoji name
|
||||
await ChannelScreen.postInput.typeText(`${emojiName.substring(2, 4)}`);
|
||||
|
||||
// * Verify emoji suggestion autocomplete contains associated emoji suggestion
|
||||
await expect(emojiSuggestionAutocomplete).toBeVisible();
|
||||
});
|
||||
|
||||
it('MM-T4880_4 - should stop suggesting emoji after emoji name with trailing space', async () => {
|
||||
// # Type in ":" then first 2 characters of emoji name to activate emoji suggestion autocomplete
|
||||
await ChannelScreen.postInput.typeText(`:${emojiNameFirst2Chars}`);
|
||||
await Autocomplete.toBeVisible();
|
||||
|
||||
// * Verify emoji suggestion list is displayed
|
||||
await expect(Autocomplete.flatEmojiSuggestionList).toBeVisible();
|
||||
|
||||
// # Type in 3rd to last characters of emoji name
|
||||
await ChannelScreen.postInput.typeText(emojiName3rdToLastChars);
|
||||
|
||||
// * Verify emoji suggestion autocomplete contains associated emoji suggestion
|
||||
await expect(emojiSuggestionAutocomplete).toBeVisible();
|
||||
|
||||
// # Type in trailing space
|
||||
await ChannelScreen.postInput.typeText(' ');
|
||||
await wait(timeouts.ONE_SEC);
|
||||
|
||||
// * Verify emoji suggestion autocomplete does not contain associated emoji suggestion
|
||||
await expect(emojiSuggestionAutocomplete).not.toBeVisible();
|
||||
});
|
||||
|
||||
it('MM-T4880_5 - should stop suggesting emoji when keyword is not associated with any emoji', async () => {
|
||||
// # Type in ":" then first 2 characters of emoji name to activate emoji suggestion autocomplete
|
||||
await ChannelScreen.postInput.typeText(`:${emojiNameFirst2Chars}`);
|
||||
await Autocomplete.toBeVisible();
|
||||
|
||||
// * Verify emoji suggestion list is displayed
|
||||
await expect(Autocomplete.flatEmojiSuggestionList).toBeVisible();
|
||||
|
||||
// # Type in keyword not associated with any emoji
|
||||
await ChannelScreen.postInput.typeText(getRandomId());
|
||||
|
||||
// * Verify emoji suggestion autocomplete does not contain associated emoji suggestion
|
||||
await expect(emojiSuggestionAutocomplete).not.toBeVisible();
|
||||
});
|
||||
|
||||
it('MM-T4880_6 - should be able to select emoji suggestion multiple times', async () => {
|
||||
// # Type in ":" then first 2 characters of emoji name to activate emoji suggestion autocomplete
|
||||
await expect(Autocomplete.flatEmojiSuggestionList).not.toBeVisible();
|
||||
await ChannelScreen.postInput.typeText(`:${emojiNameFirst2Chars}`);
|
||||
|
||||
// * Verify emoji suggestion list is displayed
|
||||
await expect(Autocomplete.flatEmojiSuggestionList).toBeVisible();
|
||||
|
||||
// # Type in 3rd to last characters of emoji name and tap on emoji suggestion autocomplete
|
||||
await ChannelScreen.postInput.typeText(emojiName3rdToLastChars);
|
||||
await emojiSuggestionAutocomplete.tap();
|
||||
|
||||
// * Verify emoji suggestion list disappears
|
||||
await expect(Autocomplete.flatEmojiSuggestionList).not.toBeVisible();
|
||||
|
||||
// # Type in ":" then first 2 characters of emoji name again to re-activate emoji suggestion list
|
||||
await ChannelScreen.postInput.typeText(`:${emojiNameFirst2Chars}`);
|
||||
|
||||
// * Verify emoji suggestion list is displayed
|
||||
await expect(Autocomplete.flatEmojiSuggestionList).toBeVisible();
|
||||
});
|
||||
});
|
||||
100
detox/e2e/test/autocomplete/post_draft.e2e.ts
Normal file
100
detox/e2e/test/autocomplete/post_draft.e2e.ts
Normal file
@@ -0,0 +1,100 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
// *******************************************************************
|
||||
// - [#] indicates a test step (e.g. # Go to a screen)
|
||||
// - [*] indicates an assertion (e.g. * Check the title)
|
||||
// - Use element testID when selecting an element. Create one if none.
|
||||
// *******************************************************************
|
||||
|
||||
import {Setup} from '@support/server_api';
|
||||
import {
|
||||
serverOneUrl,
|
||||
siteOneUrl,
|
||||
} from '@support/test_config';
|
||||
import {Autocomplete} from '@support/ui/component';
|
||||
import {
|
||||
ChannelListScreen,
|
||||
ChannelScreen,
|
||||
HomeScreen,
|
||||
LoginScreen,
|
||||
ServerScreen,
|
||||
} from '@support/ui/screen';
|
||||
import {expect} from 'detox';
|
||||
|
||||
describe('Autocomplete - Post Draft', () => {
|
||||
const serverOneDisplayName = 'Server 1';
|
||||
const channelsCategory = 'channels';
|
||||
|
||||
beforeAll(async () => {
|
||||
const {channel, user} = await Setup.apiInit(siteOneUrl);
|
||||
|
||||
// # Log in to server
|
||||
await ServerScreen.connectToServer(serverOneUrl, serverOneDisplayName);
|
||||
await LoginScreen.login(user);
|
||||
|
||||
// * Verify on channel list screen
|
||||
await ChannelListScreen.toBeVisible();
|
||||
|
||||
// # Open a channel screen
|
||||
await ChannelScreen.open(channelsCategory, channel.name);
|
||||
});
|
||||
|
||||
beforeEach(async () => {
|
||||
// # Clear post input
|
||||
await ChannelScreen.postInput.clearText();
|
||||
|
||||
// * Verify autocomplete is not displayed
|
||||
await Autocomplete.toBeVisible(false);
|
||||
});
|
||||
|
||||
afterAll(async () => {
|
||||
// # Log out
|
||||
await ChannelScreen.back();
|
||||
await HomeScreen.logout();
|
||||
});
|
||||
|
||||
it('MM-T4882_1 - should render at-mention autocomplete in post input', async () => {
|
||||
// * Verify at-mention list is not displayed
|
||||
await expect(Autocomplete.sectionAtMentionList).not.toBeVisible();
|
||||
|
||||
// # Type in "@" to activate at-mention autocomplete
|
||||
await ChannelScreen.postInput.typeText('@');
|
||||
|
||||
// * Verify at-mention list is displayed
|
||||
await expect(Autocomplete.sectionAtMentionList).toBeVisible();
|
||||
});
|
||||
|
||||
it('MM-T4882_2 - should render channel mention autocomplete in post input', async () => {
|
||||
// * Verify channel mention list is not displayed
|
||||
await expect(Autocomplete.sectionChannelMentionList).not.toBeVisible();
|
||||
|
||||
// # Type in "~" to activate channel mention autocomplete
|
||||
await ChannelScreen.postInput.typeText('~');
|
||||
|
||||
// * Verify channel mention list is displayed
|
||||
await expect(Autocomplete.sectionChannelMentionList).toBeVisible();
|
||||
});
|
||||
|
||||
it('MM-T4882_3 - should render emoji suggestion autocomplete in post input', async () => {
|
||||
// * Verify emoji suggestion list is not displayed
|
||||
await expect(Autocomplete.flatEmojiSuggestionList).not.toBeVisible();
|
||||
|
||||
// # Type in ":" followed by 2 characters to activate emoji suggestion autocomplete
|
||||
await ChannelScreen.postInput.typeText(':sm');
|
||||
|
||||
// * Verify emoji suggestion list is displayed
|
||||
await expect(Autocomplete.flatEmojiSuggestionList).toBeVisible();
|
||||
});
|
||||
|
||||
it('MM-T4882_4 - should render slash suggestion autocomplete in post input', async () => {
|
||||
// * Verify slash suggestion list is not displayed
|
||||
await expect(Autocomplete.flatSlashSuggestionList).not.toBeVisible();
|
||||
|
||||
// # Type in "/" to activate slash suggestion autocomplete
|
||||
await ChannelScreen.postInput.typeText('/');
|
||||
|
||||
// * Verify slash suggestion list is displayed
|
||||
await expect(Autocomplete.flatSlashSuggestionList).toBeVisible();
|
||||
});
|
||||
});
|
||||
165
detox/e2e/test/autocomplete/slash_suggestion.e2e.ts
Normal file
165
detox/e2e/test/autocomplete/slash_suggestion.e2e.ts
Normal file
@@ -0,0 +1,165 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
// *******************************************************************
|
||||
// - [#] indicates a test step (e.g. # Go to a screen)
|
||||
// - [*] indicates an assertion (e.g. * Check the title)
|
||||
// - Use element testID when selecting an element. Create one if none.
|
||||
// *******************************************************************
|
||||
|
||||
import {Setup} from '@support/server_api';
|
||||
import {
|
||||
serverOneUrl,
|
||||
siteOneUrl,
|
||||
} from '@support/test_config';
|
||||
import {Autocomplete} from '@support/ui/component';
|
||||
import {
|
||||
ChannelListScreen,
|
||||
ChannelScreen,
|
||||
HomeScreen,
|
||||
LoginScreen,
|
||||
ServerScreen,
|
||||
} from '@support/ui/screen';
|
||||
import {getRandomId, timeouts, wait} from '@support/utils';
|
||||
import {expect} from 'detox';
|
||||
|
||||
describe('Autocomplete - Slash Suggestion', () => {
|
||||
const serverOneDisplayName = 'Server 1';
|
||||
const channelsCategory = 'channels';
|
||||
const slashCommand = 'away';
|
||||
let slashSuggestionAutocomplete: any;
|
||||
|
||||
beforeAll(async () => {
|
||||
const {channel, user} = await Setup.apiInit(siteOneUrl);
|
||||
|
||||
({slashSuggestionItem: slashSuggestionAutocomplete} = Autocomplete.getSlashSuggestionItem(slashCommand));
|
||||
|
||||
// # Log in to server
|
||||
await ServerScreen.connectToServer(serverOneUrl, serverOneDisplayName);
|
||||
await LoginScreen.login(user);
|
||||
|
||||
// * Verify on channel list screen
|
||||
await ChannelListScreen.toBeVisible();
|
||||
|
||||
// # Open a channel screen
|
||||
await ChannelScreen.open(channelsCategory, channel.name);
|
||||
});
|
||||
|
||||
beforeEach(async () => {
|
||||
// # Clear post input
|
||||
await ChannelScreen.postInput.clearText();
|
||||
|
||||
// * Verify autocomplete is not displayed
|
||||
await Autocomplete.toBeVisible(false);
|
||||
});
|
||||
|
||||
afterAll(async () => {
|
||||
// # Log out
|
||||
await ChannelScreen.back();
|
||||
await HomeScreen.logout();
|
||||
});
|
||||
|
||||
it('MM-T4881_1 - should suggest slash command based on slash command name', async () => {
|
||||
// # Type in "/" to activate slash suggestion autocomplete
|
||||
await ChannelScreen.postInput.typeText('/');
|
||||
await Autocomplete.toBeVisible();
|
||||
|
||||
// * Verify slash suggestion list is displayed
|
||||
await expect(Autocomplete.flatSlashSuggestionList).toBeVisible();
|
||||
|
||||
// # Type in slash command name
|
||||
await ChannelScreen.postInput.typeText(slashCommand);
|
||||
|
||||
// * Verify slash suggestion autocomplete contains associated slash command suggestion
|
||||
await expect(slashSuggestionAutocomplete).toBeVisible();
|
||||
});
|
||||
|
||||
it('MM-T4881_2 - should suggest slash command based on partial slash command name', async () => {
|
||||
// # Type in "/" to activate slash suggestion autocomplete
|
||||
await ChannelScreen.postInput.typeText('/');
|
||||
await Autocomplete.toBeVisible();
|
||||
|
||||
// * Verify slash suggestion list is displayed
|
||||
await expect(Autocomplete.flatSlashSuggestionList).toBeVisible();
|
||||
|
||||
// # Type in partial slash command name
|
||||
await ChannelScreen.postInput.typeText(`${slashCommand.substring(0, slashCommand.length - 2)}`);
|
||||
|
||||
// * Verify slash suggestion autocomplete contains associated slash command suggestion
|
||||
await expect(slashSuggestionAutocomplete).toBeVisible();
|
||||
});
|
||||
|
||||
it('MM-T4881_3 - should stop suggesting slash command after uppercase slash command name', async () => {
|
||||
// # Type in "/" to activate slash suggestion autocomplete
|
||||
await ChannelScreen.postInput.typeText('/');
|
||||
await Autocomplete.toBeVisible();
|
||||
|
||||
// * Verify slash suggestion list is displayed
|
||||
await expect(Autocomplete.flatSlashSuggestionList).toBeVisible();
|
||||
|
||||
// # Type in uppercase slash command name
|
||||
await ChannelScreen.postInput.typeText(slashCommand.toUpperCase());
|
||||
|
||||
// * Verify slash suggestion autocomplete does not contain associated slash command suggestion
|
||||
await expect(slashSuggestionAutocomplete).not.toBeVisible();
|
||||
});
|
||||
|
||||
it('MM-T4881_4 - should stop suggesting slash command after slash command name with trailing space', async () => {
|
||||
// # Type in "/" to activate slash suggestion autocomplete
|
||||
await ChannelScreen.postInput.typeText('/');
|
||||
await Autocomplete.toBeVisible();
|
||||
|
||||
// * Verify slash suggestion list is displayed
|
||||
await expect(Autocomplete.flatSlashSuggestionList).toBeVisible();
|
||||
|
||||
// # Type in slash command name
|
||||
await ChannelScreen.postInput.typeText(slashCommand);
|
||||
|
||||
// * Verify slash suggestion autocomplete contains associated slash command suggestion
|
||||
await expect(slashSuggestionAutocomplete).toBeVisible();
|
||||
|
||||
// # Type in trailing space
|
||||
await ChannelScreen.postInput.typeText(' ');
|
||||
await wait(timeouts.ONE_SEC);
|
||||
|
||||
// * Verify slash suggestion autocomplete does not contain associated slash command suggestion
|
||||
await expect(slashSuggestionAutocomplete).not.toBeVisible();
|
||||
});
|
||||
|
||||
it('MM-T4881_5 - should stop suggesting slash command when keyword is not associated with any slash command', async () => {
|
||||
// # Type in "/" to activate slash suggestion autocomplete
|
||||
await ChannelScreen.postInput.typeText('/');
|
||||
await Autocomplete.toBeVisible();
|
||||
|
||||
// * Verify slash suggestion list is displayed
|
||||
await expect(Autocomplete.flatSlashSuggestionList).toBeVisible();
|
||||
|
||||
// # Type in keyword not associated with any slash command
|
||||
await ChannelScreen.postInput.typeText(getRandomId());
|
||||
|
||||
// * Verify slash suggestion autocomplete does not contain associated slash command suggestion
|
||||
await expect(slashSuggestionAutocomplete).not.toBeVisible();
|
||||
});
|
||||
|
||||
it('MM-T4881_6 - should not be able to select slash suggestion multiple times', async () => {
|
||||
// # Type in "/" to activate slash suggestion autocomplete
|
||||
await expect(Autocomplete.flatSlashSuggestionList).not.toBeVisible();
|
||||
await ChannelScreen.postInput.typeText('/');
|
||||
|
||||
// * Verify slash suggestion list is displayed
|
||||
await expect(Autocomplete.flatSlashSuggestionList).toBeVisible();
|
||||
|
||||
// # Type in slash command name and tap on slash suggestion autocomplete
|
||||
await ChannelScreen.postInput.typeText(slashCommand);
|
||||
await slashSuggestionAutocomplete.tap();
|
||||
|
||||
// * Verify slash suggestion list disappears
|
||||
await expect(Autocomplete.flatSlashSuggestionList).not.toBeVisible();
|
||||
|
||||
// # Type in "/" again to re-activate slash suggestion list
|
||||
await ChannelScreen.postInput.typeText('/');
|
||||
|
||||
// * Verify slash suggestion list is not displayed
|
||||
await expect(Autocomplete.flatSlashSuggestionList).not.toBeVisible();
|
||||
});
|
||||
});
|
||||
@@ -57,9 +57,9 @@ describe('Channels - Channel Post List', () => {
|
||||
await expect(ChannelScreen.backButton).toBeVisible();
|
||||
await expect(ChannelScreen.headerTitle).toHaveText(testChannel.display_name);
|
||||
await expect(ChannelScreen.introDisplayName).toHaveText(testChannel.display_name);
|
||||
await expect(ChannelScreen.introOptionAddPeopleItem).toBeVisible();
|
||||
await expect(ChannelScreen.introOptionSetHeaderItem).toBeVisible();
|
||||
await expect(ChannelScreen.introOptionChannelDetailsItem).toBeVisible();
|
||||
await expect(ChannelScreen.introAddPeopleOption).toBeVisible();
|
||||
await expect(ChannelScreen.introSetHeaderOption).toBeVisible();
|
||||
await expect(ChannelScreen.introChannelDetailsOption).toBeVisible();
|
||||
await expect(ChannelScreen.postList.getFlatList()).toBeVisible();
|
||||
await expect(ChannelScreen.postDraft).toBeVisible();
|
||||
await expect(ChannelScreen.postInput).toBeVisible();
|
||||
|
||||
@@ -82,7 +82,7 @@ describe('Channels - Create Channel and Edit Channel Header', () => {
|
||||
await expect(ChannelScreen.introDisplayName).toHaveText(displayName);
|
||||
|
||||
// # Tap on set header option to edit the channel header
|
||||
await ChannelScreen.introOptionSetHeaderItem.tap();
|
||||
await ChannelScreen.introSetHeaderOption.tap();
|
||||
|
||||
// * Verify channel header is correct
|
||||
await expect(CreateOrEditChannelScreen.headerInput).toHaveValue(header);
|
||||
@@ -90,7 +90,7 @@ describe('Channels - Create Channel and Edit Channel Header', () => {
|
||||
// # Edit the channel header, save, and re-open edit channel header screen
|
||||
await CreateOrEditChannelScreen.headerInput.replaceText(`${header} edit`);
|
||||
await CreateOrEditChannelScreen.saveButton.tap();
|
||||
await CreateOrEditChannelScreen.openEditChannel();
|
||||
await CreateOrEditChannelScreen.openEditChannelHeader();
|
||||
|
||||
// * Verify channel header has new value
|
||||
await expect(CreateOrEditChannelScreen.headerInput).toHaveValue(`${header} edit`);
|
||||
@@ -119,7 +119,7 @@ describe('Channels - Create Channel and Edit Channel Header', () => {
|
||||
await expect(ChannelScreen.introDisplayName).toHaveText(displayName);
|
||||
|
||||
// # Tap on set header option to edit the channel header
|
||||
await ChannelScreen.introOptionSetHeaderItem.tap();
|
||||
await ChannelScreen.introSetHeaderOption.tap();
|
||||
|
||||
// * Verify channel header is correct
|
||||
await expect(CreateOrEditChannelScreen.headerInput).toHaveValue(header);
|
||||
@@ -127,7 +127,7 @@ describe('Channels - Create Channel and Edit Channel Header', () => {
|
||||
// # Edit the channel header, save, and re-open edit channel header screen
|
||||
await CreateOrEditChannelScreen.headerInput.replaceText(`${header} edit`);
|
||||
await CreateOrEditChannelScreen.saveButton.tap();
|
||||
await CreateOrEditChannelScreen.openEditChannel();
|
||||
await CreateOrEditChannelScreen.openEditChannelHeader();
|
||||
|
||||
// * Verify channel header has new value
|
||||
await expect(CreateOrEditChannelScreen.headerInput).toHaveValue(`${header} edit`);
|
||||
|
||||
@@ -40,7 +40,7 @@ describe('Channels - Create Direct Message', () => {
|
||||
|
||||
// # Log in to server
|
||||
await ServerScreen.connectToServer(serverOneUrl, serverOneDisplayName);
|
||||
await LoginScreen.login(user);
|
||||
await LoginScreen.login(testUser);
|
||||
});
|
||||
|
||||
beforeEach(async () => {
|
||||
|
||||
160
detox/e2e/test/messaging/at_mention.e2e.ts
Normal file
160
detox/e2e/test/messaging/at_mention.e2e.ts
Normal file
@@ -0,0 +1,160 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
// *******************************************************************
|
||||
// - [#] indicates a test step (e.g. # Go to a screen)
|
||||
// - [*] indicates an assertion (e.g. * Check the title)
|
||||
// - Use element testID when selecting an element. Create one if none.
|
||||
// *******************************************************************
|
||||
|
||||
import {
|
||||
Channel,
|
||||
Post,
|
||||
Setup,
|
||||
Team,
|
||||
User,
|
||||
} from '@support/server_api';
|
||||
import {
|
||||
serverOneUrl,
|
||||
siteOneUrl,
|
||||
} from '@support/test_config';
|
||||
import {Alert} from '@support/ui/component';
|
||||
import {
|
||||
ChannelListScreen,
|
||||
ChannelScreen,
|
||||
HomeScreen,
|
||||
LoginScreen,
|
||||
ServerScreen,
|
||||
UserProfileScreen,
|
||||
} from '@support/ui/screen';
|
||||
import {timeouts, wait} from '@support/utils';
|
||||
import {expect} from 'detox';
|
||||
|
||||
describe('Messaging - At-Mention', () => {
|
||||
const serverOneDisplayName = 'Server 1';
|
||||
const channelsCategory = 'channels';
|
||||
let testChannel: any;
|
||||
let testTeam: any;
|
||||
let testUser: any;
|
||||
let testOtherUser: any;
|
||||
|
||||
beforeAll(async () => {
|
||||
const {channel, team, user} = await Setup.apiInit(siteOneUrl);
|
||||
testChannel = channel;
|
||||
testTeam = team;
|
||||
testUser = user;
|
||||
|
||||
({user: testOtherUser} = await User.apiCreateUser(siteOneUrl));
|
||||
await Team.apiAddUserToTeam(siteOneUrl, testOtherUser.id, testTeam.id);
|
||||
await Channel.apiAddUserToChannel(siteOneUrl, testOtherUser.id, testChannel.id);
|
||||
|
||||
// # Log in to server
|
||||
await ServerScreen.connectToServer(serverOneUrl, serverOneDisplayName);
|
||||
await LoginScreen.login(testUser);
|
||||
});
|
||||
|
||||
beforeEach(async () => {
|
||||
// * Verify on channel list screen
|
||||
await ChannelListScreen.toBeVisible();
|
||||
});
|
||||
|
||||
afterAll(async () => {
|
||||
// # Log out
|
||||
await HomeScreen.logout();
|
||||
});
|
||||
|
||||
it('MM-T4874_1 - should post at-mention as lowercase', async () => {
|
||||
// # Open a channel screen and post a message with lowercase at-mention
|
||||
const camelCaseUsernameMessage = `Message @${testUser.username.substring(0, 1).toUpperCase()}${testUser.username.substring(1)}`;
|
||||
await ChannelScreen.open(channelsCategory, testChannel.name);
|
||||
await ChannelScreen.postMessage(camelCaseUsernameMessage);
|
||||
|
||||
// * Verify at-mention is posted as lowercase
|
||||
const {post: lowerCasePost} = await Post.apiGetLastPostInChannel(siteOneUrl, testChannel.id);
|
||||
await ChannelScreen.hasPostMessage(lowerCasePost.id, `Message @${testUser.username.toLowerCase()}`);
|
||||
|
||||
// # Post a message with uppercase at-mention
|
||||
const upperCaseUsernameMessage = `Message @${testOtherUser.username.toUpperCase()}`;
|
||||
await ChannelScreen.postMessage(upperCaseUsernameMessage);
|
||||
|
||||
// * Verify at-mention is posted as lowercase
|
||||
const {post: upperCasePost} = await Post.apiGetLastPostInChannel(siteOneUrl, testChannel.id);
|
||||
await ChannelScreen.hasPostMessage(upperCasePost.id, `Message @${testOtherUser.username.toLowerCase()}`);
|
||||
|
||||
// # Go back to channel list screen
|
||||
await ChannelScreen.back();
|
||||
});
|
||||
|
||||
it('MM-T4874_2 - should display confirmation dialog when posting @all, @channel, and @here', async () => {
|
||||
// # Add more users to the channel, open a channel screen, and post @all
|
||||
[...Array(3).keys()].forEach(async (key) => {
|
||||
const {user} = await User.apiCreateUser(siteOneUrl, {prefix: `a-${key}-`});
|
||||
await Team.apiAddUserToTeam(siteOneUrl, user.id, testTeam.id);
|
||||
await Channel.apiAddUserToChannel(siteOneUrl, user.id, testChannel.id);
|
||||
});
|
||||
await ChannelScreen.open(channelsCategory, testChannel.name);
|
||||
await ChannelScreen.postInput.replaceText('@all');
|
||||
await ChannelScreen.sendButton.tap();
|
||||
|
||||
// * Verify confirmation dialog is displayed
|
||||
await expect(Alert.confirmSendingNotificationsTitle).toBeVisible();
|
||||
|
||||
// # Tap on confirm button
|
||||
await Alert.confirmButton.tap();
|
||||
|
||||
// * Verify @all is posted
|
||||
const {post: atAllPost} = await Post.apiGetLastPostInChannel(siteOneUrl, testChannel.id);
|
||||
await ChannelScreen.hasPostMessage(atAllPost.id, '@all');
|
||||
|
||||
// # Post @channel
|
||||
await ChannelScreen.postInput.clearText();
|
||||
await ChannelScreen.postInput.replaceText('@channel');
|
||||
await ChannelScreen.sendButton.tap();
|
||||
|
||||
// * Verify confirmation dialog is displayed
|
||||
await expect(Alert.confirmSendingNotificationsTitle).toBeVisible();
|
||||
|
||||
// # Tap on confirm button
|
||||
await Alert.confirmButton.tap();
|
||||
|
||||
// * Verify @channel is posted
|
||||
const {post: atChannelPost} = await Post.apiGetLastPostInChannel(siteOneUrl, testChannel.id);
|
||||
await ChannelScreen.hasPostMessage(atChannelPost.id, '@channel');
|
||||
|
||||
// # Post @here
|
||||
await ChannelScreen.postInput.clearText();
|
||||
await ChannelScreen.postInput.replaceText('@here');
|
||||
await ChannelScreen.sendButton.tap();
|
||||
|
||||
// * Verify confirmation dialog is displayed
|
||||
await expect(Alert.confirmSendingNotificationsTitle).toBeVisible();
|
||||
|
||||
// # Tap on confirm button
|
||||
await Alert.confirmButton.tap();
|
||||
|
||||
// * Verify @here is posted
|
||||
const {post: atHerePost} = await Post.apiGetLastPostInChannel(siteOneUrl, testChannel.id);
|
||||
await ChannelScreen.hasPostMessage(atHerePost.id, '@here');
|
||||
|
||||
// # Go back to channel list screen
|
||||
await ChannelScreen.back();
|
||||
});
|
||||
|
||||
it('MM-T4874_3 - should be able to open user profile by tapping on at-mention', async () => {
|
||||
// # Open a channel screen, post a message with at-mention, and tap on at-mention
|
||||
const message = `@${testUser.username}`;
|
||||
await ChannelScreen.open(channelsCategory, testChannel.name);
|
||||
await ChannelScreen.postMessage(message);
|
||||
await element(by.text(message)).tap({x: 5, y: 10});
|
||||
await wait(timeouts.ONE_SEC);
|
||||
|
||||
// * Verify on user profile screen
|
||||
await UserProfileScreen.toBeVisible();
|
||||
await expect(UserProfileScreen.getUserProfilePicture(testUser.id)).toBeVisible();
|
||||
await expect(UserProfileScreen.userDisplayName).toHaveText(`@${testUser.username}`);
|
||||
|
||||
// # Go back to channel list screen
|
||||
await UserProfileScreen.close();
|
||||
await ChannelScreen.back();
|
||||
});
|
||||
});
|
||||
95
detox/e2e/test/messaging/channel_link.e2e.ts
Normal file
95
detox/e2e/test/messaging/channel_link.e2e.ts
Normal file
@@ -0,0 +1,95 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
// *******************************************************************
|
||||
// - [#] indicates a test step (e.g. # Go to a screen)
|
||||
// - [*] indicates an assertion (e.g. * Check the title)
|
||||
// - Use element testID when selecting an element. Create one if none.
|
||||
// *******************************************************************
|
||||
|
||||
import {
|
||||
Channel,
|
||||
Post,
|
||||
Setup,
|
||||
} from '@support/server_api';
|
||||
import {
|
||||
serverOneUrl,
|
||||
siteOneUrl,
|
||||
} from '@support/test_config';
|
||||
import {
|
||||
ChannelListScreen,
|
||||
ChannelScreen,
|
||||
HomeScreen,
|
||||
LoginScreen,
|
||||
ServerScreen,
|
||||
} from '@support/ui/screen';
|
||||
import {timeouts, wait} from '@support/utils';
|
||||
import {expect} from 'detox';
|
||||
|
||||
describe('Messaging - Channel Link', () => {
|
||||
const serverOneDisplayName = 'Server 1';
|
||||
const channelsCategory = 'channels';
|
||||
let testChannel: any;
|
||||
let testTeam: any;
|
||||
let testUser: any;
|
||||
|
||||
beforeAll(async () => {
|
||||
const {channel, team, user} = await Setup.apiInit(siteOneUrl);
|
||||
testChannel = channel;
|
||||
testTeam = team;
|
||||
testUser = user;
|
||||
|
||||
// # Log in to server
|
||||
await ServerScreen.connectToServer(serverOneUrl, serverOneDisplayName);
|
||||
await LoginScreen.login(testUser);
|
||||
});
|
||||
|
||||
beforeEach(async () => {
|
||||
// * Verify on channel list screen
|
||||
await ChannelListScreen.toBeVisible();
|
||||
});
|
||||
|
||||
afterAll(async () => {
|
||||
// # Log out
|
||||
await HomeScreen.logout();
|
||||
});
|
||||
|
||||
it('MM-T4877_1 - should be able to open joined channel by tapping on channel link from main channel', async () => {
|
||||
// # Open a channel screen and post a channel link to target channel
|
||||
await ChannelScreen.open(channelsCategory, testChannel.name);
|
||||
const {channel: targetChannel} = await Channel.apiCreateChannel(siteOneUrl, {teamId: testTeam.id});
|
||||
await Channel.apiAddUserToChannel(siteOneUrl, testUser.id, targetChannel.id);
|
||||
const channelLink = `${serverOneUrl}/${testTeam.name}/channels/${targetChannel.name}`;
|
||||
await ChannelScreen.postMessage(channelLink);
|
||||
|
||||
// # Tap on channel link
|
||||
await element(by.text(channelLink)).tap({x: 5, y: 10});
|
||||
await wait(timeouts.ONE_SEC);
|
||||
|
||||
// * Verify redirected to target channel
|
||||
await expect(ChannelScreen.headerTitle).toHaveText(targetChannel.display_name);
|
||||
|
||||
// # Go back to channel list screen
|
||||
await ChannelScreen.back();
|
||||
});
|
||||
|
||||
it('MM-T4877_2 - should be able to open joined channel by tapping on channel link from reply thread', async () => {
|
||||
// # Open a channel screen, post a channel link to target channel, tap on post to open reply thread, and tap on channel link
|
||||
await ChannelScreen.open(channelsCategory, testChannel.name);
|
||||
const {channel: targetChannel} = await Channel.apiCreateChannel(siteOneUrl, {teamId: testTeam.id});
|
||||
await Channel.apiAddUserToChannel(siteOneUrl, testUser.id, targetChannel.id);
|
||||
const channelLink = `${serverOneUrl}/${testTeam.name}/channels/${targetChannel.name}`;
|
||||
await ChannelScreen.postMessage(channelLink);
|
||||
const {post} = await Post.apiGetLastPostInChannel(siteOneUrl, testChannel.id);
|
||||
const {postListPostItem} = ChannelScreen.getPostListPostItem(post.id);
|
||||
await postListPostItem.tap({x: 1, y: 1});
|
||||
await element(by.text(channelLink)).tap({x: 5, y: 10});
|
||||
await wait(timeouts.ONE_SEC);
|
||||
|
||||
// * Verify redirected to target channel
|
||||
await expect(ChannelScreen.headerTitle).toHaveText(targetChannel.display_name);
|
||||
|
||||
// # Go back to channel list screen
|
||||
await ChannelScreen.back();
|
||||
});
|
||||
});
|
||||
91
detox/e2e/test/messaging/channel_mention.e2e.ts
Normal file
91
detox/e2e/test/messaging/channel_mention.e2e.ts
Normal file
@@ -0,0 +1,91 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
// *******************************************************************
|
||||
// - [#] indicates a test step (e.g. # Go to a screen)
|
||||
// - [*] indicates an assertion (e.g. * Check the title)
|
||||
// - Use element testID when selecting an element. Create one if none.
|
||||
// *******************************************************************
|
||||
|
||||
import {
|
||||
Channel,
|
||||
Post,
|
||||
Setup,
|
||||
} from '@support/server_api';
|
||||
import {
|
||||
serverOneUrl,
|
||||
siteOneUrl,
|
||||
} from '@support/test_config';
|
||||
import {
|
||||
ChannelListScreen,
|
||||
ChannelScreen,
|
||||
HomeScreen,
|
||||
LoginScreen,
|
||||
ServerScreen,
|
||||
} from '@support/ui/screen';
|
||||
import {timeouts, wait} from '@support/utils';
|
||||
import {expect} from 'detox';
|
||||
|
||||
describe('Messaging - Channel Mention', () => {
|
||||
const serverOneDisplayName = 'Server 1';
|
||||
const channelsCategory = 'channels';
|
||||
let testChannel: any;
|
||||
let testTeam: any;
|
||||
let testUser: any;
|
||||
|
||||
beforeAll(async () => {
|
||||
const {channel, team, user} = await Setup.apiInit(siteOneUrl);
|
||||
testChannel = channel;
|
||||
testTeam = team;
|
||||
testUser = user;
|
||||
|
||||
// # Log in to server
|
||||
await ServerScreen.connectToServer(serverOneUrl, serverOneDisplayName);
|
||||
await LoginScreen.login(testUser);
|
||||
});
|
||||
|
||||
beforeEach(async () => {
|
||||
// * Verify on channel list screen
|
||||
await ChannelListScreen.toBeVisible();
|
||||
});
|
||||
|
||||
afterAll(async () => {
|
||||
// # Log out
|
||||
await HomeScreen.logout();
|
||||
});
|
||||
|
||||
it('MM-T4875_1 - should post channel mention as channel display name', async () => {
|
||||
// # Open a channel screen and post a channel name mention
|
||||
await ChannelScreen.open(channelsCategory, testChannel.name);
|
||||
const {channel: targetChannel} = await Channel.apiCreateChannel(siteOneUrl, {teamId: testTeam.id});
|
||||
await Channel.apiAddUserToChannel(siteOneUrl, testUser.id, targetChannel.id);
|
||||
const channelNameMention = `~${targetChannel.name}`;
|
||||
await ChannelScreen.postMessage(channelNameMention);
|
||||
|
||||
// * Verify post shows channel display name mention
|
||||
const channelDisplayNameMention = `~${targetChannel.display_name}`;
|
||||
const {post} = await Post.apiGetLastPostInChannel(siteOneUrl, testChannel.id);
|
||||
await ChannelScreen.hasPostMessage(post.id, channelDisplayNameMention);
|
||||
|
||||
// # Go back to channel list screen
|
||||
await ChannelScreen.back();
|
||||
});
|
||||
|
||||
it('MM-T4875_2 - should be able to open joined channel by tapping on channel mention', async () => {
|
||||
// # Open a channel screen, post a channel name mention, and tap on channel display name mention
|
||||
await ChannelScreen.open(channelsCategory, testChannel.name);
|
||||
const {channel: targetChannel} = await Channel.apiCreateChannel(siteOneUrl, {teamId: testTeam.id});
|
||||
await Channel.apiAddUserToChannel(siteOneUrl, testUser.id, targetChannel.id);
|
||||
const channelNameMention = `~${targetChannel.name}`;
|
||||
const channelDisplayNameMention = `~${targetChannel.display_name}`;
|
||||
await ChannelScreen.postMessage(channelNameMention);
|
||||
await element(by.text(channelDisplayNameMention)).tap({x: 5, y: 10});
|
||||
await wait(timeouts.ONE_SEC);
|
||||
|
||||
// * Verify redirected to target channel
|
||||
await expect(ChannelScreen.headerTitle).toHaveText(targetChannel.display_name);
|
||||
|
||||
// # Go back to channel list screen
|
||||
await ChannelScreen.back();
|
||||
});
|
||||
});
|
||||
@@ -41,7 +41,7 @@ describe('Messaging - Emojis and Reactions', () => {
|
||||
|
||||
// # Log in to server
|
||||
await ServerScreen.connectToServer(serverOneUrl, serverOneDisplayName);
|
||||
await LoginScreen.login(user);
|
||||
await LoginScreen.login(testUser);
|
||||
});
|
||||
|
||||
beforeEach(async () => {
|
||||
@@ -72,7 +72,7 @@ describe('Messaging - Emojis and Reactions', () => {
|
||||
|
||||
// # Open emoji picker screen and add a new reaction
|
||||
await EmojiPickerScreen.open();
|
||||
await EmojiPickerScreen.searchInput.typeText('clown_face');
|
||||
await EmojiPickerScreen.searchInput.replaceText('clown_face');
|
||||
await element(by.text('🤡')).tap();
|
||||
|
||||
// * Verify new reaction is added to the message
|
||||
@@ -103,7 +103,7 @@ describe('Messaging - Emojis and Reactions', () => {
|
||||
const {post} = await Post.apiGetLastPostInChannel(siteOneUrl, testChannel.id);
|
||||
await ChannelScreen.openPostOptionsFor(post.id, message);
|
||||
await EmojiPickerScreen.open();
|
||||
await EmojiPickerScreen.searchInput.typeText('fire');
|
||||
await EmojiPickerScreen.searchInput.replaceText('fire');
|
||||
await element(by.text('🔥')).tap();
|
||||
|
||||
// * Verify reaction is added to the message
|
||||
@@ -115,11 +115,11 @@ describe('Messaging - Emojis and Reactions', () => {
|
||||
|
||||
// * Verify user who reacted with the emoji
|
||||
await ReactionsScreen.toBeVisible();
|
||||
const {reactorItemEmojiAliases, reactorItemUserProfilePicture, reactorItemUserDisplayName, reactorItemUserUsername} = ReactionsScreen.getReactorItem(testUser.id, 'fire');
|
||||
const {reactorItemEmojiAliases, reactorItemUserProfilePicture, reactorItemUserDisplayName, reactorItemUsername} = ReactionsScreen.getReactorItem(testUser.id, 'fire');
|
||||
await expect(reactorItemEmojiAliases).toHaveText(':fire:');
|
||||
await expect(reactorItemUserProfilePicture).toBeVisible();
|
||||
await expect(reactorItemUserDisplayName).toHaveText(`${testUser.first_name} ${testUser.last_name}`);
|
||||
await expect(reactorItemUserUsername).toHaveText(` @${testUser.username}`);
|
||||
await expect(reactorItemUsername).toHaveText(` @${testUser.username}`);
|
||||
|
||||
// # Go back to channel list screen
|
||||
await ReactionsScreen.close();
|
||||
@@ -168,7 +168,7 @@ describe('Messaging - Emojis and Reactions', () => {
|
||||
const searchTerm = 'blahblahblahblah';
|
||||
await ChannelScreen.openPostOptionsFor(post.id, message);
|
||||
await EmojiPickerScreen.open();
|
||||
await EmojiPickerScreen.searchInput.typeText(searchTerm);
|
||||
await EmojiPickerScreen.searchInput.replaceText(searchTerm);
|
||||
|
||||
// * Verify empty search state for emoji picker
|
||||
await expect(element(by.text(`No results for “${searchTerm}”`))).toBeVisible();
|
||||
|
||||
67
detox/e2e/test/messaging/markdown_block_quote.e2e.ts
Normal file
67
detox/e2e/test/messaging/markdown_block_quote.e2e.ts
Normal file
@@ -0,0 +1,67 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
// *******************************************************************
|
||||
// - [#] indicates a test step (e.g. # Go to a screen)
|
||||
// - [*] indicates an assertion (e.g. * Check the title)
|
||||
// - Use element testID when selecting an element. Create one if none.
|
||||
// *******************************************************************
|
||||
|
||||
import {
|
||||
Post,
|
||||
Setup,
|
||||
} from '@support/server_api';
|
||||
import {
|
||||
serverOneUrl,
|
||||
siteOneUrl,
|
||||
} from '@support/test_config';
|
||||
import {
|
||||
ChannelListScreen,
|
||||
ChannelScreen,
|
||||
HomeScreen,
|
||||
LoginScreen,
|
||||
ServerScreen,
|
||||
} from '@support/ui/screen';
|
||||
import {expect} from 'detox';
|
||||
|
||||
describe('Messaging - Markdown Block Quote', () => {
|
||||
const serverOneDisplayName = 'Server 1';
|
||||
const channelsCategory = 'channels';
|
||||
let testChannel: any;
|
||||
|
||||
beforeAll(async () => {
|
||||
const {channel, user} = await Setup.apiInit(siteOneUrl);
|
||||
testChannel = channel;
|
||||
|
||||
// # Log in to server
|
||||
await ServerScreen.connectToServer(serverOneUrl, serverOneDisplayName);
|
||||
await LoginScreen.login(user);
|
||||
});
|
||||
|
||||
beforeEach(async () => {
|
||||
// * Verify on channel list screen
|
||||
await ChannelListScreen.toBeVisible();
|
||||
});
|
||||
|
||||
afterAll(async () => {
|
||||
// # Log out
|
||||
await HomeScreen.logout();
|
||||
});
|
||||
|
||||
it('MM-T4898_1 - should be able to display markdown block quote', async () => {
|
||||
// # Open a channel screen and post a markdown block quote
|
||||
const message = 'this is a quote that i am making long so it wraps on mobile this is a quote that i am making long so it wraps on mobile this is a quote that i am making long so it wraps on mobile this is a quote that i am making long so it wraps on mobile';
|
||||
const markdownBlockQuote = `>${message}`;
|
||||
await ChannelScreen.open(channelsCategory, testChannel.name);
|
||||
await ChannelScreen.postMessage(markdownBlockQuote);
|
||||
|
||||
// * Verify markdown block quote is displayed
|
||||
const {post} = await Post.apiGetLastPostInChannel(siteOneUrl, testChannel.id);
|
||||
const {postListPostItemBlockQuote} = ChannelScreen.getPostListPostItem(post.id, message);
|
||||
await expect(postListPostItemBlockQuote).toBeVisible();
|
||||
await expect(element(by.text(message))).toBeVisible();
|
||||
|
||||
// # Go back to channel list screen
|
||||
await ChannelScreen.back();
|
||||
});
|
||||
});
|
||||
88
detox/e2e/test/messaging/markdown_code.e2e.ts
Normal file
88
detox/e2e/test/messaging/markdown_code.e2e.ts
Normal file
@@ -0,0 +1,88 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
// *******************************************************************
|
||||
// - [#] indicates a test step (e.g. # Go to a screen)
|
||||
// - [*] indicates an assertion (e.g. * Check the title)
|
||||
// - Use element testID when selecting an element. Create one if none.
|
||||
// *******************************************************************
|
||||
|
||||
import {
|
||||
Post,
|
||||
Setup,
|
||||
} from '@support/server_api';
|
||||
import {
|
||||
serverOneUrl,
|
||||
siteOneUrl,
|
||||
} from '@support/test_config';
|
||||
import {
|
||||
ChannelListScreen,
|
||||
ChannelScreen,
|
||||
HomeScreen,
|
||||
LoginScreen,
|
||||
ServerScreen,
|
||||
} from '@support/ui/screen';
|
||||
import {expect} from 'detox';
|
||||
|
||||
describe('Messaging - Markdown Code', () => {
|
||||
const serverOneDisplayName = 'Server 1';
|
||||
const channelsCategory = 'channels';
|
||||
let testChannel: any;
|
||||
|
||||
beforeAll(async () => {
|
||||
const {channel, user} = await Setup.apiInit(siteOneUrl);
|
||||
testChannel = channel;
|
||||
|
||||
// # Log in to server
|
||||
await ServerScreen.connectToServer(serverOneUrl, serverOneDisplayName);
|
||||
await LoginScreen.login(user);
|
||||
});
|
||||
|
||||
beforeEach(async () => {
|
||||
// * Verify on channel list screen
|
||||
await ChannelListScreen.toBeVisible();
|
||||
});
|
||||
|
||||
afterAll(async () => {
|
||||
// # Log out
|
||||
await HomeScreen.logout();
|
||||
});
|
||||
|
||||
it('MM-T4895_1 - should be able to display markdown code block', async () => {
|
||||
// # Open a channel screen and post a markdown code block
|
||||
const line1 = 'let x = 10;';
|
||||
const line2 = 'let y = 20;';
|
||||
// eslint-disable-next-line no-template-curly-in-string
|
||||
const line3 = 'console.log(`sum: ${x + y}`);';
|
||||
const message = `${line1}\n${line2}\n${line3}`;
|
||||
const markdownCodeBlock = `\`\`\`\n${message}\n\`\`\``;
|
||||
await ChannelScreen.open(channelsCategory, testChannel.name);
|
||||
await ChannelScreen.postMessage(markdownCodeBlock);
|
||||
|
||||
// * Verify markdown code block is displayed
|
||||
const {post} = await Post.apiGetLastPostInChannel(siteOneUrl, testChannel.id);
|
||||
const {postListPostItemCodeBlock} = ChannelScreen.getPostListPostItem(post.id);
|
||||
await ChannelScreen.flatPostList.scrollTo('bottom');
|
||||
await expect(postListPostItemCodeBlock).toBeVisible();
|
||||
|
||||
// # Go back to channel list screen
|
||||
await ChannelScreen.back();
|
||||
});
|
||||
|
||||
it('MM-T4895_2- should be able to display markdown html', async () => {
|
||||
// # Open a channel screen and post a html
|
||||
const message = '<html>\n<body>\n<span>This is html block</span>\n</body>\n</html>';
|
||||
const markdownHtml = `\`\`\`html\n${message}\n\`\`\``;
|
||||
await ChannelScreen.open(channelsCategory, testChannel.name);
|
||||
await ChannelScreen.postMessage(markdownHtml);
|
||||
|
||||
// * Verify markdown html is displayed
|
||||
const {post} = await Post.apiGetLastPostInChannel(siteOneUrl, testChannel.id);
|
||||
const {postListPostItemCodeBlock} = ChannelScreen.getPostListPostItem(post.id);
|
||||
await ChannelScreen.flatPostList.scrollTo('bottom');
|
||||
await expect(postListPostItemCodeBlock).toBeVisible();
|
||||
|
||||
// # Go back to channel list screen
|
||||
await ChannelScreen.back();
|
||||
});
|
||||
});
|
||||
67
detox/e2e/test/messaging/markdown_heading.e2e.ts
Normal file
67
detox/e2e/test/messaging/markdown_heading.e2e.ts
Normal file
@@ -0,0 +1,67 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
// *******************************************************************
|
||||
// - [#] indicates a test step (e.g. # Go to a screen)
|
||||
// - [*] indicates an assertion (e.g. * Check the title)
|
||||
// - Use element testID when selecting an element. Create one if none.
|
||||
// *******************************************************************
|
||||
|
||||
import {
|
||||
Post,
|
||||
Setup,
|
||||
} from '@support/server_api';
|
||||
import {
|
||||
serverOneUrl,
|
||||
siteOneUrl,
|
||||
} from '@support/test_config';
|
||||
import {
|
||||
ChannelListScreen,
|
||||
ChannelScreen,
|
||||
HomeScreen,
|
||||
LoginScreen,
|
||||
ServerScreen,
|
||||
} from '@support/ui/screen';
|
||||
import {expect} from 'detox';
|
||||
|
||||
describe('Messaging - Markdown Heading', () => {
|
||||
const serverOneDisplayName = 'Server 1';
|
||||
const channelsCategory = 'channels';
|
||||
let testChannel: any;
|
||||
|
||||
beforeAll(async () => {
|
||||
const {channel, user} = await Setup.apiInit(siteOneUrl);
|
||||
testChannel = channel;
|
||||
|
||||
// # Log in to server
|
||||
await ServerScreen.connectToServer(serverOneUrl, serverOneDisplayName);
|
||||
await LoginScreen.login(user);
|
||||
});
|
||||
|
||||
beforeEach(async () => {
|
||||
// * Verify on channel list screen
|
||||
await ChannelListScreen.toBeVisible();
|
||||
});
|
||||
|
||||
afterAll(async () => {
|
||||
// # Log out
|
||||
await HomeScreen.logout();
|
||||
});
|
||||
|
||||
it('MM-T4893_1 - should be able to display markdown heading', async () => {
|
||||
// # Open a channel screen and post a markdown heading
|
||||
const message = 'Heading';
|
||||
const markdownHeading = `## ${message}`;
|
||||
await ChannelScreen.open(channelsCategory, testChannel.name);
|
||||
await ChannelScreen.postMessage(markdownHeading);
|
||||
|
||||
// * Verify markdown heading is displayed
|
||||
const {post} = await Post.apiGetLastPostInChannel(siteOneUrl, testChannel.id);
|
||||
const {postListPostItemHeading} = ChannelScreen.getPostListPostItem(post.id, message);
|
||||
await expect(postListPostItemHeading).toBeVisible();
|
||||
await expect(element(by.text(message))).toBeVisible();
|
||||
|
||||
// # Go back to channel list screen
|
||||
await ChannelScreen.back();
|
||||
});
|
||||
});
|
||||
80
detox/e2e/test/messaging/markdown_image.e2e.ts
Normal file
80
detox/e2e/test/messaging/markdown_image.e2e.ts
Normal file
@@ -0,0 +1,80 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
// *******************************************************************
|
||||
// - [#] indicates a test step (e.g. # Go to a screen)
|
||||
// - [*] indicates an assertion (e.g. * Check the title)
|
||||
// - Use element testID when selecting an element. Create one if none.
|
||||
// *******************************************************************
|
||||
|
||||
import {
|
||||
Post,
|
||||
Setup,
|
||||
} from '@support/server_api';
|
||||
import {
|
||||
serverOneUrl,
|
||||
siteOneUrl,
|
||||
} from '@support/test_config';
|
||||
import {
|
||||
ChannelListScreen,
|
||||
ChannelScreen,
|
||||
HomeScreen,
|
||||
LoginScreen,
|
||||
ServerScreen,
|
||||
} from '@support/ui/screen';
|
||||
import {expect} from 'detox';
|
||||
|
||||
describe('Messaging - Markdown Image', () => {
|
||||
const serverOneDisplayName = 'Server 1';
|
||||
const channelsCategory = 'channels';
|
||||
let testChannel: any;
|
||||
|
||||
beforeAll(async () => {
|
||||
const {channel, user} = await Setup.apiInit(siteOneUrl);
|
||||
testChannel = channel;
|
||||
|
||||
// # Log in to server
|
||||
await ServerScreen.connectToServer(serverOneUrl, serverOneDisplayName);
|
||||
await LoginScreen.login(user);
|
||||
});
|
||||
|
||||
beforeEach(async () => {
|
||||
// * Verify on channel list screen
|
||||
await ChannelListScreen.toBeVisible();
|
||||
});
|
||||
|
||||
afterAll(async () => {
|
||||
// # Log out
|
||||
await HomeScreen.logout();
|
||||
});
|
||||
|
||||
it('MM-T4896_1 - should be able to display markdown image', async () => {
|
||||
// # Open a channel screen and post a markdown image
|
||||
const markdownImage = '';
|
||||
await ChannelScreen.open(channelsCategory, testChannel.name);
|
||||
await ChannelScreen.postMessage(markdownImage);
|
||||
|
||||
// * Verify markdown image is displayed
|
||||
const {post} = await Post.apiGetLastPostInChannel(siteOneUrl, testChannel.id);
|
||||
const {postListPostItemImage} = ChannelScreen.getPostListPostItem(post.id);
|
||||
await expect(postListPostItemImage).toBeVisible();
|
||||
|
||||
// # Go back to channel list screen
|
||||
await ChannelScreen.back();
|
||||
});
|
||||
|
||||
it('MM-T4896_2 - should be able to display markdown image with link', async () => {
|
||||
// # Open a channel screen and post a markdown image with link
|
||||
const markdownImage = '[](https://github.com/mattermost/mattermost-server)';
|
||||
await ChannelScreen.open(channelsCategory, testChannel.name);
|
||||
await ChannelScreen.postMessage(markdownImage);
|
||||
|
||||
// * Verify markdown image with link is displayed
|
||||
const {post} = await Post.apiGetLastPostInChannel(siteOneUrl, testChannel.id);
|
||||
const {postListPostItemImage} = ChannelScreen.getPostListPostItem(post.id);
|
||||
await expect(postListPostItemImage).toBeVisible();
|
||||
|
||||
// # Go back to channel list screen
|
||||
await ChannelScreen.back();
|
||||
});
|
||||
});
|
||||
93
detox/e2e/test/messaging/markdown_latex.e2e.ts
Normal file
93
detox/e2e/test/messaging/markdown_latex.e2e.ts
Normal file
@@ -0,0 +1,93 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
// *******************************************************************
|
||||
// - [#] indicates a test step (e.g. # Go to a screen)
|
||||
// - [*] indicates an assertion (e.g. * Check the title)
|
||||
// - Use element testID when selecting an element. Create one if none.
|
||||
// *******************************************************************
|
||||
|
||||
import {
|
||||
Post,
|
||||
Setup,
|
||||
System,
|
||||
} from '@support/server_api';
|
||||
import {
|
||||
serverOneUrl,
|
||||
siteOneUrl,
|
||||
} from '@support/test_config';
|
||||
import {
|
||||
ChannelListScreen,
|
||||
ChannelScreen,
|
||||
HomeScreen,
|
||||
LoginScreen,
|
||||
ServerScreen,
|
||||
} from '@support/ui/screen';
|
||||
import {expect} from 'detox';
|
||||
|
||||
describe('Messaging - Markdown Latex', () => {
|
||||
const serverOneDisplayName = 'Server 1';
|
||||
const channelsCategory = 'channels';
|
||||
let testChannel: any;
|
||||
|
||||
beforeAll(async () => {
|
||||
System.apiUpdateConfig(siteOneUrl, {
|
||||
ServiceSettings: {
|
||||
EnableLatex: true,
|
||||
EnableInlineLatex: true,
|
||||
},
|
||||
});
|
||||
|
||||
const {channel, user} = await Setup.apiInit(siteOneUrl);
|
||||
testChannel = channel;
|
||||
|
||||
// # Log in to server
|
||||
await ServerScreen.connectToServer(serverOneUrl, serverOneDisplayName);
|
||||
await LoginScreen.login(user);
|
||||
});
|
||||
|
||||
beforeEach(async () => {
|
||||
// * Verify on channel list screen
|
||||
await ChannelListScreen.toBeVisible();
|
||||
});
|
||||
|
||||
afterAll(async () => {
|
||||
// # Log out
|
||||
await HomeScreen.logout();
|
||||
});
|
||||
|
||||
it('MM-T4900_1 - should be able to display markdown latex code block', async () => {
|
||||
// # Open a channel screen and post a markdown latex code block
|
||||
// eslint-disable-next-line no-useless-escape
|
||||
const message = 'X_k = \sum_{n=0}^{2N-1} x_n \cos \left[\frac{\pi}{N} \left(n+\frac{1}{2}+\frac{N}{2}\right) \left(k+\frac{1}{2}\right) \right]';
|
||||
const markdownLatexCodeBlock = `\`\`\`latex\n${message}\n\`\`\``;
|
||||
await ChannelScreen.open(channelsCategory, testChannel.name);
|
||||
await ChannelScreen.postMessage(markdownLatexCodeBlock);
|
||||
|
||||
// * Verify markdown latex code block is displayed
|
||||
const {post} = await Post.apiGetLastPostInChannel(siteOneUrl, testChannel.id);
|
||||
const {postListPostItemLatexCodeBlock} = ChannelScreen.getPostListPostItem(post.id);
|
||||
await ChannelScreen.flatPostList.scrollTo('bottom');
|
||||
await expect(postListPostItemLatexCodeBlock).toBeVisible();
|
||||
|
||||
// # Go back to channel list screen
|
||||
await ChannelScreen.back();
|
||||
});
|
||||
|
||||
it('MM-T4900_2 - should be able to display markdown inline latex -- KNOWN ISSUE: MM-45466', async () => {
|
||||
// # Open a channel screen and post a markdown inline latex
|
||||
// eslint-disable-next-line no-useless-escape
|
||||
const message = 'X_k = \sum_{n=0}^{2N-1} x_n \cos \left[\frac{\pi}{N} \left(n+\frac{1}{2}+\frac{N}{2}\right) \left(k+\frac{1}{2}\right) \right]';
|
||||
const markdownInlineLatex = `$${message}$`;
|
||||
await ChannelScreen.open(channelsCategory, testChannel.name);
|
||||
await ChannelScreen.postMessage(markdownInlineLatex);
|
||||
|
||||
// * Verify markdown inline latex is displayed
|
||||
const {post} = await Post.apiGetLastPostInChannel(siteOneUrl, testChannel.id);
|
||||
const {postListPostItemInlineLatex} = ChannelScreen.getPostListPostItem(post.id);
|
||||
await expect(postListPostItemInlineLatex).toBeVisible();
|
||||
|
||||
// # Go back to channel list screen
|
||||
await ChannelScreen.back();
|
||||
});
|
||||
});
|
||||
102
detox/e2e/test/messaging/markdown_list.e2e.ts
Normal file
102
detox/e2e/test/messaging/markdown_list.e2e.ts
Normal file
@@ -0,0 +1,102 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
// *******************************************************************
|
||||
// - [#] indicates a test step (e.g. # Go to a screen)
|
||||
// - [*] indicates an assertion (e.g. * Check the title)
|
||||
// - Use element testID when selecting an element. Create one if none.
|
||||
// *******************************************************************
|
||||
|
||||
import {
|
||||
Post,
|
||||
Setup,
|
||||
} from '@support/server_api';
|
||||
import {
|
||||
serverOneUrl,
|
||||
siteOneUrl,
|
||||
} from '@support/test_config';
|
||||
import {
|
||||
ChannelListScreen,
|
||||
ChannelScreen,
|
||||
HomeScreen,
|
||||
LoginScreen,
|
||||
ServerScreen,
|
||||
} from '@support/ui/screen';
|
||||
import {expect} from 'detox';
|
||||
|
||||
describe('Messaging - Markdown List', () => {
|
||||
const serverOneDisplayName = 'Server 1';
|
||||
const channelsCategory = 'channels';
|
||||
let testChannel: any;
|
||||
|
||||
beforeAll(async () => {
|
||||
const {channel, user} = await Setup.apiInit(siteOneUrl);
|
||||
testChannel = channel;
|
||||
|
||||
// # Log in to server
|
||||
await ServerScreen.connectToServer(serverOneUrl, serverOneDisplayName);
|
||||
await LoginScreen.login(user);
|
||||
});
|
||||
|
||||
beforeEach(async () => {
|
||||
// * Verify on channel list screen
|
||||
await ChannelListScreen.toBeVisible();
|
||||
});
|
||||
|
||||
afterAll(async () => {
|
||||
// # Log out
|
||||
await HomeScreen.logout();
|
||||
});
|
||||
|
||||
it('MM-T4894_1 - should be able to display markdown bullet list', async () => {
|
||||
// # Open a channel screen and post a markdown bullet list
|
||||
const item1 = 'item one';
|
||||
const item2 = 'item two';
|
||||
const item2SubPoint = 'item two sub-point';
|
||||
const markdownBulletList = `* ${item1}\n- ${item2}\n + ${item2SubPoint}`;
|
||||
await ChannelScreen.open(channelsCategory, testChannel.name);
|
||||
await ChannelScreen.postMessage(markdownBulletList);
|
||||
|
||||
// * Verify markdown bullet list is displayed
|
||||
const {post} = await Post.apiGetLastPostInChannel(siteOneUrl, testChannel.id);
|
||||
const {postListPostItemListItem, postListPostItemListItemBullet} = ChannelScreen.getPostListPostItem(post.id);
|
||||
await expect(postListPostItemListItem.atIndex(0)).toBeVisible();
|
||||
await expect(postListPostItemListItemBullet.atIndex(0)).toHaveText('•');
|
||||
await expect(element(by.text(item1))).toBeVisible();
|
||||
await expect(postListPostItemListItem.atIndex(1)).toBeVisible();
|
||||
await expect(postListPostItemListItemBullet.atIndex(1)).toHaveText('•');
|
||||
await expect(element(by.text(item2))).toBeVisible();
|
||||
await expect(postListPostItemListItem.atIndex(2)).toBeVisible();
|
||||
await expect(postListPostItemListItemBullet.atIndex(2)).toHaveText('◦');
|
||||
await expect(element(by.text(item2SubPoint))).toBeVisible();
|
||||
|
||||
// # Go back to channel list screen
|
||||
await ChannelScreen.back();
|
||||
});
|
||||
|
||||
it('MM-T4894_2 - should be able to display markdown ordered list', async () => {
|
||||
// # Open a channel screen and post a markdown ordered list
|
||||
const item1 = 'Item one';
|
||||
const item2 = 'Item two';
|
||||
const item3 = 'Item three';
|
||||
const markdownOrderedList = `1. ${item1}\n1. ${item2}\n1. ${item3}`;
|
||||
await ChannelScreen.open(channelsCategory, testChannel.name);
|
||||
await ChannelScreen.postMessage(markdownOrderedList);
|
||||
|
||||
// * Verify markdown ordered list is displayed
|
||||
const {post} = await Post.apiGetLastPostInChannel(siteOneUrl, testChannel.id);
|
||||
const {postListPostItemListItem, postListPostItemListItemBullet} = ChannelScreen.getPostListPostItem(post.id);
|
||||
await expect(postListPostItemListItem.atIndex(0)).toBeVisible();
|
||||
await expect(postListPostItemListItemBullet.atIndex(0)).toHaveText('1.');
|
||||
await expect(element(by.text(item1))).toBeVisible();
|
||||
await expect(postListPostItemListItem.atIndex(1)).toBeVisible();
|
||||
await expect(postListPostItemListItemBullet.atIndex(1)).toHaveText('2.');
|
||||
await expect(element(by.text(item2))).toBeVisible();
|
||||
await expect(postListPostItemListItem.atIndex(2)).toBeVisible();
|
||||
await expect(postListPostItemListItemBullet.atIndex(2)).toHaveText('3.');
|
||||
await expect(element(by.text(item3))).toBeVisible();
|
||||
|
||||
// # Go back to channel list screen
|
||||
await ChannelScreen.back();
|
||||
});
|
||||
});
|
||||
68
detox/e2e/test/messaging/markdown_separator.e2e.ts
Normal file
68
detox/e2e/test/messaging/markdown_separator.e2e.ts
Normal file
@@ -0,0 +1,68 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
// *******************************************************************
|
||||
// - [#] indicates a test step (e.g. # Go to a screen)
|
||||
// - [*] indicates an assertion (e.g. * Check the title)
|
||||
// - Use element testID when selecting an element. Create one if none.
|
||||
// *******************************************************************
|
||||
|
||||
import {
|
||||
Post,
|
||||
Setup,
|
||||
} from '@support/server_api';
|
||||
import {
|
||||
serverOneUrl,
|
||||
siteOneUrl,
|
||||
} from '@support/test_config';
|
||||
import {
|
||||
ChannelListScreen,
|
||||
ChannelScreen,
|
||||
HomeScreen,
|
||||
LoginScreen,
|
||||
ServerScreen,
|
||||
} from '@support/ui/screen';
|
||||
import {expect} from 'detox';
|
||||
|
||||
describe('Messaging - Markdown Separator', () => {
|
||||
const serverOneDisplayName = 'Server 1';
|
||||
const channelsCategory = 'channels';
|
||||
let testChannel: any;
|
||||
|
||||
beforeAll(async () => {
|
||||
const {channel, user} = await Setup.apiInit(siteOneUrl);
|
||||
testChannel = channel;
|
||||
|
||||
// # Log in to server
|
||||
await ServerScreen.connectToServer(serverOneUrl, serverOneDisplayName);
|
||||
await LoginScreen.login(user);
|
||||
});
|
||||
|
||||
beforeEach(async () => {
|
||||
// * Verify on channel list screen
|
||||
await ChannelListScreen.toBeVisible();
|
||||
});
|
||||
|
||||
afterAll(async () => {
|
||||
// # Log out
|
||||
await HomeScreen.logout();
|
||||
});
|
||||
|
||||
it('MM-T4897_1 - should be able to display markdown separator', async () => {
|
||||
// # Open a channel screen and post a markdown separator
|
||||
const markdownSeparator = '---';
|
||||
await ChannelScreen.open(channelsCategory, testChannel.name);
|
||||
await Post.apiCreatePost(siteOneUrl, {
|
||||
channelId: testChannel.id,
|
||||
message: markdownSeparator,
|
||||
});
|
||||
|
||||
// * Verify markdown separator is displayed
|
||||
const {post} = await Post.apiGetLastPostInChannel(siteOneUrl, testChannel.id);
|
||||
const {postListPostItemThematicBreak} = ChannelScreen.getPostListPostItem(post.id);
|
||||
await expect(postListPostItemThematicBreak).toBeVisible();
|
||||
|
||||
// # Go back to channel list screen
|
||||
await ChannelScreen.back();
|
||||
});
|
||||
});
|
||||
228
detox/e2e/test/messaging/markdown_table.e2e.ts
Normal file
228
detox/e2e/test/messaging/markdown_table.e2e.ts
Normal file
@@ -0,0 +1,228 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
// *******************************************************************
|
||||
// - [#] indicates a test step (e.g. # Go to a screen)
|
||||
// - [*] indicates an assertion (e.g. * Check the title)
|
||||
// - Use element testID when selecting an element. Create one if none.
|
||||
// *******************************************************************
|
||||
|
||||
import {
|
||||
Post,
|
||||
Setup,
|
||||
} from '@support/server_api';
|
||||
import {
|
||||
serverOneUrl,
|
||||
siteOneUrl,
|
||||
} from '@support/test_config';
|
||||
import {
|
||||
ChannelListScreen,
|
||||
ChannelScreen,
|
||||
HomeScreen,
|
||||
LoginScreen,
|
||||
ServerScreen,
|
||||
TableScreen,
|
||||
} from '@support/ui/screen';
|
||||
import {expect} from 'detox';
|
||||
|
||||
describe('Messaging - Markdown Table', () => {
|
||||
const serverOneDisplayName = 'Server 1';
|
||||
const channelsCategory = 'channels';
|
||||
let testChannel: any;
|
||||
|
||||
beforeAll(async () => {
|
||||
const {channel, user} = await Setup.apiInit(siteOneUrl);
|
||||
testChannel = channel;
|
||||
|
||||
// # Log in to server
|
||||
await ServerScreen.connectToServer(serverOneUrl, serverOneDisplayName);
|
||||
await LoginScreen.login(user);
|
||||
});
|
||||
|
||||
beforeEach(async () => {
|
||||
// * Verify on channel list screen
|
||||
await ChannelListScreen.toBeVisible();
|
||||
});
|
||||
|
||||
afterAll(async () => {
|
||||
// # Log out
|
||||
await HomeScreen.logout();
|
||||
});
|
||||
|
||||
it('MM-T4899_1 - should be able to display markdown table', async () => {
|
||||
// # Open a channel screen and post a markdown table
|
||||
const markdownTable =
|
||||
'| A | B | C |\n' +
|
||||
'|:---|:---|:---|\n' +
|
||||
'| 1 | Name | Toast |\n' +
|
||||
'| 2 | Name | Server |\n';
|
||||
await ChannelScreen.open(channelsCategory, testChannel.name);
|
||||
await Post.apiCreatePost(siteOneUrl, {
|
||||
channelId: testChannel.id,
|
||||
message: markdownTable,
|
||||
});
|
||||
|
||||
// * Verify markdown table is displayed
|
||||
const {post} = await Post.apiGetLastPostInChannel(siteOneUrl, testChannel.id);
|
||||
const {postListPostItemTable} = ChannelScreen.getPostListPostItem(post.id);
|
||||
await expect(postListPostItemTable).toBeVisible();
|
||||
|
||||
// # Go back to channel list screen
|
||||
await ChannelScreen.back();
|
||||
});
|
||||
|
||||
it('MM-T4899_2 - should be able to display markdown table with long text wrapped properly', async () => {
|
||||
// # Open a channel screen and post a markdown table with long text
|
||||
const markdownTable =
|
||||
'| Left header that wraps | Center header that wraps | Right header that wraps |\n' +
|
||||
'| :-- | :-: | --: |\n' +
|
||||
'| Left text that wraps row | Center text that wraps row | Right text that wraps row |\n';
|
||||
await ChannelScreen.open(channelsCategory, testChannel.name);
|
||||
await Post.apiCreatePost(siteOneUrl, {
|
||||
channelId: testChannel.id,
|
||||
message: markdownTable,
|
||||
});
|
||||
|
||||
// * Verify table is displayed with long text wrapped properly
|
||||
const {post} = await Post.apiGetLastPostInChannel(siteOneUrl, testChannel.id);
|
||||
const {postListPostItemTable, postListPostItemTableExpandButton} = ChannelScreen.getPostListPostItem(post.id);
|
||||
await expect(postListPostItemTable).toBeVisible();
|
||||
await expect(element(by.text('Left header that wraps'))).toBeVisible();
|
||||
await expect(element(by.text('Center header that wraps'))).toBeVisible();
|
||||
await expect(element(by.text('Right header that wraps'))).toBeVisible();
|
||||
await expect(element(by.text('Left text that wraps row'))).toBeVisible();
|
||||
await expect(element(by.text('Center text that wraps row'))).toBeVisible();
|
||||
await expect(element(by.text('Right text that wraps row'))).toBeVisible();
|
||||
|
||||
// # Expand to full view
|
||||
await ChannelScreen.flatPostList.scrollTo('bottom');
|
||||
await postListPostItemTableExpandButton.tap();
|
||||
|
||||
// * Verify on table screen with the markdown table
|
||||
await TableScreen.toBeVisible();
|
||||
await expect(element(by.text('Left header that wraps'))).toBeVisible();
|
||||
await expect(element(by.text('Center header that wraps'))).toBeVisible();
|
||||
await expect(element(by.text('Right header that wraps'))).toBeVisible();
|
||||
await expect(element(by.text('Left text that wraps row'))).toBeVisible();
|
||||
await expect(element(by.text('Center text that wraps row'))).toBeVisible();
|
||||
await expect(element(by.text('Right text that wraps row'))).toBeVisible();
|
||||
|
||||
// # Go back to channel list screen
|
||||
await TableScreen.back();
|
||||
await ChannelScreen.back();
|
||||
});
|
||||
|
||||
it('MM-T4899_3 - should be able to open markdown table in full view and allow horizontal scroll', async () => {
|
||||
// # Open a channel screen and post a markdown table with more columns past horizontal view
|
||||
const markdownTable =
|
||||
'| Header | Header | Header | Header | Header | Header | Header | Header HS last |\n' +
|
||||
'| :-- | :-: | --: | --: | :-- | :-: | --: | --: |\n' +
|
||||
'| Left | Center | Right | Right | Left | Center | Right | Right |\n'.repeat(7) +
|
||||
'| Left | Center | Right | Right | Left | Center | Right | Right HS last |\n';
|
||||
await ChannelScreen.open(channelsCategory, testChannel.name);
|
||||
await Post.apiCreatePost(siteOneUrl, {
|
||||
channelId: testChannel.id,
|
||||
message: markdownTable,
|
||||
});
|
||||
|
||||
// * Verify table is displayed with some right columns not visible
|
||||
const {post} = await Post.apiGetLastPostInChannel(siteOneUrl, testChannel.id);
|
||||
const {postListPostItemTable, postListPostItemTableExpandButton} = ChannelScreen.getPostListPostItem(post.id);
|
||||
await expect(postListPostItemTable).toBeVisible();
|
||||
await expect(element(by.text('Header HS last'))).not.toBeVisible();
|
||||
await expect(element(by.text('Right HS last'))).not.toBeVisible();
|
||||
|
||||
// # Expand to full view
|
||||
await ChannelScreen.flatPostList.scrollTo('bottom');
|
||||
await postListPostItemTableExpandButton.tap();
|
||||
await TableScreen.toBeVisible();
|
||||
await expect(element(by.text('Header HS last'))).not.toBeVisible();
|
||||
await expect(element(by.text('Right HS last'))).not.toBeVisible();
|
||||
|
||||
// * Verify table screen is scrollable to the right
|
||||
await TableScreen.tableScrollView.scrollTo('right');
|
||||
await expect(element(by.text('Header HS last'))).toBeVisible();
|
||||
await expect(element(by.text('Right HS last'))).toBeVisible();
|
||||
|
||||
// # Go back to channel list screen
|
||||
await TableScreen.back();
|
||||
await ChannelScreen.back();
|
||||
});
|
||||
|
||||
it('MM-T4899_4 - should be able to open markdown table in full view and allow vertical scroll', async () => {
|
||||
// # Open a channel screen and post a markdown table with more rows past vertical view
|
||||
const markdownTable =
|
||||
'| Header | Header | Header VS last |\n' +
|
||||
'| :-- | :-: | --: |\n' +
|
||||
'| Left | Center | Right |\n'.repeat(30) +
|
||||
'| Left | Center | Right VS last |\n';
|
||||
await ChannelScreen.open(channelsCategory, testChannel.name);
|
||||
await Post.apiCreatePost(siteOneUrl, {
|
||||
channelId: testChannel.id,
|
||||
message: markdownTable,
|
||||
});
|
||||
|
||||
// * Verify table is displayed with some bottom rows not visible
|
||||
const {post} = await Post.apiGetLastPostInChannel(siteOneUrl, testChannel.id);
|
||||
const {postListPostItemTable, postListPostItemTableExpandButton} = ChannelScreen.getPostListPostItem(post.id);
|
||||
await expect(postListPostItemTable).toBeVisible();
|
||||
await expect(element(by.text('Header VS last'))).toBeVisible();
|
||||
await expect(element(by.text('Right VS last'))).not.toBeVisible();
|
||||
|
||||
// # Expand to full view
|
||||
await ChannelScreen.flatPostList.scrollTo('bottom');
|
||||
await postListPostItemTableExpandButton.tap();
|
||||
await TableScreen.toBeVisible();
|
||||
await expect(element(by.text('Header VS last'))).toBeVisible();
|
||||
await expect(element(by.text('Right VS last'))).not.toBeVisible();
|
||||
|
||||
// * Verify table screen is scrollable to the bottom
|
||||
await TableScreen.tableScrollView.scrollTo('bottom');
|
||||
await expect(element(by.text('Header VS last'))).not.toBeVisible();
|
||||
await expect(element(by.text('Right VS last'))).toBeVisible();
|
||||
|
||||
// # Go back to channel list screen
|
||||
await TableScreen.back();
|
||||
await ChannelScreen.back();
|
||||
});
|
||||
|
||||
it('MM-T4899_5 - should be able to open markdown table in full view and allow both horizontal and vertical scrolls', async () => {
|
||||
// # Open a channel screen and post a markdown table with more columns and rows past horizontal and vertical views
|
||||
const markdownTable =
|
||||
'| Header | Header | Header | Header | Header | Header | Header | Header last |\n' +
|
||||
'| :-- | :-: | --: | --: | :-- | :-: | --: | --: |\n' +
|
||||
'| Left | Center | Right | Right | Left | Center | Right | Right |\n'.repeat(30) +
|
||||
'| Left | Center | Right | Right | Left | Center | Right | Right last |\n';
|
||||
await ChannelScreen.open(channelsCategory, testChannel.name);
|
||||
await Post.apiCreatePost(siteOneUrl, {
|
||||
channelId: testChannel.id,
|
||||
message: markdownTable,
|
||||
});
|
||||
|
||||
// * Verify table is displayed with some right columns and bottom rows not visible
|
||||
const {post} = await Post.apiGetLastPostInChannel(siteOneUrl, testChannel.id);
|
||||
const {postListPostItemTable, postListPostItemTableExpandButton} = ChannelScreen.getPostListPostItem(post.id);
|
||||
await expect(postListPostItemTable).toBeVisible();
|
||||
await expect(element(by.text('Header last'))).not.toBeVisible();
|
||||
await expect(element(by.text('Right last'))).not.toBeVisible();
|
||||
|
||||
// # Expand to full view
|
||||
await ChannelScreen.flatPostList.scrollTo('bottom');
|
||||
await postListPostItemTableExpandButton.tap();
|
||||
await TableScreen.toBeVisible();
|
||||
await expect(element(by.text('Header last'))).not.toBeVisible();
|
||||
await expect(element(by.text('Right last'))).not.toBeVisible();
|
||||
|
||||
// * Verify table screen is scrollable to the right and scrollable to the bottom
|
||||
await TableScreen.tableScrollView.scrollTo('right');
|
||||
await expect(element(by.text('Header last'))).toBeVisible();
|
||||
await expect(element(by.text('Right last'))).not.toBeVisible();
|
||||
await TableScreen.tableScrollView.scrollTo('bottom');
|
||||
await expect(element(by.text('Header last'))).not.toBeVisible();
|
||||
await expect(element(by.text('Right last'))).toBeVisible();
|
||||
|
||||
// # Go back to channel list screen
|
||||
await TableScreen.back();
|
||||
await ChannelScreen.back();
|
||||
});
|
||||
});
|
||||
145
detox/e2e/test/messaging/permalink.e2e.ts
Normal file
145
detox/e2e/test/messaging/permalink.e2e.ts
Normal file
@@ -0,0 +1,145 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
// *******************************************************************
|
||||
// - [#] indicates a test step (e.g. # Go to a screen)
|
||||
// - [*] indicates an assertion (e.g. * Check the title)
|
||||
// - Use element testID when selecting an element. Create one if none.
|
||||
// *******************************************************************
|
||||
|
||||
import {
|
||||
Channel,
|
||||
Post,
|
||||
Setup,
|
||||
User,
|
||||
} from '@support/server_api';
|
||||
import {
|
||||
serverOneUrl,
|
||||
siteOneUrl,
|
||||
} from '@support/test_config';
|
||||
import {
|
||||
ChannelListScreen,
|
||||
ChannelScreen,
|
||||
HomeScreen,
|
||||
LoginScreen,
|
||||
PermalinkScreen,
|
||||
ServerScreen,
|
||||
} from '@support/ui/screen';
|
||||
import {getRandomId, timeouts, wait} from '@support/utils';
|
||||
import {expect} from 'detox';
|
||||
|
||||
describe('Messaging - Permalink', () => {
|
||||
const serverOneDisplayName = 'Server 1';
|
||||
const channelsCategory = 'channels';
|
||||
let testChannel: any;
|
||||
let testTeam: any;
|
||||
let testUser: any;
|
||||
|
||||
beforeAll(async () => {
|
||||
const {channel, team, user} = await Setup.apiInit(siteOneUrl);
|
||||
testChannel = channel;
|
||||
testTeam = team;
|
||||
testUser = user;
|
||||
|
||||
// # Log in to server
|
||||
await ServerScreen.connectToServer(serverOneUrl, serverOneDisplayName);
|
||||
await LoginScreen.login(testUser);
|
||||
});
|
||||
|
||||
beforeEach(async () => {
|
||||
// * Verify on channel list screen
|
||||
await ChannelListScreen.toBeVisible();
|
||||
});
|
||||
|
||||
afterAll(async () => {
|
||||
// # Log out
|
||||
await HomeScreen.logout();
|
||||
});
|
||||
|
||||
const expectPermalinkTargetMessage = async (teamName: any, permalinkTargetPost: any, permalinkTargetChannelDiplayName: string) => {
|
||||
// # Open a channel screen, post a permalink to target post, and tap on permalink
|
||||
await ChannelScreen.open(channelsCategory, testChannel.name);
|
||||
const permalinkLabel = `permalink-${getRandomId()}`;
|
||||
const permalinkMessage = `[${permalinkLabel}](/${teamName}/pl/${permalinkTargetPost.id})`;
|
||||
await ChannelScreen.postMessage(permalinkMessage);
|
||||
await element(by.text(permalinkLabel)).tap({x: 5, y: 10});
|
||||
await wait(timeouts.ONE_SEC);
|
||||
|
||||
// * Verify on permalink screen and target post is displayed
|
||||
await PermalinkScreen.toBeVisible();
|
||||
const {postListPostItem: permalinkPostListPostItem} = PermalinkScreen.getPostListPostItem(permalinkTargetPost.id, permalinkTargetPost.message);
|
||||
await expect(permalinkPostListPostItem).toBeVisible();
|
||||
|
||||
// # Jump to recent messages
|
||||
await PermalinkScreen.jumpToRecentMessages();
|
||||
|
||||
// * Verify on channel screen and target post is displayed
|
||||
await expect(ChannelScreen.headerTitle).toHaveText(permalinkTargetChannelDiplayName);
|
||||
const {postListPostItem: channelPostListPostItem} = ChannelScreen.getPostListPostItem(permalinkTargetPost.id, permalinkTargetPost.message);
|
||||
await expect(channelPostListPostItem).toBeVisible();
|
||||
};
|
||||
|
||||
it('MM-T4876_1 - should be able to jump to target public channel post by tapping on permalink with team name', async () => {
|
||||
// # Post a target message in a target public channel
|
||||
const permalinkTargetMessage = `Message ${getRandomId()}`;
|
||||
const {channel: targetChannel} = await Channel.apiCreateChannel(siteOneUrl, {teamId: testTeam.id});
|
||||
await Channel.apiAddUserToChannel(siteOneUrl, testUser.id, targetChannel.id);
|
||||
const permalinkTargetPost = await Post.apiCreatePost(siteOneUrl, {
|
||||
channelId: targetChannel.id,
|
||||
message: permalinkTargetMessage,
|
||||
});
|
||||
|
||||
await expectPermalinkTargetMessage(testTeam.name, permalinkTargetPost.post, targetChannel.display_name);
|
||||
|
||||
// # Go back to channel list screen
|
||||
await ChannelScreen.back();
|
||||
});
|
||||
|
||||
it('MM-T4876_2 - should be able to jump to target public channel post by tapping on permalink with _redirect', async () => {
|
||||
// # Post a target message in a target public channel
|
||||
const permalinkTargetMessage = `Message ${getRandomId()}`;
|
||||
const {channel: targetChannel} = await Channel.apiCreateChannel(siteOneUrl, {teamId: testTeam.id});
|
||||
await Channel.apiAddUserToChannel(siteOneUrl, testUser.id, targetChannel.id);
|
||||
const permalinkTargetPost = await Post.apiCreatePost(siteOneUrl, {
|
||||
channelId: targetChannel.id,
|
||||
message: permalinkTargetMessage,
|
||||
});
|
||||
|
||||
await expectPermalinkTargetMessage('_redirect', permalinkTargetPost.post, targetChannel.display_name);
|
||||
|
||||
// # Go back to channel list screen
|
||||
await ChannelScreen.back();
|
||||
});
|
||||
|
||||
it('MM-T4876_3 - should be able to jump to target DM post by tapping on permalink with team name', async () => {
|
||||
// # Post a target message in a target DM channel
|
||||
const {user: dmOtherUser} = await User.apiCreateUser(siteOneUrl, {prefix: 'testchannel-1'});
|
||||
const {channel: targetChannel} = await Channel.apiCreateDirectChannel(siteOneUrl, [testUser.id, dmOtherUser.id]);
|
||||
const permalinkTargetMessage = `Message ${getRandomId()}`;
|
||||
const permalinkTargetPost = await Post.apiCreatePost(siteOneUrl, {
|
||||
channelId: targetChannel.id,
|
||||
message: permalinkTargetMessage,
|
||||
});
|
||||
|
||||
await expectPermalinkTargetMessage(testTeam.name, permalinkTargetPost.post, dmOtherUser.username);
|
||||
|
||||
// # Go back to channel list screen
|
||||
await ChannelScreen.back();
|
||||
});
|
||||
|
||||
it('MM-T4876_4 - should be able to jump to target DM post by tapping on permalink with _redirect', async () => {
|
||||
// # Post a target message in a target DM channel
|
||||
const {user: dmOtherUser} = await User.apiCreateUser(siteOneUrl, {prefix: 'testchannel-1'});
|
||||
const {channel: targetChannel} = await Channel.apiCreateDirectChannel(siteOneUrl, [testUser.id, dmOtherUser.id]);
|
||||
const permalinkTargetMessage = `Message ${getRandomId()}`;
|
||||
const permalinkTargetPost = await Post.apiCreatePost(siteOneUrl, {
|
||||
channelId: targetChannel.id,
|
||||
message: permalinkTargetMessage,
|
||||
});
|
||||
|
||||
await expectPermalinkTargetMessage('_redirect', permalinkTargetPost.post, dmOtherUser.username);
|
||||
|
||||
// # Go back to channel list screen
|
||||
await ChannelScreen.back();
|
||||
});
|
||||
});
|
||||
162
detox/e2e/test/smoke_test/autocomplete.e2e.ts
Normal file
162
detox/e2e/test/smoke_test/autocomplete.e2e.ts
Normal file
@@ -0,0 +1,162 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
// *******************************************************************
|
||||
// - [#] indicates a test step (e.g. # Go to a screen)
|
||||
// - [*] indicates an assertion (e.g. * Check the title)
|
||||
// - Use element testID when selecting an element. Create one if none.
|
||||
// *******************************************************************
|
||||
|
||||
import {
|
||||
Post,
|
||||
Setup,
|
||||
} from '@support/server_api';
|
||||
import {
|
||||
serverOneUrl,
|
||||
siteOneUrl,
|
||||
} from '@support/test_config';
|
||||
import {Autocomplete} from '@support/ui/component';
|
||||
import {
|
||||
ChannelListScreen,
|
||||
ChannelScreen,
|
||||
HomeScreen,
|
||||
LoginScreen,
|
||||
ServerScreen,
|
||||
} from '@support/ui/screen';
|
||||
import {expect} from 'detox';
|
||||
|
||||
describe('Autocomplete - At-Mention', () => {
|
||||
const serverOneDisplayName = 'Server 1';
|
||||
const channelsCategory = 'channels';
|
||||
let testChannel: any;
|
||||
let testUser: any;
|
||||
|
||||
beforeAll(async () => {
|
||||
const {channel, user} = await Setup.apiInit(siteOneUrl);
|
||||
testChannel = channel;
|
||||
testUser = user;
|
||||
|
||||
// # Log in to server
|
||||
await ServerScreen.connectToServer(serverOneUrl, serverOneDisplayName);
|
||||
await LoginScreen.login(testUser);
|
||||
|
||||
// * Verify on channel list screen
|
||||
await ChannelListScreen.toBeVisible();
|
||||
|
||||
// # Open a channel screen
|
||||
await ChannelScreen.open(channelsCategory, testChannel.name);
|
||||
});
|
||||
|
||||
beforeEach(async () => {
|
||||
// # Clear post input
|
||||
await ChannelScreen.postInput.clearText();
|
||||
|
||||
// * Verify autocomplete is not displayed
|
||||
await Autocomplete.toBeVisible(false);
|
||||
});
|
||||
|
||||
afterAll(async () => {
|
||||
// # Log out
|
||||
await ChannelScreen.back();
|
||||
await HomeScreen.logout();
|
||||
});
|
||||
|
||||
it('MM-T4886_1 - should be able to select and post at-mention suggestion', async () => {
|
||||
// # Type in "@" to activate at-mention autocomplete
|
||||
await ChannelScreen.postInput.typeText('@');
|
||||
await Autocomplete.toBeVisible();
|
||||
|
||||
// * Verify at-mention list is displayed
|
||||
await expect(Autocomplete.sectionAtMentionList).toBeVisible();
|
||||
|
||||
// # Type in username
|
||||
await ChannelScreen.postInput.typeText(testUser.username);
|
||||
|
||||
// * Verify at-mention autocomplete contains associated user suggestion
|
||||
const {atMentionItem} = Autocomplete.getAtMentionItem(testUser.id);
|
||||
await expect(atMentionItem).toBeVisible();
|
||||
|
||||
// # Select and post at-mention suggestion
|
||||
await atMentionItem.tap();
|
||||
await ChannelScreen.sendButton.tap();
|
||||
|
||||
// * Verify at-mention suggestion is posted
|
||||
const {post} = await Post.apiGetLastPostInChannel(siteOneUrl, testChannel.id);
|
||||
await ChannelScreen.hasPostMessage(post.id, `@${testUser.username}`);
|
||||
});
|
||||
|
||||
it('MM-T4886_2 - should be able to select and post channel mention suggestion', async () => {
|
||||
// # Type in "~" to activate channel mention autocomplete
|
||||
await ChannelScreen.postInput.typeText('~');
|
||||
await Autocomplete.toBeVisible();
|
||||
|
||||
// * Verify channel mention list is displayed
|
||||
await expect(Autocomplete.sectionChannelMentionList).toBeVisible();
|
||||
|
||||
// # Type in channel name
|
||||
await ChannelScreen.postInput.typeText(testChannel.name);
|
||||
|
||||
// * Verify channel mention autocomplete contains associated channel suggestion
|
||||
const {channelMentionItem} = Autocomplete.getChannelMentionItem(testChannel.name);
|
||||
await expect(channelMentionItem).toBeVisible();
|
||||
|
||||
// # Select and post channel mention suggestion
|
||||
await channelMentionItem.tap();
|
||||
await ChannelScreen.sendButton.tap();
|
||||
|
||||
// * Verify channel mention suggestion is posted
|
||||
const {post} = await Post.apiGetLastPostInChannel(siteOneUrl, testChannel.id);
|
||||
await ChannelScreen.hasPostMessage(post.id, `~${testChannel.display_name}`);
|
||||
});
|
||||
|
||||
it('MM-T4886_3 - should be able to select and post emoji suggestion', async () => {
|
||||
// # Type in ":" then first 2 characters of emoji name to activate emoji suggestion autocomplete
|
||||
const emojiName = 'fox_face';
|
||||
const emojiNameFirst2Chars = emojiName.substring(0, 2);
|
||||
const emojiName3rdToLastChars = emojiName.substring(2);
|
||||
await ChannelScreen.postInput.typeText(`:${emojiNameFirst2Chars}`);
|
||||
await Autocomplete.toBeVisible();
|
||||
|
||||
// * Verify emoji suggestion list is displayed
|
||||
await expect(Autocomplete.flatEmojiSuggestionList).toBeVisible();
|
||||
|
||||
// # Type in 3rd to last characters of emoji name
|
||||
await ChannelScreen.postInput.typeText(emojiName3rdToLastChars);
|
||||
|
||||
// * Verify emoji suggestion autocomplete contains associated emoji suggestion
|
||||
const {emojiSuggestionItem} = Autocomplete.getEmojiSuggestionItem(emojiName);
|
||||
await expect(emojiSuggestionItem).toBeVisible();
|
||||
|
||||
// # Select and post emoji suggestion
|
||||
await emojiSuggestionItem.tap();
|
||||
await ChannelScreen.sendButton.tap();
|
||||
|
||||
// * Verify emoji suggestion is posted
|
||||
const {post} = await Post.apiGetLastPostInChannel(siteOneUrl, testChannel.id);
|
||||
await ChannelScreen.hasPostMessage(post.id, '🦊');
|
||||
});
|
||||
|
||||
it('MM-T4886_4 - should be able to select and post slash suggestion', async () => {
|
||||
// # Type in "/" to activate slash suggestion autocomplete
|
||||
await ChannelScreen.postInput.typeText('/');
|
||||
await Autocomplete.toBeVisible();
|
||||
|
||||
// * Verify slash suggestion list is displayed
|
||||
await expect(Autocomplete.flatSlashSuggestionList).toBeVisible();
|
||||
|
||||
// # Type in slash command name
|
||||
const slashCommand = 'away';
|
||||
await ChannelScreen.postInput.typeText(slashCommand);
|
||||
|
||||
// * Verify slash suggestion autocomplete contains associated slash command suggestion
|
||||
const {slashSuggestionItem} = Autocomplete.getSlashSuggestionItem(slashCommand);
|
||||
await expect(slashSuggestionItem).toBeVisible();
|
||||
|
||||
// # Select and post slash suggestion
|
||||
await slashSuggestionItem.tap();
|
||||
await ChannelScreen.sendButton.tap();
|
||||
|
||||
// * Verify slash suggestion is posted
|
||||
await expect(element(by.text('You are now away'))).toBeVisible();
|
||||
});
|
||||
});
|
||||
@@ -8,6 +8,7 @@
|
||||
// *******************************************************************
|
||||
|
||||
import {
|
||||
Channel,
|
||||
Post,
|
||||
Setup,
|
||||
} from '@support/server_api';
|
||||
@@ -35,14 +36,18 @@ describe('Smoke Test - Messaging', () => {
|
||||
const savedText = 'Saved';
|
||||
const pinnedText = 'Pinned';
|
||||
let testChannel: any;
|
||||
let testTeam: any;
|
||||
let testUser: any;
|
||||
|
||||
beforeAll(async () => {
|
||||
const {channel, user} = await Setup.apiInit(siteOneUrl);
|
||||
const {channel, team, user} = await Setup.apiInit(siteOneUrl);
|
||||
testChannel = channel;
|
||||
testTeam = team;
|
||||
testUser = user;
|
||||
|
||||
// # Log in to server
|
||||
await ServerScreen.connectToServer(serverOneUrl, serverOneDisplayName);
|
||||
await LoginScreen.login(user);
|
||||
await LoginScreen.login(testUser);
|
||||
});
|
||||
|
||||
beforeEach(async () => {
|
||||
@@ -135,7 +140,7 @@ describe('Smoke Test - Messaging', () => {
|
||||
// # Open post options for message, open emoji picker screen, and add a reaction
|
||||
await ChannelScreen.openPostOptionsFor(post.id, resolvedMessage);
|
||||
await EmojiPickerScreen.open();
|
||||
await EmojiPickerScreen.searchInput.typeText('clown_face');
|
||||
await EmojiPickerScreen.searchInput.replaceText('clown_face');
|
||||
await element(by.text('🤡')).tap();
|
||||
|
||||
// * Verify reaction is added to the message
|
||||
@@ -198,4 +203,64 @@ describe('Smoke Test - Messaging', () => {
|
||||
// # Go back to channel list screen
|
||||
await ChannelScreen.back();
|
||||
});
|
||||
|
||||
it('MM-T4786_5 - should be able to post a message with at-mention and channel mention', async () => {
|
||||
// # Open a channel screen and post a message with at-mention and channel mention
|
||||
const {channel: targetChannel} = await Channel.apiCreateChannel(siteOneUrl, {teamId: testTeam.id});
|
||||
await Channel.apiAddUserToChannel(siteOneUrl, testUser.id, targetChannel.id);
|
||||
const message = `Message @${testUser.username} ~${targetChannel.name}`;
|
||||
await ChannelScreen.open(channelsCategory, testChannel.name);
|
||||
await ChannelScreen.postMessage(message);
|
||||
|
||||
// * Verify at-mention is posted as lowercase and channel mention is posted as display name
|
||||
const {post} = await Post.apiGetLastPostInChannel(siteOneUrl, testChannel.id);
|
||||
await ChannelScreen.hasPostMessage(post.id, `Message @${testUser.username.toLowerCase()} ~${targetChannel.display_name}`);
|
||||
|
||||
// # Go back to channel list screen
|
||||
await ChannelScreen.back();
|
||||
});
|
||||
|
||||
it('MM-T4786_6 - should be able to post labeled permalink and labeled channel link', async () => {
|
||||
// # Post a target message in a target channel
|
||||
const permalinkTargetMessage = `Message ${getRandomId()}`;
|
||||
const {channel: targetChannel} = await Channel.apiCreateChannel(siteOneUrl, {teamId: testTeam.id});
|
||||
await Channel.apiAddUserToChannel(siteOneUrl, testUser.id, targetChannel.id);
|
||||
const permalinkTargetPost = await Post.apiCreatePost(siteOneUrl, {
|
||||
channelId: targetChannel.id,
|
||||
message: permalinkTargetMessage,
|
||||
});
|
||||
|
||||
// # Open a channel screen and post a message with labeled permalink to the target message and labeled channel link to the target channel
|
||||
await ChannelScreen.open(channelsCategory, testChannel.name);
|
||||
const permalinkLabel = `permalink-${getRandomId()}`;
|
||||
const permalinkMessage = `[${permalinkLabel}](/${testTeam.name}/pl/${permalinkTargetPost.id})`;
|
||||
const channelLinkLabel = `channel-link-${getRandomId()}`;
|
||||
const channelLinkMessage = `[${channelLinkLabel}](${serverOneUrl}/${testTeam.name}/channels/${targetChannel.name})`;
|
||||
const message = `Message ${permalinkMessage} ${channelLinkMessage}`;
|
||||
await ChannelScreen.postMessage(message);
|
||||
|
||||
// * Verify permalink and channel link are posted as labeled links
|
||||
const {post} = await Post.apiGetLastPostInChannel(siteOneUrl, testChannel.id);
|
||||
await ChannelScreen.hasPostMessage(post.id, `Message ${permalinkLabel} ${channelLinkLabel}`);
|
||||
|
||||
// # Go back to channel list screen
|
||||
await ChannelScreen.back();
|
||||
});
|
||||
|
||||
it('MM-T4786_7 - should be able to post a message with markdown', async () => {
|
||||
// # Open a channel screen and post a message with markdown
|
||||
const message = `Message ${getRandomId()}`;
|
||||
const markdown = `#### ${message}`;
|
||||
await ChannelScreen.open(channelsCategory, testChannel.name);
|
||||
await ChannelScreen.postMessage(markdown);
|
||||
|
||||
// * Verify message with markdown is posted
|
||||
const {post} = await Post.apiGetLastPostInChannel(siteOneUrl, testChannel.id);
|
||||
const {postListPostItemHeading} = ChannelScreen.getPostListPostItem(post.id, message);
|
||||
await expect(postListPostItemHeading).toBeVisible();
|
||||
await expect(element(by.text(message))).toBeVisible();
|
||||
|
||||
// # Go back to channel list screen
|
||||
await ChannelScreen.back();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -47,7 +47,7 @@ describe('Threads - Global Threads', () => {
|
||||
|
||||
// # Log in to server
|
||||
await ServerScreen.connectToServer(serverOneUrl, serverOneDisplayName);
|
||||
await LoginScreen.login(user);
|
||||
await LoginScreen.login(testUser);
|
||||
});
|
||||
|
||||
beforeEach(async () => {
|
||||
|
||||
@@ -113,7 +113,7 @@ describe('Threads - Open Thread in Channel', () => {
|
||||
await expect(GlobalThreadsScreen.getThreadItem(parentPost.id)).toBeVisible();
|
||||
|
||||
// # Open thread options for thread, tap on copy link option, go back to channel list screen, go to another channel, post the permalink, and tap on permalink
|
||||
const permalinkLabel = `permalink-${Date.now().toString()}`;
|
||||
const permalinkLabel = `permalink-${getRandomId()}`;
|
||||
const permalinkMessage = `[${permalinkLabel}](/_redirect/pl/${parentPost.id})`;
|
||||
await GlobalThreadsScreen.back();
|
||||
await ChannelScreen.open(channelsCategory, 'off-topic');
|
||||
|
||||
Reference in New Issue
Block a user