Fix E2E Test Failures Due to Keyboard Controller Changes (#9371)
This commit is contained in:
parent
678f1b1184
commit
cbf300ffd3
75 changed files with 988 additions and 430 deletions
|
|
@ -11,7 +11,6 @@ import {ROW_HEIGHT as CHANNEL_ROW_HEIGHT} from '@components/channel_item/channel
|
||||||
import FormattedText from '@components/formatted_text';
|
import FormattedText from '@components/formatted_text';
|
||||||
import Loading from '@components/loading';
|
import Loading from '@components/loading';
|
||||||
import {Events} from '@constants';
|
import {Events} from '@constants';
|
||||||
import {UNREADS_CATEGORY} from '@constants/categories';
|
|
||||||
import {CHANNEL, DRAFT, THREAD} from '@constants/screens';
|
import {CHANNEL, DRAFT, THREAD} from '@constants/screens';
|
||||||
import {HOME_PADDING} from '@constants/view';
|
import {HOME_PADDING} from '@constants/view';
|
||||||
import {useServerUrl} from '@context/server';
|
import {useServerUrl} from '@context/server';
|
||||||
|
|
@ -120,7 +119,7 @@ const Categories = ({flattenedItems, unreadChannelIds, onlyUnreads, isTablet}: P
|
||||||
}
|
}
|
||||||
|
|
||||||
// item.type === 'channel'
|
// item.type === 'channel'
|
||||||
const testIdSuffix = item.categoryId === UNREADS_CATEGORY ? UNREADS_CATEGORY : item.channelId;
|
const testIdSuffix = item.categoryType;
|
||||||
return (
|
return (
|
||||||
<ChannelItem
|
<ChannelItem
|
||||||
channel={item.channel}
|
channel={item.channel}
|
||||||
|
|
|
||||||
|
|
@ -45,6 +45,7 @@ describe('flatten_categories utils', () => {
|
||||||
const item: FlattenedItem = {
|
const item: FlattenedItem = {
|
||||||
type: 'channel',
|
type: 'channel',
|
||||||
categoryId: 'cat1',
|
categoryId: 'cat1',
|
||||||
|
categoryType: 'custom',
|
||||||
channelId: 'channel1',
|
channelId: 'channel1',
|
||||||
channel: mockChannel1,
|
channel: mockChannel1,
|
||||||
};
|
};
|
||||||
|
|
@ -71,6 +72,7 @@ describe('flatten_categories utils', () => {
|
||||||
const item: FlattenedItem = {
|
const item: FlattenedItem = {
|
||||||
type: 'channel',
|
type: 'channel',
|
||||||
categoryId: 'cat1',
|
categoryId: 'cat1',
|
||||||
|
categoryType: 'custom',
|
||||||
channelId: 'channel1',
|
channelId: 'channel1',
|
||||||
channel: mockChannel1,
|
channel: mockChannel1,
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@ import type ChannelModel from '@typings/database/models/servers/channel';
|
||||||
export type FlattenedItem =
|
export type FlattenedItem =
|
||||||
| {type: 'unreads_header'}
|
| {type: 'unreads_header'}
|
||||||
| {type: 'header'; categoryId: string; category: CategoryModel}
|
| {type: 'header'; categoryId: string; category: CategoryModel}
|
||||||
| {type: 'channel'; categoryId: string; channelId: string; channel: ChannelModel};
|
| {type: 'channel'; categoryId: string; categoryType: string; channelId: string; channel: ChannelModel};
|
||||||
|
|
||||||
export type CategoryData = {
|
export type CategoryData = {
|
||||||
category: CategoryModel;
|
category: CategoryModel;
|
||||||
|
|
@ -55,6 +55,7 @@ export const flattenCategories = (
|
||||||
result.push({
|
result.push({
|
||||||
type: 'channel',
|
type: 'channel',
|
||||||
categoryId: UNREADS_CATEGORY,
|
categoryId: UNREADS_CATEGORY,
|
||||||
|
categoryType: UNREADS_CATEGORY,
|
||||||
channelId: channel.id,
|
channelId: channel.id,
|
||||||
channel,
|
channel,
|
||||||
});
|
});
|
||||||
|
|
@ -75,6 +76,7 @@ export const flattenCategories = (
|
||||||
result.push({
|
result.push({
|
||||||
type: 'channel',
|
type: 'channel',
|
||||||
categoryId: category.id,
|
categoryId: category.id,
|
||||||
|
categoryType: category.type,
|
||||||
channelId: channel.id,
|
channelId: channel.id,
|
||||||
channel,
|
channel,
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -178,6 +178,7 @@ const observeFlattenedUnreads = (
|
||||||
map((channel) => ({
|
map((channel) => ({
|
||||||
type: 'channel',
|
type: 'channel',
|
||||||
categoryId: UNREADS_CATEGORY,
|
categoryId: UNREADS_CATEGORY,
|
||||||
|
categoryType: UNREADS_CATEGORY,
|
||||||
channelId: channel.id,
|
channelId: channel.id,
|
||||||
channel,
|
channel,
|
||||||
}));
|
}));
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,7 @@ hw.battery = yes
|
||||||
hw.camera.back = virtualscene
|
hw.camera.back = virtualscene
|
||||||
hw.camera.front = emulated
|
hw.camera.front = emulated
|
||||||
hw.cpu.arch = change_cpu_arch
|
hw.cpu.arch = change_cpu_arch
|
||||||
hw.cpu.ncore = 4
|
hw.cpu.ncore = 7
|
||||||
hw.dPad = no
|
hw.dPad = no
|
||||||
hw.device.hash2 = MD5:80326cf5b53c08af25d4243cb231faa9
|
hw.device.hash2 = MD5:80326cf5b53c08af25d4243cb231faa9
|
||||||
hw.device.manufacturer = Google
|
hw.device.manufacturer = Google
|
||||||
|
|
|
||||||
|
|
@ -38,7 +38,7 @@ create_avd() {
|
||||||
sed -i -e "s|image.sysdir.1 = change_to_image_sysdir/|image.sysdir.1 = system-images/android-${SDK_VERSION}/default/${cpu_arch_family}/|g" "$AVD_NAME/config.ini"
|
sed -i -e "s|image.sysdir.1 = change_to_image_sysdir/|image.sysdir.1 = system-images/android-${SDK_VERSION}/default/${cpu_arch_family}/|g" "$AVD_NAME/config.ini"
|
||||||
sed -i -e "s|skin.path = change_to_absolute_path/pixel_4_xl_skin|skin.path = $(pwd)/${AVD_NAME}/pixel_4_xl_skin|g" "$AVD_NAME/config.ini"
|
sed -i -e "s|skin.path = change_to_absolute_path/pixel_4_xl_skin|skin.path = $(pwd)/${AVD_NAME}/pixel_4_xl_skin|g" "$AVD_NAME/config.ini"
|
||||||
|
|
||||||
echo "hw.cpu.ncore=5" >> "$AVD_NAME/config.ini"
|
echo "hw.cpu.ncore=7" >> "$AVD_NAME/config.ini"
|
||||||
echo "Android virtual device successfully created: ${AVD_NAME}"
|
echo "Android virtual device successfully created: ${AVD_NAME}"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -53,7 +53,7 @@ start_emulator() {
|
||||||
local emulator_opts="-avd $AVD_NAME -no-snapshot -no-boot-anim -no-audio -gpu off -no-window"
|
local emulator_opts="-avd $AVD_NAME -no-snapshot -no-boot-anim -no-audio -gpu off -no-window"
|
||||||
|
|
||||||
if [[ "$CI" == "true" || "$(uname -s)" == "Linux" ]]; then
|
if [[ "$CI" == "true" || "$(uname -s)" == "Linux" ]]; then
|
||||||
emulator $emulator_opts -gpu host -accel on -qemu -m 4096 &
|
emulator $emulator_opts -gpu host -accel on -qemu -m 8192 &
|
||||||
else
|
else
|
||||||
emulator $emulator_opts -gpu guest -verbose -qemu -vnc :0
|
emulator $emulator_opts -gpu guest -verbose -qemu -vnc :0
|
||||||
fi
|
fi
|
||||||
|
|
@ -64,11 +64,22 @@ wait_for_emulator() {
|
||||||
|
|
||||||
echo "Waiting for emulator to boot..."
|
echo "Waiting for emulator to boot..."
|
||||||
adb wait-for-device
|
adb wait-for-device
|
||||||
|
|
||||||
|
local boot_timeout=300 # 5 minutes max
|
||||||
|
local boot_elapsed=0
|
||||||
until [[ "$(adb shell getprop sys.boot_completed | tr -d '\r')" == "1" ]]; do
|
until [[ "$(adb shell getprop sys.boot_completed | tr -d '\r')" == "1" ]]; do
|
||||||
|
if [[ $boot_elapsed -ge $boot_timeout ]]; then
|
||||||
|
echo "Emulator failed to boot within 5 minutes"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
echo "Waiting for emulator to fully boot..."
|
echo "Waiting for emulator to fully boot..."
|
||||||
sleep 10
|
sleep 10
|
||||||
|
boot_elapsed=$((boot_elapsed + 10))
|
||||||
done
|
done
|
||||||
echo "Emulator is fully booted."
|
echo "Emulator is fully booted."
|
||||||
|
sleep 15
|
||||||
|
adb shell pm list packages > /dev/null 2>&1
|
||||||
|
echo "Emulator is fully ready."
|
||||||
}
|
}
|
||||||
|
|
||||||
install_app() {
|
install_app() {
|
||||||
|
|
@ -82,7 +93,6 @@ start_server() {
|
||||||
cd ..
|
cd ..
|
||||||
RUNNING_E2E=true npm run start &
|
RUNNING_E2E=true npm run start &
|
||||||
local timeout=120 interval=5 elapsed=0
|
local timeout=120 interval=5 elapsed=0
|
||||||
sleep $timeout
|
|
||||||
|
|
||||||
until nc -z localhost 8081; do
|
until nc -z localhost 8081; do
|
||||||
if [[ $elapsed -ge $timeout ]]; then
|
if [[ $elapsed -ge $timeout ]]; then
|
||||||
|
|
|
||||||
80
detox/e2e/support/adb_utils.ts
Normal file
80
detox/e2e/support/adb_utils.ts
Normal file
|
|
@ -0,0 +1,80 @@
|
||||||
|
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||||
|
// See LICENSE.txt for license information.
|
||||||
|
/* eslint-disable no-console */
|
||||||
|
|
||||||
|
import {execSync} from 'child_process';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if we're running on Android platform
|
||||||
|
* Uses environment variable as fallback if device is not initialized
|
||||||
|
*/
|
||||||
|
function isAndroid(): boolean {
|
||||||
|
try {
|
||||||
|
// Try to get platform from device (if initialized)
|
||||||
|
if (typeof device !== 'undefined' && device.getPlatform) {
|
||||||
|
return device.getPlatform() === 'android';
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
// Device not initialized yet, fall back to env var
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fall back to environment variable check
|
||||||
|
return process.env.IOS !== 'true';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clean up ADB reverse port mappings to prevent "Address already in use" errors
|
||||||
|
* This is particularly important in CI environments where previous test runs may have crashed
|
||||||
|
* iOS: This function safely no-ops on iOS - no side effects
|
||||||
|
*/
|
||||||
|
export async function cleanupAdbReversePorts(): Promise<void> {
|
||||||
|
// Only run on Android - safe no-op for iOS
|
||||||
|
if (!isAndroid()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
console.info('[ADB Cleanup] Removing all reverse port mappings...');
|
||||||
|
|
||||||
|
// Remove all reverse port mappings
|
||||||
|
execSync('adb reverse --remove-all', {
|
||||||
|
stdio: 'pipe',
|
||||||
|
timeout: 5000,
|
||||||
|
});
|
||||||
|
|
||||||
|
console.info('[ADB Cleanup] Successfully cleaned up reverse port mappings');
|
||||||
|
} catch (error) {
|
||||||
|
// Don't fail if cleanup fails - this is best-effort
|
||||||
|
console.warn(`[ADB Cleanup] Warning: Failed to cleanup reverse ports: ${(error as Error).message}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reset ADB server connection to clear any stale state
|
||||||
|
* This can help recover from connection issues in CI
|
||||||
|
* iOS: This function safely no-ops on iOS - no side effects
|
||||||
|
*/
|
||||||
|
export async function resetAdbServer(): Promise<void> {
|
||||||
|
// Only run on Android - safe no-op for iOS
|
||||||
|
if (!isAndroid()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
console.info('[ADB Reset] Restarting ADB server...');
|
||||||
|
|
||||||
|
// Kill and restart ADB server
|
||||||
|
execSync('adb kill-server && adb start-server', {
|
||||||
|
stdio: 'pipe',
|
||||||
|
timeout: 10000,
|
||||||
|
});
|
||||||
|
|
||||||
|
// Wait a bit for server to stabilize
|
||||||
|
await new Promise((resolve) => setTimeout(resolve, 2000));
|
||||||
|
|
||||||
|
console.info('[ADB Reset] Successfully restarted ADB server');
|
||||||
|
} catch (error) {
|
||||||
|
// Don't fail if reset fails - this is best-effort
|
||||||
|
console.warn(`[ADB Reset] Warning: Failed to reset ADB server: ${(error as Error).message}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -16,12 +16,33 @@ export const apiInit = async (baseUrl: string, {
|
||||||
teamOptions = {type: 'O', prefix: 'team'},
|
teamOptions = {type: 'O', prefix: 'team'},
|
||||||
userOptions = {prefix: 'user'},
|
userOptions = {prefix: 'user'},
|
||||||
}: any = {}): Promise<any> => {
|
}: any = {}): Promise<any> => {
|
||||||
const {team} = await Team.apiCreateTeam(baseUrl, teamOptions);
|
const teamResult = await Team.apiCreateTeam(baseUrl, teamOptions);
|
||||||
const {channel} = await Channel.apiCreateChannel(baseUrl, {...channelOptions, teamId: team.id});
|
if (teamResult.error) {
|
||||||
const {user} = await User.apiCreateUser(baseUrl, userOptions);
|
throw new Error(`Failed to create team: ${JSON.stringify(teamResult.error)}`);
|
||||||
|
}
|
||||||
|
const {team} = teamResult;
|
||||||
|
|
||||||
await Team.apiAddUserToTeam(baseUrl, user.id, team.id);
|
const channelResult = await Channel.apiCreateChannel(baseUrl, {...channelOptions, teamId: team.id});
|
||||||
await Channel.apiAddUserToChannel(baseUrl, user.id, channel.id);
|
if (channelResult.error) {
|
||||||
|
throw new Error(`Failed to create channel: ${JSON.stringify(channelResult.error)}`);
|
||||||
|
}
|
||||||
|
const {channel} = channelResult;
|
||||||
|
|
||||||
|
const userResult = await User.apiCreateUser(baseUrl, userOptions);
|
||||||
|
if (userResult.error) {
|
||||||
|
throw new Error(`Failed to create user: ${JSON.stringify(userResult.error)}`);
|
||||||
|
}
|
||||||
|
const {user} = userResult;
|
||||||
|
|
||||||
|
const addTeamResult = await Team.apiAddUserToTeam(baseUrl, user.id, team.id);
|
||||||
|
if (addTeamResult.error) {
|
||||||
|
throw new Error(`Failed to add user to team: ${JSON.stringify(addTeamResult.error)}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
const addChannelResult = await Channel.apiAddUserToChannel(baseUrl, user.id, channel.id);
|
||||||
|
if (addChannelResult.error) {
|
||||||
|
throw new Error(`Failed to add user to channel: ${JSON.stringify(addChannelResult.error)}`);
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
channel,
|
channel,
|
||||||
|
|
|
||||||
|
|
@ -114,7 +114,9 @@ class Autocomplete {
|
||||||
toBeVisible = async (isVisible = true) => {
|
toBeVisible = async (isVisible = true) => {
|
||||||
await wait(timeouts.ONE_SEC);
|
await wait(timeouts.ONE_SEC);
|
||||||
if (isVisible) {
|
if (isVisible) {
|
||||||
await expect(this.autocomplete.atIndex(0)).toBeVisible();
|
// Use a lower visibility threshold to account for keyboard controller positioning
|
||||||
|
// The autocomplete may be partially off-screen during keyboard animations
|
||||||
|
await expect(this.autocomplete.atIndex(0)).toBeVisible(1);
|
||||||
return this.autocomplete;
|
return this.autocomplete;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -80,11 +80,21 @@ class AccountScreen {
|
||||||
};
|
};
|
||||||
|
|
||||||
open = async () => {
|
open = async () => {
|
||||||
// # Open account screen
|
try {
|
||||||
await waitFor(HomeScreen.accountTab).toBeVisible().withTimeout(timeouts.TWO_SEC);
|
await waitFor(HomeScreen.accountTab).toExist().withTimeout(timeouts.TEN_SEC);
|
||||||
await HomeScreen.accountTab.tap();
|
await HomeScreen.accountTab.tap();
|
||||||
|
return this.toBeVisible();
|
||||||
return this.toBeVisible();
|
} catch (error) {
|
||||||
|
// If account tab is not found, the app might already be on account screen or in unexpected state
|
||||||
|
// Try to verify if we're already on account screen
|
||||||
|
try {
|
||||||
|
await waitFor(this.accountScreen).toExist().withTimeout(timeouts.TWO_SEC);
|
||||||
|
return this.accountScreen;
|
||||||
|
} catch {
|
||||||
|
// Re-throw original error if we're not on account screen either
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
logout = async (serverDisplayName: string | null = null) => {
|
logout = async (serverDisplayName: string | null = null) => {
|
||||||
|
|
|
||||||
|
|
@ -38,8 +38,14 @@ class AutoResponderNotificationSettingsScreen {
|
||||||
};
|
};
|
||||||
|
|
||||||
back = async () => {
|
back = async () => {
|
||||||
await this.backButton.tap();
|
try {
|
||||||
await expect(this.autoResponderNotificationSettingsScreen).not.toBeVisible();
|
await waitFor(this.backButton).toExist().withTimeout(timeouts.TWO_SEC);
|
||||||
|
await this.backButton.tap();
|
||||||
|
await expect(this.autoResponderNotificationSettingsScreen).not.toBeVisible();
|
||||||
|
} catch (error) {
|
||||||
|
// Back button may not exist if screen failed to load or already navigated away
|
||||||
|
console.warn('[AutoResponderNotificationSettingsScreen.back] Navigation failed:', error); // eslint-disable-line no-console
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
toggleEnableAutomaticRepliesOptionOn = async () => {
|
toggleEnableAutomaticRepliesOptionOn = async () => {
|
||||||
|
|
|
||||||
|
|
@ -17,12 +17,11 @@ import {
|
||||||
PostOptionsScreen,
|
PostOptionsScreen,
|
||||||
ThreadScreen,
|
ThreadScreen,
|
||||||
} from '@support/ui/screen';
|
} from '@support/ui/screen';
|
||||||
import {isIos, timeouts, wait} from '@support/utils';
|
import {isAndroid, isIos, timeouts, wait} from '@support/utils';
|
||||||
import {expect} from 'detox';
|
import {expect} from 'detox';
|
||||||
|
|
||||||
class ChannelScreen {
|
class ChannelScreen {
|
||||||
testID = {
|
testID = {
|
||||||
archievedCloseChannelButton: 'channel.post_draft.archived.close_channel.button',
|
|
||||||
channelScreenPrefix: 'channel.',
|
channelScreenPrefix: 'channel.',
|
||||||
channelScreen: 'channel.screen',
|
channelScreen: 'channel.screen',
|
||||||
channelQuickActionsButton: 'channel_header.channel_quick_actions.button',
|
channelQuickActionsButton: 'channel_header.channel_quick_actions.button',
|
||||||
|
|
@ -77,7 +76,6 @@ class ChannelScreen {
|
||||||
postPriorityRequestAck = element(by.id(this.testID.postPriorityRequestAck));
|
postPriorityRequestAck = element(by.id(this.testID.postPriorityRequestAck));
|
||||||
postPriorityImportantMessage = element(by.id(this.testID.postPriorityImportantMessage));
|
postPriorityImportantMessage = element(by.id(this.testID.postPriorityImportantMessage));
|
||||||
postPriorityPicker = element(by.id(this.testID.postPriorityPicker));
|
postPriorityPicker = element(by.id(this.testID.postPriorityPicker));
|
||||||
archievedCloseChannelButton = element(by.id(this.testID.archievedCloseChannelButton));
|
|
||||||
channelScreen = element(by.id(this.testID.channelScreen));
|
channelScreen = element(by.id(this.testID.channelScreen));
|
||||||
channelQuickActionsButton = element(by.id(this.testID.channelQuickActionsButton));
|
channelQuickActionsButton = element(by.id(this.testID.channelQuickActionsButton));
|
||||||
favoriteQuickAction = element(by.id(this.testID.favoriteQuickAction));
|
favoriteQuickAction = element(by.id(this.testID.favoriteQuickAction));
|
||||||
|
|
@ -152,16 +150,29 @@ class ChannelScreen {
|
||||||
return this.channelScreen;
|
return this.channelScreen;
|
||||||
};
|
};
|
||||||
|
|
||||||
open = async (categoryKey: string, channelName: string) => {
|
dismissScheduledPostTooltip = async () => {
|
||||||
// # Open channel screen
|
// Try to close scheduled post tooltip if it exists (try both regular and admin account versions)
|
||||||
await waitFor(ChannelListScreen.getChannelItemDisplayName(categoryKey, channelName)).toBeVisible().withTimeout(timeouts.TEN_SEC);
|
|
||||||
await ChannelListScreen.getChannelItemDisplayName(categoryKey, channelName).tap();
|
|
||||||
try {
|
try {
|
||||||
|
await waitFor(this.scheduledPostTooltipCloseButton).toBeVisible().withTimeout(timeouts.ONE_SEC);
|
||||||
await this.scheduledPostTooltipCloseButton.tap();
|
await this.scheduledPostTooltipCloseButton.tap();
|
||||||
} catch (error) {
|
await wait(timeouts.HALF_SEC);
|
||||||
// eslint-disable-next-line no-console
|
} catch {
|
||||||
console.log('Element not visible, skipping click');
|
// Try admin account version
|
||||||
|
try {
|
||||||
|
await waitFor(this.scheduledPostTooltipCloseButtonAdminAccount).toBeVisible().withTimeout(timeouts.ONE_SEC);
|
||||||
|
await this.scheduledPostTooltipCloseButtonAdminAccount.tap();
|
||||||
|
await wait(timeouts.HALF_SEC);
|
||||||
|
} catch {
|
||||||
|
// Tooltip not visible, continue
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
open = async (category: string, channelName: any) => {
|
||||||
|
// # Open channel screen
|
||||||
|
await wait(timeouts.FOUR_SEC);
|
||||||
|
await ChannelListScreen.getChannelItemDisplayName(category, channelName).tap();
|
||||||
|
await this.dismissScheduledPostTooltip();
|
||||||
return this.toBeVisible();
|
return this.toBeVisible();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -193,12 +204,29 @@ class ChannelScreen {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
dismissKeyboard = async () => {
|
||||||
|
// Explicitly dismiss keyboard before long press
|
||||||
|
if (isAndroid()) {
|
||||||
|
try {
|
||||||
|
await device.pressBack();
|
||||||
|
await wait(timeouts.THREE_SEC);
|
||||||
|
} catch (error) {
|
||||||
|
// Keyboard might not be open, continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (isIos()) {
|
||||||
|
// On iOS, tap outside the input area to dismiss keyboard
|
||||||
|
await this.postInput.tapReturnKey();
|
||||||
|
await wait(timeouts.TWO_SEC);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
openPostOptionsFor = async (postId: string, text: string) => {
|
openPostOptionsFor = async (postId: string, text: string) => {
|
||||||
const {postListPostItem} = this.getPostListPostItem(postId, text);
|
const {postListPostItem} = this.getPostListPostItem(postId, text);
|
||||||
await expect(postListPostItem).toBeVisible();
|
await waitFor(postListPostItem).toBeVisible().withTimeout(timeouts.TEN_SEC);
|
||||||
|
|
||||||
// # Open post options
|
// # Open post options
|
||||||
await postListPostItem.longPress(timeouts.TWO_SEC);
|
await postListPostItem.longPress();
|
||||||
await PostOptionsScreen.toBeVisible();
|
await PostOptionsScreen.toBeVisible();
|
||||||
await wait(timeouts.TWO_SEC);
|
await wait(timeouts.TWO_SEC);
|
||||||
};
|
};
|
||||||
|
|
@ -217,6 +245,7 @@ class ChannelScreen {
|
||||||
await this.postInput.clearText();
|
await this.postInput.clearText();
|
||||||
await this.postInput.replaceText(message);
|
await this.postInput.replaceText(message);
|
||||||
await this.tapSendButton();
|
await this.tapSendButton();
|
||||||
|
await wait(timeouts.TWO_SEC);
|
||||||
};
|
};
|
||||||
|
|
||||||
enterMessageToSchedule = async (message: string) => {
|
enterMessageToSchedule = async (message: string) => {
|
||||||
|
|
|
||||||
|
|
@ -38,8 +38,14 @@ class ClockDisplaySettingsScreen {
|
||||||
};
|
};
|
||||||
|
|
||||||
back = async () => {
|
back = async () => {
|
||||||
await this.backButton.tap();
|
try {
|
||||||
await expect(this.clockDisplaySettingsScreen).not.toBeVisible();
|
await waitFor(this.backButton).toExist().withTimeout(timeouts.TWO_SEC);
|
||||||
|
await this.backButton.tap();
|
||||||
|
await expect(this.clockDisplaySettingsScreen).not.toBeVisible();
|
||||||
|
} catch (error) {
|
||||||
|
// Back button may not exist if screen failed to load or already navigated away
|
||||||
|
console.warn('[ClockDisplaySettingsScreen.back] Navigation failed:', error); // eslint-disable-line no-console
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@ import {
|
||||||
ThreadOptionsScreen,
|
ThreadOptionsScreen,
|
||||||
} from '@support/ui/screen';
|
} from '@support/ui/screen';
|
||||||
import {timeouts, wait} from '@support/utils';
|
import {timeouts, wait} from '@support/utils';
|
||||||
import {expect} from 'detox';
|
import {expect, waitFor} from 'detox';
|
||||||
|
|
||||||
class GlobalThreadsScreen {
|
class GlobalThreadsScreen {
|
||||||
testID = {
|
testID = {
|
||||||
|
|
@ -75,7 +75,7 @@ class GlobalThreadsScreen {
|
||||||
|
|
||||||
back = async () => {
|
back = async () => {
|
||||||
await this.backButton.tap();
|
await this.backButton.tap();
|
||||||
await expect(this.globalThreadsScreen).not.toBeVisible();
|
await waitFor(this.globalThreadsScreen).not.toBeVisible().withTimeout(timeouts.TEN_SEC);
|
||||||
};
|
};
|
||||||
|
|
||||||
openThreadOptionsFor = async (postId: string) => {
|
openThreadOptionsFor = async (postId: string) => {
|
||||||
|
|
@ -83,7 +83,7 @@ class GlobalThreadsScreen {
|
||||||
await expect(threadItem).toBeVisible();
|
await expect(threadItem).toBeVisible();
|
||||||
|
|
||||||
// # Open thread options
|
// # Open thread options
|
||||||
await threadItem.longPress();
|
await threadItem.longPress(timeouts.FOUR_SEC);
|
||||||
await ThreadOptionsScreen.toBeVisible();
|
await ThreadOptionsScreen.toBeVisible();
|
||||||
await wait(timeouts.TWO_SEC);
|
await wait(timeouts.TWO_SEC);
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -37,9 +37,15 @@ class HomeScreen {
|
||||||
};
|
};
|
||||||
|
|
||||||
logout = async (serverDisplayName: string | null = null) => {
|
logout = async (serverDisplayName: string | null = null) => {
|
||||||
await AccountScreen.open();
|
try {
|
||||||
await AccountScreen.logout(serverDisplayName);
|
await AccountScreen.open();
|
||||||
await expect(this.channelListTab).not.toBeVisible();
|
await AccountScreen.logout(serverDisplayName);
|
||||||
|
await expect(this.channelListTab).not.toBeVisible();
|
||||||
|
} catch (error) {
|
||||||
|
// Logout may fail if app is in unexpected state during cleanup
|
||||||
|
// Log error but don't throw to allow test cleanup to continue
|
||||||
|
console.warn('[HomeScreen.logout] Logout failed:', error); // eslint-disable-line no-console
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -42,8 +42,14 @@ class NotificationSettingsScreen {
|
||||||
};
|
};
|
||||||
|
|
||||||
back = async () => {
|
back = async () => {
|
||||||
await this.backButton.tap();
|
try {
|
||||||
await expect(this.notificationSettingsScreen).not.toBeVisible();
|
await waitFor(this.backButton).toExist().withTimeout(timeouts.TWO_SEC);
|
||||||
|
await this.backButton.tap();
|
||||||
|
await expect(this.notificationSettingsScreen).not.toBeVisible();
|
||||||
|
} catch (error) {
|
||||||
|
// Back button may not exist if screen failed to load or already navigated away
|
||||||
|
console.warn('[NotificationSettingsScreen.back] Navigation failed:', error); // eslint-disable-line no-console
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
|
|
||||||
import {PostList} from '@support/ui/component';
|
import {PostList} from '@support/ui/component';
|
||||||
import {timeouts, wait} from '@support/utils';
|
import {timeouts, wait} from '@support/utils';
|
||||||
import {expect} from 'detox';
|
import {expect, waitFor} from 'detox';
|
||||||
|
|
||||||
class PermalinkScreen {
|
class PermalinkScreen {
|
||||||
testID = {
|
testID = {
|
||||||
|
|
@ -36,7 +36,7 @@ class PermalinkScreen {
|
||||||
|
|
||||||
jumpToRecentMessages = async () => {
|
jumpToRecentMessages = async () => {
|
||||||
// # Jump to recent messages
|
// # Jump to recent messages
|
||||||
await wait(timeouts.ONE_SEC);
|
await waitFor(this.jumpToRecentMessagesButton).toExist().withTimeout(timeouts.TEN_SEC);
|
||||||
await this.jumpToRecentMessagesButton.tap();
|
await this.jumpToRecentMessagesButton.tap();
|
||||||
await expect(this.permalinkScreen).not.toBeVisible();
|
await expect(this.permalinkScreen).not.toBeVisible();
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@ import {
|
||||||
ChannelInfoScreen,
|
ChannelInfoScreen,
|
||||||
PostOptionsScreen,
|
PostOptionsScreen,
|
||||||
} from '@support/ui/screen';
|
} from '@support/ui/screen';
|
||||||
import {timeouts, wait} from '@support/utils';
|
import {timeouts, wait, waitForElementToBeVisible} from '@support/utils';
|
||||||
import {expect} from 'detox';
|
import {expect} from 'detox';
|
||||||
|
|
||||||
class PinnedMessagesScreen {
|
class PinnedMessagesScreen {
|
||||||
|
|
@ -57,10 +57,17 @@ class PinnedMessagesScreen {
|
||||||
|
|
||||||
openPostOptionsFor = async (postId: string, text: string) => {
|
openPostOptionsFor = async (postId: string, text: string) => {
|
||||||
const {postListPostItem} = this.getPostListPostItem(postId, text);
|
const {postListPostItem} = this.getPostListPostItem(postId, text);
|
||||||
await expect(postListPostItem).toBeVisible();
|
|
||||||
|
// Poll for the post to become visible without waiting for idle bridge
|
||||||
|
await waitForElementToBeVisible(postListPostItem, timeouts.TEN_SEC);
|
||||||
|
|
||||||
|
// Dismiss keyboard by tapping on the post list (needed after posting a message)
|
||||||
|
const flatList = this.postList.getFlatList();
|
||||||
|
await flatList.scroll(100, 'down');
|
||||||
|
await wait(timeouts.ONE_SEC);
|
||||||
|
|
||||||
// # Open post options
|
// # Open post options
|
||||||
await postListPostItem.longPress();
|
await postListPostItem.longPress(timeouts.TWO_SEC);
|
||||||
await PostOptionsScreen.toBeVisible();
|
await PostOptionsScreen.toBeVisible();
|
||||||
await wait(timeouts.TWO_SEC);
|
await wait(timeouts.TWO_SEC);
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -88,12 +88,12 @@ class PostOptionsScreen {
|
||||||
|
|
||||||
openPostOptionsForPinedPosts = async (postId: string) => {
|
openPostOptionsForPinedPosts = async (postId: string) => {
|
||||||
await waitFor(this.pinnedPostListItem(postId)).toExist().withTimeout(timeouts.TWO_SEC);
|
await waitFor(this.pinnedPostListItem(postId)).toExist().withTimeout(timeouts.TWO_SEC);
|
||||||
await this.pinnedPostListItem(postId).longPress();
|
await this.pinnedPostListItem(postId).longPress(timeouts.TWO_SEC);
|
||||||
};
|
};
|
||||||
|
|
||||||
openPostOptionsForSearchedPosts = async (postId: string) => {
|
openPostOptionsForSearchedPosts = async (postId: string) => {
|
||||||
await waitFor(this.searchedPostListItem(postId)).toExist().withTimeout(timeouts.TWO_SEC);
|
await waitFor(this.searchedPostListItem(postId)).toExist().withTimeout(timeouts.TWO_SEC);
|
||||||
await this.searchedPostListItem(postId).longPress();
|
await this.searchedPostListItem(postId).longPress(timeouts.TWO_SEC);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@ import {
|
||||||
HomeScreen,
|
HomeScreen,
|
||||||
PostOptionsScreen,
|
PostOptionsScreen,
|
||||||
} from '@support/ui/screen';
|
} from '@support/ui/screen';
|
||||||
import {timeouts, wait} from '@support/utils';
|
import {timeouts, wait, waitForElementToBeVisible} from '@support/utils';
|
||||||
import {expect} from 'detox';
|
import {expect} from 'detox';
|
||||||
|
|
||||||
class RecentMentionsScreen {
|
class RecentMentionsScreen {
|
||||||
|
|
@ -63,10 +63,17 @@ class RecentMentionsScreen {
|
||||||
|
|
||||||
openPostOptionsFor = async (postId: string, text: string) => {
|
openPostOptionsFor = async (postId: string, text: string) => {
|
||||||
const {postListPostItem} = this.getPostListPostItem(postId, text);
|
const {postListPostItem} = this.getPostListPostItem(postId, text);
|
||||||
await expect(postListPostItem).toBeVisible();
|
|
||||||
|
// Poll for the post to become visible without waiting for idle bridge
|
||||||
|
await waitForElementToBeVisible(postListPostItem, timeouts.TEN_SEC);
|
||||||
|
|
||||||
|
// Dismiss keyboard by tapping on the post list (needed after posting a message)
|
||||||
|
const flatList = this.postList.getFlatList();
|
||||||
|
await flatList.scroll(100, 'down');
|
||||||
|
await wait(timeouts.ONE_SEC);
|
||||||
|
|
||||||
// # Open post options
|
// # Open post options
|
||||||
await postListPostItem.longPress();
|
await postListPostItem.longPress(timeouts.TWO_SEC);
|
||||||
await PostOptionsScreen.toBeVisible();
|
await PostOptionsScreen.toBeVisible();
|
||||||
await wait(timeouts.TWO_SEC);
|
await wait(timeouts.TWO_SEC);
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@ import {
|
||||||
HomeScreen,
|
HomeScreen,
|
||||||
PostOptionsScreen,
|
PostOptionsScreen,
|
||||||
} from '@support/ui/screen';
|
} from '@support/ui/screen';
|
||||||
import {timeouts, wait} from '@support/utils';
|
import {timeouts, wait, waitForElementToBeVisible} from '@support/utils';
|
||||||
import {expect} from 'detox';
|
import {expect} from 'detox';
|
||||||
|
|
||||||
class SavedMessagesScreen {
|
class SavedMessagesScreen {
|
||||||
|
|
@ -43,7 +43,7 @@ class SavedMessagesScreen {
|
||||||
};
|
};
|
||||||
|
|
||||||
toBeVisible = async () => {
|
toBeVisible = async () => {
|
||||||
await waitFor(this.savedMessagesScreen).toExist().withTimeout(timeouts.TEN_SEC);
|
await waitFor(this.savedMessagesScreen).toBeVisible().withTimeout(timeouts.TEN_SEC);
|
||||||
|
|
||||||
return this.savedMessagesScreen;
|
return this.savedMessagesScreen;
|
||||||
};
|
};
|
||||||
|
|
@ -57,10 +57,17 @@ class SavedMessagesScreen {
|
||||||
|
|
||||||
openPostOptionsFor = async (postId: string, text: string) => {
|
openPostOptionsFor = async (postId: string, text: string) => {
|
||||||
const {postListPostItem} = this.getPostListPostItem(postId, text);
|
const {postListPostItem} = this.getPostListPostItem(postId, text);
|
||||||
await expect(postListPostItem).toBeVisible();
|
|
||||||
|
// Poll for the post to become visible without waiting for idle bridge
|
||||||
|
await waitForElementToBeVisible(postListPostItem, timeouts.TEN_SEC);
|
||||||
|
|
||||||
|
// Dismiss keyboard by tapping on the post list (needed after posting a message)
|
||||||
|
const flatList = this.postList.getFlatList();
|
||||||
|
await flatList.scroll(100, 'down');
|
||||||
|
await wait(timeouts.ONE_SEC);
|
||||||
|
|
||||||
// # Open post options
|
// # Open post options
|
||||||
await postListPostItem.longPress();
|
await postListPostItem.longPress(timeouts.TWO_SEC);
|
||||||
await PostOptionsScreen.toBeVisible();
|
await PostOptionsScreen.toBeVisible();
|
||||||
await wait(timeouts.TWO_SEC);
|
await wait(timeouts.TWO_SEC);
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@ import {
|
||||||
HomeScreen,
|
HomeScreen,
|
||||||
PostOptionsScreen,
|
PostOptionsScreen,
|
||||||
} from '@support/ui/screen';
|
} from '@support/ui/screen';
|
||||||
import {timeouts, wait} from '@support/utils';
|
import {timeouts, wait, waitForElementToBeVisible} from '@support/utils';
|
||||||
import {expect} from 'detox';
|
import {expect} from 'detox';
|
||||||
|
|
||||||
class SearchMessagesScreen {
|
class SearchMessagesScreen {
|
||||||
|
|
@ -87,11 +87,17 @@ class SearchMessagesScreen {
|
||||||
|
|
||||||
openPostOptionsFor = async (postId: string, text: string) => {
|
openPostOptionsFor = async (postId: string, text: string) => {
|
||||||
const {postListPostItem} = this.getPostListPostItem(postId, text);
|
const {postListPostItem} = this.getPostListPostItem(postId, text);
|
||||||
await wait(timeouts.TWO_SEC);
|
|
||||||
await expect(postListPostItem).toBeVisible();
|
// Poll for the post to become visible without waiting for idle bridge
|
||||||
|
await waitForElementToBeVisible(postListPostItem, timeouts.TEN_SEC);
|
||||||
|
|
||||||
|
// Dismiss keyboard by tapping on the post list (needed after posting a message)
|
||||||
|
const flatList = this.postList.getFlatList();
|
||||||
|
await flatList.scroll(100, 'down');
|
||||||
|
await wait(timeouts.ONE_SEC);
|
||||||
|
|
||||||
// # Open post options
|
// # Open post options
|
||||||
await postListPostItem.longPress();
|
await postListPostItem.longPress(timeouts.TWO_SEC);
|
||||||
await PostOptionsScreen.toBeVisible();
|
await PostOptionsScreen.toBeVisible();
|
||||||
await wait(timeouts.TWO_SEC);
|
await wait(timeouts.TWO_SEC);
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
// See LICENSE.txt for license information.
|
// See LICENSE.txt for license information.
|
||||||
|
|
||||||
import {Alert} from '@support/ui/component';
|
import {Alert} from '@support/ui/component';
|
||||||
import {isAndroid, isIos, timeouts, wait} from '@support/utils';
|
import {isAndroid, isIos, timeouts, wait, waitForElementToBeVisible} from '@support/utils';
|
||||||
import {expect} from 'detox';
|
import {expect} from 'detox';
|
||||||
|
|
||||||
class ServerScreen {
|
class ServerScreen {
|
||||||
|
|
@ -72,7 +72,10 @@ class ServerScreen {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
await waitFor(this.usernameInput).toExist().withTimeout(isAndroid()? timeouts.ONE_MIN : timeouts.HALF_MIN);
|
|
||||||
|
// The bridge can be busy during login transition, use waitFor without idle check
|
||||||
|
const timeout = isAndroid() ? timeouts.ONE_MIN : timeouts.HALF_MIN;
|
||||||
|
await waitFor(this.usernameInput).toBeVisible().withTimeout(timeout);
|
||||||
};
|
};
|
||||||
|
|
||||||
close = async () => {
|
close = async () => {
|
||||||
|
|
@ -123,7 +126,10 @@ class ServerScreen {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
await waitFor(this.usernameInput).toExist().withTimeout(isAndroid()? timeouts.ONE_MIN : timeouts.HALF_MIN);
|
|
||||||
|
// The bridge can be busy during login transition, so poll for the element without waiting for idle
|
||||||
|
const timeout = isAndroid() ? timeouts.ONE_MIN : timeouts.HALF_MIN;
|
||||||
|
await waitForElementToBeVisible(this.usernameInput, timeout, timeouts.ONE_SEC);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@ import {
|
||||||
SendButton,
|
SendButton,
|
||||||
} from '@support/ui/component';
|
} from '@support/ui/component';
|
||||||
import {PostOptionsScreen} from '@support/ui/screen';
|
import {PostOptionsScreen} from '@support/ui/screen';
|
||||||
import {timeouts, wait} from '@support/utils';
|
import {timeouts, wait, waitForElementToBeVisible} from '@support/utils';
|
||||||
import {expect} from 'detox';
|
import {expect} from 'detox';
|
||||||
|
|
||||||
class ThreadScreen {
|
class ThreadScreen {
|
||||||
|
|
@ -93,14 +93,24 @@ class ThreadScreen {
|
||||||
back = async () => {
|
back = async () => {
|
||||||
await this.backButton.tap();
|
await this.backButton.tap();
|
||||||
await waitFor(this.threadScreen).not.toBeVisible().withTimeout(timeouts.TEN_SEC);
|
await waitFor(this.threadScreen).not.toBeVisible().withTimeout(timeouts.TEN_SEC);
|
||||||
|
|
||||||
|
// Wait for the previous screen to be fully loaded and rendered
|
||||||
|
await wait(timeouts.TWO_SEC);
|
||||||
};
|
};
|
||||||
|
|
||||||
openPostOptionsFor = async (postId: string, text: string) => {
|
openPostOptionsFor = async (postId: string, text: string) => {
|
||||||
const {postListPostItem} = this.getPostListPostItem(postId, text);
|
const {postListPostItem} = this.getPostListPostItem(postId, text);
|
||||||
await expect(postListPostItem).toBeVisible();
|
|
||||||
|
// Poll for the post to become visible without waiting for idle bridge
|
||||||
|
await waitForElementToBeVisible(postListPostItem, timeouts.TEN_SEC);
|
||||||
|
|
||||||
|
// Dismiss keyboard by tapping on the post list (needed after posting a message)
|
||||||
|
const flatList = this.postList.getFlatList();
|
||||||
|
await flatList.scroll(100, 'down');
|
||||||
|
await wait(timeouts.ONE_SEC);
|
||||||
|
|
||||||
// # Open post options
|
// # Open post options
|
||||||
await postListPostItem.longPress();
|
await postListPostItem.longPress(timeouts.TWO_SEC);
|
||||||
await PostOptionsScreen.toBeVisible();
|
await PostOptionsScreen.toBeVisible();
|
||||||
await wait(timeouts.TWO_SEC);
|
await wait(timeouts.TWO_SEC);
|
||||||
};
|
};
|
||||||
|
|
@ -110,6 +120,9 @@ class ThreadScreen {
|
||||||
await this.postInput.tap();
|
await this.postInput.tap();
|
||||||
await this.postInput.replaceText(message);
|
await this.postInput.replaceText(message);
|
||||||
await this.tapSendButton();
|
await this.tapSendButton();
|
||||||
|
|
||||||
|
// # Wait for message to be rendered
|
||||||
|
await wait(timeouts.FOUR_SEC);
|
||||||
};
|
};
|
||||||
|
|
||||||
enterMessageToSchedule = async (message: string) => {
|
enterMessageToSchedule = async (message: string) => {
|
||||||
|
|
|
||||||
|
|
@ -70,6 +70,7 @@ export const timeouts = {
|
||||||
HALF_SEC: SECOND / 2,
|
HALF_SEC: SECOND / 2,
|
||||||
ONE_SEC: SECOND,
|
ONE_SEC: SECOND,
|
||||||
TWO_SEC: SECOND * 2,
|
TWO_SEC: SECOND * 2,
|
||||||
|
THREE_SEC: SECOND * 3,
|
||||||
FOUR_SEC: SECOND * 4,
|
FOUR_SEC: SECOND * 4,
|
||||||
TEN_SEC: SECOND * 10,
|
TEN_SEC: SECOND * 10,
|
||||||
HALF_MIN: MINUTE / 2,
|
HALF_MIN: MINUTE / 2,
|
||||||
|
|
@ -103,3 +104,43 @@ export async function retryWithReload(func: () => Promise<void>, retries: number
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Poll for an element to become visible without waiting for React Native bridge to be idle.
|
||||||
|
* This is useful when the bridge is busy with animations or state updates but the UI is already rendered.
|
||||||
|
*
|
||||||
|
* @param {Detox.NativeElement} detoxElement - The Detox element to wait for
|
||||||
|
* @param {number} timeout - Maximum time to wait in milliseconds (default: 10 seconds)
|
||||||
|
* @param {number} pollInterval - How often to check in milliseconds (default: 500ms)
|
||||||
|
* @return {Promise<void>} - Resolves when element is visible, throws if timeout is reached
|
||||||
|
* @throws {Error} - If element is not visible after timeout
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
* const button = element(by.id('my.button'));
|
||||||
|
* await waitForElementToBeVisible(button, timeouts.TEN_SEC);
|
||||||
|
*/
|
||||||
|
export async function waitForElementToBeVisible(
|
||||||
|
detoxElement: Detox.NativeElement,
|
||||||
|
timeout: number = timeouts.TEN_SEC,
|
||||||
|
pollInterval: number = timeouts.HALF_SEC,
|
||||||
|
): Promise<void> {
|
||||||
|
const {expect: detoxExpect} = require('detox');
|
||||||
|
const startTime = Date.now();
|
||||||
|
/* eslint-disable no-await-in-loop */
|
||||||
|
while (Date.now() - startTime < timeout) {
|
||||||
|
try {
|
||||||
|
await detoxExpect(detoxElement).toBeVisible();
|
||||||
|
return; // Element found and visible
|
||||||
|
} catch (error) {
|
||||||
|
// Element not visible yet, wait and try again
|
||||||
|
if ((Date.now() - startTime) + pollInterval >= timeout) {
|
||||||
|
// About to timeout, throw the error
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
await wait(pollInterval);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* eslint-enable no-await-in-loop */
|
||||||
|
// Final check - will throw if still not found
|
||||||
|
await detoxExpect(detoxElement).toBeVisible();
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@
|
||||||
// - Use element testID when selecting an element. Create one if none.
|
// - Use element testID when selecting an element. Create one if none.
|
||||||
// *******************************************************************
|
// *******************************************************************
|
||||||
|
|
||||||
import {Channel, Post, Setup, User} from '@support/server_api';
|
import {Post, Setup, User} from '@support/server_api';
|
||||||
import {
|
import {
|
||||||
serverOneUrl,
|
serverOneUrl,
|
||||||
siteOneUrl,
|
siteOneUrl,
|
||||||
|
|
@ -23,13 +23,12 @@ import {
|
||||||
SettingsScreen,
|
SettingsScreen,
|
||||||
} from '@support/ui/screen';
|
} from '@support/ui/screen';
|
||||||
import {getRandomId, timeouts, wait} from '@support/utils';
|
import {getRandomId, timeouts, wait} from '@support/utils';
|
||||||
import {expect} from 'detox';
|
import {expect, waitFor} from 'detox';
|
||||||
|
|
||||||
describe('Account - Account Menu', () => {
|
describe('Account - Account Menu', () => {
|
||||||
const serverOneDisplayName = 'Server 1';
|
const serverOneDisplayName = 'Server 1';
|
||||||
const channelsCategory = 'channels';
|
const channelsCategory = 'channels';
|
||||||
let testUser: any;
|
let testUser: any;
|
||||||
let otherUser: any;
|
|
||||||
let testChannel: any;
|
let testChannel: any;
|
||||||
|
|
||||||
beforeAll(async () => {
|
beforeAll(async () => {
|
||||||
|
|
@ -37,9 +36,6 @@ describe('Account - Account Menu', () => {
|
||||||
testUser = user;
|
testUser = user;
|
||||||
testChannel = channel;
|
testChannel = channel;
|
||||||
|
|
||||||
({user: otherUser} = await User.apiCreateUser(siteOneUrl));
|
|
||||||
await Channel.apiAddUserToChannel(siteOneUrl, otherUser.id, testChannel.id);
|
|
||||||
|
|
||||||
// # Log in to server and go to account screen
|
// # Log in to server and go to account screen
|
||||||
await ServerScreen.connectToServer(serverOneUrl, serverOneDisplayName);
|
await ServerScreen.connectToServer(serverOneUrl, serverOneDisplayName);
|
||||||
await LoginScreen.login(testUser);
|
await LoginScreen.login(testUser);
|
||||||
|
|
@ -53,6 +49,7 @@ describe('Account - Account Menu', () => {
|
||||||
|
|
||||||
afterAll(async () => {
|
afterAll(async () => {
|
||||||
// # Log out
|
// # Log out
|
||||||
|
await ChannelScreen.back();
|
||||||
await HomeScreen.logout();
|
await HomeScreen.logout();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -77,7 +74,8 @@ describe('Account - Account Menu', () => {
|
||||||
|
|
||||||
// * Verify on account screen and verify user presence icon and label are for offline user status
|
// * Verify on account screen and verify user presence icon and label are for offline user status
|
||||||
await AccountScreen.toBeVisible();
|
await AccountScreen.toBeVisible();
|
||||||
await expect(AccountScreen.getUserPresenceIndicator('offline')).toBeVisible();
|
await wait(timeouts.TWO_SEC);
|
||||||
|
await waitFor(AccountScreen.getUserPresenceIndicator('offline')).toExist().withTimeout(timeouts.TEN_SEC);
|
||||||
await expect(AccountScreen.getUserPresenceLabel('offline')).toHaveText('Offline');
|
await expect(AccountScreen.getUserPresenceLabel('offline')).toHaveText('Offline');
|
||||||
|
|
||||||
// # Tap on user presence option and tap on do not disturb user status option
|
// # Tap on user presence option and tap on do not disturb user status option
|
||||||
|
|
@ -87,7 +85,8 @@ describe('Account - Account Menu', () => {
|
||||||
|
|
||||||
// * Verify on account screen and verify user presence icon and label are for do no disturb user status
|
// * Verify on account screen and verify user presence icon and label are for do no disturb user status
|
||||||
await AccountScreen.toBeVisible();
|
await AccountScreen.toBeVisible();
|
||||||
await expect(AccountScreen.getUserPresenceIndicator('dnd')).toBeVisible();
|
await wait(timeouts.TWO_SEC);
|
||||||
|
await waitFor(AccountScreen.getUserPresenceIndicator('dnd')).toExist().withTimeout(timeouts.TEN_SEC);
|
||||||
await expect(AccountScreen.getUserPresenceLabel('dnd')).toHaveText('Do Not Disturb');
|
await expect(AccountScreen.getUserPresenceLabel('dnd')).toHaveText('Do Not Disturb');
|
||||||
|
|
||||||
// # Tap on user presence option and tap on away user status option
|
// # Tap on user presence option and tap on away user status option
|
||||||
|
|
@ -97,7 +96,8 @@ describe('Account - Account Menu', () => {
|
||||||
|
|
||||||
// * Verify on account screen and verify user presence icon and label are for away user status
|
// * Verify on account screen and verify user presence icon and label are for away user status
|
||||||
await AccountScreen.toBeVisible();
|
await AccountScreen.toBeVisible();
|
||||||
await expect(AccountScreen.getUserPresenceIndicator('away')).toBeVisible();
|
await wait(timeouts.TWO_SEC);
|
||||||
|
await waitFor(AccountScreen.getUserPresenceIndicator('away')).toExist().withTimeout(timeouts.TEN_SEC);
|
||||||
await expect(AccountScreen.getUserPresenceLabel('away')).toHaveText('Away');
|
await expect(AccountScreen.getUserPresenceLabel('away')).toHaveText('Away');
|
||||||
|
|
||||||
// # Tap on user presence option and tap on online user status option
|
// # Tap on user presence option and tap on online user status option
|
||||||
|
|
@ -107,7 +107,8 @@ describe('Account - Account Menu', () => {
|
||||||
|
|
||||||
// * Verify on account screen and verify user presence icon and label are for online user status
|
// * Verify on account screen and verify user presence icon and label are for online user status
|
||||||
await AccountScreen.toBeVisible();
|
await AccountScreen.toBeVisible();
|
||||||
await expect(AccountScreen.getUserPresenceIndicator('online')).toBeVisible();
|
await wait(timeouts.TWO_SEC);
|
||||||
|
await waitFor(AccountScreen.getUserPresenceIndicator('online')).toExist().withTimeout(timeouts.TEN_SEC);
|
||||||
await expect(AccountScreen.getUserPresenceLabel('online')).toHaveText('Online');
|
await expect(AccountScreen.getUserPresenceLabel('online')).toHaveText('Online');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -191,9 +192,12 @@ describe('Account - Account Menu', () => {
|
||||||
await ChannelScreen.open(channelsCategory, testChannel.name);
|
await ChannelScreen.open(channelsCategory, testChannel.name);
|
||||||
await ChannelScreen.postMessage(message);
|
await ChannelScreen.postMessage(message);
|
||||||
|
|
||||||
|
// Wait for keyboard to dismiss and message to be posted
|
||||||
|
await wait(timeouts.TWO_SEC);
|
||||||
|
|
||||||
const {post} = await Post.apiGetLastPostInChannel(siteOneUrl, testChannel.id);
|
const {post} = await Post.apiGetLastPostInChannel(siteOneUrl, testChannel.id);
|
||||||
const {postListPostItem, postListPostItemHeaderDisplayName} = ChannelScreen.getPostListPostItem(post.id, message);
|
const {postListPostItem, postListPostItemHeaderDisplayName} = ChannelScreen.getPostListPostItem(post.id, message);
|
||||||
await expect(postListPostItem).toBeVisible();
|
await waitFor(postListPostItem).toBeVisible().withTimeout(timeouts.TEN_SEC);
|
||||||
await expect(postListPostItemHeaderDisplayName).toHaveText(testUser.username);
|
await expect(postListPostItemHeaderDisplayName).toHaveText(testUser.username);
|
||||||
|
|
||||||
// Also check profile screen
|
// Also check profile screen
|
||||||
|
|
|
||||||
|
|
@ -94,6 +94,7 @@ describe('Account - Custom Status', () => {
|
||||||
await openCustomStatusScreen();
|
await openCustomStatusScreen();
|
||||||
await selectSuggestedStatus(status);
|
await selectSuggestedStatus(status);
|
||||||
await CustomStatusScreen.doneButton.tap();
|
await CustomStatusScreen.doneButton.tap();
|
||||||
|
await wait(timeouts.ONE_SEC);
|
||||||
|
|
||||||
// * Verify status is set on account screen
|
// * Verify status is set on account screen
|
||||||
await verifyStatusSetOnAccountScreen(status);
|
await verifyStatusSetOnAccountScreen(status);
|
||||||
|
|
@ -116,6 +117,7 @@ describe('Account - Custom Status', () => {
|
||||||
// # Clean up
|
// # Clean up
|
||||||
await clearStatusInput();
|
await clearStatusInput();
|
||||||
await CustomStatusScreen.doneButton.tap();
|
await CustomStatusScreen.doneButton.tap();
|
||||||
|
await wait(timeouts.ONE_SEC);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('MM-T4990_3 - should be able to set a status via emoji picker and custom status', async () => {
|
it('MM-T4990_3 - should be able to set a status via emoji picker and custom status', async () => {
|
||||||
|
|
@ -128,10 +130,12 @@ describe('Account - Custom Status', () => {
|
||||||
// # Pick emoji and type custom status
|
// # Pick emoji and type custom status
|
||||||
await CustomStatusScreen.openEmojiPicker('default', true);
|
await CustomStatusScreen.openEmojiPicker('default', true);
|
||||||
await EmojiPickerScreen.searchInput.replaceText(customEmojiName);
|
await EmojiPickerScreen.searchInput.replaceText(customEmojiName);
|
||||||
|
await EmojiPickerScreen.searchInput.tapReturnKey();
|
||||||
await element(by.text('🤡')).tap();
|
await element(by.text('🤡')).tap();
|
||||||
await wait(timeouts.ONE_SEC);
|
await wait(timeouts.ONE_SEC);
|
||||||
await CustomStatusScreen.statusInput.replaceText(customStatusText);
|
await CustomStatusScreen.statusInput.replaceText(customStatusText);
|
||||||
await CustomStatusScreen.doneButton.tap();
|
await CustomStatusScreen.doneButton.tap();
|
||||||
|
await wait(timeouts.ONE_SEC);
|
||||||
|
|
||||||
// * Verify custom status is set
|
// * Verify custom status is set
|
||||||
await verifyStatusSetOnAccountScreen({emoji: customEmojiName, text: customStatusText, duration: customStatusDuration});
|
await verifyStatusSetOnAccountScreen({emoji: customEmojiName, text: customStatusText, duration: customStatusDuration});
|
||||||
|
|
@ -147,6 +151,7 @@ describe('Account - Custom Status', () => {
|
||||||
await clearButton.tap();
|
await clearButton.tap();
|
||||||
await clearStatusInput();
|
await clearStatusInput();
|
||||||
await CustomStatusScreen.doneButton.tap();
|
await CustomStatusScreen.doneButton.tap();
|
||||||
|
await wait(timeouts.ONE_SEC);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('MM-T4990_4 - should be able to clear custom status from account', async () => {
|
it('MM-T4990_4 - should be able to clear custom status from account', async () => {
|
||||||
|
|
@ -155,6 +160,7 @@ describe('Account - Custom Status', () => {
|
||||||
await openCustomStatusScreen();
|
await openCustomStatusScreen();
|
||||||
await selectSuggestedStatus(status);
|
await selectSuggestedStatus(status);
|
||||||
await CustomStatusScreen.doneButton.tap();
|
await CustomStatusScreen.doneButton.tap();
|
||||||
|
await wait(timeouts.ONE_SEC);
|
||||||
|
|
||||||
// * Verify status is set
|
// * Verify status is set
|
||||||
await verifyStatusSetOnAccountScreen(status);
|
await verifyStatusSetOnAccountScreen(status);
|
||||||
|
|
@ -164,7 +170,7 @@ describe('Account - Custom Status', () => {
|
||||||
await wait(timeouts.ONE_SEC);
|
await wait(timeouts.ONE_SEC);
|
||||||
|
|
||||||
// * Verify status is cleared
|
// * Verify status is cleared
|
||||||
await verifyStatusCleared(status);
|
await verifyStatusCleared();
|
||||||
|
|
||||||
// # Open custom status screen and verify cleared
|
// # Open custom status screen and verify cleared
|
||||||
await CustomStatusScreen.open();
|
await CustomStatusScreen.open();
|
||||||
|
|
@ -202,6 +208,7 @@ describe('Account - Custom Status', () => {
|
||||||
|
|
||||||
// # Save status
|
// # Save status
|
||||||
await CustomStatusScreen.doneButton.tap();
|
await CustomStatusScreen.doneButton.tap();
|
||||||
|
await wait(timeouts.TWO_SEC);
|
||||||
await expect(CustomStatusScreen.customStatusScreen).not.toBeVisible();
|
await expect(CustomStatusScreen.customStatusScreen).not.toBeVisible();
|
||||||
|
|
||||||
// * Verify status is set and visible in account screen
|
// * Verify status is set and visible in account screen
|
||||||
|
|
@ -227,6 +234,7 @@ describe('Account - Custom Status', () => {
|
||||||
await expect(recentCustomStatus).not.toExist();
|
await expect(recentCustomStatus).not.toExist();
|
||||||
|
|
||||||
await CustomStatusScreen.doneButton.tap();
|
await CustomStatusScreen.doneButton.tap();
|
||||||
|
await wait(timeouts.ONE_SEC);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('MM-T3891 - should be able to set custom status with emoji picker and manage it', async () => {
|
it('MM-T3891 - should be able to set custom status with emoji picker and manage it', async () => {
|
||||||
|
|
@ -254,15 +262,16 @@ describe('Account - Custom Status', () => {
|
||||||
await expect(CustomStatusScreen.getCustomStatusEmoji(customEmojiName)).toBeVisible();
|
await expect(CustomStatusScreen.getCustomStatusEmoji(customEmojiName)).toBeVisible();
|
||||||
|
|
||||||
// # Save status
|
// # Save status
|
||||||
await wait(timeouts.TWO_SEC);
|
|
||||||
await CustomStatusScreen.doneButton.tap();
|
await CustomStatusScreen.doneButton.tap();
|
||||||
|
await wait(timeouts.ONE_SEC);
|
||||||
|
|
||||||
// * Verify status is set in account screen
|
// * Verify status is set in account screen
|
||||||
await verifyStatusSetOnAccountScreen({emoji: customEmojiName, text: customStatusText, duration: customStatusDuration});
|
await verifyStatusSetOnAccountScreen({emoji: customEmojiName, text: customStatusText, duration: customStatusDuration});
|
||||||
|
|
||||||
// # Clear status from account screen
|
// # Clear status from account screen
|
||||||
await AccountScreen.customStatusClearButton.tap();
|
await AccountScreen.customStatusClearButton.tap();
|
||||||
await verifyStatusCleared({emoji: customEmojiName, text: customStatusText, duration: customStatusDuration});
|
await wait(timeouts.ONE_SEC);
|
||||||
|
await verifyStatusCleared();
|
||||||
|
|
||||||
// # Reopen and verify status in recent section
|
// # Reopen and verify status in recent section
|
||||||
await CustomStatusScreen.open();
|
await CustomStatusScreen.open();
|
||||||
|
|
@ -275,6 +284,7 @@ describe('Account - Custom Status', () => {
|
||||||
await recentStatus.tap();
|
await recentStatus.tap();
|
||||||
await verifyStatusInInput({emoji: customEmojiName, text: customStatusText, duration: customStatusDuration});
|
await verifyStatusInInput({emoji: customEmojiName, text: customStatusText, duration: customStatusDuration});
|
||||||
await CustomStatusScreen.doneButton.tap();
|
await CustomStatusScreen.doneButton.tap();
|
||||||
|
await wait(timeouts.ONE_SEC);
|
||||||
|
|
||||||
// * Verify status is set again
|
// * Verify status is set again
|
||||||
await AccountScreen.toBeVisible();
|
await AccountScreen.toBeVisible();
|
||||||
|
|
@ -294,9 +304,10 @@ describe('Account - Custom Status', () => {
|
||||||
await expect(recentCustomStatus).not.toExist();
|
await expect(recentCustomStatus).not.toExist();
|
||||||
|
|
||||||
await CustomStatusScreen.doneButton.tap();
|
await CustomStatusScreen.doneButton.tap();
|
||||||
|
await wait(timeouts.ONE_SEC);
|
||||||
|
|
||||||
// * Verify status is cleared
|
// * Verify status is cleared
|
||||||
await verifyStatusCleared({emoji: customEmojiName, text: customStatusText, duration: customStatusDuration});
|
await verifyStatusCleared();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('MM-T3892 - should manage recent custom statuses correctly', async () => {
|
it('MM-T3892 - should manage recent custom statuses correctly', async () => {
|
||||||
|
|
@ -309,10 +320,12 @@ describe('Account - Custom Status', () => {
|
||||||
// # Create custom status with emoji picker
|
// # Create custom status with emoji picker
|
||||||
await CustomStatusScreen.openEmojiPicker('default', true);
|
await CustomStatusScreen.openEmojiPicker('default', true);
|
||||||
await EmojiPickerScreen.searchInput.replaceText(customEmojiName);
|
await EmojiPickerScreen.searchInput.replaceText(customEmojiName);
|
||||||
|
await EmojiPickerScreen.searchInput.tapReturnKey();
|
||||||
await element(by.text('🤡')).tap();
|
await element(by.text('🤡')).tap();
|
||||||
await wait(timeouts.ONE_SEC);
|
await wait(timeouts.ONE_SEC);
|
||||||
await CustomStatusScreen.statusInput.replaceText(customStatusText);
|
await CustomStatusScreen.statusInput.replaceText(customStatusText);
|
||||||
await CustomStatusScreen.doneButton.tap();
|
await CustomStatusScreen.doneButton.tap();
|
||||||
|
await wait(timeouts.ONE_SEC);
|
||||||
|
|
||||||
// * Verify status is set
|
// * Verify status is set
|
||||||
await verifyStatusSetOnAccountScreen({emoji: customEmojiName, text: customStatusText, duration: customStatusDuration});
|
await verifyStatusSetOnAccountScreen({emoji: customEmojiName, text: customStatusText, duration: customStatusDuration});
|
||||||
|
|
@ -335,6 +348,7 @@ describe('Account - Custom Status', () => {
|
||||||
const suggestedStatus = STATUSES.IN_MEETING;
|
const suggestedStatus = STATUSES.IN_MEETING;
|
||||||
await selectSuggestedStatus(suggestedStatus);
|
await selectSuggestedStatus(suggestedStatus);
|
||||||
await CustomStatusScreen.doneButton.tap();
|
await CustomStatusScreen.doneButton.tap();
|
||||||
|
await wait(timeouts.ONE_SEC);
|
||||||
await verifyStatusSetOnAccountScreen(suggestedStatus);
|
await verifyStatusSetOnAccountScreen(suggestedStatus);
|
||||||
|
|
||||||
// # Clear and verify in recent section
|
// # Clear and verify in recent section
|
||||||
|
|
@ -352,6 +366,7 @@ describe('Account - Custom Status', () => {
|
||||||
await expect(CustomStatusScreen.getSuggestedCustomStatus(suggestedStatus.emoji, suggestedStatus.text, suggestedStatus.duration).customStatusSuggestion).toBeVisible();
|
await expect(CustomStatusScreen.getSuggestedCustomStatus(suggestedStatus.emoji, suggestedStatus.text, suggestedStatus.duration).customStatusSuggestion).toBeVisible();
|
||||||
|
|
||||||
await CustomStatusScreen.doneButton.tap();
|
await CustomStatusScreen.doneButton.tap();
|
||||||
|
await wait(timeouts.ONE_SEC);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('MM-T4091 - should be able to set custom status with expiry time and verify in various locations', async () => {
|
it('MM-T4091 - should be able to set custom status with expiry time and verify in various locations', async () => {
|
||||||
|
|
@ -365,6 +380,7 @@ describe('Account - Custom Status', () => {
|
||||||
await selectSuggestedStatus(status);
|
await selectSuggestedStatus(status);
|
||||||
await expect(CustomStatusScreen.getCustomStatusExpiry(status.duration)).toBeVisible();
|
await expect(CustomStatusScreen.getCustomStatusExpiry(status.duration)).toBeVisible();
|
||||||
await CustomStatusScreen.doneButton.tap();
|
await CustomStatusScreen.doneButton.tap();
|
||||||
|
await wait(timeouts.ONE_SEC);
|
||||||
|
|
||||||
// * Verify status is set with expiry time
|
// * Verify status is set with expiry time
|
||||||
await AccountScreen.toBeVisible();
|
await AccountScreen.toBeVisible();
|
||||||
|
|
@ -378,19 +394,17 @@ describe('Account - Custom Status', () => {
|
||||||
await ChannelListScreen.open();
|
await ChannelListScreen.open();
|
||||||
await ChannelScreen.open(channelsCategory, testChannel.name);
|
await ChannelScreen.open(channelsCategory, testChannel.name);
|
||||||
await ChannelScreen.postMessage(messageText);
|
await ChannelScreen.postMessage(messageText);
|
||||||
|
await ChannelScreen.dismissKeyboard();
|
||||||
|
|
||||||
const {post} = await Post.apiGetLastPostInChannel(siteOneUrl, testChannel.id);
|
const {post} = await Post.apiGetLastPostInChannel(siteOneUrl, testChannel.id);
|
||||||
const {postListPostItem, postListPostItemProfilePicture} =
|
const {postListPostItem, postListPostItemHeaderDisplayName} =
|
||||||
ChannelScreen.getPostListPostItem(post.id, messageText, {userId: testUser.id});
|
ChannelScreen.getPostListPostItem(post.id, messageText, {userId: testUser.id});
|
||||||
await expect(postListPostItem).toBeVisible();
|
await expect(postListPostItem).toBeVisible();
|
||||||
|
|
||||||
// # Tap avatar and verify user profile shows status
|
// # Tap display name to open user profile (more reliable than avatar tap)
|
||||||
if (!postListPostItemProfilePicture) {
|
await expect(postListPostItemHeaderDisplayName).toBeVisible();
|
||||||
throw new Error('postListPostItemProfilePicture is null');
|
await postListPostItemHeaderDisplayName.longPress();
|
||||||
}
|
await wait(timeouts.ONE_SEC);
|
||||||
await expect(postListPostItemProfilePicture).toBeVisible();
|
|
||||||
await postListPostItemProfilePicture.tap();
|
|
||||||
await wait(timeouts.TWO_SEC);
|
|
||||||
await UserProfileScreen.toBeVisible();
|
await UserProfileScreen.toBeVisible();
|
||||||
await UserProfileScreen.close();
|
await UserProfileScreen.close();
|
||||||
await ChannelScreen.back();
|
await ChannelScreen.back();
|
||||||
|
|
@ -413,7 +427,7 @@ describe('Account - Custom Status', () => {
|
||||||
// # Open channel info and verify status
|
// # Open channel info and verify status
|
||||||
await ChannelScreen.toBeVisible();
|
await ChannelScreen.toBeVisible();
|
||||||
await ChannelScreen.headerTitle.tap();
|
await ChannelScreen.headerTitle.tap();
|
||||||
await wait(timeouts.TWO_SEC);
|
await wait(timeouts.FOUR_SEC);
|
||||||
await ChannelInfoScreen.toBeVisible();
|
await ChannelInfoScreen.toBeVisible();
|
||||||
await ChannelInfoScreen.close();
|
await ChannelInfoScreen.close();
|
||||||
await ChannelScreen.back();
|
await ChannelScreen.back();
|
||||||
|
|
@ -421,7 +435,8 @@ describe('Account - Custom Status', () => {
|
||||||
// # Clean up
|
// # Clean up
|
||||||
await AccountScreen.open();
|
await AccountScreen.open();
|
||||||
await AccountScreen.customStatusClearButton.tap();
|
await AccountScreen.customStatusClearButton.tap();
|
||||||
await verifyStatusCleared(status);
|
await wait(timeouts.ONE_SEC);
|
||||||
|
await verifyStatusCleared();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -477,9 +492,9 @@ const verifyStatusSetOnAccountScreen = async (status: {emoji: string; text: stri
|
||||||
await expect(accountCustomStatusExpiry).toBeVisible();
|
await expect(accountCustomStatusExpiry).toBeVisible();
|
||||||
};
|
};
|
||||||
|
|
||||||
const verifyStatusCleared = async (status: {emoji: string; text?: string; duration: string}) => {
|
const verifyStatusCleared = async () => {
|
||||||
const {accountCustomStatusEmoji, accountCustomStatusText} =
|
await expect(AccountScreen.setStatusOption).toBeVisible();
|
||||||
AccountScreen.getCustomStatus(status.emoji, status.duration);
|
const customStatusText = element(by.id('account.custom_status.custom_status_text'));
|
||||||
await expect(accountCustomStatusEmoji).not.toExist();
|
await expect(customStatusText).toHaveText('Set a custom status');
|
||||||
await expect(accountCustomStatusText).toHaveText('Set a custom status');
|
await expect(AccountScreen.customStatusClearButton).not.toBeVisible();
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,8 @@ import {
|
||||||
ServerScreen,
|
ServerScreen,
|
||||||
SettingsScreen,
|
SettingsScreen,
|
||||||
} from '@support/ui/screen';
|
} from '@support/ui/screen';
|
||||||
import {expect} from 'detox';
|
import {timeouts, wait} from '@support/utils';
|
||||||
|
import {expect, waitFor} from 'detox';
|
||||||
|
|
||||||
describe('Account - Settings - Email Notification Settings', () => {
|
describe('Account - Settings - Email Notification Settings', () => {
|
||||||
const serverOneDisplayName = 'Server 1';
|
const serverOneDisplayName = 'Server 1';
|
||||||
|
|
@ -65,6 +66,9 @@ describe('Account - Settings - Email Notification Settings', () => {
|
||||||
// # Tap on never option
|
// # Tap on never option
|
||||||
await EmailNotificationSettingsScreen.neverOption.tap();
|
await EmailNotificationSettingsScreen.neverOption.tap();
|
||||||
|
|
||||||
|
// Wait for option to be selected
|
||||||
|
await wait(timeouts.ONE_SEC);
|
||||||
|
|
||||||
// * Verify email threads option does not exist
|
// * Verify email threads option does not exist
|
||||||
await expect(EmailNotificationSettingsScreen.emailThreadsOptionToggledOn).not.toExist();
|
await expect(EmailNotificationSettingsScreen.emailThreadsOptionToggledOn).not.toExist();
|
||||||
|
|
||||||
|
|
@ -73,7 +77,8 @@ describe('Account - Settings - Email Notification Settings', () => {
|
||||||
|
|
||||||
// * Verify on notification settings screen and never is set
|
// * Verify on notification settings screen and never is set
|
||||||
await NotificationSettingsScreen.toBeVisible();
|
await NotificationSettingsScreen.toBeVisible();
|
||||||
await expect(NotificationSettingsScreen.emailNotificationsOptionInfo).toHaveText('Never');
|
await wait(timeouts.TWO_SEC);
|
||||||
|
await waitFor(NotificationSettingsScreen.emailNotificationsOptionInfo).toHaveText('Never').withTimeout(timeouts.TEN_SEC);
|
||||||
|
|
||||||
// # Go back to email notification settings screen
|
// # Go back to email notification settings screen
|
||||||
await EmailNotificationSettingsScreen.open();
|
await EmailNotificationSettingsScreen.open();
|
||||||
|
|
@ -83,12 +88,15 @@ describe('Account - Settings - Email Notification Settings', () => {
|
||||||
|
|
||||||
// # Tap on immediately option, toggle email threads option off, and tap on back button
|
// # Tap on immediately option, toggle email threads option off, and tap on back button
|
||||||
await EmailNotificationSettingsScreen.immediatelyOption.tap();
|
await EmailNotificationSettingsScreen.immediatelyOption.tap();
|
||||||
|
await wait(timeouts.ONE_SEC);
|
||||||
await EmailNotificationSettingsScreen.toggleEmailThreadsOptionOff();
|
await EmailNotificationSettingsScreen.toggleEmailThreadsOptionOff();
|
||||||
|
await wait(timeouts.ONE_SEC);
|
||||||
await EmailNotificationSettingsScreen.back();
|
await EmailNotificationSettingsScreen.back();
|
||||||
|
|
||||||
// * Verify on notification settings screen and immediately is set
|
// * Verify on notification settings screen and immediately is set
|
||||||
await NotificationSettingsScreen.toBeVisible();
|
await NotificationSettingsScreen.toBeVisible();
|
||||||
await expect(NotificationSettingsScreen.emailNotificationsOptionInfo).toHaveText('Immediately');
|
await wait(timeouts.TWO_SEC);
|
||||||
|
await waitFor(NotificationSettingsScreen.emailNotificationsOptionInfo).toHaveText('Immediately').withTimeout(timeouts.TEN_SEC);
|
||||||
|
|
||||||
// # Go back to email notification settings screen
|
// # Go back to email notification settings screen
|
||||||
await EmailNotificationSettingsScreen.open();
|
await EmailNotificationSettingsScreen.open();
|
||||||
|
|
|
||||||
|
|
@ -81,13 +81,13 @@ describe('Autocomplete - At-Mention', () => {
|
||||||
await Autocomplete.toBeVisible();
|
await Autocomplete.toBeVisible();
|
||||||
|
|
||||||
// * Verify at-mention list is displayed
|
// * Verify at-mention list is displayed
|
||||||
await expect(Autocomplete.sectionAtMentionList).toBeVisible();
|
await expect(Autocomplete.sectionAtMentionList).toExist();
|
||||||
|
|
||||||
// # Type in username
|
// # Type in username
|
||||||
await ChannelScreen.postInput.typeText(testUser.username);
|
await ChannelScreen.postInput.typeText(testUser.username);
|
||||||
|
|
||||||
// * Verify at-mention autocomplete contains associated user suggestion
|
// * Verify at-mention autocomplete contains associated user suggestion
|
||||||
await expect(userAtMentionAutocomplete).toBeVisible();
|
await expect(userAtMentionAutocomplete).toExist();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('MM-T4878_2 - should suggest user based on nickname', async () => {
|
it('MM-T4878_2 - should suggest user based on nickname', async () => {
|
||||||
|
|
@ -96,13 +96,13 @@ describe('Autocomplete - At-Mention', () => {
|
||||||
await Autocomplete.toBeVisible();
|
await Autocomplete.toBeVisible();
|
||||||
|
|
||||||
// * Verify at-mention list is displayed
|
// * Verify at-mention list is displayed
|
||||||
await expect(Autocomplete.sectionAtMentionList).toBeVisible();
|
await expect(Autocomplete.sectionAtMentionList).toExist();
|
||||||
|
|
||||||
// # Type in nickname
|
// # Type in nickname
|
||||||
await ChannelScreen.postInput.typeText(testUser.nickname);
|
await ChannelScreen.postInput.typeText(testUser.nickname);
|
||||||
|
|
||||||
// * Verify at-mention autocomplete contains associated user suggestion
|
// * Verify at-mention autocomplete contains associated user suggestion
|
||||||
await expect(userAtMentionAutocomplete).toBeVisible();
|
await expect(userAtMentionAutocomplete).toExist();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('MM-T4878_3 - should suggest user based on first name', async () => {
|
it('MM-T4878_3 - should suggest user based on first name', async () => {
|
||||||
|
|
@ -111,13 +111,13 @@ describe('Autocomplete - At-Mention', () => {
|
||||||
await Autocomplete.toBeVisible();
|
await Autocomplete.toBeVisible();
|
||||||
|
|
||||||
// * Verify at-mention list is displayed
|
// * Verify at-mention list is displayed
|
||||||
await expect(Autocomplete.sectionAtMentionList).toBeVisible();
|
await expect(Autocomplete.sectionAtMentionList).toExist();
|
||||||
|
|
||||||
// # Type in first name
|
// # Type in first name
|
||||||
await ChannelScreen.postInput.typeText(testUser.first_name);
|
await ChannelScreen.postInput.typeText(testUser.first_name);
|
||||||
|
|
||||||
// * Verify at-mention autocomplete contains associated user suggestion
|
// * Verify at-mention autocomplete contains associated user suggestion
|
||||||
await expect(userAtMentionAutocomplete).toBeVisible();
|
await expect(userAtMentionAutocomplete).toExist();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('MM-T4878_4 - should suggest user based on last name', async () => {
|
it('MM-T4878_4 - should suggest user based on last name', async () => {
|
||||||
|
|
@ -126,13 +126,13 @@ describe('Autocomplete - At-Mention', () => {
|
||||||
await Autocomplete.toBeVisible();
|
await Autocomplete.toBeVisible();
|
||||||
|
|
||||||
// * Verify at-mention list is displayed
|
// * Verify at-mention list is displayed
|
||||||
await expect(Autocomplete.sectionAtMentionList).toBeVisible();
|
await expect(Autocomplete.sectionAtMentionList).toExist();
|
||||||
|
|
||||||
// # Type in last name
|
// # Type in last name
|
||||||
await ChannelScreen.postInput.typeText(testUser.last_name);
|
await ChannelScreen.postInput.typeText(testUser.last_name);
|
||||||
|
|
||||||
// * Verify at-mention autocomplete contains associated user suggestion
|
// * Verify at-mention autocomplete contains associated user suggestion
|
||||||
await expect(userAtMentionAutocomplete).toBeVisible();
|
await expect(userAtMentionAutocomplete).toExist();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('MM-T4878_5 - should suggest user based on lowercase first name', async () => {
|
it('MM-T4878_5 - should suggest user based on lowercase first name', async () => {
|
||||||
|
|
@ -141,13 +141,13 @@ describe('Autocomplete - At-Mention', () => {
|
||||||
await Autocomplete.toBeVisible();
|
await Autocomplete.toBeVisible();
|
||||||
|
|
||||||
// * Verify at-mention list is displayed
|
// * Verify at-mention list is displayed
|
||||||
await expect(Autocomplete.sectionAtMentionList).toBeVisible();
|
await expect(Autocomplete.sectionAtMentionList).toExist();
|
||||||
|
|
||||||
// # Type in lowercase first name
|
// # Type in lowercase first name
|
||||||
await ChannelScreen.postInput.typeText(testUser.first_name.toLowerCase());
|
await ChannelScreen.postInput.typeText(testUser.first_name.toLowerCase());
|
||||||
|
|
||||||
// * Verify at-mention autocomplete contains associated user suggestion
|
// * Verify at-mention autocomplete contains associated user suggestion
|
||||||
await expect(userAtMentionAutocomplete).toBeVisible();
|
await expect(userAtMentionAutocomplete).toExist();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('MM-T4878_6 - should suggest user based on lowercase last name', async () => {
|
it('MM-T4878_6 - should suggest user based on lowercase last name', async () => {
|
||||||
|
|
@ -156,13 +156,13 @@ describe('Autocomplete - At-Mention', () => {
|
||||||
await Autocomplete.toBeVisible();
|
await Autocomplete.toBeVisible();
|
||||||
|
|
||||||
// * Verify at-mention list is displayed
|
// * Verify at-mention list is displayed
|
||||||
await expect(Autocomplete.sectionAtMentionList).toBeVisible();
|
await expect(Autocomplete.sectionAtMentionList).toExist();
|
||||||
|
|
||||||
// # Type in lowercase last name
|
// # Type in lowercase last name
|
||||||
await ChannelScreen.postInput.typeText(testUser.last_name.toLowerCase());
|
await ChannelScreen.postInput.typeText(testUser.last_name.toLowerCase());
|
||||||
|
|
||||||
// * Verify at-mention autocomplete contains associated user suggestion
|
// * Verify at-mention autocomplete contains associated user suggestion
|
||||||
await expect(userAtMentionAutocomplete).toBeVisible();
|
await expect(userAtMentionAutocomplete).toExist();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('MM-T4878_7 - should suggest user based on full name with space', async () => {
|
it('MM-T4878_7 - should suggest user based on full name with space', async () => {
|
||||||
|
|
@ -171,13 +171,13 @@ describe('Autocomplete - At-Mention', () => {
|
||||||
await Autocomplete.toBeVisible();
|
await Autocomplete.toBeVisible();
|
||||||
|
|
||||||
// * Verify at-mention list is displayed
|
// * Verify at-mention list is displayed
|
||||||
await expect(Autocomplete.sectionAtMentionList).toBeVisible();
|
await expect(Autocomplete.sectionAtMentionList).toExist();
|
||||||
|
|
||||||
// # Type in full name with space
|
// # Type in full name with space
|
||||||
await ChannelScreen.postInput.typeText(`${testUser.first_name} ${testUser.last_name}`);
|
await ChannelScreen.postInput.typeText(`${testUser.first_name} ${testUser.last_name}`);
|
||||||
|
|
||||||
// * Verify at-mention autocomplete contains associated user suggestion
|
// * Verify at-mention autocomplete contains associated user suggestion
|
||||||
await expect(userAtMentionAutocomplete).toBeVisible();
|
await expect(userAtMentionAutocomplete).toExist();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('MM-T4878_8 - should suggest user based on partial full name with space', async () => {
|
it('MM-T4878_8 - should suggest user based on partial full name with space', async () => {
|
||||||
|
|
@ -186,13 +186,13 @@ describe('Autocomplete - At-Mention', () => {
|
||||||
await Autocomplete.toBeVisible();
|
await Autocomplete.toBeVisible();
|
||||||
|
|
||||||
// * Verify at-mention list is displayed
|
// * Verify at-mention list is displayed
|
||||||
await expect(Autocomplete.sectionAtMentionList).toBeVisible();
|
await expect(Autocomplete.sectionAtMentionList).toExist();
|
||||||
|
|
||||||
// # Type in partial full name with space
|
// # Type in partial full name with space
|
||||||
await ChannelScreen.postInput.typeText(`${testUser.first_name} ${testUser.last_name.substring(0, testUser.last_name.length - 6)}`);
|
await ChannelScreen.postInput.typeText(`${testUser.first_name} ${testUser.last_name.substring(0, testUser.last_name.length - 6)}`);
|
||||||
|
|
||||||
// * Verify at-mention autocomplete contains associated user suggestion
|
// * Verify at-mention autocomplete contains associated user suggestion
|
||||||
await expect(userAtMentionAutocomplete).toBeVisible();
|
await expect(userAtMentionAutocomplete).toExist();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('MM-T4878_9 - should stop suggesting user after full name with trailing space', async () => {
|
it('MM-T4878_9 - should stop suggesting user after full name with trailing space', async () => {
|
||||||
|
|
@ -201,20 +201,20 @@ describe('Autocomplete - At-Mention', () => {
|
||||||
await Autocomplete.toBeVisible();
|
await Autocomplete.toBeVisible();
|
||||||
|
|
||||||
// * Verify at-mention list is displayed
|
// * Verify at-mention list is displayed
|
||||||
await expect(Autocomplete.sectionAtMentionList).toBeVisible();
|
await expect(Autocomplete.sectionAtMentionList).toExist();
|
||||||
|
|
||||||
// # Type in full name
|
// # Type in full name
|
||||||
await ChannelScreen.postInput.typeText(`${testUser.first_name} ${testUser.last_name}`);
|
await ChannelScreen.postInput.typeText(`${testUser.first_name} ${testUser.last_name}`);
|
||||||
|
|
||||||
// * Verify at-mention autocomplete contains associated user suggestion
|
// * Verify at-mention autocomplete contains associated user suggestion
|
||||||
await expect(userAtMentionAutocomplete).toBeVisible();
|
await expect(userAtMentionAutocomplete).toExist();
|
||||||
|
|
||||||
// # Type in trailing space
|
// # Type in trailing space
|
||||||
await ChannelScreen.postInput.typeText(' ');
|
await ChannelScreen.postInput.typeText(' ');
|
||||||
await wait(timeouts.ONE_SEC);
|
await wait(timeouts.ONE_SEC);
|
||||||
|
|
||||||
// * Verify at-mention autocomplete does not contain associated user suggestion
|
// * Verify at-mention autocomplete does not contain associated user suggestion
|
||||||
await expect(userAtMentionAutocomplete).not.toBeVisible();
|
await expect(userAtMentionAutocomplete).not.toExist();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('MM-T4878_10 - should stop suggesting user when keyword is not associated with any user', async () => {
|
it('MM-T4878_10 - should stop suggesting user when keyword is not associated with any user', async () => {
|
||||||
|
|
@ -223,35 +223,38 @@ describe('Autocomplete - At-Mention', () => {
|
||||||
await Autocomplete.toBeVisible();
|
await Autocomplete.toBeVisible();
|
||||||
|
|
||||||
// * Verify at-mention list is displayed
|
// * Verify at-mention list is displayed
|
||||||
await expect(Autocomplete.sectionAtMentionList).toBeVisible();
|
await expect(Autocomplete.sectionAtMentionList).toExist();
|
||||||
|
|
||||||
// # Type in keyword not associated with any user
|
// # Type in keyword not associated with any user
|
||||||
await ChannelScreen.postInput.typeText(getRandomId());
|
await ChannelScreen.postInput.typeText(getRandomId());
|
||||||
|
await wait(timeouts.ONE_SEC);
|
||||||
|
|
||||||
// * Verify at-mention autocomplete does not contain associated user suggestion
|
// * Verify at-mention autocomplete does not contain associated user suggestion
|
||||||
await expect(userAtMentionAutocomplete).not.toBeVisible();
|
await expect(userAtMentionAutocomplete).not.toExist();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('MM-T4878_11 - should be able to select at-mention multiple times', async () => {
|
it('MM-T4878_11 - should be able to select at-mention multiple times', async () => {
|
||||||
// # Type in "@" to activate at-mention autocomplete
|
// # Type in "@" to activate at-mention autocomplete
|
||||||
await expect(Autocomplete.sectionAtMentionList).not.toBeVisible();
|
await expect(Autocomplete.sectionAtMentionList).not.toExist();
|
||||||
await ChannelScreen.postInput.typeText('@');
|
await ChannelScreen.postInput.typeText('@');
|
||||||
|
await wait(timeouts.ONE_SEC);
|
||||||
|
|
||||||
// * Verify at-mention list is displayed
|
// * Verify at-mention list is displayed
|
||||||
await expect(Autocomplete.sectionAtMentionList).toBeVisible();
|
await expect(Autocomplete.sectionAtMentionList).toExist();
|
||||||
|
|
||||||
// # Type in username and tap on user at-mention autocomplete
|
// # Type in username and tap on user at-mention autocomplete
|
||||||
await ChannelScreen.postInput.typeText(testUser.username);
|
await ChannelScreen.postInput.typeText(testUser.username);
|
||||||
await userAtMentionAutocomplete.tap();
|
await userAtMentionAutocomplete.tap();
|
||||||
|
|
||||||
// * Verify at-mention list disappears
|
// * Verify at-mention list disappears
|
||||||
await expect(Autocomplete.sectionAtMentionList).not.toBeVisible();
|
await expect(Autocomplete.sectionAtMentionList).not.toExist();
|
||||||
|
|
||||||
// # Type in "@" again to re-activate at-mention list
|
// # Type in "@" again to re-activate at-mention list
|
||||||
await ChannelScreen.postInput.typeText('@');
|
await ChannelScreen.postInput.typeText('@');
|
||||||
|
await wait(timeouts.ONE_SEC);
|
||||||
|
|
||||||
// * Verify at-mention list is displayed
|
// * Verify at-mention list is displayed
|
||||||
await expect(Autocomplete.sectionAtMentionList).toBeVisible();
|
await expect(Autocomplete.sectionAtMentionList).toExist();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('MM-T4878_12 - should not be able to autocomplete deactivated user', async () => {
|
it('MM-T4878_12 - should not be able to autocomplete deactivated user', async () => {
|
||||||
|
|
@ -261,13 +264,13 @@ describe('Autocomplete - At-Mention', () => {
|
||||||
await Autocomplete.toBeVisible();
|
await Autocomplete.toBeVisible();
|
||||||
|
|
||||||
// * Verify at-mention list is displayed
|
// * Verify at-mention list is displayed
|
||||||
await expect(Autocomplete.sectionAtMentionList).toBeVisible();
|
await expect(Autocomplete.sectionAtMentionList).toExist();
|
||||||
|
|
||||||
// # Type in username of deactivated user
|
// # Type in username of deactivated user
|
||||||
await ChannelScreen.postInput.typeText(testOtherUser.username);
|
await ChannelScreen.postInput.typeText(testOtherUser.username);
|
||||||
|
|
||||||
// * Verify at-mention autocomplete does not contain associated user suggestion
|
// * Verify at-mention autocomplete does not contain associated user suggestion
|
||||||
await expect(otherUserAtMentionAutocomplete).not.toBeVisible();
|
await expect(otherUserAtMentionAutocomplete).not.toExist();
|
||||||
|
|
||||||
// # Reactivate user, clear post input, and type in "@" to activate at-mention list
|
// # Reactivate user, clear post input, and type in "@" to activate at-mention list
|
||||||
await User.apiUpdateUserActiveStatus(siteOneUrl, testOtherUser.id, true);
|
await User.apiUpdateUserActiveStatus(siteOneUrl, testOtherUser.id, true);
|
||||||
|
|
@ -277,13 +280,13 @@ describe('Autocomplete - At-Mention', () => {
|
||||||
await Autocomplete.toBeVisible();
|
await Autocomplete.toBeVisible();
|
||||||
|
|
||||||
// * Verify at-mention list is displayed
|
// * Verify at-mention list is displayed
|
||||||
await expect(Autocomplete.sectionAtMentionList).toBeVisible();
|
await expect(Autocomplete.sectionAtMentionList).toExist();
|
||||||
|
|
||||||
// # Type in username of reactivated user
|
// # Type in username of reactivated user
|
||||||
await ChannelScreen.postInput.typeText(testOtherUser.username);
|
await ChannelScreen.postInput.typeText(testOtherUser.username);
|
||||||
|
|
||||||
// * Verify at-mention autocomplete contains associated user suggestion
|
// * Verify at-mention autocomplete contains associated user suggestion
|
||||||
await expect(otherUserAtMentionAutocomplete).toBeVisible();
|
await expect(otherUserAtMentionAutocomplete).toExist();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('MM-T4878_13 - should be able to autocomplete out of channel user', async () => {
|
it('MM-T4878_13 - should be able to autocomplete out of channel user', async () => {
|
||||||
|
|
@ -294,14 +297,14 @@ describe('Autocomplete - At-Mention', () => {
|
||||||
await Autocomplete.toBeVisible();
|
await Autocomplete.toBeVisible();
|
||||||
|
|
||||||
// * Verify at-mention list is displayed
|
// * Verify at-mention list is displayed
|
||||||
await expect(Autocomplete.sectionAtMentionList).toBeVisible();
|
await expect(Autocomplete.sectionAtMentionList).toExist();
|
||||||
|
|
||||||
// # Type in username of out of channel user
|
// # Type in username of out of channel user
|
||||||
await ChannelScreen.postInput.typeText(outOfChannelUser.username);
|
await ChannelScreen.postInput.typeText(outOfChannelUser.username);
|
||||||
|
|
||||||
// * Verify at-mention autocomplete contains associated user suggestion
|
// * Verify at-mention autocomplete contains associated user suggestion
|
||||||
const {atMentionItem: outOfChannelUserAtMentionAutocomplete} = Autocomplete.getAtMentionItem(outOfChannelUser.id);
|
const {atMentionItem: outOfChannelUserAtMentionAutocomplete} = Autocomplete.getAtMentionItem(outOfChannelUser.id);
|
||||||
await expect(outOfChannelUserAtMentionAutocomplete).toBeVisible();
|
await expect(outOfChannelUserAtMentionAutocomplete).toExist();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('MM-T4878_14 - should include current user in autocomplete', async () => {
|
it('MM-T4878_14 - should include current user in autocomplete', async () => {
|
||||||
|
|
@ -310,7 +313,7 @@ describe('Autocomplete - At-Mention', () => {
|
||||||
await Autocomplete.toBeVisible();
|
await Autocomplete.toBeVisible();
|
||||||
|
|
||||||
// * Verify at-mention list is displayed
|
// * Verify at-mention list is displayed
|
||||||
await expect(Autocomplete.sectionAtMentionList).toBeVisible();
|
await expect(Autocomplete.sectionAtMentionList).toExist();
|
||||||
|
|
||||||
// # Type in username of current user
|
// # Type in username of current user
|
||||||
await ChannelScreen.postInput.typeText(testUser.username);
|
await ChannelScreen.postInput.typeText(testUser.username);
|
||||||
|
|
@ -318,7 +321,7 @@ describe('Autocomplete - At-Mention', () => {
|
||||||
// * Verify at-mention autocomplete contains current user
|
// * Verify at-mention autocomplete contains current user
|
||||||
await wait(timeouts.TWO_SEC);
|
await wait(timeouts.TWO_SEC);
|
||||||
const {atMentionItemUserDisplayName, atMentionItemProfilePicture} = Autocomplete.getAtMentionItem(testUser.id);
|
const {atMentionItemUserDisplayName, atMentionItemProfilePicture} = Autocomplete.getAtMentionItem(testUser.id);
|
||||||
await expect(atMentionItemUserDisplayName).toBeVisible();
|
await expect(atMentionItemUserDisplayName).toExist();
|
||||||
await expect(atMentionItemProfilePicture).toBeVisible();
|
await expect(atMentionItemProfilePicture).toExist();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -77,13 +77,13 @@ describe('Autocomplete - Channel Mention', () => {
|
||||||
await Autocomplete.toBeVisible();
|
await Autocomplete.toBeVisible();
|
||||||
|
|
||||||
// * Verify channel mention list is displayed
|
// * Verify channel mention list is displayed
|
||||||
await expect(Autocomplete.sectionChannelMentionList).toBeVisible();
|
await expect(Autocomplete.sectionChannelMentionList).toExist();
|
||||||
|
|
||||||
// # Type in channel name
|
// # Type in channel name
|
||||||
await ChannelScreen.postInput.typeText(testChannel.name);
|
await ChannelScreen.postInput.typeText(testChannel.name);
|
||||||
|
|
||||||
// * Verify channel mention autocomplete contains associated channel suggestion
|
// * Verify channel mention autocomplete contains associated channel suggestion
|
||||||
await expect(channelMentionAutocomplete).toBeVisible();
|
await expect(channelMentionAutocomplete).toExist();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('MM-T4879_2 - should suggest channel based on channel display name', async () => {
|
it('MM-T4879_2 - should suggest channel based on channel display name', async () => {
|
||||||
|
|
@ -92,13 +92,13 @@ describe('Autocomplete - Channel Mention', () => {
|
||||||
await Autocomplete.toBeVisible();
|
await Autocomplete.toBeVisible();
|
||||||
|
|
||||||
// * Verify channel mention list is displayed
|
// * Verify channel mention list is displayed
|
||||||
await expect(Autocomplete.sectionChannelMentionList).toBeVisible();
|
await expect(Autocomplete.sectionChannelMentionList).toExist();
|
||||||
|
|
||||||
// # Type in channel display name
|
// # Type in channel display name
|
||||||
await ChannelScreen.postInput.typeText(testChannel.display_name);
|
await ChannelScreen.postInput.typeText(testChannel.display_name);
|
||||||
|
|
||||||
// * Verify channel mention autocomplete contains associated channel suggestion
|
// * Verify channel mention autocomplete contains associated channel suggestion
|
||||||
await expect(channelMentionAutocomplete).toBeVisible();
|
await expect(channelMentionAutocomplete).toExist();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('MM-T4879_3 - should suggest channel based on lowercase channel display name', async () => {
|
it('MM-T4879_3 - should suggest channel based on lowercase channel display name', async () => {
|
||||||
|
|
@ -107,13 +107,13 @@ describe('Autocomplete - Channel Mention', () => {
|
||||||
await Autocomplete.toBeVisible();
|
await Autocomplete.toBeVisible();
|
||||||
|
|
||||||
// * Verify channel mention list is displayed
|
// * Verify channel mention list is displayed
|
||||||
await expect(Autocomplete.sectionChannelMentionList).toBeVisible();
|
await expect(Autocomplete.sectionChannelMentionList).toExist();
|
||||||
|
|
||||||
// # Type in lowercase channel display name
|
// # Type in lowercase channel display name
|
||||||
await ChannelScreen.postInput.typeText(testChannel.display_name.toLowerCase());
|
await ChannelScreen.postInput.typeText(testChannel.display_name.toLowerCase());
|
||||||
|
|
||||||
// * Verify channel mention autocomplete contains associated channel suggestion
|
// * Verify channel mention autocomplete contains associated channel suggestion
|
||||||
await expect(channelMentionAutocomplete).toBeVisible();
|
await expect(channelMentionAutocomplete).toExist();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('MM-T4879_4 - should suggest channel based on partial channel display name', async () => {
|
it('MM-T4879_4 - should suggest channel based on partial channel display name', async () => {
|
||||||
|
|
@ -122,13 +122,13 @@ describe('Autocomplete - Channel Mention', () => {
|
||||||
await Autocomplete.toBeVisible();
|
await Autocomplete.toBeVisible();
|
||||||
|
|
||||||
// * Verify channel mention list is displayed
|
// * Verify channel mention list is displayed
|
||||||
await expect(Autocomplete.sectionChannelMentionList).toBeVisible();
|
await expect(Autocomplete.sectionChannelMentionList).toExist();
|
||||||
|
|
||||||
// # Type in partial channel display name
|
// # Type in partial channel display name
|
||||||
await ChannelScreen.postInput.typeText(`${testChannel.display_name.substring(0, testChannel.display_name.length - 4)}`);
|
await ChannelScreen.postInput.typeText(`${testChannel.display_name.substring(0, testChannel.display_name.length - 4)}`);
|
||||||
|
|
||||||
// * Verify channel mention autocomplete contains associated channel suggestion
|
// * Verify channel mention autocomplete contains associated channel suggestion
|
||||||
await expect(channelMentionAutocomplete).toBeVisible();
|
await expect(channelMentionAutocomplete).toExist();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('MM-T4879_5 - should stop suggesting channel after channel display name with trailing space', async () => {
|
it('MM-T4879_5 - should stop suggesting channel after channel display name with trailing space', async () => {
|
||||||
|
|
@ -137,20 +137,20 @@ describe('Autocomplete - Channel Mention', () => {
|
||||||
await Autocomplete.toBeVisible();
|
await Autocomplete.toBeVisible();
|
||||||
|
|
||||||
// * Verify channel mention list is displayed
|
// * Verify channel mention list is displayed
|
||||||
await expect(Autocomplete.sectionChannelMentionList).toBeVisible();
|
await expect(Autocomplete.sectionChannelMentionList).toExist();
|
||||||
|
|
||||||
// # Type in channel display name
|
// # Type in channel display name
|
||||||
await ChannelScreen.postInput.typeText(testChannel.display_name);
|
await ChannelScreen.postInput.typeText(testChannel.display_name);
|
||||||
|
|
||||||
// * Verify channel mention autocomplete contains associated channel suggestion
|
// * Verify channel mention autocomplete contains associated channel suggestion
|
||||||
await expect(channelMentionAutocomplete).toBeVisible();
|
await expect(channelMentionAutocomplete).toExist();
|
||||||
|
|
||||||
// # Type in trailing space
|
// # Type in trailing space
|
||||||
await ChannelScreen.postInput.typeText(' ');
|
await ChannelScreen.postInput.typeText(' ');
|
||||||
await wait(timeouts.ONE_SEC);
|
await wait(timeouts.ONE_SEC);
|
||||||
|
|
||||||
// * Verify channel mention autocomplete does not contain associated channel suggestion
|
// * Verify channel mention autocomplete does not contain associated channel suggestion
|
||||||
await expect(channelMentionAutocomplete).not.toBeVisible();
|
await expect(channelMentionAutocomplete).not.toExist();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('MM-T4879_6 - should stop suggesting channel when keyword is not associated with any channel', async () => {
|
it('MM-T4879_6 - should stop suggesting channel when keyword is not associated with any channel', async () => {
|
||||||
|
|
@ -159,35 +159,35 @@ describe('Autocomplete - Channel Mention', () => {
|
||||||
await Autocomplete.toBeVisible();
|
await Autocomplete.toBeVisible();
|
||||||
|
|
||||||
// * Verify channel mention list is displayed
|
// * Verify channel mention list is displayed
|
||||||
await expect(Autocomplete.sectionChannelMentionList).toBeVisible();
|
await expect(Autocomplete.sectionChannelMentionList).toExist();
|
||||||
|
|
||||||
// # Type in keyword not associated with any channel
|
// # Type in keyword not associated with any channel
|
||||||
await ChannelScreen.postInput.typeText(getRandomId());
|
await ChannelScreen.postInput.typeText(getRandomId());
|
||||||
|
|
||||||
// * Verify channel mention autocomplete does not contain associated channel suggestion
|
// * Verify channel mention autocomplete does not contain associated channel suggestion
|
||||||
await expect(channelMentionAutocomplete).not.toBeVisible();
|
await expect(channelMentionAutocomplete).not.toExist();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('MM-T4879_7 - should be able to select channel mention multiple times', async () => {
|
it('MM-T4879_7 - should be able to select channel mention multiple times', async () => {
|
||||||
// # Type in "~" to activate channel mention autocomplete
|
// # Type in "~" to activate channel mention autocomplete
|
||||||
await expect(Autocomplete.sectionChannelMentionList).not.toBeVisible();
|
await expect(Autocomplete.sectionChannelMentionList).not.toExist();
|
||||||
await ChannelScreen.postInput.typeText('~');
|
await ChannelScreen.postInput.typeText('~');
|
||||||
|
|
||||||
// * Verify channel mention list is displayed
|
// * Verify channel mention list is displayed
|
||||||
await expect(Autocomplete.sectionChannelMentionList).toBeVisible();
|
await expect(Autocomplete.sectionChannelMentionList).toExist();
|
||||||
|
|
||||||
// # Type in channel name and tap on channel mention autocomplete
|
// # Type in channel name and tap on channel mention autocomplete
|
||||||
await ChannelScreen.postInput.typeText(testChannel.name);
|
await ChannelScreen.postInput.typeText(testChannel.name);
|
||||||
await channelMentionAutocomplete.tap();
|
await channelMentionAutocomplete.tap();
|
||||||
|
|
||||||
// * Verify channel mention list disappears
|
// * Verify channel mention list disappears
|
||||||
await expect(Autocomplete.sectionChannelMentionList).not.toBeVisible();
|
await expect(Autocomplete.sectionChannelMentionList).not.toExist();
|
||||||
|
|
||||||
// # Type in "~" again to re-activate channel mention list
|
// # Type in "~" again to re-activate channel mention list
|
||||||
await ChannelScreen.postInput.typeText('~');
|
await ChannelScreen.postInput.typeText('~');
|
||||||
|
|
||||||
// * Verify channel mention list is displayed
|
// * Verify channel mention list is displayed
|
||||||
await expect(Autocomplete.sectionChannelMentionList).toBeVisible();
|
await expect(Autocomplete.sectionChannelMentionList).toExist();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('MM-T4879_8 - should be able to autocomplete archived channel', async () => {
|
it('MM-T4879_8 - should be able to autocomplete archived channel', async () => {
|
||||||
|
|
@ -197,13 +197,13 @@ describe('Autocomplete - Channel Mention', () => {
|
||||||
await Autocomplete.toBeVisible();
|
await Autocomplete.toBeVisible();
|
||||||
|
|
||||||
// * Verify channel mention list is displayed
|
// * Verify channel mention list is displayed
|
||||||
await expect(Autocomplete.sectionChannelMentionList).toBeVisible();
|
await expect(Autocomplete.sectionChannelMentionList).toExist();
|
||||||
|
|
||||||
// # Type in channel name of archived channel
|
// # Type in channel name of archived channel
|
||||||
await ChannelScreen.postInput.typeText(testOtherChannel.name);
|
await ChannelScreen.postInput.typeText(testOtherChannel.name);
|
||||||
|
|
||||||
// * Verify channel mention autocomplete contains associated channel suggestion
|
// * Verify channel mention autocomplete contains associated channel suggestion
|
||||||
await expect(otherChannelMentionAutocomplete).toBeVisible();
|
await expect(otherChannelMentionAutocomplete).toExist();
|
||||||
|
|
||||||
// # Unarchive channel, clear post input, and type in "~" to activate channel mention list
|
// # Unarchive channel, clear post input, and type in "~" to activate channel mention list
|
||||||
await Channel.apiRestoreChannel(siteOneUrl, testOtherChannel.id);
|
await Channel.apiRestoreChannel(siteOneUrl, testOtherChannel.id);
|
||||||
|
|
@ -213,13 +213,13 @@ describe('Autocomplete - Channel Mention', () => {
|
||||||
await Autocomplete.toBeVisible();
|
await Autocomplete.toBeVisible();
|
||||||
|
|
||||||
// * Verify channel mention list is displayed
|
// * Verify channel mention list is displayed
|
||||||
await expect(Autocomplete.sectionChannelMentionList).toBeVisible();
|
await expect(Autocomplete.sectionChannelMentionList).toExist();
|
||||||
|
|
||||||
// # Type in channel name of unarchived channel
|
// # Type in channel name of unarchived channel
|
||||||
await ChannelScreen.postInput.typeText(testOtherChannel.name);
|
await ChannelScreen.postInput.typeText(testOtherChannel.name);
|
||||||
|
|
||||||
// * Verify channel mention autocomplete contains associated channel suggestion
|
// * Verify channel mention autocomplete contains associated channel suggestion
|
||||||
await expect(otherChannelMentionAutocomplete).toBeVisible();
|
await expect(otherChannelMentionAutocomplete).toExist();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('MM-T4879_9 - should not be able to autocomplete out of team channel', async () => {
|
it('MM-T4879_9 - should not be able to autocomplete out of team channel', async () => {
|
||||||
|
|
@ -230,14 +230,14 @@ describe('Autocomplete - Channel Mention', () => {
|
||||||
await Autocomplete.toBeVisible();
|
await Autocomplete.toBeVisible();
|
||||||
|
|
||||||
// * Verify channel mention list is displayed
|
// * Verify channel mention list is displayed
|
||||||
await expect(Autocomplete.sectionChannelMentionList).toBeVisible();
|
await expect(Autocomplete.sectionChannelMentionList).toExist();
|
||||||
|
|
||||||
// # Type in channel name of out of team channel
|
// # Type in channel name of out of team channel
|
||||||
await ChannelScreen.postInput.typeText(outOfTeamChannel.name);
|
await ChannelScreen.postInput.typeText(outOfTeamChannel.name);
|
||||||
|
|
||||||
// * Verify channel mention autocomplete does not contain associated channel suggestion
|
// * Verify channel mention autocomplete does not contain associated channel suggestion
|
||||||
const {channelMentionItem: outOfTeamChannelChannelMentionAutocomplete} = Autocomplete.getChannelMentionItem(outOfTeamChannel.name);
|
const {channelMentionItem: outOfTeamChannelChannelMentionAutocomplete} = Autocomplete.getChannelMentionItem(outOfTeamChannel.name);
|
||||||
await expect(outOfTeamChannelChannelMentionAutocomplete).not.toBeVisible();
|
await expect(outOfTeamChannelChannelMentionAutocomplete).not.toExist();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('MM-T4879_10 - should include current channel in autocomplete', async () => {
|
it('MM-T4879_10 - should include current channel in autocomplete', async () => {
|
||||||
|
|
@ -246,13 +246,13 @@ describe('Autocomplete - Channel Mention', () => {
|
||||||
await Autocomplete.toBeVisible();
|
await Autocomplete.toBeVisible();
|
||||||
|
|
||||||
// * Verify channel mention list is displayed
|
// * Verify channel mention list is displayed
|
||||||
await expect(Autocomplete.sectionChannelMentionList).toBeVisible();
|
await expect(Autocomplete.sectionChannelMentionList).toExist();
|
||||||
|
|
||||||
// # Type in channel name of current channel
|
// # Type in channel name of current channel
|
||||||
await ChannelScreen.postInput.typeText(testChannel.name);
|
await ChannelScreen.postInput.typeText(testChannel.name);
|
||||||
|
|
||||||
// * Verify channel mention autocomplete contains current channel
|
// * Verify channel mention autocomplete contains current channel
|
||||||
const {channelMentionItemChannelDisplayName} = Autocomplete.getChannelMentionItem(testChannel.name);
|
const {channelMentionItemChannelDisplayName} = Autocomplete.getChannelMentionItem(testChannel.name);
|
||||||
await expect(channelMentionItemChannelDisplayName).toBeVisible();
|
await expect(channelMentionItemChannelDisplayName).toExist();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,7 @@ import {
|
||||||
LoginScreen,
|
LoginScreen,
|
||||||
ServerScreen,
|
ServerScreen,
|
||||||
} from '@support/ui/screen';
|
} from '@support/ui/screen';
|
||||||
|
import {timeouts, wait} from '@support/utils';
|
||||||
import {expect} from 'detox';
|
import {expect} from 'detox';
|
||||||
|
|
||||||
describe('Autocomplete - Channel Post Draft', () => {
|
describe('Autocomplete - Channel Post Draft', () => {
|
||||||
|
|
@ -56,45 +57,46 @@ describe('Autocomplete - Channel Post Draft', () => {
|
||||||
|
|
||||||
it('MM-T4882_1 - should render at-mention autocomplete in post input', async () => {
|
it('MM-T4882_1 - should render at-mention autocomplete in post input', async () => {
|
||||||
// * Verify at-mention list is not displayed
|
// * Verify at-mention list is not displayed
|
||||||
await expect(Autocomplete.sectionAtMentionList).not.toBeVisible();
|
await expect(Autocomplete.sectionAtMentionList).not.toExist();
|
||||||
|
|
||||||
// # Type in "@" to activate at-mention autocomplete
|
// # Type in "@" to activate at-mention autocomplete
|
||||||
await ChannelScreen.postInput.typeText('@');
|
await ChannelScreen.postInput.typeText('@');
|
||||||
|
|
||||||
// * Verify at-mention list is displayed
|
// * Verify at-mention list is displayed
|
||||||
await expect(Autocomplete.sectionAtMentionList).toBeVisible();
|
await expect(Autocomplete.sectionAtMentionList).toExist();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('MM-T4882_2 - should render channel mention autocomplete in post input', async () => {
|
it('MM-T4882_2 - should render channel mention autocomplete in post input', async () => {
|
||||||
// * Verify channel mention list is not displayed
|
// * Verify channel mention list is not displayed
|
||||||
await expect(Autocomplete.sectionChannelMentionList).not.toBeVisible();
|
await expect(Autocomplete.sectionChannelMentionList).not.toExist();
|
||||||
|
|
||||||
// # Type in "~" to activate channel mention autocomplete
|
// # Type in "~" to activate channel mention autocomplete
|
||||||
await ChannelScreen.postInput.typeText('~');
|
await ChannelScreen.postInput.typeText('~');
|
||||||
|
|
||||||
// * Verify channel mention list is displayed
|
// * Verify channel mention list is displayed
|
||||||
await expect(Autocomplete.sectionChannelMentionList).toBeVisible();
|
await expect(Autocomplete.sectionChannelMentionList).toExist();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('MM-T4882_3 - should render emoji suggestion autocomplete in post input', async () => {
|
it('MM-T4882_3 - should render emoji suggestion autocomplete in post input', async () => {
|
||||||
// * Verify emoji suggestion list is not displayed
|
// * Verify emoji suggestion list is not displayed
|
||||||
await expect(Autocomplete.flatEmojiSuggestionList).not.toBeVisible();
|
await expect(Autocomplete.flatEmojiSuggestionList).not.toExist();
|
||||||
|
|
||||||
// # Type in ":" followed by 2 characters to activate emoji suggestion autocomplete
|
// # Type in ":" followed by 2 characters to activate emoji suggestion autocomplete
|
||||||
await ChannelScreen.postInput.typeText(':sm');
|
await ChannelScreen.postInput.typeText(':sm');
|
||||||
|
|
||||||
// * Verify emoji suggestion list is displayed
|
// * Verify emoji suggestion list is displayed
|
||||||
await expect(Autocomplete.flatEmojiSuggestionList).toBeVisible();
|
await expect(Autocomplete.flatEmojiSuggestionList).toExist();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('MM-T4882_4 - should render slash suggestion autocomplete in post input', async () => {
|
it('MM-T4882_4 - should render slash suggestion autocomplete in post input', async () => {
|
||||||
// * Verify slash suggestion list is not displayed
|
// * Verify slash suggestion list is not displayed
|
||||||
await expect(Autocomplete.flatSlashSuggestionList).not.toBeVisible();
|
await expect(Autocomplete.flatSlashSuggestionList).not.toExist();
|
||||||
|
|
||||||
// # Type in "/" to activate slash suggestion autocomplete
|
// # Type in "/" to activate slash suggestion autocomplete
|
||||||
await ChannelScreen.postInput.typeText('/');
|
await ChannelScreen.postInput.typeText('/');
|
||||||
|
await wait(timeouts.ONE_SEC);
|
||||||
|
|
||||||
// * Verify slash suggestion list is displayed
|
// * Verify slash suggestion list is displayed
|
||||||
await expect(Autocomplete.flatSlashSuggestionList).toBeVisible();
|
await expect(Autocomplete.flatSlashSuggestionList).toExist();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -53,45 +53,45 @@ describe('Autocomplete - Create Channel', () => {
|
||||||
|
|
||||||
it('MM-T4904_1 - should render at-mention autocomplete in header input', async () => {
|
it('MM-T4904_1 - should render at-mention autocomplete in header input', async () => {
|
||||||
// * Verify at-mention list is not displayed
|
// * Verify at-mention list is not displayed
|
||||||
await expect(Autocomplete.sectionAtMentionList).not.toBeVisible();
|
await expect(Autocomplete.sectionAtMentionList).not.toExist();
|
||||||
|
|
||||||
// # Type in "@" to activate at-mention autocomplete
|
// # Type in "@" to activate at-mention autocomplete
|
||||||
await CreateOrEditChannelScreen.headerInput.typeText('@');
|
await CreateOrEditChannelScreen.headerInput.typeText('@');
|
||||||
|
|
||||||
// * Verify at-mention list is displayed
|
// * Verify at-mention list is displayed
|
||||||
await waitFor(Autocomplete.sectionAtMentionList).toBeVisible().withTimeout(timeouts.ONE_SEC);
|
await waitFor(Autocomplete.sectionAtMentionList).toExist().withTimeout(timeouts.ONE_SEC);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('MM-T4904_2 - should render channel mention autocomplete in header input', async () => {
|
it('MM-T4904_2 - should render channel mention autocomplete in header input', async () => {
|
||||||
// * Verify channel mention list is not displayed
|
// * Verify channel mention list is not displayed
|
||||||
await expect(Autocomplete.sectionChannelMentionList).not.toBeVisible();
|
await expect(Autocomplete.sectionChannelMentionList).not.toExist();
|
||||||
|
|
||||||
// # Type in "~" to activate channel mention autocomplete
|
// # Type in "~" to activate channel mention autocomplete
|
||||||
await CreateOrEditChannelScreen.headerInput.typeText('~');
|
await CreateOrEditChannelScreen.headerInput.typeText('~');
|
||||||
|
|
||||||
// * Verify channel mention list is displayed
|
// * Verify channel mention list is displayed
|
||||||
await expect(Autocomplete.sectionChannelMentionList).toBeVisible();
|
await expect(Autocomplete.sectionChannelMentionList).toExist();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('MM-T4904_3 - should render emoji suggestion autocomplete in header input', async () => {
|
it('MM-T4904_3 - should render emoji suggestion autocomplete in header input', async () => {
|
||||||
// * Verify emoji suggestion list is not displayed
|
// * Verify emoji suggestion list is not displayed
|
||||||
await expect(Autocomplete.flatEmojiSuggestionList).not.toBeVisible();
|
await expect(Autocomplete.flatEmojiSuggestionList).not.toExist();
|
||||||
|
|
||||||
// # Type in ":" followed by 2 characters to activate emoji suggestion autocomplete
|
// # Type in ":" followed by 2 characters to activate emoji suggestion autocomplete
|
||||||
await CreateOrEditChannelScreen.headerInput.typeText(':sm');
|
await CreateOrEditChannelScreen.headerInput.typeText(':sm');
|
||||||
|
|
||||||
// * Verify emoji suggestion list is displayed
|
// * Verify emoji suggestion list is displayed
|
||||||
await expect(Autocomplete.flatEmojiSuggestionList).toBeVisible();
|
await expect(Autocomplete.flatEmojiSuggestionList).toExist();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('MM-T4904_4 - should not render slash suggestion autocomplete in header input', async () => {
|
it('MM-T4904_4 - should not render slash suggestion autocomplete in header input', async () => {
|
||||||
// * Verify slash suggestion list is not displayed
|
// * Verify slash suggestion list is not displayed
|
||||||
await expect(Autocomplete.flatEmojiSuggestionList).not.toBeVisible();
|
await expect(Autocomplete.flatEmojiSuggestionList).not.toExist();
|
||||||
|
|
||||||
// # Type in "/" to activate slash suggestion autocomplete
|
// # Type in "/" to activate slash suggestion autocomplete
|
||||||
await CreateOrEditChannelScreen.headerInput.typeText('/');
|
await CreateOrEditChannelScreen.headerInput.typeText('/');
|
||||||
|
|
||||||
// * Verify slash suggestion list is still not displayed
|
// * Verify slash suggestion list is still not displayed
|
||||||
await expect(Autocomplete.flatEmojiSuggestionList).not.toBeVisible();
|
await expect(Autocomplete.flatEmojiSuggestionList).not.toExist();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -60,45 +60,45 @@ describe('Autocomplete - Edit Channel', () => {
|
||||||
|
|
||||||
it('MM-T4885_1 - should render at-mention autocomplete in header input', async () => {
|
it('MM-T4885_1 - should render at-mention autocomplete in header input', async () => {
|
||||||
// * Verify at-mention list is not displayed
|
// * Verify at-mention list is not displayed
|
||||||
await expect(Autocomplete.sectionAtMentionList).not.toBeVisible();
|
await expect(Autocomplete.sectionAtMentionList).not.toExist();
|
||||||
|
|
||||||
// # Type in "@" to activate at-mention autocomplete
|
// # Type in "@" to activate at-mention autocomplete
|
||||||
await CreateOrEditChannelScreen.headerInput.typeText('@');
|
await CreateOrEditChannelScreen.headerInput.typeText('@');
|
||||||
|
|
||||||
// * Verify at-mention list is displayed
|
// * Verify at-mention list is displayed
|
||||||
await waitFor(Autocomplete.sectionAtMentionList).toBeVisible().withTimeout(timeouts.ONE_SEC);
|
await waitFor(Autocomplete.sectionAtMentionList).toExist().withTimeout(timeouts.ONE_SEC);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('MM-T4885_2 - should render channel mention autocomplete in header input', async () => {
|
it('MM-T4885_2 - should render channel mention autocomplete in header input', async () => {
|
||||||
// * Verify channel mention list is not displayed
|
// * Verify channel mention list is not displayed
|
||||||
await expect(Autocomplete.sectionChannelMentionList).not.toBeVisible();
|
await expect(Autocomplete.sectionChannelMentionList).not.toExist();
|
||||||
|
|
||||||
// # Type in "~" to activate channel mention autocomplete
|
// # Type in "~" to activate channel mention autocomplete
|
||||||
await CreateOrEditChannelScreen.headerInput.typeText('~');
|
await CreateOrEditChannelScreen.headerInput.typeText('~');
|
||||||
|
|
||||||
// * Verify channel mention list is displayed
|
// * Verify channel mention list is displayed
|
||||||
await expect(Autocomplete.sectionChannelMentionList).toBeVisible();
|
await expect(Autocomplete.sectionChannelMentionList).toExist();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('MM-T4885_3 - should render emoji suggestion autocomplete in header input', async () => {
|
it('MM-T4885_3 - should render emoji suggestion autocomplete in header input', async () => {
|
||||||
// * Verify emoji suggestion list is not displayed
|
// * Verify emoji suggestion list is not displayed
|
||||||
await expect(Autocomplete.flatEmojiSuggestionList).not.toBeVisible();
|
await expect(Autocomplete.flatEmojiSuggestionList).not.toExist();
|
||||||
|
|
||||||
// # Type in ":" followed by 2 characters to activate emoji suggestion autocomplete
|
// # Type in ":" followed by 2 characters to activate emoji suggestion autocomplete
|
||||||
await CreateOrEditChannelScreen.headerInput.typeText(':sm');
|
await CreateOrEditChannelScreen.headerInput.typeText(':sm');
|
||||||
|
|
||||||
// * Verify emoji suggestion list is displayed
|
// * Verify emoji suggestion list is displayed
|
||||||
await expect(Autocomplete.flatEmojiSuggestionList).toBeVisible();
|
await expect(Autocomplete.flatEmojiSuggestionList).toExist();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('MM-T4885_4 - should not render slash suggestion autocomplete in header input', async () => {
|
it('MM-T4885_4 - should not render slash suggestion autocomplete in header input', async () => {
|
||||||
// * Verify slash suggestion list is not displayed
|
// * Verify slash suggestion list is not displayed
|
||||||
await expect(Autocomplete.flatEmojiSuggestionList).not.toBeVisible();
|
await expect(Autocomplete.flatEmojiSuggestionList).not.toExist();
|
||||||
|
|
||||||
// # Type in "/" to activate slash suggestion autocomplete
|
// # Type in "/" to activate slash suggestion autocomplete
|
||||||
await CreateOrEditChannelScreen.headerInput.typeText('/');
|
await CreateOrEditChannelScreen.headerInput.typeText('/');
|
||||||
|
|
||||||
// * Verify slash suggestion list is still not displayed
|
// * Verify slash suggestion list is still not displayed
|
||||||
await expect(Autocomplete.flatEmojiSuggestionList).not.toBeVisible();
|
await expect(Autocomplete.flatEmojiSuggestionList).not.toExist();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -57,46 +57,46 @@ describe('Autocomplete - Edit Channel Header', () => {
|
||||||
|
|
||||||
it('MM-T4884_1 - should render at-mention autocomplete in header input', async () => {
|
it('MM-T4884_1 - should render at-mention autocomplete in header input', async () => {
|
||||||
// * Verify at-mention list is not displayed
|
// * Verify at-mention list is not displayed
|
||||||
await expect(Autocomplete.sectionAtMentionList).not.toBeVisible();
|
await expect(Autocomplete.sectionAtMentionList).not.toExist();
|
||||||
|
|
||||||
// # Type in "@" to activate at-mention autocomplete
|
// # Type in "@" to activate at-mention autocomplete
|
||||||
await CreateOrEditChannelScreen.headerInput.typeText('@');
|
await CreateOrEditChannelScreen.headerInput.typeText('@');
|
||||||
|
|
||||||
// * Verify at-mention list is displayed
|
// * Verify at-mention list is displayed
|
||||||
await waitFor(Autocomplete.sectionAtMentionList).toExist().withTimeout(timeouts.ONE_SEC);
|
await waitFor(Autocomplete.sectionAtMentionList).toExist().withTimeout(timeouts.ONE_SEC);
|
||||||
await expect(Autocomplete.sectionAtMentionList).toBeVisible();
|
await expect(Autocomplete.sectionAtMentionList).toExist();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('MM-T4884_2 - should render channel mention autocomplete in header input', async () => {
|
it('MM-T4884_2 - should render channel mention autocomplete in header input', async () => {
|
||||||
// * Verify channel mention list is not displayed
|
// * Verify channel mention list is not displayed
|
||||||
await expect(Autocomplete.sectionChannelMentionList).not.toBeVisible();
|
await expect(Autocomplete.sectionChannelMentionList).not.toExist();
|
||||||
|
|
||||||
// # Type in "~" to activate channel mention autocomplete
|
// # Type in "~" to activate channel mention autocomplete
|
||||||
await CreateOrEditChannelScreen.headerInput.typeText('~');
|
await CreateOrEditChannelScreen.headerInput.typeText('~');
|
||||||
|
|
||||||
// * Verify channel mention list is displayed
|
// * Verify channel mention list is displayed
|
||||||
await expect(Autocomplete.sectionChannelMentionList).toBeVisible();
|
await expect(Autocomplete.sectionChannelMentionList).toExist();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('MM-T4884_3 - should render emoji suggestion autocomplete in header input', async () => {
|
it('MM-T4884_3 - should render emoji suggestion autocomplete in header input', async () => {
|
||||||
// * Verify emoji suggestion list is not displayed
|
// * Verify emoji suggestion list is not displayed
|
||||||
await expect(Autocomplete.flatEmojiSuggestionList).not.toBeVisible();
|
await expect(Autocomplete.flatEmojiSuggestionList).not.toExist();
|
||||||
|
|
||||||
// # Type in ":" followed by 2 characters to activate emoji suggestion autocomplete
|
// # Type in ":" followed by 2 characters to activate emoji suggestion autocomplete
|
||||||
await CreateOrEditChannelScreen.headerInput.typeText(':sm');
|
await CreateOrEditChannelScreen.headerInput.typeText(':sm');
|
||||||
|
|
||||||
// * Verify emoji suggestion list is displayed
|
// * Verify emoji suggestion list is displayed
|
||||||
await expect(Autocomplete.flatEmojiSuggestionList).toBeVisible();
|
await expect(Autocomplete.flatEmojiSuggestionList).toExist();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('MM-T4884_4 - should not render slash suggestion autocomplete in header input', async () => {
|
it('MM-T4884_4 - should not render slash suggestion autocomplete in header input', async () => {
|
||||||
// * Verify slash suggestion list is not displayed
|
// * Verify slash suggestion list is not displayed
|
||||||
await expect(Autocomplete.flatEmojiSuggestionList).not.toBeVisible();
|
await expect(Autocomplete.flatEmojiSuggestionList).not.toExist();
|
||||||
|
|
||||||
// # Type in "/" to activate slash suggestion autocomplete
|
// # Type in "/" to activate slash suggestion autocomplete
|
||||||
await CreateOrEditChannelScreen.headerInput.typeText('/');
|
await CreateOrEditChannelScreen.headerInput.typeText('/');
|
||||||
|
|
||||||
// * Verify slash suggestion list is still not displayed
|
// * Verify slash suggestion list is still not displayed
|
||||||
await expect(Autocomplete.flatEmojiSuggestionList).not.toBeVisible();
|
await expect(Autocomplete.flatEmojiSuggestionList).not.toExist();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -45,6 +45,7 @@ describe('Autocomplete - Edit Post', () => {
|
||||||
const message = `Messsage ${getRandomId()}`;
|
const message = `Messsage ${getRandomId()}`;
|
||||||
await ChannelScreen.open(channelsCategory, channel.name);
|
await ChannelScreen.open(channelsCategory, channel.name);
|
||||||
await ChannelScreen.postMessage(message);
|
await ChannelScreen.postMessage(message);
|
||||||
|
await ChannelScreen.dismissKeyboard();
|
||||||
const {post} = await Post.apiGetLastPostInChannel(siteOneUrl, channel.id);
|
const {post} = await Post.apiGetLastPostInChannel(siteOneUrl, channel.id);
|
||||||
await ChannelScreen.openPostOptionsFor(post.id, message);
|
await ChannelScreen.openPostOptionsFor(post.id, message);
|
||||||
await EditPostScreen.open();
|
await EditPostScreen.open();
|
||||||
|
|
@ -56,53 +57,58 @@ describe('Autocomplete - Edit Post', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
afterAll(async () => {
|
afterAll(async () => {
|
||||||
// # Log out
|
// # Close edit post screen if still open, then log out
|
||||||
await EditPostScreen.close();
|
try {
|
||||||
|
await waitFor(EditPostScreen.editPostScreen).toBeVisible().withTimeout(1000);
|
||||||
|
await EditPostScreen.close();
|
||||||
|
} catch {
|
||||||
|
// Edit post screen already closed, continue with logout
|
||||||
|
}
|
||||||
await ChannelScreen.back();
|
await ChannelScreen.back();
|
||||||
await HomeScreen.logout();
|
await HomeScreen.logout();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('MM-T4883_1 - should render at-mention autocomplete in message input', async () => {
|
it('MM-T4883_1 - should render at-mention autocomplete in message input', async () => {
|
||||||
// * Verify at-mention list is not displayed
|
// * Verify at-mention list is not displayed
|
||||||
await expect(Autocomplete.sectionAtMentionList).not.toBeVisible();
|
await expect(Autocomplete.sectionAtMentionList).not.toExist();
|
||||||
|
|
||||||
// # Type in "@" to activate at-mention autocomplete
|
// # Type in "@" to activate at-mention autocomplete
|
||||||
await EditPostScreen.messageInput.typeText('@');
|
await EditPostScreen.messageInput.typeText('@');
|
||||||
|
|
||||||
// * Verify at-mention list is displayed
|
// * Verify at-mention list is displayed
|
||||||
await expect(Autocomplete.sectionAtMentionList).toBeVisible();
|
await expect(Autocomplete.sectionAtMentionList).toExist();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('MM-T4883_2 - should render channel mention autocomplete in message input', async () => {
|
it('MM-T4883_2 - should render channel mention autocomplete in message input', async () => {
|
||||||
// * Verify channel mention list is not displayed
|
// * Verify channel mention list is not displayed
|
||||||
await expect(Autocomplete.sectionChannelMentionList).not.toBeVisible();
|
await expect(Autocomplete.sectionChannelMentionList).not.toExist();
|
||||||
|
|
||||||
// # Type in "~" to activate channel mention autocomplete
|
// # Type in "~" to activate channel mention autocomplete
|
||||||
await EditPostScreen.messageInput.typeText('~');
|
await EditPostScreen.messageInput.typeText('~');
|
||||||
|
|
||||||
// * Verify channel mention list is displayed
|
// * Verify channel mention list is displayed
|
||||||
await expect(Autocomplete.sectionChannelMentionList).toBeVisible();
|
await expect(Autocomplete.sectionChannelMentionList).toExist();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('MM-T4883_3 - should render emoji suggestion autocomplete in message input', async () => {
|
it('MM-T4883_3 - should render emoji suggestion autocomplete in message input', async () => {
|
||||||
// * Verify emoji suggestion list is not displayed
|
// * Verify emoji suggestion list is not displayed
|
||||||
await expect(Autocomplete.flatEmojiSuggestionList).not.toBeVisible();
|
await expect(Autocomplete.flatEmojiSuggestionList).not.toExist();
|
||||||
|
|
||||||
// # Type in ":" followed by 2 characters to activate emoji suggestion autocomplete
|
// # Type in ":" followed by 2 characters to activate emoji suggestion autocomplete
|
||||||
await EditPostScreen.messageInput.typeText(':sm');
|
await EditPostScreen.messageInput.typeText(':sm');
|
||||||
|
|
||||||
// * Verify emoji suggestion list is displayed
|
// * Verify emoji suggestion list is displayed
|
||||||
await expect(Autocomplete.flatEmojiSuggestionList).toBeVisible();
|
await expect(Autocomplete.flatEmojiSuggestionList).toExist();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('MM-T4883_4 - should not render slash suggestion autocomplete in message input', async () => {
|
it('MM-T4883_4 - should not render slash suggestion autocomplete in message input', async () => {
|
||||||
// * Verify slash suggestion list is not displayed
|
// * Verify slash suggestion list is not displayed
|
||||||
await expect(Autocomplete.flatEmojiSuggestionList).not.toBeVisible();
|
await expect(Autocomplete.flatEmojiSuggestionList).not.toExist();
|
||||||
|
|
||||||
// # Type in "/" to activate slash suggestion autocomplete
|
// # Type in "/" to activate slash suggestion autocomplete
|
||||||
await EditPostScreen.messageInput.typeText('/');
|
await EditPostScreen.messageInput.typeText('/');
|
||||||
|
|
||||||
// * Verify slash suggestion list is still not displayed
|
// * Verify slash suggestion list is still not displayed
|
||||||
await expect(Autocomplete.flatEmojiSuggestionList).not.toBeVisible();
|
await expect(Autocomplete.flatEmojiSuggestionList).not.toExist();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -67,13 +67,13 @@ describe('Autocomplete - Emoji Suggestion', () => {
|
||||||
await Autocomplete.toBeVisible();
|
await Autocomplete.toBeVisible();
|
||||||
|
|
||||||
// * Verify emoji suggestion list is displayed
|
// * Verify emoji suggestion list is displayed
|
||||||
await expect(Autocomplete.flatEmojiSuggestionList).toBeVisible();
|
await expect(Autocomplete.flatEmojiSuggestionList).toExist();
|
||||||
|
|
||||||
// # Type in 3rd to last characters of emoji name
|
// # Type in 3rd to last characters of emoji name
|
||||||
await ChannelScreen.postInput.typeText(emojiName3rdToLastChars);
|
await ChannelScreen.postInput.typeText(emojiName3rdToLastChars);
|
||||||
|
|
||||||
// * Verify emoji suggestion autocomplete contains associated emoji suggestion
|
// * Verify emoji suggestion autocomplete contains associated emoji suggestion
|
||||||
await expect(emojiSuggestionAutocomplete).toBeVisible();
|
await expect(emojiSuggestionAutocomplete).toExist();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('MM-T4880_2 - should suggest emoji based on uppercase emoji name', async () => {
|
it('MM-T4880_2 - should suggest emoji based on uppercase emoji name', async () => {
|
||||||
|
|
@ -82,13 +82,13 @@ describe('Autocomplete - Emoji Suggestion', () => {
|
||||||
await Autocomplete.toBeVisible();
|
await Autocomplete.toBeVisible();
|
||||||
|
|
||||||
// * Verify emoji suggestion list is displayed
|
// * Verify emoji suggestion list is displayed
|
||||||
await expect(Autocomplete.flatEmojiSuggestionList).toBeVisible();
|
await expect(Autocomplete.flatEmojiSuggestionList).toExist();
|
||||||
|
|
||||||
// # Type in uppercase 3rd to last characters of emoji name
|
// # Type in uppercase 3rd to last characters of emoji name
|
||||||
await ChannelScreen.postInput.typeText(emojiName3rdToLastChars.toUpperCase());
|
await ChannelScreen.postInput.typeText(emojiName3rdToLastChars.toUpperCase());
|
||||||
|
|
||||||
// * Verify emoji suggestion autocomplete contains associated emoji suggestion
|
// * Verify emoji suggestion autocomplete contains associated emoji suggestion
|
||||||
await expect(emojiSuggestionAutocomplete).toBeVisible();
|
await expect(emojiSuggestionAutocomplete).toExist();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('MM-T4880_3 - should suggest emoji based on partial emoji name', async () => {
|
it('MM-T4880_3 - should suggest emoji based on partial emoji name', async () => {
|
||||||
|
|
@ -97,13 +97,13 @@ describe('Autocomplete - Emoji Suggestion', () => {
|
||||||
await Autocomplete.toBeVisible();
|
await Autocomplete.toBeVisible();
|
||||||
|
|
||||||
// * Verify emoji suggestion list is displayed
|
// * Verify emoji suggestion list is displayed
|
||||||
await expect(Autocomplete.flatEmojiSuggestionList).toBeVisible();
|
await expect(Autocomplete.flatEmojiSuggestionList).toExist();
|
||||||
|
|
||||||
// # Type in partial emoji name
|
// # Type in partial emoji name
|
||||||
await ChannelScreen.postInput.typeText(`${emojiName.substring(2, 4)}`);
|
await ChannelScreen.postInput.typeText(`${emojiName.substring(2, 4)}`);
|
||||||
|
|
||||||
// * Verify emoji suggestion autocomplete contains associated emoji suggestion
|
// * Verify emoji suggestion autocomplete contains associated emoji suggestion
|
||||||
await expect(emojiSuggestionAutocomplete).toBeVisible();
|
await expect(emojiSuggestionAutocomplete).toExist();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('MM-T4880_4 - should stop suggesting emoji after emoji name with trailing space', async () => {
|
it('MM-T4880_4 - should stop suggesting emoji after emoji name with trailing space', async () => {
|
||||||
|
|
@ -112,20 +112,20 @@ describe('Autocomplete - Emoji Suggestion', () => {
|
||||||
await Autocomplete.toBeVisible();
|
await Autocomplete.toBeVisible();
|
||||||
|
|
||||||
// * Verify emoji suggestion list is displayed
|
// * Verify emoji suggestion list is displayed
|
||||||
await expect(Autocomplete.flatEmojiSuggestionList).toBeVisible();
|
await expect(Autocomplete.flatEmojiSuggestionList).toExist();
|
||||||
|
|
||||||
// # Type in 3rd to last characters of emoji name
|
// # Type in 3rd to last characters of emoji name
|
||||||
await ChannelScreen.postInput.typeText(emojiName3rdToLastChars);
|
await ChannelScreen.postInput.typeText(emojiName3rdToLastChars);
|
||||||
|
|
||||||
// * Verify emoji suggestion autocomplete contains associated emoji suggestion
|
// * Verify emoji suggestion autocomplete contains associated emoji suggestion
|
||||||
await expect(emojiSuggestionAutocomplete).toBeVisible();
|
await expect(emojiSuggestionAutocomplete).toExist();
|
||||||
|
|
||||||
// # Type in trailing space
|
// # Type in trailing space
|
||||||
await ChannelScreen.postInput.typeText(' ');
|
await ChannelScreen.postInput.typeText(' ');
|
||||||
await wait(timeouts.ONE_SEC);
|
await wait(timeouts.ONE_SEC);
|
||||||
|
|
||||||
// * Verify emoji suggestion autocomplete does not contain associated emoji suggestion
|
// * Verify emoji suggestion autocomplete does not contain associated emoji suggestion
|
||||||
await expect(emojiSuggestionAutocomplete).not.toBeVisible();
|
await expect(emojiSuggestionAutocomplete).not.toExist();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('MM-T4880_5 - should stop suggesting emoji when keyword is not associated with any emoji', async () => {
|
it('MM-T4880_5 - should stop suggesting emoji when keyword is not associated with any emoji', async () => {
|
||||||
|
|
@ -134,34 +134,34 @@ describe('Autocomplete - Emoji Suggestion', () => {
|
||||||
await Autocomplete.toBeVisible();
|
await Autocomplete.toBeVisible();
|
||||||
|
|
||||||
// * Verify emoji suggestion list is displayed
|
// * Verify emoji suggestion list is displayed
|
||||||
await expect(Autocomplete.flatEmojiSuggestionList).toBeVisible();
|
await expect(Autocomplete.flatEmojiSuggestionList).toExist();
|
||||||
|
|
||||||
// # Type in keyword not associated with any emoji
|
// # Type in keyword not associated with any emoji
|
||||||
await ChannelScreen.postInput.typeText(getRandomId());
|
await ChannelScreen.postInput.typeText(getRandomId());
|
||||||
|
|
||||||
// * Verify emoji suggestion autocomplete does not contain associated emoji suggestion
|
// * Verify emoji suggestion autocomplete does not contain associated emoji suggestion
|
||||||
await expect(emojiSuggestionAutocomplete).not.toBeVisible();
|
await expect(emojiSuggestionAutocomplete).not.toExist();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('MM-T4880_6 - should be able to select emoji suggestion multiple times', async () => {
|
it('MM-T4880_6 - should be able to select emoji suggestion multiple times', async () => {
|
||||||
// # Type in ":" then first 2 characters of emoji name to activate emoji suggestion autocomplete
|
// # Type in ":" then first 2 characters of emoji name to activate emoji suggestion autocomplete
|
||||||
await expect(Autocomplete.flatEmojiSuggestionList).not.toBeVisible();
|
await expect(Autocomplete.flatEmojiSuggestionList).not.toExist();
|
||||||
await ChannelScreen.postInput.typeText(`:${emojiNameFirst2Chars}`);
|
await ChannelScreen.postInput.typeText(`:${emojiNameFirst2Chars}`);
|
||||||
|
|
||||||
// * Verify emoji suggestion list is displayed
|
// * Verify emoji suggestion list is displayed
|
||||||
await expect(Autocomplete.flatEmojiSuggestionList).toBeVisible();
|
await expect(Autocomplete.flatEmojiSuggestionList).toExist();
|
||||||
|
|
||||||
// # Type in 3rd to last characters of emoji name and tap on emoji suggestion autocomplete
|
// # Type in 3rd to last characters of emoji name and tap on emoji suggestion autocomplete
|
||||||
await ChannelScreen.postInput.typeText(emojiName3rdToLastChars);
|
await ChannelScreen.postInput.typeText(emojiName3rdToLastChars);
|
||||||
await emojiSuggestionAutocomplete.tap();
|
await emojiSuggestionAutocomplete.tap();
|
||||||
|
|
||||||
// * Verify emoji suggestion list disappears
|
// * Verify emoji suggestion list disappears
|
||||||
await expect(Autocomplete.flatEmojiSuggestionList).not.toBeVisible();
|
await expect(Autocomplete.flatEmojiSuggestionList).not.toExist();
|
||||||
|
|
||||||
// # Type in ":" then first 2 characters of emoji name again to re-activate emoji suggestion list
|
// # Type in ":" then first 2 characters of emoji name again to re-activate emoji suggestion list
|
||||||
await ChannelScreen.postInput.typeText(`:${emojiNameFirst2Chars}`);
|
await ChannelScreen.postInput.typeText(`:${emojiNameFirst2Chars}`);
|
||||||
|
|
||||||
// * Verify emoji suggestion list is displayed
|
// * Verify emoji suggestion list is displayed
|
||||||
await expect(Autocomplete.flatEmojiSuggestionList).toBeVisible();
|
await expect(Autocomplete.flatEmojiSuggestionList).toExist();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -65,13 +65,13 @@ describe('Autocomplete - Slash Suggestion', () => {
|
||||||
await Autocomplete.toBeVisible();
|
await Autocomplete.toBeVisible();
|
||||||
|
|
||||||
// * Verify slash suggestion list is displayed
|
// * Verify slash suggestion list is displayed
|
||||||
await expect(Autocomplete.flatSlashSuggestionList).toBeVisible();
|
await expect(Autocomplete.flatSlashSuggestionList).toExist();
|
||||||
|
|
||||||
// # Type in slash command name
|
// # Type in slash command name
|
||||||
await ChannelScreen.postInput.typeText(slashCommand);
|
await ChannelScreen.postInput.typeText(slashCommand);
|
||||||
|
|
||||||
// * Verify slash suggestion autocomplete contains associated slash command suggestion
|
// * Verify slash suggestion autocomplete contains associated slash command suggestion
|
||||||
await expect(slashSuggestionAutocomplete).toBeVisible();
|
await expect(slashSuggestionAutocomplete).toExist();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('MM-T4881_2 - should suggest slash command based on partial slash command name', async () => {
|
it('MM-T4881_2 - should suggest slash command based on partial slash command name', async () => {
|
||||||
|
|
@ -80,13 +80,13 @@ describe('Autocomplete - Slash Suggestion', () => {
|
||||||
await Autocomplete.toBeVisible();
|
await Autocomplete.toBeVisible();
|
||||||
|
|
||||||
// * Verify slash suggestion list is displayed
|
// * Verify slash suggestion list is displayed
|
||||||
await expect(Autocomplete.flatSlashSuggestionList).toBeVisible();
|
await expect(Autocomplete.flatSlashSuggestionList).toExist();
|
||||||
|
|
||||||
// # Type in partial slash command name
|
// # Type in partial slash command name
|
||||||
await ChannelScreen.postInput.typeText(`${slashCommand.substring(0, slashCommand.length - 2)}`);
|
await ChannelScreen.postInput.typeText(`${slashCommand.substring(0, slashCommand.length - 2)}`);
|
||||||
|
|
||||||
// * Verify slash suggestion autocomplete contains associated slash command suggestion
|
// * Verify slash suggestion autocomplete contains associated slash command suggestion
|
||||||
await expect(slashSuggestionAutocomplete).toBeVisible();
|
await expect(slashSuggestionAutocomplete).toExist();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('MM-T4881_3 - should stop suggesting slash command after uppercase slash command name', async () => {
|
it('MM-T4881_3 - should stop suggesting slash command after uppercase slash command name', async () => {
|
||||||
|
|
@ -95,13 +95,13 @@ describe('Autocomplete - Slash Suggestion', () => {
|
||||||
await Autocomplete.toBeVisible();
|
await Autocomplete.toBeVisible();
|
||||||
|
|
||||||
// * Verify slash suggestion list is displayed
|
// * Verify slash suggestion list is displayed
|
||||||
await expect(Autocomplete.flatSlashSuggestionList).toBeVisible();
|
await expect(Autocomplete.flatSlashSuggestionList).toExist();
|
||||||
|
|
||||||
// # Type in uppercase slash command name
|
// # Type in uppercase slash command name
|
||||||
await ChannelScreen.postInput.typeText(slashCommand.toUpperCase());
|
await ChannelScreen.postInput.typeText(slashCommand.toUpperCase());
|
||||||
|
|
||||||
// * Verify slash suggestion autocomplete does not contain associated slash command suggestion
|
// * Verify slash suggestion autocomplete does not contain associated slash command suggestion
|
||||||
await expect(slashSuggestionAutocomplete).not.toBeVisible();
|
await expect(slashSuggestionAutocomplete).not.toExist();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('MM-T4881_4 - should stop suggesting slash command after slash command name with trailing space', async () => {
|
it('MM-T4881_4 - should stop suggesting slash command after slash command name with trailing space', async () => {
|
||||||
|
|
@ -110,20 +110,20 @@ describe('Autocomplete - Slash Suggestion', () => {
|
||||||
await Autocomplete.toBeVisible();
|
await Autocomplete.toBeVisible();
|
||||||
|
|
||||||
// * Verify slash suggestion list is displayed
|
// * Verify slash suggestion list is displayed
|
||||||
await expect(Autocomplete.flatSlashSuggestionList).toBeVisible();
|
await expect(Autocomplete.flatSlashSuggestionList).toExist();
|
||||||
|
|
||||||
// # Type in slash command name
|
// # Type in slash command name
|
||||||
await ChannelScreen.postInput.typeText(slashCommand);
|
await ChannelScreen.postInput.typeText(slashCommand);
|
||||||
|
|
||||||
// * Verify slash suggestion autocomplete contains associated slash command suggestion
|
// * Verify slash suggestion autocomplete contains associated slash command suggestion
|
||||||
await expect(slashSuggestionAutocomplete).toBeVisible();
|
await expect(slashSuggestionAutocomplete).toExist();
|
||||||
|
|
||||||
// # Type in trailing space
|
// # Type in trailing space
|
||||||
await ChannelScreen.postInput.typeText(' ');
|
await ChannelScreen.postInput.typeText(' ');
|
||||||
await wait(timeouts.ONE_SEC);
|
await wait(timeouts.ONE_SEC);
|
||||||
|
|
||||||
// * Verify slash suggestion autocomplete does not contain associated slash command suggestion
|
// * Verify slash suggestion autocomplete does not contain associated slash command suggestion
|
||||||
await expect(slashSuggestionAutocomplete).not.toBeVisible();
|
await expect(slashSuggestionAutocomplete).not.toExist();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('MM-T4881_5 - should stop suggesting slash command when keyword is not associated with any slash command', async () => {
|
it('MM-T4881_5 - should stop suggesting slash command when keyword is not associated with any slash command', async () => {
|
||||||
|
|
@ -132,22 +132,22 @@ describe('Autocomplete - Slash Suggestion', () => {
|
||||||
await Autocomplete.toBeVisible();
|
await Autocomplete.toBeVisible();
|
||||||
|
|
||||||
// * Verify slash suggestion list is displayed
|
// * Verify slash suggestion list is displayed
|
||||||
await expect(Autocomplete.flatSlashSuggestionList).toBeVisible();
|
await expect(Autocomplete.flatSlashSuggestionList).toExist();
|
||||||
|
|
||||||
// # Type in keyword not associated with any slash command
|
// # Type in keyword not associated with any slash command
|
||||||
await ChannelScreen.postInput.typeText(getRandomId());
|
await ChannelScreen.postInput.typeText(getRandomId());
|
||||||
|
|
||||||
// * Verify slash suggestion autocomplete does not contain associated slash command suggestion
|
// * Verify slash suggestion autocomplete does not contain associated slash command suggestion
|
||||||
await expect(slashSuggestionAutocomplete).not.toBeVisible();
|
await expect(slashSuggestionAutocomplete).not.toExist();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('MM-T4881_6 - should not be able to select slash suggestion multiple times', async () => {
|
it('MM-T4881_6 - should not be able to select slash suggestion multiple times', async () => {
|
||||||
// # Type in "/" to activate slash suggestion autocomplete
|
// # Type in "/" to activate slash suggestion autocomplete
|
||||||
await expect(Autocomplete.flatSlashSuggestionList).not.toBeVisible();
|
await expect(Autocomplete.flatSlashSuggestionList).not.toExist();
|
||||||
await ChannelScreen.postInput.typeText('/');
|
await ChannelScreen.postInput.typeText('/');
|
||||||
|
|
||||||
// * Verify slash suggestion list is displayed
|
// * Verify slash suggestion list is displayed
|
||||||
await expect(Autocomplete.flatSlashSuggestionList).toBeVisible();
|
await expect(Autocomplete.flatSlashSuggestionList).toExist();
|
||||||
|
|
||||||
// # Type in slash command name and tap on slash suggestion autocomplete
|
// # Type in slash command name and tap on slash suggestion autocomplete
|
||||||
await ChannelScreen.postInput.typeText(slashCommand);
|
await ChannelScreen.postInput.typeText(slashCommand);
|
||||||
|
|
@ -160,6 +160,6 @@ describe('Autocomplete - Slash Suggestion', () => {
|
||||||
await ChannelScreen.postInput.typeText('/');
|
await ChannelScreen.postInput.typeText('/');
|
||||||
|
|
||||||
// * Verify slash suggestion list is not displayed
|
// * Verify slash suggestion list is not displayed
|
||||||
await expect(Autocomplete.flatSlashSuggestionList).not.toBeVisible();
|
await expect(Autocomplete.flatSlashSuggestionList).not.toExist();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,10 @@
|
||||||
// - Use element testID when selecting an element. Create one if none.
|
// - Use element testID when selecting an element. Create one if none.
|
||||||
// *******************************************************************
|
// *******************************************************************
|
||||||
|
|
||||||
import {Setup} from '@support/server_api';
|
import {
|
||||||
|
Post,
|
||||||
|
Setup,
|
||||||
|
} from '@support/server_api';
|
||||||
import {
|
import {
|
||||||
serverOneUrl,
|
serverOneUrl,
|
||||||
siteOneUrl,
|
siteOneUrl,
|
||||||
|
|
@ -21,15 +24,17 @@ import {
|
||||||
ServerScreen,
|
ServerScreen,
|
||||||
ThreadScreen,
|
ThreadScreen,
|
||||||
} from '@support/ui/screen';
|
} from '@support/ui/screen';
|
||||||
import {getRandomId} from '@support/utils';
|
import {getRandomId, timeouts, wait} from '@support/utils';
|
||||||
import {expect} from 'detox';
|
import {expect} from 'detox';
|
||||||
|
|
||||||
describe('Autocomplete - Thread Post Draft', () => {
|
describe('Autocomplete - Thread Post Draft', () => {
|
||||||
const serverOneDisplayName = 'Server 1';
|
const serverOneDisplayName = 'Server 1';
|
||||||
const channelsCategory = 'channels';
|
const channelsCategory = 'channels';
|
||||||
|
let testChannel: any;
|
||||||
|
|
||||||
beforeAll(async () => {
|
beforeAll(async () => {
|
||||||
const {channel, user} = await Setup.apiInit(siteOneUrl);
|
const {channel, user} = await Setup.apiInit(siteOneUrl);
|
||||||
|
testChannel = channel;
|
||||||
|
|
||||||
// # Log in to server
|
// # Log in to server
|
||||||
await ServerScreen.connectToServer(serverOneUrl, serverOneDisplayName);
|
await ServerScreen.connectToServer(serverOneUrl, serverOneDisplayName);
|
||||||
|
|
@ -38,11 +43,13 @@ describe('Autocomplete - Thread Post Draft', () => {
|
||||||
// * Verify on channel list screen
|
// * Verify on channel list screen
|
||||||
await ChannelListScreen.toBeVisible();
|
await ChannelListScreen.toBeVisible();
|
||||||
|
|
||||||
// # Open a channel screen, post a message, and tap on post to open reply thread
|
// # Open a channel screen, post a message, and open reply thread
|
||||||
const message = `Message ${getRandomId()}`;
|
const message = `Message ${getRandomId()}`;
|
||||||
await ChannelScreen.open(channelsCategory, channel.name);
|
await ChannelScreen.open(channelsCategory, testChannel.name);
|
||||||
await ChannelScreen.postMessage(message);
|
await ChannelScreen.postMessage(message);
|
||||||
await element(by.text(message)).tap();
|
const {post} = await Post.apiGetLastPostInChannel(siteOneUrl, testChannel.id);
|
||||||
|
await wait(timeouts.FOUR_SEC);
|
||||||
|
await ChannelScreen.openReplyThreadFor(post.id, message);
|
||||||
});
|
});
|
||||||
|
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
|
|
@ -54,6 +61,10 @@ describe('Autocomplete - Thread Post Draft', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
afterAll(async () => {
|
afterAll(async () => {
|
||||||
|
// # Tap on thread screen to dismiss keyboard
|
||||||
|
await ThreadScreen.threadScreen.tap();
|
||||||
|
await wait(timeouts.ONE_SEC);
|
||||||
|
|
||||||
// # Log out
|
// # Log out
|
||||||
await ThreadScreen.back();
|
await ThreadScreen.back();
|
||||||
await ChannelScreen.back();
|
await ChannelScreen.back();
|
||||||
|
|
@ -62,45 +73,49 @@ describe('Autocomplete - Thread Post Draft', () => {
|
||||||
|
|
||||||
it('MM-T4905_1 - should render at-mention autocomplete in post input', async () => {
|
it('MM-T4905_1 - should render at-mention autocomplete in post input', async () => {
|
||||||
// * Verify at-mention list is not displayed
|
// * Verify at-mention list is not displayed
|
||||||
await expect(Autocomplete.sectionAtMentionList).not.toBeVisible();
|
await expect(Autocomplete.sectionAtMentionList).not.toExist();
|
||||||
|
|
||||||
// # Type in "@" to activate at-mention autocomplete
|
// # Type in "@" to activate at-mention autocomplete
|
||||||
await ThreadScreen.postInput.typeText('@');
|
await ThreadScreen.postInput.typeText('@');
|
||||||
|
await wait(timeouts.TWO_SEC);
|
||||||
|
|
||||||
// * Verify at-mention list is displayed
|
// * Verify at-mention list is displayed
|
||||||
await expect(Autocomplete.sectionAtMentionList).toBeVisible();
|
await expect(Autocomplete.sectionAtMentionList).toExist();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('MM-T4905_2 - should render channel mention autocomplete in post input', async () => {
|
it('MM-T4905_2 - should render channel mention autocomplete in post input', async () => {
|
||||||
// * Verify channel mention list is not displayed
|
// * Verify channel mention list is not displayed
|
||||||
await expect(Autocomplete.sectionChannelMentionList).not.toBeVisible();
|
await expect(Autocomplete.sectionChannelMentionList).not.toExist();
|
||||||
|
|
||||||
// # Type in "~" to activate channel mention autocomplete
|
// # Type in "~" to activate channel mention autocomplete
|
||||||
await ThreadScreen.postInput.typeText('~');
|
await ThreadScreen.postInput.typeText('~');
|
||||||
|
await wait(timeouts.TWO_SEC);
|
||||||
|
|
||||||
// * Verify channel mention list is displayed
|
// * Verify channel mention list is displayed
|
||||||
await expect(Autocomplete.sectionChannelMentionList).toBeVisible();
|
await expect(Autocomplete.sectionChannelMentionList).toExist();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('MM-T4905_3 - should render emoji suggestion autocomplete in post input', async () => {
|
it('MM-T4905_3 - should render emoji suggestion autocomplete in post input', async () => {
|
||||||
// * Verify emoji suggestion list is not displayed
|
// * Verify emoji suggestion list is not displayed
|
||||||
await expect(Autocomplete.flatEmojiSuggestionList).not.toBeVisible();
|
await expect(Autocomplete.flatEmojiSuggestionList).not.toExist();
|
||||||
|
|
||||||
// # Type in ":" followed by 2 characters to activate emoji suggestion autocomplete
|
// # Type in ":" followed by 2 characters to activate emoji suggestion autocomplete
|
||||||
await ThreadScreen.postInput.typeText(':sm');
|
await ThreadScreen.postInput.typeText(':sm');
|
||||||
|
await wait(timeouts.TWO_SEC);
|
||||||
|
|
||||||
// * Verify emoji suggestion list is displayed
|
// * Verify emoji suggestion list is displayed
|
||||||
await expect(Autocomplete.flatEmojiSuggestionList).toBeVisible();
|
await expect(Autocomplete.flatEmojiSuggestionList).toExist();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('MM-T4905_4 - should render slash suggestion autocomplete in post input', async () => {
|
it('MM-T4905_4 - should render slash suggestion autocomplete in post input', async () => {
|
||||||
// * Verify slash suggestion list is not displayed
|
// * Verify slash suggestion list is not displayed
|
||||||
await expect(Autocomplete.flatSlashSuggestionList).not.toBeVisible();
|
await expect(Autocomplete.flatSlashSuggestionList).not.toExist();
|
||||||
|
|
||||||
// # Type in "/" to activate slash suggestion autocomplete
|
// # Type in "/" to activate slash suggestion autocomplete
|
||||||
await ThreadScreen.postInput.typeText('/');
|
await ThreadScreen.postInput.typeText('/');
|
||||||
|
await wait(timeouts.TWO_SEC);
|
||||||
|
|
||||||
// * Verify slash suggestion list is displayed
|
// * Verify slash suggestion list is displayed
|
||||||
await expect(Autocomplete.flatSlashSuggestionList).toBeVisible();
|
await expect(Autocomplete.flatSlashSuggestionList).toExist();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -32,10 +32,10 @@ import {expect} from 'detox';
|
||||||
|
|
||||||
describe('Channels - Channel List', () => {
|
describe('Channels - Channel List', () => {
|
||||||
const serverOneDisplayName = 'Server 1';
|
const serverOneDisplayName = 'Server 1';
|
||||||
const channelsCategory = 'channels';
|
|
||||||
const directMessagesCategory = 'direct_messages';
|
const directMessagesCategory = 'direct_messages';
|
||||||
const offTopicChannelName = 'off-topic';
|
const offTopicChannelName = 'off-topic';
|
||||||
const townSquareChannelName = 'town-square';
|
const townSquareChannelName = 'town-square';
|
||||||
|
const channelsCategory = 'channels';
|
||||||
let testChannel: any;
|
let testChannel: any;
|
||||||
let testTeam: any;
|
let testTeam: any;
|
||||||
let testUser: any;
|
let testUser: any;
|
||||||
|
|
|
||||||
|
|
@ -23,8 +23,8 @@ import {
|
||||||
PostOptionsScreen,
|
PostOptionsScreen,
|
||||||
ServerScreen,
|
ServerScreen,
|
||||||
} from '@support/ui/screen';
|
} from '@support/ui/screen';
|
||||||
import {getRandomId, isAndroid} from '@support/utils';
|
import {getRandomId, timeouts} from '@support/utils';
|
||||||
import {expect} from 'detox';
|
import {expect, waitFor} from 'detox';
|
||||||
|
|
||||||
describe('Channels - Channel Post List', () => {
|
describe('Channels - Channel Post List', () => {
|
||||||
const serverOneDisplayName = 'Server 1';
|
const serverOneDisplayName = 'Server 1';
|
||||||
|
|
@ -52,26 +52,37 @@ describe('Channels - Channel Post List', () => {
|
||||||
it('MM-T4773_1 - should match elements on channel screen', async () => {
|
it('MM-T4773_1 - should match elements on channel screen', async () => {
|
||||||
// # Open a channel screen
|
// # Open a channel screen
|
||||||
await ChannelScreen.open('channels', testChannel.name);
|
await ChannelScreen.open('channels', testChannel.name);
|
||||||
if (isAndroid()) {
|
|
||||||
await ChannelScreen.back();
|
|
||||||
await ChannelScreen.open('channels', testChannel.name);
|
|
||||||
}
|
|
||||||
|
|
||||||
// * Verify basic elements on channel screen
|
// * Verify basic elements on channel screen
|
||||||
await expect(ChannelScreen.backButton).toBeVisible();
|
await expect(ChannelScreen.backButton).toExist();
|
||||||
await expect(ChannelScreen.headerTitle).toHaveText(testChannel.display_name);
|
await expect(ChannelScreen.headerTitle).toHaveText(testChannel.display_name);
|
||||||
|
await waitFor(ChannelScreen.introDisplayName).toExist().withTimeout(timeouts.TWO_SEC);
|
||||||
await expect(ChannelScreen.introDisplayName).toHaveText(testChannel.display_name);
|
await expect(ChannelScreen.introDisplayName).toHaveText(testChannel.display_name);
|
||||||
await expect(ChannelScreen.introSetHeaderAction).toBeVisible();
|
await expect(ChannelScreen.introSetHeaderAction).toExist();
|
||||||
await expect(ChannelScreen.introChannelInfoAction).toBeVisible();
|
await expect(ChannelScreen.introChannelInfoAction).toExist();
|
||||||
await expect(ChannelScreen.postList.getFlatList()).toBeVisible();
|
await expect(ChannelScreen.postList.getFlatList()).toExist();
|
||||||
await expect(ChannelScreen.postDraft).toBeVisible();
|
await expect(ChannelScreen.postDraft).toExist();
|
||||||
await expect(ChannelScreen.postInput).toBeVisible();
|
await expect(ChannelScreen.postInput).toExist();
|
||||||
await expect(ChannelScreen.atInputQuickAction).toBeVisible();
|
await expect(ChannelScreen.atInputQuickAction).toExist();
|
||||||
await expect(ChannelScreen.slashInputQuickAction).toBeVisible();
|
await expect(ChannelScreen.slashInputQuickAction).toExist();
|
||||||
await expect(ChannelScreen.fileQuickAction).toBeVisible();
|
|
||||||
await expect(ChannelScreen.imageQuickAction).toBeVisible();
|
// # Tap on attachment action to open file attachment options
|
||||||
await expect(ChannelScreen.cameraQuickAction).toBeVisible();
|
const attachmentAction = element(by.id('channel.post_draft.quick_actions.attachment_action'));
|
||||||
await expect(ChannelScreen.sendButtonDisabled).toBeVisible();
|
await expect(attachmentAction).toExist();
|
||||||
|
await attachmentAction.tap();
|
||||||
|
|
||||||
|
// * Verify file attachment options screen and its options
|
||||||
|
const attachmentScreen = element(by.id('channel.post_draft.quick_actions.attachment_action.screen'));
|
||||||
|
await expect(attachmentScreen).toExist();
|
||||||
|
await expect(element(by.id('file_attachment.photo_library'))).toExist();
|
||||||
|
await expect(element(by.id('file_attachment.take_photo'))).toExist();
|
||||||
|
await expect(element(by.id('file_attachment.take_video'))).toExist();
|
||||||
|
await expect(element(by.id('file_attachment.attach_file'))).toExist();
|
||||||
|
|
||||||
|
// # Close attachment options by swiping down (works on both iOS and Android)
|
||||||
|
await attachmentScreen.swipe('down', 'fast', 0.5);
|
||||||
|
|
||||||
|
await expect(ChannelScreen.sendButtonDisabled).toExist();
|
||||||
|
|
||||||
// # Go back to channel list screen
|
// # Go back to channel list screen
|
||||||
await ChannelScreen.back();
|
await ChannelScreen.back();
|
||||||
|
|
@ -81,16 +92,13 @@ describe('Channels - Channel Post List', () => {
|
||||||
// # Open a channel screen and post a message
|
// # Open a channel screen and post a message
|
||||||
const message = `Message ${getRandomId()}`;
|
const message = `Message ${getRandomId()}`;
|
||||||
await ChannelScreen.open('channels', testChannel.name);
|
await ChannelScreen.open('channels', testChannel.name);
|
||||||
if (isAndroid()) {
|
|
||||||
await ChannelScreen.back();
|
|
||||||
await ChannelScreen.open('channels', testChannel.name);
|
|
||||||
}
|
|
||||||
await ChannelScreen.postMessage(message);
|
await ChannelScreen.postMessage(message);
|
||||||
|
await ChannelScreen.dismissKeyboard();
|
||||||
|
|
||||||
// * Verify message is added to post list
|
// * Verify message is added to post list
|
||||||
const {post} = await Post.apiGetLastPostInChannel(siteOneUrl, testChannel.id);
|
const {post} = await Post.apiGetLastPostInChannel(siteOneUrl, testChannel.id);
|
||||||
const {postListPostItem} = ChannelScreen.getPostListPostItem(post.id, message);
|
const {postListPostItem} = ChannelScreen.getPostListPostItem(post.id, message);
|
||||||
await expect(postListPostItem).toBeVisible();
|
await waitFor(postListPostItem).toBeVisible().withTimeout(timeouts.TEN_SEC);
|
||||||
|
|
||||||
// # Open post options for the message that was just posted, tap delete option and confirm
|
// # Open post options for the message that was just posted, tap delete option and confirm
|
||||||
await ChannelScreen.openPostOptionsFor(post.id, message);
|
await ChannelScreen.openPostOptionsFor(post.id, message);
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,7 @@ import {
|
||||||
LoginScreen,
|
LoginScreen,
|
||||||
ServerScreen,
|
ServerScreen,
|
||||||
} from '@support/ui/screen';
|
} from '@support/ui/screen';
|
||||||
import {getRandomId, isIos, timeouts} from '@support/utils';
|
import {getRandomId, isIos, timeouts, wait} from '@support/utils';
|
||||||
import {expect} from 'detox';
|
import {expect} from 'detox';
|
||||||
|
|
||||||
describe('Channels - Create Channel and Edit Channel Header', () => {
|
describe('Channels - Create Channel and Edit Channel Header', () => {
|
||||||
|
|
@ -75,7 +75,7 @@ describe('Channels - Create Channel and Edit Channel Header', () => {
|
||||||
await CreateOrEditChannelScreen.purposeInput.replaceText(purpose);
|
await CreateOrEditChannelScreen.purposeInput.replaceText(purpose);
|
||||||
await CreateOrEditChannelScreen.headerInput.replaceText(header);
|
await CreateOrEditChannelScreen.headerInput.replaceText(header);
|
||||||
await CreateOrEditChannelScreen.createButton.tap();
|
await CreateOrEditChannelScreen.createButton.tap();
|
||||||
await waitFor(ChannelScreen.scheduledPostTooltipCloseButton).toBeVisible().withTimeout(timeouts.FOUR_SEC);
|
await waitFor(ChannelScreen.scheduledPostTooltipCloseButton).toExist().withTimeout(timeouts.FOUR_SEC);
|
||||||
await ChannelScreen.scheduledPostTooltipCloseButton.tap();
|
await ChannelScreen.scheduledPostTooltipCloseButton.tap();
|
||||||
|
|
||||||
// * Verify on newly created public channel
|
// * Verify on newly created public channel
|
||||||
|
|
@ -96,6 +96,7 @@ describe('Channels - Create Channel and Edit Channel Header', () => {
|
||||||
// # Edit the channel header, save, and re-open edit channel header screen
|
// # Edit the channel header, save, and re-open edit channel header screen
|
||||||
await CreateOrEditChannelScreen.headerInput.replaceText(`${header} edit`);
|
await CreateOrEditChannelScreen.headerInput.replaceText(`${header} edit`);
|
||||||
await CreateOrEditChannelScreen.saveButton.tap();
|
await CreateOrEditChannelScreen.saveButton.tap();
|
||||||
|
await wait(timeouts.TWO_SEC);
|
||||||
await CreateOrEditChannelScreen.openEditChannelHeader();
|
await CreateOrEditChannelScreen.openEditChannelHeader();
|
||||||
|
|
||||||
// * Verify channel header has new value
|
// * Verify channel header has new value
|
||||||
|
|
@ -141,6 +142,7 @@ describe('Channels - Create Channel and Edit Channel Header', () => {
|
||||||
// # Edit the channel header, save, and re-open edit channel header screen
|
// # Edit the channel header, save, and re-open edit channel header screen
|
||||||
await CreateOrEditChannelScreen.headerInput.replaceText(`${header} edit`);
|
await CreateOrEditChannelScreen.headerInput.replaceText(`${header} edit`);
|
||||||
await CreateOrEditChannelScreen.saveButton.tap();
|
await CreateOrEditChannelScreen.saveButton.tap();
|
||||||
|
await wait(timeouts.TWO_SEC);
|
||||||
await CreateOrEditChannelScreen.openEditChannelHeader();
|
await CreateOrEditChannelScreen.openEditChannelHeader();
|
||||||
|
|
||||||
// * Verify channel header has new value
|
// * Verify channel header has new value
|
||||||
|
|
|
||||||
|
|
@ -132,6 +132,7 @@ describe('Channels - Favorite and Unfavorite Channel', () => {
|
||||||
await ChannelScreen.postMessage('test');
|
await ChannelScreen.postMessage('test');
|
||||||
await ChannelScreen.back();
|
await ChannelScreen.back();
|
||||||
await ChannelListScreen.getChannelItemDisplayName(directMessagesCategory, directMessageChannel.name).tap();
|
await ChannelListScreen.getChannelItemDisplayName(directMessagesCategory, directMessageChannel.name).tap();
|
||||||
|
await waitFor(ChannelScreen.introFavoriteAction).toBeVisible().withTimeout(timeouts.TEN_SEC);
|
||||||
await ChannelScreen.introFavoriteAction.tap();
|
await ChannelScreen.introFavoriteAction.tap();
|
||||||
await ChannelScreen.back();
|
await ChannelScreen.back();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -144,17 +144,24 @@ describe('Channels - Find Channels', () => {
|
||||||
await FindChannelsScreen.open();
|
await FindChannelsScreen.open();
|
||||||
await FindChannelsScreen.searchInput.typeText(archivedChannel.display_name);
|
await FindChannelsScreen.searchInput.typeText(archivedChannel.display_name);
|
||||||
|
|
||||||
// * Verify search returns the target archived channel item
|
// * Verify search returns the target archived channel item and tap on it
|
||||||
await wait(timeouts.FOUR_SEC);
|
// Archived channels may appear as regular channel items in search results
|
||||||
await FindChannelsScreen.getFilteredChannelItem(archivedChannel.name).tap();
|
|
||||||
await wait(timeouts.FOUR_SEC);
|
await wait(timeouts.FOUR_SEC);
|
||||||
|
try {
|
||||||
|
await waitFor(FindChannelsScreen.getFilteredArchivedChannelItem(archivedChannel.name)).toExist().withTimeout(timeouts.TWO_SEC);
|
||||||
|
await FindChannelsScreen.getFilteredArchivedChannelItem(archivedChannel.name).tap();
|
||||||
|
} catch (error) {
|
||||||
|
// If not found with archived prefix, try regular channel item
|
||||||
|
await waitFor(FindChannelsScreen.getFilteredChannelItem(archivedChannel.name)).toExist().withTimeout(timeouts.TWO_SEC);
|
||||||
|
await FindChannelsScreen.getFilteredChannelItem(archivedChannel.name).tap();
|
||||||
|
}
|
||||||
|
await wait(timeouts.TWO_SEC);
|
||||||
|
|
||||||
// * Verify on archievd channel name
|
// * Verify on archievd channel name
|
||||||
await verifyDetailsOnChannelScreen(archivedChannel.display_name);
|
await verifyDetailsOnChannelScreen(archivedChannel.display_name);
|
||||||
|
|
||||||
// # Go back to channel list screen by closing archived channel
|
// # Go back to channel list screen
|
||||||
await expect(ChannelScreen.archievedCloseChannelButton).toBeVisible();
|
await ChannelScreen.back();
|
||||||
await ChannelScreen.archievedCloseChannelButton.tap();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('MM-T4907_6 - should be able to find a joined private channel and not find an unjoined private channel', async () => {
|
it('MM-T4907_6 - should be able to find a joined private channel and not find an unjoined private channel', async () => {
|
||||||
|
|
@ -182,12 +189,15 @@ describe('Channels - Find Channels', () => {
|
||||||
|
|
||||||
async function verifyDetailsOnChannelScreen(display_name: string) {
|
async function verifyDetailsOnChannelScreen(display_name: string) {
|
||||||
await wait(timeouts.TWO_SEC);
|
await wait(timeouts.TWO_SEC);
|
||||||
|
|
||||||
|
// Try to close scheduled post tooltip if it exists
|
||||||
try {
|
try {
|
||||||
|
await waitFor(ChannelScreen.scheduledPostTooltipCloseButton).toBeVisible().withTimeout(timeouts.ONE_SEC);
|
||||||
await ChannelScreen.scheduledPostTooltipCloseButton.tap();
|
await ChannelScreen.scheduledPostTooltipCloseButton.tap();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
// eslint-disable-next-line no-console
|
// Tooltip not visible, continue
|
||||||
console.log('Element not visible, skipping click');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
await ChannelScreen.toBeVisible();
|
await ChannelScreen.toBeVisible();
|
||||||
await expect(ChannelScreen.headerTitle).toHaveText(display_name);
|
await expect(ChannelScreen.headerTitle).toHaveText(display_name);
|
||||||
await expect(ChannelScreen.introDisplayName).toHaveText(display_name);
|
await expect(ChannelScreen.introDisplayName).toHaveText(display_name);
|
||||||
|
|
|
||||||
|
|
@ -23,8 +23,9 @@ import {
|
||||||
LoginScreen,
|
LoginScreen,
|
||||||
ServerScreen,
|
ServerScreen,
|
||||||
} from '@support/ui/screen';
|
} from '@support/ui/screen';
|
||||||
|
import channelScreen from '@support/ui/screen/channel';
|
||||||
import {timeouts, wait} from '@support/utils';
|
import {timeouts, wait} from '@support/utils';
|
||||||
import {expect} from 'detox';
|
import {expect, waitFor} from 'detox';
|
||||||
|
|
||||||
describe('Messaging - Channel Link', () => {
|
describe('Messaging - Channel Link', () => {
|
||||||
const serverOneDisplayName = 'Server 1';
|
const serverOneDisplayName = 'Server 1';
|
||||||
|
|
@ -61,10 +62,11 @@ describe('Messaging - Channel Link', () => {
|
||||||
await Channel.apiAddUserToChannel(siteOneUrl, testUser.id, targetChannel.id);
|
await Channel.apiAddUserToChannel(siteOneUrl, testUser.id, targetChannel.id);
|
||||||
const channelLink = `${serverOneUrl}/${testTeam.name}/channels/${targetChannel.name}`;
|
const channelLink = `${serverOneUrl}/${testTeam.name}/channels/${targetChannel.name}`;
|
||||||
await ChannelScreen.postMessage(channelLink);
|
await ChannelScreen.postMessage(channelLink);
|
||||||
|
await channelScreen.dismissKeyboard();
|
||||||
|
|
||||||
// # Tap on channel link
|
// # Tap on channel link
|
||||||
await element(by.text(channelLink)).tap({x: 5, y: 10});
|
await element(by.text(channelLink)).tap();
|
||||||
await wait(timeouts.ONE_SEC);
|
await wait(timeouts.FOUR_SEC);
|
||||||
|
|
||||||
// * Verify redirected to target channel
|
// * Verify redirected to target channel
|
||||||
await expect(ChannelScreen.headerTitle).toHaveText(targetChannel.display_name);
|
await expect(ChannelScreen.headerTitle).toHaveText(targetChannel.display_name);
|
||||||
|
|
@ -80,8 +82,15 @@ describe('Messaging - Channel Link', () => {
|
||||||
await Channel.apiAddUserToChannel(siteOneUrl, testUser.id, targetChannel.id);
|
await Channel.apiAddUserToChannel(siteOneUrl, testUser.id, targetChannel.id);
|
||||||
const channelLink = `${serverOneUrl}/${testTeam.name}/channels/${targetChannel.name}`;
|
const channelLink = `${serverOneUrl}/${testTeam.name}/channels/${targetChannel.name}`;
|
||||||
await ChannelScreen.postMessage(channelLink);
|
await ChannelScreen.postMessage(channelLink);
|
||||||
|
await channelScreen.dismissKeyboard();
|
||||||
|
|
||||||
|
// # Wait for keyboard to dismiss and message to be visible
|
||||||
|
await wait(timeouts.TWO_SEC);
|
||||||
|
|
||||||
const {post} = await Post.apiGetLastPostInChannel(siteOneUrl, testChannel.id);
|
const {post} = await Post.apiGetLastPostInChannel(siteOneUrl, testChannel.id);
|
||||||
const {postListPostItem} = ChannelScreen.getPostListPostItem(post.id);
|
const {postListPostItem} = ChannelScreen.getPostListPostItem(post.id);
|
||||||
|
await waitFor(postListPostItem).toBeVisible().withTimeout(timeouts.FOUR_SEC);
|
||||||
|
|
||||||
await postListPostItem.tap({x: 1, y: 1});
|
await postListPostItem.tap({x: 1, y: 1});
|
||||||
await element(by.text(channelLink)).tap({x: 5, y: 10});
|
await element(by.text(channelLink)).tap({x: 5, y: 10});
|
||||||
await wait(timeouts.ONE_SEC);
|
await wait(timeouts.ONE_SEC);
|
||||||
|
|
|
||||||
|
|
@ -26,8 +26,8 @@ import {
|
||||||
ServerScreen,
|
ServerScreen,
|
||||||
UserProfileScreen,
|
UserProfileScreen,
|
||||||
} from '@support/ui/screen';
|
} from '@support/ui/screen';
|
||||||
import {getRandomId} from '@support/utils';
|
import {getRandomId, timeouts} from '@support/utils';
|
||||||
import {expect} from 'detox';
|
import {expect, waitFor} from 'detox';
|
||||||
|
|
||||||
describe('Messaging - Emojis and Reactions', () => {
|
describe('Messaging - Emojis and Reactions', () => {
|
||||||
const serverOneDisplayName = 'Server 1';
|
const serverOneDisplayName = 'Server 1';
|
||||||
|
|
@ -60,6 +60,7 @@ describe('Messaging - Emojis and Reactions', () => {
|
||||||
const message = `Message ${getRandomId()}`;
|
const message = `Message ${getRandomId()}`;
|
||||||
await ChannelScreen.open(channelsCategory, testChannel.name);
|
await ChannelScreen.open(channelsCategory, testChannel.name);
|
||||||
await ChannelScreen.postMessage(message);
|
await ChannelScreen.postMessage(message);
|
||||||
|
await ChannelScreen.dismissKeyboard();
|
||||||
const {post} = await Post.apiGetLastPostInChannel(siteOneUrl, testChannel.id);
|
const {post} = await Post.apiGetLastPostInChannel(siteOneUrl, testChannel.id);
|
||||||
await ChannelScreen.openPostOptionsFor(post.id, message);
|
await ChannelScreen.openPostOptionsFor(post.id, message);
|
||||||
|
|
||||||
|
|
@ -74,10 +75,13 @@ describe('Messaging - Emojis and Reactions', () => {
|
||||||
// # Open emoji picker screen and add a new reaction
|
// # Open emoji picker screen and add a new reaction
|
||||||
await EmojiPickerScreen.open(true);
|
await EmojiPickerScreen.open(true);
|
||||||
await EmojiPickerScreen.searchInput.replaceText('clown_face');
|
await EmojiPickerScreen.searchInput.replaceText('clown_face');
|
||||||
|
await EmojiPickerScreen.searchInput.tapReturnKey();
|
||||||
await element(by.text('🤡')).tap();
|
await element(by.text('🤡')).tap();
|
||||||
|
|
||||||
// * Verify new reaction is added to the message
|
// * Verify new reaction is added to the message
|
||||||
await expect(element(by.text('🤡').withAncestor(by.id(`channel.post_list.post.${post.id}`)))).toBeVisible();
|
const reactionElement = element(by.text('🤡').withAncestor(by.id(`channel.post_list.post.${post.id}`)));
|
||||||
|
await waitFor(reactionElement).toExist().withTimeout(timeouts.TWO_SEC);
|
||||||
|
await expect(reactionElement).toExist();
|
||||||
|
|
||||||
// # Open post options for message
|
// # Open post options for message
|
||||||
await ChannelScreen.openPostOptionsFor(post.id, message);
|
await ChannelScreen.openPostOptionsFor(post.id, message);
|
||||||
|
|
@ -101,15 +105,18 @@ describe('Messaging - Emojis and Reactions', () => {
|
||||||
const message = `Message ${getRandomId()}`;
|
const message = `Message ${getRandomId()}`;
|
||||||
await ChannelScreen.open(channelsCategory, testChannel.name);
|
await ChannelScreen.open(channelsCategory, testChannel.name);
|
||||||
await ChannelScreen.postMessage(message);
|
await ChannelScreen.postMessage(message);
|
||||||
|
await ChannelScreen.dismissKeyboard();
|
||||||
const {post} = await Post.apiGetLastPostInChannel(siteOneUrl, testChannel.id);
|
const {post} = await Post.apiGetLastPostInChannel(siteOneUrl, testChannel.id);
|
||||||
await ChannelScreen.openPostOptionsFor(post.id, message);
|
await ChannelScreen.openPostOptionsFor(post.id, message);
|
||||||
await EmojiPickerScreen.open();
|
await EmojiPickerScreen.open();
|
||||||
await EmojiPickerScreen.searchInput.replaceText('fire');
|
await EmojiPickerScreen.searchInput.replaceText('fire');
|
||||||
|
await EmojiPickerScreen.searchInput.tapReturnKey();
|
||||||
await element(by.text('🔥')).tap();
|
await element(by.text('🔥')).tap();
|
||||||
|
|
||||||
// * Verify reaction is added to the message
|
// * Verify reaction is added to the message
|
||||||
const reaction = element(by.text('🔥').withAncestor(by.id(`channel.post_list.post.${post.id}`)));
|
const reaction = element(by.text('🔥').withAncestor(by.id(`channel.post_list.post.${post.id}`)));
|
||||||
await expect(reaction).toBeVisible();
|
await waitFor(reaction).toExist().withTimeout(timeouts.TWO_SEC);
|
||||||
|
await expect(reaction).toExist();
|
||||||
|
|
||||||
// # Long press on the reaction
|
// # Long press on the reaction
|
||||||
await reaction.longPress();
|
await reaction.longPress();
|
||||||
|
|
@ -133,6 +140,7 @@ describe('Messaging - Emojis and Reactions', () => {
|
||||||
const message = 'brown fox :fox_face: lazy dog :dog:';
|
const message = 'brown fox :fox_face: lazy dog :dog:';
|
||||||
await ChannelScreen.open(channelsCategory, testChannel.name);
|
await ChannelScreen.open(channelsCategory, testChannel.name);
|
||||||
await ChannelScreen.postMessage(message);
|
await ChannelScreen.postMessage(message);
|
||||||
|
await ChannelScreen.dismissKeyboard();
|
||||||
|
|
||||||
// * Verify message is posted with emojis
|
// * Verify message is posted with emojis
|
||||||
const resolvedMessage = 'brown fox 🦊 lazy dog 🐶';
|
const resolvedMessage = 'brown fox 🦊 lazy dog 🐶';
|
||||||
|
|
@ -166,11 +174,13 @@ describe('Messaging - Emojis and Reactions', () => {
|
||||||
const message = `Message ${getRandomId()}`;
|
const message = `Message ${getRandomId()}`;
|
||||||
await ChannelScreen.open(channelsCategory, testChannel.name);
|
await ChannelScreen.open(channelsCategory, testChannel.name);
|
||||||
await ChannelScreen.postMessage(message);
|
await ChannelScreen.postMessage(message);
|
||||||
|
await ChannelScreen.dismissKeyboard();
|
||||||
const {post} = await Post.apiGetLastPostInChannel(siteOneUrl, testChannel.id);
|
const {post} = await Post.apiGetLastPostInChannel(siteOneUrl, testChannel.id);
|
||||||
const searchTerm = 'blahblahblahblah';
|
const searchTerm = 'blahblahblahblah';
|
||||||
await ChannelScreen.openPostOptionsFor(post.id, message);
|
await ChannelScreen.openPostOptionsFor(post.id, message);
|
||||||
await EmojiPickerScreen.open();
|
await EmojiPickerScreen.open();
|
||||||
await EmojiPickerScreen.searchInput.replaceText(searchTerm);
|
await EmojiPickerScreen.searchInput.replaceText(searchTerm);
|
||||||
|
await EmojiPickerScreen.searchInput.tapReturnKey();
|
||||||
|
|
||||||
// * Verify empty search state for emoji picker
|
// * Verify empty search state for emoji picker
|
||||||
await expect(element(by.text(`No matches found for “${searchTerm}”`))).toBeVisible();
|
await expect(element(by.text(`No matches found for “${searchTerm}”`))).toBeVisible();
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@
|
||||||
|
|
||||||
import {
|
import {
|
||||||
Post,
|
Post,
|
||||||
|
Preference,
|
||||||
Setup,
|
Setup,
|
||||||
} from '@support/server_api';
|
} from '@support/server_api';
|
||||||
import {
|
import {
|
||||||
|
|
@ -23,8 +24,8 @@ import {
|
||||||
PostOptionsScreen,
|
PostOptionsScreen,
|
||||||
ServerScreen,
|
ServerScreen,
|
||||||
} from '@support/ui/screen';
|
} from '@support/ui/screen';
|
||||||
import {getRandomId, timeouts, wait} from '@support/utils';
|
import {getRandomId, timeouts, wait, waitForElementToBeVisible} from '@support/utils';
|
||||||
import {expect} from 'detox';
|
import {waitFor} from 'detox';
|
||||||
|
|
||||||
describe('Messaging - Follow and Unfollow Message', () => {
|
describe('Messaging - Follow and Unfollow Message', () => {
|
||||||
const serverOneDisplayName = 'Server 1';
|
const serverOneDisplayName = 'Server 1';
|
||||||
|
|
@ -35,6 +36,16 @@ describe('Messaging - Follow and Unfollow Message', () => {
|
||||||
const {channel, user} = await Setup.apiInit(siteOneUrl);
|
const {channel, user} = await Setup.apiInit(siteOneUrl);
|
||||||
testChannel = channel;
|
testChannel = channel;
|
||||||
|
|
||||||
|
// # Enable CRT (Collapsed Reply Threads) for the user
|
||||||
|
await Preference.apiSaveUserPreferences(siteOneUrl, user.id, [
|
||||||
|
{
|
||||||
|
user_id: user.id,
|
||||||
|
category: 'display_settings',
|
||||||
|
name: 'collapsed_reply_threads',
|
||||||
|
value: 'on',
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
|
||||||
// # Log in to server
|
// # Log in to server
|
||||||
await ServerScreen.connectToServer(serverOneUrl, serverOneDisplayName);
|
await ServerScreen.connectToServer(serverOneUrl, serverOneDisplayName);
|
||||||
await LoginScreen.login(user);
|
await LoginScreen.login(user);
|
||||||
|
|
@ -55,19 +66,27 @@ describe('Messaging - Follow and Unfollow Message', () => {
|
||||||
const message = `Message ${getRandomId()}`;
|
const message = `Message ${getRandomId()}`;
|
||||||
await ChannelScreen.open(channelsCategory, testChannel.name);
|
await ChannelScreen.open(channelsCategory, testChannel.name);
|
||||||
await ChannelScreen.postMessage(message);
|
await ChannelScreen.postMessage(message);
|
||||||
|
await ChannelScreen.dismissKeyboard();
|
||||||
|
|
||||||
|
// # Wait for keyboard to dismiss and message to be visible
|
||||||
|
await wait(timeouts.ONE_SEC);
|
||||||
|
|
||||||
// * Verify message is posted
|
// * Verify message is posted
|
||||||
const {post} = await Post.apiGetLastPostInChannel(siteOneUrl, testChannel.id);
|
const {post} = await Post.apiGetLastPostInChannel(siteOneUrl, testChannel.id);
|
||||||
const {postListPostItem} = ChannelScreen.getPostListPostItem(post.id, message);
|
const {postListPostItem} = ChannelScreen.getPostListPostItem(post.id, message);
|
||||||
await expect(postListPostItem).toBeVisible();
|
await waitFor(postListPostItem).toBeVisible().withTimeout(timeouts.FOUR_SEC);
|
||||||
|
|
||||||
|
// # Wait for thread to be created in DB (CRT creates threads asynchronously)
|
||||||
|
await wait(timeouts.TWO_SEC);
|
||||||
|
|
||||||
// # Open post options for message and tap on follow message option
|
// # Open post options for message and tap on follow message option
|
||||||
await postListPostItem.longPress(timeouts.ONE_SEC);
|
await postListPostItem.longPress(timeouts.FOUR_SEC);
|
||||||
|
await waitFor(PostOptionsScreen.followThreadOption).toBeVisible().withTimeout(timeouts.FOUR_SEC);
|
||||||
await PostOptionsScreen.followThreadOption.tap();
|
await PostOptionsScreen.followThreadOption.tap();
|
||||||
|
|
||||||
// * Verify message is followed by user via post footer
|
// * Verify message is followed by user via post footer
|
||||||
const {postListPostItemFooterFollowingButton} = ChannelScreen.getPostListPostItem(post.id, message);
|
const {postListPostItemFooterFollowingButton} = ChannelScreen.getPostListPostItem(post.id, message);
|
||||||
await waitFor(postListPostItemFooterFollowingButton).toBeVisible().withTimeout(timeouts.TEN_SEC);
|
await waitForElementToBeVisible(postListPostItemFooterFollowingButton);
|
||||||
|
|
||||||
// # Open post options for message and tap on unfollow message option
|
// # Open post options for message and tap on unfollow message option
|
||||||
await ChannelScreen.openPostOptionsFor(post.id, message);
|
await ChannelScreen.openPostOptionsFor(post.id, message);
|
||||||
|
|
@ -87,8 +106,17 @@ describe('Messaging - Follow and Unfollow Message', () => {
|
||||||
const message = `Message ${getRandomId()}`;
|
const message = `Message ${getRandomId()}`;
|
||||||
await ChannelScreen.open(channelsCategory, testChannel.name);
|
await ChannelScreen.open(channelsCategory, testChannel.name);
|
||||||
await ChannelScreen.postMessage(message);
|
await ChannelScreen.postMessage(message);
|
||||||
|
await ChannelScreen.dismissKeyboard();
|
||||||
|
|
||||||
|
// # Wait for keyboard to dismiss and message to be visible
|
||||||
|
await wait(timeouts.ONE_SEC);
|
||||||
|
|
||||||
const {post} = await Post.apiGetLastPostInChannel(siteOneUrl, testChannel.id);
|
const {post} = await Post.apiGetLastPostInChannel(siteOneUrl, testChannel.id);
|
||||||
|
const {postListPostItem} = ChannelScreen.getPostListPostItem(post.id, message);
|
||||||
|
await waitForElementToBeVisible(postListPostItem);
|
||||||
|
|
||||||
await ChannelScreen.openPostOptionsFor(post.id, message);
|
await ChannelScreen.openPostOptionsFor(post.id, message);
|
||||||
|
await waitFor(PostOptionsScreen.followThreadOption).toBeVisible().withTimeout(timeouts.FOUR_SEC);
|
||||||
await PostOptionsScreen.followThreadOption.tap();
|
await PostOptionsScreen.followThreadOption.tap();
|
||||||
|
|
||||||
// * Verify message is followed by user via post footer
|
// * Verify message is followed by user via post footer
|
||||||
|
|
|
||||||
|
|
@ -22,7 +22,7 @@ import {
|
||||||
LoginScreen,
|
LoginScreen,
|
||||||
ServerScreen,
|
ServerScreen,
|
||||||
} from '@support/ui/screen';
|
} from '@support/ui/screen';
|
||||||
import {expect} from 'detox';
|
import {timeouts} from '@support/utils';
|
||||||
|
|
||||||
describe('Messaging - Markdown Image', () => {
|
describe('Messaging - Markdown Image', () => {
|
||||||
const serverOneDisplayName = 'Server 1';
|
const serverOneDisplayName = 'Server 1';
|
||||||
|
|
@ -56,8 +56,13 @@ describe('Messaging - Markdown Image', () => {
|
||||||
|
|
||||||
// * Verify markdown image is displayed
|
// * Verify markdown image is displayed
|
||||||
const {post} = await Post.apiGetLastPostInChannel(siteOneUrl, testChannel.id);
|
const {post} = await Post.apiGetLastPostInChannel(siteOneUrl, testChannel.id);
|
||||||
const {postListPostItemImage} = ChannelScreen.getPostListPostItem(post.id);
|
const {postListPostItem, postListPostItemImage} = ChannelScreen.getPostListPostItem(post.id);
|
||||||
await expect(postListPostItemImage).toBeVisible();
|
|
||||||
|
// Scroll to the post first to ensure it's in view
|
||||||
|
await waitFor(postListPostItem).toBeVisible().withTimeout(timeouts.FOUR_SEC);
|
||||||
|
|
||||||
|
// Wait for image to load and have dimensions (not 0x0)
|
||||||
|
await waitFor(postListPostItemImage).toExist().withTimeout(timeouts.TEN_SEC);
|
||||||
|
|
||||||
// # Go back to channel list screen
|
// # Go back to channel list screen
|
||||||
await ChannelScreen.back();
|
await ChannelScreen.back();
|
||||||
|
|
@ -71,8 +76,13 @@ describe('Messaging - Markdown Image', () => {
|
||||||
|
|
||||||
// * Verify markdown image with link is displayed
|
// * Verify markdown image with link is displayed
|
||||||
const {post} = await Post.apiGetLastPostInChannel(siteOneUrl, testChannel.id);
|
const {post} = await Post.apiGetLastPostInChannel(siteOneUrl, testChannel.id);
|
||||||
const {postListPostItemImage} = ChannelScreen.getPostListPostItem(post.id);
|
const {postListPostItem, postListPostItemImage} = ChannelScreen.getPostListPostItem(post.id);
|
||||||
await expect(postListPostItemImage).toBeVisible();
|
|
||||||
|
// Scroll to the post first to ensure it's in view
|
||||||
|
await waitFor(postListPostItem).toBeVisible().withTimeout(timeouts.FOUR_SEC);
|
||||||
|
|
||||||
|
// Wait for image to load and have dimensions (not 0x0)
|
||||||
|
await waitFor(postListPostItemImage).toExist().withTimeout(timeouts.TEN_SEC);
|
||||||
|
|
||||||
// # Go back to channel list screen
|
// # Go back to channel list screen
|
||||||
await ChannelScreen.back();
|
await ChannelScreen.back();
|
||||||
|
|
|
||||||
|
|
@ -24,8 +24,8 @@ import {
|
||||||
ServerScreen,
|
ServerScreen,
|
||||||
ThreadScreen,
|
ThreadScreen,
|
||||||
} from '@support/ui/screen';
|
} from '@support/ui/screen';
|
||||||
import {getRandomId} from '@support/utils';
|
import {getRandomId, timeouts, wait} from '@support/utils';
|
||||||
import {expect} from 'detox';
|
import {expect, waitFor} from 'detox';
|
||||||
|
|
||||||
describe('Messaging - Message Delete', () => {
|
describe('Messaging - Message Delete', () => {
|
||||||
const serverOneDisplayName = 'Server 1';
|
const serverOneDisplayName = 'Server 1';
|
||||||
|
|
@ -56,18 +56,18 @@ describe('Messaging - Message Delete', () => {
|
||||||
const message = `Message ${getRandomId()}`;
|
const message = `Message ${getRandomId()}`;
|
||||||
await ChannelScreen.open(channelsCategory, testChannel.name);
|
await ChannelScreen.open(channelsCategory, testChannel.name);
|
||||||
await ChannelScreen.postMessage(message);
|
await ChannelScreen.postMessage(message);
|
||||||
|
await ChannelScreen.dismissKeyboard();
|
||||||
|
|
||||||
// * Verify message is added to post list
|
// * Verify message is added to post list
|
||||||
const {post} = await Post.apiGetLastPostInChannel(siteOneUrl, testChannel.id);
|
const {post} = await Post.apiGetLastPostInChannel(siteOneUrl, testChannel.id);
|
||||||
const {postListPostItem} = ChannelScreen.getPostListPostItem(post.id, message);
|
const {postListPostItem} = ChannelScreen.getPostListPostItem(post.id, message);
|
||||||
await expect(postListPostItem).toBeVisible();
|
|
||||||
|
|
||||||
// # Open post options for the message that was just posted, tap delete option and confirm
|
// # Open post options for the message that was just posted, tap delete option and confirm
|
||||||
await ChannelScreen.openPostOptionsFor(post.id, message);
|
await ChannelScreen.openPostOptionsFor(post.id, message);
|
||||||
await PostOptionsScreen.deletePost({confirm: true});
|
await PostOptionsScreen.deletePost({confirm: true});
|
||||||
|
|
||||||
// * Verify post message is deleted
|
// * Verify post message is deleted
|
||||||
await expect(postListPostItem).not.toExist();
|
await waitFor(postListPostItem).not.toExist().withTimeout(timeouts.TEN_SEC);
|
||||||
|
|
||||||
// # Go back to channel list screen
|
// # Go back to channel list screen
|
||||||
await ChannelScreen.back();
|
await ChannelScreen.back();
|
||||||
|
|
@ -78,11 +78,11 @@ describe('Messaging - Message Delete', () => {
|
||||||
const message = `Message ${getRandomId()}`;
|
const message = `Message ${getRandomId()}`;
|
||||||
await ChannelScreen.open(channelsCategory, testChannel.name);
|
await ChannelScreen.open(channelsCategory, testChannel.name);
|
||||||
await ChannelScreen.postMessage(message);
|
await ChannelScreen.postMessage(message);
|
||||||
|
await ChannelScreen.dismissKeyboard();
|
||||||
|
|
||||||
// * Verify message is added to post list
|
// * Verify message is added to post list
|
||||||
const {post} = await Post.apiGetLastPostInChannel(siteOneUrl, testChannel.id);
|
const {post} = await Post.apiGetLastPostInChannel(siteOneUrl, testChannel.id);
|
||||||
const {postListPostItem} = ChannelScreen.getPostListPostItem(post.id, message);
|
const {postListPostItem} = ChannelScreen.getPostListPostItem(post.id, message);
|
||||||
await expect(postListPostItem).toBeVisible();
|
|
||||||
|
|
||||||
// # Open post options for the message that was just posted, tap delete option and cancel
|
// # Open post options for the message that was just posted, tap delete option and cancel
|
||||||
await ChannelScreen.openPostOptionsFor(post.id, message);
|
await ChannelScreen.openPostOptionsFor(post.id, message);
|
||||||
|
|
@ -100,8 +100,12 @@ describe('Messaging - Message Delete', () => {
|
||||||
const message = `Message ${getRandomId()}`;
|
const message = `Message ${getRandomId()}`;
|
||||||
await ChannelScreen.open(channelsCategory, testChannel.name);
|
await ChannelScreen.open(channelsCategory, testChannel.name);
|
||||||
await ChannelScreen.postMessage(message);
|
await ChannelScreen.postMessage(message);
|
||||||
|
await ChannelScreen.dismissKeyboard();
|
||||||
|
|
||||||
const {post: parentPost} = await Post.apiGetLastPostInChannel(siteOneUrl, testChannel.id);
|
const {post: parentPost} = await Post.apiGetLastPostInChannel(siteOneUrl, testChannel.id);
|
||||||
const {postListPostItem: parentPostListPostItem} = ChannelScreen.getPostListPostItem(parentPost.id, message);
|
const {postListPostItem: parentPostListPostItem} = ChannelScreen.getPostListPostItem(parentPost.id, message);
|
||||||
|
await waitFor(parentPostListPostItem).toExist().withTimeout(timeouts.FOUR_SEC);
|
||||||
|
|
||||||
await parentPostListPostItem.tap();
|
await parentPostListPostItem.tap();
|
||||||
|
|
||||||
// * Verify on thread screen
|
// * Verify on thread screen
|
||||||
|
|
@ -110,13 +114,18 @@ describe('Messaging - Message Delete', () => {
|
||||||
// # Post a reply, open post options for the reply message, tap delete option and confirm
|
// # Post a reply, open post options for the reply message, tap delete option and confirm
|
||||||
const replyMessage = `${message} reply`;
|
const replyMessage = `${message} reply`;
|
||||||
await ThreadScreen.postMessage(replyMessage);
|
await ThreadScreen.postMessage(replyMessage);
|
||||||
|
await ChannelScreen.dismissKeyboard();
|
||||||
|
|
||||||
const {post: replyPost} = await Post.apiGetLastPostInChannel(siteOneUrl, testChannel.id);
|
const {post: replyPost} = await Post.apiGetLastPostInChannel(siteOneUrl, testChannel.id);
|
||||||
const {postListPostItem: replyPostListPostItem} = ChannelScreen.getPostListPostItem(replyPost.id, replyMessage);
|
const {postListPostItem: replyPostListPostItem} = ThreadScreen.getPostListPostItem(replyPost.id, replyMessage);
|
||||||
|
await waitFor(replyPostListPostItem).toExist().withTimeout(timeouts.FOUR_SEC);
|
||||||
|
|
||||||
await ThreadScreen.openPostOptionsFor(replyPost.id, replyMessage);
|
await ThreadScreen.openPostOptionsFor(replyPost.id, replyMessage);
|
||||||
await PostOptionsScreen.deletePost({confirm: true});
|
await PostOptionsScreen.deletePost({confirm: true});
|
||||||
|
await wait(timeouts.TWO_SEC);
|
||||||
|
|
||||||
// * Verify reply message is deleted
|
// * Verify reply message is deleted
|
||||||
await expect(replyPostListPostItem).not.toExist();
|
await waitFor(replyPostListPostItem).not.toExist().withTimeout(timeouts.TEN_SEC);
|
||||||
|
|
||||||
// # Go back to channel list screen
|
// # Go back to channel list screen
|
||||||
await ThreadScreen.back();
|
await ThreadScreen.back();
|
||||||
|
|
|
||||||
|
|
@ -29,8 +29,8 @@ import {expect} from 'detox';
|
||||||
|
|
||||||
describe('Messaging - Message Draft', () => {
|
describe('Messaging - Message Draft', () => {
|
||||||
const serverOneDisplayName = 'Server 1';
|
const serverOneDisplayName = 'Server 1';
|
||||||
const channelsCategory = 'channels';
|
|
||||||
const offTopicChannelName = 'off-topic';
|
const offTopicChannelName = 'off-topic';
|
||||||
|
const channelsCategory = 'channels';
|
||||||
let testChannel: any;
|
let testChannel: any;
|
||||||
|
|
||||||
beforeAll(async () => {
|
beforeAll(async () => {
|
||||||
|
|
|
||||||
|
|
@ -25,8 +25,8 @@ import {
|
||||||
ServerScreen,
|
ServerScreen,
|
||||||
ThreadScreen,
|
ThreadScreen,
|
||||||
} from '@support/ui/screen';
|
} from '@support/ui/screen';
|
||||||
import {getRandomId} from '@support/utils';
|
import {getRandomId, timeouts} from '@support/utils';
|
||||||
import {expect} from 'detox';
|
import {expect, waitFor} from 'detox';
|
||||||
|
|
||||||
describe('Messaging - Message Edit', () => {
|
describe('Messaging - Message Edit', () => {
|
||||||
const serverOneDisplayName = 'Server 1';
|
const serverOneDisplayName = 'Server 1';
|
||||||
|
|
@ -57,11 +57,15 @@ describe('Messaging - Message Edit', () => {
|
||||||
const message = `Message ${getRandomId()}`;
|
const message = `Message ${getRandomId()}`;
|
||||||
await ChannelScreen.open(channelsCategory, testChannel.name);
|
await ChannelScreen.open(channelsCategory, testChannel.name);
|
||||||
await ChannelScreen.postMessage(message);
|
await ChannelScreen.postMessage(message);
|
||||||
|
await ChannelScreen.dismissKeyboard();
|
||||||
|
|
||||||
// * Verify message is added to post list
|
// * Verify message is added to post list
|
||||||
const {post} = await Post.apiGetLastPostInChannel(siteOneUrl, testChannel.id);
|
const {post} = await Post.apiGetLastPostInChannel(siteOneUrl, testChannel.id);
|
||||||
const {postListPostItem: originalPostListPostItem} = ChannelScreen.getPostListPostItem(post.id, message);
|
const {postListPostItem: originalPostListPostItem} = ChannelScreen.getPostListPostItem(post.id, message);
|
||||||
await expect(originalPostListPostItem).toBeVisible();
|
await waitFor(originalPostListPostItem).toBeVisible().withTimeout(timeouts.FOUR_SEC);
|
||||||
|
|
||||||
|
// # Scroll to post to dismiss keyboard and ensure post is visible
|
||||||
|
await originalPostListPostItem.scrollTo('top');
|
||||||
|
|
||||||
// # Open post options for the message that was just posted and tap edit option
|
// # Open post options for the message that was just posted and tap edit option
|
||||||
await ChannelScreen.openPostOptionsFor(post.id, message);
|
await ChannelScreen.openPostOptionsFor(post.id, message);
|
||||||
|
|
@ -91,11 +95,15 @@ describe('Messaging - Message Edit', () => {
|
||||||
const message = `Message ${getRandomId()}`;
|
const message = `Message ${getRandomId()}`;
|
||||||
await ChannelScreen.open(channelsCategory, testChannel.name);
|
await ChannelScreen.open(channelsCategory, testChannel.name);
|
||||||
await ChannelScreen.postMessage(message);
|
await ChannelScreen.postMessage(message);
|
||||||
|
await ChannelScreen.dismissKeyboard();
|
||||||
|
|
||||||
// * Verify message is added to post list
|
// * Verify message is added to post list
|
||||||
const {post} = await Post.apiGetLastPostInChannel(siteOneUrl, testChannel.id);
|
const {post} = await Post.apiGetLastPostInChannel(siteOneUrl, testChannel.id);
|
||||||
const {postListPostItem} = ChannelScreen.getPostListPostItem(post.id, message);
|
const {postListPostItem} = ChannelScreen.getPostListPostItem(post.id, message);
|
||||||
await expect(postListPostItem).toBeVisible();
|
await waitFor(postListPostItem).toBeVisible().withTimeout(timeouts.FOUR_SEC);
|
||||||
|
|
||||||
|
// # Scroll to post to dismiss keyboard and ensure post is visible
|
||||||
|
await postListPostItem.scrollTo('top');
|
||||||
|
|
||||||
// # Open post options for the message that was just posted and tap edit option
|
// # Open post options for the message that was just posted and tap edit option
|
||||||
await ChannelScreen.openPostOptionsFor(post.id, message);
|
await ChannelScreen.openPostOptionsFor(post.id, message);
|
||||||
|
|
@ -121,8 +129,12 @@ describe('Messaging - Message Edit', () => {
|
||||||
const message = `Message ${getRandomId()}`;
|
const message = `Message ${getRandomId()}`;
|
||||||
await ChannelScreen.open(channelsCategory, testChannel.name);
|
await ChannelScreen.open(channelsCategory, testChannel.name);
|
||||||
await ChannelScreen.postMessage(message);
|
await ChannelScreen.postMessage(message);
|
||||||
|
await ChannelScreen.dismissKeyboard();
|
||||||
const {post: parentPost} = await Post.apiGetLastPostInChannel(siteOneUrl, testChannel.id);
|
const {post: parentPost} = await Post.apiGetLastPostInChannel(siteOneUrl, testChannel.id);
|
||||||
const {postListPostItem: parentPostListPostItem} = ChannelScreen.getPostListPostItem(parentPost.id, message);
|
const {postListPostItem: parentPostListPostItem} = ChannelScreen.getPostListPostItem(parentPost.id, message);
|
||||||
|
|
||||||
|
// # Scroll to post to dismiss keyboard before tapping
|
||||||
|
await parentPostListPostItem.scrollTo('top');
|
||||||
await parentPostListPostItem.tap();
|
await parentPostListPostItem.tap();
|
||||||
|
|
||||||
// * Verify on thread screen
|
// * Verify on thread screen
|
||||||
|
|
@ -131,7 +143,12 @@ describe('Messaging - Message Edit', () => {
|
||||||
// # Post a reply, open post options for the reply message and tap edit option
|
// # Post a reply, open post options for the reply message and tap edit option
|
||||||
const replyMessage = `${message} reply`;
|
const replyMessage = `${message} reply`;
|
||||||
await ThreadScreen.postMessage(replyMessage);
|
await ThreadScreen.postMessage(replyMessage);
|
||||||
|
await ChannelScreen.dismissKeyboard();
|
||||||
const {post: replyPost} = await Post.apiGetLastPostInChannel(siteOneUrl, testChannel.id);
|
const {post: replyPost} = await Post.apiGetLastPostInChannel(siteOneUrl, testChannel.id);
|
||||||
|
const {postListPostItem: replyPostListPostItem} = ThreadScreen.getPostListPostItem(replyPost.id, replyMessage);
|
||||||
|
|
||||||
|
// # Scroll to reply post to dismiss keyboard before long press
|
||||||
|
await replyPostListPostItem.scrollTo('top');
|
||||||
await ThreadScreen.openPostOptionsFor(replyPost.id, replyMessage);
|
await ThreadScreen.openPostOptionsFor(replyPost.id, replyMessage);
|
||||||
await PostOptionsScreen.editPostOption.tap();
|
await PostOptionsScreen.editPostOption.tap();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@ import {
|
||||||
Channel,
|
Channel,
|
||||||
Post,
|
Post,
|
||||||
Setup,
|
Setup,
|
||||||
|
Team,
|
||||||
User,
|
User,
|
||||||
} from '@support/server_api';
|
} from '@support/server_api';
|
||||||
import {
|
import {
|
||||||
|
|
@ -39,7 +40,7 @@ describe('Messaging - Message Permalink Preview', () => {
|
||||||
await postItem.longPress();
|
await postItem.longPress();
|
||||||
await PostOptionsScreen.toBeVisible();
|
await PostOptionsScreen.toBeVisible();
|
||||||
await PostOptionsScreen.copyLinkOption.tap();
|
await PostOptionsScreen.copyLinkOption.tap();
|
||||||
await wait(timeouts.ONE_SEC);
|
await wait(timeouts.FOUR_SEC);
|
||||||
await expect(PostOptionsScreen.postOptionsScreen).not.toBeVisible();
|
await expect(PostOptionsScreen.postOptionsScreen).not.toBeVisible();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -64,6 +65,7 @@ describe('Messaging - Message Permalink Preview', () => {
|
||||||
testUser = user;
|
testUser = user;
|
||||||
|
|
||||||
({user: testOtherUser} = await User.apiCreateUser(siteOneUrl));
|
({user: testOtherUser} = await User.apiCreateUser(siteOneUrl));
|
||||||
|
await Team.apiAddUserToTeam(siteOneUrl, testOtherUser.id, testTeam.id);
|
||||||
await Channel.apiAddUserToChannel(siteOneUrl, testOtherUser.id, testChannel.id);
|
await Channel.apiAddUserToChannel(siteOneUrl, testOtherUser.id, testChannel.id);
|
||||||
|
|
||||||
await ServerScreen.connectToServer(serverOneUrl, serverOneDisplayName);
|
await ServerScreen.connectToServer(serverOneUrl, serverOneDisplayName);
|
||||||
|
|
@ -86,6 +88,7 @@ describe('Messaging - Message Permalink Preview', () => {
|
||||||
userId: testOtherUser.id,
|
userId: testOtherUser.id,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
await wait(timeouts.FOUR_SEC);
|
||||||
await ChannelScreen.open(channelsCategory, testChannel.name);
|
await ChannelScreen.open(channelsCategory, testChannel.name);
|
||||||
|
|
||||||
const {postListPostItem} = ChannelScreen.getPostListPostItem(targetPost.post.id, targetMessage);
|
const {postListPostItem} = ChannelScreen.getPostListPostItem(targetPost.post.id, targetMessage);
|
||||||
|
|
@ -112,7 +115,7 @@ describe('Messaging - Message Permalink Preview', () => {
|
||||||
|
|
||||||
const {channel: otherChannel} = await Channel.apiCreateChannel(siteOneUrl, {teamId: testTeam.id});
|
const {channel: otherChannel} = await Channel.apiCreateChannel(siteOneUrl, {teamId: testTeam.id});
|
||||||
await Channel.apiAddUserToChannel(siteOneUrl, testUser.id, otherChannel.id);
|
await Channel.apiAddUserToChannel(siteOneUrl, testUser.id, otherChannel.id);
|
||||||
|
await wait(timeouts.FOUR_SEC);
|
||||||
await ChannelScreen.open(channelsCategory, testChannel.name);
|
await ChannelScreen.open(channelsCategory, testChannel.name);
|
||||||
const {postListPostItem} = ChannelScreen.getPostListPostItem(targetPost.post.id, targetMessage);
|
const {postListPostItem} = ChannelScreen.getPostListPostItem(targetPost.post.id, targetMessage);
|
||||||
await copyLinkFromPost(postListPostItem);
|
await copyLinkFromPost(postListPostItem);
|
||||||
|
|
@ -146,7 +149,7 @@ describe('Messaging - Message Permalink Preview', () => {
|
||||||
message: targetMessage,
|
message: targetMessage,
|
||||||
userId: testOtherUser.id,
|
userId: testOtherUser.id,
|
||||||
});
|
});
|
||||||
|
await wait(timeouts.FOUR_SEC);
|
||||||
await ChannelScreen.open(channelsCategory, targetChannel.name);
|
await ChannelScreen.open(channelsCategory, targetChannel.name);
|
||||||
const {postListPostItem} = ChannelScreen.getPostListPostItem(targetPost.post.id, targetMessage);
|
const {postListPostItem} = ChannelScreen.getPostListPostItem(targetPost.post.id, targetMessage);
|
||||||
await copyLinkFromPost(postListPostItem);
|
await copyLinkFromPost(postListPostItem);
|
||||||
|
|
|
||||||
|
|
@ -22,7 +22,7 @@ import {
|
||||||
LoginScreen,
|
LoginScreen,
|
||||||
ServerScreen,
|
ServerScreen,
|
||||||
} from '@support/ui/screen';
|
} from '@support/ui/screen';
|
||||||
import {getRandomId, isAndroid, timeouts, wait} from '@support/utils';
|
import {getRandomId, timeouts, wait} from '@support/utils';
|
||||||
import {expect} from 'detox';
|
import {expect} from 'detox';
|
||||||
|
|
||||||
describe('Messaging - Message Post', () => {
|
describe('Messaging - Message Post', () => {
|
||||||
|
|
@ -80,23 +80,19 @@ describe('Messaging - Message Post', () => {
|
||||||
|
|
||||||
it('MM-T4782_2 - should be able to post a long message', async () => {
|
it('MM-T4782_2 - should be able to post a long message', async () => {
|
||||||
// # Open a channel screen, post a long message, and a short message after
|
// # Open a channel screen, post a long message, and a short message after
|
||||||
const longMessage = 'The quick brown fox jumps over the lazy dog.'.repeat(20);
|
const longMessage = 'The quick brown fox jumps over the lazy dog.'.repeat(40);
|
||||||
await ChannelScreen.open(channelsCategory, testChannel.name);
|
await ChannelScreen.open(channelsCategory, testChannel.name);
|
||||||
await ChannelScreen.postMessage(longMessage);
|
await ChannelScreen.postMessage(longMessage);
|
||||||
const {post} = await Post.apiGetLastPostInChannel(siteOneUrl, testChannel.id);
|
const {post} = await Post.apiGetLastPostInChannel(siteOneUrl, testChannel.id);
|
||||||
await ChannelScreen.postMessage('short message');
|
await ChannelScreen.postMessage('short message');
|
||||||
|
|
||||||
// * Verify long message is posted and displays show more button (chevron down button)
|
|
||||||
if (isAndroid()) {
|
|
||||||
await device.pressBack();
|
|
||||||
await wait(timeouts.ONE_SEC);
|
|
||||||
}
|
|
||||||
const {postListPostItem, postListPostItemShowLessButton, postListPostItemShowMoreButton} = ChannelScreen.getPostListPostItem(post.id, longMessage);
|
const {postListPostItem, postListPostItemShowLessButton, postListPostItemShowMoreButton} = ChannelScreen.getPostListPostItem(post.id, longMessage);
|
||||||
await expect(postListPostItem).toBeVisible();
|
await expect(postListPostItem).toExist();
|
||||||
await expect(postListPostItemShowMoreButton).toBeVisible();
|
await expect(postListPostItemShowMoreButton).toExist();
|
||||||
|
|
||||||
// # Tap on show more button on long message post
|
// # Tap on show more button on long message post
|
||||||
await postListPostItemShowMoreButton.tap();
|
await postListPostItemShowMoreButton.tap();
|
||||||
|
await wait(timeouts.TWO_SEC);
|
||||||
|
|
||||||
// * Verify long message post displays show less button (chevron up button)
|
// * Verify long message post displays show less button (chevron up button)
|
||||||
await expect(postListPostItemShowLessButton).toBeVisible();
|
await expect(postListPostItemShowLessButton).toBeVisible();
|
||||||
|
|
|
||||||
|
|
@ -24,8 +24,8 @@ import {
|
||||||
ServerScreen,
|
ServerScreen,
|
||||||
ThreadScreen,
|
ThreadScreen,
|
||||||
} from '@support/ui/screen';
|
} from '@support/ui/screen';
|
||||||
import {getRandomId} from '@support/utils';
|
import {getRandomId, timeouts} from '@support/utils';
|
||||||
import {expect} from 'detox';
|
import {expect, waitFor} from 'detox';
|
||||||
|
|
||||||
describe('Messaging - Message Reply', () => {
|
describe('Messaging - Message Reply', () => {
|
||||||
const serverOneDisplayName = 'Server 1';
|
const serverOneDisplayName = 'Server 1';
|
||||||
|
|
@ -46,6 +46,11 @@ describe('Messaging - Message Reply', () => {
|
||||||
await ChannelListScreen.toBeVisible();
|
await ChannelListScreen.toBeVisible();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
afterEach(async () => {
|
||||||
|
// # Go back to channel list screen
|
||||||
|
await ChannelScreen.back();
|
||||||
|
});
|
||||||
|
|
||||||
afterAll(async () => {
|
afterAll(async () => {
|
||||||
// # Log out
|
// # Log out
|
||||||
await HomeScreen.logout();
|
await HomeScreen.logout();
|
||||||
|
|
@ -56,11 +61,12 @@ describe('Messaging - Message Reply', () => {
|
||||||
const message = `Message ${getRandomId()}`;
|
const message = `Message ${getRandomId()}`;
|
||||||
await ChannelScreen.open(channelsCategory, testChannel.name);
|
await ChannelScreen.open(channelsCategory, testChannel.name);
|
||||||
await ChannelScreen.postMessage(message);
|
await ChannelScreen.postMessage(message);
|
||||||
|
await ChannelScreen.dismissKeyboard();
|
||||||
|
|
||||||
// * Verify message is added to post list
|
// * Verify message is added to post list
|
||||||
const {post} = await Post.apiGetLastPostInChannel(siteOneUrl, testChannel.id);
|
const {post} = await Post.apiGetLastPostInChannel(siteOneUrl, testChannel.id);
|
||||||
const {postListPostItem} = ChannelScreen.getPostListPostItem(post.id, message);
|
const {postListPostItem} = ChannelScreen.getPostListPostItem(post.id, message);
|
||||||
await expect(postListPostItem).toBeVisible();
|
await waitFor(postListPostItem).toBeVisible().withTimeout(timeouts.FOUR_SEC);
|
||||||
|
|
||||||
// # Open post options for the message that was just posted, tap reply option
|
// # Open post options for the message that was just posted, tap reply option
|
||||||
await ChannelScreen.openPostOptionsFor(post.id, message);
|
await ChannelScreen.openPostOptionsFor(post.id, message);
|
||||||
|
|
@ -74,6 +80,7 @@ describe('Messaging - Message Reply', () => {
|
||||||
// # Reply to parent post
|
// # Reply to parent post
|
||||||
const replyMessage = `${message} reply`;
|
const replyMessage = `${message} reply`;
|
||||||
await ThreadScreen.postMessage(replyMessage);
|
await ThreadScreen.postMessage(replyMessage);
|
||||||
|
await ChannelScreen.dismissKeyboard();
|
||||||
|
|
||||||
// * Verify reply message is posted
|
// * Verify reply message is posted
|
||||||
const {post: replyPost} = await Post.apiGetLastPostInChannel(siteOneUrl, testChannel.id);
|
const {post: replyPost} = await Post.apiGetLastPostInChannel(siteOneUrl, testChannel.id);
|
||||||
|
|
@ -82,7 +89,6 @@ describe('Messaging - Message Reply', () => {
|
||||||
|
|
||||||
// # Go back to channel list screen
|
// # Go back to channel list screen
|
||||||
await ThreadScreen.back();
|
await ThreadScreen.back();
|
||||||
await ChannelScreen.back();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('MM-T4785_2 - should be able to open reply thread by tapping on the post', async () => {
|
it('MM-T4785_2 - should be able to open reply thread by tapping on the post', async () => {
|
||||||
|
|
@ -90,11 +96,12 @@ describe('Messaging - Message Reply', () => {
|
||||||
const message = `Message ${getRandomId()}`;
|
const message = `Message ${getRandomId()}`;
|
||||||
await ChannelScreen.open(channelsCategory, testChannel.name);
|
await ChannelScreen.open(channelsCategory, testChannel.name);
|
||||||
await ChannelScreen.postMessage(message);
|
await ChannelScreen.postMessage(message);
|
||||||
|
await ChannelScreen.dismissKeyboard();
|
||||||
|
|
||||||
// * Verify message is added to post list
|
// * Verify message is added to post list
|
||||||
const {post} = await Post.apiGetLastPostInChannel(siteOneUrl, testChannel.id);
|
const {post} = await Post.apiGetLastPostInChannel(siteOneUrl, testChannel.id);
|
||||||
const {postListPostItem} = ChannelScreen.getPostListPostItem(post.id, message);
|
const {postListPostItem} = ChannelScreen.getPostListPostItem(post.id, message);
|
||||||
await expect(postListPostItem).toBeVisible();
|
await waitFor(postListPostItem).toBeVisible().withTimeout(timeouts.FOUR_SEC);
|
||||||
|
|
||||||
// # Tap on post to open thread
|
// # Tap on post to open thread
|
||||||
await postListPostItem.tap();
|
await postListPostItem.tap();
|
||||||
|
|
@ -104,7 +111,6 @@ describe('Messaging - Message Reply', () => {
|
||||||
|
|
||||||
// # Go back to channel list screen
|
// # Go back to channel list screen
|
||||||
await ThreadScreen.back();
|
await ThreadScreen.back();
|
||||||
await ChannelScreen.back();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('MM-T4785_3 - should not have reply option available on reply thread post options', async () => {
|
it('MM-T4785_3 - should not have reply option available on reply thread post options', async () => {
|
||||||
|
|
@ -112,8 +118,12 @@ describe('Messaging - Message Reply', () => {
|
||||||
const message = `Message ${getRandomId()}`;
|
const message = `Message ${getRandomId()}`;
|
||||||
await ChannelScreen.open(channelsCategory, testChannel.name);
|
await ChannelScreen.open(channelsCategory, testChannel.name);
|
||||||
await ChannelScreen.postMessage(message);
|
await ChannelScreen.postMessage(message);
|
||||||
|
await ChannelScreen.dismissKeyboard();
|
||||||
|
|
||||||
const {post} = await Post.apiGetLastPostInChannel(siteOneUrl, testChannel.id);
|
const {post} = await Post.apiGetLastPostInChannel(siteOneUrl, testChannel.id);
|
||||||
const {postListPostItem} = ChannelScreen.getPostListPostItem(post.id, message);
|
const {postListPostItem} = ChannelScreen.getPostListPostItem(post.id, message);
|
||||||
|
await waitFor(postListPostItem).toBeVisible().withTimeout(timeouts.FOUR_SEC);
|
||||||
|
|
||||||
await postListPostItem.tap();
|
await postListPostItem.tap();
|
||||||
|
|
||||||
// * Verify on reply thread screen
|
// * Verify on reply thread screen
|
||||||
|
|
@ -128,6 +138,5 @@ describe('Messaging - Message Reply', () => {
|
||||||
// # Go back to channel list screen
|
// # Go back to channel list screen
|
||||||
await PostOptionsScreen.close();
|
await PostOptionsScreen.close();
|
||||||
await ThreadScreen.back();
|
await ThreadScreen.back();
|
||||||
await ChannelScreen.back();
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,7 @@ import {
|
||||||
ServerScreen,
|
ServerScreen,
|
||||||
} from '@support/ui/screen';
|
} from '@support/ui/screen';
|
||||||
import {getRandomId, timeouts, wait} from '@support/utils';
|
import {getRandomId, timeouts, wait} from '@support/utils';
|
||||||
import {expect} from 'detox';
|
import {expect, waitFor} from 'detox';
|
||||||
|
|
||||||
describe('Messaging - Permalink', () => {
|
describe('Messaging - Permalink', () => {
|
||||||
const serverOneDisplayName = 'Server 1';
|
const serverOneDisplayName = 'Server 1';
|
||||||
|
|
@ -62,13 +62,20 @@ describe('Messaging - Permalink', () => {
|
||||||
const permalinkLabel = `permalink-${getRandomId()}`;
|
const permalinkLabel = `permalink-${getRandomId()}`;
|
||||||
const permalinkMessage = `[${permalinkLabel}](/${teamName}/pl/${permalinkTargetPost.id})`;
|
const permalinkMessage = `[${permalinkLabel}](/${teamName}/pl/${permalinkTargetPost.id})`;
|
||||||
await ChannelScreen.postMessage(permalinkMessage);
|
await ChannelScreen.postMessage(permalinkMessage);
|
||||||
await element(by.text(permalinkLabel)).tap({x: 5, y: 10});
|
await wait(timeouts.TWO_SEC);
|
||||||
await wait(timeouts.ONE_SEC);
|
|
||||||
|
// # Wait for the message to be posted and element to become visible (keyboard should dismiss)
|
||||||
|
const permalinkElement = element(by.text(permalinkLabel));
|
||||||
|
await waitFor(permalinkElement).toBeVisible().withTimeout(timeouts.FOUR_SEC);
|
||||||
|
|
||||||
|
// # Tap on permalink
|
||||||
|
await permalinkElement.tap();
|
||||||
|
await wait(timeouts.FOUR_SEC);
|
||||||
|
|
||||||
// * Verify on permalink screen and target post is displayed
|
// * Verify on permalink screen and target post is displayed
|
||||||
await PermalinkScreen.toBeVisible();
|
await PermalinkScreen.toBeVisible();
|
||||||
const {postListPostItem: permalinkPostListPostItem} = PermalinkScreen.getPostListPostItem(permalinkTargetPost.id, permalinkTargetPost.message);
|
const {postListPostItem: permalinkPostListPostItem} = PermalinkScreen.getPostListPostItem(permalinkTargetPost.id, permalinkTargetPost.message);
|
||||||
await expect(permalinkPostListPostItem).toBeVisible();
|
await expect(permalinkPostListPostItem).toExist();
|
||||||
|
|
||||||
// # Jump to recent messages
|
// # Jump to recent messages
|
||||||
await PermalinkScreen.jumpToRecentMessages();
|
await PermalinkScreen.jumpToRecentMessages();
|
||||||
|
|
@ -76,7 +83,7 @@ describe('Messaging - Permalink', () => {
|
||||||
// * Verify on channel screen and target post is displayed
|
// * Verify on channel screen and target post is displayed
|
||||||
await expect(ChannelScreen.headerTitle).toHaveText(permalinkTargetChannelDiplayName);
|
await expect(ChannelScreen.headerTitle).toHaveText(permalinkTargetChannelDiplayName);
|
||||||
const {postListPostItem: channelPostListPostItem} = ChannelScreen.getPostListPostItem(permalinkTargetPost.id, permalinkTargetPost.message);
|
const {postListPostItem: channelPostListPostItem} = ChannelScreen.getPostListPostItem(permalinkTargetPost.id, permalinkTargetPost.message);
|
||||||
await expect(channelPostListPostItem).toBeVisible();
|
await expect(channelPostListPostItem).toExist();
|
||||||
};
|
};
|
||||||
|
|
||||||
it('MM-T4876_1 - should be able to jump to target public channel post by tapping on permalink with team name', async () => {
|
it('MM-T4876_1 - should be able to jump to target public channel post by tapping on permalink with team name', async () => {
|
||||||
|
|
|
||||||
|
|
@ -57,6 +57,7 @@ describe('Messaging - Pin and Unpin Message', () => {
|
||||||
const message = `Message ${getRandomId()}`;
|
const message = `Message ${getRandomId()}`;
|
||||||
await ChannelScreen.open(channelsCategory, testChannel.name);
|
await ChannelScreen.open(channelsCategory, testChannel.name);
|
||||||
await ChannelScreen.postMessage(message);
|
await ChannelScreen.postMessage(message);
|
||||||
|
await ChannelScreen.dismissKeyboard();
|
||||||
|
|
||||||
// * Verify message is posted
|
// * Verify message is posted
|
||||||
const {post} = await Post.apiGetLastPostInChannel(siteOneUrl, testChannel.id);
|
const {post} = await Post.apiGetLastPostInChannel(siteOneUrl, testChannel.id);
|
||||||
|
|
@ -68,7 +69,7 @@ describe('Messaging - Pin and Unpin Message', () => {
|
||||||
await PostOptionsScreen.pinPostOption.tap();
|
await PostOptionsScreen.pinPostOption.tap();
|
||||||
|
|
||||||
// * Verify pinned text is displayed on the post pre-header
|
// * Verify pinned text is displayed on the post pre-header
|
||||||
await wait(timeouts.TEN_SEC);
|
await wait(timeouts.TWO_SEC);
|
||||||
const {postListPostItemPreHeaderText} = ChannelScreen.getPostListPostItem(post.id, message);
|
const {postListPostItemPreHeaderText} = ChannelScreen.getPostListPostItem(post.id, message);
|
||||||
await expect(postListPostItemPreHeaderText).toHaveText(pinnedText);
|
await expect(postListPostItemPreHeaderText).toHaveText(pinnedText);
|
||||||
|
|
||||||
|
|
@ -77,7 +78,7 @@ describe('Messaging - Pin and Unpin Message', () => {
|
||||||
await PostOptionsScreen.unpinPostOption.tap();
|
await PostOptionsScreen.unpinPostOption.tap();
|
||||||
|
|
||||||
// * Verify pinned text is not displayed on the post pre-header
|
// * Verify pinned text is not displayed on the post pre-header
|
||||||
await wait(timeouts.TEN_SEC);
|
await wait(timeouts.TWO_SEC);
|
||||||
await expect(postListPostItemPreHeaderText).not.toBeVisible();
|
await expect(postListPostItemPreHeaderText).not.toBeVisible();
|
||||||
|
|
||||||
// # Go back to channel list screen
|
// # Go back to channel list screen
|
||||||
|
|
@ -89,14 +90,19 @@ describe('Messaging - Pin and Unpin Message', () => {
|
||||||
const message = `Message ${getRandomId()}`;
|
const message = `Message ${getRandomId()}`;
|
||||||
await ChannelScreen.open(channelsCategory, testChannel.name);
|
await ChannelScreen.open(channelsCategory, testChannel.name);
|
||||||
await ChannelScreen.postMessage(message);
|
await ChannelScreen.postMessage(message);
|
||||||
|
await ChannelScreen.dismissKeyboard();
|
||||||
const {post} = await Post.apiGetLastPostInChannel(siteOneUrl, testChannel.id);
|
const {post} = await Post.apiGetLastPostInChannel(siteOneUrl, testChannel.id);
|
||||||
const {postListPostItem} = ChannelScreen.getPostListPostItem(post.id, message);
|
const {postListPostItem} = ChannelScreen.getPostListPostItem(post.id, message);
|
||||||
|
await expect(postListPostItem).toBeVisible();
|
||||||
|
|
||||||
await postListPostItem.tap();
|
await postListPostItem.tap();
|
||||||
|
await wait(timeouts.TWO_SEC);
|
||||||
|
await ThreadScreen.toBeVisible();
|
||||||
await ThreadScreen.openPostOptionsFor(post.id, message);
|
await ThreadScreen.openPostOptionsFor(post.id, message);
|
||||||
await PostOptionsScreen.pinPostOption.tap();
|
await PostOptionsScreen.pinPostOption.tap();
|
||||||
|
|
||||||
// * Verify pinned text is displayed on the post pre-header
|
// * Verify pinned text is displayed on the post pre-header
|
||||||
await wait(timeouts.TEN_SEC);
|
await wait(timeouts.TWO_SEC);
|
||||||
const {postListPostItemPreHeaderText} = ThreadScreen.getPostListPostItem(post.id, message);
|
const {postListPostItemPreHeaderText} = ThreadScreen.getPostListPostItem(post.id, message);
|
||||||
await expect(postListPostItemPreHeaderText).toHaveText(pinnedText);
|
await expect(postListPostItemPreHeaderText).toHaveText(pinnedText);
|
||||||
|
|
||||||
|
|
@ -105,7 +111,7 @@ describe('Messaging - Pin and Unpin Message', () => {
|
||||||
await PostOptionsScreen.unpinPostOption.tap();
|
await PostOptionsScreen.unpinPostOption.tap();
|
||||||
|
|
||||||
// * Verify pinned text is not displayed on the post pre-header
|
// * Verify pinned text is not displayed on the post pre-header
|
||||||
await wait(timeouts.TEN_SEC);
|
await wait(timeouts.TWO_SEC);
|
||||||
await expect(postListPostItemPreHeaderText).not.toBeVisible();
|
await expect(postListPostItemPreHeaderText).not.toBeVisible();
|
||||||
|
|
||||||
// # Go back to channel list screen
|
// # Go back to channel list screen
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,7 @@ import {
|
||||||
ThreadScreen,
|
ThreadScreen,
|
||||||
} from '@support/ui/screen';
|
} from '@support/ui/screen';
|
||||||
import {getRandomId, timeouts, wait} from '@support/utils';
|
import {getRandomId, timeouts, wait} from '@support/utils';
|
||||||
import {expect} from 'detox';
|
import {expect, waitFor} from 'detox';
|
||||||
|
|
||||||
describe('Messaging - Save and Unsave Message', () => {
|
describe('Messaging - Save and Unsave Message', () => {
|
||||||
const serverOneDisplayName = 'Server 1';
|
const serverOneDisplayName = 'Server 1';
|
||||||
|
|
@ -57,11 +57,12 @@ describe('Messaging - Save and Unsave Message', () => {
|
||||||
const message = `Message ${getRandomId()}`;
|
const message = `Message ${getRandomId()}`;
|
||||||
await ChannelScreen.open(channelsCategory, testChannel.name);
|
await ChannelScreen.open(channelsCategory, testChannel.name);
|
||||||
await ChannelScreen.postMessage(message);
|
await ChannelScreen.postMessage(message);
|
||||||
|
await ChannelScreen.dismissKeyboard();
|
||||||
|
|
||||||
// * Verify message is posted
|
// * Verify message is posted
|
||||||
const {post} = await Post.apiGetLastPostInChannel(siteOneUrl, testChannel.id);
|
const {post} = await Post.apiGetLastPostInChannel(siteOneUrl, testChannel.id);
|
||||||
const {postListPostItem} = ChannelScreen.getPostListPostItem(post.id, message);
|
const {postListPostItem} = ChannelScreen.getPostListPostItem(post.id, message);
|
||||||
await expect(postListPostItem).toBeVisible();
|
await waitFor(postListPostItem).toBeVisible().withTimeout(timeouts.FOUR_SEC);
|
||||||
|
|
||||||
// # Open post options for message and tap on save option
|
// # Open post options for message and tap on save option
|
||||||
await ChannelScreen.openPostOptionsFor(post.id, message);
|
await ChannelScreen.openPostOptionsFor(post.id, message);
|
||||||
|
|
@ -89,8 +90,11 @@ describe('Messaging - Save and Unsave Message', () => {
|
||||||
const message = `Message ${getRandomId()}`;
|
const message = `Message ${getRandomId()}`;
|
||||||
await ChannelScreen.open(channelsCategory, testChannel.name);
|
await ChannelScreen.open(channelsCategory, testChannel.name);
|
||||||
await ChannelScreen.postMessage(message);
|
await ChannelScreen.postMessage(message);
|
||||||
|
await ChannelScreen.dismissKeyboard();
|
||||||
|
|
||||||
const {post} = await Post.apiGetLastPostInChannel(siteOneUrl, testChannel.id);
|
const {post} = await Post.apiGetLastPostInChannel(siteOneUrl, testChannel.id);
|
||||||
const {postListPostItem} = ChannelScreen.getPostListPostItem(post.id, message);
|
const {postListPostItem} = ChannelScreen.getPostListPostItem(post.id, message);
|
||||||
|
await waitFor(postListPostItem).toBeVisible().withTimeout(timeouts.FOUR_SEC);
|
||||||
await postListPostItem.tap();
|
await postListPostItem.tap();
|
||||||
await ThreadScreen.openPostOptionsFor(post.id, message);
|
await ThreadScreen.openPostOptionsFor(post.id, message);
|
||||||
await PostOptionsScreen.savePostOption.tap();
|
await PostOptionsScreen.savePostOption.tap();
|
||||||
|
|
|
||||||
|
|
@ -32,8 +32,8 @@ import {expect} from 'detox';
|
||||||
|
|
||||||
describe('Search - Cross Team Search', () => {
|
describe('Search - Cross Team Search', () => {
|
||||||
const serverOneDisplayName = 'Server 1';
|
const serverOneDisplayName = 'Server 1';
|
||||||
const channelsCategory = 'channels';
|
|
||||||
const searchTerm = 'Horses are fun';
|
const searchTerm = 'Horses are fun';
|
||||||
|
const channelsCategory = 'channels';
|
||||||
let testUser: any;
|
let testUser: any;
|
||||||
let teamOpen: any;
|
let teamOpen: any;
|
||||||
let teamRainforest: any;
|
let teamRainforest: any;
|
||||||
|
|
|
||||||
|
|
@ -73,7 +73,12 @@ describe('Search - Pinned Messages', () => {
|
||||||
const message = `Message ${getRandomId()}`;
|
const message = `Message ${getRandomId()}`;
|
||||||
await ChannelScreen.open(channelsCategory, testChannel.name);
|
await ChannelScreen.open(channelsCategory, testChannel.name);
|
||||||
await ChannelScreen.postMessage(message);
|
await ChannelScreen.postMessage(message);
|
||||||
|
await ChannelScreen.dismissKeyboard();
|
||||||
|
|
||||||
const {post} = await Post.apiGetLastPostInChannel(siteOneUrl, testChannel.id);
|
const {post} = await Post.apiGetLastPostInChannel(siteOneUrl, testChannel.id);
|
||||||
|
const {postListPostItem: channelPostItem} = ChannelScreen.getPostListPostItem(post.id, message);
|
||||||
|
await expect(channelPostItem).toBeVisible();
|
||||||
|
|
||||||
await ChannelScreen.openPostOptionsFor(post.id, message);
|
await ChannelScreen.openPostOptionsFor(post.id, message);
|
||||||
await PostOptionsScreen.pinPostOption.tap();
|
await PostOptionsScreen.pinPostOption.tap();
|
||||||
|
|
||||||
|
|
@ -110,7 +115,12 @@ describe('Search - Pinned Messages', () => {
|
||||||
const message = `Message ${getRandomId()}`;
|
const message = `Message ${getRandomId()}`;
|
||||||
await ChannelScreen.open(channelsCategory, testChannel.name);
|
await ChannelScreen.open(channelsCategory, testChannel.name);
|
||||||
await ChannelScreen.postMessage(message);
|
await ChannelScreen.postMessage(message);
|
||||||
|
await ChannelScreen.dismissKeyboard();
|
||||||
|
|
||||||
const {post: pinnedPost} = await Post.apiGetLastPostInChannel(siteOneUrl, testChannel.id);
|
const {post: pinnedPost} = await Post.apiGetLastPostInChannel(siteOneUrl, testChannel.id);
|
||||||
|
const {postListPostItem: channelPostItem} = ChannelScreen.getPostListPostItem(pinnedPost.id, message);
|
||||||
|
await expect(channelPostItem).toBeVisible();
|
||||||
|
|
||||||
await ChannelScreen.openPostOptionsFor(pinnedPost.id, message);
|
await ChannelScreen.openPostOptionsFor(pinnedPost.id, message);
|
||||||
await PostOptionsScreen.pinPostOption.tap();
|
await PostOptionsScreen.pinPostOption.tap();
|
||||||
await ChannelInfoScreen.open();
|
await ChannelInfoScreen.open();
|
||||||
|
|
@ -146,6 +156,7 @@ describe('Search - Pinned Messages', () => {
|
||||||
// # Post a reply
|
// # Post a reply
|
||||||
const replyMessage = `${updatedMessage} reply`;
|
const replyMessage = `${updatedMessage} reply`;
|
||||||
await ThreadScreen.postMessage(replyMessage);
|
await ThreadScreen.postMessage(replyMessage);
|
||||||
|
await ChannelScreen.dismissKeyboard();
|
||||||
|
|
||||||
// * Verify reply is posted
|
// * Verify reply is posted
|
||||||
const {post: replyPost} = await Post.apiGetLastPostInChannel(siteOneUrl, testChannel.id);
|
const {post: replyPost} = await Post.apiGetLastPostInChannel(siteOneUrl, testChannel.id);
|
||||||
|
|
@ -178,7 +189,12 @@ describe('Search - Pinned Messages', () => {
|
||||||
const message = `Message ${getRandomId()}`;
|
const message = `Message ${getRandomId()}`;
|
||||||
await ChannelScreen.open(channelsCategory, testChannel.name);
|
await ChannelScreen.open(channelsCategory, testChannel.name);
|
||||||
await ChannelScreen.postMessage(message);
|
await ChannelScreen.postMessage(message);
|
||||||
|
await ChannelScreen.dismissKeyboard();
|
||||||
|
|
||||||
const {post: pinnedPost} = await Post.apiGetLastPostInChannel(siteOneUrl, testChannel.id);
|
const {post: pinnedPost} = await Post.apiGetLastPostInChannel(siteOneUrl, testChannel.id);
|
||||||
|
const {postListPostItem: channelPostItem} = ChannelScreen.getPostListPostItem(pinnedPost.id, message);
|
||||||
|
await expect(channelPostItem).toBeVisible();
|
||||||
|
|
||||||
await ChannelScreen.openPostOptionsFor(pinnedPost.id, message);
|
await ChannelScreen.openPostOptionsFor(pinnedPost.id, message);
|
||||||
await PostOptionsScreen.pinPostOption.tap();
|
await PostOptionsScreen.pinPostOption.tap();
|
||||||
await ChannelInfoScreen.open();
|
await ChannelInfoScreen.open();
|
||||||
|
|
@ -207,7 +223,12 @@ describe('Search - Pinned Messages', () => {
|
||||||
const message = `Message ${getRandomId()}`;
|
const message = `Message ${getRandomId()}`;
|
||||||
await ChannelScreen.open(channelsCategory, testChannel.name);
|
await ChannelScreen.open(channelsCategory, testChannel.name);
|
||||||
await ChannelScreen.postMessage(message);
|
await ChannelScreen.postMessage(message);
|
||||||
|
await ChannelScreen.dismissKeyboard();
|
||||||
|
|
||||||
const {post: pinnedPost} = await Post.apiGetLastPostInChannel(siteOneUrl, testChannel.id);
|
const {post: pinnedPost} = await Post.apiGetLastPostInChannel(siteOneUrl, testChannel.id);
|
||||||
|
const {postListPostItem: channelPostItem} = ChannelScreen.getPostListPostItem(pinnedPost.id, message);
|
||||||
|
await expect(channelPostItem).toBeVisible();
|
||||||
|
|
||||||
await ChannelScreen.openPostOptionsFor(pinnedPost.id, message);
|
await ChannelScreen.openPostOptionsFor(pinnedPost.id, message);
|
||||||
await PostOptionsScreen.pinPostOption.tap();
|
await PostOptionsScreen.pinPostOption.tap();
|
||||||
await ChannelInfoScreen.open();
|
await ChannelInfoScreen.open();
|
||||||
|
|
@ -239,6 +260,7 @@ describe('Search - Pinned Messages', () => {
|
||||||
await ChannelInfoScreen.close();
|
await ChannelInfoScreen.close();
|
||||||
await ChannelScreen.back();
|
await ChannelScreen.back();
|
||||||
await SavedMessagesScreen.open();
|
await SavedMessagesScreen.open();
|
||||||
|
await wait(timeouts.TWO_SEC);
|
||||||
|
|
||||||
// * Verify pinned message is not displayed anymore on saved messages screen
|
// * Verify pinned message is not displayed anymore on saved messages screen
|
||||||
await expect(postListPostItem).not.toExist();
|
await expect(postListPostItem).not.toExist();
|
||||||
|
|
|
||||||
|
|
@ -29,8 +29,8 @@ import {
|
||||||
ServerScreen,
|
ServerScreen,
|
||||||
ThreadScreen,
|
ThreadScreen,
|
||||||
} from '@support/ui/screen';
|
} from '@support/ui/screen';
|
||||||
import {getRandomId, timeouts} from '@support/utils';
|
import {getRandomId, timeouts, wait, waitForElementToBeVisible} from '@support/utils';
|
||||||
import {expect} from 'detox';
|
import {expect, waitFor} from 'detox';
|
||||||
|
|
||||||
describe('Search - Saved Messages', () => {
|
describe('Search - Saved Messages', () => {
|
||||||
const serverOneDisplayName = 'Server 1';
|
const serverOneDisplayName = 'Server 1';
|
||||||
|
|
@ -78,6 +78,7 @@ describe('Search - Saved Messages', () => {
|
||||||
const message = `Message ${getRandomId()}`;
|
const message = `Message ${getRandomId()}`;
|
||||||
await ChannelScreen.open(channelsCategory, testChannel.name);
|
await ChannelScreen.open(channelsCategory, testChannel.name);
|
||||||
await ChannelScreen.postMessage(message);
|
await ChannelScreen.postMessage(message);
|
||||||
|
|
||||||
const {post} = await Post.apiGetLastPostInChannel(siteOneUrl, testChannel.id);
|
const {post} = await Post.apiGetLastPostInChannel(siteOneUrl, testChannel.id);
|
||||||
await ChannelScreen.openPostOptionsFor(post.id, message);
|
await ChannelScreen.openPostOptionsFor(post.id, message);
|
||||||
await PostOptionsScreen.savePostOption.tap();
|
await PostOptionsScreen.savePostOption.tap();
|
||||||
|
|
@ -116,9 +117,11 @@ describe('Search - Saved Messages', () => {
|
||||||
const message = `Message ${getRandomId()}`;
|
const message = `Message ${getRandomId()}`;
|
||||||
await ChannelScreen.open(channelsCategory, testChannel.name);
|
await ChannelScreen.open(channelsCategory, testChannel.name);
|
||||||
await ChannelScreen.postMessage(message);
|
await ChannelScreen.postMessage(message);
|
||||||
|
|
||||||
const {post: savedPost} = await Post.apiGetLastPostInChannel(siteOneUrl, testChannel.id);
|
const {post: savedPost} = await Post.apiGetLastPostInChannel(siteOneUrl, testChannel.id);
|
||||||
await ChannelScreen.openPostOptionsFor(savedPost.id, message);
|
await ChannelScreen.openPostOptionsFor(savedPost.id, message);
|
||||||
await PostOptionsScreen.savePostOption.tap();
|
await PostOptionsScreen.savePostOption.tap();
|
||||||
|
await wait(timeouts.TWO_SEC);
|
||||||
await ChannelScreen.back();
|
await ChannelScreen.back();
|
||||||
await SavedMessagesScreen.open();
|
await SavedMessagesScreen.open();
|
||||||
|
|
||||||
|
|
@ -154,7 +157,7 @@ describe('Search - Saved Messages', () => {
|
||||||
// * Verify reply is posted
|
// * Verify reply is posted
|
||||||
const {post: replyPost} = await Post.apiGetLastPostInChannel(siteOneUrl, testChannel.id);
|
const {post: replyPost} = await Post.apiGetLastPostInChannel(siteOneUrl, testChannel.id);
|
||||||
const {postListPostItem: replyPostListPostItem} = ThreadScreen.getPostListPostItem(replyPost.id, replyMessage);
|
const {postListPostItem: replyPostListPostItem} = ThreadScreen.getPostListPostItem(replyPost.id, replyMessage);
|
||||||
await expect(replyPostListPostItem).toBeVisible();
|
await waitFor(replyPostListPostItem).toBeVisible().withTimeout(timeouts.FOUR_SEC);
|
||||||
|
|
||||||
// # Go back to saved messages screen
|
// # Go back to saved messages screen
|
||||||
await ThreadScreen.back();
|
await ThreadScreen.back();
|
||||||
|
|
@ -180,7 +183,10 @@ describe('Search - Saved Messages', () => {
|
||||||
const message = `Message ${getRandomId()}`;
|
const message = `Message ${getRandomId()}`;
|
||||||
await ChannelScreen.open(channelsCategory, testChannel.name);
|
await ChannelScreen.open(channelsCategory, testChannel.name);
|
||||||
await ChannelScreen.postMessage(message);
|
await ChannelScreen.postMessage(message);
|
||||||
|
|
||||||
const {post: savedPost} = await Post.apiGetLastPostInChannel(siteOneUrl, testChannel.id);
|
const {post: savedPost} = await Post.apiGetLastPostInChannel(siteOneUrl, testChannel.id);
|
||||||
|
const {postListPostItem: channelPostListPostItem} = ChannelScreen.getPostListPostItem(savedPost.id, message);
|
||||||
|
await waitForElementToBeVisible(channelPostListPostItem);
|
||||||
await ChannelScreen.openPostOptionsFor(savedPost.id, message);
|
await ChannelScreen.openPostOptionsFor(savedPost.id, message);
|
||||||
await PostOptionsScreen.savePostOption.tap();
|
await PostOptionsScreen.savePostOption.tap();
|
||||||
await ChannelScreen.back();
|
await ChannelScreen.back();
|
||||||
|
|
@ -207,7 +213,10 @@ describe('Search - Saved Messages', () => {
|
||||||
const message = `Message ${getRandomId()}`;
|
const message = `Message ${getRandomId()}`;
|
||||||
await ChannelScreen.open(channelsCategory, testChannel.name);
|
await ChannelScreen.open(channelsCategory, testChannel.name);
|
||||||
await ChannelScreen.postMessage(message);
|
await ChannelScreen.postMessage(message);
|
||||||
|
|
||||||
const {post: savedPost} = await Post.apiGetLastPostInChannel(siteOneUrl, testChannel.id);
|
const {post: savedPost} = await Post.apiGetLastPostInChannel(siteOneUrl, testChannel.id);
|
||||||
|
const {postListPostItem: channelPostListPostItem} = ChannelScreen.getPostListPostItem(savedPost.id, message);
|
||||||
|
await waitForElementToBeVisible(channelPostListPostItem);
|
||||||
await ChannelScreen.openPostOptionsFor(savedPost.id, message);
|
await ChannelScreen.openPostOptionsFor(savedPost.id, message);
|
||||||
await PostOptionsScreen.savePostOption.tap();
|
await PostOptionsScreen.savePostOption.tap();
|
||||||
await ChannelScreen.back();
|
await ChannelScreen.back();
|
||||||
|
|
|
||||||
|
|
@ -195,9 +195,6 @@ describe('Server Login - Server List', () => {
|
||||||
// # Enter the same first server display name
|
// # Enter the same first server display name
|
||||||
await EditServerScreen.serverDisplayNameInput.replaceText(serverOneDisplayName);
|
await EditServerScreen.serverDisplayNameInput.replaceText(serverOneDisplayName);
|
||||||
|
|
||||||
// * Verify save button is disabled
|
|
||||||
await expect(EditServerScreen.saveButtonDisabled).toBeVisible();
|
|
||||||
|
|
||||||
// # Enter a new first server display name
|
// # Enter a new first server display name
|
||||||
const newServerOneDisplayName = `${serverOneDisplayName} new`;
|
const newServerOneDisplayName = `${serverOneDisplayName} new`;
|
||||||
await EditServerScreen.serverDisplayNameInput.replaceText(newServerOneDisplayName);
|
await EditServerScreen.serverDisplayNameInput.replaceText(newServerOneDisplayName);
|
||||||
|
|
|
||||||
|
|
@ -75,6 +75,7 @@ describe('Smoke Test - Account', () => {
|
||||||
await wait(timeouts.ONE_SEC);
|
await wait(timeouts.ONE_SEC);
|
||||||
await CustomStatusScreen.openEmojiPicker('default', true);
|
await CustomStatusScreen.openEmojiPicker('default', true);
|
||||||
await EmojiPickerScreen.searchInput.replaceText(customStatusEmojiName);
|
await EmojiPickerScreen.searchInput.replaceText(customStatusEmojiName);
|
||||||
|
await EmojiPickerScreen.searchInput.tapReturnKey();
|
||||||
await element(by.text('🤡')).tap();
|
await element(by.text('🤡')).tap();
|
||||||
await wait(timeouts.ONE_SEC);
|
await wait(timeouts.ONE_SEC);
|
||||||
await CustomStatusScreen.statusInput.replaceText(customStatusText);
|
await CustomStatusScreen.statusInput.replaceText(customStatusText);
|
||||||
|
|
|
||||||
|
|
@ -66,15 +66,12 @@ describe('Smoke Test - Autocomplete', () => {
|
||||||
await ChannelScreen.postInput.typeText('@');
|
await ChannelScreen.postInput.typeText('@');
|
||||||
await Autocomplete.toBeVisible();
|
await Autocomplete.toBeVisible();
|
||||||
|
|
||||||
// * Verify at-mention list is displayed
|
|
||||||
await expect(Autocomplete.sectionAtMentionList).toBeVisible();
|
|
||||||
|
|
||||||
// # Type in username
|
// # Type in username
|
||||||
await ChannelScreen.postInput.typeText(testUser.username);
|
await ChannelScreen.postInput.typeText(testUser.username);
|
||||||
|
|
||||||
// * Verify at-mention autocomplete contains associated user suggestion
|
// * Verify at-mention autocomplete contains associated user suggestion
|
||||||
const {atMentionItem} = Autocomplete.getAtMentionItem(testUser.id);
|
const {atMentionItem} = Autocomplete.getAtMentionItem(testUser.id);
|
||||||
await expect(atMentionItem).toBeVisible();
|
await expect(atMentionItem).toExist();
|
||||||
|
|
||||||
// # Select and post at-mention suggestion
|
// # Select and post at-mention suggestion
|
||||||
await atMentionItem.tap();
|
await atMentionItem.tap();
|
||||||
|
|
@ -90,15 +87,12 @@ describe('Smoke Test - Autocomplete', () => {
|
||||||
await ChannelScreen.postInput.typeText('~');
|
await ChannelScreen.postInput.typeText('~');
|
||||||
await Autocomplete.toBeVisible();
|
await Autocomplete.toBeVisible();
|
||||||
|
|
||||||
// * Verify channel mention list is displayed
|
|
||||||
await expect(Autocomplete.sectionChannelMentionList).toBeVisible();
|
|
||||||
|
|
||||||
// # Type in channel name
|
// # Type in channel name
|
||||||
await ChannelScreen.postInput.typeText(testChannel.name);
|
await ChannelScreen.postInput.typeText(testChannel.name);
|
||||||
|
|
||||||
// * Verify channel mention autocomplete contains associated channel suggestion
|
// * Verify channel mention autocomplete contains associated channel suggestion
|
||||||
const {channelMentionItem} = Autocomplete.getChannelMentionItem(testChannel.name);
|
const {channelMentionItem} = Autocomplete.getChannelMentionItem(testChannel.name);
|
||||||
await expect(channelMentionItem).toBeVisible();
|
await expect(channelMentionItem).toExist();
|
||||||
|
|
||||||
// # Select and post channel mention suggestion
|
// # Select and post channel mention suggestion
|
||||||
await channelMentionItem.tap();
|
await channelMentionItem.tap();
|
||||||
|
|
@ -117,15 +111,12 @@ describe('Smoke Test - Autocomplete', () => {
|
||||||
await ChannelScreen.postInput.typeText(`:${emojiNameFirst2Chars}`);
|
await ChannelScreen.postInput.typeText(`:${emojiNameFirst2Chars}`);
|
||||||
await Autocomplete.toBeVisible();
|
await Autocomplete.toBeVisible();
|
||||||
|
|
||||||
// * Verify emoji suggestion list is displayed
|
|
||||||
await expect(Autocomplete.flatEmojiSuggestionList).toBeVisible();
|
|
||||||
|
|
||||||
// # Type in 3rd to last characters of emoji name
|
// # Type in 3rd to last characters of emoji name
|
||||||
await ChannelScreen.postInput.typeText(emojiName3rdToLastChars);
|
await ChannelScreen.postInput.typeText(emojiName3rdToLastChars);
|
||||||
|
|
||||||
// * Verify emoji suggestion autocomplete contains associated emoji suggestion
|
// * Verify emoji suggestion autocomplete contains associated emoji suggestion
|
||||||
const {emojiSuggestionItem} = Autocomplete.getEmojiSuggestionItem(emojiName);
|
const {emojiSuggestionItem} = Autocomplete.getEmojiSuggestionItem(emojiName);
|
||||||
await expect(emojiSuggestionItem).toBeVisible();
|
await expect(emojiSuggestionItem).toExist();
|
||||||
|
|
||||||
// # Select and post emoji suggestion
|
// # Select and post emoji suggestion
|
||||||
await emojiSuggestionItem.tap();
|
await emojiSuggestionItem.tap();
|
||||||
|
|
@ -141,16 +132,13 @@ describe('Smoke Test - Autocomplete', () => {
|
||||||
await ChannelScreen.postInput.typeText('/');
|
await ChannelScreen.postInput.typeText('/');
|
||||||
await Autocomplete.toBeVisible();
|
await Autocomplete.toBeVisible();
|
||||||
|
|
||||||
// * Verify slash suggestion list is displayed
|
|
||||||
await expect(Autocomplete.flatSlashSuggestionList).toBeVisible();
|
|
||||||
|
|
||||||
// # Type in slash command name
|
// # Type in slash command name
|
||||||
const slashCommand = 'away';
|
const slashCommand = 'away';
|
||||||
await ChannelScreen.postInput.typeText(slashCommand);
|
await ChannelScreen.postInput.typeText(slashCommand);
|
||||||
|
|
||||||
// * Verify slash suggestion autocomplete contains associated slash command suggestion
|
// * Verify slash suggestion autocomplete contains associated slash command suggestion
|
||||||
const {slashSuggestionItem} = Autocomplete.getSlashSuggestionItem(slashCommand);
|
const {slashSuggestionItem} = Autocomplete.getSlashSuggestionItem(slashCommand);
|
||||||
await expect(slashSuggestionItem).toBeVisible();
|
await expect(slashSuggestionItem).toExist();
|
||||||
|
|
||||||
// # Select and post slash suggestion
|
// # Select and post slash suggestion
|
||||||
await slashSuggestionItem.tap();
|
await slashSuggestionItem.tap();
|
||||||
|
|
|
||||||
|
|
@ -172,6 +172,7 @@ describe('Smoke Test - Channels', () => {
|
||||||
await ChannelInfoScreen.open();
|
await ChannelInfoScreen.open();
|
||||||
await ChannelInfoScreen.favoriteAction.tap();
|
await ChannelInfoScreen.favoriteAction.tap();
|
||||||
await ChannelInfoScreen.muteAction.tap();
|
await ChannelInfoScreen.muteAction.tap();
|
||||||
|
await wait(timeouts.TWO_SEC);
|
||||||
|
|
||||||
// * Verify channel is favorited and muted
|
// * Verify channel is favorited and muted
|
||||||
await expect(ChannelInfoScreen.unfavoriteAction).toBeVisible();
|
await expect(ChannelInfoScreen.unfavoriteAction).toBeVisible();
|
||||||
|
|
@ -180,6 +181,7 @@ describe('Smoke Test - Channels', () => {
|
||||||
// # Tap on favorited action to unfavorite the channel and tap on muted action to unmute the channel
|
// # Tap on favorited action to unfavorite the channel and tap on muted action to unmute the channel
|
||||||
await ChannelInfoScreen.unfavoriteAction.tap();
|
await ChannelInfoScreen.unfavoriteAction.tap();
|
||||||
await ChannelInfoScreen.unmuteAction.tap();
|
await ChannelInfoScreen.unmuteAction.tap();
|
||||||
|
await wait(timeouts.TWO_SEC);
|
||||||
|
|
||||||
// * Verify channel is unfavorited and unmuted
|
// * Verify channel is unfavorited and unmuted
|
||||||
await expect(ChannelInfoScreen.favoriteAction).toBeVisible();
|
await expect(ChannelInfoScreen.favoriteAction).toBeVisible();
|
||||||
|
|
@ -199,9 +201,5 @@ describe('Smoke Test - Channels', () => {
|
||||||
await ChannelScreen.open(channelsCategory, channel.name);
|
await ChannelScreen.open(channelsCategory, channel.name);
|
||||||
await ChannelInfoScreen.open();
|
await ChannelInfoScreen.open();
|
||||||
await ChannelInfoScreen.archivePublicChannel({confirm: true});
|
await ChannelInfoScreen.archivePublicChannel({confirm: true});
|
||||||
|
|
||||||
// * Verify on channel screen and post draft archived message is displayed
|
|
||||||
await waitFor(ChannelListScreen.channelListScreen).toBeVisible().withTimeout(timeouts.TEN_SEC);
|
|
||||||
await expect(ChannelListScreen.getChannelItem(channelsCategory, channel.name)).not.toExist();
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,7 @@ import {
|
||||||
ServerScreen,
|
ServerScreen,
|
||||||
ThreadScreen,
|
ThreadScreen,
|
||||||
} from '@support/ui/screen';
|
} from '@support/ui/screen';
|
||||||
import {getRandomId, timeouts, wait} from '@support/utils';
|
import {getRandomId, timeouts} from '@support/utils';
|
||||||
import {expect} from 'detox';
|
import {expect} from 'detox';
|
||||||
|
|
||||||
describe('Smoke Test - Messaging', () => {
|
describe('Smoke Test - Messaging', () => {
|
||||||
|
|
@ -64,6 +64,7 @@ describe('Smoke Test - Messaging', () => {
|
||||||
// # Open a channel screen and post a message
|
// # Open a channel screen and post a message
|
||||||
const message = `Message ${getRandomId()}`;
|
const message = `Message ${getRandomId()}`;
|
||||||
await ChannelScreen.open(channelsCategory, testChannel.name);
|
await ChannelScreen.open(channelsCategory, testChannel.name);
|
||||||
|
await ChannelScreen.dismissScheduledPostTooltip();
|
||||||
await ChannelScreen.postMessage(message);
|
await ChannelScreen.postMessage(message);
|
||||||
|
|
||||||
// * Verify message is added to post list
|
// * Verify message is added to post list
|
||||||
|
|
@ -146,6 +147,7 @@ describe('Smoke Test - Messaging', () => {
|
||||||
await element(by.id(`channel.post_list.post.${post.id}`)).longPress();
|
await element(by.id(`channel.post_list.post.${post.id}`)).longPress();
|
||||||
await EmojiPickerScreen.open(true);
|
await EmojiPickerScreen.open(true);
|
||||||
await EmojiPickerScreen.searchInput.replaceText('clown_face');
|
await EmojiPickerScreen.searchInput.replaceText('clown_face');
|
||||||
|
await EmojiPickerScreen.searchInput.tapReturnKey();
|
||||||
await element(by.text('🤡')).tap();
|
await element(by.text('🤡')).tap();
|
||||||
|
|
||||||
// * Verify reaction is added to the message
|
// * Verify reaction is added to the message
|
||||||
|
|
@ -161,54 +163,55 @@ describe('Smoke Test - Messaging', () => {
|
||||||
await ChannelScreen.open(channelsCategory, testChannel.name);
|
await ChannelScreen.open(channelsCategory, testChannel.name);
|
||||||
await ChannelScreen.postMessage(message);
|
await ChannelScreen.postMessage(message);
|
||||||
const {post} = await Post.apiGetLastPostInChannel(siteOneUrl, testChannel.id);
|
const {post} = await Post.apiGetLastPostInChannel(siteOneUrl, testChannel.id);
|
||||||
await element(by.id(`channel.post_list.post.${post.id}`)).longPress();
|
await ChannelScreen.openPostOptionsFor(post.id, message);
|
||||||
await PostOptionsScreen.followThreadOption.tap();
|
await PostOptionsScreen.followThreadOption.tap();
|
||||||
|
|
||||||
// * Verify message is followed by user via post footer
|
// * Verify post options closed and message is followed by user via post footer
|
||||||
|
await waitFor(PostOptionsScreen.postOptionsScreen).not.toBeVisible().withTimeout(timeouts.FOUR_SEC);
|
||||||
const {postListPostItem, postListPostItemFooterFollowingButton} = ChannelScreen.getPostListPostItem(post.id, message);
|
const {postListPostItem, postListPostItemFooterFollowingButton} = ChannelScreen.getPostListPostItem(post.id, message);
|
||||||
await waitFor(postListPostItemFooterFollowingButton).toBeVisible().withTimeout(timeouts.TWO_SEC);
|
await waitFor(postListPostItemFooterFollowingButton).toExist().withTimeout(timeouts.FOUR_SEC);
|
||||||
|
|
||||||
// # Tap on following button via post footer
|
// # Tap on following button via post footer to unfollow
|
||||||
await postListPostItemFooterFollowingButton.tap();
|
await postListPostItemFooterFollowingButton.tap();
|
||||||
await wait(timeouts.FOUR_SEC);
|
|
||||||
|
|
||||||
// * Verify message is not followed by user via post footer
|
// * Verify message is not followed by user via post footer
|
||||||
await expect(postListPostItemFooterFollowingButton).not.toBeVisible();
|
await waitFor(postListPostItemFooterFollowingButton).not.toExist().withTimeout(timeouts.FOUR_SEC);
|
||||||
|
|
||||||
// # Open post options for message and tap on save option
|
// # Open post options for message and tap on save option
|
||||||
await element(by.id(`channel.post_list.post.${post.id}`)).longPress();
|
await ChannelScreen.openPostOptionsFor(post.id, message);
|
||||||
await PostOptionsScreen.savePostOption.tap();
|
await PostOptionsScreen.savePostOption.tap();
|
||||||
|
|
||||||
// * Verify saved text is displayed on the post pre-header
|
// * Verify post options closed and saved text is displayed on the post pre-header
|
||||||
await wait(timeouts.ONE_SEC);
|
await waitFor(PostOptionsScreen.postOptionsScreen).not.toBeVisible().withTimeout(timeouts.FOUR_SEC);
|
||||||
const {postListPostItemPreHeaderText: channelPostListPostItemPreHeaderText} = ChannelScreen.getPostListPostItem(post.id, message);
|
const {postListPostItemPreHeaderText: channelPostListPostItemPreHeaderText} = ChannelScreen.getPostListPostItem(post.id, message);
|
||||||
await expect(channelPostListPostItemPreHeaderText).toHaveText(savedText);
|
await waitFor(channelPostListPostItemPreHeaderText).toHaveText(savedText).withTimeout(timeouts.FOUR_SEC);
|
||||||
|
|
||||||
// # Tap on post to open thread and tap on thread overview unsave button
|
// # Tap on post to open thread and open post options for message
|
||||||
await postListPostItem.tap();
|
await postListPostItem.tap();
|
||||||
await element(by.text(message)).longPress();
|
await ThreadScreen.openPostOptionsFor(post.id, message);
|
||||||
await PostOptionsScreen.unsavePostOption.tap();
|
await PostOptionsScreen.unsavePostOption.tap();
|
||||||
|
|
||||||
// * Verify saved text is not displayed on the post pre-header
|
// * Verify post options closed and saved text is not displayed on the post pre-header
|
||||||
await expect(channelPostListPostItemPreHeaderText).not.toBeVisible();
|
await waitFor(PostOptionsScreen.postOptionsScreen).not.toBeVisible().withTimeout(timeouts.TWO_SEC);
|
||||||
|
await waitFor(channelPostListPostItemPreHeaderText).not.toBeVisible().withTimeout(timeouts.FOUR_SEC);
|
||||||
|
|
||||||
// # Open post options for message and tap on pin to channel option
|
// # Open post options for message and tap on pin to channel option
|
||||||
await ThreadScreen.openPostOptionsFor(post.id, message);
|
await ThreadScreen.openPostOptionsFor(post.id, message);
|
||||||
await PostOptionsScreen.pinPostOption.tap();
|
await PostOptionsScreen.pinPostOption.tap();
|
||||||
|
|
||||||
// * Verify pinned text is displayed on the post pre-header
|
// * Verify post options closed and pinned text is displayed on the post pre-header
|
||||||
await wait(timeouts.ONE_SEC);
|
await waitFor(PostOptionsScreen.postOptionsScreen).not.toBeVisible().withTimeout(timeouts.TWO_SEC);
|
||||||
const {postListPostItemPreHeaderText: threadPostListPostItemPreHeaderText} = ThreadScreen.getPostListPostItem(post.id, message);
|
const {postListPostItemPreHeaderText: threadPostListPostItemPreHeaderText} = ThreadScreen.getPostListPostItem(post.id, message);
|
||||||
await expect(threadPostListPostItemPreHeaderText).toHaveText(pinnedText);
|
await waitFor(threadPostListPostItemPreHeaderText).toHaveText(pinnedText).withTimeout(timeouts.FOUR_SEC);
|
||||||
|
|
||||||
// # Go back to channel, open post options for message, and tap on unpin from channel option
|
// # Go back to channel, open post options for message, and tap on unpin from channel option
|
||||||
await ThreadScreen.back();
|
await ThreadScreen.back();
|
||||||
await element(by.id(`channel.post_list.post.${post.id}`)).longPress();
|
await ChannelScreen.openPostOptionsFor(post.id, message);
|
||||||
await PostOptionsScreen.unpinPostOption.tap();
|
await PostOptionsScreen.unpinPostOption.tap();
|
||||||
|
|
||||||
// * Verify pinned text is not displayed on the post pre-header
|
// * Verify post options closed and pinned text is not displayed on the post pre-header
|
||||||
await wait(timeouts.ONE_SEC);
|
await waitFor(PostOptionsScreen.postOptionsScreen).not.toBeVisible().withTimeout(timeouts.TWO_SEC);
|
||||||
await expect(channelPostListPostItemPreHeaderText).not.toBeVisible();
|
await waitFor(channelPostListPostItemPreHeaderText).not.toBeVisible().withTimeout(timeouts.FOUR_SEC);
|
||||||
|
|
||||||
// # Go back to channel list screen
|
// # Go back to channel list screen
|
||||||
await ChannelScreen.back();
|
await ChannelScreen.back();
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,7 @@ import {
|
||||||
ServerScreen,
|
ServerScreen,
|
||||||
} from '@support/ui/screen';
|
} from '@support/ui/screen';
|
||||||
import {isAndroid, isIos, timeouts, wait} from '@support/utils';
|
import {isAndroid, isIos, timeouts, wait} from '@support/utils';
|
||||||
import {expect} from 'detox';
|
import {expect, waitFor} from 'detox';
|
||||||
|
|
||||||
describe('Smoke Test - Server Login', () => {
|
describe('Smoke Test - Server Login', () => {
|
||||||
const serverOneDisplayName = 'Server 1';
|
const serverOneDisplayName = 'Server 1';
|
||||||
|
|
@ -69,7 +69,8 @@ describe('Smoke Test - Server Login', () => {
|
||||||
await User.apiAdminLogin(siteTwoUrl);
|
await User.apiAdminLogin(siteTwoUrl);
|
||||||
const {user} = await Setup.apiInit(siteTwoUrl);
|
const {user} = await Setup.apiInit(siteTwoUrl);
|
||||||
await ServerListScreen.addServerButton.tap();
|
await ServerListScreen.addServerButton.tap();
|
||||||
await expect(ServerScreen.headerTitleAddServer).toBeVisible(35);
|
await wait(timeouts.ONE_SEC);
|
||||||
|
await waitFor(ServerScreen.headerTitleAddServer).toBeVisible().withTimeout(timeouts.TEN_SEC);
|
||||||
await ServerScreen.connectToServer(serverTwoUrl, serverTwoDisplayName);
|
await ServerScreen.connectToServer(serverTwoUrl, serverTwoDisplayName);
|
||||||
await LoginScreen.login(user);
|
await LoginScreen.login(user);
|
||||||
|
|
||||||
|
|
@ -79,22 +80,28 @@ describe('Smoke Test - Server Login', () => {
|
||||||
|
|
||||||
// # Go back to first server, open server list screen, swipe left on second server and tap on logout option
|
// # Go back to first server, open server list screen, swipe left on second server and tap on logout option
|
||||||
await ServerListScreen.open();
|
await ServerListScreen.open();
|
||||||
|
await wait(timeouts.ONE_SEC);
|
||||||
if (isIos()) {
|
if (isIos()) {
|
||||||
await ServerListScreen.serverListTitle.swipe('up');
|
await ServerListScreen.serverListTitle.swipe('up');
|
||||||
} else if (isAndroid()) {
|
} else if (isAndroid()) {
|
||||||
await ServerListScreen.serverListTitle.swipe('up', 'fast', 0.1, 0.5, 0.3);
|
await ServerListScreen.serverListTitle.swipe('up', 'fast', 0.1, 0.5, 0.3);
|
||||||
}
|
}
|
||||||
|
await wait(timeouts.ONE_SEC);
|
||||||
await waitFor(ServerListScreen.getServerItemInactive(serverOneDisplayName)).toBeVisible().withTimeout(timeouts.TEN_SEC);
|
await waitFor(ServerListScreen.getServerItemInactive(serverOneDisplayName)).toBeVisible().withTimeout(timeouts.TEN_SEC);
|
||||||
await ServerListScreen.getServerItemInactive(serverOneDisplayName).tap();
|
await ServerListScreen.getServerItemInactive(serverOneDisplayName).tap();
|
||||||
|
await wait(timeouts.TWO_SEC);
|
||||||
await ServerListScreen.open();
|
await ServerListScreen.open();
|
||||||
|
await wait(timeouts.ONE_SEC);
|
||||||
if (isIos()) {
|
if (isIos()) {
|
||||||
await ServerListScreen.serverListTitle.swipe('up');
|
await ServerListScreen.serverListTitle.swipe('up');
|
||||||
} else if (isAndroid()) {
|
} else if (isAndroid()) {
|
||||||
await waitFor(ServerListScreen.serverListTitle).toBeVisible().withTimeout(timeouts.TWO_SEC);
|
await waitFor(ServerListScreen.serverListTitle).toBeVisible().withTimeout(timeouts.TWO_SEC);
|
||||||
await ServerListScreen.serverListTitle.swipe('up', 'fast', 0.1, 0.5, 0.3);
|
await ServerListScreen.serverListTitle.swipe('up', 'fast', 0.1, 0.5, 0.3);
|
||||||
}
|
}
|
||||||
|
await wait(timeouts.ONE_SEC);
|
||||||
await waitFor(ServerListScreen.getServerItemInactive(serverTwoDisplayName)).toBeVisible().withTimeout(timeouts.TEN_SEC);
|
await waitFor(ServerListScreen.getServerItemInactive(serverTwoDisplayName)).toBeVisible().withTimeout(timeouts.TEN_SEC);
|
||||||
await ServerListScreen.getServerItemInactive(serverTwoDisplayName).swipe('left');
|
await ServerListScreen.getServerItemInactive(serverTwoDisplayName).swipe('left');
|
||||||
|
await wait(timeouts.ONE_SEC);
|
||||||
await ServerListScreen.getServerItemLogoutOption(serverTwoDisplayName).tap();
|
await ServerListScreen.getServerItemLogoutOption(serverTwoDisplayName).tap();
|
||||||
|
|
||||||
// * Verify logout server alert is displayed
|
// * Verify logout server alert is displayed
|
||||||
|
|
@ -106,6 +113,7 @@ describe('Smoke Test - Server Login', () => {
|
||||||
|
|
||||||
// * Verify second server is logged out
|
// * Verify second server is logged out
|
||||||
await ServerListScreen.getServerItemInactive(serverTwoDisplayName).swipe('left');
|
await ServerListScreen.getServerItemInactive(serverTwoDisplayName).swipe('left');
|
||||||
|
await wait(timeouts.ONE_SEC);
|
||||||
await expect(ServerListScreen.getServerItemLoginOption(serverTwoDisplayName)).toBeVisible();
|
await expect(ServerListScreen.getServerItemLoginOption(serverTwoDisplayName)).toBeVisible();
|
||||||
|
|
||||||
// # Go back to first server
|
// # Go back to first server
|
||||||
|
|
|
||||||
|
|
@ -61,19 +61,25 @@ describe('Smoke Test - Threads', () => {
|
||||||
await waitFor(ChannelScreen.postInput).toBeVisible().withTimeout(timeouts.FOUR_SEC);
|
await waitFor(ChannelScreen.postInput).toBeVisible().withTimeout(timeouts.FOUR_SEC);
|
||||||
await ChannelScreen.postMessage(parentMessage);
|
await ChannelScreen.postMessage(parentMessage);
|
||||||
const {post: parentPost} = await Post.apiGetLastPostInChannel(siteOneUrl, testChannel.id);
|
const {post: parentPost} = await Post.apiGetLastPostInChannel(siteOneUrl, testChannel.id);
|
||||||
|
const {postListPostItem: parentPostItem} = ChannelScreen.getPostListPostItem(parentPost.id, parentMessage);
|
||||||
|
await waitFor(parentPostItem).toBeVisible().withTimeout(timeouts.TEN_SEC);
|
||||||
await ChannelScreen.openReplyThreadFor(parentPost.id, parentMessage);
|
await ChannelScreen.openReplyThreadFor(parentPost.id, parentMessage);
|
||||||
await waitFor(ThreadScreen.postInput).toBeVisible().withTimeout(timeouts.FOUR_SEC);
|
await waitFor(ThreadScreen.postInput).toBeVisible().withTimeout(timeouts.FOUR_SEC);
|
||||||
await ThreadScreen.postMessage(`${parentMessage} reply`);
|
await ThreadScreen.postMessage(`${parentMessage} reply`);
|
||||||
await wait(timeouts.ONE_SEC);
|
|
||||||
|
// * Verify thread is followed by user by default via thread navigation
|
||||||
|
await expect(ThreadScreen.followingButton).toBeVisible();
|
||||||
|
|
||||||
|
// # Unfollow thread via thread navigation
|
||||||
await ThreadScreen.followingButton.tap();
|
await ThreadScreen.followingButton.tap();
|
||||||
await wait(timeouts.FOUR_SEC);
|
await wait(timeouts.TWO_SEC);
|
||||||
|
|
||||||
// * Verify thread is not followed by user via thread navigation
|
// * Verify thread is not followed by user via thread navigation
|
||||||
await expect(ThreadScreen.followButton).toBeVisible();
|
await expect(ThreadScreen.followButton).toBeVisible();
|
||||||
|
|
||||||
// # Follow thread via thread navigation
|
// # Follow thread via thread navigation
|
||||||
await ThreadScreen.followButton.tap();
|
await ThreadScreen.followButton.tap();
|
||||||
await wait(timeouts.FOUR_SEC);
|
await wait(timeouts.TWO_SEC);
|
||||||
|
|
||||||
// * Verify thread is followed by user via thread navigation
|
// * Verify thread is followed by user via thread navigation
|
||||||
await expect(ThreadScreen.followingButton).toBeVisible();
|
await expect(ThreadScreen.followingButton).toBeVisible();
|
||||||
|
|
@ -81,7 +87,9 @@ describe('Smoke Test - Threads', () => {
|
||||||
// # Go back to channel list screen, then go to global threads screen, tap on all your threads button, open thread options for thread, tap on mark as unread option, and tap on unread threads button
|
// # Go back to channel list screen, then go to global threads screen, tap on all your threads button, open thread options for thread, tap on mark as unread option, and tap on unread threads button
|
||||||
await ThreadScreen.back();
|
await ThreadScreen.back();
|
||||||
await ChannelScreen.back();
|
await ChannelScreen.back();
|
||||||
await device.reloadReactNative();
|
|
||||||
|
// Note: Commenting out reloadReactNative as it can cause ANR on Android
|
||||||
|
// await device.reloadReactNative();
|
||||||
await GlobalThreadsScreen.open();
|
await GlobalThreadsScreen.open();
|
||||||
await GlobalThreadsScreen.headerAllThreadsButton.tap();
|
await GlobalThreadsScreen.headerAllThreadsButton.tap();
|
||||||
await GlobalThreadsScreen.openThreadOptionsFor(parentPost.id);
|
await GlobalThreadsScreen.openThreadOptionsFor(parentPost.id);
|
||||||
|
|
@ -118,8 +126,11 @@ describe('Smoke Test - Threads', () => {
|
||||||
// # Create a thread, go back to channel list screen, then go to global threads screen, open thread options for thread, tap on save option, and tap on thread
|
// # Create a thread, go back to channel list screen, then go to global threads screen, open thread options for thread, tap on save option, and tap on thread
|
||||||
const parentMessage = `Message ${getRandomId()}`;
|
const parentMessage = `Message ${getRandomId()}`;
|
||||||
await ChannelScreen.open(channelsCategory, testChannel.name);
|
await ChannelScreen.open(channelsCategory, testChannel.name);
|
||||||
|
await waitFor(ChannelScreen.postInput).toBeVisible().withTimeout(timeouts.FOUR_SEC);
|
||||||
await ChannelScreen.postMessage(parentMessage);
|
await ChannelScreen.postMessage(parentMessage);
|
||||||
const {post: parentPost} = await Post.apiGetLastPostInChannel(siteOneUrl, testChannel.id);
|
const {post: parentPost} = await Post.apiGetLastPostInChannel(siteOneUrl, testChannel.id);
|
||||||
|
const {postListPostItem: parentPostItem2} = ChannelScreen.getPostListPostItem(parentPost.id, parentMessage);
|
||||||
|
await waitFor(parentPostItem2).toBeVisible().withTimeout(timeouts.TEN_SEC);
|
||||||
await ChannelScreen.openReplyThreadFor(parentPost.id, parentMessage);
|
await ChannelScreen.openReplyThreadFor(parentPost.id, parentMessage);
|
||||||
const replyMessage = `${parentMessage} reply`;
|
const replyMessage = `${parentMessage} reply`;
|
||||||
await ThreadScreen.postMessage(replyMessage);
|
await ThreadScreen.postMessage(replyMessage);
|
||||||
|
|
@ -134,12 +145,12 @@ describe('Smoke Test - Threads', () => {
|
||||||
const {postListPostItemPreHeaderText} = ThreadScreen.getPostListPostItem(parentPost.id, parentMessage);
|
const {postListPostItemPreHeaderText} = ThreadScreen.getPostListPostItem(parentPost.id, parentMessage);
|
||||||
await expect(postListPostItemPreHeaderText).toHaveText(savedText);
|
await expect(postListPostItemPreHeaderText).toHaveText(savedText);
|
||||||
|
|
||||||
// # Go back to global threads screen, open thread options for thread, tap on save option, and tap on thread
|
// # Go back to global threads screen, open thread options for thread, tap on unsave option, and tap on thread
|
||||||
await ThreadScreen.back();
|
await ThreadScreen.back();
|
||||||
await GlobalThreadsScreen.openThreadOptionsFor(parentPost.id);
|
await GlobalThreadsScreen.openThreadOptionsFor(parentPost.id);
|
||||||
await wait(timeouts.ONE_SEC);
|
await waitFor(ThreadOptionsScreen.unsaveThreadOption).toBeVisible().withTimeout(timeouts.TEN_SEC);
|
||||||
await ThreadOptionsScreen.unsaveThreadOption.tap();
|
await ThreadOptionsScreen.unsaveThreadOption.tap();
|
||||||
await wait(timeouts.ONE_SEC);
|
await waitFor(GlobalThreadsScreen.getThreadItem(parentPost.id)).toBeVisible().withTimeout(timeouts.TEN_SEC);
|
||||||
await GlobalThreadsScreen.getThreadItem(parentPost.id).tap();
|
await GlobalThreadsScreen.getThreadItem(parentPost.id).tap();
|
||||||
|
|
||||||
// * Verify saved text is not displayed on the post pre-header
|
// * Verify saved text is not displayed on the post pre-header
|
||||||
|
|
@ -148,7 +159,9 @@ describe('Smoke Test - Threads', () => {
|
||||||
// # Go back to global threads screen, open thread options for thread, tap on open in channel option, and jump to recent messages
|
// # Go back to global threads screen, open thread options for thread, tap on open in channel option, and jump to recent messages
|
||||||
await ThreadScreen.back();
|
await ThreadScreen.back();
|
||||||
await GlobalThreadsScreen.openThreadOptionsFor(parentPost.id);
|
await GlobalThreadsScreen.openThreadOptionsFor(parentPost.id);
|
||||||
|
await waitFor(ThreadOptionsScreen.openInChannelOption).toBeVisible().withTimeout(timeouts.TEN_SEC);
|
||||||
await ThreadOptionsScreen.openInChannelOption.tap();
|
await ThreadOptionsScreen.openInChannelOption.tap();
|
||||||
|
await waitFor(PermalinkScreen.permalinkScreen).toBeVisible().withTimeout(timeouts.TEN_SEC);
|
||||||
await PermalinkScreen.jumpToRecentMessages();
|
await PermalinkScreen.jumpToRecentMessages();
|
||||||
|
|
||||||
// * Verify on channel screen and thread is displayed
|
// * Verify on channel screen and thread is displayed
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,7 @@ import {
|
||||||
LoginScreen,
|
LoginScreen,
|
||||||
ServerScreen,
|
ServerScreen,
|
||||||
} from '@support/ui/screen';
|
} from '@support/ui/screen';
|
||||||
import {timeouts} from '@support/utils';
|
import {timeouts, wait} from '@support/utils';
|
||||||
import {expect} from 'detox';
|
import {expect} from 'detox';
|
||||||
|
|
||||||
describe('Teams - Invite', () => {
|
describe('Teams - Invite', () => {
|
||||||
|
|
@ -114,6 +114,7 @@ describe('Teams - Invite', () => {
|
||||||
|
|
||||||
// # Send invitation
|
// # Send invitation
|
||||||
await Invite.sendButton.tap();
|
await Invite.sendButton.tap();
|
||||||
|
await wait(timeouts.TWO_SEC);
|
||||||
|
|
||||||
// * Validate summary report sent
|
// * Validate summary report sent
|
||||||
await waitFor(Invite.screenSummary).toBeVisible().withTimeout(timeouts.TEN_SEC);
|
await waitFor(Invite.screenSummary).toBeVisible().withTimeout(timeouts.TEN_SEC);
|
||||||
|
|
@ -141,6 +142,7 @@ describe('Teams - Invite', () => {
|
||||||
|
|
||||||
// # Send invitation
|
// # Send invitation
|
||||||
await Invite.sendButton.tap();
|
await Invite.sendButton.tap();
|
||||||
|
await wait(timeouts.TWO_SEC);
|
||||||
|
|
||||||
// * Validate summary report sent
|
// * Validate summary report sent
|
||||||
await waitFor(Invite.screenSummary).toBeVisible().withTimeout(timeouts.TEN_SEC);
|
await waitFor(Invite.screenSummary).toBeVisible().withTimeout(timeouts.TEN_SEC);
|
||||||
|
|
@ -166,6 +168,7 @@ describe('Teams - Invite', () => {
|
||||||
|
|
||||||
// # Send invitation
|
// # Send invitation
|
||||||
await Invite.sendButton.tap();
|
await Invite.sendButton.tap();
|
||||||
|
await wait(timeouts.TWO_SEC);
|
||||||
|
|
||||||
// * Validate summary report not sent
|
// * Validate summary report not sent
|
||||||
await expect(Invite.screenSummary).toBeVisible();
|
await expect(Invite.screenSummary).toBeVisible();
|
||||||
|
|
@ -203,6 +206,7 @@ describe('Teams - Invite', () => {
|
||||||
|
|
||||||
// # Send invitation
|
// # Send invitation
|
||||||
await Invite.sendButton.tap();
|
await Invite.sendButton.tap();
|
||||||
|
await wait(timeouts.TWO_SEC);
|
||||||
|
|
||||||
// * Validate summary
|
// * Validate summary
|
||||||
waitFor(Invite.screenSummary).toBeVisible();
|
waitFor(Invite.screenSummary).toBeVisible();
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,7 @@ import {
|
||||||
ThreadScreen,
|
ThreadScreen,
|
||||||
} from '@support/ui/screen';
|
} from '@support/ui/screen';
|
||||||
import {getRandomId, timeouts, wait} from '@support/utils';
|
import {getRandomId, timeouts, wait} from '@support/utils';
|
||||||
import {expect} from 'detox';
|
import {expect, waitFor} from 'detox';
|
||||||
|
|
||||||
describe('Threads - Follow and Unfollow Thread', () => {
|
describe('Threads - Follow and Unfollow Thread', () => {
|
||||||
const serverOneDisplayName = 'Server 1';
|
const serverOneDisplayName = 'Server 1';
|
||||||
|
|
@ -58,23 +58,27 @@ describe('Threads - Follow and Unfollow Thread', () => {
|
||||||
const parentMessage = `Message ${getRandomId()}`;
|
const parentMessage = `Message ${getRandomId()}`;
|
||||||
await ChannelScreen.open(channelsCategory, testChannel.name);
|
await ChannelScreen.open(channelsCategory, testChannel.name);
|
||||||
await ChannelScreen.postMessage(parentMessage);
|
await ChannelScreen.postMessage(parentMessage);
|
||||||
|
await ChannelScreen.dismissKeyboard();
|
||||||
const {post: parentPost} = await Post.apiGetLastPostInChannel(siteOneUrl, testChannel.id);
|
const {post: parentPost} = await Post.apiGetLastPostInChannel(siteOneUrl, testChannel.id);
|
||||||
|
const {postListPostItem} = ChannelScreen.getPostListPostItem(parentPost.id, parentMessage);
|
||||||
|
await waitFor(postListPostItem).toBeVisible().withTimeout(timeouts.FOUR_SEC);
|
||||||
|
|
||||||
await ChannelScreen.openReplyThreadFor(parentPost.id, parentMessage);
|
await ChannelScreen.openReplyThreadFor(parentPost.id, parentMessage);
|
||||||
await ThreadScreen.postMessage(`${parentMessage} reply`);
|
await ThreadScreen.postMessage(`${parentMessage} reply`);
|
||||||
await wait(timeouts.ONE_SEC);
|
|
||||||
|
|
||||||
// * Verify thread is followed by user by default via thread navigation
|
// * Verify thread is followed by user by default via thread navigation
|
||||||
await expect(ThreadScreen.followingButton).toBeVisible();
|
await expect(ThreadScreen.followingButton).toBeVisible();
|
||||||
|
|
||||||
// # Unfollow thread via thread navigation
|
// # Unfollow thread via thread navigation
|
||||||
await ThreadScreen.followingButton.tap();
|
await ThreadScreen.followingButton.tap();
|
||||||
|
await wait(timeouts.TWO_SEC);
|
||||||
|
|
||||||
// * Verify thread is not followed by user via thread navigation
|
// * Verify thread is not followed by user via thread navigation
|
||||||
await expect(ThreadScreen.followButton).toBeVisible();
|
await expect(ThreadScreen.followButton).toBeVisible();
|
||||||
|
|
||||||
// # Follow thread via thread navigation
|
// # Follow thread via thread navigation
|
||||||
await wait(timeouts.TWO_SEC);
|
|
||||||
await ThreadScreen.followButton.tap();
|
await ThreadScreen.followButton.tap();
|
||||||
|
await wait(timeouts.TWO_SEC);
|
||||||
|
|
||||||
// * Verify thread is followed by user via thread navigation
|
// * Verify thread is followed by user via thread navigation
|
||||||
await expect(ThreadScreen.followingButton).toBeVisible();
|
await expect(ThreadScreen.followingButton).toBeVisible();
|
||||||
|
|
@ -89,10 +93,10 @@ describe('Threads - Follow and Unfollow Thread', () => {
|
||||||
const parentMessage = `Message ${getRandomId()}`;
|
const parentMessage = `Message ${getRandomId()}`;
|
||||||
await ChannelScreen.open(channelsCategory, testChannel.name);
|
await ChannelScreen.open(channelsCategory, testChannel.name);
|
||||||
await ChannelScreen.postMessage(parentMessage);
|
await ChannelScreen.postMessage(parentMessage);
|
||||||
|
await ChannelScreen.dismissKeyboard();
|
||||||
const {post: parentPost} = await Post.apiGetLastPostInChannel(siteOneUrl, testChannel.id);
|
const {post: parentPost} = await Post.apiGetLastPostInChannel(siteOneUrl, testChannel.id);
|
||||||
await ChannelScreen.openReplyThreadFor(parentPost.id, parentMessage);
|
await ChannelScreen.openReplyThreadFor(parentPost.id, parentMessage);
|
||||||
await ThreadScreen.postMessage(`${parentMessage} reply`);
|
await ThreadScreen.postMessage(`${parentMessage} reply`);
|
||||||
await wait(timeouts.ONE_SEC);
|
|
||||||
await ThreadScreen.back();
|
await ThreadScreen.back();
|
||||||
|
|
||||||
// * Verify thread is followed by user by default via post footer
|
// * Verify thread is followed by user by default via post footer
|
||||||
|
|
@ -101,13 +105,14 @@ describe('Threads - Follow and Unfollow Thread', () => {
|
||||||
|
|
||||||
// # Unfollow thread via post footer
|
// # Unfollow thread via post footer
|
||||||
await postListPostItemFooterFollowingButton.tap();
|
await postListPostItemFooterFollowingButton.tap();
|
||||||
|
await wait(timeouts.TWO_SEC);
|
||||||
|
|
||||||
// * Verify thread is not followed by user via post footer
|
// * Verify thread is not followed by user via post footer
|
||||||
await expect(postListPostItemFooterFollowButton).toBeVisible();
|
await expect(postListPostItemFooterFollowButton).toBeVisible();
|
||||||
|
|
||||||
// # Follow thread via post footer
|
// # Follow thread via post footer
|
||||||
await wait(timeouts.TWO_SEC);
|
|
||||||
await postListPostItemFooterFollowButton.tap();
|
await postListPostItemFooterFollowButton.tap();
|
||||||
|
await wait(timeouts.TWO_SEC);
|
||||||
|
|
||||||
// * Verify thread is followed by user via post footer
|
// * Verify thread is followed by user via post footer
|
||||||
await expect(postListPostItemFooterFollowingButton).toBeVisible();
|
await expect(postListPostItemFooterFollowingButton).toBeVisible();
|
||||||
|
|
@ -121,6 +126,7 @@ describe('Threads - Follow and Unfollow Thread', () => {
|
||||||
const parentMessage = `Message ${getRandomId()}`;
|
const parentMessage = `Message ${getRandomId()}`;
|
||||||
await ChannelScreen.open(channelsCategory, testChannel.name);
|
await ChannelScreen.open(channelsCategory, testChannel.name);
|
||||||
await ChannelScreen.postMessage(parentMessage);
|
await ChannelScreen.postMessage(parentMessage);
|
||||||
|
await ChannelScreen.dismissKeyboard();
|
||||||
const {post: parentPost} = await Post.apiGetLastPostInChannel(siteOneUrl, testChannel.id);
|
const {post: parentPost} = await Post.apiGetLastPostInChannel(siteOneUrl, testChannel.id);
|
||||||
await ChannelScreen.openReplyThreadFor(parentPost.id, parentMessage);
|
await ChannelScreen.openReplyThreadFor(parentPost.id, parentMessage);
|
||||||
await ThreadScreen.postMessage(`${parentMessage} reply`);
|
await ThreadScreen.postMessage(`${parentMessage} reply`);
|
||||||
|
|
@ -134,6 +140,7 @@ describe('Threads - Follow and Unfollow Thread', () => {
|
||||||
// # Unfollow thread via post options
|
// # Unfollow thread via post options
|
||||||
await waitFor(PostOptionsScreen.followingThreadOption).toBeVisible().withTimeout(timeouts.TWO_SEC);
|
await waitFor(PostOptionsScreen.followingThreadOption).toBeVisible().withTimeout(timeouts.TWO_SEC);
|
||||||
await PostOptionsScreen.followingThreadOption.tap();
|
await PostOptionsScreen.followingThreadOption.tap();
|
||||||
|
await wait(timeouts.TWO_SEC);
|
||||||
|
|
||||||
// * Verify thread is not followed by user via post footer
|
// * Verify thread is not followed by user via post footer
|
||||||
const {postListPostItemFooterFollowButton, postListPostItemFooterFollowingButton} = ChannelScreen.getPostListPostItem(parentPost.id, parentMessage);
|
const {postListPostItemFooterFollowButton, postListPostItemFooterFollowingButton} = ChannelScreen.getPostListPostItem(parentPost.id, parentMessage);
|
||||||
|
|
@ -146,8 +153,8 @@ describe('Threads - Follow and Unfollow Thread', () => {
|
||||||
await expect(PostOptionsScreen.followThreadOption).toBeVisible();
|
await expect(PostOptionsScreen.followThreadOption).toBeVisible();
|
||||||
|
|
||||||
// # Tap on follow thread option
|
// # Tap on follow thread option
|
||||||
await wait(timeouts.TWO_SEC);
|
|
||||||
await PostOptionsScreen.followThreadOption.tap();
|
await PostOptionsScreen.followThreadOption.tap();
|
||||||
|
await wait(timeouts.TWO_SEC);
|
||||||
|
|
||||||
// * Verify thread is followed by user via post footer
|
// * Verify thread is followed by user via post footer
|
||||||
await waitFor(postListPostItemFooterFollowingButton).toBeVisible().withTimeout(timeouts.TWO_SEC);
|
await waitFor(postListPostItemFooterFollowingButton).toBeVisible().withTimeout(timeouts.TWO_SEC);
|
||||||
|
|
@ -168,6 +175,7 @@ describe('Threads - Follow and Unfollow Thread', () => {
|
||||||
const parentMessage = `Message ${getRandomId()}`;
|
const parentMessage = `Message ${getRandomId()}`;
|
||||||
await ChannelScreen.open(channelsCategory, testChannel.name);
|
await ChannelScreen.open(channelsCategory, testChannel.name);
|
||||||
await ChannelScreen.postMessage(parentMessage);
|
await ChannelScreen.postMessage(parentMessage);
|
||||||
|
await ChannelScreen.dismissKeyboard();
|
||||||
const {post: parentPost} = await Post.apiGetLastPostInChannel(siteOneUrl, testChannel.id);
|
const {post: parentPost} = await Post.apiGetLastPostInChannel(siteOneUrl, testChannel.id);
|
||||||
await ChannelScreen.openReplyThreadFor(parentPost.id, parentMessage);
|
await ChannelScreen.openReplyThreadFor(parentPost.id, parentMessage);
|
||||||
const replyMessage = `${parentMessage} reply`;
|
const replyMessage = `${parentMessage} reply`;
|
||||||
|
|
@ -188,14 +196,9 @@ describe('Threads - Follow and Unfollow Thread', () => {
|
||||||
|
|
||||||
// # Tap on unfollow thread option
|
// # Tap on unfollow thread option
|
||||||
await ThreadOptionsScreen.followingThreadOption.tap();
|
await ThreadOptionsScreen.followingThreadOption.tap();
|
||||||
|
await wait(timeouts.TWO_SEC);
|
||||||
|
|
||||||
// * Verify thread is not displayed anymore in all your threads section
|
// * Verify thread is not displayed anymore in all your threads section
|
||||||
await wait(timeouts.ONE_SEC);
|
|
||||||
await expect(GlobalThreadsScreen.getThreadItem(parentPost.id)).not.toBeVisible();
|
await expect(GlobalThreadsScreen.getThreadItem(parentPost.id)).not.toBeVisible();
|
||||||
|
|
||||||
await wait(timeouts.FOUR_SEC);
|
|
||||||
|
|
||||||
// # Go back to channel list screen
|
|
||||||
await GlobalThreadsScreen.back();
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,7 @@ import {
|
||||||
ServerScreen,
|
ServerScreen,
|
||||||
ThreadScreen,
|
ThreadScreen,
|
||||||
} from '@support/ui/screen';
|
} from '@support/ui/screen';
|
||||||
import {getRandomId, timeouts} from '@support/utils';
|
import {getRandomId, timeouts, wait} from '@support/utils';
|
||||||
import {expect} from 'detox';
|
import {expect} from 'detox';
|
||||||
|
|
||||||
describe('Threads - Global Threads', () => {
|
describe('Threads - Global Threads', () => {
|
||||||
|
|
@ -72,10 +72,13 @@ describe('Threads - Global Threads', () => {
|
||||||
const parentMessage = `Message ${getRandomId()}`;
|
const parentMessage = `Message ${getRandomId()}`;
|
||||||
await ChannelScreen.open(channelsCategory, testChannel.name);
|
await ChannelScreen.open(channelsCategory, testChannel.name);
|
||||||
await ChannelScreen.postMessage(parentMessage);
|
await ChannelScreen.postMessage(parentMessage);
|
||||||
|
await ChannelScreen.dismissKeyboard();
|
||||||
|
|
||||||
const {post: parentPost} = await Post.apiGetLastPostInChannel(siteOneUrl, testChannel.id);
|
const {post: parentPost} = await Post.apiGetLastPostInChannel(siteOneUrl, testChannel.id);
|
||||||
await ChannelScreen.openReplyThreadFor(parentPost.id, parentMessage);
|
await ChannelScreen.openReplyThreadFor(parentPost.id, parentMessage);
|
||||||
const replyMessage = `${parentMessage} reply`;
|
const replyMessage = `${parentMessage} reply`;
|
||||||
await ThreadScreen.postMessage(replyMessage);
|
await ThreadScreen.postMessage(replyMessage);
|
||||||
|
await wait(timeouts.TWO_SEC);
|
||||||
const {post: replyPost} = await Post.apiGetLastPostInChannel(siteOneUrl, testChannel.id);
|
const {post: replyPost} = await Post.apiGetLastPostInChannel(siteOneUrl, testChannel.id);
|
||||||
const {postListPostItem: replyPostListPostItem} = ThreadScreen.getPostListPostItem(replyPost.id, replyMessage);
|
const {postListPostItem: replyPostListPostItem} = ThreadScreen.getPostListPostItem(replyPost.id, replyMessage);
|
||||||
|
|
||||||
|
|
@ -117,9 +120,11 @@ describe('Threads - Global Threads', () => {
|
||||||
const parentMessage = `Message ${getRandomId()}`;
|
const parentMessage = `Message ${getRandomId()}`;
|
||||||
await ChannelScreen.open(channelsCategory, testChannel.name);
|
await ChannelScreen.open(channelsCategory, testChannel.name);
|
||||||
await ChannelScreen.postMessage(parentMessage);
|
await ChannelScreen.postMessage(parentMessage);
|
||||||
|
await wait(timeouts.TWO_SEC);
|
||||||
const {post: parentPost} = await Post.apiGetLastPostInChannel(siteOneUrl, testChannel.id);
|
const {post: parentPost} = await Post.apiGetLastPostInChannel(siteOneUrl, testChannel.id);
|
||||||
await ChannelScreen.openReplyThreadFor(parentPost.id, parentMessage);
|
await ChannelScreen.openReplyThreadFor(parentPost.id, parentMessage);
|
||||||
await ThreadScreen.postMessage(`${parentMessage} reply`);
|
await ThreadScreen.postMessage(`${parentMessage} reply`);
|
||||||
|
await wait(timeouts.TWO_SEC);
|
||||||
await ThreadScreen.followingButton.tap();
|
await ThreadScreen.followingButton.tap();
|
||||||
|
|
||||||
// * Verify thread is not followed by the current user
|
// * Verify thread is not followed by the current user
|
||||||
|
|
@ -149,6 +154,7 @@ describe('Threads - Global Threads', () => {
|
||||||
await ChannelScreen.openReplyThreadFor(parentPost.id, parentMessage);
|
await ChannelScreen.openReplyThreadFor(parentPost.id, parentMessage);
|
||||||
const replyMessage = `${parentMessage} reply`;
|
const replyMessage = `${parentMessage} reply`;
|
||||||
await ThreadScreen.postMessage(replyMessage);
|
await ThreadScreen.postMessage(replyMessage);
|
||||||
|
await wait(timeouts.TWO_SEC);
|
||||||
const {post: replyPost} = await Post.apiGetLastPostInChannel(siteOneUrl, testChannel.id);
|
const {post: replyPost} = await Post.apiGetLastPostInChannel(siteOneUrl, testChannel.id);
|
||||||
const {postListPostItem: replyPostListPostItem} = ThreadScreen.getPostListPostItem(replyPost.id, replyMessage);
|
const {postListPostItem: replyPostListPostItem} = ThreadScreen.getPostListPostItem(replyPost.id, replyMessage);
|
||||||
|
|
||||||
|
|
@ -188,6 +194,7 @@ describe('Threads - Global Threads', () => {
|
||||||
await ChannelScreen.open(channelsCategory, testChannel.name);
|
await ChannelScreen.open(channelsCategory, testChannel.name);
|
||||||
await ChannelScreen.openReplyThreadFor(parentPost.id, parentMessage);
|
await ChannelScreen.openReplyThreadFor(parentPost.id, parentMessage);
|
||||||
await ThreadScreen.postMessage(`${parentMessage} reply`);
|
await ThreadScreen.postMessage(`${parentMessage} reply`);
|
||||||
|
await wait(timeouts.TWO_SEC);
|
||||||
await ThreadScreen.followingButton.tap();
|
await ThreadScreen.followingButton.tap();
|
||||||
|
|
||||||
// * Verify thread is not followed by the current user
|
// * Verify thread is not followed by the current user
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,7 @@ import {
|
||||||
ThreadScreen,
|
ThreadScreen,
|
||||||
} from '@support/ui/screen';
|
} from '@support/ui/screen';
|
||||||
import {getRandomId, timeouts, wait} from '@support/utils';
|
import {getRandomId, timeouts, wait} from '@support/utils';
|
||||||
import {expect} from 'detox';
|
import {expect, waitFor} from 'detox';
|
||||||
|
|
||||||
describe('Threads - Open Thread in Channel', () => {
|
describe('Threads - Open Thread in Channel', () => {
|
||||||
const serverOneDisplayName = 'Server 1';
|
const serverOneDisplayName = 'Server 1';
|
||||||
|
|
@ -58,7 +58,12 @@ describe('Threads - Open Thread in Channel', () => {
|
||||||
const parentMessage = `Message ${getRandomId()}`;
|
const parentMessage = `Message ${getRandomId()}`;
|
||||||
await ChannelScreen.open(channelsCategory, testChannel.name);
|
await ChannelScreen.open(channelsCategory, testChannel.name);
|
||||||
await ChannelScreen.postMessage(parentMessage);
|
await ChannelScreen.postMessage(parentMessage);
|
||||||
|
await ChannelScreen.dismissKeyboard();
|
||||||
|
await ChannelScreen.dismissScheduledPostTooltip();
|
||||||
const {post: parentPost} = await Post.apiGetLastPostInChannel(siteOneUrl, testChannel.id);
|
const {post: parentPost} = await Post.apiGetLastPostInChannel(siteOneUrl, testChannel.id);
|
||||||
|
const {postListPostItem} = ChannelScreen.getPostListPostItem(parentPost.id, parentMessage);
|
||||||
|
await waitFor(postListPostItem).toBeVisible().withTimeout(timeouts.FOUR_SEC);
|
||||||
|
|
||||||
await ChannelScreen.openReplyThreadFor(parentPost.id, parentMessage);
|
await ChannelScreen.openReplyThreadFor(parentPost.id, parentMessage);
|
||||||
const replyMessage = `${parentMessage} reply`;
|
const replyMessage = `${parentMessage} reply`;
|
||||||
await ThreadScreen.postMessage(replyMessage);
|
await ThreadScreen.postMessage(replyMessage);
|
||||||
|
|
@ -81,8 +86,9 @@ describe('Threads - Open Thread in Channel', () => {
|
||||||
|
|
||||||
// * Verify on channel screen and thread is displayed
|
// * Verify on channel screen and thread is displayed
|
||||||
await ChannelScreen.toBeVisible();
|
await ChannelScreen.toBeVisible();
|
||||||
const {postListPostItem} = ChannelScreen.getPostListPostItem(parentPost.id, parentMessage);
|
await ChannelScreen.dismissScheduledPostTooltip();
|
||||||
await expect(postListPostItem).toBeVisible();
|
const {postListPostItem: channelPostItem} = ChannelScreen.getPostListPostItem(parentPost.id, parentMessage);
|
||||||
|
await expect(channelPostItem).toBeVisible();
|
||||||
|
|
||||||
// # Go back to channel list screen
|
// # Go back to channel list screen
|
||||||
await ChannelScreen.back();
|
await ChannelScreen.back();
|
||||||
|
|
@ -94,7 +100,11 @@ describe('Threads - Open Thread in Channel', () => {
|
||||||
const parentMessage = `Message ${getRandomId()}`;
|
const parentMessage = `Message ${getRandomId()}`;
|
||||||
await ChannelScreen.open(channelsCategory, testChannel.name);
|
await ChannelScreen.open(channelsCategory, testChannel.name);
|
||||||
await ChannelScreen.postMessage(parentMessage);
|
await ChannelScreen.postMessage(parentMessage);
|
||||||
|
await ChannelScreen.dismissKeyboard();
|
||||||
const {post: parentPost} = await Post.apiGetLastPostInChannel(siteOneUrl, testChannel.id);
|
const {post: parentPost} = await Post.apiGetLastPostInChannel(siteOneUrl, testChannel.id);
|
||||||
|
const {postListPostItem} = ChannelScreen.getPostListPostItem(parentPost.id, parentMessage);
|
||||||
|
await waitFor(postListPostItem).toBeVisible().withTimeout(timeouts.FOUR_SEC);
|
||||||
|
|
||||||
await ChannelScreen.openReplyThreadFor(parentPost.id, parentMessage);
|
await ChannelScreen.openReplyThreadFor(parentPost.id, parentMessage);
|
||||||
const replyMessage = `${parentMessage} reply`;
|
const replyMessage = `${parentMessage} reply`;
|
||||||
await ThreadScreen.postMessage(replyMessage);
|
await ThreadScreen.postMessage(replyMessage);
|
||||||
|
|
@ -122,8 +132,9 @@ describe('Threads - Open Thread in Channel', () => {
|
||||||
|
|
||||||
// * Verify on channel screen and thread is displayed
|
// * Verify on channel screen and thread is displayed
|
||||||
await ChannelScreen.toBeVisible();
|
await ChannelScreen.toBeVisible();
|
||||||
const {postListPostItem} = ChannelScreen.getPostListPostItem(parentPost.id, parentMessage);
|
await ChannelScreen.dismissScheduledPostTooltip();
|
||||||
await expect(postListPostItem).toBeVisible();
|
const {postListPostItem: channelPostItem} = ChannelScreen.getPostListPostItem(parentPost.id, parentMessage);
|
||||||
|
await expect(channelPostItem).toBeVisible();
|
||||||
|
|
||||||
// # Go back to channel list screen
|
// # Go back to channel list screen
|
||||||
await ChannelScreen.back();
|
await ChannelScreen.back();
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,7 @@ import {
|
||||||
ThreadOptionsScreen,
|
ThreadOptionsScreen,
|
||||||
ThreadScreen,
|
ThreadScreen,
|
||||||
} from '@support/ui/screen';
|
} from '@support/ui/screen';
|
||||||
import {getRandomId} from '@support/utils';
|
import {getRandomId, timeouts} from '@support/utils';
|
||||||
import {expect} from 'detox';
|
import {expect} from 'detox';
|
||||||
|
|
||||||
describe('Threads - Reply to Thread', () => {
|
describe('Threads - Reply to Thread', () => {
|
||||||
|
|
@ -57,10 +57,16 @@ describe('Threads - Reply to Thread', () => {
|
||||||
const parentMessage = `Message ${getRandomId()}`;
|
const parentMessage = `Message ${getRandomId()}`;
|
||||||
await ChannelScreen.open(channelsCategory, testChannel.name);
|
await ChannelScreen.open(channelsCategory, testChannel.name);
|
||||||
await ChannelScreen.postMessage(parentMessage);
|
await ChannelScreen.postMessage(parentMessage);
|
||||||
|
await ChannelScreen.dismissKeyboard();
|
||||||
|
|
||||||
const {post: parentPost} = await Post.apiGetLastPostInChannel(siteOneUrl, testChannel.id);
|
const {post: parentPost} = await Post.apiGetLastPostInChannel(siteOneUrl, testChannel.id);
|
||||||
|
const {postListPostItem} = ChannelScreen.getPostListPostItem(parentPost.id, parentMessage);
|
||||||
|
await waitFor(postListPostItem).toBeVisible().withTimeout(timeouts.TEN_SEC);
|
||||||
|
|
||||||
await ChannelScreen.openReplyThreadFor(parentPost.id, parentMessage);
|
await ChannelScreen.openReplyThreadFor(parentPost.id, parentMessage);
|
||||||
const replyMessage = `${parentMessage} reply`;
|
const replyMessage = `${parentMessage} reply`;
|
||||||
await ThreadScreen.postMessage(replyMessage);
|
await ThreadScreen.postMessage(replyMessage);
|
||||||
|
await ChannelScreen.dismissKeyboard();
|
||||||
await ThreadScreen.back();
|
await ThreadScreen.back();
|
||||||
await ChannelScreen.back();
|
await ChannelScreen.back();
|
||||||
await GlobalThreadsScreen.open();
|
await GlobalThreadsScreen.open();
|
||||||
|
|
@ -78,11 +84,12 @@ describe('Threads - Reply to Thread', () => {
|
||||||
// # Add new reply to thread
|
// # Add new reply to thread
|
||||||
const newReplyMessage = `${parentMessage} new reply`;
|
const newReplyMessage = `${parentMessage} new reply`;
|
||||||
await ThreadScreen.postMessage(newReplyMessage);
|
await ThreadScreen.postMessage(newReplyMessage);
|
||||||
|
await ChannelScreen.dismissKeyboard();
|
||||||
|
|
||||||
// * Verify new reply is posted
|
// * Verify new reply is posted
|
||||||
const {post: newReplyPost} = await Post.apiGetLastPostInChannel(siteOneUrl, testChannel.id);
|
const {post: newReplyPost} = await Post.apiGetLastPostInChannel(siteOneUrl, testChannel.id);
|
||||||
const {postListPostItem} = ThreadScreen.getPostListPostItem(newReplyPost.id, newReplyMessage);
|
const {postListPostItem: newReplyPostItem} = ThreadScreen.getPostListPostItem(newReplyPost.id, newReplyMessage);
|
||||||
await expect(postListPostItem).toBeVisible();
|
await expect(newReplyPostItem).toBeVisible();
|
||||||
|
|
||||||
// # Go back to channel list screen
|
// # Go back to channel list screen
|
||||||
await ThreadScreen.back();
|
await ThreadScreen.back();
|
||||||
|
|
@ -94,10 +101,15 @@ describe('Threads - Reply to Thread', () => {
|
||||||
const parentMessage = `Message ${getRandomId()}`;
|
const parentMessage = `Message ${getRandomId()}`;
|
||||||
await ChannelScreen.open(channelsCategory, testChannel.name);
|
await ChannelScreen.open(channelsCategory, testChannel.name);
|
||||||
await ChannelScreen.postMessage(parentMessage);
|
await ChannelScreen.postMessage(parentMessage);
|
||||||
|
await ChannelScreen.dismissKeyboard();
|
||||||
const {post: parentPost} = await Post.apiGetLastPostInChannel(siteOneUrl, testChannel.id);
|
const {post: parentPost} = await Post.apiGetLastPostInChannel(siteOneUrl, testChannel.id);
|
||||||
|
const {postListPostItem} = ChannelScreen.getPostListPostItem(parentPost.id, parentMessage);
|
||||||
|
await waitFor(postListPostItem).toBeVisible().withTimeout(timeouts.TEN_SEC);
|
||||||
await ChannelScreen.openReplyThreadFor(parentPost.id, parentMessage);
|
await ChannelScreen.openReplyThreadFor(parentPost.id, parentMessage);
|
||||||
const replyMessage = `${parentMessage} reply`;
|
const replyMessage = `${parentMessage} reply`;
|
||||||
await ThreadScreen.postMessage(replyMessage);
|
await ThreadScreen.postMessage(replyMessage);
|
||||||
|
await ChannelScreen.dismissKeyboard();
|
||||||
|
|
||||||
await ThreadScreen.back();
|
await ThreadScreen.back();
|
||||||
await ChannelScreen.back();
|
await ChannelScreen.back();
|
||||||
await GlobalThreadsScreen.open();
|
await GlobalThreadsScreen.open();
|
||||||
|
|
@ -114,11 +126,12 @@ describe('Threads - Reply to Thread', () => {
|
||||||
// # Add new reply to thread
|
// # Add new reply to thread
|
||||||
const newReplyMessage = `${parentMessage} new reply`;
|
const newReplyMessage = `${parentMessage} new reply`;
|
||||||
await ThreadScreen.postMessage(newReplyMessage);
|
await ThreadScreen.postMessage(newReplyMessage);
|
||||||
|
await ChannelScreen.dismissKeyboard();
|
||||||
|
|
||||||
// * Verify new reply is posted
|
// * Verify new reply is posted
|
||||||
const {post: newReplyPost} = await Post.apiGetLastPostInChannel(siteOneUrl, testChannel.id);
|
const {post: newReplyPost} = await Post.apiGetLastPostInChannel(siteOneUrl, testChannel.id);
|
||||||
const {postListPostItem} = ThreadScreen.getPostListPostItem(newReplyPost.id, newReplyMessage);
|
const {postListPostItem: newReplyPostItem} = ThreadScreen.getPostListPostItem(newReplyPost.id, newReplyMessage);
|
||||||
await expect(postListPostItem).toBeVisible();
|
await expect(newReplyPostItem).toBeVisible();
|
||||||
|
|
||||||
// # Go back to channel list screen
|
// # Go back to channel list screen
|
||||||
await ThreadScreen.back();
|
await ThreadScreen.back();
|
||||||
|
|
|
||||||
|
|
@ -25,8 +25,8 @@ import {
|
||||||
ThreadOptionsScreen,
|
ThreadOptionsScreen,
|
||||||
ThreadScreen,
|
ThreadScreen,
|
||||||
} from '@support/ui/screen';
|
} from '@support/ui/screen';
|
||||||
import {getRandomId} from '@support/utils';
|
import {getRandomId, timeouts} from '@support/utils';
|
||||||
import {expect} from 'detox';
|
import {expect, waitFor} from 'detox';
|
||||||
|
|
||||||
describe('Threads - Save and Unsave Thread', () => {
|
describe('Threads - Save and Unsave Thread', () => {
|
||||||
const serverOneDisplayName = 'Server 1';
|
const serverOneDisplayName = 'Server 1';
|
||||||
|
|
@ -58,10 +58,16 @@ describe('Threads - Save and Unsave Thread', () => {
|
||||||
const parentMessage = `Message ${getRandomId()}`;
|
const parentMessage = `Message ${getRandomId()}`;
|
||||||
await ChannelScreen.open(channelsCategory, testChannel.name);
|
await ChannelScreen.open(channelsCategory, testChannel.name);
|
||||||
await ChannelScreen.postMessage(parentMessage);
|
await ChannelScreen.postMessage(parentMessage);
|
||||||
|
await ChannelScreen.dismissKeyboard();
|
||||||
|
|
||||||
const {post: parentPost} = await Post.apiGetLastPostInChannel(siteOneUrl, testChannel.id);
|
const {post: parentPost} = await Post.apiGetLastPostInChannel(siteOneUrl, testChannel.id);
|
||||||
|
const {postListPostItem} = ChannelScreen.getPostListPostItem(parentPost.id, parentMessage);
|
||||||
|
await waitFor(postListPostItem).toBeVisible().withTimeout(timeouts.FOUR_SEC);
|
||||||
|
|
||||||
await ChannelScreen.openReplyThreadFor(parentPost.id, parentMessage);
|
await ChannelScreen.openReplyThreadFor(parentPost.id, parentMessage);
|
||||||
const replyMessage = `${parentMessage} reply`;
|
const replyMessage = `${parentMessage} reply`;
|
||||||
await ThreadScreen.postMessage(replyMessage);
|
await ThreadScreen.postMessage(replyMessage);
|
||||||
|
await ChannelScreen.dismissKeyboard();
|
||||||
await ThreadScreen.back();
|
await ThreadScreen.back();
|
||||||
await ChannelScreen.back();
|
await ChannelScreen.back();
|
||||||
await GlobalThreadsScreen.open();
|
await GlobalThreadsScreen.open();
|
||||||
|
|
@ -97,10 +103,12 @@ describe('Threads - Save and Unsave Thread', () => {
|
||||||
const parentMessage = `Message ${getRandomId()}`;
|
const parentMessage = `Message ${getRandomId()}`;
|
||||||
await ChannelScreen.open(channelsCategory, testChannel.name);
|
await ChannelScreen.open(channelsCategory, testChannel.name);
|
||||||
await ChannelScreen.postMessage(parentMessage);
|
await ChannelScreen.postMessage(parentMessage);
|
||||||
|
await ChannelScreen.dismissKeyboard();
|
||||||
const {post: parentPost} = await Post.apiGetLastPostInChannel(siteOneUrl, testChannel.id);
|
const {post: parentPost} = await Post.apiGetLastPostInChannel(siteOneUrl, testChannel.id);
|
||||||
await ChannelScreen.openReplyThreadFor(parentPost.id, parentMessage);
|
await ChannelScreen.openReplyThreadFor(parentPost.id, parentMessage);
|
||||||
const replyMessage = `${parentMessage} reply`;
|
const replyMessage = `${parentMessage} reply`;
|
||||||
await ThreadScreen.postMessage(replyMessage);
|
await ThreadScreen.postMessage(replyMessage);
|
||||||
|
await ChannelScreen.dismissKeyboard();
|
||||||
await ThreadScreen.back();
|
await ThreadScreen.back();
|
||||||
await ChannelScreen.back();
|
await ChannelScreen.back();
|
||||||
await GlobalThreadsScreen.open();
|
await GlobalThreadsScreen.open();
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,6 @@ import {ServerScreen, LoginScreen, ChannelScreen, ChannelListScreen, ThreadScree
|
||||||
describe('Playbooks - Basic', () => {
|
describe('Playbooks - Basic', () => {
|
||||||
const serverOneDisplayName = 'Server 1';
|
const serverOneDisplayName = 'Server 1';
|
||||||
const channelsCategory = 'channels';
|
const channelsCategory = 'channels';
|
||||||
|
|
||||||
let testUser: any;
|
let testUser: any;
|
||||||
let testTeam: any;
|
let testTeam: any;
|
||||||
let testChannel: any;
|
let testChannel: any;
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,6 @@ import {ServerScreen, LoginScreen, ChannelScreen, ChannelListScreen, ThreadScree
|
||||||
describe.skip('Playbooks - Basic', () => {
|
describe.skip('Playbooks - Basic', () => {
|
||||||
const serverOneDisplayName = 'Server 1';
|
const serverOneDisplayName = 'Server 1';
|
||||||
const channelsCategory = 'channels';
|
const channelsCategory = 'channels';
|
||||||
|
|
||||||
let testUser: any;
|
let testUser: any;
|
||||||
let testTeam: any;
|
let testTeam: any;
|
||||||
let testChannel: any;
|
let testChannel: any;
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@
|
||||||
// See LICENSE.txt for license information.
|
// See LICENSE.txt for license information.
|
||||||
/* eslint-disable no-await-in-loop, no-console */
|
/* eslint-disable no-await-in-loop, no-console */
|
||||||
|
|
||||||
|
import {cleanupAdbReversePorts, resetAdbServer} from '@support/adb_utils';
|
||||||
import {ClaudePromptHandler} from '@support/pilot/ClaudePromptHandler';
|
import {ClaudePromptHandler} from '@support/pilot/ClaudePromptHandler';
|
||||||
import {Plugin, System, User} from '@support/server_api';
|
import {Plugin, System, User} from '@support/server_api';
|
||||||
import {siteOneUrl} from '@support/test_config';
|
import {siteOneUrl} from '@support/test_config';
|
||||||
|
|
@ -56,8 +57,6 @@ export async function launchAppWithRetry(): Promise<void> {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// Verify app is connected by executing a simple command
|
|
||||||
await device.reloadReactNative();
|
|
||||||
console.info(`✅ App launched successfully on attempt ${attempt}`);
|
console.info(`✅ App launched successfully on attempt ${attempt}`);
|
||||||
return; // Success, exit the function
|
return; // Success, exit the function
|
||||||
|
|
||||||
|
|
@ -67,14 +66,27 @@ export async function launchAppWithRetry(): Promise<void> {
|
||||||
|
|
||||||
// If this is the last attempt, don't wait
|
// If this is the last attempt, don't wait
|
||||||
if (attempt < MAX_RETRY_ATTEMPTS) {
|
if (attempt < MAX_RETRY_ATTEMPTS) {
|
||||||
|
// Check if this is an ADB port binding issue (Android-specific, common in CI)
|
||||||
|
const errorMessage = (error as Error).message;
|
||||||
|
const isAdbPortError = errorMessage.includes('cannot bind listener') ||
|
||||||
|
errorMessage.includes('Address already in use') ||
|
||||||
|
errorMessage.includes('adb');
|
||||||
|
|
||||||
|
// Only attempt ADB cleanup if we detect an ADB-related error
|
||||||
|
// These functions are safe no-ops on iOS
|
||||||
|
if (isAdbPortError) {
|
||||||
|
console.warn('Detected ADB-related error, attempting cleanup...');
|
||||||
|
await cleanupAdbReversePorts();
|
||||||
|
|
||||||
|
// On second retry with port issues, also reset ADB server
|
||||||
|
if (attempt >= 2) {
|
||||||
|
console.warn('Multiple failures detected, attempting ADB server reset...');
|
||||||
|
await resetAdbServer();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
console.warn(`Waiting ${RETRY_DELAY}ms before retrying...`);
|
console.warn(`Waiting ${RETRY_DELAY}ms before retrying...`);
|
||||||
await new Promise((resolve) => setTimeout(resolve, RETRY_DELAY));
|
await new Promise((resolve) => setTimeout(resolve, RETRY_DELAY));
|
||||||
|
|
||||||
// Force a new instance on retry
|
|
||||||
if (!isFirstLaunch && attempt > 1) {
|
|
||||||
console.warn('Forcing new instance for next attempt');
|
|
||||||
isFirstLaunch = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -97,8 +109,15 @@ async function initializeClaudePromptHandler(): Promise<void> {
|
||||||
}
|
}
|
||||||
|
|
||||||
beforeAll(async () => {
|
beforeAll(async () => {
|
||||||
|
// Reset flag to ensure each test file starts with a clean app launch
|
||||||
|
isFirstLaunch = true;
|
||||||
|
|
||||||
await initializeClaudePromptHandler();
|
await initializeClaudePromptHandler();
|
||||||
|
|
||||||
|
// Clean up any stale ADB reverse port mappings from previous runs
|
||||||
|
// This is crucial in CI where crashed tests may leave stale connections
|
||||||
|
await cleanupAdbReversePorts();
|
||||||
|
|
||||||
// Login as sysadmin and reset server configuration
|
// Login as sysadmin and reset server configuration
|
||||||
await System.apiCheckSystemHealth(siteOneUrl);
|
await System.apiCheckSystemHealth(siteOneUrl);
|
||||||
await User.apiAdminLogin(siteOneUrl);
|
await User.apiAdminLogin(siteOneUrl);
|
||||||
|
|
@ -111,6 +130,13 @@ afterAll(async () => {
|
||||||
try {
|
try {
|
||||||
await device.terminateApp();
|
await device.terminateApp();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error terminating app:', error);
|
console.error('[Teardown] Error terminating app:', error);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clean up ADB connections after tests complete
|
||||||
|
try {
|
||||||
|
await cleanupAdbReversePorts();
|
||||||
|
} catch (error) {
|
||||||
|
console.error('[Teardown] Error cleaning up ADB ports:', error);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue