Detox/E2E: Edit Profile, Custom Status, and Settings e2e tests in Gekidou

This commit is contained in:
Joseph Baylon
2022-08-25 17:42:41 -07:00
parent c051e94b6e
commit 8d7b15da51
79 changed files with 2700 additions and 109 deletions

View File

@@ -181,12 +181,14 @@ const ChannelListItem = ({
displayName = formatMessage({id: 'channel_header.directchannel.you', defaultMessage: '{displayName} (you)'}, {displayName});
}
const channelItemTestId = `${testID}.${channel.name}`;
return (
<TouchableOpacity onPress={handleOnPress}>
<>
<View
style={containerStyle}
testID={`${testID}.${channel.name}`}
testID={channelItemTestId}
>
<View style={styles.wrapper}>
<ChannelIcon
@@ -207,7 +209,7 @@ const ChannelListItem = ({
ellipsizeMode='tail'
numberOfLines={1}
style={textStyles}
testID={`${testID}.${channel.name}.display_name`}
testID={`${channelItemTestId}.display_name`}
>
{displayName}
</Text>
@@ -216,7 +218,7 @@ const ChannelListItem = ({
ellipsizeMode='tail'
numberOfLines={1}
style={[styles.teamName, isMuted && styles.teamNameMuted]}
testID={`${testID}.${channel.name}.team_display_name`}
testID={`${channelItemTestId}.team_display_name`}
>
{teamDisplayName}
</Text>
@@ -225,6 +227,7 @@ const ChannelListItem = ({
{Boolean(teammateId) &&
<CustomStatus
isInfo={isInfo}
testID={channelItemTestId}
userId={teammateId!}
/>
}
@@ -233,7 +236,7 @@ const ChannelListItem = ({
ellipsizeMode='tail'
numberOfLines={1}
style={[styles.teamName, styles.teamNameTablet, isMuted && styles.teamNameMuted]}
testID={`${testID}.${channel.name}.team_display_name`}
testID={`${channelItemTestId}.team_display_name`}
>
{teamDisplayName}
</Text>

View File

@@ -11,6 +11,7 @@ type Props = {
customStatusExpired: boolean;
isCustomStatusEnabled: boolean;
isInfo?: boolean;
testID?: string;
}
const style = StyleSheet.create({
@@ -24,7 +25,7 @@ const style = StyleSheet.create({
},
});
const CustomStatus = ({customStatus, customStatusExpired, isCustomStatusEnabled, isInfo}: Props) => {
const CustomStatus = ({customStatus, customStatusExpired, isCustomStatusEnabled, isInfo, testID}: Props) => {
const showCustomStatusEmoji = Boolean(isCustomStatusEnabled && customStatus?.emoji && !customStatusExpired);
if (!showCustomStatusEmoji) {
@@ -35,7 +36,7 @@ const CustomStatus = ({customStatus, customStatusExpired, isCustomStatusEnabled,
<CustomStatusEmoji
customStatus={customStatus!}
style={[style.customStatusEmoji, isInfo && style.info]}
testID={`channel_item.custom_status.${customStatus!.emoji}-${customStatus!.text}`}
testID={testID}
/>
);
};

View File

@@ -2,7 +2,7 @@
exports[`components/custom_status/custom_status_emoji should match snapshot 1`] = `
<View
testID="custom_status_emoji.calendar"
testID="test.custom_status.custom_status_emoji.calendar"
>
<Text
style={
@@ -22,7 +22,7 @@ exports[`components/custom_status/custom_status_emoji should match snapshot 1`]
exports[`components/custom_status/custom_status_emoji should match snapshot with props 1`] = `
<View
testID="custom_status_emoji.calendar"
testID="test.custom_status.custom_status_emoji.calendar"
>
<Text
style={

View File

@@ -23,7 +23,10 @@ describe('components/custom_status/custom_status_emoji', () => {
};
it('should match snapshot', () => {
const wrapper = renderWithEverything(
<CustomStatusEmoji customStatus={customStatus}/>,
<CustomStatusEmoji
customStatus={customStatus}
testID='test'
/>,
{database},
);
expect(wrapper.toJSON()).toMatchSnapshot();
@@ -34,6 +37,7 @@ describe('components/custom_status/custom_status_emoji', () => {
<CustomStatusEmoji
customStatus={customStatus}
emojiSize={34}
testID='test'
/>,
{database},
);

View File

@@ -14,16 +14,15 @@ interface ComponentProps {
}
const CustomStatusEmoji = ({customStatus, emojiSize = 16, style, testID}: ComponentProps) => {
const testIdPrefix = testID ? `${testID}.` : '';
if (customStatus.emoji) {
return (
<View
style={style}
testID={`${testIdPrefix}custom_status_emoji.${customStatus.emoji}`}
testID={`${testID}.custom_status.custom_status_emoji.${customStatus.emoji}`}
>
<Emoji
size={emojiSize}
emojiName={customStatus.emoji!}
emojiName={customStatus.emoji}
/>
</View>
);

View File

@@ -12,6 +12,7 @@ interface ComponentProps {
textStyle?: TextStyle;
ellipsizeMode?: 'head' | 'middle' | 'tail' | 'clip';
numberOfLines?: number;
testID?: string;
}
const getStyleSheet = makeStyleSheetFromTheme((theme: Theme) => {
@@ -25,11 +26,12 @@ const getStyleSheet = makeStyleSheetFromTheme((theme: Theme) => {
};
});
const CustomStatusText = ({text, theme, textStyle, ellipsizeMode, numberOfLines}: ComponentProps) => (
const CustomStatusText = ({text, theme, textStyle, ellipsizeMode, numberOfLines, testID}: ComponentProps) => (
<Text
style={[getStyleSheet(theme).label, textStyle]}
ellipsizeMode={ellipsizeMode}
numberOfLines={numberOfLines}
testID={testID}
>
{text}
</Text>

View File

@@ -266,7 +266,12 @@ const OptionItem = ({
{
Boolean(info) &&
<View style={styles.infoContainer}>
<Text style={[styles.info, destructive && {color: theme.dndIndicator}]}>{info}</Text>
<Text
style={[styles.info, destructive && {color: theme.dndIndicator}]}
testID={`${testID}.info`}
>
{info}
</Text>
</View>
}
{actionComponent}

View File

@@ -160,7 +160,7 @@ const UserItem = ({
<CustomStatusEmoji
customStatus={customStatus!}
style={style.icon}
testID={testID}
testID={userItemTestId}
/>
)}
{shared && (

View File

@@ -199,6 +199,7 @@ const ChannelHeader = ({
customStatus={customStatus}
emojiSize={13}
style={styles.customStatusEmoji}
testID='channel_header'
/>
}
<View style={styles.customStatusText}>
@@ -206,6 +207,7 @@ const ChannelHeader = ({
numberOfLines={1}
ellipsizeMode='tail'
style={styles.subtitle}
testID='channel_header.custom_status.custom_status_text'
>
{customStatus.text}
</Text>

View File

@@ -91,7 +91,10 @@ const Extra = ({channelId, createdAt, createdBy, customStatus, header}: Props) =
/>
<View style={styles.customStatus}>
{Boolean(customStatus?.emoji) &&
<View style={styles.customStatusEmoji}>
<View
style={styles.customStatusEmoji}
testID={`channel_info.custom_status.custom_status_emoji.${customStatus?.emoji}`}
>
<Emoji
emojiName={customStatus!.emoji!}
size={24}
@@ -99,7 +102,10 @@ const Extra = ({channelId, createdAt, createdBy, customStatus, header}: Props) =
</View>
}
{Boolean(customStatus?.text) &&
<Text style={styles.customStatusLabel}>
<Text
style={styles.customStatusLabel}
testID='channel_info.custom_status.custom_status_text'
>
{customStatus?.text}
</Text>
}
@@ -112,6 +118,7 @@ const Extra = ({channelId, createdAt, createdBy, customStatus, header}: Props) =
showPrefix={true}
showToday={true}
showTimeCompulsory={false}
testID={`channel_info.custom_status.custom_status_duration.${customStatus?.duration}.custom_status_expiry`}
/>
}
</View>

View File

@@ -61,6 +61,7 @@ const ClearAfter = ({duration, expiresAt, onOpenClearAfterModal, theme}: Props)
textStyles={style.customStatusExpiry}
theme={theme}
time={expiresAt.toDate()}
testID={`custom_status.clear_after.custom_status_duration.${duration}.custom_status_expiry`}
/>
</View>
);
@@ -71,19 +72,17 @@ const ClearAfter = ({duration, expiresAt, onOpenClearAfterModal, theme}: Props)
id={CST[duration].id}
defaultMessage={CST[duration].defaultMessage}
style={style.expiryTime}
testID={`custom_status.clear_after.custom_status_duration.${duration}.custom_status_expiry`}
/>
);
};
return (
<TouchableOpacity
testID={'custom_status.clear_after.action'}
onPress={onOpenClearAfterModal}
testID={`custom_status.clear_after.custom_status_duration.${duration}.action`}
>
<View
testID={`custom_status.duration.${duration}`}
style={style.inputContainer}
>
<View style={style.inputContainer}>
<Text style={style.expiryTimeLabel}>{intl.formatMessage({id: 'mobile.custom_status.clear_after', defaultMessage: 'Clear After'})}</Text>
{renderClearAfterTime()}
<CompassIcon

View File

@@ -33,7 +33,7 @@ const CustomStatusEmoji = ({emoji, isStatusSet, onPress, theme}: Props) => {
const style = getStyleSheet(theme);
return (
<TouchableOpacity
testID={`custom_status.emoji.${isStatusSet ? (emoji || 'speech_balloon') : 'default'}`}
testID={`custom_status.custom_status_emoji.${isStatusSet ? (emoji || 'speech_balloon') : 'default'}`}
onPress={onPress}
style={style.iconContainer}
>

View File

@@ -68,7 +68,7 @@ const CustomStatusInput = ({emoji, isStatusSet, onChangeText, onClearHandle, onO
theme={theme}
/>
<TextInput
testID='custom_status.input'
testID='custom_status.status.input'
autoCapitalize='none'
autoCorrect={false}
blurOnSubmit={false}
@@ -88,7 +88,7 @@ const CustomStatusInput = ({emoji, isStatusSet, onChangeText, onClearHandle, onO
{isStatusSet ? (
<View
style={style.clearButton}
testID='custom_status.input.clear.button'
testID='custom_status.status.input.clear.button'
>
<ClearButton
handlePress={onClearHandle}

View File

@@ -76,6 +76,7 @@ const CustomStatusSuggestion = ({duration, emoji, expires_at, handleClear, handl
}, []);
const showCustomStatus = Boolean(duration && duration !== 'date_and_time' && isExpirySupported);
const customStatusSuggestionTestId = `custom_status.custom_status_suggestion.${text}`;
const clearButton =
handleClear && expires_at ? (
@@ -85,19 +86,22 @@ const CustomStatusSuggestion = ({duration, emoji, expires_at, handleClear, handl
theme={theme}
iconName='close'
size={18}
testID='custom_status_suggestion.clear.button'
testID={`${customStatusSuggestionTestId}.clear.button`}
/>
</View>
) : null;
return (
<TouchableOpacity
testID={`custom_status_suggestion.${text}`}
onPress={handleClick}
testID={customStatusSuggestionTestId}
>
<View style={style.container}>
{emoji && (
<View style={style.iconContainer}>
<View
style={style.iconContainer}
testID={`${customStatusSuggestionTestId}.custom_status_emoji.${emoji}`}
>
<Emoji
emojiName={emoji}
size={20}
@@ -112,6 +116,7 @@ const CustomStatusSuggestion = ({duration, emoji, expires_at, handleClear, handl
text={text}
theme={theme}
textStyle={style.customStatusText}
testID={`${customStatusSuggestionTestId}.custom_status_text`}
/>
</View>
)}
@@ -121,6 +126,7 @@ const CustomStatusSuggestion = ({duration, emoji, expires_at, handleClear, handl
text={intl.formatMessage(CST[duration!])}
theme={theme}
textStyle={style.customStatusDuration}
testID={`${customStatusSuggestionTestId}.custom_status_duration.${duration}`}
/>
</View>
)}

View File

@@ -91,11 +91,13 @@ const ClearAfterMenuItem = ({currentUser, duration, expiryTime = '', handleItemC
handleItemClick(duration, expiresAt.toISOString());
}, [handleItemClick, duration]);
const clearAfterMenuItemTestId = `custom_status_clear_after.menu_item.${duration}`;
return (
<View>
<TouchableOpacity
testID={`clear_after.menu_item.${duration}`}
onPress={handleClick}
testID={clearAfterMenuItemTestId}
>
<View style={style.container}>
<View style={style.textContainer}>
@@ -103,6 +105,7 @@ const ClearAfterMenuItem = ({currentUser, duration, expiryTime = '', handleItemC
text={expiryMenuItems[duration]}
theme={theme}
textStyle={{color: theme.centerChannelColor}}
testID={`${clearAfterMenuItemTestId}.custom_status_text`}
/>
{isSelected && (
<View style={style.rightPosition}>
@@ -121,6 +124,7 @@ const ClearAfterMenuItem = ({currentUser, duration, expiryTime = '', handleItemC
textStyles={style.customStatusExpiry}
showTimeCompulsory={true}
showToday={true}
testID={`${clearAfterMenuItemTestId}.custom_status_expiry`}
/>
</View>
)}

View File

@@ -82,13 +82,13 @@ const DateTimeSelector = ({timezone, handleChange, isMilitaryTime, theme}: Props
<View style={styles.container}>
<View style={styles.buttonContainer}>
<Button
testID={'clear_after.menu_item.date_and_time.button.date'}
testID={'custom_status_clear_after.menu_item.date_and_time.button.date'}
onPress={showDatepicker}
title='Select Date'
color={theme.buttonBg}
/>
<Button
testID={'clear_after.menu_item.date_and_time.button.time'}
testID={'custom_status_clear_after.menu_item.date_and_time.button.time'}
onPress={showTimepicker}
title='Select Time'
color={theme.buttonBg}
@@ -96,7 +96,7 @@ const DateTimeSelector = ({timezone, handleChange, isMilitaryTime, theme}: Props
</View>
{show && (
<DateTimePicker
testID='clear_after.date_time_picker'
testID='custom_status_clear_after.date_time_picker'
value={date.toDate()}
mode={mode}
is24Hour={isMilitaryTime}

View File

@@ -76,7 +76,7 @@ class ClearAfterModal extends NavigationComponent<Props, State> {
enabled: true,
id: CLEAR_AFTER,
showAsAction: 'always',
testID: 'clear_after.done.button',
testID: 'custom_status_clear_after.done.button',
text: props.intl.formatMessage({
id: 'mobile.custom_status.modal_confirm',
defaultMessage: 'Done',
@@ -173,7 +173,7 @@ class ClearAfterModal extends NavigationComponent<Props, State> {
}
return (
<View testID='clear_after.menu'>
<View testID='custom_status_clear_after.menu'>
<View style={style.block}>{clearAfterMenu}</View>
</View>
);
@@ -186,7 +186,7 @@ class ClearAfterModal extends NavigationComponent<Props, State> {
return (
<SafeAreaView
style={style.container}
testID='clear_after.screen'
testID='custom_status_clear_after.screen'
>
<KeyboardAwareScrollView bounces={false}>
<View style={style.scrollView}>

View File

@@ -93,7 +93,7 @@ const EmailField = ({
>
<Text
style={style.text}
testID='edit_profile_form.email.description'
testID='edit_profile_form.email.input.description'
>
{fieldDescription}
</Text>

View File

@@ -54,6 +54,7 @@ const CustomLabel = ({customStatus, isCustomStatusExpirySupported, isStatusSet,
<CustomStatusText
isStatusSet={Boolean(isStatusSet)}
customStatus={customStatus}
testID='account.custom_status.custom_status_text'
/>
{Boolean(isStatusSet && isCustomStatusExpirySupported && customStatus?.duration) && (
<CustomStatusExpiry
@@ -62,7 +63,7 @@ const CustomLabel = ({customStatus, isCustomStatusExpirySupported, isStatusSet,
textStyles={styles.customStatusExpiryText}
withinBrackets={true}
showPrefix={true}
testID={'custom_status.expiry'}
testID={`account.custom_status.custom_status_duration.${customStatus.duration}.custom_status_expiry`}
/>
)}
</View>
@@ -71,6 +72,7 @@ const CustomLabel = ({customStatus, isCustomStatusExpirySupported, isStatusSet,
id={'custom_status.failure_message'}
defaultMessage='Failed to update status. Try again'
style={styles.retryMessage}
testID='account.custom_status.failure_message'
/>
)}
{isStatusSet && (
@@ -78,7 +80,7 @@ const CustomLabel = ({customStatus, isCustomStatusExpirySupported, isStatusSet,
<ClearButton
handlePress={onClearCustomStatus}
theme={theme}
testID='settings.sidebar.custom_status.action.clear'
testID='account.custom_status.clear.button'
/>
</View>
)}

View File

@@ -28,7 +28,7 @@ const CustomStatusEmoji = ({emoji, isStatusSet}: CustomStatusEmojiProps) => {
return (
<View
testID={`custom_status.emoji.${isStatusSet ? emoji : 'default'}`}
testID={`account.custom_status.custom_status_emoji.${isStatusSet ? emoji : 'default'}`}
>
{isStatusSet && emoji ? (
<Emoji

View File

@@ -12,6 +12,7 @@ import {typography} from '@utils/typography';
type CustomStatusTextProps = {
customStatus?: UserCustomStatus;
isStatusSet: boolean;
testID?: string;
};
const getStyleSheet = makeStyleSheetFromTheme((theme: Theme) => ({
@@ -21,7 +22,7 @@ const getStyleSheet = makeStyleSheetFromTheme((theme: Theme) => ({
},
}));
const CustomStatusText = ({isStatusSet, customStatus}: CustomStatusTextProps) => {
const CustomStatusText = ({isStatusSet, customStatus, testID}: CustomStatusTextProps) => {
const theme = useTheme();
const styles = getStyleSheet(theme);
@@ -44,6 +45,7 @@ const CustomStatusText = ({isStatusSet, customStatus}: CustomStatusTextProps) =>
text={text}
theme={theme}
textStyle={styles.text}
testID={testID}
/>
);
};

View File

@@ -184,35 +184,59 @@ const About = ({config, license}: AboutProps) => {
</View>
<View style={styles.infoContainer}>
<View style={styles.group}>
<Text style={styles.leftHeading}>
<Text
style={styles.leftHeading}
testID='about.app_version.title'
>
{intl.formatMessage({id: 'settings.about.version', defaultMessage: 'App Version:'})}
</Text>
<Text style={styles.rightHeading}>
<Text
style={styles.rightHeading}
testID='about.app_version.value'
>
{intl.formatMessage({id: 'settings.about.build', defaultMessage: '{version} (Build {number})'},
{version: DeviceInfo.getVersion(), number: DeviceInfo.getBuildNumber()})}
</Text>
</View>
<View style={styles.group}>
<Text style={styles.leftHeading}>
<Text
style={styles.leftHeading}
testID='about.server_version.title'
>
{intl.formatMessage({id: 'settings.about.server.version.desc', defaultMessage: 'Server Version:'})}
</Text>
<Text style={styles.rightHeading}>
<Text
style={styles.rightHeading}
testID='about.server_version.value'
>
{intl.formatMessage({id: serverVersion.id, defaultMessage: serverVersion.defaultMessage}, serverVersion.values)}
</Text>
</View>
<View style={styles.group}>
<Text style={styles.leftHeading}>
<Text
style={styles.leftHeading}
testID='about.database.title'
>
{intl.formatMessage({id: 'settings.about.database', defaultMessage: 'Database:'})}
</Text>
<Text style={styles.rightHeading}>
<Text
style={styles.rightHeading}
testID='about.database.value'
>
{intl.formatMessage({id: 'settings.about.database.value', defaultMessage: `${config.SQLDriverName}`})}
</Text>
</View>
<View style={styles.group}>
<Text style={styles.leftHeading}>
<Text
style={styles.leftHeading}
testID='about.database_schema_version.title'
>
{intl.formatMessage({id: 'settings.about.database.schema', defaultMessage: 'Database Schema Version:'})}
</Text>
<Text style={styles.rightHeading}>
<Text
style={styles.rightHeading}
testID='about.database_schema_version.value'
>
{intl.formatMessage({
id: 'settings.about.database.schema.value',
defaultMessage: `${config.SchemaVersion}`,

View File

@@ -57,7 +57,7 @@ const LearnMore = ({config, onHandleAboutEnterprise, onHandleAboutTeam}: LearnMo
id={id}
defaultMessage={defaultMessage}
style={style.learn}
testID='about.learn_more'
testID='about.learn_more.text'
/>
<TouchableOpacity onPress={onPress}>
<Text

View File

@@ -57,7 +57,7 @@ const DisplayClock = ({componentId, currentUserId, hasMilitaryTimeFormat}: Displ
useAndroidHardwareBackHandler(componentId, saveClockDisplayPreference);
return (
<SettingContainer testID='display_clock'>
<SettingContainer testID='clock_display_settings'>
<SettingBlock
disableHeader={true}
>
@@ -66,7 +66,7 @@ const DisplayClock = ({componentId, currentUserId, hasMilitaryTimeFormat}: Displ
label={intl.formatMessage({id: 'settings_display.clock.standard', defaultMessage: '12-hour clock'})}
description={intl.formatMessage({id: 'settings_display.clock.normal.desc', defaultMessage: 'Example: 4:00 PM'})}
selected={!isMilitaryTimeFormat}
testID='clock_display_settings.normal_clock.action'
testID='clock_display_settings.twelve_hour.option'
type='select'
value={CLOCK_TYPE.NORMAL}
/>
@@ -76,7 +76,7 @@ const DisplayClock = ({componentId, currentUserId, hasMilitaryTimeFormat}: Displ
label={intl.formatMessage({id: 'settings_display.clock.mz', defaultMessage: '24-hour clock'})}
description={intl.formatMessage({id: 'settings_display.clock.mz.desc', defaultMessage: 'Example: 16:00'})}
selected={isMilitaryTimeFormat}
testID='clock_display_settings.military_clock.action'
testID='clock_display_settings.twenty_four_hour.option'
type='select'
value={CLOCK_TYPE.MILITARY}
/>

View File

@@ -28,6 +28,7 @@ const CustomTheme = ({setTheme, displayTheme}: CustomThemeProps) => {
label={intl.formatMessage({id: 'settings_display.custom_theme', defaultMessage: 'Custom Theme'})}
selected={theme.type?.toLowerCase() === displayTheme?.toLowerCase()}
radioItemProps={radioItemProps}
testID='theme_display_settings.custom.option'
/>
</>
);

View File

@@ -49,7 +49,7 @@ const DisplayTheme = ({allowedThemeKeys, componentId, currentTeamId, currentUser
useAndroidHardwareBackHandler(componentId, setThemePreference);
return (
<SettingContainer testID='display_theme'>
<SettingContainer testID='theme_display_settings'>
<ThemeTiles
allowedThemeKeys={allowedThemeKeys}
onThemeChange={setThemePreference}

View File

@@ -56,6 +56,7 @@ type ThemeTileProps = {
activeTheme: Theme;
label: React.ReactElement;
selected: boolean;
testID?: string;
theme: Theme;
};
export const ThemeTile = ({
@@ -64,6 +65,7 @@ export const ThemeTile = ({
activeTheme,
label,
selected,
testID,
theme,
}: ThemeTileProps) => {
const isTablet = useIsTablet();
@@ -92,6 +94,7 @@ export const ThemeTile = ({
<TouchableOpacity
onPress={onPressHandler}
style={[styles.container, layoutStyle.container]}
testID={testID}
>
<View style={[styles.imageWrapper, layoutStyle.thumbnail]}>
<ThemeThumbnail
@@ -105,6 +108,7 @@ export const ThemeTile = ({
name='check-circle'
size={31.2}
style={styles.check}
testID={`${testID}.selected`}
/>
)}
</View>
@@ -141,6 +145,7 @@ export const ThemeTiles = ({allowedThemeKeys, onThemeChange, selectedTheme}: The
action={onThemeChange}
actionValue={themeKey}
selected={selectedTheme?.toLowerCase() === themeKey.toLowerCase()}
testID={`theme_display_settings.${themeKey}.option`}
theme={Preferences.THEMES[themeKey]}
activeTheme={theme}
/>

View File

@@ -92,12 +92,13 @@ const DisplayTimezone = ({currentUser, componentId}: DisplayTimezoneProps) => {
}, [userTimezone.useAutomaticTimezone]);
return (
<SettingContainer testID='display_timezone'>
<SettingContainer testID='timezone_display_settings'>
<SettingOption
action={updateAutomaticTimezone}
description={toggleDesc}
label={intl.formatMessage({id: 'settings_display.timezone.automatically', defaultMessage: 'Set automatically'})}
selected={userTimezone.useAutomaticTimezone}
testID='timezone_display_settings.automatic.option'
type='toggle'
/>
<SettingSeparator/>
@@ -106,6 +107,7 @@ const DisplayTimezone = ({currentUser, componentId}: DisplayTimezoneProps) => {
action={goToSelectTimezone}
info={getTimezoneRegion(userTimezone.manualTimezone)}
label={intl.formatMessage({id: 'settings_display.timezone.manual', defaultMessage: 'Change timezone'})}
testID='timezone_display_settings.manual.option'
type='arrow'
/>
)}

View File

@@ -139,7 +139,7 @@ const SelectTimezones = ({componentId, onBack, currentTimezone}: SelectTimezones
<SafeAreaView
edges={EDGES}
style={styles.container}
testID='settings.select_timezone.screen'
testID='select_timezone.screen'
>
<Search
autoCapitalize='none'
@@ -152,7 +152,7 @@ const SelectTimezones = ({componentId, onBack, currentTimezone}: SelectTimezones
placeholder={intl.formatMessage({id: 'search_bar.search.placeholder', defaultMessage: 'Search timezone'})}
placeholderTextColor={changeOpacity(theme.centerChannelColor, 0.5)}
selectionColor={changeOpacity(theme.centerChannelColor, 0.5)}
testID='settings.select_timezone.search_bar'
testID='select_timezone.search_bar'
value={searchRegion}
/>
<FlatList
@@ -165,6 +165,7 @@ const SelectTimezones = ({componentId, onBack, currentTimezone}: SelectTimezones
keyboardShouldPersistTaps='always'
removeClippedSubviews={true}
renderItem={renderItem}
testID='select_timezone.timezone.flat_list'
/>
</SafeAreaView>
);

View File

@@ -50,11 +50,14 @@ const TimezoneRow = ({onPressTimezone, isSelected, timezone}: TimezoneRowProps)
onPressTimezone(timezone);
}, [onPressTimezone, timezone]);
const timezoneRowTestId = isSelected ? `select_timezone.timezone_row.${timezone}.selected` : `select_timezone.timezone_row.${timezone}`;
return (
<TouchableOpacity
key={timezone}
onPress={onTimezoneSelect}
style={styles.itemContainer}
testID={timezoneRowTestId}
>
<View
style={styles.body}

View File

@@ -97,10 +97,11 @@ const NotificationAutoResponder = ({currentUser, componentId}: NotificationAutoR
useAndroidHardwareBackHandler(componentId, saveAutoResponder);
return (
<SettingContainer testID='notification_auto_responder'>
<SettingContainer testID='auto_responder_notification_settings'>
<SettingOption
label={intl.formatMessage({id: 'notification_settings.auto_responder.to.enable', defaultMessage: 'Enable automatic replies'})}
action={setAutoResponderActive}
testID='auto_responder_notification_settings.enable_automatic_replies.option'
type='toggle'
selected={autoResponderActive}
/>
@@ -118,6 +119,7 @@ const NotificationAutoResponder = ({currentUser, componentId}: NotificationAutoR
placeholder={intl.formatMessage(label)}
placeholderTextColor={changeOpacity(theme.centerChannelColor, 0.4)}
returnKeyType='default'
testID='auto_responder_notification_settings.message.input'
textAlignVertical='top'
textInputStyle={styles.input}
theme={theme}
@@ -129,6 +131,7 @@ const NotificationAutoResponder = ({currentUser, componentId}: NotificationAutoR
id={'notification_settings.auto_responder.footer.message'}
defaultMessage={'Set a custom message that is automatically sent in response to direct messages, such as an out of office or vacation reply. Enabling this setting changes your status to Out of Office and disables notifications.'}
style={styles.footer}
testID='auto_responder_notification_settings.message.input.description'
/>
</SettingContainer>
);

View File

@@ -113,7 +113,7 @@ const NotificationEmail = ({componentId, currentUser, emailInterval, enableEmail
useBackNavigation(saveEmail);
return (
<SettingContainer testID='notification_email'>
<SettingContainer testID='email_notification_settings'>
<SettingBlock
disableFooter={!sendEmailNotifications}
footerText={emailFooterText}
@@ -125,7 +125,7 @@ const NotificationEmail = ({componentId, currentUser, emailInterval, enableEmail
action={setNotifyInterval}
label={intl.formatMessage({id: 'notification_settings.email.immediately', defaultMessage: 'Immediately'})}
selected={notifyInterval === `${Preferences.INTERVAL_IMMEDIATE}`}
testID='notification_settings.email.immediately.action'
testID='email_notification_settings.immediately.option'
type='select'
value={`${Preferences.INTERVAL_IMMEDIATE}`}
/>
@@ -136,6 +136,7 @@ const NotificationEmail = ({componentId, currentUser, emailInterval, enableEmail
action={setNotifyInterval}
label={intl.formatMessage({id: 'notification_settings.email.fifteenMinutes', defaultMessage: 'Every 15 minutes'})}
selected={notifyInterval === `${Preferences.INTERVAL_FIFTEEN_MINUTES}`}
testID='email_notification_settings.every_fifteen_minutes.option'
type='select'
value={`${Preferences.INTERVAL_FIFTEEN_MINUTES}`}
/>
@@ -144,6 +145,7 @@ const NotificationEmail = ({componentId, currentUser, emailInterval, enableEmail
action={setNotifyInterval}
label={intl.formatMessage({id: 'notification_settings.email.everyHour', defaultMessage: 'Every hour'})}
selected={notifyInterval === `${Preferences.INTERVAL_HOUR}`}
testID='email_notification_settings.every_hour.option'
type='select'
value={`${Preferences.INTERVAL_HOUR}`}
/>
@@ -154,7 +156,7 @@ const NotificationEmail = ({componentId, currentUser, emailInterval, enableEmail
action={setNotifyInterval}
label={intl.formatMessage({id: 'notification_settings.email.never', defaultMessage: 'Never'})}
selected={notifyInterval === `${Preferences.INTERVAL_NEVER}`}
testID='notification_settings.email.never.action'
testID='email_notification_settings.never.option'
type='select'
value={`${Preferences.INTERVAL_NEVER}`}
/>
@@ -180,6 +182,7 @@ const NotificationEmail = ({componentId, currentUser, emailInterval, enableEmail
action={setEmailThreads}
label={intl.formatMessage({id: 'user.settings.notifications.email_threads.description', defaultMessage: 'Notify me about all replies to threads I\'m following'})}
selected={emailThreads}
testID='email_notification_settings.email_threads.option'
type='toggle'
/>
<SettingSeparator/>

View File

@@ -167,6 +167,7 @@ const MentionSettings = ({componentId, currentUser, isCRTEnabled}: MentionSectio
description={intl.formatMessage({id: 'notification_settings.mentions.sensitiveName', defaultMessage: 'Your case sensitive first name'})}
label={currentUser.firstName}
selected={firstNameMentionOn}
testID='mention_notification_settings.case_sensitive_first_name.option'
type='toggle'
/>
<SettingSeparator/>
@@ -179,6 +180,7 @@ const MentionSettings = ({componentId, currentUser, isCRTEnabled}: MentionSectio
description={intl.formatMessage({id: 'notification_settings.mentions.sensitiveUsername', defaultMessage: 'Your non-case sensitive username'})}
label={currentUser.username}
selected={usernameMentionOn}
testID='mention_notification_settings.non_case_sensitive_username.option'
type='toggle'
/>
)}
@@ -188,6 +190,7 @@ const MentionSettings = ({componentId, currentUser, isCRTEnabled}: MentionSectio
description={intl.formatMessage({id: 'notification_settings.mentions.channelWide', defaultMessage: 'Channel-wide mentions'})}
label='@channel, @all, @here'
selected={channelMentionOn}
testID='mention_notification_settings.channel_wide_mentions.option'
type='toggle'
/>
<SettingSeparator/>
@@ -204,6 +207,7 @@ const MentionSettings = ({componentId, currentUser, isCRTEnabled}: MentionSectio
placeholder={intl.formatMessage({id: 'notification_settings.mentions..keywordsDescription', defaultMessage: 'Other words that trigger a mention'})}
placeholderTextColor={changeOpacity(theme.centerChannelColor, 0.4)}
returnKeyType='done'
testID='mention_notification_settings.keywords.input'
textInputStyle={styles.input}
textAlignVertical='top'
theme={theme}
@@ -212,6 +216,7 @@ const MentionSettings = ({componentId, currentUser, isCRTEnabled}: MentionSectio
/>
<Text
style={styles.keywordLabelStyle}
testID='mention_notification_settings.keywords.input.description'
>
{intl.formatMessage({id: 'notification_settings.mentions.keywordsLabel', defaultMessage: 'Keywords are not case-sensitive. Separate keywords with commas.'})}
</Text>

View File

@@ -16,7 +16,7 @@ type NotificationMentionProps = {
}
const NotificationMention = ({componentId, currentUser, isCRTEnabled}: NotificationMentionProps) => {
return (
<SettingContainer testID='notification_mention'>
<SettingContainer testID='mention_notification_settings'>
<MentionSettings
currentUser={currentUser}
componentId={componentId}

View File

@@ -29,6 +29,7 @@ const ReplySettings = ({replyNotificationType, setReplyNotificationType}: ReplyS
action={setReplyNotificationType}
label={intl.formatMessage({id: 'notification_settings.threads_start_participate', defaultMessage: 'Threads that I start or participate in'})}
selected={replyNotificationType === 'any'}
testID='mention_notification_settings.threads_start_participate.option'
type='select'
value='any'
/>
@@ -37,6 +38,7 @@ const ReplySettings = ({replyNotificationType, setReplyNotificationType}: ReplyS
action={setReplyNotificationType}
label={intl.formatMessage({id: 'notification_settings.threads_start', defaultMessage: 'Threads that I start'})}
selected={replyNotificationType === 'root'}
testID='mention_notification_settings.threads_start.option'
type='select'
value='root'
/>
@@ -45,6 +47,7 @@ const ReplySettings = ({replyNotificationType, setReplyNotificationType}: ReplyS
action={setReplyNotificationType}
label={intl.formatMessage({id: 'notification_settings.threads_mentions', defaultMessage: 'Mentions in threads'})}
selected={replyNotificationType === 'never'}
testID='mention_notification_settings.threads_mentions.option'
type='select'
value='never'
/>

View File

@@ -67,7 +67,7 @@ const NotificationPush = ({componentId, currentUser, isCRTEnabled, sendPushNotif
useAndroidHardwareBackHandler(componentId, saveNotificationSettings);
return (
<SettingContainer testID='notification_push'>
<SettingContainer testID='push_notification_settings'>
<MobileSendPush
pushStatus={pushSend}
sendPushNotifications={sendPushNotifications}

View File

@@ -49,7 +49,7 @@ const MobileSendPush = ({sendPushNotifications, pushStatus, setMobilePushPref}:
action={setMobilePushPref}
label={intl.formatMessage({id: 'notification_settings.pushNotification.all_new_messages', defaultMessage: 'All new messages'})}
selected={pushStatus === 'all'}
testID='notification_settings.pushNotification.allActivity'
testID='push_notification_settings.all_new_messages.option'
type='select'
value='all'
/>
@@ -58,7 +58,7 @@ const MobileSendPush = ({sendPushNotifications, pushStatus, setMobilePushPref}:
action={setMobilePushPref}
label={intl.formatMessage({id: 'notification_settings.pushNotification.mentions_only', defaultMessage: 'Mentions, direct messages only (default)'})}
selected={pushStatus === 'mention'}
testID='notification_settings.pushNotification.onlyMentions'
testID='push_notification_settings.mentions_only.option'
type='select'
value='mention'
/>
@@ -67,7 +67,7 @@ const MobileSendPush = ({sendPushNotifications, pushStatus, setMobilePushPref}:
action={setMobilePushPref}
label={intl.formatMessage({id: 'notification_settings.pushNotification.nothing', defaultMessage: 'Nothing'})}
selected={pushStatus === 'none'}
testID='notification_settings.pushNotification.never'
testID='push_notification_settings.nothing.option'
type='select'
value='none'
/>

View File

@@ -30,6 +30,7 @@ const MobilePushStatus = ({pushStatus, setMobilePushStatus}: MobilePushStatusPro
action={setMobilePushStatus}
label={intl.formatMessage({id: 'notification_settings.mobile.online', defaultMessage: 'Online, away or offline'})}
selected={pushStatus === 'online'}
testID='push_notification_settings.mobile_online.option'
type='select'
value='online'
/>
@@ -38,6 +39,7 @@ const MobilePushStatus = ({pushStatus, setMobilePushStatus}: MobilePushStatusPro
action={setMobilePushStatus}
label={intl.formatMessage({id: 'notification_settings.mobile.away', defaultMessage: 'Away or offline'})}
selected={pushStatus === 'away'}
testID='push_notification_settings.mobile_away.option'
type='select'
value='away'
/>
@@ -46,6 +48,7 @@ const MobilePushStatus = ({pushStatus, setMobilePushStatus}: MobilePushStatusPro
action={setMobilePushStatus}
label={intl.formatMessage({id: 'notification_settings.mobile.offline', defaultMessage: 'Offline'})}
selected={pushStatus === 'offline'}
testID='push_notification_settings.mobile_offline.option'
type='select'
value='offline'
/>

View File

@@ -31,6 +31,7 @@ const MobilePushThread = ({pushThread, onMobilePushThreadChanged}: MobilePushThr
action={onMobilePushThreadChanged}
label={intl.formatMessage({id: 'notification_settings.push_threads.following', defaultMessage: 'Notify me about replies to threads I\'m following in this channel'})}
selected={pushThread === 'all'}
testID='push_notification_settings.push_threads_following.option'
type='toggle'
/>
<SettingSeparator/>

View File

@@ -114,7 +114,7 @@
"EnableConfirmNotificationsToChannel": true,
"TeammateNameDisplay": "username",
"ExperimentalViewArchivedChannels": true,
"ExperimentalEnableAutomaticReplies": false,
"ExperimentalEnableAutomaticReplies": true,
"ExperimentalHideTownSquareinLHS": false,
"ExperimentalTownSquareIsReadOnly": false,
"LockTeammateNameDisplay": false,
@@ -283,7 +283,7 @@
},
"DisplaySettings": {
"CustomUrlSchemes": [],
"ExperimentalTimezone": false
"ExperimentalTimezone": true
},
"GuestAccountsSettings": {
"Enable": true,

View File

@@ -0,0 +1,91 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import {SettingsScreen} from '@support/ui/screen';
import {timeouts} from '@support/utils';
import {expect} from 'detox';
class AboutScreen {
testID = {
aboutScreen: 'about.screen',
backButton: 'screen.back.button',
scrollView: 'about.scroll_view',
logo: 'about.logo',
siteName: 'about.site_name',
title: 'about.title',
subtitle: 'about.subtitle',
appVersionTitle: 'about.app_version.title',
appVersionValue: 'about.app_version.value',
serverVersionTitle: 'about.server_version.title',
serverVersionValue: 'about.server_version.value',
databaseTitle: 'about.database.title',
databaseValue: 'about.database.value',
databaseSchemaVersionTitle: 'about.database_schema_version.title',
databaseSchemaVersionValue: 'about.database_schema_version.value',
licensee: 'about.licensee',
learnMoreText: 'about.learn_more.text',
learnMoreUrl: 'about.learn_more.url',
poweredBy: 'about.powered_by',
copyright: 'about.copyright',
termsOfService: 'about.terms_of_service',
privacyPolicy: 'about.privacy_policy',
noticeText: 'about.notice_text',
buildHashTitle: 'about.build_hash.title',
buildHashValue: 'about.build_hash.value',
buildHashEnterpriseTitle: 'about.build_hash_enterprise.title',
buildHashEnterpriseValue: 'about.build_hash_enterprise.value',
buildDateTitle: 'about.build_date.title',
buildDateValue: 'about.build_date.value',
};
aboutScreen = element(by.id(this.testID.aboutScreen));
backButton = element(by.id(this.testID.backButton));
scrollView = element(by.id(this.testID.scrollView));
logo = element(by.id(this.testID.logo));
siteName = element(by.id(this.testID.siteName));
title = element(by.id(this.testID.title));
subtitle = element(by.id(this.testID.subtitle));
appVersionTitle = element(by.id(this.testID.appVersionTitle));
appVersionValue = element(by.id(this.testID.appVersionValue));
serverVersionTitle = element(by.id(this.testID.serverVersionTitle));
serverVersionValue = element(by.id(this.testID.serverVersionValue));
databaseTitle = element(by.id(this.testID.databaseTitle));
databaseValue = element(by.id(this.testID.databaseValue));
databaseSchemaVersionTitle = element(by.id(this.testID.databaseSchemaVersionTitle));
databaseSchemaVersionValue = element(by.id(this.testID.databaseSchemaVersionValue));
licensee = element(by.id(this.testID.licensee));
learnMoreText = element(by.id(this.testID.learnMoreText));
learnMoreUrl = element(by.id(this.testID.learnMoreUrl));
poweredBy = element(by.id(this.testID.poweredBy));
copyright = element(by.id(this.testID.copyright));
termsOfService = element(by.id(this.testID.termsOfService));
privacyPolicy = element(by.id(this.testID.privacyPolicy));
noticeText = element(by.id(this.testID.noticeText));
buildHashTitle = element(by.id(this.testID.buildHashTitle));
buildHashValue = element(by.id(this.testID.buildHashValue));
buildHashEnterpriseTitle = element(by.id(this.testID.buildHashEnterpriseTitle));
buildHashEnterpriseValue = element(by.id(this.testID.buildHashEnterpriseValue));
buildDateTitle = element(by.id(this.testID.buildDateTitle));
buildDateValue = element(by.id(this.testID.buildDateValue));
toBeVisible = async () => {
await waitFor(this.aboutScreen).toExist().withTimeout(timeouts.TEN_SEC);
return this.aboutScreen;
};
open = async () => {
// # Open about screen
await SettingsScreen.aboutOption.tap();
return this.toBeVisible();
};
back = async () => {
await this.backButton.tap();
await expect(this.aboutScreen).not.toBeVisible();
};
}
const aboutScreen = new AboutScreen();
export default aboutScreen;

View File

@@ -12,6 +12,7 @@ import {expect} from 'detox';
class AccountScreen {
testID = {
userInfoPrefix: 'account.user_info.',
customStatusPrefix: 'account.custom_status.',
accountScreen: 'account.screen',
userPresenceOption: 'account.user_presence.option',
setStatusOption: 'account.custom_status.option',
@@ -22,6 +23,8 @@ class AccountScreen {
awayUserStatusOption: 'user_status.away.option',
dndUserStatusOption: 'user_status.dnd.option',
offlineUserStatusOption: 'user_status.offline.option',
customStatusFailureMessage: 'account.custom_status.failure_message',
customStatusClearButton: 'account.custom_status.clear.button',
};
accountScreen = element(by.id(this.testID.accountScreen));
@@ -34,6 +37,8 @@ class AccountScreen {
awayUserStatusOption = element(by.id(this.testID.awayUserStatusOption));
dndUserStatusOption = element(by.id(this.testID.dndUserStatusOption));
offlineUserStatusOption = element(by.id(this.testID.offlineUserStatusOption));
customStatusFailureMessage = element(by.id(this.testID.customStatusFailureMessage));
customStatusClearButton = element(by.id(this.testID.customStatusClearButton));
getUserInfo = (userId: string) => {
const userInfoTestId = `${this.testID.userInfoPrefix}${userId}`;
@@ -56,6 +61,18 @@ class AccountScreen {
return element(by.id(`user_status.label.${status}`)).atIndex(0);
};
getCustomStatus = (emojiName: string, duration: string) => {
const accountCustomStatusEmojiMatcher = by.id(`${this.testID.customStatusPrefix}custom_status_emoji.${emojiName}`);
const accountCustomStatusTextMatcher = by.id(`${this.testID.customStatusPrefix}custom_status_text`);
const accountCustomStatusExpiryMatcher = by.id(`${this.testID.customStatusPrefix}custom_status_duration.${duration}.custom_status_expiry`);
return {
accountCustomStatusEmoji: element(accountCustomStatusEmojiMatcher),
accountCustomStatusText: element(accountCustomStatusTextMatcher),
accountCustomStatusExpiry: element(accountCustomStatusExpiryMatcher),
};
};
toBeVisible = async () => {
await waitFor(this.accountScreen).toExist().withTimeout(timeouts.TEN_SEC);

View File

@@ -0,0 +1,41 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import {SettingsScreen} from '@support/ui/screen';
import {timeouts} from '@support/utils';
import {expect} from 'detox';
class AdvancedSettingsScreen {
testID = {
advancedSettingsScreen: 'advanced_settings.screen',
backButton: 'screen.back.button',
scrollView: 'advanced_settings.scroll_view',
deleteDataOption: 'advanced_settings.delete_data.option',
};
advancedSettingsScreen = element(by.id(this.testID.advancedSettingsScreen));
backButton = element(by.id(this.testID.backButton));
scrollView = element(by.id(this.testID.scrollView));
deleteDataOption = element(by.id(this.testID.deleteDataOption));
toBeVisible = async () => {
await waitFor(this.advancedSettingsScreen).toExist().withTimeout(timeouts.TEN_SEC);
return this.advancedSettingsScreen;
};
open = async () => {
// # Open advanced settings screen
await SettingsScreen.advancedSettingsOption.tap();
return this.toBeVisible();
};
back = async () => {
await this.backButton.tap();
await expect(this.advancedSettingsScreen).not.toBeVisible();
};
}
const advancedSettingsScreen = new AdvancedSettingsScreen();
export default advancedSettingsScreen;

View File

@@ -0,0 +1,57 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import {NotificationSettingsScreen} from '@support/ui/screen';
import {timeouts} from '@support/utils';
import {expect} from 'detox';
class AutoResponderNotificationSettingsScreen {
testID = {
autoResponderNotificationSettingsScreen: 'auto_responder_notification_settings.screen',
backButton: 'screen.back.button',
scrollView: 'auto_responder_notification_settings.scroll_view',
enableAutomaticRepliesOptionToggledOff: 'auto_responder_notification_settings.enable_automatic_replies.option.toggled.false',
enableAutomaticRepliesOptionToggledOn: 'auto_responder_notification_settings.enable_automatic_replies.option.toggled.true',
messageInput: 'auto_responder_notification_settings.message.input',
messageInputDescription: 'auto_responder_notification_settings.message.input.description',
};
autoResponderNotificationSettingsScreen = element(by.id(this.testID.autoResponderNotificationSettingsScreen));
backButton = element(by.id(this.testID.backButton));
scrollView = element(by.id(this.testID.scrollView));
enableAutomaticRepliesOptionToggledOff = element(by.id(this.testID.enableAutomaticRepliesOptionToggledOff));
enableAutomaticRepliesOptionToggledOn = element(by.id(this.testID.enableAutomaticRepliesOptionToggledOn));
messageInput = element(by.id(this.testID.messageInput));
messageInputDescription = element(by.id(this.testID.messageInputDescription));
toBeVisible = async () => {
await waitFor(this.autoResponderNotificationSettingsScreen).toExist().withTimeout(timeouts.TEN_SEC);
return this.autoResponderNotificationSettingsScreen;
};
open = async () => {
// # Open auto-responder notification settings screen
await NotificationSettingsScreen.automaticRepliesOption.tap();
return this.toBeVisible();
};
back = async () => {
await this.backButton.tap();
await expect(this.autoResponderNotificationSettingsScreen).not.toBeVisible();
};
toggleEnableAutomaticRepliesOptionOn = async () => {
await this.enableAutomaticRepliesOptionToggledOff.tap();
await expect(this.enableAutomaticRepliesOptionToggledOn).toBeVisible();
};
toggleEnableAutomaticRepliesOptionOff = async () => {
await this.enableAutomaticRepliesOptionToggledOn.tap();
await expect(this.enableAutomaticRepliesOptionToggledOff).toBeVisible();
};
}
const autoResponderNotificationSettingsScreen = new AutoResponderNotificationSettingsScreen();
export default autoResponderNotificationSettingsScreen;

View File

@@ -7,6 +7,7 @@ import {expect} from 'detox';
class BrowseChannelsScreen {
testID = {
channelItemPrefix: 'browse_channels.custom_list.channel_item.',
browseChannelsScreen: 'browse_channels.screen',
closeButton: 'close.browse_channels.button',
createButton: 'browse_channels.create.button',
@@ -33,11 +34,11 @@ class BrowseChannelsScreen {
flatChannelList = element(by.id(this.testID.flatChannelList));
getChannelItem = (channelName: string) => {
return element(by.id(`browse_channels.custom_list.channel_item.${channelName}`));
return element(by.id(`${this.testID.channelItemPrefix}${channelName}`));
};
getChannelItemDisplayName = (channelName: string) => {
return element(by.id(`browse_channels.custom_list.channel_item.${channelName}.display_name`));
return element(by.id(`${this.testID.channelItemPrefix}${channelName}.display_name`));
};
toBeVisible = async () => {

View File

@@ -10,6 +10,9 @@ import {timeouts} from '@support/utils';
class ChannelListScreen {
testID = {
categoryHeaderPrefix: 'channel_list.category_header.',
categoryPrefix: 'channel_list.category.',
teamItemPrefix: 'team_sidebar.team_list.team_item.',
channelListScreen: 'channel_list.screen',
serverIcon: 'channel_list.servers.server_icon',
headerTeamDisplayName: 'channel_list_header.team_display_name',
@@ -38,35 +41,35 @@ class ChannelListScreen {
openDirectMessageItem = PlusMenu.openDirectMessageItem;
getCategoryCollapsed = (categoryKey: string) => {
return element(by.id(`channel_list.category_header.${categoryKey}.collapsed.true`));
return element(by.id(`${this.testID.categoryHeaderPrefix}${categoryKey}.collapsed.true`));
};
getCategoryExpanded = (categoryKey: string) => {
return element(by.id(`channel_list.category_header.${categoryKey}.collapsed.false`));
return element(by.id(`${this.testID.categoryHeaderPrefix}${categoryKey}.collapsed.false`));
};
getCategoryHeaderDisplayName = (categoryKey: string) => {
return element(by.id(`channel_list.category_header.${categoryKey}.display_name`));
return element(by.id(`${this.testID.categoryHeaderPrefix}${categoryKey}.display_name`));
};
getChannelItem = (categoryKey: string, channelName: string) => {
return element(by.id(`channel_list.category.${categoryKey}.channel_item.${channelName}`));
return element(by.id(`${this.testID.categoryPrefix}${categoryKey}.channel_item.${channelName}`));
};
getChannelItemDisplayName = (categoryKey: string, channelName: string) => {
return element(by.id(`channel_list.category.${categoryKey}.channel_item.${channelName}.display_name`));
return element(by.id(`${this.testID.categoryPrefix}${categoryKey}.channel_item.${channelName}.display_name`));
};
getTeamItemSelected = (teamId: string) => {
return element(by.id(`team_sidebar.team_list.team_item.${teamId}.selected`));
return element(by.id(`${this.testID.teamItemPrefix}${teamId}.selected`));
};
getTeamItemNotSelected = (teamId: string) => {
return element(by.id(`team_sidebar.team_list.team_item.${teamId}.not_selected`));
return element(by.id(`${this.testID.teamItemPrefix}${teamId}.not_selected`));
};
getTeamItemDisplayNameAbbreviation = (teamId: string) => {
return element(by.id(`team_sidebar.team_list.team_item.${teamId}.team_icon.display_name_abbreviation`));
return element(by.id(`${this.testID.teamItemPrefix}${teamId}.team_icon.display_name_abbreviation`));
};
toBeVisible = async () => {

View File

@@ -0,0 +1,47 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import {DisplaySettingsScreen} from '@support/ui/screen';
import {timeouts} from '@support/utils';
import {expect} from 'detox';
class ClockDisplaySettingsScreen {
testID = {
clockDisplaySettingsScreen: 'clock_display_settings.screen',
backButton: 'screen.back.button',
scrollView: 'clock_display_settings.scroll_view',
twelveHourOption: 'clock_display_settings.twelve_hour.option',
twelveHourOptionSelected: 'clock_display_settings.twelve_hour.option.selected',
twentyFourHourOption: 'clock_display_settings.twenty_four_hour.option',
twentyFourHourOptionSelected: 'clock_display_settings.twenty_four_hour.option.selected',
};
clockDisplaySettingsScreen = element(by.id(this.testID.clockDisplaySettingsScreen));
backButton = element(by.id(this.testID.backButton));
scrollView = element(by.id(this.testID.scrollView));
twelveHourOption = element(by.id(this.testID.twelveHourOption));
twelveHourOptionSelected = element(by.id(this.testID.twelveHourOptionSelected));
twentyFourHourOption = element(by.id(this.testID.twentyFourHourOption));
twentyFourHourOptionSelected = element(by.id(this.testID.twentyFourHourOptionSelected));
toBeVisible = async () => {
await waitFor(this.clockDisplaySettingsScreen).toExist().withTimeout(timeouts.TEN_SEC);
return this.clockDisplaySettingsScreen;
};
open = async () => {
// # Open clock display settings screen
await DisplaySettingsScreen.clockDisplayOption.tap();
return this.toBeVisible();
};
back = async () => {
await this.backButton.tap();
await expect(this.clockDisplaySettingsScreen).not.toBeVisible();
};
}
const clockDisplaySettingsScreen = new ClockDisplaySettingsScreen();
export default clockDisplaySettingsScreen;

View File

@@ -8,6 +8,8 @@ import {expect} from 'detox';
class CreateDirectMessageScreen {
testID = {
selectedUserPrefix: 'create_direct_message.selected_user.',
userItemPrefix: 'create_direct_message.user_list.user_item.',
createDirectMessageScreen: 'create_direct_message.screen',
closeButton: 'close.create_direct_message.button',
startButton: 'create_direct_message.start.button',
@@ -30,27 +32,27 @@ class CreateDirectMessageScreen {
tutorialHighlight = element(by.id(this.testID.tutorialHighlight));
getSelectedUser = (userId: string) => {
return element(by.id(`create_direct_message.selected_user.${userId}`));
return element(by.id(`${this.testID.selectedUserPrefix}${userId}`));
};
getSelectedUserDisplayName = (userId: string) => {
return element(by.id(`create_direct_message.selected_user.${userId}.display_name`));
return element(by.id(`${this.testID.selectedUserPrefix}${userId}.display_name`));
};
getSelectedUserRemoveButton = (userId: string) => {
return element(by.id(`create_direct_message.selected_user.${userId}.remove.button`));
return element(by.id(`${this.testID.selectedUserPrefix}${userId}.remove.button`));
};
getUserItem = (userId: string) => {
return element(by.id(`create_direct_message.user_list.user_item.${userId}`));
return element(by.id(`${this.testID.userItemPrefix}${userId}`));
};
getUserItemProfilePicture = (userId: string) => {
return element(ProfilePicture.getProfilePictureItemMatcher('create_direct_message.user_list.user_item.', userId));
return element(ProfilePicture.getProfilePictureItemMatcher(this.testID.userItemPrefix, userId));
};
getUserItemDisplayName = (userId: string) => {
return element(by.id(`create_direct_message.user_list.user_item.${userId}.display_name`));
return element(by.id(`${this.testID.userItemPrefix}${userId}.display_name`));
};
toBeVisible = async () => {

View File

@@ -1,18 +1,73 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import {AccountScreen} from '@support/ui/screen';
import {
AccountScreen,
EmojiPickerScreen,
} from '@support/ui/screen';
import {timeouts} from '@support/utils';
import {expect} from 'detox';
class CustomStatusScreen {
testID = {
customStatusEmojiPrefix: 'custom_status.custom_status_emoji.',
customStatusDurationPrefix: 'custom_status.clear_after.custom_status_duration.',
customStatusSuggestionPrefix: 'custom_status.custom_status_suggestion.',
customStatusScreen: 'custom_status.screen',
doneButton: 'custom_status.done.button',
scrollView: 'custom_status.scroll_view',
statusInput: 'custom_status.status.input',
statusInputClearButton: 'custom_status.status.input.clear.button',
recents: 'custom_status.recents',
suggestions: 'custom_status.suggestions',
};
customStatusScreen = element(by.id(this.testID.customStatusScreen));
doneButton = element(by.id(this.testID.doneButton));
scrollView = element(by.id(this.testID.scrollView));
statusInput = element(by.id(this.testID.statusInput));
statusInputClearButton = element(by.id(this.testID.statusInputClearButton));
recents = element(by.id(this.testID.recents));
suggestions = element(by.id(this.testID.suggestions));
getCustomStatusEmoji = (emojiName: string) => {
return element(by.id(`${this.testID.customStatusEmojiPrefix}${emojiName}`));
};
getCustomStatusClearAfterAction = (duration: string) => {
return element(by.id(`${this.testID.customStatusDurationPrefix}${duration}.action`));
};
getCustomStatusExpiry = (duration: string) => {
return element(by.id(`${this.testID.customStatusDurationPrefix}${duration}.custom_status_expiry`));
};
getCustomStatusSuggestion = (blockMatcher: Detox.NativeMatcher, emojiName: string, text: string, duration: string) => {
const customStatusSuggestionTestId = `${this.testID.customStatusSuggestionPrefix}${text}`;
const customStatusSuggestionMatcher = by.id(customStatusSuggestionTestId).withAncestor(blockMatcher);
const customStatusEmojiMatcher = by.id(`${customStatusSuggestionTestId}.custom_status_emoji.${emojiName}`).withAncestor(blockMatcher);
const customStatusTextMatcher = by.id(`${customStatusSuggestionTestId}.custom_status_text`).withAncestor(blockMatcher);
const customStatusDurationMatcher = by.id(`${customStatusSuggestionTestId}.custom_status_duration.${duration}`).withAncestor(blockMatcher);
const customStatusClearButtonMatcher = by.id(`${customStatusSuggestionTestId}.clear.button`).withAncestor(blockMatcher);
return {
customStatusSuggestion: element(customStatusSuggestionMatcher),
customStatusSuggestionEmoji: element(customStatusEmojiMatcher),
customStatusSuggestionText: element(customStatusTextMatcher),
customStatusSuggestionDuration: element(customStatusDurationMatcher),
customStatusClearButton: element(customStatusClearButtonMatcher),
};
};
getRecentCustomStatus = (emojiName: string, text: string, duration: string) => {
const recentsMatcher = by.id(this.testID.recents);
return this.getCustomStatusSuggestion(recentsMatcher, emojiName, text, duration);
};
getSuggestedCustomStatus = (emojiName: string, text: string, duration: string) => {
const suggestedMatcher = by.id(this.testID.suggestions);
return this.getCustomStatusSuggestion(suggestedMatcher, emojiName, text, duration);
};
toBeVisible = async () => {
await waitFor(this.customStatusScreen).toExist().withTimeout(timeouts.TEN_SEC);
@@ -27,6 +82,11 @@ class CustomStatusScreen {
return this.toBeVisible();
};
openEmojiPicker = async (emojiName: string) => {
await this.getCustomStatusEmoji(emojiName).tap();
await EmojiPickerScreen.toBeVisible();
};
close = async () => {
await this.doneButton.tap();
await expect(this.customStatusScreen).not.toBeVisible();

View File

@@ -0,0 +1,51 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import {SettingsScreen} from '@support/ui/screen';
import {timeouts} from '@support/utils';
import {expect} from 'detox';
class DisplaySettingsScreen {
testID = {
displaySettingsScreen: 'display_settings.screen',
backButton: 'screen.back.button',
scrollView: 'display_settings.scroll_view',
themeOption: 'display_settings.theme.option',
themeOptionInfo: 'display_settings.theme.option.info',
clockDisplayOption: 'display_settings.clock_display.option',
clockDisplayOptionInfo: 'display_settings.clock_display.option.info',
timezoneOption: 'display_settings.timezone.option',
timezoneOptionInfo: 'display_settings.timezone.option.info',
};
displaySettingsScreen = element(by.id(this.testID.displaySettingsScreen));
backButton = element(by.id(this.testID.backButton));
scrollView = element(by.id(this.testID.scrollView));
themeOption = element(by.id(this.testID.themeOption));
themeOptionInfo = element(by.id(this.testID.themeOptionInfo));
clockDisplayOption = element(by.id(this.testID.clockDisplayOption));
clockDisplayOptionInfo = element(by.id(this.testID.clockDisplayOptionInfo));
timezoneOption = element(by.id(this.testID.timezoneOption));
timezoneOptionInfo = element(by.id(this.testID.timezoneOptionInfo));
toBeVisible = async () => {
await waitFor(this.displaySettingsScreen).toExist().withTimeout(timeouts.TEN_SEC);
return this.displaySettingsScreen;
};
open = async () => {
// # Open display settings screen
await SettingsScreen.displayOption.tap();
return this.toBeVisible();
};
back = async () => {
await this.backButton.tap();
await expect(this.displaySettingsScreen).not.toBeVisible();
};
}
const displaySettingsScreen = new DisplaySettingsScreen();
export default displaySettingsScreen;

View File

@@ -8,8 +8,8 @@ import {expect} from 'detox';
class EditProfileScreen {
testID = {
editProfileScreenPrefix: 'edit_profile.',
editProfileScreen: 'edit_profile.screen',
editProfilePrefix: 'edit_profile.',
closeButton: 'close.edit_profile.button',
saveButton: 'edit_profile.save.button',
scrollView: 'edit_profile.scroll_view',
@@ -47,7 +47,7 @@ class EditProfileScreen {
positionInputDisabled = element(by.id(this.testID.positionInputDisabled));
getEditProfilePicture = (userId: string) => {
return element(ProfilePicture.getProfilePictureItemMatcher(this.testID.editProfilePrefix, userId));
return element(ProfilePicture.getProfilePictureItemMatcher(this.testID.editProfileScreenPrefix, userId));
};
toBeVisible = async () => {

View File

@@ -0,0 +1,69 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import {NotificationSettingsScreen} from '@support/ui/screen';
import {timeouts} from '@support/utils';
import {expect} from 'detox';
class EmailNotificationSettingsScreen {
testID = {
emailNotificationSettingsScreen: 'email_notification_settings.screen',
backButton: 'screen.back.button',
scrollView: 'email_notification_settings.scroll_view',
immediatelyOption: 'email_notification_settings.immediately.option',
immediatelyOptionSelected: 'email_notification_settings.immediately.option.selected',
everyFifteenMinutesOption: 'email_notification_settings.every_fifteen_minutes.option',
everyFifteenMinutesOptionSelected: 'email_notification_settings.every_fifteen_minutes.option.selected',
everyHourOption: 'email_notification_settings.every_hour.option',
everyHourOptionSelected: 'email_notification_settings.every_hour.option.selected',
neverOption: 'email_notification_settings.never.option',
neverOptionSelected: 'email_notification_settings.never.option.selected',
emailThreadsOptionToggledOff: 'email_notification_settings.email_threads.option.toggled.false',
emailThreadsOptionToggledOn: 'email_notification_settings.email_threads.option.toggled.true',
};
emailNotificationSettingsScreen = element(by.id(this.testID.emailNotificationSettingsScreen));
backButton = element(by.id(this.testID.backButton));
scrollView = element(by.id(this.testID.scrollView));
immediatelyOption = element(by.id(this.testID.immediatelyOption));
immediatelyOptionSelected = element(by.id(this.testID.immediatelyOptionSelected));
everyFifteenMinutesOption = element(by.id(this.testID.everyFifteenMinutesOption));
everyFifteenMinutesOptionSelected = element(by.id(this.testID.everyFifteenMinutesOptionSelected));
everyHourOption = element(by.id(this.testID.everyHourOption));
everyHourOptionSelected = element(by.id(this.testID.everyHourOptionSelected));
neverOption = element(by.id(this.testID.neverOption));
neverOptionSelected = element(by.id(this.testID.neverOptionSelected));
emailThreadsOptionToggledOff = element(by.id(this.testID.emailThreadsOptionToggledOff));
emailThreadsOptionToggledOn = element(by.id(this.testID.emailThreadsOptionToggledOn));
toBeVisible = async () => {
await waitFor(this.emailNotificationSettingsScreen).toExist().withTimeout(timeouts.TEN_SEC);
return this.emailNotificationSettingsScreen;
};
open = async () => {
// # Open email notification settings screen
await NotificationSettingsScreen.emailNotificationsOption.tap();
return this.toBeVisible();
};
back = async () => {
await this.backButton.tap();
await expect(this.emailNotificationSettingsScreen).not.toBeVisible();
};
toggleEmailThreadsOptionOn = async () => {
await this.emailThreadsOptionToggledOff.tap();
await expect(this.emailThreadsOptionToggledOn).toBeVisible();
};
toggleEmailThreadsOptionOff = async () => {
await this.emailThreadsOptionToggledOn.tap();
await expect(this.emailThreadsOptionToggledOff).toBeVisible();
};
}
const emailNotificationSettingsScreen = new EmailNotificationSettingsScreen();
export default emailNotificationSettingsScreen;

View File

@@ -7,8 +7,8 @@ import {expect} from 'detox';
class EmojiPickerScreen {
testID = {
emojiPickerScreenPrefix: 'emoji_picker.',
emojiPickerScreen: 'emoji_picker.screen',
emojiPickerPrefix: 'emoji_picker.',
closeButton: 'close.emoji_picker.button',
};
@@ -16,10 +16,10 @@ class EmojiPickerScreen {
closeButton = element(by.id(this.testID.closeButton));
// convenience props
searchBar = SearchBar.getSearchBar(this.testID.emojiPickerPrefix);
searchInput = SearchBar.getSearchInput(this.testID.emojiPickerPrefix);
cancelButton = SearchBar.getCancelButton(this.testID.emojiPickerPrefix);
clearButton = SearchBar.getClearButton(this.testID.emojiPickerPrefix);
searchBar = SearchBar.getSearchBar(this.testID.emojiPickerScreenPrefix);
searchInput = SearchBar.getSearchInput(this.testID.emojiPickerScreenPrefix);
cancelButton = SearchBar.getCancelButton(this.testID.emojiPickerScreenPrefix);
clearButton = SearchBar.getClearButton(this.testID.emojiPickerScreenPrefix);
toBeVisible = async () => {
await expect(this.emojiPickerScreen).toBeVisible();

View File

@@ -8,8 +8,10 @@ import {expect} from 'detox';
class FindChannelsScreen {
testID = {
findChannelsScreenPrefix: 'find_channels.',
filteredChannelItemPrefix: 'find_channels.filtered_list.channel_item.',
unfilteredChannelItemPrefix: 'find_channels.unfiltered_list.channel_item.',
findChannelsScreen: 'find_channels.screen',
findChannelsPrefix: 'find_channels.',
closeButton: 'close.find_channels.button',
directoryQuickOption: 'find_channels.quick_options.directory.option',
openDirectMessageQuickOption: 'find_channels.quick_options.open_dm.option',
@@ -27,25 +29,25 @@ class FindChannelsScreen {
flatFilteredChannelList = element(by.id(this.testID.flatFilteredChannelList));
// convenience props
searchBar = SearchBar.getSearchBar(this.testID.findChannelsPrefix);
searchInput = SearchBar.getSearchInput(this.testID.findChannelsPrefix);
cancelButton = SearchBar.getCancelButton(this.testID.findChannelsPrefix);
clearButton = SearchBar.getClearButton(this.testID.findChannelsPrefix);
searchBar = SearchBar.getSearchBar(this.testID.findChannelsScreenPrefix);
searchInput = SearchBar.getSearchInput(this.testID.findChannelsScreenPrefix);
cancelButton = SearchBar.getCancelButton(this.testID.findChannelsScreenPrefix);
clearButton = SearchBar.getClearButton(this.testID.findChannelsScreenPrefix);
getUnfilteredChannelItem = (channelName: string) => {
return element(by.id(`find_channels.unfiltered_list.channel_item.${channelName}`));
return element(by.id(`${this.testID.unfilteredChannelItemPrefix}${channelName}`));
};
getUnfilteredChannelItemDisplayName = (channelName: string) => {
return element(by.id(`find_channels.unfiltered_list.channel_item.${channelName}.display_name`));
return element(by.id(`${this.testID.unfilteredChannelItemPrefix}${channelName}.display_name`));
};
getFilteredChannelItem = (channelName: string) => {
return element(by.id(`find_channels.filtered_list.channel_item.${channelName}`));
return element(by.id(`${this.testID.filteredChannelItemPrefix}${channelName}`));
};
getFilteredChannelItemDisplayName = (channelName: string) => {
return element(by.id(`find_channels.filtered_list.channel_item.${channelName}.display_name`));
return element(by.id(`${this.testID.filteredChannelItemPrefix}${channelName}.display_name`));
};
toBeVisible = async () => {

View File

@@ -11,6 +11,7 @@ import {expect} from 'detox';
class GlobalThreadsScreen {
testID = {
threadItemPrefix: 'global_threads.threads_list.thread_item.',
globalThreadsScreen: 'global_threads.screen',
headerAllThreadsButton: 'global_threads.threads_list.header.all_threads.button',
headerUnreadThreadsButton: 'global_threads.threads_list.header.unread_threads.button',
@@ -32,31 +33,31 @@ class GlobalThreadsScreen {
backButton = NavigationHeader.backButton;
getThreadItem = (threadId: string) => {
return element(by.id(`global_threads.threads_list.thread_item.${threadId}`));
return element(by.id(`${this.testID.threadItemPrefix}${threadId}`));
};
getThreadItemUnreadMentionsBadge = (threadId: string) => {
return element(by.id(`global_threads.threads_list.thread_item.${threadId}.unread_mentions.badge`));
return element(by.id(`${this.testID.threadItemPrefix}${threadId}.unread_mentions.badge`));
};
getThreadItemUnreadDotBadge = (threadId: string) => {
return element(by.id(`global_threads.threads_list.thread_item.${threadId}.unread_dot.badge`));
return element(by.id(`${this.testID.threadItemPrefix}${threadId}.unread_dot.badge`));
};
getThreadItemThreadStarterUserDisplayName = (threadId: string) => {
return element(by.id(`global_threads.threads_list.thread_item.${threadId}.thread_starter.user_display_name`));
return element(by.id(`${this.testID.threadItemPrefix}${threadId}.thread_starter.user_display_name`));
};
getThreadItemThreadStarterChannelDisplayName = (threadId: string) => {
return element(by.id(`global_threads.threads_list.thread_item.${threadId}.thread_starter.channel_display_name`));
return element(by.id(`${this.testID.threadItemPrefix}${threadId}.thread_starter.channel_display_name`));
};
getThreadItemFooterUnreadReplies = (threadId: string) => {
return element(by.id(`global_threads.threads_list.thread_item.${threadId}.footer.unread_replies`));
return element(by.id(`${this.testID.threadItemPrefix}${threadId}.footer.unread_replies`));
};
getThreadItemFooterReplyCount = (threadId: string) => {
return element(by.id(`global_threads.threads_list.thread_item.${threadId}.footer.reply_count`));
return element(by.id(`${this.testID.threadItemPrefix}${threadId}.footer.reply_count`));
};
toBeVisible = async () => {

View File

@@ -1,66 +1,90 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import AboutScreen from './about';
import AccountScreen from './account';
import AdvancedSettingsScreen from './advanced_settings';
import AutoResponderNotificationSettingsScreen from './auto_responder_notification_settings';
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 ClockDisplaySettingsScreen from './clock_display_settings';
import CreateDirectMessageScreen from './create_direct_message';
import CreateOrEditChannelScreen from './create_or_edit_channel';
import CustomStatusScreen from './custom_status';
import DisplaySettingsScreen from './display_settings';
import EditPostScreen from './edit_post';
import EditProfileScreen from './edit_profile';
import EditServerScreen from './edit_server';
import EmailNotificationSettingsScreen from './email_notification_settings';
import EmojiPickerScreen from './emoji_picker';
import FindChannelsScreen from './find_channels';
import GlobalThreadsScreen from './global_threads';
import HomeScreen from './home';
import LoginScreen from './login';
import MentionNotificationSettingsScreen from './mention_notification_settings';
import NotificationSettingsScreen from './notification_settings';
import PermalinkScreen from './permalink';
import PinnedMessagesScreen from './pinned_messages';
import PostOptionsScreen from './post_options';
import PushNotificationSettingsScreen from './push_notification_settings';
import ReactionsScreen from './reactions';
import RecentMentionsScreen from './recent_mentions';
import SavedMessagesScreen from './saved_messages';
import SelectTimezoneScreen from './select_timezone';
import ServerScreen from './server';
import ServerListScreen from './server_list';
import SettingsScreen from './settings';
import TableScreen from './table';
import ThemeDisplaySettingsScreen from './theme_display_settings';
import ThreadScreen from './thread';
import ThreadOptionsScreen from './thread_options';
import TimezoneDisplaySettingsScreen from './timezone_display_settings';
import UserProfileScreen from './user_profile';
export {
AboutScreen,
AccountScreen,
AdvancedSettingsScreen,
AutoResponderNotificationSettingsScreen,
BrowseChannelsScreen,
ChannelScreen,
ChannelDropdownMenuScreen,
ChannelInfoScreen,
ChannelListScreen,
ClockDisplaySettingsScreen,
CreateDirectMessageScreen,
CreateOrEditChannelScreen,
CustomStatusScreen,
DisplaySettingsScreen,
EditPostScreen,
EditProfileScreen,
EditServerScreen,
EmailNotificationSettingsScreen,
EmojiPickerScreen,
FindChannelsScreen,
GlobalThreadsScreen,
HomeScreen,
LoginScreen,
MentionNotificationSettingsScreen,
NotificationSettingsScreen,
PermalinkScreen,
PinnedMessagesScreen,
PostOptionsScreen,
PushNotificationSettingsScreen,
ReactionsScreen,
RecentMentionsScreen,
SavedMessagesScreen,
SelectTimezoneScreen,
ServerScreen,
ServerListScreen,
SettingsScreen,
TableScreen,
ThemeDisplaySettingsScreen,
ThreadScreen,
ThreadOptionsScreen,
TimezoneDisplaySettingsScreen,
UserProfileScreen,
};

View File

@@ -0,0 +1,97 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import {NotificationSettingsScreen} from '@support/ui/screen';
import {timeouts} from '@support/utils';
import {expect} from 'detox';
class MentionNotificationSettingsScreen {
testID = {
mentionNotificationSettingsScreen: 'mention_notification_settings.screen',
backButton: 'screen.back.button',
scrollView: 'mention_notification_settings.scroll_view',
caseSensitiveFirstNameOptionToggledOff: 'mention_notification_settings.case_sensitive_first_name.option.toggled.false',
caseSensitiveFirstNameOptionToggledOn: 'mention_notification_settings.case_sensitive_first_name.option.toggled.true',
nonCaseSensitiveUsernameOptionToggledOff: 'mention_notification_settings.non_case_sensitive_username.option.toggled.false',
nonCaseSensitiveUsernameOptionToggledOn: 'mention_notification_settings.non_case_sensitive_username.option.toggled.true',
channelWideMentionsOptionToggledOff: 'mention_notification_settings.channel_wide_mentions.option.toggled.false',
channelWideMentionsOptionToggledOn: 'mention_notification_settings.channel_wide_mentions.option.toggled.true',
keywordsInput: 'mention_notification_settings.keywords.input',
keywordsInputDescription: 'mention_notification_settings.keywords.input.description',
threadsStartParticipateOption: 'mention_notification_settings.threads_start_participate.option',
threadsStartParticipateOptionSelected: 'mention_notification_settings.threads_start_participate.option.selected',
threadsStartOption: 'mention_notification_settings.threads_start.option',
threadsStartOptionSelected: 'mention_notification_settings.threads_start.option.selected',
threadsMentionsOption: 'mention_notification_settings.threads_mentions.option',
threadsMentionsOptionSelected: 'mention_notification_settings.threads_mentions.option.selected',
};
mentionNotificationSettingsScreen = element(by.id(this.testID.mentionNotificationSettingsScreen));
backButton = element(by.id(this.testID.backButton));
scrollView = element(by.id(this.testID.scrollView));
caseSensitiveFirstNameOptionToggledOff = element(by.id(this.testID.caseSensitiveFirstNameOptionToggledOff));
caseSensitiveFirstNameOptionToggledOn = element(by.id(this.testID.caseSensitiveFirstNameOptionToggledOn));
nonCaseSensitiveUsernameOptionToggledOff = element(by.id(this.testID.nonCaseSensitiveUsernameOptionToggledOff));
nonCaseSensitiveUsernameOptionToggledOn = element(by.id(this.testID.nonCaseSensitiveUsernameOptionToggledOn));
channelWideMentionsOptionToggledOff = element(by.id(this.testID.channelWideMentionsOptionToggledOff));
channelWideMentionsOptionToggledOn = element(by.id(this.testID.channelWideMentionsOptionToggledOn));
keywordsInput = element(by.id(this.testID.keywordsInput));
keywordsInputDescription = element(by.id(this.testID.keywordsInputDescription));
threadsStartParticipateOption = element(by.id(this.testID.threadsStartParticipateOption));
threadsStartParticipateOptionSelected = element(by.id(this.testID.threadsStartParticipateOptionSelected));
threadsStartOption = element(by.id(this.testID.threadsStartOption));
threadsStartOptionSelected = element(by.id(this.testID.threadsStartOptionSelected));
threadsMentionsOption = element(by.id(this.testID.threadsMentionsOption));
threadsMentionsOptionSelected = element(by.id(this.testID.threadsMentionsOptionSelected));
toBeVisible = async () => {
await waitFor(this.mentionNotificationSettingsScreen).toExist().withTimeout(timeouts.TEN_SEC);
return this.mentionNotificationSettingsScreen;
};
open = async () => {
// # Open mention notification settings screen
await NotificationSettingsScreen.mentionsOption.tap();
return this.toBeVisible();
};
back = async () => {
await this.backButton.tap();
await expect(this.mentionNotificationSettingsScreen).not.toBeVisible();
};
toggleCaseSensitiveFirstNameOptionOn = async () => {
await this.caseSensitiveFirstNameOptionToggledOff.tap();
await expect(this.caseSensitiveFirstNameOptionToggledOn).toBeVisible();
};
toggleCaseSensitiveFirstNameOptionOff = async () => {
await this.caseSensitiveFirstNameOptionToggledOn.tap();
await expect(this.caseSensitiveFirstNameOptionToggledOff).toBeVisible();
};
toggleNonCaseSensitiveUsernameOptionOn = async () => {
await this.nonCaseSensitiveUsernameOptionToggledOff.tap();
await expect(this.nonCaseSensitiveUsernameOptionToggledOn).toBeVisible();
};
toggleNonCaseSensitiveUsernameOptionOff = async () => {
await this.nonCaseSensitiveUsernameOptionToggledOn.tap();
await expect(this.nonCaseSensitiveUsernameOptionToggledOff).toBeVisible();
};
toggleChannelWideMentionsOptionOn = async () => {
await this.channelWideMentionsOptionToggledOff.tap();
await expect(this.channelWideMentionsOptionToggledOn).toBeVisible();
};
toggleChannelWideMentionsOptionOff = async () => {
await this.channelWideMentionsOptionToggledOn.tap();
await expect(this.channelWideMentionsOptionToggledOff).toBeVisible();
};
}
const mentionNotificationSettingsScreen = new MentionNotificationSettingsScreen();
export default mentionNotificationSettingsScreen;

View File

@@ -0,0 +1,51 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import {SettingsScreen} from '@support/ui/screen';
import {timeouts} from '@support/utils';
import {expect} from 'detox';
class NotificationSettingsScreen {
testID = {
notificationSettingsScreen: 'notification_settings.screen',
backButton: 'screen.back.button',
scrollView: 'notification_settings.scroll_view',
mentionsOption: 'notification_settings.mentions.option',
pushNotificationsOption: 'notification_settings.push_notifications.option',
emailNotificationsOption: 'notification_settings.email_notifications.option',
emailNotificationsOptionInfo: 'notification_settings.email_notifications.option.info',
automaticRepliesOption: 'notification_settings.automatic_replies.option',
automaticRepliesOptionInfo: 'notification_settings.automatic_replies.option.info',
};
notificationSettingsScreen = element(by.id(this.testID.notificationSettingsScreen));
backButton = element(by.id(this.testID.backButton));
scrollView = element(by.id(this.testID.scrollView));
mentionsOption = element(by.id(this.testID.mentionsOption));
pushNotificationsOption = element(by.id(this.testID.pushNotificationsOption));
emailNotificationsOption = element(by.id(this.testID.emailNotificationsOption));
emailNotificationsOptionInfo = element(by.id(this.testID.emailNotificationsOptionInfo));
automaticRepliesOption = element(by.id(this.testID.automaticRepliesOption));
automaticRepliesOptionInfo = element(by.id(this.testID.automaticRepliesOptionInfo));
toBeVisible = async () => {
await waitFor(this.notificationSettingsScreen).toExist().withTimeout(timeouts.TEN_SEC);
return this.notificationSettingsScreen;
};
open = async () => {
// # Open notification settings screen
await SettingsScreen.notificationsOption.tap();
return this.toBeVisible();
};
back = async () => {
await this.backButton.tap();
await expect(this.notificationSettingsScreen).not.toBeVisible();
};
}
const notificationSettingsScreen = new NotificationSettingsScreen();
export default notificationSettingsScreen;

View File

@@ -0,0 +1,77 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import {NotificationSettingsScreen} from '@support/ui/screen';
import {timeouts} from '@support/utils';
import {expect} from 'detox';
class PushNotificationSettingsScreen {
testID = {
pushNotificationSettingsScreen: 'push_notification_settings.screen',
backButton: 'screen.back.button',
scrollView: 'push_notification_settings.scroll_view',
allNewMessagesOption: 'push_notification_settings.all_new_messages.option',
allNewMessagesOptionSelected: 'push_notification_settings.all_new_messages.option.selected',
mentionsOnlyOption: 'push_notification_settings.mentions_only.option',
mentionsOnlyOptionSelected: 'push_notification_settings.mentions_only.option.selected',
nothingOption: 'push_notification_settings.nothing.option',
nothingOptionSelected: 'push_notification_settings.nothing.option.selected',
pushThreadsFollowingOptionToggledOff: 'push_notification_settings.push_threads_following.option.toggled.false',
pushThreadsFollowingOptionToggledOn: 'push_notification_settings.push_threads_following.option.toggled.true',
mobileOnlineOption: 'push_notification_settings.mobile_online.option',
mobileOnlineOptionSelected: 'push_notification_settings.mobile_online.option.selected',
mobileAwayOption: 'push_notification_settings.mobile_away.option',
mobileAwayOptionSelected: 'push_notification_settings.mobile_away.option.selected',
mobileOfflineOption: 'push_notification_settings.mobile_offline.option',
mobileOfflineOptionSelected: 'push_notification_settings.mobile_offline.option.selected',
};
pushNotificationSettingsScreen = element(by.id(this.testID.pushNotificationSettingsScreen));
backButton = element(by.id(this.testID.backButton));
scrollView = element(by.id(this.testID.scrollView));
allNewMessagesOption = element(by.id(this.testID.allNewMessagesOption));
allNewMessagesOptionSelected = element(by.id(this.testID.allNewMessagesOptionSelected));
mentionsOnlyOption = element(by.id(this.testID.mentionsOnlyOption));
mentionsOnlyOptionSelected = element(by.id(this.testID.mentionsOnlyOptionSelected));
nothingOption = element(by.id(this.testID.nothingOption));
nothingOptionSelected = element(by.id(this.testID.nothingOptionSelected));
pushThreadsFollowingOptionToggledOff = element(by.id(this.testID.pushThreadsFollowingOptionToggledOff));
pushThreadsFollowingOptionToggledOn = element(by.id(this.testID.pushThreadsFollowingOptionToggledOn));
mobileOnlineOption = element(by.id(this.testID.mobileOnlineOption));
mobileOnlineOptionSelected = element(by.id(this.testID.mobileOnlineOptionSelected));
mobileAwayOption = element(by.id(this.testID.mobileAwayOption));
mobileAwayOptionSelected = element(by.id(this.testID.mobileAwayOptionSelected));
mobileOfflineOption = element(by.id(this.testID.mobileOfflineOption));
mobileOfflineOptionSelected = element(by.id(this.testID.mobileOfflineOptionSelected));
toBeVisible = async () => {
await waitFor(this.pushNotificationSettingsScreen).toExist().withTimeout(timeouts.TEN_SEC);
return this.pushNotificationSettingsScreen;
};
open = async () => {
// # Open push notification settings screen
await NotificationSettingsScreen.pushNotificationsOption.tap();
return this.toBeVisible();
};
back = async () => {
await this.backButton.tap();
await expect(this.pushNotificationSettingsScreen).not.toBeVisible();
};
togglePushThreadsFollowingOptionOn = async () => {
await this.pushThreadsFollowingOptionToggledOff.tap();
await expect(this.pushThreadsFollowingOptionToggledOn).toBeVisible();
};
togglePushThreadsFollowingOptionOff = async () => {
await this.pushThreadsFollowingOptionToggledOn.tap();
await expect(this.pushThreadsFollowingOptionToggledOff).toBeVisible();
};
}
const pushNotificationSettingsScreen = new PushNotificationSettingsScreen();
export default pushNotificationSettingsScreen;

View File

@@ -0,0 +1,56 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import {SearchBar} from '@support/ui/component';
import {TimezoneDisplaySettingsScreen} from '@support/ui/screen';
import {timeouts} from '@support/utils';
import {expect} from 'detox';
class SelectTimezoneScreen {
testID = {
selectTimezoneScreenPrefix: 'select_timezone.',
timezoneRowPrefix: 'select_timezone.timezone_row.',
selectTimezoneScreen: 'select_timezone.screen',
backButton: 'screen.back.button',
flatTimezoneList: 'select_timezone.timezone.flat_list',
};
selectTimezoneScreen = element(by.id(this.testID.selectTimezoneScreen));
backButton = element(by.id(this.testID.backButton));
flatTimezoneList = element(by.id(this.testID.flatTimezoneList));
// convenience props
searchBar = SearchBar.getSearchBar(this.testID.selectTimezoneScreenPrefix);
searchInput = SearchBar.getSearchInput(this.testID.selectTimezoneScreenPrefix);
cancelButton = SearchBar.getCancelButton(this.testID.selectTimezoneScreenPrefix);
clearButton = SearchBar.getClearButton(this.testID.selectTimezoneScreenPrefix);
getNonSelectedTimezoneRow = (timezone: string) => {
return element(by.id(`${this.testID.timezoneRowPrefix}${timezone}`));
};
getSelectedTimezoneRow = (timezone: string) => {
return element(by.id(`${this.testID.timezoneRowPrefix}${timezone}.selected`));
};
toBeVisible = async () => {
await waitFor(this.selectTimezoneScreen).toExist().withTimeout(timeouts.TEN_SEC);
return this.selectTimezoneScreen;
};
open = async () => {
// # Open select timezone screen
await TimezoneDisplaySettingsScreen.manualOption.tap();
return this.toBeVisible();
};
back = async () => {
await this.backButton.tap();
await expect(this.selectTimezoneScreen).not.toBeVisible();
};
}
const selectTimezoneScreen = new SelectTimezoneScreen();
export default selectTimezoneScreen;

View File

@@ -0,0 +1,63 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import {DisplaySettingsScreen} from '@support/ui/screen';
import {timeouts} from '@support/utils';
import {expect} from 'detox';
class ThemeDisplaySettingsScreen {
testID = {
themeDisplaySettingsScreen: 'theme_display_settings.screen',
backButton: 'screen.back.button',
scrollView: 'theme_display_settings.scroll_view',
denimOption: 'theme_display_settings.denim.option',
denimOptionSelected: 'theme_display_settings.denim.option.selected',
sapphireOption: 'theme_display_settings.sapphire.option',
sapphireOptionSelected: 'theme_display_settings.sapphire.option.selected',
quartzOption: 'theme_display_settings.quartz.option',
quartzOptionSelected: 'theme_display_settings.quartz.option.selected',
indigoOption: 'theme_display_settings.indigo.option',
indigoOptionSelected: 'theme_display_settings.indigo.option.selected',
onyxOption: 'theme_display_settings.onyx.option',
onyxOptionSelected: 'theme_display_settings.onyx.option.selected',
customOption: 'theme_display_settings.custom.option',
customOptionSelected: 'theme_display_settings.custom.option.selected',
};
themeDisplaySettingsScreen = element(by.id(this.testID.themeDisplaySettingsScreen));
backButton = element(by.id(this.testID.backButton));
scrollView = element(by.id(this.testID.scrollView));
denimOption = element(by.id(this.testID.denimOption));
denimOptionSelected = element(by.id(this.testID.denimOptionSelected));
sapphireOption = element(by.id(this.testID.sapphireOption));
sapphireOptionSelected = element(by.id(this.testID.sapphireOptionSelected));
quartzOption = element(by.id(this.testID.quartzOption));
quartzOptionSelected = element(by.id(this.testID.quartzOptionSelected));
indigoOption = element(by.id(this.testID.indigoOption));
indigoOptionSelected = element(by.id(this.testID.indigoOptionSelected));
onyxOption = element(by.id(this.testID.onyxOption));
onyxOptionSelected = element(by.id(this.testID.onyxOptionSelected));
customOption = element(by.id(this.testID.customOption));
customOptionSelected = element(by.id(this.testID.customOptionSelected));
toBeVisible = async () => {
await waitFor(this.themeDisplaySettingsScreen).toExist().withTimeout(timeouts.TEN_SEC);
return this.themeDisplaySettingsScreen;
};
open = async () => {
// # Open theme display settings screen
await DisplaySettingsScreen.themeOption.tap();
return this.toBeVisible();
};
back = async () => {
await this.backButton.tap();
await expect(this.themeDisplaySettingsScreen).not.toBeVisible();
};
}
const themeDisplaySettingsScreen = new ThemeDisplaySettingsScreen();
export default themeDisplaySettingsScreen;

View File

@@ -0,0 +1,57 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import {DisplaySettingsScreen} from '@support/ui/screen';
import {timeouts} from '@support/utils';
import {expect} from 'detox';
class TimezoneDisplaySettingsScreen {
testID = {
timezoneDisplaySettingsScreen: 'timezone_display_settings.screen',
backButton: 'screen.back.button',
scrollView: 'timezone_display_settings.scroll_view',
automaticOptionToggledOff: 'timezone_display_settings.automatic.option.toggled.false',
automaticOptionToggledOn: 'timezone_display_settings.automatic.option.toggled.true',
manualOption: 'timezone_display_settings.manual.option',
manualOptionInfo: 'timezone_display_settings.manual.option.info',
};
timezoneDisplaySettingsScreen = element(by.id(this.testID.timezoneDisplaySettingsScreen));
backButton = element(by.id(this.testID.backButton));
scrollView = element(by.id(this.testID.scrollView));
automaticOptionToggledOff = element(by.id(this.testID.automaticOptionToggledOff));
automaticOptionToggledOn = element(by.id(this.testID.automaticOptionToggledOn));
manualOption = element(by.id(this.testID.manualOption));
manualOptionInfo = element(by.id(this.testID.manualOptionInfo));
toBeVisible = async () => {
await waitFor(this.timezoneDisplaySettingsScreen).toExist().withTimeout(timeouts.TEN_SEC);
return this.timezoneDisplaySettingsScreen;
};
open = async () => {
// # Open timezone display settings screen
await DisplaySettingsScreen.timezoneOption.tap();
return this.toBeVisible();
};
back = async () => {
await this.backButton.tap();
await expect(this.timezoneDisplaySettingsScreen).not.toBeVisible();
};
toggleAutomaticOptionOn = async () => {
await this.automaticOptionToggledOff.tap();
await expect(this.automaticOptionToggledOn).toBeVisible();
};
toggleAutomaticOptionOff = async () => {
await this.automaticOptionToggledOn.tap();
await expect(this.automaticOptionToggledOff).toBeVisible();
};
}
const timezoneDisplaySettingsScreen = new TimezoneDisplaySettingsScreen();
export default timezoneDisplaySettingsScreen;

View File

@@ -0,0 +1,83 @@
// 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 {
AccountScreen,
HomeScreen,
LoginScreen,
AboutScreen,
ServerScreen,
SettingsScreen,
} from '@support/ui/screen';
import {expect} from 'detox';
describe('Account - Settings - About', () => {
const serverOneDisplayName = 'Server 1';
let testUser: any;
beforeAll(async () => {
const {user} = await Setup.apiInit(siteOneUrl);
testUser = user;
// # Log in to server, open account screen, open settings screen, and go to about screen
await ServerScreen.connectToServer(serverOneUrl, serverOneDisplayName);
await LoginScreen.login(testUser);
await AccountScreen.open();
await SettingsScreen.open();
await AboutScreen.open();
});
beforeEach(async () => {
// * Verify on about screen
await AboutScreen.toBeVisible();
});
afterAll(async () => {
// # Log out
await AboutScreen.back();
await SettingsScreen.close();
await HomeScreen.logout();
});
it('MM-T5104_1 - should match elements on about screen', async () => {
// * Verify basic elements on about screen
await expect(AboutScreen.backButton).toBeVisible();
await expect(AboutScreen.logo).toBeVisible();
await expect(AboutScreen.siteName).toBeVisible();
await expect(AboutScreen.title).toBeVisible();
await expect(AboutScreen.subtitle).toBeVisible();
await expect(AboutScreen.appVersionTitle).toHaveText('App Version:');
await expect(AboutScreen.appVersionValue).toBeVisible();
await expect(AboutScreen.serverVersionTitle).toHaveText('Server Version:');
await expect(AboutScreen.serverVersionValue).toBeVisible();
await expect(AboutScreen.databaseTitle).toHaveText('Database:');
await expect(AboutScreen.databaseValue).toBeVisible();
await expect(AboutScreen.databaseSchemaVersionTitle).toHaveText('Database Schema Version:');
await expect(AboutScreen.databaseSchemaVersionValue).toBeVisible();
await expect(AboutScreen.licensee).toBeVisible();
await expect(AboutScreen.learnMoreText).toHaveText('Learn more about Enterprise Edition at ');
await expect(AboutScreen.learnMoreUrl).toBeVisible();
await expect(AboutScreen.copyright).toHaveText(`Copyright 2015-${new Date().getFullYear()} Mattermost, Inc. All rights reserved`);
await expect(AboutScreen.termsOfService).toHaveText('Terms of Service');
await expect(AboutScreen.privacyPolicy).toHaveText('Privacy Policy');
await expect(AboutScreen.noticeText).toHaveText('Mattermost is made possible by the open source software used in our server and mobile apps.');
await AboutScreen.scrollView.scrollTo('bottom');
await expect(AboutScreen.buildHashTitle).toHaveText('Build Hash:');
await expect(AboutScreen.buildHashValue).toBeVisible();
await expect(AboutScreen.buildHashEnterpriseTitle).toHaveText('EE Build Hash:');
await expect(AboutScreen.buildHashEnterpriseValue).toBeVisible();
await expect(AboutScreen.buildDateTitle).toHaveText('Build Date:');
await expect(AboutScreen.buildDateValue).toBeVisible();
});
});

View File

@@ -0,0 +1,58 @@
// 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 {
AccountScreen,
AdvancedSettingsScreen,
HomeScreen,
LoginScreen,
ServerScreen,
SettingsScreen,
} from '@support/ui/screen';
import {expect} from 'detox';
describe('Account - Settings - Advanced Settings', () => {
const serverOneDisplayName = 'Server 1';
let testUser: any;
beforeAll(async () => {
const {user} = await Setup.apiInit(siteOneUrl);
testUser = user;
// # Log in to server, open account screen, open settings screen, and go to advanced settings screen
await ServerScreen.connectToServer(serverOneUrl, serverOneDisplayName);
await LoginScreen.login(testUser);
await AccountScreen.open();
await SettingsScreen.open();
await AdvancedSettingsScreen.open();
});
beforeEach(async () => {
// * Verify on advanced settings screen
await AdvancedSettingsScreen.toBeVisible();
});
afterAll(async () => {
// # Log out
await AdvancedSettingsScreen.back();
await SettingsScreen.close();
await HomeScreen.logout();
});
it('MM-T5103_1 - should match elements on advanced settings screen', async () => {
// * Verify basic elements on advanced settings screen
await expect(AdvancedSettingsScreen.backButton).toBeVisible();
await expect(AdvancedSettingsScreen.deleteDataOption).toBeVisible();
});
});

View File

@@ -0,0 +1,97 @@
// 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 {
AccountScreen,
AutoResponderNotificationSettingsScreen,
HomeScreen,
LoginScreen,
NotificationSettingsScreen,
ServerScreen,
SettingsScreen,
} from '@support/ui/screen';
import {getRandomId} from '@support/utils';
import {expect} from 'detox';
describe('Account - Settings - Auto-Responder Notification Settings', () => {
const serverOneDisplayName = 'Server 1';
let testUser: any;
beforeAll(async () => {
const {user} = await Setup.apiInit(siteOneUrl);
testUser = user;
// # Log in to server, open account screen, open settings screen, open notification settings screen, and go to auto-responder notification settings screen
await ServerScreen.connectToServer(serverOneUrl, serverOneDisplayName);
await LoginScreen.login(testUser);
await AccountScreen.open();
await SettingsScreen.open();
await NotificationSettingsScreen.open();
await AutoResponderNotificationSettingsScreen.open();
});
beforeEach(async () => {
// * Verify on auto-responder notification settings screen
await AutoResponderNotificationSettingsScreen.toBeVisible();
});
afterAll(async () => {
// # Log out
await AutoResponderNotificationSettingsScreen.back();
await NotificationSettingsScreen.back();
await SettingsScreen.close();
await HomeScreen.logout();
});
it('MM-T5110_1 - should match elements on auto-responder notification settings screen', async () => {
// * Verify basic elements on auto-responder notification settings screen
await expect(AutoResponderNotificationSettingsScreen.backButton).toBeVisible();
await expect(AutoResponderNotificationSettingsScreen.enableAutomaticRepliesOptionToggledOff).toBeVisible();
await expect(AutoResponderNotificationSettingsScreen.messageInputDescription).toHaveText('Set a custom message that is automatically sent in response to direct messages, such as an out of office or vacation reply. Enabling this setting changes your status to Out of Office and disables notifications.');
});
it('MM-T5110_2 - should be able to change auto-responder notification settings and save by tapping navigation back button', async () => {
// # Toggle enable automatic replies option on, type in message, and tap on back button
const message = `Message ${getRandomId()}`;
await AutoResponderNotificationSettingsScreen.toggleEnableAutomaticRepliesOptionOn();
await AutoResponderNotificationSettingsScreen.messageInput.replaceText(message);
await AutoResponderNotificationSettingsScreen.back();
// * Verify on notification settings screen and automatic replies is enabled
await NotificationSettingsScreen.toBeVisible();
await expect(NotificationSettingsScreen.automaticRepliesOptionInfo).toHaveText('On');
// * Go back to auto-responder notification settings screen
await AutoResponderNotificationSettingsScreen.open();
// * Verify enable automatic replies option is toggled on and message is saved
await expect(AutoResponderNotificationSettingsScreen.enableAutomaticRepliesOptionToggledOn).toBeVisible();
await expect(AutoResponderNotificationSettingsScreen.messageInput).toHaveValue(message);
// # Toggle enable automatic replies option off and tap on back button
await AutoResponderNotificationSettingsScreen.toggleEnableAutomaticRepliesOptionOff();
await AutoResponderNotificationSettingsScreen.back();
// * Verify on notification settings screen and automatic replies is disabled
await NotificationSettingsScreen.toBeVisible();
await expect(NotificationSettingsScreen.automaticRepliesOptionInfo).toHaveText('Off');
// * Go back to auto-responder notification settings screen
await AutoResponderNotificationSettingsScreen.open();
// * Verify enable automatic replies option is toggled off and message input does not exist
await expect(AutoResponderNotificationSettingsScreen.enableAutomaticRepliesOptionToggledOff).toBeVisible();
await expect(AutoResponderNotificationSettingsScreen.messageInput).not.toExist();
});
});

View File

@@ -0,0 +1,92 @@
// 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 {
AccountScreen,
ClockDisplaySettingsScreen,
DisplaySettingsScreen,
HomeScreen,
LoginScreen,
ServerScreen,
SettingsScreen,
} from '@support/ui/screen';
import {expect} from 'detox';
describe('Account - Settings - Clock Display Settings', () => {
const serverOneDisplayName = 'Server 1';
let testUser: any;
beforeAll(async () => {
const {user} = await Setup.apiInit(siteOneUrl);
testUser = user;
// # Log in to server, open account screen, open settings screen, open display settings screen, and go to clock display settings
await ServerScreen.connectToServer(serverOneUrl, serverOneDisplayName);
await LoginScreen.login(testUser);
await AccountScreen.open();
await SettingsScreen.open();
await DisplaySettingsScreen.open();
await ClockDisplaySettingsScreen.open();
});
beforeEach(async () => {
// * Verify on clock display settings screen
await ClockDisplaySettingsScreen.toBeVisible();
});
afterAll(async () => {
// # Log out
await ClockDisplaySettingsScreen.back();
await DisplaySettingsScreen.back();
await SettingsScreen.close();
await HomeScreen.logout();
});
it('MM-T5112_1 - should match elements on clock display settings screen', async () => {
// * Verify basic elements on clock display settings screen
await expect(ClockDisplaySettingsScreen.backButton).toBeVisible();
await expect(ClockDisplaySettingsScreen.twelveHourOption).toBeVisible();
await expect(ClockDisplaySettingsScreen.twentyFourHourOption).toBeVisible();
});
it('MM-T5112_2 - should be able to select a clock display and save by tapping navigation back button', async () => {
// # Tap on a twenty four hour option and tap on back button
await ClockDisplaySettingsScreen.twentyFourHourOption.tap();
await ClockDisplaySettingsScreen.back();
// * Verify on display settings screen and twenty four hour is set
await DisplaySettingsScreen.toBeVisible();
await expect(DisplaySettingsScreen.clockDisplayOptionInfo).toHaveText('24-hour');
// # Go back to clock display settings screen
await ClockDisplaySettingsScreen.open();
// * Verify twenty four option is selected
await expect(ClockDisplaySettingsScreen.twentyFourHourOptionSelected).toBeVisible();
// # Tap on twelve hour option and tap on back button
await ClockDisplaySettingsScreen.twelveHourOption.tap();
await ClockDisplaySettingsScreen.back();
// * Verify on display settings screen and twelve hour is set
await DisplaySettingsScreen.toBeVisible();
await expect(DisplaySettingsScreen.clockDisplayOptionInfo).toHaveText('12-hour');
// # Go back to clock display settings screen
await ClockDisplaySettingsScreen.open();
// * Verify twelve hour option is selected
await expect(ClockDisplaySettingsScreen.twelveHourOptionSelected).toBeVisible();
});
});

View File

@@ -0,0 +1,188 @@
// 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 {
AccountScreen,
CustomStatusScreen,
EmojiPickerScreen,
HomeScreen,
LoginScreen,
ServerScreen,
} from '@support/ui/screen';
import {getRandomId} from '@support/utils';
import {expect} from 'detox';
describe('Account - Custom Status', () => {
const serverOneDisplayName = 'Server 1';
let testUser: any;
beforeAll(async () => {
const {user} = await Setup.apiInit(siteOneUrl);
testUser = user;
// # Log in to server and go to account screen
await ServerScreen.connectToServer(serverOneUrl, serverOneDisplayName);
await LoginScreen.login(testUser);
await AccountScreen.open();
});
beforeEach(async () => {
// * Verify on account screen
await AccountScreen.toBeVisible();
});
afterAll(async () => {
// # Log out
await HomeScreen.logout();
});
it('MM-T4990_1 - should match elements on custom status screen', async () => {
// # Open custom status screen
await CustomStatusScreen.open();
// * Verify basic elements on custom status screen
await expect(CustomStatusScreen.doneButton).toBeVisible();
await expect(CustomStatusScreen.getCustomStatusEmoji('default')).toBeVisible();
await expect(CustomStatusScreen.statusInput).toBeVisible();
await expect(CustomStatusScreen.suggestions).toBeVisible();
await verifySuggestedCustomStatus('calendar', 'In a meeting', 'one_hour');
await verifySuggestedCustomStatus('hamburger', 'Out for lunch', 'thirty_minutes');
await verifySuggestedCustomStatus('sneezing_face', 'Out sick', 'today');
await verifySuggestedCustomStatus('house', 'Working from home', 'today');
await verifySuggestedCustomStatus('palm_tree', 'On a vacation', 'this_week');
// # Go back to account screen
await CustomStatusScreen.close();
});
it('MM-T4990_2 - should be able to set a status via suggestions', async () => {
// # Open custom status screen, tap on a suggested custom status, and tap on done button
const customStatusEmojiName = 'calendar';
const customStatusText = 'In a meeting';
const customStatusDuration = 'one_hour';
await CustomStatusScreen.open();
const {customStatusSuggestion} = CustomStatusScreen.getSuggestedCustomStatus(customStatusEmojiName, customStatusText, customStatusDuration);
await customStatusSuggestion.tap();
await CustomStatusScreen.doneButton.tap();
// * Verify on account screen and suggested custom status is set
await verifyOnAccountScreenAndCustomStatusIsSet(customStatusEmojiName, customStatusText, customStatusDuration);
// # Open custom status screen
await CustomStatusScreen.open();
// * Verify custom status is set on the field, shown under recent, and removed from suggestions
await expect(CustomStatusScreen.getCustomStatusEmoji(customStatusEmojiName)).toBeVisible();
await expect(CustomStatusScreen.statusInput).toHaveValue(customStatusText);
const {customStatusSuggestion: recentCustomStatus, customStatusClearButton: recentCustomStatusClearButton} = CustomStatusScreen.getRecentCustomStatus(customStatusEmojiName, customStatusText, customStatusDuration);
await expect(recentCustomStatus).toBeVisible();
const {customStatusSuggestion: suggestedCustomStatus} = CustomStatusScreen.getSuggestedCustomStatus(customStatusEmojiName, customStatusText, customStatusDuration);
await expect(suggestedCustomStatus).not.toExist();
// # Tap on clear button for custom status from recent
await recentCustomStatusClearButton.tap();
// * Verify custom status is removed from recent and shown back under suggestions
await expect(recentCustomStatus).not.toExist();
await expect(suggestedCustomStatus).toBeVisible();
// # Tap on status input clear button and tap on done button
await CustomStatusScreen.statusInputClearButton.tap();
await CustomStatusScreen.doneButton.tap();
});
it('MM-T4990_3 - should be able to set a status via emoji picker and custom status', async () => {
// # Open custom status screen, pick an emoji and type in custom status, and tap on done button
const customStatusEmojiName = 'clown_face';
const customStatusText = `Status ${getRandomId()}`;
const customStatusDuration = 'today';
await CustomStatusScreen.open();
await CustomStatusScreen.openEmojiPicker('default');
await EmojiPickerScreen.searchInput.replaceText(customStatusEmojiName);
await element(by.text('🤡')).tap();
await CustomStatusScreen.statusInput.replaceText(customStatusText);
await CustomStatusScreen.doneButton.tap();
// * Verify on account screen and custom status is set
await verifyOnAccountScreenAndCustomStatusIsSet(customStatusEmojiName, customStatusText, customStatusDuration);
// # Open custom status screen
await CustomStatusScreen.open();
// * Verify custom status is set on the field and shown under recent
await expect(CustomStatusScreen.getCustomStatusEmoji(customStatusEmojiName)).toBeVisible();
await expect(CustomStatusScreen.statusInput).toHaveValue(customStatusText);
const {customStatusSuggestion: recentCustomStatus, customStatusClearButton: recentCustomStatusClearButton} = CustomStatusScreen.getRecentCustomStatus(customStatusEmojiName, customStatusText, customStatusDuration);
await expect(recentCustomStatus).toBeVisible();
// # Tap on clear button for custom status from recent
await recentCustomStatusClearButton.tap();
// * Verify custom status is removed from recent
await expect(recentCustomStatus).not.toExist();
// # Tap on status input clear button and tap on done button
await CustomStatusScreen.statusInputClearButton.tap();
await CustomStatusScreen.doneButton.tap();
});
it('MM-T4990_4 - should be able to clear custom status from account', async () => {
// # Open custom status screen, tap on a suggested custom status, and tap on done button
const customStatusEmojiName = 'calendar';
const customStatusText = 'In a meeting';
const customStatusDuration = 'one_hour';
await CustomStatusScreen.open();
const {customStatusSuggestion} = CustomStatusScreen.getSuggestedCustomStatus(customStatusEmojiName, customStatusText, customStatusDuration);
await customStatusSuggestion.tap();
await CustomStatusScreen.doneButton.tap();
// * Verify on account screen and suggested custom status is set
await verifyOnAccountScreenAndCustomStatusIsSet(customStatusEmojiName, customStatusText, customStatusDuration);
// # Tap on clear button for custom status from display field
await AccountScreen.customStatusClearButton.tap();
// * Verify custom status is cleared from account screen
const defaultStatusText = 'Set a Status';
const {accountCustomStatusEmoji, accountCustomStatusText, accountCustomStatusExpiry} = AccountScreen.getCustomStatus(customStatusEmojiName, customStatusDuration);
await expect(accountCustomStatusEmoji).not.toExist();
await expect(accountCustomStatusText).toHaveText(defaultStatusText);
await expect(accountCustomStatusExpiry).not.toExist();
// # Open custom status screen
await CustomStatusScreen.open();
// * Verify custom status is cleared from input field
await expect(CustomStatusScreen.getCustomStatusEmoji('default')).toBeVisible();
await expect(CustomStatusScreen.statusInput).toHaveValue(defaultStatusText);
// # Go back to account screen
await CustomStatusScreen.close();
});
});
const verifySuggestedCustomStatus = async (emojiName: string, text: string, duration: string) => {
const {customStatusSuggestionEmoji, customStatusSuggestionText, customStatusSuggestionDuration} = CustomStatusScreen.getSuggestedCustomStatus(emojiName, text, duration);
await expect(customStatusSuggestionEmoji).toBeVisible();
await expect(customStatusSuggestionText).toBeVisible();
await expect(customStatusSuggestionDuration).toBeVisible();
};
const verifyOnAccountScreenAndCustomStatusIsSet = async (emojiName: string, text: string, duration: string) => {
await AccountScreen.toBeVisible();
const {accountCustomStatusEmoji, accountCustomStatusText, accountCustomStatusExpiry} = AccountScreen.getCustomStatus(emojiName, duration);
await expect(accountCustomStatusEmoji).toBeVisible();
await expect(accountCustomStatusText).toHaveText(text);
await expect(accountCustomStatusExpiry).toBeVisible();
};

View File

@@ -0,0 +1,96 @@
// 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 {
AccountScreen,
ClockDisplaySettingsScreen,
DisplaySettingsScreen,
HomeScreen,
LoginScreen,
ServerScreen,
SettingsScreen,
ThemeDisplaySettingsScreen,
TimezoneDisplaySettingsScreen,
} from '@support/ui/screen';
import {expect} from 'detox';
describe('Account - Settings - Display Settings', () => {
const serverOneDisplayName = 'Server 1';
let testUser: any;
beforeAll(async () => {
const {user} = await Setup.apiInit(siteOneUrl);
testUser = user;
// # Log in to server, open account screen, open settings screen, and go to display settings screen
await ServerScreen.connectToServer(serverOneUrl, serverOneDisplayName);
await LoginScreen.login(testUser);
await AccountScreen.open();
await SettingsScreen.open();
await DisplaySettingsScreen.open();
});
beforeEach(async () => {
// * Verify on display settings screen
await DisplaySettingsScreen.toBeVisible();
});
afterAll(async () => {
// # Log out
await DisplaySettingsScreen.back();
await SettingsScreen.close();
await HomeScreen.logout();
});
it('MM-T5102_1 - should match elements on display settings screen', async () => {
// * Verify basic elements on display settings screen
await expect(DisplaySettingsScreen.backButton).toBeVisible();
await expect(DisplaySettingsScreen.themeOption).toBeVisible();
await expect(DisplaySettingsScreen.clockDisplayOption).toBeVisible();
await expect(DisplaySettingsScreen.timezoneOption).toBeVisible();
});
it('MM-T5102_2 - should be able to go to theme display settings screen', async () => {
// # Tap on theme option
await DisplaySettingsScreen.themeOption.tap();
// * Verify on theme display settings screen
await ThemeDisplaySettingsScreen.toBeVisible();
// # Go back to display settings screen
await ThemeDisplaySettingsScreen.back();
});
it('MM-T5102_3 - should be able to go to clock display settings screen', async () => {
// # Tap on clock display option
await DisplaySettingsScreen.clockDisplayOption.tap();
// * Verify on clock display settings screen
await ClockDisplaySettingsScreen.toBeVisible();
// # Go back to display settings screen
await ClockDisplaySettingsScreen.back();
});
it('MM-T5102_4 - should be able to go to timezone display settings screen', async () => {
// # Tap on timezone option
await DisplaySettingsScreen.timezoneOption.tap();
// # Verify on timezone display settings screen
await TimezoneDisplaySettingsScreen.toBeVisible();
// # Go back to display settings screen
await TimezoneDisplaySettingsScreen.back();
});
});

View File

@@ -0,0 +1,106 @@
// 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 {
AccountScreen,
EditProfileScreen,
HomeScreen,
LoginScreen,
ServerScreen,
} from '@support/ui/screen';
import {getRandomId} from '@support/utils';
import {expect} from 'detox';
describe('Account - Edit Profile', () => {
const serverOneDisplayName = 'Server 1';
let testUser: any;
beforeAll(async () => {
const {user} = await Setup.apiInit(siteOneUrl);
testUser = user;
// # Log in to server and go to account screen
await ServerScreen.connectToServer(serverOneUrl, serverOneDisplayName);
await LoginScreen.login(testUser);
await AccountScreen.open();
});
beforeEach(async () => {
// * Verify on account screen
await AccountScreen.toBeVisible();
});
afterAll(async () => {
// # Log out
await HomeScreen.logout();
});
it('MM-T4989_1 - should match elements on edit profile screen', async () => {
// # Open edit profile screen
await EditProfileScreen.open();
// * Verify basic elements on edit profile screen
await expect(EditProfileScreen.closeButton).toBeVisible();
await expect(EditProfileScreen.saveButton).toBeVisible();
await expect(EditProfileScreen.getEditProfilePicture(testUser.id)).toBeVisible();
await expect(EditProfileScreen.firstNameInput).toHaveValue(testUser.first_name);
await expect(EditProfileScreen.lastNameInput).toHaveValue(testUser.last_name);
await expect(EditProfileScreen.usernameInput).toHaveValue(testUser.username);
await expect(EditProfileScreen.emailInputDisabled).toHaveValue(testUser.email);
await expect(EditProfileScreen.emailInputDescription).toHaveText('Email must be updated using a web client or desktop application.');
await expect(EditProfileScreen.nicknameInput).toHaveValue(testUser.nickname);
await expect(EditProfileScreen.positionInput).toHaveValue(testUser.position);
// # Go back to account screen
await EditProfileScreen.close();
});
it('MM-T4989_2 - should be able to edit profile and save', async () => {
// # Open edit profile screen, edit fields, and tap on save button
const suffix = getRandomId(3);
await EditProfileScreen.open();
await EditProfileScreen.firstNameInput.replaceText(`${testUser.first_name}${suffix}`);
await EditProfileScreen.lastNameInput.replaceText(`${testUser.last_name}${suffix}`);
await EditProfileScreen.scrollView.tap({x: 1, y: 1});
await EditProfileScreen.scrollView.scroll(100, 'down');
await EditProfileScreen.usernameInput.clearText();
await EditProfileScreen.usernameInput.typeText(`${testUser.username}${suffix}`);
await EditProfileScreen.scrollView.tap({x: 1, y: 1});
await EditProfileScreen.scrollView.scroll(100, 'down');
await EditProfileScreen.nicknameInput.replaceText(`${testUser.nickname}${suffix}`);
await EditProfileScreen.scrollView.tap({x: 1, y: 1});
await EditProfileScreen.positionInput.replaceText(`${testUser.position}${suffix}`);
await EditProfileScreen.saveButton.tap();
// * Verify on account screen and user full name and username are updated
await AccountScreen.toBeVisible();
const {userInfoUserDisplayName, userInfoUsername} = AccountScreen.getUserInfo(testUser.id);
await expect(userInfoUserDisplayName).toHaveText(`${testUser.first_name}${suffix} ${testUser.last_name}${suffix} (${testUser.nickname}${suffix})`);
await expect(userInfoUsername).toHaveText(`@${testUser.username}${suffix}`);
// # Open edit profile screen
await EditProfileScreen.open();
// * Verify edited profile fields contain the updated values
await expect(EditProfileScreen.firstNameInput).toHaveValue(`${testUser.first_name}${suffix}`);
await expect(EditProfileScreen.lastNameInput).toHaveValue(`${testUser.last_name}${suffix}`);
await expect(EditProfileScreen.usernameInput).toHaveValue(`${testUser.username}${suffix}`);
await expect(EditProfileScreen.emailInputDisabled).toHaveValue(testUser.email);
await expect(EditProfileScreen.nicknameInput).toHaveValue(`${testUser.nickname}${suffix}`);
await expect(EditProfileScreen.positionInput).toHaveValue(`${testUser.position}${suffix}`);
// # Go back to account screen
await EditProfileScreen.close();
});
});

View File

@@ -0,0 +1,105 @@
// 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 {
AccountScreen,
EmailNotificationSettingsScreen,
HomeScreen,
LoginScreen,
NotificationSettingsScreen,
ServerScreen,
SettingsScreen,
} from '@support/ui/screen';
import {expect} from 'detox';
describe('Account - Settings - Email Notification Settings', () => {
const serverOneDisplayName = 'Server 1';
let testUser: any;
beforeAll(async () => {
const {user} = await Setup.apiInit(siteOneUrl);
testUser = user;
// # Log in to server, open account screen, open settings screen, open notification settings screen, and go to email notification settings screen
await ServerScreen.connectToServer(serverOneUrl, serverOneDisplayName);
await LoginScreen.login(testUser);
await AccountScreen.open();
await SettingsScreen.open();
await NotificationSettingsScreen.open();
await EmailNotificationSettingsScreen.open();
});
beforeEach(async () => {
// * Verify on email notification settings screen
await EmailNotificationSettingsScreen.toBeVisible();
});
afterAll(async () => {
// # Log out
await EmailNotificationSettingsScreen.back();
await NotificationSettingsScreen.back();
await SettingsScreen.close();
await HomeScreen.logout();
});
it('MM-T5109_1 - should match elements on email notification settings screen', async () => {
// * Verify basic elements on email notification settings screen
await expect(EmailNotificationSettingsScreen.backButton).toBeVisible();
await expect(EmailNotificationSettingsScreen.immediatelyOption).toBeVisible();
await expect(EmailNotificationSettingsScreen.neverOption).toBeVisible();
await expect(EmailNotificationSettingsScreen.emailThreadsOptionToggledOn).toBeVisible();
});
it('MM-T5109_2 - should be able to change email notification settings and save by tapping navigation back button', async () => {
// # Tap on never option
await EmailNotificationSettingsScreen.neverOption.tap();
// * Verify email threads option does not exist
await expect(EmailNotificationSettingsScreen.emailThreadsOptionToggledOn).not.toExist();
// # Tap on back button
await EmailNotificationSettingsScreen.back();
// * Verify on notification settings screen and never is set
await NotificationSettingsScreen.toBeVisible();
await expect(NotificationSettingsScreen.emailNotificationsOptionInfo).toHaveText('Never');
// # Go back to email notification settings screen
await EmailNotificationSettingsScreen.open();
// * Verify never option is selected
await expect(EmailNotificationSettingsScreen.neverOptionSelected).toBeVisible();
// # Tap on immediately option, toggle email threads option off, and tap on back button
await EmailNotificationSettingsScreen.immediatelyOption.tap();
await EmailNotificationSettingsScreen.toggleEmailThreadsOptionOff();
await EmailNotificationSettingsScreen.back();
// * Verify on notification settings screen and immediately is set
await NotificationSettingsScreen.toBeVisible();
await expect(NotificationSettingsScreen.emailNotificationsOptionInfo).toHaveText('Immediately');
// # Go back to email notification settings screen
await EmailNotificationSettingsScreen.open();
// * Verify immediately option is selected and email thread option is toggled off
await expect(EmailNotificationSettingsScreen.immediatelyOptionSelected).toBeVisible();
await expect(EmailNotificationSettingsScreen.emailThreadsOptionToggledOff).toBeVisible();
// # Toggle email threads option off, tap on back button, and go back to email notification settings screen
await EmailNotificationSettingsScreen.toggleEmailThreadsOptionOn();
await EmailNotificationSettingsScreen.back();
await EmailNotificationSettingsScreen.open();
});
});

View File

@@ -0,0 +1,97 @@
// 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 {
AccountScreen,
HomeScreen,
LoginScreen,
MentionNotificationSettingsScreen,
NotificationSettingsScreen,
ServerScreen,
SettingsScreen,
} from '@support/ui/screen';
import {getRandomId} from '@support/utils';
import {expect} from 'detox';
describe('Account - Settings - Mention Notification Settings', () => {
const serverOneDisplayName = 'Server 1';
let testUser: any;
beforeAll(async () => {
const {user} = await Setup.apiInit(siteOneUrl);
testUser = user;
// # Log in to server, open account screen, open settings screen, open notification settings screen, and go to mention notification settings screen
await ServerScreen.connectToServer(serverOneUrl, serverOneDisplayName);
await LoginScreen.login(testUser);
await AccountScreen.open();
await SettingsScreen.open();
await NotificationSettingsScreen.open();
await MentionNotificationSettingsScreen.open();
});
beforeEach(async () => {
// * Verify on mention notification settings screen
await MentionNotificationSettingsScreen.toBeVisible();
});
afterAll(async () => {
// # Log out
await MentionNotificationSettingsScreen.back();
await NotificationSettingsScreen.back();
await SettingsScreen.close();
await HomeScreen.logout();
});
it('MM-T5107_1 - should match elements on mention notification settings screen', async () => {
// * Verify basic elements on mention notification settings screen
await expect(MentionNotificationSettingsScreen.backButton).toBeVisible();
await expect(MentionNotificationSettingsScreen.caseSensitiveFirstNameOptionToggledOff).toBeVisible();
await expect(MentionNotificationSettingsScreen.nonCaseSensitiveUsernameOptionToggledOff).toBeVisible();
await expect(MentionNotificationSettingsScreen.channelWideMentionsOptionToggledOn).toBeVisible();
await expect(MentionNotificationSettingsScreen.keywordsInput).toBeVisible();
await expect(MentionNotificationSettingsScreen.keywordsInputDescription).toHaveText('Keywords are not case-sensitive. Separate keywords with commas.');
});
it('MM-T5107_2 - should be able to change mention notification settings and save by tapping navigation back button', async () => {
// # Switch toggles, type in keywords as camelcase with spaces, tap on back button, and go back to mention notifications screen
const keywords = ` Keywords ${getRandomId()} `;
await MentionNotificationSettingsScreen.toggleCaseSensitiveFirstNameOptionOn();
await MentionNotificationSettingsScreen.toggleNonCaseSensitiveUsernameOptionOn();
await MentionNotificationSettingsScreen.toggleChannelWideMentionsOptionOff();
await MentionNotificationSettingsScreen.keywordsInput.replaceText(keywords);
await MentionNotificationSettingsScreen.back();
await MentionNotificationSettingsScreen.open();
// * Verify toggles are switched and keywords are saved as lowercase without spaces
await expect(MentionNotificationSettingsScreen.caseSensitiveFirstNameOptionToggledOn).toBeVisible();
await expect(MentionNotificationSettingsScreen.nonCaseSensitiveUsernameOptionToggledOn).toBeVisible();
await expect(MentionNotificationSettingsScreen.channelWideMentionsOptionToggledOff).toBeVisible();
await expect(MentionNotificationSettingsScreen.keywordsInput).toHaveValue(keywords.replace(/ /g, '').toLowerCase());
// # Switch toggles back to original state, clear keywords, tap on back button, and go back to mention notifications screen
await MentionNotificationSettingsScreen.toggleCaseSensitiveFirstNameOptionOff();
await MentionNotificationSettingsScreen.toggleNonCaseSensitiveUsernameOptionOff();
await MentionNotificationSettingsScreen.toggleChannelWideMentionsOptionOn();
await MentionNotificationSettingsScreen.keywordsInput.clearText();
await MentionNotificationSettingsScreen.back();
await MentionNotificationSettingsScreen.open();
// * Verify toggles are switched back to original state and keywords are cleared
await expect(MentionNotificationSettingsScreen.caseSensitiveFirstNameOptionToggledOff).toBeVisible();
await expect(MentionNotificationSettingsScreen.nonCaseSensitiveUsernameOptionToggledOff).toBeVisible();
await expect(MentionNotificationSettingsScreen.channelWideMentionsOptionToggledOn).toBeVisible();
await expect(MentionNotificationSettingsScreen.keywordsInput).not.toHaveValue(keywords.replace(/ /g, '').toLowerCase());
});
});

View File

@@ -0,0 +1,109 @@
// 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 {
AccountScreen,
AutoResponderNotificationSettingsScreen,
EmailNotificationSettingsScreen,
HomeScreen,
LoginScreen,
MentionNotificationSettingsScreen,
NotificationSettingsScreen,
PushNotificationSettingsScreen,
ServerScreen,
SettingsScreen,
} from '@support/ui/screen';
import {expect} from 'detox';
describe('Account - Settings - Notification Settings', () => {
const serverOneDisplayName = 'Server 1';
let testUser: any;
beforeAll(async () => {
const {user} = await Setup.apiInit(siteOneUrl);
testUser = user;
// # Log in to server, open account screen, open settings screen, and go to notification settings screen
await ServerScreen.connectToServer(serverOneUrl, serverOneDisplayName);
await LoginScreen.login(testUser);
await AccountScreen.open();
await SettingsScreen.open();
await NotificationSettingsScreen.open();
});
beforeEach(async () => {
// * Verify on notification settings screen
await NotificationSettingsScreen.toBeVisible();
});
afterAll(async () => {
// # Log out
await NotificationSettingsScreen.back();
await SettingsScreen.close();
await HomeScreen.logout();
});
it('MM-T5101_1 - should match elements on notification settings screen', async () => {
// * Verify basic elements on notification settings screen
await expect(NotificationSettingsScreen.backButton).toBeVisible();
await expect(NotificationSettingsScreen.mentionsOption).toBeVisible();
await expect(NotificationSettingsScreen.pushNotificationsOption).toBeVisible();
await expect(NotificationSettingsScreen.emailNotificationsOption).toBeVisible();
await expect(NotificationSettingsScreen.automaticRepliesOption).toBeVisible();
});
it('MM-T5101_2 - should be able to go to mention notification settings screen', async () => {
// # Tap on mention option
await NotificationSettingsScreen.mentionsOption.tap();
// * Verify on mention notification settings screen
await MentionNotificationSettingsScreen.toBeVisible();
// # Go back to notification settings screen
await MentionNotificationSettingsScreen.back();
});
it('MM-T5101_3 - should be able to go to push notification settings screen', async () => {
// # Tap on push notifications option
await NotificationSettingsScreen.pushNotificationsOption.tap();
// * Verify on push notification settings screen
await PushNotificationSettingsScreen.toBeVisible();
// # Go back to notification settings screen
await PushNotificationSettingsScreen.back();
});
it('MM-T5101_4 - should be able to go to email notification settings screen', async () => {
// # Tap on email notifications option
await NotificationSettingsScreen.emailNotificationsOption.tap();
// # Verify on email notification settings screen
await EmailNotificationSettingsScreen.toBeVisible();
// # Go back to notification settings screen
await EmailNotificationSettingsScreen.back();
});
it('MM-T5101_5 - should be able to go to auto-responder notification settings screen', async () => {
// # Tap on automatic replies option
await NotificationSettingsScreen.automaticRepliesOption.tap();
// # Verify on auto-responder notification settings screen
await AutoResponderNotificationSettingsScreen.toBeVisible();
// # Go back to notification settings screen
await AutoResponderNotificationSettingsScreen.back();
});
});

View File

@@ -0,0 +1,111 @@
// 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 {
AccountScreen,
HomeScreen,
LoginScreen,
NotificationSettingsScreen,
PushNotificationSettingsScreen,
ServerScreen,
SettingsScreen,
} from '@support/ui/screen';
import {expect} from 'detox';
describe('Account - Settings - Push Notification Settings', () => {
const serverOneDisplayName = 'Server 1';
let testUser: any;
beforeAll(async () => {
const {user} = await Setup.apiInit(siteOneUrl);
testUser = user;
// # Log in to server, open account screen, open settings screen, open notification settings screen, and go to push notification settings screen
await ServerScreen.connectToServer(serverOneUrl, serverOneDisplayName);
await LoginScreen.login(testUser);
await AccountScreen.open();
await SettingsScreen.open();
await NotificationSettingsScreen.open();
await PushNotificationSettingsScreen.open();
});
beforeEach(async () => {
// * Verify on push notification settings screen
await PushNotificationSettingsScreen.toBeVisible();
});
afterAll(async () => {
// # Log out
await PushNotificationSettingsScreen.back();
await NotificationSettingsScreen.back();
await SettingsScreen.close();
await HomeScreen.logout();
});
it('MM-T5108_1 - should match elements on push notification settings screen', async () => {
// * Verify basic elements on push notification settings screen
await expect(PushNotificationSettingsScreen.backButton).toBeVisible();
await expect(PushNotificationSettingsScreen.allNewMessagesOption).toBeVisible();
await expect(PushNotificationSettingsScreen.mentionsOnlyOption).toBeVisible();
await expect(PushNotificationSettingsScreen.nothingOption).toBeVisible();
await expect(PushNotificationSettingsScreen.pushThreadsFollowingOptionToggledOn).toBeVisible();
await expect(PushNotificationSettingsScreen.mobileOnlineOption).toBeVisible();
await expect(PushNotificationSettingsScreen.mobileAwayOption).toBeVisible();
await expect(PushNotificationSettingsScreen.mobileOfflineOption).toBeVisible();
});
it('MM-T5108_2 - should be able to change push notification settings and save by tapping navigation back button', async () => {
// # Tap on all new messages option, tap on mobile online option, tap on back button, and go back to push notification settings screen
await PushNotificationSettingsScreen.allNewMessagesOption.tap();
await PushNotificationSettingsScreen.mobileOnlineOption.tap();
await PushNotificationSettingsScreen.back();
await PushNotificationSettingsScreen.open();
// * Verify all new messages option and mobile online option are selected and push threads following option does not exist
await expect(PushNotificationSettingsScreen.allNewMessagesOptionSelected).toBeVisible();
await expect(PushNotificationSettingsScreen.mobileOnlineOptionSelected).toBeVisible();
await expect(PushNotificationSettingsScreen.pushThreadsFollowingOptionToggledOn).not.toExist();
// # Tap on nothing option, tap on back button, and go back to push notification settings screen
await PushNotificationSettingsScreen.nothingOption.tap();
await PushNotificationSettingsScreen.back();
await PushNotificationSettingsScreen.open();
// * Verify nothing option is selected and mobile options do no exist
await expect(PushNotificationSettingsScreen.nothingOptionSelected).toBeVisible();
await expect(PushNotificationSettingsScreen.mobileOnlineOption).not.toExist();
await expect(PushNotificationSettingsScreen.mobileAwayOption).not.toExist();
await expect(PushNotificationSettingsScreen.mobileOfflineOption).not.toExist();
// # Tap on mentions only option, tap on mobile away option, toggle push threads following option off, tap on back button, and go back to push notification settings screen
await PushNotificationSettingsScreen.mentionsOnlyOption.tap();
await PushNotificationSettingsScreen.mobileAwayOption.tap();
await PushNotificationSettingsScreen.togglePushThreadsFollowingOptionOff();
await PushNotificationSettingsScreen.back();
await PushNotificationSettingsScreen.open();
// * Verify mentions only option and mobile away option are selected and push threads following option is toggled off
await expect(PushNotificationSettingsScreen.mentionsOnlyOptionSelected).toBeVisible();
await expect(PushNotificationSettingsScreen.mobileAwayOptionSelected).toBeVisible();
await expect(PushNotificationSettingsScreen.pushThreadsFollowingOptionToggledOff).toBeVisible();
// # Toggle push threads following option on, tap on back button, and go back to push notification settings screen
await PushNotificationSettingsScreen.togglePushThreadsFollowingOptionOn();
await PushNotificationSettingsScreen.back();
await PushNotificationSettingsScreen.open();
// * Verify push threads following option is toggled on
await expect(PushNotificationSettingsScreen.pushThreadsFollowingOptionToggledOn).toBeVisible();
});
});

View File

@@ -0,0 +1,106 @@
// 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 {
AboutScreen,
AccountScreen,
AdvancedSettingsScreen,
DisplaySettingsScreen,
HomeScreen,
NotificationSettingsScreen,
LoginScreen,
ServerScreen,
SettingsScreen,
} from '@support/ui/screen';
import {expect} from 'detox';
describe('Account - Settings', () => {
const serverOneDisplayName = 'Server 1';
let testUser: any;
beforeAll(async () => {
const {user} = await Setup.apiInit(siteOneUrl);
testUser = user;
// # Log in to server, open account screen, and go to settings screen
await ServerScreen.connectToServer(serverOneUrl, serverOneDisplayName);
await LoginScreen.login(testUser);
await AccountScreen.open();
await SettingsScreen.open();
});
beforeEach(async () => {
// * Verify on settings screen
await SettingsScreen.toBeVisible();
});
afterAll(async () => {
// # Log out
await SettingsScreen.close();
await HomeScreen.logout();
});
it('MM-T4991_1 - should match elements on settings screen', async () => {
// * Verify basic elements on settings screen
await expect(SettingsScreen.notificationsOption).toBeVisible();
await expect(SettingsScreen.displayOption).toBeVisible();
await expect(SettingsScreen.advancedSettingsOption).toBeVisible();
await expect(SettingsScreen.aboutOption).toBeVisible();
await expect(SettingsScreen.helpOption).toBeVisible();
});
it('MM-T4991_2 - should be able to go to notification settings screen', async () => {
// # Tap on notifications option
await SettingsScreen.notificationsOption.tap();
// * Verify on notification settings screen
await NotificationSettingsScreen.toBeVisible();
// # Go back to settings screen
await NotificationSettingsScreen.back();
});
it('MM-T4991_3 - should be able to go to display settings screen', async () => {
// # Tap on display option
await SettingsScreen.displayOption.tap();
// * Verify on display settings screen
await DisplaySettingsScreen.toBeVisible();
// # Go back to settings screen
await DisplaySettingsScreen.back();
});
it('MM-T4991_4 - should be able to go to advanced settings screen', async () => {
// # Tap on advanced settings option
await SettingsScreen.advancedSettingsOption.tap();
// * Verify on advanced settings screen
await AdvancedSettingsScreen.toBeVisible();
// # Go back to settings screen
await AdvancedSettingsScreen.back();
});
it('MM-T4991_5 - should be able to go to about screen', async () => {
// # Tap on about option
await SettingsScreen.aboutOption.tap();
// * Verify on about screen
await AboutScreen.toBeVisible();
// # Go back to settings screen
await AboutScreen.back();
});
});

View 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 {Setup} from '@support/server_api';
import {
serverOneUrl,
siteOneUrl,
} from '@support/test_config';
import {
AccountScreen,
DisplaySettingsScreen,
HomeScreen,
LoginScreen,
ServerScreen,
SettingsScreen,
ThemeDisplaySettingsScreen,
} from '@support/ui/screen';
import {expect} from 'detox';
describe('Account - Settings - Theme Display Settings', () => {
const serverOneDisplayName = 'Server 1';
let testUser: any;
beforeAll(async () => {
const {user} = await Setup.apiInit(siteOneUrl);
testUser = user;
// # Log in to server, open account screen, open settings screen, open display settings screen, and go to theme display settings
await ServerScreen.connectToServer(serverOneUrl, serverOneDisplayName);
await LoginScreen.login(testUser);
await AccountScreen.open();
await SettingsScreen.open();
await DisplaySettingsScreen.open();
await ThemeDisplaySettingsScreen.open();
});
beforeEach(async () => {
// * Verify on theme display settings screen
await ThemeDisplaySettingsScreen.toBeVisible();
});
afterAll(async () => {
// # Log out
await ThemeDisplaySettingsScreen.back();
await DisplaySettingsScreen.back();
await SettingsScreen.close();
await HomeScreen.logout();
});
it('MM-T5111_1 - should match elements on theme display settings screen', async () => {
// * Verify basic elements on theme display settings screen
await expect(ThemeDisplaySettingsScreen.backButton).toBeVisible();
await expect(ThemeDisplaySettingsScreen.denimOption).toBeVisible();
await expect(ThemeDisplaySettingsScreen.sapphireOption).toBeVisible();
await expect(ThemeDisplaySettingsScreen.quartzOption).toBeVisible();
await expect(ThemeDisplaySettingsScreen.indigoOption).toBeVisible();
await expect(ThemeDisplaySettingsScreen.onyxOption).toBeVisible();
});
it('MM-T5111_2 - should be able to select a theme and save by tapping navigation back button', async () => {
// # Tap on a sapphire option and tap on back button
await ThemeDisplaySettingsScreen.sapphireOption.tap();
await ThemeDisplaySettingsScreen.back();
// * Verify on display settings screen and sapphire is set
await DisplaySettingsScreen.toBeVisible();
await expect(DisplaySettingsScreen.themeOptionInfo).toHaveText('Sapphire');
// # Go back to theme display settings screen
await ThemeDisplaySettingsScreen.open();
// * Verify sapphire option is selected
await expect(ThemeDisplaySettingsScreen.sapphireOptionSelected).toBeVisible();
// # Tap on denim option and tap on back button
await ThemeDisplaySettingsScreen.denimOption.tap();
await ThemeDisplaySettingsScreen.back();
// * Verify on display settings screen and denim is set
await DisplaySettingsScreen.toBeVisible();
await expect(DisplaySettingsScreen.themeOptionInfo).toHaveText('Denim');
// # Go back to theme display settings screen
await ThemeDisplaySettingsScreen.open();
// * Verify denim option is selected
await expect(ThemeDisplaySettingsScreen.denimOptionSelected).toBeVisible();
});
});

View File

@@ -0,0 +1,98 @@
// 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 {
AccountScreen,
DisplaySettingsScreen,
HomeScreen,
LoginScreen,
SelectTimezoneScreen,
ServerScreen,
SettingsScreen,
TimezoneDisplaySettingsScreen,
} from '@support/ui/screen';
import {expect} from 'detox';
describe('Account - Settings - Timezone Display Settings', () => {
const serverOneDisplayName = 'Server 1';
let testUser: any;
beforeAll(async () => {
const {user} = await Setup.apiInit(siteOneUrl);
testUser = user;
// # Log in to server, open account screen, open settings screen, open display settings screen, and go to timezone display settings
await ServerScreen.connectToServer(serverOneUrl, serverOneDisplayName);
await LoginScreen.login(testUser);
await AccountScreen.open();
await SettingsScreen.open();
await DisplaySettingsScreen.open();
await TimezoneDisplaySettingsScreen.open();
});
beforeEach(async () => {
// * Verify on timezone display settings screen
await TimezoneDisplaySettingsScreen.toBeVisible();
});
afterAll(async () => {
// # Log out
await TimezoneDisplaySettingsScreen.back();
await DisplaySettingsScreen.back();
await SettingsScreen.close();
await HomeScreen.logout();
});
it('MM-T5113_1 - should match elements on timezone display settings screen', async () => {
// * Verify basic elements on timezone display settings screen
await expect(TimezoneDisplaySettingsScreen.backButton).toBeVisible();
await expect(TimezoneDisplaySettingsScreen.automaticOptionToggledOn).toBeVisible();
});
it('MM-T5113_2 - should be able to select a timezone and save by tapping navigation back button', async () => {
// # Toggle automatic option off and tap on manual option
await TimezoneDisplaySettingsScreen.toggleAutomaticOptionOff();
await TimezoneDisplaySettingsScreen.manualOption.tap();
// * Verify on select timezone screen
await SelectTimezoneScreen.toBeVisible();
// # Search for a timezone and tap on a timezone
await SelectTimezoneScreen.searchInput.replaceText('Africa');
await SelectTimezoneScreen.getNonSelectedTimezoneRow('Africa/Nairobi').tap();
// * Verify on timezone display settings screen and timezone is set
await TimezoneDisplaySettingsScreen.toBeVisible();
await expect(TimezoneDisplaySettingsScreen.manualOptionInfo).toHaveText('Nairobi');
// # Tap on back button
await TimezoneDisplaySettingsScreen.back();
// * Verify on display settings screen and manual is set
await DisplaySettingsScreen.toBeVisible();
await expect(DisplaySettingsScreen.timezoneOptionInfo).toHaveText('Manual');
// # Go back to timezone display settings screen, toggle automatic option on and tap on back button
await TimezoneDisplaySettingsScreen.open();
await TimezoneDisplaySettingsScreen.toggleAutomaticOptionOn();
await TimezoneDisplaySettingsScreen.back();
// * Verify on display settings and auto is set
await DisplaySettingsScreen.toBeVisible();
await expect(DisplaySettingsScreen.timezoneOptionInfo).toHaveText('Auto');
// # Go back to timezone display settings screen
await TimezoneDisplaySettingsScreen.open();
});
});

View File

@@ -195,7 +195,7 @@ describe('Autocomplete - At-Mention', () => {
await expect(userAtMentionAutocomplete).toBeVisible();
});
it('MM-T4878_9 - should stop suggesting user after full name with trailing space -- KNOWN ISSUE: MM-45279', async () => {
it('MM-T4878_9 - should stop suggesting user after full name with trailing space', async () => {
// # Type in "@" to activate at-mention autocomplete
await ChannelScreen.postInput.typeText('@');
await Autocomplete.toBeVisible();

View File

@@ -131,7 +131,7 @@ describe('Autocomplete - Channel Mention', () => {
await expect(channelMentionAutocomplete).toBeVisible();
});
it('MM-T4879_5 - should stop suggesting channel after channel display name with trailing space -- KNOWN ISSUE: MM-45279', async () => {
it('MM-T4879_5 - should stop suggesting channel after channel display name with trailing space', async () => {
// # Type in "~" to activate channel mention autocomplete
await ChannelScreen.postInput.typeText('~');
await Autocomplete.toBeVisible();

View File

@@ -0,0 +1,193 @@
// 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 {
AccountScreen,
ClockDisplaySettingsScreen,
CustomStatusScreen,
DisplaySettingsScreen,
EditProfileScreen,
EmailNotificationSettingsScreen,
EmojiPickerScreen,
HomeScreen,
LoginScreen,
MentionNotificationSettingsScreen,
NotificationSettingsScreen,
PushNotificationSettingsScreen,
ServerScreen,
SettingsScreen,
ThemeDisplaySettingsScreen,
} from '@support/ui/screen';
import {getRandomId} from '@support/utils';
import {expect} from 'detox';
describe('Smoke Test - Account', () => {
const serverOneDisplayName = 'Server 1';
let testUser: any;
beforeAll(async () => {
const {user} = await Setup.apiInit(siteOneUrl);
testUser = user;
// # Log in to server and go to account screen
await ServerScreen.connectToServer(serverOneUrl, serverOneDisplayName);
await LoginScreen.login(testUser);
await AccountScreen.open();
});
beforeEach(async () => {
// * Verify on account screen
await AccountScreen.toBeVisible();
});
afterAll(async () => {
// # Log out
await HomeScreen.logout();
});
it('MM-T5114_1 - should be able to set user presence and custom status', async () => {
// # Tap on user presence option and tap on online user status option
await AccountScreen.userPresenceOption.tap();
await AccountScreen.onlineUserStatusOption.tap();
// * Verify on account screen and verify user presence icon and label are for online user status
await AccountScreen.toBeVisible();
await expect(AccountScreen.getUserPresenceIndicator('online')).toBeVisible();
await expect(AccountScreen.getUserPresenceLabel('online')).toHaveText('Online');
// # Open custom status screen, pick an emoji and type in custom status, and tap on done button
const customStatusEmojiName = 'clown_face';
const customStatusText = `Status ${getRandomId()}`;
const customStatusDuration = 'today';
await CustomStatusScreen.open();
await CustomStatusScreen.openEmojiPicker('default');
await EmojiPickerScreen.searchInput.replaceText(customStatusEmojiName);
await element(by.text('🤡')).tap();
await CustomStatusScreen.statusInput.replaceText(customStatusText);
await CustomStatusScreen.doneButton.tap();
// * Verify on account screen and custom status is set
await AccountScreen.toBeVisible();
const {accountCustomStatusEmoji, accountCustomStatusText, accountCustomStatusExpiry} = AccountScreen.getCustomStatus(customStatusEmojiName, customStatusDuration);
await expect(accountCustomStatusEmoji).toBeVisible();
await expect(accountCustomStatusText).toHaveText(customStatusText);
await expect(accountCustomStatusExpiry).toBeVisible();
// # Tap on clear button for custom status from display field
await AccountScreen.customStatusClearButton.tap();
// * Verify custom status is cleared from account screen
const defaultStatusText = 'Set a Status';
await expect(accountCustomStatusEmoji).not.toExist();
await expect(accountCustomStatusText).toHaveText(defaultStatusText);
await expect(accountCustomStatusExpiry).not.toExist();
});
it('MM-T5114_2 - should be able to edit profile', async () => {
// # Open edit profile screen, edit fields, and tap on save button
const suffix = getRandomId(3);
await EditProfileScreen.open();
await EditProfileScreen.firstNameInput.replaceText(`${testUser.first_name}${suffix}`);
await EditProfileScreen.scrollView.tap({x: 1, y: 1});
await EditProfileScreen.scrollView.scroll(100, 'down');
await EditProfileScreen.usernameInput.clearText();
await EditProfileScreen.usernameInput.typeText(`${testUser.username}${suffix}`);
await EditProfileScreen.saveButton.tap();
// * Verify on account screen and user full name and username are updated
await AccountScreen.toBeVisible();
const {userInfoUserDisplayName, userInfoUsername} = AccountScreen.getUserInfo(testUser.id);
await expect(userInfoUserDisplayName).toHaveText(`${testUser.first_name}${suffix} ${testUser.last_name} (${testUser.nickname})`);
await expect(userInfoUsername).toHaveText(`@${testUser.username}${suffix}`);
// # Open edit profile screen, revert back to original field values, and tap on save button
await EditProfileScreen.open();
await EditProfileScreen.firstNameInput.replaceText(testUser.first_name);
await EditProfileScreen.scrollView.tap({x: 1, y: 1});
await EditProfileScreen.scrollView.scroll(100, 'down');
await EditProfileScreen.usernameInput.clearText();
await EditProfileScreen.usernameInput.typeText(testUser.username);
await EditProfileScreen.saveButton.tap();
// * Verify on account screen and user full name and username are reverted back to original values
await AccountScreen.toBeVisible();
await expect(userInfoUserDisplayName).toHaveText(`${testUser.first_name} ${testUser.last_name} (${testUser.nickname})`);
await expect(userInfoUsername).toHaveText(`@${testUser.username}`);
});
it('MM-T5114_3 - should be able to set notification settings', async () => {
// # Open settings screen, open notification settings screen, open mention notification settings screen, type in keywords, tap on back button, and go back to mention notification settings screen
const keywords = `${getRandomId()},${getRandomId()}`;
await SettingsScreen.open();
await NotificationSettingsScreen.open();
await MentionNotificationSettingsScreen.open();
await MentionNotificationSettingsScreen.keywordsInput.replaceText(keywords);
await MentionNotificationSettingsScreen.back();
await MentionNotificationSettingsScreen.open();
// * Verify keywords are saved
await expect(MentionNotificationSettingsScreen.keywordsInput).toHaveValue(keywords.toLowerCase());
// # Go back to notification settings screen, open push notification settings screen, tap on mentions only option, tap on mobile away option, tap on back button, and go back to notification settings screen
await MentionNotificationSettingsScreen.back();
await PushNotificationSettingsScreen.open();
await PushNotificationSettingsScreen.mentionsOnlyOption.tap();
await PushNotificationSettingsScreen.mobileAwayOption.tap();
await PushNotificationSettingsScreen.back();
await PushNotificationSettingsScreen.open();
// * Verify mentions only option and mobile away option are selected
await expect(PushNotificationSettingsScreen.mentionsOnlyOptionSelected).toBeVisible();
await expect(PushNotificationSettingsScreen.mobileAwayOptionSelected).toBeVisible();
// # Go back to notification settings screen, open email notification settings screen, tap on immediately option, and tap on back button
await PushNotificationSettingsScreen.back();
await EmailNotificationSettingsScreen.open();
await EmailNotificationSettingsScreen.immediatelyOption.tap();
await EmailNotificationSettingsScreen.back();
// * Verify on notification settings screen and immediately is set
await NotificationSettingsScreen.toBeVisible();
await expect(NotificationSettingsScreen.emailNotificationsOptionInfo).toHaveText('Immediately');
// # Go back to account screen
await NotificationSettingsScreen.back();
await SettingsScreen.close();
});
it('MM-T5114_4 - should be able to set display settings', async () => {
// # Open settings screen, open display settings screen, open theme display settings screen, and tap on denim option
await SettingsScreen.open();
await DisplaySettingsScreen.open();
await ThemeDisplaySettingsScreen.open();
await ThemeDisplaySettingsScreen.denimOption.tap();
// * Verify on display settings screen and denim is set
await DisplaySettingsScreen.toBeVisible();
await expect(DisplaySettingsScreen.themeOptionInfo).toHaveText('Denim');
// # Open clock display settings screen, select twelve hour option, and tap on back button
await ClockDisplaySettingsScreen.open();
await ClockDisplaySettingsScreen.twelveHourOption.tap();
await ClockDisplaySettingsScreen.back();
// * Verify on display settings screen and twelve hour is set
await DisplaySettingsScreen.toBeVisible();
await expect(DisplaySettingsScreen.clockDisplayOptionInfo).toHaveText('12-hour');
// # Go back to account screen
await DisplaySettingsScreen.back();
await SettingsScreen.close();
});
});