Merge branch 'develop' into chore/ts-RoomView
This commit is contained in:
commit
b1d1e29d41
|
@ -1419,6 +1419,7 @@ Array [
|
||||||
</Text>
|
</Text>
|
||||||
</View>
|
</View>
|
||||||
<View
|
<View
|
||||||
|
accessibilityLabel="Use"
|
||||||
accessible={true}
|
accessible={true}
|
||||||
focusable={true}
|
focusable={true}
|
||||||
onClick={[Function]}
|
onClick={[Function]}
|
||||||
|
@ -1581,6 +1582,7 @@ Array [
|
||||||
</Text>
|
</Text>
|
||||||
</View>
|
</View>
|
||||||
<View
|
<View
|
||||||
|
accessibilityLabel="Use"
|
||||||
accessible={true}
|
accessible={true}
|
||||||
focusable={true}
|
focusable={true}
|
||||||
onClick={[Function]}
|
onClick={[Function]}
|
||||||
|
@ -41244,6 +41246,7 @@ exports[`Storyshots Message Show a button as attachment 1`] = `
|
||||||
Test Button
|
Test Button
|
||||||
</Text>
|
</Text>
|
||||||
<View
|
<View
|
||||||
|
accessibilityLabel="Text button"
|
||||||
accessible={true}
|
accessible={true}
|
||||||
focusable={true}
|
focusable={true}
|
||||||
onClick={[Function]}
|
onClick={[Function]}
|
||||||
|
|
|
@ -151,6 +151,8 @@ android {
|
||||||
missingDimensionStrategy "RNNotifications.reactNativeVersion", "reactNative60" // See note below!
|
missingDimensionStrategy "RNNotifications.reactNativeVersion", "reactNative60" // See note below!
|
||||||
}
|
}
|
||||||
resValue "string", "rn_config_reader_custom_package", "chat.rocket.reactnative"
|
resValue "string", "rn_config_reader_custom_package", "chat.rocket.reactnative"
|
||||||
|
testBuildType System.getProperty('testBuildType', 'debug')
|
||||||
|
testInstrumentationRunner 'androidx.test.runner.AndroidJUnitRunner'
|
||||||
}
|
}
|
||||||
|
|
||||||
signingConfigs {
|
signingConfigs {
|
||||||
|
@ -203,6 +205,10 @@ android {
|
||||||
dimension = "app"
|
dimension = "app"
|
||||||
buildConfigField "boolean", "IS_OFFICIAL", "false"
|
buildConfigField "boolean", "IS_OFFICIAL", "false"
|
||||||
}
|
}
|
||||||
|
e2e {
|
||||||
|
dimension = "app"
|
||||||
|
buildConfigField "boolean", "IS_OFFICIAL", "false"
|
||||||
|
}
|
||||||
foss {
|
foss {
|
||||||
dimension = "type"
|
dimension = "type"
|
||||||
buildConfigField "boolean", "FDROID_BUILD", "true"
|
buildConfigField "boolean", "FDROID_BUILD", "true"
|
||||||
|
@ -230,6 +236,16 @@ android {
|
||||||
java.srcDirs = ['src/main/java', 'src/play/java']
|
java.srcDirs = ['src/main/java', 'src/play/java']
|
||||||
manifest.srcFile 'src/play/AndroidManifest.xml'
|
manifest.srcFile 'src/play/AndroidManifest.xml'
|
||||||
}
|
}
|
||||||
|
e2ePlayDebug {
|
||||||
|
java.srcDirs = ['src/main/java', 'src/play/java']
|
||||||
|
res.srcDirs = ['src/experimental/res']
|
||||||
|
manifest.srcFile 'src/play/AndroidManifest.xml'
|
||||||
|
}
|
||||||
|
e2ePlayRelease {
|
||||||
|
java.srcDirs = ['src/main/java', 'src/play/java']
|
||||||
|
res.srcDirs = ['src/experimental/res']
|
||||||
|
manifest.srcFile 'src/play/AndroidManifest.xml'
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
applicationVariants.all { variant ->
|
applicationVariants.all { variant ->
|
||||||
|
@ -294,6 +310,8 @@ dependencies {
|
||||||
implementation "com.tencent:mmkv-static:1.2.1"
|
implementation "com.tencent:mmkv-static:1.2.1"
|
||||||
implementation 'com.squareup.okhttp3:okhttp:4.9.0'
|
implementation 'com.squareup.okhttp3:okhttp:4.9.0'
|
||||||
implementation "com.squareup.okhttp3:okhttp-urlconnection:4.9.0"
|
implementation "com.squareup.okhttp3:okhttp-urlconnection:4.9.0"
|
||||||
|
androidTestImplementation('com.wix:detox:+') { transitive = true }
|
||||||
|
androidTestImplementation 'junit:junit:4.12'
|
||||||
}
|
}
|
||||||
|
|
||||||
// Run this once to be able to run the application with BUCK
|
// Run this once to be able to run the application with BUCK
|
||||||
|
|
|
@ -0,0 +1,32 @@
|
||||||
|
// Replace "com.example" here and below with your app's package name from the top of MainActivity.java
|
||||||
|
package chat.rocket.reactnative;
|
||||||
|
|
||||||
|
import com.wix.detox.Detox;
|
||||||
|
import com.wix.detox.config.DetoxConfig;
|
||||||
|
|
||||||
|
import org.junit.Rule;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
|
||||||
|
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||||
|
import androidx.test.filters.LargeTest;
|
||||||
|
import androidx.test.rule.ActivityTestRule;
|
||||||
|
|
||||||
|
@RunWith(AndroidJUnit4.class)
|
||||||
|
@LargeTest
|
||||||
|
public class DetoxTest {
|
||||||
|
@Rule
|
||||||
|
// Replace 'MainActivity' with the value of android:name entry in
|
||||||
|
// <activity> in AndroidManifest.xml
|
||||||
|
public ActivityTestRule<MainActivity> mActivityRule = new ActivityTestRule<>(MainActivity.class, false, false);
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void runDetoxTests() {
|
||||||
|
DetoxConfig detoxConfig = new DetoxConfig();
|
||||||
|
detoxConfig.idlePolicyConfig.masterTimeoutSec = 90;
|
||||||
|
detoxConfig.idlePolicyConfig.idleResourceTimeoutSec = 60;
|
||||||
|
detoxConfig.rnContextLoadTimeoutSec = (chat.rocket.reactnative.BuildConfig.DEBUG ? 180 : 60);
|
||||||
|
|
||||||
|
Detox.runTests(mActivityRule, detoxConfig);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,10 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<network-security-config xmlns:tools="http://schemas.android.com/tools">
|
||||||
|
<base-config cleartextTrafficPermitted="true">
|
||||||
|
<trust-anchors>
|
||||||
|
<certificates src="system" />
|
||||||
|
<certificates src="user"
|
||||||
|
tools:ignore="AcceptsUserCertificates" />
|
||||||
|
</trust-anchors>
|
||||||
|
</base-config>
|
||||||
|
</network-security-config>
|
|
@ -53,6 +53,10 @@ allprojects {
|
||||||
url("$rootDir/../node_modules/jsc-android/dist")
|
url("$rootDir/../node_modules/jsc-android/dist")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
maven {
|
||||||
|
url "$rootDir/../node_modules/detox/Detox-android"
|
||||||
|
}
|
||||||
|
|
||||||
maven {
|
maven {
|
||||||
url jitsi_url
|
url jitsi_url
|
||||||
}
|
}
|
||||||
|
|
|
@ -124,7 +124,11 @@ const ActionSheet = React.memo(
|
||||||
|
|
||||||
const renderFooter = () =>
|
const renderFooter = () =>
|
||||||
data?.hasCancel ? (
|
data?.hasCancel ? (
|
||||||
<Button onPress={hide} style={[styles.button, { backgroundColor: themes[theme].auxiliaryBackground }]} theme={theme}>
|
<Button
|
||||||
|
onPress={hide}
|
||||||
|
style={[styles.button, { backgroundColor: themes[theme].auxiliaryBackground }]}
|
||||||
|
theme={theme}
|
||||||
|
accessibilityLabel={I18n.t('Cancel')}>
|
||||||
<Text style={[styles.text, { color: themes[theme].bodyText }]}>{I18n.t('Cancel')}</Text>
|
<Text style={[styles.text, { color: themes[theme].bodyText }]}>{I18n.t('Cancel')}</Text>
|
||||||
</Button>
|
</Button>
|
||||||
) : null;
|
) : null;
|
||||||
|
|
|
@ -70,6 +70,7 @@ export default class Button extends React.PureComponent<Partial<IButtonProps>, a
|
||||||
disabled && styles.disabled,
|
disabled && styles.disabled,
|
||||||
style
|
style
|
||||||
]}
|
]}
|
||||||
|
accessibilityLabel={title}
|
||||||
{...otherProps}>
|
{...otherProps}>
|
||||||
{loading ? (
|
{loading ? (
|
||||||
<ActivityIndicator color={textColor} />
|
<ActivityIndicator color={textColor} />
|
||||||
|
|
|
@ -2,7 +2,7 @@ import React from 'react';
|
||||||
import { StyleSheet, View } from 'react-native';
|
import { StyleSheet, View } from 'react-native';
|
||||||
|
|
||||||
interface IHeaderButtonContainer {
|
interface IHeaderButtonContainer {
|
||||||
children: JSX.Element;
|
children: React.ReactNode;
|
||||||
left?: boolean;
|
left?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -20,7 +20,7 @@ interface IPasscodeBase {
|
||||||
previousPasscode?: string;
|
previousPasscode?: string;
|
||||||
title: string;
|
title: string;
|
||||||
subtitle?: string;
|
subtitle?: string;
|
||||||
showBiometry?: string;
|
showBiometry?: boolean;
|
||||||
onEndProcess: Function;
|
onEndProcess: Function;
|
||||||
onError?: Function;
|
onError?: Function;
|
||||||
onBiometryPress?(): void;
|
onBiometryPress?(): void;
|
||||||
|
|
|
@ -15,7 +15,7 @@ import I18n from '../../i18n';
|
||||||
|
|
||||||
interface IPasscodePasscodeEnter {
|
interface IPasscodePasscodeEnter {
|
||||||
theme: string;
|
theme: string;
|
||||||
hasBiometry: string;
|
hasBiometry: boolean;
|
||||||
finishProcess: Function;
|
finishProcess: Function;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -8,6 +8,7 @@ interface IStatus {
|
||||||
status: string;
|
status: string;
|
||||||
size: number;
|
size: number;
|
||||||
style?: StyleProp<TextStyle>;
|
style?: StyleProp<TextStyle>;
|
||||||
|
testID?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
const Status = React.memo(({ style, status = 'offline', size = 32, ...props }: IStatus) => {
|
const Status = React.memo(({ style, status = 'offline', size = 32, ...props }: IStatus) => {
|
||||||
|
|
|
@ -43,7 +43,11 @@ const Content = React.memo(
|
||||||
content = <Text style={[styles.text, { color: themes[props.theme].bodyText }]}>{I18n.t('Sent_an_attachment')}</Text>;
|
content = <Text style={[styles.text, { color: themes[props.theme].bodyText }]}>{I18n.t('Sent_an_attachment')}</Text>;
|
||||||
} else if (props.isEncrypted) {
|
} else if (props.isEncrypted) {
|
||||||
content = (
|
content = (
|
||||||
<Text style={[styles.textInfo, { color: themes[props.theme].auxiliaryText }]}>{I18n.t('Encrypted_message')}</Text>
|
<Text
|
||||||
|
style={[styles.textInfo, { color: themes[props.theme].auxiliaryText }]}
|
||||||
|
accessibilityLabel={I18n.t('Encrypted_message')}>
|
||||||
|
{I18n.t('Encrypted_message')}
|
||||||
|
</Text>
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
const { baseUrl, user, onLinkPress } = useContext(MessageContext);
|
const { baseUrl, user, onLinkPress } = useContext(MessageContext);
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
// https://github.com/RocketChat/Rocket.Chat/blob/develop/definition/ITeam.ts
|
// https://github.com/RocketChat/Rocket.Chat/blob/develop/definition/ITeam.ts
|
||||||
export const TEAM_TYPE = {
|
exports.TEAM_TYPE = {
|
||||||
PUBLIC: 0,
|
PUBLIC: 0,
|
||||||
PRIVATE: 1
|
PRIVATE: 1
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { Text, View } from 'react-native';
|
import { Text, View, ViewStyle } from 'react-native';
|
||||||
|
|
||||||
import Touch from '../../utils/touch';
|
import Touch from '../../utils/touch';
|
||||||
import Avatar from '../../containers/Avatar';
|
import Avatar from '../../containers/Avatar';
|
||||||
|
@ -10,7 +10,7 @@ import { themes } from '../../constants/colors';
|
||||||
export { ROW_HEIGHT };
|
export { ROW_HEIGHT };
|
||||||
|
|
||||||
interface IDirectoryItemLabel {
|
interface IDirectoryItemLabel {
|
||||||
text: string;
|
text?: string;
|
||||||
theme: string;
|
theme: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -21,9 +21,9 @@ interface IDirectoryItem {
|
||||||
type: string;
|
type: string;
|
||||||
onPress(): void;
|
onPress(): void;
|
||||||
testID: string;
|
testID: string;
|
||||||
style: any;
|
style?: ViewStyle;
|
||||||
rightLabel: string;
|
rightLabel?: string;
|
||||||
rid: string;
|
rid?: string;
|
||||||
theme: string;
|
theme: string;
|
||||||
teamMain?: boolean;
|
teamMain?: boolean;
|
||||||
}
|
}
|
||||||
|
@ -32,7 +32,7 @@ const DirectoryItemLabel = React.memo(({ text, theme }: IDirectoryItemLabel) =>
|
||||||
if (!text) {
|
if (!text) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return <Text style={[styles.directoryItemLabel, { color: themes[theme!].auxiliaryText }]}>{text}</Text>;
|
return <Text style={[styles.directoryItemLabel, { color: themes[theme].auxiliaryText }]}>{text}</Text>;
|
||||||
});
|
});
|
||||||
|
|
||||||
const DirectoryItem = ({
|
const DirectoryItem = ({
|
||||||
|
|
|
@ -4,7 +4,7 @@ import { KeyboardAwareScrollView, KeyboardAwareScrollViewProps } from '@codler/r
|
||||||
import scrollPersistTaps from '../utils/scrollPersistTaps';
|
import scrollPersistTaps from '../utils/scrollPersistTaps';
|
||||||
|
|
||||||
interface IKeyboardViewProps extends KeyboardAwareScrollViewProps {
|
interface IKeyboardViewProps extends KeyboardAwareScrollViewProps {
|
||||||
keyboardVerticalOffset: number;
|
keyboardVerticalOffset?: number;
|
||||||
scrollEnabled?: boolean;
|
scrollEnabled?: boolean;
|
||||||
children: React.ReactNode;
|
children: React.ReactNode;
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,7 +46,7 @@ interface IUserItem {
|
||||||
testID: string;
|
testID: string;
|
||||||
onLongPress?: () => void;
|
onLongPress?: () => void;
|
||||||
style?: StyleProp<ViewStyle>;
|
style?: StyleProp<ViewStyle>;
|
||||||
icon: string;
|
icon?: string;
|
||||||
theme: string;
|
theme: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -63,7 +63,11 @@ export default class DirectoryOptions extends PureComponent<IDirectoryOptionsPro
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Touch onPress={() => changeType(itemType)} style={styles.dropdownItemButton} theme={theme}>
|
<Touch
|
||||||
|
onPress={() => changeType(itemType)}
|
||||||
|
style={styles.dropdownItemButton}
|
||||||
|
theme={theme}
|
||||||
|
accessibilityLabel={I18n.t(text)}>
|
||||||
<View style={styles.dropdownItemContainer}>
|
<View style={styles.dropdownItemContainer}>
|
||||||
<CustomIcon style={[styles.dropdownItemIcon, { color: themes[theme].bodyText }]} size={22} name={icon} />
|
<CustomIcon style={[styles.dropdownItemIcon, { color: themes[theme].bodyText }]} size={22} name={icon} />
|
||||||
<Text style={[styles.dropdownItemText, { color: themes[theme].bodyText }]}>{I18n.t(text)}</Text>
|
<Text style={[styles.dropdownItemText, { color: themes[theme].bodyText }]}>{I18n.t(text)}</Text>
|
||||||
|
@ -90,7 +94,7 @@ export default class DirectoryOptions extends PureComponent<IDirectoryOptionsPro
|
||||||
</TouchableWithoutFeedback>
|
</TouchableWithoutFeedback>
|
||||||
<Animated.View
|
<Animated.View
|
||||||
style={[styles.dropdownContainer, { transform: [{ translateY }], backgroundColor: themes[theme].backgroundColor }]}>
|
style={[styles.dropdownContainer, { transform: [{ translateY }], backgroundColor: themes[theme].backgroundColor }]}>
|
||||||
<Touch onPress={this.close} theme={theme}>
|
<Touch onPress={this.close} theme={theme} accessibilityLabel={I18n.t('Search_by')}>
|
||||||
<View
|
<View
|
||||||
style={[
|
style={[
|
||||||
styles.dropdownContainerHeader,
|
styles.dropdownContainerHeader,
|
||||||
|
|
|
@ -1,11 +1,12 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import { StackNavigationOptions, StackNavigationProp } from '@react-navigation/stack';
|
||||||
import { FlatList, StyleSheet, Text, View } from 'react-native';
|
import { FlatList, StyleSheet, Text, View } from 'react-native';
|
||||||
|
import { Dispatch } from 'redux';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { Q } from '@nozbe/watermelondb';
|
import { Q } from '@nozbe/watermelondb';
|
||||||
import { dequal } from 'dequal';
|
import { dequal } from 'dequal';
|
||||||
import * as List from '../containers/List';
|
|
||||||
|
|
||||||
|
import * as List from '../containers/List';
|
||||||
import Touch from '../utils/touch';
|
import Touch from '../utils/touch';
|
||||||
import database from '../lib/database';
|
import database from '../lib/database';
|
||||||
import RocketChat from '../lib/rocketchat';
|
import RocketChat from '../lib/rocketchat';
|
||||||
|
@ -18,7 +19,6 @@ import * as HeaderButton from '../containers/HeaderButton';
|
||||||
import StatusBar from '../containers/StatusBar';
|
import StatusBar from '../containers/StatusBar';
|
||||||
import { themes } from '../constants/colors';
|
import { themes } from '../constants/colors';
|
||||||
import { withTheme } from '../theme';
|
import { withTheme } from '../theme';
|
||||||
import { getUserSelector } from '../selectors/login';
|
|
||||||
import Navigation from '../lib/Navigation';
|
import Navigation from '../lib/Navigation';
|
||||||
import { createChannelRequest } from '../actions/createChannel';
|
import { createChannelRequest } from '../actions/createChannel';
|
||||||
import { goRoom } from '../utils/goRoom';
|
import { goRoom } from '../utils/goRoom';
|
||||||
|
@ -47,33 +47,54 @@ const styles = StyleSheet.create({
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
class NewMessageView extends React.Component {
|
interface IButton {
|
||||||
static navigationOptions = ({ navigation }) => ({
|
onPress: () => void;
|
||||||
|
testID: string;
|
||||||
|
title: string;
|
||||||
|
icon: string;
|
||||||
|
first?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface ISearch {
|
||||||
|
_id: string;
|
||||||
|
status: string;
|
||||||
|
username: string;
|
||||||
|
avatarETag: string;
|
||||||
|
outside: boolean;
|
||||||
|
rid: string;
|
||||||
|
name: string;
|
||||||
|
t: string;
|
||||||
|
search: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface INewMessageViewState {
|
||||||
|
search: ISearch[];
|
||||||
|
// TODO: Refactor when migrate room
|
||||||
|
chats: any[];
|
||||||
|
permissions: boolean[];
|
||||||
|
}
|
||||||
|
|
||||||
|
interface INewMessageViewProps {
|
||||||
|
navigation: StackNavigationProp<any, 'NewMessageView'>;
|
||||||
|
create: (params: { group: boolean }) => void;
|
||||||
|
maxUsers: number;
|
||||||
|
theme: string;
|
||||||
|
isMasterDetail: boolean;
|
||||||
|
serverVersion: string;
|
||||||
|
createTeamPermission: string[];
|
||||||
|
createDirectMessagePermission: string[];
|
||||||
|
createPublicChannelPermission: string[];
|
||||||
|
createPrivateChannelPermission: string[];
|
||||||
|
createDiscussionPermission: string[];
|
||||||
|
}
|
||||||
|
|
||||||
|
class NewMessageView extends React.Component<INewMessageViewProps, INewMessageViewState> {
|
||||||
|
static navigationOptions = ({ navigation }: INewMessageViewProps): StackNavigationOptions => ({
|
||||||
headerLeft: () => <HeaderButton.CloseModal navigation={navigation} testID='new-message-view-close' />,
|
headerLeft: () => <HeaderButton.CloseModal navigation={navigation} testID='new-message-view-close' />,
|
||||||
title: I18n.t('New_Message')
|
title: I18n.t('New_Message')
|
||||||
});
|
});
|
||||||
|
|
||||||
static propTypes = {
|
constructor(props: INewMessageViewProps) {
|
||||||
navigation: PropTypes.object,
|
|
||||||
baseUrl: PropTypes.string,
|
|
||||||
user: PropTypes.shape({
|
|
||||||
id: PropTypes.string,
|
|
||||||
token: PropTypes.string,
|
|
||||||
roles: PropTypes.array
|
|
||||||
}),
|
|
||||||
create: PropTypes.func,
|
|
||||||
maxUsers: PropTypes.number,
|
|
||||||
theme: PropTypes.string,
|
|
||||||
isMasterDetail: PropTypes.bool,
|
|
||||||
serverVersion: PropTypes.string,
|
|
||||||
createTeamPermission: PropTypes.array,
|
|
||||||
createDirectMessagePermission: PropTypes.array,
|
|
||||||
createPublicChannelPermission: PropTypes.array,
|
|
||||||
createPrivateChannelPermission: PropTypes.array,
|
|
||||||
createDiscussionPermission: PropTypes.array
|
|
||||||
};
|
|
||||||
|
|
||||||
constructor(props) {
|
|
||||||
super(props);
|
super(props);
|
||||||
this.init();
|
this.init();
|
||||||
this.state = {
|
this.state = {
|
||||||
|
@ -102,7 +123,7 @@ class NewMessageView extends React.Component {
|
||||||
this.handleHasPermission();
|
this.handleHasPermission();
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidUpdate(prevProps) {
|
componentDidUpdate(prevProps: INewMessageViewProps) {
|
||||||
const {
|
const {
|
||||||
createTeamPermission,
|
createTeamPermission,
|
||||||
createPublicChannelPermission,
|
createPublicChannelPermission,
|
||||||
|
@ -122,7 +143,7 @@ class NewMessageView extends React.Component {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
onSearchChangeText(text) {
|
onSearchChangeText(text: string) {
|
||||||
this.search(text);
|
this.search(text);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -131,7 +152,7 @@ class NewMessageView extends React.Component {
|
||||||
return navigation.pop();
|
return navigation.pop();
|
||||||
};
|
};
|
||||||
|
|
||||||
search = async text => {
|
search = async (text: string) => {
|
||||||
const result = await RocketChat.search({ text, filterRooms: false });
|
const result = await RocketChat.search({ text, filterRooms: false });
|
||||||
this.setState({
|
this.setState({
|
||||||
search: result
|
search: result
|
||||||
|
@ -162,7 +183,8 @@ class NewMessageView extends React.Component {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
goRoom = item => {
|
// TODO: Refactor when migrate room
|
||||||
|
goRoom = (item: any) => {
|
||||||
logEvent(events.NEW_MSG_CHAT_WITH_USER);
|
logEvent(events.NEW_MSG_CHAT_WITH_USER);
|
||||||
const { isMasterDetail, navigation } = this.props;
|
const { isMasterDetail, navigation } = this.props;
|
||||||
if (isMasterDetail) {
|
if (isMasterDetail) {
|
||||||
|
@ -171,7 +193,7 @@ class NewMessageView extends React.Component {
|
||||||
goRoom({ item, isMasterDetail });
|
goRoom({ item, isMasterDetail });
|
||||||
};
|
};
|
||||||
|
|
||||||
renderButton = ({ onPress, testID, title, icon, first }) => {
|
renderButton = ({ onPress, testID, title, icon, first }: IButton) => {
|
||||||
const { theme } = this.props;
|
const { theme } = this.props;
|
||||||
return (
|
return (
|
||||||
<Touch onPress={onPress} style={{ backgroundColor: themes[theme].backgroundColor }} testID={testID} theme={theme}>
|
<Touch onPress={onPress} style={{ backgroundColor: themes[theme].backgroundColor }} testID={testID} theme={theme}>
|
||||||
|
@ -218,7 +240,7 @@ class NewMessageView extends React.Component {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View style={{ backgroundColor: themes[theme].auxiliaryBackground }}>
|
<View style={{ backgroundColor: themes[theme].auxiliaryBackground }}>
|
||||||
<SearchBox onChangeText={text => this.onSearchChangeText(text)} testID='new-message-view-search' />
|
<SearchBox onChangeText={(text: string) => this.onSearchChangeText(text)} testID='new-message-view-search' />
|
||||||
<View style={styles.buttonContainer}>
|
<View style={styles.buttonContainer}>
|
||||||
{permissions[0] || permissions[1]
|
{permissions[0] || permissions[1]
|
||||||
? this.renderButton({
|
? this.renderButton({
|
||||||
|
@ -258,9 +280,10 @@ class NewMessageView extends React.Component {
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
renderItem = ({ item, index }) => {
|
// TODO: Refactor when migrate room
|
||||||
|
renderItem = ({ item, index }: { item: ISearch | any; index: number }) => {
|
||||||
const { search, chats } = this.state;
|
const { search, chats } = this.state;
|
||||||
const { baseUrl, user, theme } = this.props;
|
const { theme } = this.props;
|
||||||
|
|
||||||
let style = { borderColor: themes[theme].separatorColor };
|
let style = { borderColor: themes[theme].separatorColor };
|
||||||
if (index === 0) {
|
if (index === 0) {
|
||||||
|
@ -277,10 +300,8 @@ class NewMessageView extends React.Component {
|
||||||
name={item.search ? item.name : item.fname}
|
name={item.search ? item.name : item.fname}
|
||||||
username={item.search ? item.username : item.name}
|
username={item.search ? item.username : item.name}
|
||||||
onPress={() => this.goRoom(item)}
|
onPress={() => this.goRoom(item)}
|
||||||
baseUrl={baseUrl}
|
|
||||||
testID={`new-message-view-item-${item.name}`}
|
testID={`new-message-view-item-${item.name}`}
|
||||||
style={style}
|
style={style}
|
||||||
user={user}
|
|
||||||
theme={theme}
|
theme={theme}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
@ -313,12 +334,10 @@ class NewMessageView extends React.Component {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const mapStateToProps = state => ({
|
const mapStateToProps = (state: any) => ({
|
||||||
serverVersion: state.server.version,
|
serverVersion: state.server.version,
|
||||||
isMasterDetail: state.app.isMasterDetail,
|
isMasterDetail: state.app.isMasterDetail,
|
||||||
baseUrl: state.server.server,
|
|
||||||
maxUsers: state.settings.DirectMesssage_maxUsers || 1,
|
maxUsers: state.settings.DirectMesssage_maxUsers || 1,
|
||||||
user: getUserSelector(state),
|
|
||||||
createTeamPermission: state.permissions['create-team'],
|
createTeamPermission: state.permissions['create-team'],
|
||||||
createDirectMessagePermission: state.permissions['create-d'],
|
createDirectMessagePermission: state.permissions['create-d'],
|
||||||
createPublicChannelPermission: state.permissions['create-c'],
|
createPublicChannelPermission: state.permissions['create-c'],
|
||||||
|
@ -326,8 +345,8 @@ const mapStateToProps = state => ({
|
||||||
createDiscussionPermission: state.permissions['start-discussion']
|
createDiscussionPermission: state.permissions['start-discussion']
|
||||||
});
|
});
|
||||||
|
|
||||||
const mapDispatchToProps = dispatch => ({
|
const mapDispatchToProps = (dispatch: Dispatch) => ({
|
||||||
create: params => dispatch(createChannelRequest(params))
|
create: (params: { group: boolean }) => dispatch(createChannelRequest(params))
|
||||||
});
|
});
|
||||||
|
|
||||||
export default connect(mapStateToProps, mapDispatchToProps)(withTheme(NewMessageView));
|
export default connect(mapStateToProps, mapDispatchToProps)(withTheme(NewMessageView));
|
|
@ -918,7 +918,6 @@ class RoomActionsView extends React.Component {
|
||||||
event: this.convertTeamToChannel
|
event: this.convertTeamToChannel
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
testID='room-actions-convert-channel-to-team'
|
|
||||||
left={() => <List.Icon name='channel-public' />}
|
left={() => <List.Icon name='channel-public' />}
|
||||||
showActionIndicator
|
showActionIndicator
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -1,7 +1,9 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import PropTypes from 'prop-types';
|
|
||||||
import { Switch } from 'react-native';
|
import { Switch } from 'react-native';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
|
import { StackNavigationOptions } from '@react-navigation/stack';
|
||||||
|
import Model from '@nozbe/watermelondb/Model';
|
||||||
|
import { Subscription } from 'rxjs';
|
||||||
|
|
||||||
import I18n from '../i18n';
|
import I18n from '../i18n';
|
||||||
import { withTheme } from '../theme';
|
import { withTheme } from '../theme';
|
||||||
|
@ -16,19 +18,42 @@ import { events, logEvent } from '../utils/log';
|
||||||
|
|
||||||
const DEFAULT_BIOMETRY = false;
|
const DEFAULT_BIOMETRY = false;
|
||||||
|
|
||||||
class ScreenLockConfigView extends React.Component {
|
interface IServerRecords extends Model {
|
||||||
static navigationOptions = () => ({
|
autoLock?: boolean;
|
||||||
|
autoLockTime?: number;
|
||||||
|
biometry?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface IItem {
|
||||||
|
title: string;
|
||||||
|
value: number;
|
||||||
|
disabled?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface IScreenLockConfigViewProps {
|
||||||
|
theme: string;
|
||||||
|
server: string;
|
||||||
|
Force_Screen_Lock: boolean;
|
||||||
|
Force_Screen_Lock_After: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface IScreenLockConfigViewState {
|
||||||
|
autoLock?: boolean;
|
||||||
|
autoLockTime?: number | null;
|
||||||
|
biometry?: boolean;
|
||||||
|
biometryLabel: null;
|
||||||
|
}
|
||||||
|
|
||||||
|
class ScreenLockConfigView extends React.Component<IScreenLockConfigViewProps, IScreenLockConfigViewState> {
|
||||||
|
private serverRecord?: IServerRecords;
|
||||||
|
|
||||||
|
private observable?: Subscription;
|
||||||
|
|
||||||
|
static navigationOptions = (): StackNavigationOptions => ({
|
||||||
title: I18n.t('Screen_lock')
|
title: I18n.t('Screen_lock')
|
||||||
});
|
});
|
||||||
|
|
||||||
static propTypes = {
|
constructor(props: IScreenLockConfigViewProps) {
|
||||||
theme: PropTypes.string,
|
|
||||||
server: PropTypes.string,
|
|
||||||
Force_Screen_Lock: PropTypes.string,
|
|
||||||
Force_Screen_Lock_After: PropTypes.string
|
|
||||||
};
|
|
||||||
|
|
||||||
constructor(props) {
|
|
||||||
super(props);
|
super(props);
|
||||||
this.state = {
|
this.state = {
|
||||||
autoLock: false,
|
autoLock: false,
|
||||||
|
@ -104,7 +129,7 @@ class ScreenLockConfigView extends React.Component {
|
||||||
logEvent(events.SLC_SAVE_SCREEN_LOCK);
|
logEvent(events.SLC_SAVE_SCREEN_LOCK);
|
||||||
const { autoLock, autoLockTime, biometry } = this.state;
|
const { autoLock, autoLockTime, biometry } = this.state;
|
||||||
const serversDB = database.servers;
|
const serversDB = database.servers;
|
||||||
await serversDB.action(async () => {
|
await serversDB.write(async () => {
|
||||||
await this.serverRecord?.update(record => {
|
await this.serverRecord?.update(record => {
|
||||||
record.autoLock = autoLock;
|
record.autoLock = autoLock;
|
||||||
record.autoLockTime = autoLockTime === null ? DEFAULT_AUTO_LOCK : autoLockTime;
|
record.autoLockTime = autoLockTime === null ? DEFAULT_AUTO_LOCK : autoLockTime;
|
||||||
|
@ -113,7 +138,7 @@ class ScreenLockConfigView extends React.Component {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
changePasscode = async ({ force }) => {
|
changePasscode = async ({ force }: { force: boolean }) => {
|
||||||
logEvent(events.SLC_CHANGE_PASSCODE);
|
logEvent(events.SLC_CHANGE_PASSCODE);
|
||||||
await changePasscode({ force });
|
await changePasscode({ force });
|
||||||
};
|
};
|
||||||
|
@ -144,12 +169,12 @@ class ScreenLockConfigView extends React.Component {
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
isSelected = value => {
|
isSelected = (value: number) => {
|
||||||
const { autoLockTime } = this.state;
|
const { autoLockTime } = this.state;
|
||||||
return autoLockTime === value;
|
return autoLockTime === value;
|
||||||
};
|
};
|
||||||
|
|
||||||
changeAutoLockTime = autoLockTime => {
|
changeAutoLockTime = (autoLockTime: number) => {
|
||||||
logEvent(events.SLC_CHANGE_AUTOLOCK_TIME);
|
logEvent(events.SLC_CHANGE_AUTOLOCK_TIME);
|
||||||
this.setState({ autoLockTime }, () => this.save());
|
this.setState({ autoLockTime }, () => this.save());
|
||||||
};
|
};
|
||||||
|
@ -159,7 +184,7 @@ class ScreenLockConfigView extends React.Component {
|
||||||
return <List.Icon name='check' color={themes[theme].tintColor} />;
|
return <List.Icon name='check' color={themes[theme].tintColor} />;
|
||||||
};
|
};
|
||||||
|
|
||||||
renderItem = ({ item }) => {
|
renderItem = ({ item }: { item: IItem }) => {
|
||||||
const { title, value, disabled } = item;
|
const { title, value, disabled } = item;
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
@ -194,7 +219,7 @@ class ScreenLockConfigView extends React.Component {
|
||||||
if (!autoLock) {
|
if (!autoLock) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
let items = this.defaultAutoLockOptions;
|
let items: IItem[] = this.defaultAutoLockOptions;
|
||||||
if (Force_Screen_Lock && Force_Screen_Lock_After > 0) {
|
if (Force_Screen_Lock && Force_Screen_Lock_After > 0) {
|
||||||
items = [
|
items = [
|
||||||
{
|
{
|
||||||
|
@ -262,7 +287,7 @@ class ScreenLockConfigView extends React.Component {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const mapStateToProps = state => ({
|
const mapStateToProps = (state: any) => ({
|
||||||
server: state.server.server,
|
server: state.server.server,
|
||||||
Force_Screen_Lock: state.settings.Force_Screen_Lock,
|
Force_Screen_Lock: state.settings.Force_Screen_Lock,
|
||||||
Force_Screen_Lock_After: state.settings.Force_Screen_Lock_After
|
Force_Screen_Lock_After: state.settings.Force_Screen_Lock_After
|
|
@ -1,19 +1,25 @@
|
||||||
import React, { useEffect, useState } from 'react';
|
import React, { useEffect, useState } from 'react';
|
||||||
import PropTypes from 'prop-types';
|
|
||||||
import Modal from 'react-native-modal';
|
import Modal from 'react-native-modal';
|
||||||
import useDeepCompareEffect from 'use-deep-compare-effect';
|
import useDeepCompareEffect from 'use-deep-compare-effect';
|
||||||
import isEmpty from 'lodash/isEmpty';
|
import isEmpty from 'lodash/isEmpty';
|
||||||
import Orientation from 'react-native-orientation-locker';
|
import Orientation from 'react-native-orientation-locker';
|
||||||
|
|
||||||
import { withTheme } from '../theme';
|
import { useTheme } from '../theme';
|
||||||
import EventEmitter from '../utils/events';
|
import EventEmitter from '../utils/events';
|
||||||
import { LOCAL_AUTHENTICATE_EMITTER } from '../constants/localAuthentication';
|
import { LOCAL_AUTHENTICATE_EMITTER } from '../constants/localAuthentication';
|
||||||
import { isTablet } from '../utils/deviceInfo';
|
import { isTablet } from '../utils/deviceInfo';
|
||||||
import { PasscodeEnter } from '../containers/Passcode';
|
import { PasscodeEnter } from '../containers/Passcode';
|
||||||
|
|
||||||
const ScreenLockedView = ({ theme }) => {
|
interface IData {
|
||||||
|
submit?: () => void;
|
||||||
|
hasBiometry?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
const ScreenLockedView = (): JSX.Element => {
|
||||||
const [visible, setVisible] = useState(false);
|
const [visible, setVisible] = useState(false);
|
||||||
const [data, setData] = useState({});
|
const [data, setData] = useState<IData>({});
|
||||||
|
|
||||||
|
const { theme } = useTheme();
|
||||||
|
|
||||||
useDeepCompareEffect(() => {
|
useDeepCompareEffect(() => {
|
||||||
if (!isEmpty(data)) {
|
if (!isEmpty(data)) {
|
||||||
|
@ -23,7 +29,7 @@ const ScreenLockedView = ({ theme }) => {
|
||||||
}
|
}
|
||||||
}, [data]);
|
}, [data]);
|
||||||
|
|
||||||
const showScreenLock = args => {
|
const showScreenLock = (args: IData) => {
|
||||||
setData(args);
|
setData(args);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -56,13 +62,9 @@ const ScreenLockedView = ({ theme }) => {
|
||||||
style={{ margin: 0 }}
|
style={{ margin: 0 }}
|
||||||
animationIn='fadeIn'
|
animationIn='fadeIn'
|
||||||
animationOut='fadeOut'>
|
animationOut='fadeOut'>
|
||||||
<PasscodeEnter theme={theme} hasBiometry={data?.hasBiometry} finishProcess={onSubmit} />
|
<PasscodeEnter theme={theme} hasBiometry={!!data?.hasBiometry} finishProcess={onSubmit} />
|
||||||
</Modal>
|
</Modal>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
ScreenLockedView.propTypes = {
|
export default ScreenLockedView;
|
||||||
theme: PropTypes.string
|
|
||||||
};
|
|
||||||
|
|
||||||
export default withTheme(ScreenLockedView);
|
|
|
@ -1,6 +1,6 @@
|
||||||
import React, { useEffect, useState } from 'react';
|
import React, { useEffect, useState } from 'react';
|
||||||
import { Switch } from 'react-native';
|
import { Switch } from 'react-native';
|
||||||
import PropTypes from 'prop-types';
|
import { StackNavigationProp } from '@react-navigation/stack';
|
||||||
import AsyncStorage from '@react-native-community/async-storage';
|
import AsyncStorage from '@react-native-community/async-storage';
|
||||||
import { useSelector } from 'react-redux';
|
import { useSelector } from 'react-redux';
|
||||||
|
|
||||||
|
@ -20,11 +20,15 @@ import {
|
||||||
import SafeAreaView from '../containers/SafeAreaView';
|
import SafeAreaView from '../containers/SafeAreaView';
|
||||||
import { isFDroidBuild } from '../constants/environment';
|
import { isFDroidBuild } from '../constants/environment';
|
||||||
|
|
||||||
const SecurityPrivacyView = ({ navigation }) => {
|
interface ISecurityPrivacyViewProps {
|
||||||
|
navigation: StackNavigationProp<any, 'SecurityPrivacyView'>;
|
||||||
|
}
|
||||||
|
|
||||||
|
const SecurityPrivacyView = ({ navigation }: ISecurityPrivacyViewProps): JSX.Element => {
|
||||||
const [crashReportState, setCrashReportState] = useState(getReportCrashErrorsValue());
|
const [crashReportState, setCrashReportState] = useState(getReportCrashErrorsValue());
|
||||||
const [analyticsEventsState, setAnalyticsEventsState] = useState(getReportAnalyticsEventsValue());
|
const [analyticsEventsState, setAnalyticsEventsState] = useState(getReportAnalyticsEventsValue());
|
||||||
|
|
||||||
const e2eEnabled = useSelector(state => state.settings.E2E_Enable);
|
const e2eEnabled = useSelector((state: any) => state.settings.E2E_Enable);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
navigation.setOptions({
|
navigation.setOptions({
|
||||||
|
@ -32,21 +36,22 @@ const SecurityPrivacyView = ({ navigation }) => {
|
||||||
});
|
});
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const toggleCrashReport = value => {
|
const toggleCrashReport = (value: boolean) => {
|
||||||
logEvent(events.SE_TOGGLE_CRASH_REPORT);
|
logEvent(events.SP_TOGGLE_CRASH_REPORT);
|
||||||
AsyncStorage.setItem(CRASH_REPORT_KEY, JSON.stringify(value));
|
AsyncStorage.setItem(CRASH_REPORT_KEY, JSON.stringify(value));
|
||||||
setCrashReportState(value);
|
setCrashReportState(value);
|
||||||
toggleCrashErrorsReport(value);
|
toggleCrashErrorsReport(value);
|
||||||
};
|
};
|
||||||
|
|
||||||
const toggleAnalyticsEvents = value => {
|
const toggleAnalyticsEvents = (value: boolean) => {
|
||||||
logEvent(events.SE_TOGGLE_ANALYTICS_EVENTS);
|
logEvent(events.SP_TOGGLE_ANALYTICS_EVENTS);
|
||||||
AsyncStorage.setItem(ANALYTICS_EVENTS_KEY, JSON.stringify(value));
|
AsyncStorage.setItem(ANALYTICS_EVENTS_KEY, JSON.stringify(value));
|
||||||
setAnalyticsEventsState(value);
|
setAnalyticsEventsState(value);
|
||||||
toggleAnalyticsEventsReport(value);
|
toggleAnalyticsEventsReport(value);
|
||||||
};
|
};
|
||||||
|
|
||||||
const navigateToScreen = screen => {
|
const navigateToScreen = (screen: 'E2EEncryptionSecurityView' | 'ScreenLockConfigView') => {
|
||||||
|
// @ts-ignore
|
||||||
logEvent(events[`SP_GO_${screen.replace('View', '').toUpperCase()}`]);
|
logEvent(events[`SP_GO_${screen.replace('View', '').toUpperCase()}`]);
|
||||||
navigation.navigate(screen);
|
navigation.navigate(screen);
|
||||||
};
|
};
|
||||||
|
@ -106,8 +111,4 @@ const SecurityPrivacyView = ({ navigation }) => {
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
SecurityPrivacyView.propTypes = {
|
|
||||||
navigation: PropTypes.object
|
|
||||||
};
|
|
||||||
|
|
||||||
export default SecurityPrivacyView;
|
export default SecurityPrivacyView;
|
|
@ -1,8 +1,9 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import { StackNavigationOptions, StackNavigationProp } from '@react-navigation/stack';
|
||||||
import { FlatList, StyleSheet, Text, View } from 'react-native';
|
import { FlatList, StyleSheet, Text, View } from 'react-native';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { RadioButton } from 'react-native-ui-lib';
|
import { RadioButton } from 'react-native-ui-lib';
|
||||||
|
import { RouteProp } from '@react-navigation/native';
|
||||||
|
|
||||||
import log from '../utils/log';
|
import log from '../utils/log';
|
||||||
import * as List from '../containers/List';
|
import * as List from '../containers/List';
|
||||||
|
@ -25,15 +26,58 @@ const styles = StyleSheet.create({
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
class SelectListView extends React.Component {
|
interface IData {
|
||||||
static propTypes = {
|
rid: string;
|
||||||
navigation: PropTypes.object,
|
name: string;
|
||||||
route: PropTypes.object,
|
t?: string;
|
||||||
theme: PropTypes.string,
|
teamMain?: boolean;
|
||||||
isMasterDetail: PropTypes.bool
|
alert?: boolean;
|
||||||
};
|
}
|
||||||
|
|
||||||
constructor(props) {
|
interface ISelectListViewState {
|
||||||
|
data: IData[];
|
||||||
|
dataFiltered: IData[];
|
||||||
|
isSearching: boolean;
|
||||||
|
selected: string[];
|
||||||
|
}
|
||||||
|
|
||||||
|
interface ISelectListViewProps {
|
||||||
|
navigation: StackNavigationProp<any, 'SelectListView'>;
|
||||||
|
route: RouteProp<
|
||||||
|
{
|
||||||
|
SelectView: {
|
||||||
|
data: IData[];
|
||||||
|
title: string;
|
||||||
|
infoText: string;
|
||||||
|
nextAction(selected: string[]): void;
|
||||||
|
showAlert(): void;
|
||||||
|
isSearch: boolean;
|
||||||
|
onSearch(text: string): IData[];
|
||||||
|
isRadio: boolean;
|
||||||
|
};
|
||||||
|
},
|
||||||
|
'SelectView'
|
||||||
|
>;
|
||||||
|
theme: string;
|
||||||
|
isMasterDetail: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
class SelectListView extends React.Component<ISelectListViewProps, ISelectListViewState> {
|
||||||
|
private title: string;
|
||||||
|
|
||||||
|
private infoText: string;
|
||||||
|
|
||||||
|
private nextAction: (selected: string[]) => void;
|
||||||
|
|
||||||
|
private showAlert: () => void;
|
||||||
|
|
||||||
|
private isSearch: boolean;
|
||||||
|
|
||||||
|
private onSearch: (text: string) => IData[];
|
||||||
|
|
||||||
|
private isRadio: boolean;
|
||||||
|
|
||||||
|
constructor(props: ISelectListViewProps) {
|
||||||
super(props);
|
super(props);
|
||||||
const data = props.route?.params?.data;
|
const data = props.route?.params?.data;
|
||||||
this.title = props.route?.params?.title;
|
this.title = props.route?.params?.title;
|
||||||
|
@ -56,7 +100,7 @@ class SelectListView extends React.Component {
|
||||||
const { navigation, isMasterDetail } = this.props;
|
const { navigation, isMasterDetail } = this.props;
|
||||||
const { selected } = this.state;
|
const { selected } = this.state;
|
||||||
|
|
||||||
const options = {
|
const options: StackNavigationOptions = {
|
||||||
headerTitle: I18n.t(this.title)
|
headerTitle: I18n.t(this.title)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -87,7 +131,7 @@ class SelectListView extends React.Component {
|
||||||
return (
|
return (
|
||||||
<View style={{ backgroundColor: themes[theme].auxiliaryBackground }}>
|
<View style={{ backgroundColor: themes[theme].auxiliaryBackground }}>
|
||||||
<SearchBox
|
<SearchBox
|
||||||
onChangeText={text => this.search(text)}
|
onChangeText={(text: string) => this.search(text)}
|
||||||
testID='select-list-view-search'
|
testID='select-list-view-search'
|
||||||
onCancelPress={() => this.setState({ isSearching: false })}
|
onCancelPress={() => this.setState({ isSearching: false })}
|
||||||
/>
|
/>
|
||||||
|
@ -95,7 +139,7 @@ class SelectListView extends React.Component {
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
search = async text => {
|
search = async (text: string) => {
|
||||||
try {
|
try {
|
||||||
this.setState({ isSearching: true });
|
this.setState({ isSearching: true });
|
||||||
const result = await this.onSearch(text);
|
const result = await this.onSearch(text);
|
||||||
|
@ -105,12 +149,12 @@ class SelectListView extends React.Component {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
isChecked = rid => {
|
isChecked = (rid: string) => {
|
||||||
const { selected } = this.state;
|
const { selected } = this.state;
|
||||||
return selected.includes(rid);
|
return selected.includes(rid);
|
||||||
};
|
};
|
||||||
|
|
||||||
toggleItem = rid => {
|
toggleItem = (rid: string) => {
|
||||||
const { selected } = this.state;
|
const { selected } = this.state;
|
||||||
|
|
||||||
animateNextTransition();
|
animateNextTransition();
|
||||||
|
@ -126,7 +170,7 @@ class SelectListView extends React.Component {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
renderItem = ({ item }) => {
|
renderItem = ({ item }: { item: IData }) => {
|
||||||
const { theme } = this.props;
|
const { theme } = this.props;
|
||||||
const { selected } = this.state;
|
const { selected } = this.state;
|
||||||
|
|
||||||
|
@ -187,7 +231,7 @@ class SelectListView extends React.Component {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const mapStateToProps = state => ({
|
const mapStateToProps = (state: any) => ({
|
||||||
isMasterDetail: state.app.isMasterDetail
|
isMasterDetail: state.app.isMasterDetail
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { FlatList } from 'react-native';
|
import { FlatList } from 'react-native';
|
||||||
import PropTypes from 'prop-types';
|
import { StackNavigationOptions, StackNavigationProp } from '@react-navigation/stack';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { Q } from '@nozbe/watermelondb';
|
import { Q, Model } from '@nozbe/watermelondb';
|
||||||
|
|
||||||
import I18n from '../i18n';
|
import I18n from '../i18n';
|
||||||
import StatusBar from '../containers/StatusBar';
|
import StatusBar from '../containers/StatusBar';
|
||||||
|
@ -12,29 +12,39 @@ import database from '../lib/database';
|
||||||
import SafeAreaView from '../containers/SafeAreaView';
|
import SafeAreaView from '../containers/SafeAreaView';
|
||||||
import * as List from '../containers/List';
|
import * as List from '../containers/List';
|
||||||
|
|
||||||
const getItemLayout = (data, index) => ({ length: ROW_HEIGHT, offset: ROW_HEIGHT * index, index });
|
const getItemLayout = (data: any, index: number) => ({ length: ROW_HEIGHT, offset: ROW_HEIGHT * index, index });
|
||||||
const keyExtractor = item => item.id;
|
const keyExtractor = (item: IServer) => item.id;
|
||||||
|
|
||||||
class SelectServerView extends React.Component {
|
interface IServer extends Model {
|
||||||
static navigationOptions = () => ({
|
id: string;
|
||||||
|
iconURL?: string;
|
||||||
|
name?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface ISelectServerViewState {
|
||||||
|
servers: IServer[];
|
||||||
|
}
|
||||||
|
|
||||||
|
interface ISelectServerViewProps {
|
||||||
|
navigation: StackNavigationProp<any, 'SelectServerView'>;
|
||||||
|
server: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
class SelectServerView extends React.Component<ISelectServerViewProps, ISelectServerViewState> {
|
||||||
|
static navigationOptions = (): StackNavigationOptions => ({
|
||||||
title: I18n.t('Select_Server')
|
title: I18n.t('Select_Server')
|
||||||
});
|
});
|
||||||
|
|
||||||
static propTypes = {
|
state = { servers: [] as IServer[] };
|
||||||
server: PropTypes.string,
|
|
||||||
navigation: PropTypes.object
|
|
||||||
};
|
|
||||||
|
|
||||||
state = { servers: [] };
|
|
||||||
|
|
||||||
async componentDidMount() {
|
async componentDidMount() {
|
||||||
const serversDB = database.servers;
|
const serversDB = database.servers;
|
||||||
const serversCollection = serversDB.get('servers');
|
const serversCollection = serversDB.get('servers');
|
||||||
const servers = await serversCollection.query(Q.where('rooms_updated_at', Q.notEq(null))).fetch();
|
const servers: IServer[] = await serversCollection.query(Q.where('rooms_updated_at', Q.notEq(null))).fetch();
|
||||||
this.setState({ servers });
|
this.setState({ servers });
|
||||||
}
|
}
|
||||||
|
|
||||||
select = async server => {
|
select = async (server: string) => {
|
||||||
const { server: currentServer, navigation } = this.props;
|
const { server: currentServer, navigation } = this.props;
|
||||||
|
|
||||||
navigation.navigate('ShareListView');
|
navigation.navigate('ShareListView');
|
||||||
|
@ -43,7 +53,7 @@ class SelectServerView extends React.Component {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
renderItem = ({ item }) => {
|
renderItem = ({ item }: { item: IServer }) => {
|
||||||
const { server } = this.props;
|
const { server } = this.props;
|
||||||
return <ServerItem onPress={() => this.select(item.id)} item={item} hasCheck={item.id === server} />;
|
return <ServerItem onPress={() => this.select(item.id)} item={item} hasCheck={item.id === server} />;
|
||||||
};
|
};
|
||||||
|
@ -62,7 +72,6 @@ class SelectServerView extends React.Component {
|
||||||
ItemSeparatorComponent={List.Separator}
|
ItemSeparatorComponent={List.Separator}
|
||||||
ListHeaderComponent={List.Separator}
|
ListHeaderComponent={List.Separator}
|
||||||
ListFooterComponent={List.Separator}
|
ListFooterComponent={List.Separator}
|
||||||
enableEmptySections
|
|
||||||
removeClippedSubviews
|
removeClippedSubviews
|
||||||
keyboardShouldPersistTaps='always'
|
keyboardShouldPersistTaps='always'
|
||||||
/>
|
/>
|
||||||
|
@ -71,7 +80,7 @@ class SelectServerView extends React.Component {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const mapStateToProps = ({ share }) => ({
|
const mapStateToProps = ({ share }: any) => ({
|
||||||
server: share.server.server
|
server: share.server.server
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,8 +1,10 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import { StackNavigationOptions, StackNavigationProp } from '@react-navigation/stack';
|
||||||
|
import { Dispatch } from 'redux';
|
||||||
import { ScrollView, StyleSheet, Text } from 'react-native';
|
import { ScrollView, StyleSheet, Text } from 'react-native';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import Orientation from 'react-native-orientation-locker';
|
import Orientation from 'react-native-orientation-locker';
|
||||||
|
import { RouteProp } from '@react-navigation/native';
|
||||||
|
|
||||||
import { loginRequest as loginRequestAction } from '../actions/login';
|
import { loginRequest as loginRequestAction } from '../actions/login';
|
||||||
import TextInput from '../containers/TextInput';
|
import TextInput from '../containers/TextInput';
|
||||||
|
@ -27,21 +29,27 @@ const styles = StyleSheet.create({
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
class SetUsernameView extends React.Component {
|
interface ISetUsernameViewState {
|
||||||
static navigationOptions = ({ route }) => ({
|
username: string;
|
||||||
|
saving: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface ISetUsernameViewProps {
|
||||||
|
navigation: StackNavigationProp<any, 'SetUsernameView'>;
|
||||||
|
route: RouteProp<{ SetUsernameView: { title: string } }, 'SetUsernameView'>;
|
||||||
|
server: string;
|
||||||
|
userId: string;
|
||||||
|
loginRequest: ({ resume }: { resume: string }) => void;
|
||||||
|
token: string;
|
||||||
|
theme: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
class SetUsernameView extends React.Component<ISetUsernameViewProps, ISetUsernameViewState> {
|
||||||
|
static navigationOptions = ({ route }: Pick<ISetUsernameViewProps, 'route'>): StackNavigationOptions => ({
|
||||||
title: route.params?.title
|
title: route.params?.title
|
||||||
});
|
});
|
||||||
|
|
||||||
static propTypes = {
|
constructor(props: ISetUsernameViewProps) {
|
||||||
navigation: PropTypes.object,
|
|
||||||
server: PropTypes.string,
|
|
||||||
userId: PropTypes.string,
|
|
||||||
loginRequest: PropTypes.func,
|
|
||||||
token: PropTypes.string,
|
|
||||||
theme: PropTypes.string
|
|
||||||
};
|
|
||||||
|
|
||||||
constructor(props) {
|
|
||||||
super(props);
|
super(props);
|
||||||
this.state = {
|
this.state = {
|
||||||
username: '',
|
username: '',
|
||||||
|
@ -61,7 +69,7 @@ class SetUsernameView extends React.Component {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
shouldComponentUpdate(nextProps, nextState) {
|
shouldComponentUpdate(nextProps: ISetUsernameViewProps, nextState: ISetUsernameViewState) {
|
||||||
const { username, saving } = this.state;
|
const { username, saving } = this.state;
|
||||||
const { theme } = this.props;
|
const { theme } = this.props;
|
||||||
if (nextProps.theme !== theme) {
|
if (nextProps.theme !== theme) {
|
||||||
|
@ -88,7 +96,7 @@ class SetUsernameView extends React.Component {
|
||||||
try {
|
try {
|
||||||
await RocketChat.saveUserProfile({ username });
|
await RocketChat.saveUserProfile({ username });
|
||||||
await loginRequest({ resume: token });
|
await loginRequest({ resume: token });
|
||||||
} catch (e) {
|
} catch (e: any) {
|
||||||
showErrorAlert(e.message, I18n.t('Oops'));
|
showErrorAlert(e.message, I18n.t('Oops'));
|
||||||
}
|
}
|
||||||
this.setState({ saving: false });
|
this.setState({ saving: false });
|
||||||
|
@ -136,13 +144,13 @@ class SetUsernameView extends React.Component {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const mapStateToProps = state => ({
|
const mapStateToProps = (state: any) => ({
|
||||||
server: state.server.server,
|
server: state.server.server,
|
||||||
token: getUserSelector(state).token
|
token: getUserSelector(state).token
|
||||||
});
|
});
|
||||||
|
|
||||||
const mapDispatchToProps = dispatch => ({
|
const mapDispatchToProps = (dispatch: Dispatch) => ({
|
||||||
loginRequest: params => dispatch(loginRequestAction(params))
|
loginRequest: (params: { resume: string }) => dispatch(loginRequestAction(params))
|
||||||
});
|
});
|
||||||
|
|
||||||
export default connect(mapStateToProps, mapDispatchToProps)(withTheme(SetUsernameView));
|
export default connect(mapStateToProps, mapDispatchToProps)(withTheme(SetUsernameView));
|
|
@ -1,5 +1,4 @@
|
||||||
import React, { useState } from 'react';
|
import React, { useState } from 'react';
|
||||||
import PropTypes from 'prop-types';
|
|
||||||
import { Keyboard, StyleSheet, View } from 'react-native';
|
import { Keyboard, StyleSheet, View } from 'react-native';
|
||||||
import ShareExtension from 'rn-extensions-share';
|
import ShareExtension from 'rn-extensions-share';
|
||||||
|
|
||||||
|
@ -8,6 +7,7 @@ import * as HeaderButton from '../../../containers/HeaderButton';
|
||||||
import { themes } from '../../../constants/colors';
|
import { themes } from '../../../constants/colors';
|
||||||
import sharedStyles from '../../Styles';
|
import sharedStyles from '../../Styles';
|
||||||
import { animateNextTransition } from '../../../utils/layoutAnimation';
|
import { animateNextTransition } from '../../../utils/layoutAnimation';
|
||||||
|
import { IShareListHeaderIos } from './interface';
|
||||||
|
|
||||||
const styles = StyleSheet.create({
|
const styles = StyleSheet.create({
|
||||||
container: {
|
container: {
|
||||||
|
@ -16,10 +16,10 @@ const styles = StyleSheet.create({
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
const Header = React.memo(({ searching, onChangeSearchText, initSearch, cancelSearch, theme }) => {
|
const Header = React.memo(({ searching, onChangeSearchText, initSearch, cancelSearch, theme }: IShareListHeaderIos) => {
|
||||||
const [text, setText] = useState('');
|
const [text, setText] = useState('');
|
||||||
|
|
||||||
const onChangeText = searchText => {
|
const onChangeText = (searchText: string) => {
|
||||||
onChangeSearchText(searchText);
|
onChangeSearchText(searchText);
|
||||||
setText(searchText);
|
setText(searchText);
|
||||||
};
|
};
|
||||||
|
@ -59,12 +59,4 @@ const Header = React.memo(({ searching, onChangeSearchText, initSearch, cancelSe
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
Header.propTypes = {
|
|
||||||
searching: PropTypes.bool,
|
|
||||||
onChangeSearchText: PropTypes.func,
|
|
||||||
initSearch: PropTypes.func,
|
|
||||||
cancelSearch: PropTypes.func,
|
|
||||||
theme: PropTypes.string
|
|
||||||
};
|
|
||||||
|
|
||||||
export default Header;
|
export default Header;
|
|
@ -1,11 +1,11 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { StyleSheet, Text, View } from 'react-native';
|
import { StyleSheet, Text, View } from 'react-native';
|
||||||
import PropTypes from 'prop-types';
|
|
||||||
|
|
||||||
import TextInput from '../../../presentation/TextInput';
|
import TextInput from '../../../presentation/TextInput';
|
||||||
import I18n from '../../../i18n';
|
import I18n from '../../../i18n';
|
||||||
import { themes } from '../../../constants/colors';
|
import { themes } from '../../../constants/colors';
|
||||||
import sharedStyles from '../../Styles';
|
import sharedStyles from '../../Styles';
|
||||||
|
import { IShareListHeader } from './interface';
|
||||||
|
|
||||||
const styles = StyleSheet.create({
|
const styles = StyleSheet.create({
|
||||||
container: {
|
container: {
|
||||||
|
@ -24,7 +24,7 @@ const styles = StyleSheet.create({
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
const Header = React.memo(({ searching, onChangeSearchText, theme }) => {
|
const Header = React.memo(({ searching, onChangeSearchText, theme }: IShareListHeader) => {
|
||||||
const titleColorStyle = { color: themes[theme].headerTintColor };
|
const titleColorStyle = { color: themes[theme].headerTintColor };
|
||||||
const isLight = theme === 'light';
|
const isLight = theme === 'light';
|
||||||
if (searching) {
|
if (searching) {
|
||||||
|
@ -43,10 +43,4 @@ const Header = React.memo(({ searching, onChangeSearchText, theme }) => {
|
||||||
return <Text style={[styles.title, titleColorStyle]}>{I18n.t('Send_to')}</Text>;
|
return <Text style={[styles.title, titleColorStyle]}>{I18n.t('Send_to')}</Text>;
|
||||||
});
|
});
|
||||||
|
|
||||||
Header.propTypes = {
|
|
||||||
searching: PropTypes.bool,
|
|
||||||
onChangeSearchText: PropTypes.func,
|
|
||||||
theme: PropTypes.string
|
|
||||||
};
|
|
||||||
|
|
||||||
export default Header;
|
export default Header;
|
|
@ -1,11 +1,11 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import PropTypes from 'prop-types';
|
|
||||||
|
|
||||||
import Header from './Header';
|
import Header from './Header';
|
||||||
|
import { IShareListHeader } from './interface';
|
||||||
|
|
||||||
const ShareListHeader = React.memo(({ searching, initSearch, cancelSearch, search, theme }) => {
|
const ShareListHeader = React.memo(({ searching, initSearch, cancelSearch, onChangeSearchText, theme }: IShareListHeader) => {
|
||||||
const onSearchChangeText = text => {
|
const onSearchChangeText = (text: string) => {
|
||||||
search(text.trim());
|
onChangeSearchText(text.trim());
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -19,12 +19,4 @@ const ShareListHeader = React.memo(({ searching, initSearch, cancelSearch, searc
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
ShareListHeader.propTypes = {
|
|
||||||
searching: PropTypes.bool,
|
|
||||||
initSearch: PropTypes.func,
|
|
||||||
cancelSearch: PropTypes.func,
|
|
||||||
search: PropTypes.func,
|
|
||||||
theme: PropTypes.string
|
|
||||||
};
|
|
||||||
|
|
||||||
export default ShareListHeader;
|
export default ShareListHeader;
|
|
@ -0,0 +1,13 @@
|
||||||
|
import { TextInputProps } from 'react-native';
|
||||||
|
|
||||||
|
type RequiredOnChangeText = Required<Pick<TextInputProps, 'onChangeText'>>;
|
||||||
|
|
||||||
|
export interface IShareListHeader {
|
||||||
|
searching: boolean;
|
||||||
|
onChangeSearchText: RequiredOnChangeText['onChangeText'];
|
||||||
|
theme: string;
|
||||||
|
initSearch?: () => void;
|
||||||
|
cancelSearch?: () => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export type IShareListHeaderIos = Required<IShareListHeader>;
|
|
@ -1,6 +1,6 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import { StackNavigationProp } from '@react-navigation/stack';
|
||||||
import { BackHandler, FlatList, Keyboard, PermissionsAndroid, ScrollView, Text, View } from 'react-native';
|
import { BackHandler, FlatList, Keyboard, PermissionsAndroid, ScrollView, Text, View, Rationale } from 'react-native';
|
||||||
import ShareExtension from 'rn-extensions-share';
|
import ShareExtension from 'rn-extensions-share';
|
||||||
import * as FileSystem from 'expo-file-system';
|
import * as FileSystem from 'expo-file-system';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
|
@ -25,24 +25,75 @@ import { sanitizeLikeString } from '../../lib/database/utils';
|
||||||
import styles from './styles';
|
import styles from './styles';
|
||||||
import ShareListHeader from './Header';
|
import ShareListHeader from './Header';
|
||||||
|
|
||||||
const permission = {
|
interface IFile {
|
||||||
|
value: string;
|
||||||
|
type: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface IAttachment {
|
||||||
|
filename: string;
|
||||||
|
description: string;
|
||||||
|
size: number;
|
||||||
|
mime: any;
|
||||||
|
path: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface IChat {
|
||||||
|
rid: string;
|
||||||
|
t: string;
|
||||||
|
name: string;
|
||||||
|
fname: string;
|
||||||
|
blocked: boolean;
|
||||||
|
blocker: boolean;
|
||||||
|
prid: string;
|
||||||
|
uids: string[];
|
||||||
|
usernames: string[];
|
||||||
|
topic: string;
|
||||||
|
description: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface IServerInfo {
|
||||||
|
useRealName: boolean;
|
||||||
|
}
|
||||||
|
interface IState {
|
||||||
|
searching: boolean;
|
||||||
|
searchText: string;
|
||||||
|
searchResults: IChat[];
|
||||||
|
chats: IChat[];
|
||||||
|
serversCount: number;
|
||||||
|
attachments: IAttachment[];
|
||||||
|
text: string;
|
||||||
|
loading: boolean;
|
||||||
|
serverInfo: IServerInfo;
|
||||||
|
needsPermission: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface INavigationOption {
|
||||||
|
navigation: StackNavigationProp<any, 'ShareListView'>;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface IShareListViewProps extends INavigationOption {
|
||||||
|
server: string;
|
||||||
|
token: string;
|
||||||
|
userId: string;
|
||||||
|
theme: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const permission: Rationale = {
|
||||||
title: I18n.t('Read_External_Permission'),
|
title: I18n.t('Read_External_Permission'),
|
||||||
message: I18n.t('Read_External_Permission_Message')
|
message: I18n.t('Read_External_Permission_Message'),
|
||||||
|
buttonPositive: 'Ok'
|
||||||
};
|
};
|
||||||
|
|
||||||
const getItemLayout = (data, index) => ({ length: data.length, offset: ROW_HEIGHT * index, index });
|
const getItemLayout = (data: any, index: number) => ({ length: data.length, offset: ROW_HEIGHT * index, index });
|
||||||
const keyExtractor = item => item.rid;
|
const keyExtractor = (item: IChat) => item.rid;
|
||||||
|
|
||||||
class ShareListView extends React.Component {
|
class ShareListView extends React.Component<IShareListViewProps, IState> {
|
||||||
static propTypes = {
|
private unsubscribeFocus: (() => void) | undefined;
|
||||||
navigation: PropTypes.object,
|
|
||||||
server: PropTypes.string,
|
|
||||||
token: PropTypes.string,
|
|
||||||
userId: PropTypes.string,
|
|
||||||
theme: PropTypes.string
|
|
||||||
};
|
|
||||||
|
|
||||||
constructor(props) {
|
private unsubscribeBlur: (() => void) | undefined;
|
||||||
|
|
||||||
|
constructor(props: IShareListViewProps) {
|
||||||
super(props);
|
super(props);
|
||||||
this.state = {
|
this.state = {
|
||||||
searching: false,
|
searching: false,
|
||||||
|
@ -53,7 +104,7 @@ class ShareListView extends React.Component {
|
||||||
attachments: [],
|
attachments: [],
|
||||||
text: '',
|
text: '',
|
||||||
loading: true,
|
loading: true,
|
||||||
serverInfo: null,
|
serverInfo: {} as IServerInfo,
|
||||||
needsPermission: isAndroid || false
|
needsPermission: isAndroid || false
|
||||||
};
|
};
|
||||||
this.setHeader();
|
this.setHeader();
|
||||||
|
@ -70,7 +121,7 @@ class ShareListView extends React.Component {
|
||||||
async componentDidMount() {
|
async componentDidMount() {
|
||||||
const { server } = this.props;
|
const { server } = this.props;
|
||||||
try {
|
try {
|
||||||
const data = await ShareExtension.data();
|
const data = (await ShareExtension.data()) as IFile[];
|
||||||
if (isAndroid) {
|
if (isAndroid) {
|
||||||
await this.askForPermission(data);
|
await this.askForPermission(data);
|
||||||
}
|
}
|
||||||
|
@ -85,7 +136,7 @@ class ShareListView extends React.Component {
|
||||||
size: file.size,
|
size: file.size,
|
||||||
mime: mime.lookup(file.uri),
|
mime: mime.lookup(file.uri),
|
||||||
path: file.uri
|
path: file.uri
|
||||||
}));
|
})) as IAttachment[];
|
||||||
const text = data.filter(item => item.type === 'text').reduce((acc, item) => `${item.value}\n${acc}`, '');
|
const text = data.filter(item => item.type === 'text').reduce((acc, item) => `${item.value}\n${acc}`, '');
|
||||||
this.setState({
|
this.setState({
|
||||||
text,
|
text,
|
||||||
|
@ -98,14 +149,14 @@ class ShareListView extends React.Component {
|
||||||
this.getSubscriptions(server);
|
this.getSubscriptions(server);
|
||||||
}
|
}
|
||||||
|
|
||||||
UNSAFE_componentWillReceiveProps(nextProps) {
|
UNSAFE_componentWillReceiveProps(nextProps: IShareListViewProps) {
|
||||||
const { server } = this.props;
|
const { server } = this.props;
|
||||||
if (nextProps.server !== server) {
|
if (nextProps.server !== server) {
|
||||||
this.getSubscriptions(nextProps.server);
|
this.getSubscriptions(nextProps.server);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
shouldComponentUpdate(nextProps, nextState) {
|
shouldComponentUpdate(nextProps: IShareListViewProps, nextState: IState) {
|
||||||
const { searching, needsPermission } = this.state;
|
const { searching, needsPermission } = this.state;
|
||||||
if (nextState.searching !== searching) {
|
if (nextState.searching !== searching) {
|
||||||
return true;
|
return true;
|
||||||
|
@ -151,7 +202,7 @@ class ShareListView extends React.Component {
|
||||||
searching={searching}
|
searching={searching}
|
||||||
initSearch={this.initSearch}
|
initSearch={this.initSearch}
|
||||||
cancelSearch={this.cancelSearch}
|
cancelSearch={this.cancelSearch}
|
||||||
search={this.search}
|
onChangeSearchText={this.search}
|
||||||
theme={theme}
|
theme={theme}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
|
@ -168,7 +219,7 @@ class ShareListView extends React.Component {
|
||||||
) : (
|
) : (
|
||||||
<HeaderButton.CancelModal onPress={ShareExtension.close} testID='share-extension-close' />
|
<HeaderButton.CancelModal onPress={ShareExtension.close} testID='share-extension-close' />
|
||||||
),
|
),
|
||||||
headerTitle: () => <ShareListHeader searching={searching} search={this.search} theme={theme} />,
|
headerTitle: () => <ShareListHeader searching={searching} onChangeSearchText={this.search} theme={theme} />,
|
||||||
headerRight: () =>
|
headerRight: () =>
|
||||||
searching ? null : (
|
searching ? null : (
|
||||||
<HeaderButton.Container>
|
<HeaderButton.Container>
|
||||||
|
@ -178,16 +229,16 @@ class ShareListView extends React.Component {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
// eslint-disable-next-line react/sort-comp
|
internalSetState = (...args: object[]) => {
|
||||||
internalSetState = (...args) => {
|
|
||||||
const { navigation } = this.props;
|
const { navigation } = this.props;
|
||||||
if (navigation.isFocused()) {
|
if (navigation.isFocused()) {
|
||||||
animateNextTransition();
|
animateNextTransition();
|
||||||
}
|
}
|
||||||
|
// @ts-ignore
|
||||||
this.setState(...args);
|
this.setState(...args);
|
||||||
};
|
};
|
||||||
|
|
||||||
query = async text => {
|
query = async (text?: string) => {
|
||||||
const db = database.active;
|
const db = database.active;
|
||||||
const defaultWhereClause = [
|
const defaultWhereClause = [
|
||||||
Q.where('archived', false),
|
Q.where('archived', false),
|
||||||
|
@ -195,15 +246,16 @@ class ShareListView extends React.Component {
|
||||||
Q.experimentalSkip(0),
|
Q.experimentalSkip(0),
|
||||||
Q.experimentalTake(20),
|
Q.experimentalTake(20),
|
||||||
Q.experimentalSortBy('room_updated_at', Q.desc)
|
Q.experimentalSortBy('room_updated_at', Q.desc)
|
||||||
];
|
] as (Q.WhereDescription | Q.Skip | Q.Take | Q.SortBy | Q.Or)[];
|
||||||
if (text) {
|
if (text) {
|
||||||
const likeString = sanitizeLikeString(text);
|
const likeString = sanitizeLikeString(text);
|
||||||
defaultWhereClause.push(Q.or(Q.where('name', Q.like(`%${likeString}%`)), Q.where('fname', Q.like(`%${likeString}%`))));
|
defaultWhereClause.push(Q.or(Q.where('name', Q.like(`%${likeString}%`)), Q.where('fname', Q.like(`%${likeString}%`))));
|
||||||
}
|
}
|
||||||
const data = await db
|
const data = (await db
|
||||||
.get('subscriptions')
|
.get('subscriptions')
|
||||||
.query(...defaultWhereClause)
|
.query(...defaultWhereClause)
|
||||||
.fetch();
|
.fetch()) as IChat[];
|
||||||
|
|
||||||
return data.map(item => ({
|
return data.map(item => ({
|
||||||
rid: item.rid,
|
rid: item.rid,
|
||||||
t: item.t,
|
t: item.t,
|
||||||
|
@ -218,7 +270,7 @@ class ShareListView extends React.Component {
|
||||||
}));
|
}));
|
||||||
};
|
};
|
||||||
|
|
||||||
getSubscriptions = async server => {
|
getSubscriptions = async (server: string) => {
|
||||||
const serversDB = database.servers;
|
const serversDB = database.servers;
|
||||||
|
|
||||||
if (server) {
|
if (server) {
|
||||||
|
@ -242,7 +294,7 @@ class ShareListView extends React.Component {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
askForPermission = async data => {
|
askForPermission = async (data: IFile[]) => {
|
||||||
const mediaIndex = data.findIndex(item => item.type === 'media');
|
const mediaIndex = data.findIndex(item => item.type === 'media');
|
||||||
if (mediaIndex !== -1) {
|
if (mediaIndex !== -1) {
|
||||||
const result = await PermissionsAndroid.request(PermissionsAndroid.PERMISSIONS.READ_EXTERNAL_STORAGE, permission);
|
const result = await PermissionsAndroid.request(PermissionsAndroid.PERMISSIONS.READ_EXTERNAL_STORAGE, permission);
|
||||||
|
@ -255,15 +307,14 @@ class ShareListView extends React.Component {
|
||||||
return Promise.resolve();
|
return Promise.resolve();
|
||||||
};
|
};
|
||||||
|
|
||||||
uriToPath = uri => decodeURIComponent(isIOS ? uri.replace(/^file:\/\//, '') : uri);
|
uriToPath = (uri: string) => decodeURIComponent(isIOS ? uri.replace(/^file:\/\//, '') : uri);
|
||||||
|
|
||||||
getRoomTitle = item => {
|
getRoomTitle = (item: IChat) => {
|
||||||
const { serverInfo } = this.state;
|
const { serverInfo } = this.state;
|
||||||
const { useRealName } = serverInfo;
|
return ((item.prid || serverInfo?.useRealName) && item.fname) || item.name;
|
||||||
return ((item.prid || useRealName) && item.fname) || item.name;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
shareMessage = room => {
|
shareMessage = (room: IChat) => {
|
||||||
const { attachments, text, serverInfo } = this.state;
|
const { attachments, text, serverInfo } = this.state;
|
||||||
const { navigation } = this.props;
|
const { navigation } = this.props;
|
||||||
|
|
||||||
|
@ -276,7 +327,7 @@ class ShareListView extends React.Component {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
search = async text => {
|
search = async (text: string) => {
|
||||||
const result = await this.query(text);
|
const result = await this.query(text);
|
||||||
this.internalSetState({
|
this.internalSetState({
|
||||||
searchResults: result,
|
searchResults: result,
|
||||||
|
@ -303,7 +354,7 @@ class ShareListView extends React.Component {
|
||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
|
|
||||||
renderSectionHeader = header => {
|
renderSectionHeader = (header: string) => {
|
||||||
const { searching } = this.state;
|
const { searching } = this.state;
|
||||||
const { theme } = this.props;
|
const { theme } = this.props;
|
||||||
if (searching) {
|
if (searching) {
|
||||||
|
@ -320,10 +371,9 @@ class ShareListView extends React.Component {
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
renderItem = ({ item }) => {
|
renderItem = ({ item }: { item: IChat }) => {
|
||||||
const { serverInfo } = this.state;
|
const { serverInfo } = this.state;
|
||||||
const { useRealName } = serverInfo;
|
const { theme } = this.props;
|
||||||
const { userId, token, server, theme } = this.props;
|
|
||||||
let description;
|
let description;
|
||||||
switch (item.t) {
|
switch (item.t) {
|
||||||
case 'c':
|
case 'c':
|
||||||
|
@ -333,7 +383,7 @@ class ShareListView extends React.Component {
|
||||||
description = item.topic || item.description;
|
description = item.topic || item.description;
|
||||||
break;
|
break;
|
||||||
case 'd':
|
case 'd':
|
||||||
description = useRealName ? item.name : item.fname;
|
description = serverInfo?.useRealName ? item.name : item.fname;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
description = item.fname;
|
description = item.fname;
|
||||||
|
@ -341,12 +391,7 @@ class ShareListView extends React.Component {
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
<DirectoryItem
|
<DirectoryItem
|
||||||
user={{
|
|
||||||
id: userId,
|
|
||||||
token
|
|
||||||
}}
|
|
||||||
title={this.getRoomTitle(item)}
|
title={this.getRoomTitle(item)}
|
||||||
baseUrl={server}
|
|
||||||
avatar={RocketChat.getRoomAvatar(item)}
|
avatar={RocketChat.getRoomAvatar(item)}
|
||||||
description={description}
|
description={description}
|
||||||
type={item.prid ? 'discussion' : item.t}
|
type={item.prid ? 'discussion' : item.t}
|
||||||
|
@ -439,7 +484,7 @@ class ShareListView extends React.Component {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
const mapStateToProps = ({ share }) => ({
|
const mapStateToProps = ({ share }: any) => ({
|
||||||
userId: share.user && share.user.id,
|
userId: share.user && share.user.id,
|
||||||
token: share.user && share.user.token,
|
token: share.user && share.user.token,
|
||||||
server: share.server.server
|
server: share.server.server
|
|
@ -25,7 +25,7 @@ const Item = React.memo(({ left, right, text, onPress, testID, current, theme }:
|
||||||
style={[styles.item, current && { backgroundColor: themes[theme].borderColor }]}>
|
style={[styles.item, current && { backgroundColor: themes[theme].borderColor }]}>
|
||||||
<View style={styles.itemHorizontal}>{left}</View>
|
<View style={styles.itemHorizontal}>{left}</View>
|
||||||
<View style={styles.itemCenter}>
|
<View style={styles.itemCenter}>
|
||||||
<Text style={[styles.itemText, { color: themes[theme].titleText }]} numberOfLines={1}>
|
<Text style={[styles.itemText, { color: themes[theme].titleText }]} numberOfLines={1} accessibilityLabel={text}>
|
||||||
{text}
|
{text}
|
||||||
</Text>
|
</Text>
|
||||||
</View>
|
</View>
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import { StackNavigationProp } from '@react-navigation/stack';
|
||||||
import { FlatList, StyleSheet } from 'react-native';
|
import { FlatList, StyleSheet } from 'react-native';
|
||||||
|
import { Dispatch } from 'redux';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
|
|
||||||
import I18n from '../i18n';
|
import I18n from '../i18n';
|
||||||
|
@ -53,23 +54,29 @@ const styles = StyleSheet.create({
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
class StatusView extends React.Component {
|
interface IUser {
|
||||||
static propTypes = {
|
id: string;
|
||||||
user: PropTypes.shape({
|
status: string;
|
||||||
id: PropTypes.string,
|
statusText: string;
|
||||||
status: PropTypes.string,
|
}
|
||||||
statusText: PropTypes.string
|
|
||||||
}),
|
|
||||||
theme: PropTypes.string,
|
|
||||||
navigation: PropTypes.object,
|
|
||||||
isMasterDetail: PropTypes.bool,
|
|
||||||
setUser: PropTypes.func,
|
|
||||||
Accounts_AllowInvisibleStatusOption: PropTypes.bool
|
|
||||||
};
|
|
||||||
|
|
||||||
constructor(props) {
|
interface IStatusViewState {
|
||||||
|
statusText: string;
|
||||||
|
loading: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface IStatusViewProps {
|
||||||
|
navigation: StackNavigationProp<any, 'StatusView'>;
|
||||||
|
user: IUser;
|
||||||
|
theme: string;
|
||||||
|
isMasterDetail: boolean;
|
||||||
|
setUser: (user: Partial<IUser>) => void;
|
||||||
|
Accounts_AllowInvisibleStatusOption: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
class StatusView extends React.Component<IStatusViewProps, IStatusViewState> {
|
||||||
|
constructor(props: IStatusViewProps) {
|
||||||
super(props);
|
super(props);
|
||||||
|
|
||||||
const { statusText } = props.user;
|
const { statusText } = props.user;
|
||||||
this.state = { statusText: statusText || '', loading: false };
|
this.state = { statusText: statusText || '', loading: false };
|
||||||
this.setHeader();
|
this.setHeader();
|
||||||
|
@ -103,7 +110,7 @@ class StatusView extends React.Component {
|
||||||
navigation.goBack();
|
navigation.goBack();
|
||||||
};
|
};
|
||||||
|
|
||||||
setCustomStatus = async statusText => {
|
setCustomStatus = async (statusText: string) => {
|
||||||
const { user, setUser } = this.props;
|
const { user, setUser } = this.props;
|
||||||
|
|
||||||
this.setState({ loading: true });
|
this.setState({ loading: true });
|
||||||
|
@ -147,7 +154,7 @@ class StatusView extends React.Component {
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
renderItem = ({ item }) => {
|
renderItem = ({ item }: { item: { id: string; name: string } }) => {
|
||||||
const { statusText } = this.state;
|
const { statusText } = this.state;
|
||||||
const { user, setUser } = this.props;
|
const { user, setUser } = this.props;
|
||||||
const { id, name } = item;
|
const { id, name } = item;
|
||||||
|
@ -155,6 +162,7 @@ class StatusView extends React.Component {
|
||||||
<List.Item
|
<List.Item
|
||||||
title={name}
|
title={name}
|
||||||
onPress={async () => {
|
onPress={async () => {
|
||||||
|
// @ts-ignore
|
||||||
logEvent(events[`STATUS_${item.id.toUpperCase()}`]);
|
logEvent(events[`STATUS_${item.id.toUpperCase()}`]);
|
||||||
if (user.status !== item.id) {
|
if (user.status !== item.id) {
|
||||||
try {
|
try {
|
||||||
|
@ -162,7 +170,7 @@ class StatusView extends React.Component {
|
||||||
if (result.success) {
|
if (result.success) {
|
||||||
setUser({ status: item.id });
|
setUser({ status: item.id });
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e: any) {
|
||||||
showErrorAlert(I18n.t(e.data.errorType));
|
showErrorAlert(I18n.t(e.data.errorType));
|
||||||
logEvent(events.SET_STATUS_FAIL);
|
logEvent(events.SET_STATUS_FAIL);
|
||||||
log(e);
|
log(e);
|
||||||
|
@ -197,14 +205,14 @@ class StatusView extends React.Component {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const mapStateToProps = state => ({
|
const mapStateToProps = (state: any) => ({
|
||||||
user: getUserSelector(state),
|
user: getUserSelector(state),
|
||||||
isMasterDetail: state.app.isMasterDetail,
|
isMasterDetail: state.app.isMasterDetail,
|
||||||
Accounts_AllowInvisibleStatusOption: state.settings.Accounts_AllowInvisibleStatusOption ?? true
|
Accounts_AllowInvisibleStatusOption: state.settings.Accounts_AllowInvisibleStatusOption ?? true
|
||||||
});
|
});
|
||||||
|
|
||||||
const mapDispatchToProps = dispatch => ({
|
const mapDispatchToProps = (dispatch: Dispatch) => ({
|
||||||
setUser: user => dispatch(setUserAction(user))
|
setUser: (user: IUser) => dispatch(setUserAction(user))
|
||||||
});
|
});
|
||||||
|
|
||||||
export default connect(mapStateToProps, mapDispatchToProps)(withTheme(StatusView));
|
export default connect(mapStateToProps, mapDispatchToProps)(withTheme(StatusView));
|
|
@ -1,10 +1,11 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { Alert, FlatList, Keyboard } from 'react-native';
|
import { Alert, FlatList, Keyboard } from 'react-native';
|
||||||
import PropTypes from 'prop-types';
|
import { RouteProp } from '@react-navigation/native';
|
||||||
|
import { Dispatch } from 'redux';
|
||||||
import { Q } from '@nozbe/watermelondb';
|
import { Q } from '@nozbe/watermelondb';
|
||||||
import { withSafeAreaInsets } from 'react-native-safe-area-context';
|
import { EdgeInsets, withSafeAreaInsets } from 'react-native-safe-area-context';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { HeaderBackButton } from '@react-navigation/stack';
|
import { HeaderBackButton, StackNavigationOptions, StackNavigationProp } from '@react-navigation/stack';
|
||||||
|
|
||||||
import StatusBar from '../containers/StatusBar';
|
import StatusBar from '../containers/StatusBar';
|
||||||
import RoomHeader from '../containers/RoomHeader';
|
import RoomHeader from '../containers/RoomHeader';
|
||||||
|
@ -38,35 +39,74 @@ const PERMISSION_EDIT_TEAM_CHANNEL = 'edit-team-channel';
|
||||||
const PERMISSION_REMOVE_TEAM_CHANNEL = 'remove-team-channel';
|
const PERMISSION_REMOVE_TEAM_CHANNEL = 'remove-team-channel';
|
||||||
const PERMISSION_ADD_TEAM_CHANNEL = 'add-team-channel';
|
const PERMISSION_ADD_TEAM_CHANNEL = 'add-team-channel';
|
||||||
|
|
||||||
const getItemLayout = (data, index) => ({
|
const getItemLayout = (data: IItem[] | null | undefined, index: number) => ({
|
||||||
length: data.length,
|
length: data?.length || 0,
|
||||||
offset: ROW_HEIGHT * index,
|
offset: ROW_HEIGHT * index,
|
||||||
index
|
index
|
||||||
});
|
});
|
||||||
const keyExtractor = item => item._id;
|
const keyExtractor = (item: IItem) => item._id;
|
||||||
|
|
||||||
class TeamChannelsView extends React.Component {
|
// This interface comes from request RocketChat.getTeamListRoom
|
||||||
static propTypes = {
|
interface IItem {
|
||||||
route: PropTypes.object,
|
_id: string;
|
||||||
navigation: PropTypes.object,
|
fname: string;
|
||||||
isMasterDetail: PropTypes.bool,
|
customFields: object;
|
||||||
insets: PropTypes.object,
|
broadcast: boolean;
|
||||||
theme: PropTypes.string,
|
encrypted: boolean;
|
||||||
useRealName: PropTypes.bool,
|
name: string;
|
||||||
width: PropTypes.number,
|
t: string;
|
||||||
StoreLastMessage: PropTypes.bool,
|
msgs: number;
|
||||||
addTeamChannelPermission: PropTypes.array,
|
usersCount: number;
|
||||||
editTeamChannelPermission: PropTypes.array,
|
u: { _id: string; name: string };
|
||||||
removeTeamChannelPermission: PropTypes.array,
|
ts: string;
|
||||||
deleteCPermission: PropTypes.array,
|
ro: boolean;
|
||||||
deletePPermission: PropTypes.array,
|
teamId: string;
|
||||||
showActionSheet: PropTypes.func,
|
default: boolean;
|
||||||
deleteRoom: PropTypes.func,
|
sysMes: boolean;
|
||||||
showAvatar: PropTypes.bool,
|
_updatedAt: string;
|
||||||
displayMode: PropTypes.string
|
teamDefault: boolean;
|
||||||
};
|
}
|
||||||
|
|
||||||
constructor(props) {
|
interface ITeamChannelsViewState {
|
||||||
|
loading: boolean;
|
||||||
|
loadingMore: boolean;
|
||||||
|
data: IItem[];
|
||||||
|
isSearching: boolean;
|
||||||
|
searchText: string | null;
|
||||||
|
search: IItem[];
|
||||||
|
end: boolean;
|
||||||
|
showCreate: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface ITeamChannelsViewProps {
|
||||||
|
route: RouteProp<{ TeamChannelsView: { teamId: string } }, 'TeamChannelsView'>;
|
||||||
|
navigation: StackNavigationProp<any, 'TeamChannelsView'>;
|
||||||
|
isMasterDetail: boolean;
|
||||||
|
insets: EdgeInsets;
|
||||||
|
theme: string;
|
||||||
|
useRealName: boolean;
|
||||||
|
width: number;
|
||||||
|
StoreLastMessage: boolean;
|
||||||
|
addTeamChannelPermission: string[];
|
||||||
|
editTeamChannelPermission: string[];
|
||||||
|
removeTeamChannelPermission: string[];
|
||||||
|
deleteCPermission: string[];
|
||||||
|
deletePPermission: string[];
|
||||||
|
showActionSheet: (options: any) => void;
|
||||||
|
deleteRoom: (rid: string, t: string) => void;
|
||||||
|
showAvatar: boolean;
|
||||||
|
displayMode: string;
|
||||||
|
}
|
||||||
|
class TeamChannelsView extends React.Component<ITeamChannelsViewProps, ITeamChannelsViewState> {
|
||||||
|
private teamId: string;
|
||||||
|
|
||||||
|
// TODO: Refactor when migrate room
|
||||||
|
private teamChannels: any;
|
||||||
|
|
||||||
|
// TODO: Refactor when migrate room
|
||||||
|
private team: any;
|
||||||
|
|
||||||
|
constructor(props: ITeamChannelsViewProps) {
|
||||||
super(props);
|
super(props);
|
||||||
this.teamId = props.route.params?.teamId;
|
this.teamId = props.route.params?.teamId;
|
||||||
this.state = {
|
this.state = {
|
||||||
|
@ -95,7 +135,7 @@ class TeamChannelsView extends React.Component {
|
||||||
try {
|
try {
|
||||||
const subCollection = db.get('subscriptions');
|
const subCollection = db.get('subscriptions');
|
||||||
this.teamChannels = await subCollection.query(Q.where('team_id', Q.eq(this.teamId)));
|
this.teamChannels = await subCollection.query(Q.where('team_id', Q.eq(this.teamId)));
|
||||||
this.team = this.teamChannels?.find(channel => channel.teamMain);
|
this.team = this.teamChannels?.find((channel: any) => channel.teamMain);
|
||||||
this.setHeader();
|
this.setHeader();
|
||||||
|
|
||||||
if (!this.team) {
|
if (!this.team) {
|
||||||
|
@ -140,7 +180,7 @@ class TeamChannelsView extends React.Component {
|
||||||
loading: false,
|
loading: false,
|
||||||
loadingMore: false,
|
loadingMore: false,
|
||||||
end: result.rooms.length < API_FETCH_COUNT
|
end: result.rooms.length < API_FETCH_COUNT
|
||||||
};
|
} as ITeamChannelsViewState;
|
||||||
|
|
||||||
if (isSearching) {
|
if (isSearching) {
|
||||||
newState.search = [...search, ...result.rooms];
|
newState.search = [...search, ...result.rooms];
|
||||||
|
@ -170,7 +210,7 @@ class TeamChannelsView extends React.Component {
|
||||||
const headerTitlePosition = getHeaderTitlePosition({ insets, numIconsRight: 2 });
|
const headerTitlePosition = getHeaderTitlePosition({ insets, numIconsRight: 2 });
|
||||||
|
|
||||||
if (isSearching) {
|
if (isSearching) {
|
||||||
const options = {
|
const options: StackNavigationOptions = {
|
||||||
headerTitleAlign: 'left',
|
headerTitleAlign: 'left',
|
||||||
headerLeft: () => (
|
headerLeft: () => (
|
||||||
<HeaderButton.Container left>
|
<HeaderButton.Container left>
|
||||||
|
@ -187,7 +227,7 @@ class TeamChannelsView extends React.Component {
|
||||||
return navigation.setOptions(options);
|
return navigation.setOptions(options);
|
||||||
}
|
}
|
||||||
|
|
||||||
const options = {
|
const options: StackNavigationOptions = {
|
||||||
headerShown: true,
|
headerShown: true,
|
||||||
headerTitleAlign: 'left',
|
headerTitleAlign: 'left',
|
||||||
headerTitleContainerStyle: {
|
headerTitleContainerStyle: {
|
||||||
|
@ -232,7 +272,7 @@ class TeamChannelsView extends React.Component {
|
||||||
this.setState({ isSearching: true }, () => this.setHeader());
|
this.setState({ isSearching: true }, () => this.setHeader());
|
||||||
};
|
};
|
||||||
|
|
||||||
onSearchChangeText = debounce(searchText => {
|
onSearchChangeText = debounce((searchText: string) => {
|
||||||
this.setState(
|
this.setState(
|
||||||
{
|
{
|
||||||
searchText,
|
searchText,
|
||||||
|
@ -270,7 +310,7 @@ class TeamChannelsView extends React.Component {
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
goRoomActionsView = screen => {
|
goRoomActionsView = (screen: string) => {
|
||||||
logEvent(events.TC_GO_ACTIONS);
|
logEvent(events.TC_GO_ACTIONS);
|
||||||
const { team } = this;
|
const { team } = this;
|
||||||
const { navigation, isMasterDetail } = this.props;
|
const { navigation, isMasterDetail } = this.props;
|
||||||
|
@ -293,12 +333,12 @@ class TeamChannelsView extends React.Component {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
getRoomTitle = item => RocketChat.getRoomTitle(item);
|
getRoomTitle = (item: IItem) => RocketChat.getRoomTitle(item);
|
||||||
|
|
||||||
getRoomAvatar = item => RocketChat.getRoomAvatar(item);
|
getRoomAvatar = (item: IItem) => RocketChat.getRoomAvatar(item);
|
||||||
|
|
||||||
onPressItem = debounce(
|
onPressItem = debounce(
|
||||||
async item => {
|
async (item: IItem) => {
|
||||||
logEvent(events.TC_GO_ROOM);
|
logEvent(events.TC_GO_ROOM);
|
||||||
const { navigation, isMasterDetail } = this.props;
|
const { navigation, isMasterDetail } = this.props;
|
||||||
try {
|
try {
|
||||||
|
@ -314,7 +354,7 @@ class TeamChannelsView extends React.Component {
|
||||||
navigation.pop();
|
navigation.pop();
|
||||||
}
|
}
|
||||||
goRoom({ item: params, isMasterDetail, navigationMethod: navigation.push });
|
goRoom({ item: params, isMasterDetail, navigationMethod: navigation.push });
|
||||||
} catch (e) {
|
} catch (e: any) {
|
||||||
if (e.data.error === 'not-allowed') {
|
if (e.data.error === 'not-allowed') {
|
||||||
showErrorAlert(I18n.t('error-not-allowed'));
|
showErrorAlert(I18n.t('error-not-allowed'));
|
||||||
} else {
|
} else {
|
||||||
|
@ -326,7 +366,7 @@ class TeamChannelsView extends React.Component {
|
||||||
true
|
true
|
||||||
);
|
);
|
||||||
|
|
||||||
toggleAutoJoin = async item => {
|
toggleAutoJoin = async (item: IItem) => {
|
||||||
logEvent(events.TC_TOGGLE_AUTOJOIN);
|
logEvent(events.TC_TOGGLE_AUTOJOIN);
|
||||||
try {
|
try {
|
||||||
const { data } = this.state;
|
const { data } = this.state;
|
||||||
|
@ -346,7 +386,7 @@ class TeamChannelsView extends React.Component {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
remove = item => {
|
remove = (item: IItem) => {
|
||||||
Alert.alert(
|
Alert.alert(
|
||||||
I18n.t('Confirmation'),
|
I18n.t('Confirmation'),
|
||||||
I18n.t('Remove_Team_Room_Warning'),
|
I18n.t('Remove_Team_Room_Warning'),
|
||||||
|
@ -365,7 +405,7 @@ class TeamChannelsView extends React.Component {
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
removeRoom = async item => {
|
removeRoom = async (item: IItem) => {
|
||||||
logEvent(events.TC_DELETE_ROOM);
|
logEvent(events.TC_DELETE_ROOM);
|
||||||
try {
|
try {
|
||||||
const { data } = this.state;
|
const { data } = this.state;
|
||||||
|
@ -380,7 +420,7 @@ class TeamChannelsView extends React.Component {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
delete = item => {
|
delete = (item: IItem) => {
|
||||||
logEvent(events.TC_DELETE_ROOM);
|
logEvent(events.TC_DELETE_ROOM);
|
||||||
const { deleteRoom } = this.props;
|
const { deleteRoom } = this.props;
|
||||||
|
|
||||||
|
@ -402,7 +442,7 @@ class TeamChannelsView extends React.Component {
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
showChannelActions = async item => {
|
showChannelActions = async (item: IItem) => {
|
||||||
logEvent(events.ROOM_SHOW_BOX_ACTIONS);
|
logEvent(events.ROOM_SHOW_BOX_ACTIONS);
|
||||||
const {
|
const {
|
||||||
showActionSheet,
|
showActionSheet,
|
||||||
|
@ -464,7 +504,7 @@ class TeamChannelsView extends React.Component {
|
||||||
showActionSheet({ options });
|
showActionSheet({ options });
|
||||||
};
|
};
|
||||||
|
|
||||||
renderItem = ({ item }) => {
|
renderItem = ({ item }: { item: IItem }) => {
|
||||||
const { StoreLastMessage, useRealName, theme, width, showAvatar, displayMode } = this.props;
|
const { StoreLastMessage, useRealName, theme, width, showAvatar, displayMode } = this.props;
|
||||||
return (
|
return (
|
||||||
<RoomItem
|
<RoomItem
|
||||||
|
@ -534,7 +574,7 @@ class TeamChannelsView extends React.Component {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const mapStateToProps = state => ({
|
const mapStateToProps = (state: any) => ({
|
||||||
baseUrl: state.server.server,
|
baseUrl: state.server.server,
|
||||||
user: getUserSelector(state),
|
user: getUserSelector(state),
|
||||||
useRealName: state.settings.UI_Use_Real_Name,
|
useRealName: state.settings.UI_Use_Real_Name,
|
||||||
|
@ -549,8 +589,8 @@ const mapStateToProps = state => ({
|
||||||
displayMode: state.sortPreferences.displayMode
|
displayMode: state.sortPreferences.displayMode
|
||||||
});
|
});
|
||||||
|
|
||||||
const mapDispatchToProps = dispatch => ({
|
const mapDispatchToProps = (dispatch: Dispatch) => ({
|
||||||
deleteRoom: (rid, t) => dispatch(deleteRoomAction(rid, t))
|
deleteRoom: (rid: string, t: string) => dispatch(deleteRoomAction(rid, t))
|
||||||
});
|
});
|
||||||
|
|
||||||
export default connect(
|
export default connect(
|
|
@ -1,5 +1,5 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import { StackNavigationOptions } from '@react-navigation/stack';
|
||||||
|
|
||||||
import I18n from '../i18n';
|
import I18n from '../i18n';
|
||||||
import { withTheme } from '../theme';
|
import { withTheme } from '../theme';
|
||||||
|
@ -51,18 +51,29 @@ if (supportSystemTheme()) {
|
||||||
const themeGroup = THEMES.filter(item => item.group === THEME_GROUP);
|
const themeGroup = THEMES.filter(item => item.group === THEME_GROUP);
|
||||||
const darkGroup = THEMES.filter(item => item.group === DARK_GROUP);
|
const darkGroup = THEMES.filter(item => item.group === DARK_GROUP);
|
||||||
|
|
||||||
class ThemeView extends React.Component {
|
interface ITheme {
|
||||||
static navigationOptions = () => ({
|
label: string;
|
||||||
|
value: string;
|
||||||
|
group: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface IThemePreference {
|
||||||
|
currentTheme?: string;
|
||||||
|
darkLevel?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface IThemeViewProps {
|
||||||
|
theme: string;
|
||||||
|
themePreferences: IThemePreference;
|
||||||
|
setTheme(newTheme?: IThemePreference): void;
|
||||||
|
}
|
||||||
|
|
||||||
|
class ThemeView extends React.Component<IThemeViewProps> {
|
||||||
|
static navigationOptions = (): StackNavigationOptions => ({
|
||||||
title: I18n.t('Theme')
|
title: I18n.t('Theme')
|
||||||
});
|
});
|
||||||
|
|
||||||
static propTypes = {
|
isSelected = (item: ITheme) => {
|
||||||
theme: PropTypes.string,
|
|
||||||
themePreferences: PropTypes.object,
|
|
||||||
setTheme: PropTypes.func
|
|
||||||
};
|
|
||||||
|
|
||||||
isSelected = item => {
|
|
||||||
const { themePreferences } = this.props;
|
const { themePreferences } = this.props;
|
||||||
const { group } = item;
|
const { group } = item;
|
||||||
const { darkLevel, currentTheme } = themePreferences;
|
const { darkLevel, currentTheme } = themePreferences;
|
||||||
|
@ -74,11 +85,11 @@ class ThemeView extends React.Component {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
onClick = item => {
|
onClick = (item: ITheme) => {
|
||||||
const { themePreferences } = this.props;
|
const { themePreferences } = this.props;
|
||||||
const { darkLevel, currentTheme } = themePreferences;
|
const { darkLevel, currentTheme } = themePreferences;
|
||||||
const { value, group } = item;
|
const { value, group } = item;
|
||||||
let changes = {};
|
let changes: IThemePreference = {};
|
||||||
if (group === THEME_GROUP && currentTheme !== value) {
|
if (group === THEME_GROUP && currentTheme !== value) {
|
||||||
logEvent(events.THEME_SET_THEME_GROUP, { theme_group: value });
|
logEvent(events.THEME_SET_THEME_GROUP, { theme_group: value });
|
||||||
changes = { currentTheme: value };
|
changes = { currentTheme: value };
|
||||||
|
@ -90,7 +101,7 @@ class ThemeView extends React.Component {
|
||||||
this.setTheme(changes);
|
this.setTheme(changes);
|
||||||
};
|
};
|
||||||
|
|
||||||
setTheme = async theme => {
|
setTheme = async (theme: IThemePreference) => {
|
||||||
const { setTheme, themePreferences } = this.props;
|
const { setTheme, themePreferences } = this.props;
|
||||||
const newTheme = { ...themePreferences, ...theme };
|
const newTheme = { ...themePreferences, ...theme };
|
||||||
setTheme(newTheme);
|
setTheme(newTheme);
|
||||||
|
@ -102,7 +113,7 @@ class ThemeView extends React.Component {
|
||||||
return <List.Icon name='check' color={themes[theme].tintColor} />;
|
return <List.Icon name='check' color={themes[theme].tintColor} />;
|
||||||
};
|
};
|
||||||
|
|
||||||
renderItem = ({ item }) => {
|
renderItem = ({ item }: { item: ITheme }) => {
|
||||||
const { label, value } = item;
|
const { label, value } = item;
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
|
@ -1,10 +1,33 @@
|
||||||
|
const { exec } = require('child_process');
|
||||||
const data = require('../data');
|
const data = require('../data');
|
||||||
|
|
||||||
|
const platformTypes = {
|
||||||
|
android: {
|
||||||
|
// Android types
|
||||||
|
alertButtonType: 'android.widget.Button',
|
||||||
|
scrollViewType: 'android.widget.ScrollView',
|
||||||
|
textInputType: 'android.widget.EditText',
|
||||||
|
textMatcher: 'text'
|
||||||
|
},
|
||||||
|
ios: {
|
||||||
|
// iOS types
|
||||||
|
alertButtonType: '_UIAlertControllerActionView',
|
||||||
|
scrollViewType: 'UIScrollView',
|
||||||
|
textInputType: '_UIAlertControllerTextField',
|
||||||
|
textMatcher: 'label'
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
function sleep(ms) {
|
||||||
|
return new Promise(res => setTimeout(res, ms));
|
||||||
|
}
|
||||||
|
|
||||||
async function navigateToWorkspace(server = data.server) {
|
async function navigateToWorkspace(server = data.server) {
|
||||||
await waitFor(element(by.id('new-server-view')))
|
await waitFor(element(by.id('new-server-view')))
|
||||||
.toBeVisible()
|
.toBeVisible()
|
||||||
.withTimeout(60000);
|
.withTimeout(60000);
|
||||||
await element(by.id('new-server-view-input')).typeText(`${server}\n`);
|
await element(by.id('new-server-view-input')).replaceText(`${server}`);
|
||||||
|
await element(by.id('new-server-view-input')).tapReturnKey();
|
||||||
await waitFor(element(by.id('workspace-view')))
|
await waitFor(element(by.id('workspace-view')))
|
||||||
.toBeVisible()
|
.toBeVisible()
|
||||||
.withTimeout(60000);
|
.withTimeout(60000);
|
||||||
|
@ -41,6 +64,8 @@ async function login(username, password) {
|
||||||
}
|
}
|
||||||
|
|
||||||
async function logout() {
|
async function logout() {
|
||||||
|
const deviceType = device.getPlatform();
|
||||||
|
const { scrollViewType, textMatcher } = platformTypes[deviceType];
|
||||||
await element(by.id('rooms-list-view-sidebar')).tap();
|
await element(by.id('rooms-list-view-sidebar')).tap();
|
||||||
await waitFor(element(by.id('sidebar-view')))
|
await waitFor(element(by.id('sidebar-view')))
|
||||||
.toBeVisible()
|
.toBeVisible()
|
||||||
|
@ -52,14 +77,14 @@ async function logout() {
|
||||||
await waitFor(element(by.id('settings-view')))
|
await waitFor(element(by.id('settings-view')))
|
||||||
.toBeVisible()
|
.toBeVisible()
|
||||||
.withTimeout(2000);
|
.withTimeout(2000);
|
||||||
await element(by.type('UIScrollView')).atIndex(1).scrollTo('bottom');
|
await element(by.type(scrollViewType)).atIndex(1).scrollTo('bottom');
|
||||||
await element(by.id('settings-logout')).tap();
|
await element(by.id('settings-logout')).tap();
|
||||||
const logoutAlertMessage = 'You will be logged out of this application.';
|
const logoutAlertMessage = 'You will be logged out of this application.';
|
||||||
await waitFor(element(by.text(logoutAlertMessage)).atIndex(0))
|
await waitFor(element(by[textMatcher](logoutAlertMessage)).atIndex(0))
|
||||||
.toExist()
|
.toExist()
|
||||||
.withTimeout(10000);
|
.withTimeout(10000);
|
||||||
await expect(element(by.text(logoutAlertMessage)).atIndex(0)).toExist();
|
await expect(element(by[textMatcher](logoutAlertMessage)).atIndex(0)).toExist();
|
||||||
await element(by.text('Logout')).tap();
|
await element(by[textMatcher]('Logout')).atIndex(0).tap();
|
||||||
await waitFor(element(by.id('new-server-view')))
|
await waitFor(element(by.id('new-server-view')))
|
||||||
.toBeVisible()
|
.toBeVisible()
|
||||||
.withTimeout(10000);
|
.withTimeout(10000);
|
||||||
|
@ -67,66 +92,73 @@ async function logout() {
|
||||||
}
|
}
|
||||||
|
|
||||||
async function mockMessage(message, isThread = false) {
|
async function mockMessage(message, isThread = false) {
|
||||||
|
const deviceType = device.getPlatform();
|
||||||
|
const { textMatcher } = platformTypes[deviceType];
|
||||||
const input = isThread ? 'messagebox-input-thread' : 'messagebox-input';
|
const input = isThread ? 'messagebox-input-thread' : 'messagebox-input';
|
||||||
await element(by.id(input)).tap();
|
await element(by.id(input)).replaceText(`${data.random}${message}`);
|
||||||
await element(by.id(input)).typeText(`${data.random}${message}`);
|
await sleep(300);
|
||||||
await element(by.id('messagebox-send-message')).tap();
|
await element(by.id('messagebox-send-message')).tap();
|
||||||
await waitFor(element(by.label(`${data.random}${message}`)))
|
await waitFor(element(by[textMatcher](`${data.random}${message}`)))
|
||||||
.toExist()
|
.toExist()
|
||||||
.withTimeout(60000);
|
.withTimeout(60000);
|
||||||
await expect(element(by.label(`${data.random}${message}`))).toExist();
|
await element(by[textMatcher](`${data.random}${message}`))
|
||||||
await element(by.label(`${data.random}${message}`))
|
|
||||||
.atIndex(0)
|
.atIndex(0)
|
||||||
.tap();
|
.tap();
|
||||||
}
|
}
|
||||||
|
|
||||||
async function starMessage(message) {
|
async function starMessage(message) {
|
||||||
|
const deviceType = device.getPlatform();
|
||||||
|
const { textMatcher } = platformTypes[deviceType];
|
||||||
const messageLabel = `${data.random}${message}`;
|
const messageLabel = `${data.random}${message}`;
|
||||||
await element(by.label(messageLabel)).atIndex(0).longPress();
|
await element(by[textMatcher](messageLabel)).atIndex(0).longPress();
|
||||||
await expect(element(by.id('action-sheet'))).toExist();
|
await expect(element(by.id('action-sheet'))).toExist();
|
||||||
await expect(element(by.id('action-sheet-handle'))).toBeVisible();
|
await expect(element(by.id('action-sheet-handle'))).toBeVisible();
|
||||||
await element(by.id('action-sheet-handle')).swipe('up', 'fast', 0.5);
|
await element(by.id('action-sheet-handle')).swipe('up', 'fast', 0.5);
|
||||||
await element(by.label('Star')).atIndex(0).tap();
|
await element(by[textMatcher]('Star')).atIndex(0).tap();
|
||||||
await waitFor(element(by.id('action-sheet')))
|
await waitFor(element(by.id('action-sheet')))
|
||||||
.not.toExist()
|
.not.toExist()
|
||||||
.withTimeout(5000);
|
.withTimeout(5000);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function pinMessage(message) {
|
async function pinMessage(message) {
|
||||||
|
const deviceType = device.getPlatform();
|
||||||
|
const { textMatcher } = platformTypes[deviceType];
|
||||||
const messageLabel = `${data.random}${message}`;
|
const messageLabel = `${data.random}${message}`;
|
||||||
await waitFor(element(by.label(messageLabel)).atIndex(0)).toExist();
|
await waitFor(element(by[textMatcher](messageLabel)).atIndex(0)).toExist();
|
||||||
await element(by.label(messageLabel)).atIndex(0).longPress();
|
await element(by[textMatcher](messageLabel)).atIndex(0).longPress();
|
||||||
await expect(element(by.id('action-sheet'))).toExist();
|
await expect(element(by.id('action-sheet'))).toExist();
|
||||||
await expect(element(by.id('action-sheet-handle'))).toBeVisible();
|
await expect(element(by.id('action-sheet-handle'))).toBeVisible();
|
||||||
await element(by.id('action-sheet-handle')).swipe('up', 'fast', 0.5);
|
await element(by.id('action-sheet-handle')).swipe('up', 'fast', 0.5);
|
||||||
await element(by.label('Pin')).atIndex(0).tap();
|
await element(by[textMatcher]('Pin')).atIndex(0).tap();
|
||||||
await waitFor(element(by.id('action-sheet')))
|
await waitFor(element(by.id('action-sheet')))
|
||||||
.not.toExist()
|
.not.toExist()
|
||||||
.withTimeout(5000);
|
.withTimeout(5000);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function dismissReviewNag() {
|
async function dismissReviewNag() {
|
||||||
await waitFor(element(by.text('Are you enjoying this app?')))
|
const deviceType = device.getPlatform();
|
||||||
|
const { textMatcher } = platformTypes[deviceType];
|
||||||
|
await waitFor(element(by[textMatcher]('Are you enjoying this app?')))
|
||||||
.toExist()
|
.toExist()
|
||||||
.withTimeout(60000);
|
.withTimeout(60000);
|
||||||
await element(by.label('No').and(by.type('_UIAlertControllerActionView'))).tap(); // Tap `no` on ask for review alert
|
await element(by[textMatcher]('No')).atIndex(0).tap(); // Tap `no` on ask for review alert
|
||||||
}
|
}
|
||||||
|
|
||||||
async function tapBack() {
|
async function tapBack() {
|
||||||
await element(by.id('header-back')).atIndex(0).tap();
|
await element(by.id('header-back')).atIndex(0).tap();
|
||||||
}
|
}
|
||||||
|
|
||||||
function sleep(ms) {
|
|
||||||
return new Promise(res => setTimeout(res, ms));
|
|
||||||
}
|
|
||||||
|
|
||||||
async function searchRoom(room) {
|
async function searchRoom(room) {
|
||||||
|
await waitFor(element(by.id('rooms-list-view')))
|
||||||
|
.toBeVisible()
|
||||||
|
.withTimeout(30000);
|
||||||
await element(by.id('rooms-list-view-search')).tap();
|
await element(by.id('rooms-list-view-search')).tap();
|
||||||
await expect(element(by.id('rooms-list-view-search-input'))).toExist();
|
await expect(element(by.id('rooms-list-view-search-input'))).toExist();
|
||||||
await waitFor(element(by.id('rooms-list-view-search-input')))
|
await waitFor(element(by.id('rooms-list-view-search-input')))
|
||||||
.toExist()
|
.toExist()
|
||||||
.withTimeout(5000);
|
.withTimeout(5000);
|
||||||
await element(by.id('rooms-list-view-search-input')).typeText(room);
|
await sleep(300);
|
||||||
|
await element(by.id('rooms-list-view-search-input')).replaceText(room);
|
||||||
await sleep(300);
|
await sleep(300);
|
||||||
await waitFor(element(by.id(`rooms-list-view-item-${room}`)))
|
await waitFor(element(by.id(`rooms-list-view-item-${room}`)))
|
||||||
.toBeVisible()
|
.toBeVisible()
|
||||||
|
@ -162,6 +194,29 @@ const checkServer = async server => {
|
||||||
await element(by.id('sidebar-close-drawer')).tap();
|
await element(by.id('sidebar-close-drawer')).tap();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
function runCommand(command) {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
exec(command, (error, stdout, stderr) => {
|
||||||
|
if (error) {
|
||||||
|
reject(new Error(`exec error: ${stderr}`));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
resolve();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async function prepareAndroid() {
|
||||||
|
if (device.getPlatform() !== 'android') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
await runCommand('adb shell settings put secure spell_checker_enabled 0');
|
||||||
|
await runCommand('adb shell settings put secure autofill_service null');
|
||||||
|
await runCommand('adb shell settings put global window_animation_scale 0.0');
|
||||||
|
await runCommand('adb shell settings put global transition_animation_scale 0.0');
|
||||||
|
await runCommand('adb shell settings put global animator_duration_scale 0.0');
|
||||||
|
}
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
navigateToWorkspace,
|
navigateToWorkspace,
|
||||||
navigateToLogin,
|
navigateToLogin,
|
||||||
|
@ -176,5 +231,7 @@ module.exports = {
|
||||||
sleep,
|
sleep,
|
||||||
searchRoom,
|
searchRoom,
|
||||||
tryTapping,
|
tryTapping,
|
||||||
checkServer
|
checkServer,
|
||||||
|
platformTypes,
|
||||||
|
prepareAndroid
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
const { navigateToLogin, login, sleep, tapBack, mockMessage, searchRoom, logout } = require('../../helpers/app');
|
const { navigateToLogin, login, sleep, tapBack, mockMessage, searchRoom, logout, platformTypes } = require('../../helpers/app');
|
||||||
|
|
||||||
const data = require('../../data');
|
const data = require('../../data');
|
||||||
|
|
||||||
const testuser = data.users.regular;
|
const testuser = data.users.regular;
|
||||||
|
@ -17,8 +18,9 @@ const checkServer = async server => {
|
||||||
};
|
};
|
||||||
|
|
||||||
const checkBanner = async () => {
|
const checkBanner = async () => {
|
||||||
await waitFor(element(by.id('listheader-encryption').withDescendant(by.label('Save Your Encryption Password'))))
|
// TODO: Assert 'Save Your Encryption Password'
|
||||||
.toBeVisible()
|
await waitFor(element(by.id('listheader-encryption')))
|
||||||
|
.toExist()
|
||||||
.withTimeout(10000);
|
.withTimeout(10000);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -58,9 +60,13 @@ async function navigateSecurityPrivacy() {
|
||||||
describe('E2E Encryption', () => {
|
describe('E2E Encryption', () => {
|
||||||
const room = `encrypted${data.random}`;
|
const room = `encrypted${data.random}`;
|
||||||
const newPassword = 'abc';
|
const newPassword = 'abc';
|
||||||
|
let alertButtonType;
|
||||||
|
let scrollViewType;
|
||||||
|
let textMatcher;
|
||||||
|
|
||||||
before(async () => {
|
before(async () => {
|
||||||
await device.launchApp({ permissions: { notifications: 'YES' }, delete: true });
|
await device.launchApp({ permissions: { notifications: 'YES' }, delete: true });
|
||||||
|
({ alertButtonType, scrollViewType, textMatcher } = platformTypes[device.getPlatform()]);
|
||||||
await navigateToLogin();
|
await navigateToLogin();
|
||||||
await login(testuser.username, testuser.password);
|
await login(testuser.username, testuser.password);
|
||||||
});
|
});
|
||||||
|
@ -187,11 +193,11 @@ describe('E2E Encryption', () => {
|
||||||
it('should change password', async () => {
|
it('should change password', async () => {
|
||||||
await element(by.id('e2e-encryption-security-view-password')).typeText(newPassword);
|
await element(by.id('e2e-encryption-security-view-password')).typeText(newPassword);
|
||||||
await element(by.id('e2e-encryption-security-view-change-password')).tap();
|
await element(by.id('e2e-encryption-security-view-change-password')).tap();
|
||||||
await waitFor(element(by.text('Are you sure?')))
|
await waitFor(element(by[textMatcher]('Are you sure?')))
|
||||||
.toExist()
|
.toExist()
|
||||||
.withTimeout(2000);
|
.withTimeout(2000);
|
||||||
await expect(element(by.text("Make sure you've saved it carefully somewhere else."))).toExist();
|
await expect(element(by[textMatcher]("Make sure you've saved it carefully somewhere else."))).toExist();
|
||||||
await element(by.label('Yes, change it').and(by.type('_UIAlertControllerActionView'))).tap();
|
await element(by[textMatcher]('Yes, change it')).atIndex(0).tap();
|
||||||
await waitForToast();
|
await waitForToast();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -216,7 +222,7 @@ describe('E2E Encryption', () => {
|
||||||
.toBeVisible()
|
.toBeVisible()
|
||||||
.withTimeout(2000);
|
.withTimeout(2000);
|
||||||
await navigateToRoom(room);
|
await navigateToRoom(room);
|
||||||
await waitFor(element(by.label(`${data.random}message`)).atIndex(0))
|
await waitFor(element(by[textMatcher](`${data.random}message`)).atIndex(0))
|
||||||
.toExist()
|
.toExist()
|
||||||
.withTimeout(2000);
|
.withTimeout(2000);
|
||||||
});
|
});
|
||||||
|
@ -230,7 +236,7 @@ describe('E2E Encryption', () => {
|
||||||
await navigateToLogin();
|
await navigateToLogin();
|
||||||
await login(testuser.username, testuser.password);
|
await login(testuser.username, testuser.password);
|
||||||
await navigateToRoom(room);
|
await navigateToRoom(room);
|
||||||
await waitFor(element(by.label(`${data.random}message`)).atIndex(0))
|
await waitFor(element(by[textMatcher](`${data.random}message`)).atIndex(0))
|
||||||
.not.toExist()
|
.not.toExist()
|
||||||
.withTimeout(2000);
|
.withTimeout(2000);
|
||||||
await expect(element(by.label('Encrypted message')).atIndex(0)).toExist();
|
await expect(element(by.label('Encrypted message')).atIndex(0)).toExist();
|
||||||
|
@ -241,10 +247,11 @@ describe('E2E Encryption', () => {
|
||||||
await waitFor(element(by.id('rooms-list-view')))
|
await waitFor(element(by.id('rooms-list-view')))
|
||||||
.toBeVisible()
|
.toBeVisible()
|
||||||
.withTimeout(2000);
|
.withTimeout(2000);
|
||||||
await waitFor(element(by.id('listheader-encryption').withDescendant(by.label('Enter Your E2E Password'))))
|
// TODO: assert 'Enter Your E2E Password'
|
||||||
|
await waitFor(element(by.id('listheader-encryption')))
|
||||||
.toBeVisible()
|
.toBeVisible()
|
||||||
.withTimeout(2000);
|
.withTimeout(2000);
|
||||||
await element(by.id('listheader-encryption').withDescendant(by.label('Enter Your E2E Password'))).tap();
|
await element(by.id('listheader-encryption')).tap();
|
||||||
await waitFor(element(by.id('e2e-enter-your-password-view')))
|
await waitFor(element(by.id('e2e-enter-your-password-view')))
|
||||||
.toBeVisible()
|
.toBeVisible()
|
||||||
.withTimeout(2000);
|
.withTimeout(2000);
|
||||||
|
@ -254,43 +261,52 @@ describe('E2E Encryption', () => {
|
||||||
.not.toExist()
|
.not.toExist()
|
||||||
.withTimeout(10000);
|
.withTimeout(10000);
|
||||||
await navigateToRoom(room);
|
await navigateToRoom(room);
|
||||||
await waitFor(element(by.label(`${data.random}message`)).atIndex(0))
|
await waitFor(element(by[textMatcher](`${data.random}message`)).atIndex(0))
|
||||||
.toExist()
|
.toExist()
|
||||||
.withTimeout(2000);
|
.withTimeout(2000);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('Reset E2E key', () => {
|
describe('Reset E2E key', () => {
|
||||||
it('should reset e2e key', async () => {
|
before(async () => {
|
||||||
await tapBack();
|
await tapBack();
|
||||||
await waitFor(element(by.id('rooms-list-view')))
|
await waitFor(element(by.id('rooms-list-view')))
|
||||||
.toBeVisible()
|
.toBeVisible()
|
||||||
.withTimeout(2000);
|
.withTimeout(2000);
|
||||||
|
});
|
||||||
|
it('should reset e2e key', async () => {
|
||||||
|
// FIXME: too flaky on Android for now... let's fix it later
|
||||||
|
// It's also flaky on iOS, but it works from time to time
|
||||||
|
if (device.getPlatform() === 'android') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
await navigateSecurityPrivacy();
|
await navigateSecurityPrivacy();
|
||||||
await element(by.id('security-privacy-view-e2e-encryption')).tap();
|
await element(by.id('security-privacy-view-e2e-encryption')).tap();
|
||||||
await waitFor(element(by.id('e2e-encryption-security-view')))
|
await waitFor(element(by.id('e2e-encryption-security-view')))
|
||||||
.toBeVisible()
|
.toBeVisible()
|
||||||
.withTimeout(2000);
|
.withTimeout(2000);
|
||||||
await element(by.id('e2e-encryption-security-view-reset-key').and(by.label('Reset E2E Key'))).tap();
|
await element(by.id('e2e-encryption-security-view-reset-key').and(by.label('Reset E2E Key'))).tap();
|
||||||
await waitFor(element(by.text('Are you sure?')))
|
await waitFor(element(by[textMatcher]('Are you sure?')))
|
||||||
.toExist()
|
.toExist()
|
||||||
.withTimeout(2000);
|
.withTimeout(2000);
|
||||||
await expect(element(by.text("You're going to be logged out."))).toExist();
|
await expect(element(by[textMatcher]("You're going to be logged out."))).toExist();
|
||||||
await element(by.label('Yes, reset it').and(by.type('UILabel'))).tap();
|
await element(by[textMatcher]('Yes, reset it').and(by.type(alertButtonType))).tap();
|
||||||
await sleep(2000);
|
await sleep(2000);
|
||||||
|
|
||||||
|
await waitFor(element(by[textMatcher]("You've been logged out by the server. Please log in again.")))
|
||||||
|
.toExist()
|
||||||
|
.withTimeout(20000);
|
||||||
|
await element(by[textMatcher]('OK').and(by.type(alertButtonType))).tap();
|
||||||
await waitFor(element(by.id('workspace-view')))
|
await waitFor(element(by.id('workspace-view')))
|
||||||
.toBeVisible()
|
.toBeVisible()
|
||||||
.withTimeout(10000);
|
.withTimeout(10000);
|
||||||
await waitFor(element(by.text("You've been logged out by the server. Please log in again.")))
|
|
||||||
.toExist()
|
|
||||||
.withTimeout(2000);
|
|
||||||
await element(by.label('OK').and(by.type('_UIAlertControllerActionView'))).tap();
|
|
||||||
await element(by.id('workspace-view-login')).tap();
|
await element(by.id('workspace-view-login')).tap();
|
||||||
await waitFor(element(by.id('login-view')))
|
await waitFor(element(by.id('login-view')))
|
||||||
.toBeVisible()
|
.toBeVisible()
|
||||||
.withTimeout(2000);
|
.withTimeout(2000);
|
||||||
await login(testuser.username, testuser.password);
|
await login(testuser.username, testuser.password);
|
||||||
await waitFor(element(by.id('listheader-encryption').withDescendant(by.label('Save Your Encryption Password'))))
|
// TODO: assert 'Save Your Encryption Password'
|
||||||
|
await waitFor(element(by.id('listheader-encryption')))
|
||||||
.toBeVisible()
|
.toBeVisible()
|
||||||
.withTimeout(2000);
|
.withTimeout(2000);
|
||||||
});
|
});
|
||||||
|
@ -298,6 +314,14 @@ describe('E2E Encryption', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('Persist Banner', () => {
|
describe('Persist Banner', () => {
|
||||||
|
before(async () => {
|
||||||
|
// reinstall the app because of one flaky test above
|
||||||
|
if (device.getPlatform() === 'android') {
|
||||||
|
await device.launchApp({ permissions: { notifications: 'YES' }, delete: true });
|
||||||
|
await navigateToLogin();
|
||||||
|
await login(testuser.username, testuser.password);
|
||||||
|
}
|
||||||
|
});
|
||||||
it('check save banner', async () => {
|
it('check save banner', async () => {
|
||||||
await checkServer(data.server);
|
await checkServer(data.server);
|
||||||
await checkBanner();
|
await checkBanner();
|
||||||
|
@ -315,7 +339,8 @@ describe('E2E Encryption', () => {
|
||||||
await waitFor(element(by.id('new-server-view')))
|
await waitFor(element(by.id('new-server-view')))
|
||||||
.toBeVisible()
|
.toBeVisible()
|
||||||
.withTimeout(60000);
|
.withTimeout(60000);
|
||||||
await element(by.id('new-server-view-input')).typeText(`${data.alternateServer}\n`);
|
await element(by.id('new-server-view-input')).typeText(`${data.alternateServer}`);
|
||||||
|
await element(by.id('new-server-view-input')).tapReturnKey();
|
||||||
await waitFor(element(by.id('workspace-view')))
|
await waitFor(element(by.id('workspace-view')))
|
||||||
.toBeVisible()
|
.toBeVisible()
|
||||||
.withTimeout(60000);
|
.withTimeout(60000);
|
||||||
|
@ -328,7 +353,7 @@ describe('E2E Encryption', () => {
|
||||||
await element(by.id('register-view-name')).replaceText(data.registeringUser.username);
|
await element(by.id('register-view-name')).replaceText(data.registeringUser.username);
|
||||||
await element(by.id('register-view-username')).replaceText(data.registeringUser.username);
|
await element(by.id('register-view-username')).replaceText(data.registeringUser.username);
|
||||||
await element(by.id('register-view-email')).replaceText(data.registeringUser.email);
|
await element(by.id('register-view-email')).replaceText(data.registeringUser.email);
|
||||||
await element(by.id('register-view-password')).typeText(data.registeringUser.password);
|
await element(by.id('register-view-password')).replaceText(data.registeringUser.password);
|
||||||
await element(by.id('register-view-submit')).tap();
|
await element(by.id('register-view-submit')).tap();
|
||||||
await waitFor(element(by.id('rooms-list-view')))
|
await waitFor(element(by.id('rooms-list-view')))
|
||||||
.toBeVisible()
|
.toBeVisible()
|
||||||
|
|
|
@ -1,15 +1,17 @@
|
||||||
// const OTP = require('otp.js');
|
// const OTP = require('otp.js');
|
||||||
// const GA = OTP.googleAuthenticator;
|
// const GA = OTP.googleAuthenticator;
|
||||||
|
|
||||||
const { navigateToLogin, login, mockMessage, tapBack, searchRoom } = require('../../helpers/app');
|
const { navigateToLogin, login, mockMessage, tapBack, searchRoom, platformTypes } = require('../../helpers/app');
|
||||||
const data = require('../../data');
|
const data = require('../../data');
|
||||||
|
|
||||||
const testuser = data.users.regular;
|
const testuser = data.users.regular;
|
||||||
const otheruser = data.users.alternate;
|
const otheruser = data.users.alternate;
|
||||||
|
|
||||||
describe('Broadcast room', () => {
|
describe('Broadcast room', () => {
|
||||||
|
let textMatcher;
|
||||||
before(async () => {
|
before(async () => {
|
||||||
await device.launchApp({ permissions: { notifications: 'YES' }, delete: true });
|
await device.launchApp({ permissions: { notifications: 'YES' }, delete: true });
|
||||||
|
({ textMatcher } = platformTypes[device.getPlatform()]);
|
||||||
await navigateToLogin();
|
await navigateToLogin();
|
||||||
await login(testuser.username, testuser.password);
|
await login(testuser.username, testuser.password);
|
||||||
});
|
});
|
||||||
|
@ -101,7 +103,7 @@ describe('Broadcast room', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should have the message created earlier', async () => {
|
it('should have the message created earlier', async () => {
|
||||||
await waitFor(element(by.label(`${data.random}message`)))
|
await waitFor(element(by[textMatcher](`${data.random}message`)))
|
||||||
.toExist()
|
.toExist()
|
||||||
.withTimeout(60000);
|
.withTimeout(60000);
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
const { navigateToLogin, login, sleep } = require('../../helpers/app');
|
const { navigateToLogin, login, sleep, platformTypes } = require('../../helpers/app');
|
||||||
const data = require('../../data');
|
const data = require('../../data');
|
||||||
|
|
||||||
const profileChangeUser = data.users.profileChanges;
|
const profileChangeUser = data.users.profileChanges;
|
||||||
|
@ -14,8 +14,14 @@ async function waitForToast() {
|
||||||
}
|
}
|
||||||
|
|
||||||
describe('Profile screen', () => {
|
describe('Profile screen', () => {
|
||||||
|
let textInputType;
|
||||||
|
let scrollViewType;
|
||||||
|
let alertButtonType;
|
||||||
|
let textMatcher;
|
||||||
|
|
||||||
before(async () => {
|
before(async () => {
|
||||||
await device.launchApp({ permissions: { notifications: 'YES' }, delete: true });
|
await device.launchApp({ permissions: { notifications: 'YES' }, delete: true });
|
||||||
|
({ textInputType, scrollViewType, alertButtonType, textMatcher } = platformTypes[device.getPlatform()]);
|
||||||
await navigateToLogin();
|
await navigateToLogin();
|
||||||
await login(profileChangeUser.username, profileChangeUser.password);
|
await login(profileChangeUser.username, profileChangeUser.password);
|
||||||
await element(by.id('rooms-list-view-sidebar')).tap();
|
await element(by.id('rooms-list-view-sidebar')).tap();
|
||||||
|
@ -92,8 +98,8 @@ describe('Profile screen', () => {
|
||||||
describe('Usage', () => {
|
describe('Usage', () => {
|
||||||
it('should change name and username', async () => {
|
it('should change name and username', async () => {
|
||||||
await element(by.id('profile-view-name')).replaceText(`${profileChangeUser.username}new`);
|
await element(by.id('profile-view-name')).replaceText(`${profileChangeUser.username}new`);
|
||||||
await element(by.id('profile-view-username')).typeText(`${profileChangeUser.username}new`);
|
await element(by.id('profile-view-username')).replaceText(`${profileChangeUser.username}new`);
|
||||||
await element(by.type('UIScrollView')).atIndex(1).swipe('up');
|
await element(by.type(scrollViewType)).atIndex(1).swipe('up');
|
||||||
await element(by.id('profile-view-submit')).tap();
|
await element(by.id('profile-view-submit')).tap();
|
||||||
await waitForToast();
|
await waitForToast();
|
||||||
});
|
});
|
||||||
|
@ -102,12 +108,13 @@ describe('Profile screen', () => {
|
||||||
await element(by.id('profile-view-email')).replaceText(`mobile+profileChangesNew${data.random}@rocket.chat`);
|
await element(by.id('profile-view-email')).replaceText(`mobile+profileChangesNew${data.random}@rocket.chat`);
|
||||||
await element(by.id('profile-view-new-password')).replaceText(`${profileChangeUser.password}new`);
|
await element(by.id('profile-view-new-password')).replaceText(`${profileChangeUser.password}new`);
|
||||||
await element(by.id('profile-view-submit')).tap();
|
await element(by.id('profile-view-submit')).tap();
|
||||||
await element(by.type('_UIAlertControllerTextField')).typeText(`${profileChangeUser.password}\n`);
|
await element(by.type(textInputType)).replaceText(`${profileChangeUser.password}`);
|
||||||
|
await element(by[textMatcher]('Save').and(by.type(alertButtonType))).tap();
|
||||||
await waitForToast();
|
await waitForToast();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should reset avatar', async () => {
|
it('should reset avatar', async () => {
|
||||||
await element(by.type('UIScrollView')).atIndex(1).swipe('up');
|
await element(by.type(scrollViewType)).atIndex(1).swipe('up');
|
||||||
await element(by.id('profile-view-reset-avatar')).tap();
|
await element(by.id('profile-view-reset-avatar')).tap();
|
||||||
await waitForToast();
|
await waitForToast();
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,11 +1,15 @@
|
||||||
const { navigateToLogin, login } = require('../../helpers/app');
|
const { navigateToLogin, login, platformTypes } = require('../../helpers/app');
|
||||||
|
|
||||||
const data = require('../../data');
|
const data = require('../../data');
|
||||||
|
|
||||||
const testuser = data.users.regular;
|
const testuser = data.users.regular;
|
||||||
|
|
||||||
describe('Settings screen', () => {
|
describe('Settings screen', () => {
|
||||||
|
let alertButtonType;
|
||||||
|
let textMatcher;
|
||||||
before(async () => {
|
before(async () => {
|
||||||
await device.launchApp({ permissions: { notifications: 'YES' }, delete: true });
|
await device.launchApp({ permissions: { notifications: 'YES' }, delete: true });
|
||||||
|
({ alertButtonType, textMatcher } = platformTypes[device.getPlatform()]);
|
||||||
await navigateToLogin();
|
await navigateToLogin();
|
||||||
await login(testuser.username, testuser.password);
|
await login(testuser.username, testuser.password);
|
||||||
await waitFor(element(by.id('rooms-list-view')))
|
await waitFor(element(by.id('rooms-list-view')))
|
||||||
|
@ -72,10 +76,10 @@ describe('Settings screen', () => {
|
||||||
.toBeVisible()
|
.toBeVisible()
|
||||||
.withTimeout(2000);
|
.withTimeout(2000);
|
||||||
await element(by.id('settings-view-clear-cache')).tap();
|
await element(by.id('settings-view-clear-cache')).tap();
|
||||||
await waitFor(element(by.text('This will clear all your offline data.')))
|
await waitFor(element(by[textMatcher]('This will clear all your offline data.')))
|
||||||
.toExist()
|
.toExist()
|
||||||
.withTimeout(2000);
|
.withTimeout(2000);
|
||||||
await element(by.label('Clear').and(by.type('_UIAlertControllerActionView'))).tap();
|
await element(by[textMatcher]('Clear').and(by.type(alertButtonType))).tap();
|
||||||
await waitFor(element(by.id('rooms-list-view')))
|
await waitFor(element(by.id('rooms-list-view')))
|
||||||
.toBeVisible()
|
.toBeVisible()
|
||||||
.withTimeout(5000);
|
.withTimeout(5000);
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
const data = require('../../data');
|
const data = require('../../data');
|
||||||
const { navigateToLogin, login, mockMessage, tapBack, searchRoom } = require('../../helpers/app');
|
const { navigateToLogin, login, mockMessage, tapBack, searchRoom, platformTypes } = require('../../helpers/app');
|
||||||
|
|
||||||
const testuser = data.users.regular;
|
const testuser = data.users.regular;
|
||||||
const room = data.channels.detoxpublic.name;
|
const room = data.channels.detoxpublic.name;
|
||||||
|
@ -7,21 +7,24 @@ const room = data.channels.detoxpublic.name;
|
||||||
async function navigateToRoom() {
|
async function navigateToRoom() {
|
||||||
await searchRoom(room);
|
await searchRoom(room);
|
||||||
await element(by.id(`rooms-list-view-item-${room}`)).tap();
|
await element(by.id(`rooms-list-view-item-${room}`)).tap();
|
||||||
await waitFor(element(by.id('room-view')))
|
await waitFor(element(by.id('room-view')).atIndex(0))
|
||||||
.toBeVisible()
|
.toExist()
|
||||||
.withTimeout(5000);
|
.withTimeout(5000);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function navigateToRoomActions() {
|
async function navigateToRoomActions() {
|
||||||
await element(by.id('room-header')).tap();
|
await element(by.id(`room-view-title-${room}`)).tap();
|
||||||
await waitFor(element(by.id('room-actions-view')))
|
await waitFor(element(by.id('room-actions-view')))
|
||||||
.toBeVisible()
|
.toBeVisible()
|
||||||
.withTimeout(5000);
|
.withTimeout(5000);
|
||||||
}
|
}
|
||||||
|
|
||||||
describe('Join public room', () => {
|
describe('Join public room', () => {
|
||||||
|
let alertButtonType;
|
||||||
|
let textMatcher;
|
||||||
before(async () => {
|
before(async () => {
|
||||||
await device.launchApp({ permissions: { notifications: 'YES' }, delete: true });
|
await device.launchApp({ permissions: { notifications: 'YES' }, delete: true });
|
||||||
|
({ alertButtonType, textMatcher } = platformTypes[device.getPlatform()]);
|
||||||
await navigateToLogin();
|
await navigateToLogin();
|
||||||
await login(testuser.username, testuser.password);
|
await login(testuser.username, testuser.password);
|
||||||
await navigateToRoom();
|
await navigateToRoom();
|
||||||
|
@ -32,10 +35,6 @@ describe('Join public room', () => {
|
||||||
await expect(element(by.id('room-view'))).toBeVisible();
|
await expect(element(by.id('room-view'))).toBeVisible();
|
||||||
});
|
});
|
||||||
|
|
||||||
// it('should have messages list', async() => {
|
|
||||||
// await expect(element(by.id('room-view-messages'))).toBeVisible();
|
|
||||||
// });
|
|
||||||
|
|
||||||
// Render - Header
|
// Render - Header
|
||||||
describe('Header', () => {
|
describe('Header', () => {
|
||||||
it('should have actions button ', async () => {
|
it('should have actions button ', async () => {
|
||||||
|
@ -75,16 +74,10 @@ describe('Join public room', () => {
|
||||||
await expect(element(by.id('room-actions-info'))).toBeVisible();
|
await expect(element(by.id('room-actions-info'))).toBeVisible();
|
||||||
});
|
});
|
||||||
|
|
||||||
// it('should have voice', async() => {
|
|
||||||
// await expect(element(by.id('room-actions-voice'))).toBeVisible();
|
|
||||||
// });
|
|
||||||
|
|
||||||
// it('should have video', async() => {
|
|
||||||
// await expect(element(by.id('room-actions-video'))).toBeVisible();
|
|
||||||
// });
|
|
||||||
|
|
||||||
it('should have members', async () => {
|
it('should have members', async () => {
|
||||||
await expect(element(by.id('room-actions-members'))).toBeVisible();
|
await waitFor(element(by.id('room-actions-members')))
|
||||||
|
.toBeVisible()
|
||||||
|
.withTimeout(2000);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should have files', async () => {
|
it('should have files', async () => {
|
||||||
|
@ -147,32 +140,29 @@ describe('Join public room', () => {
|
||||||
await navigateToRoomActions();
|
await navigateToRoomActions();
|
||||||
await expect(element(by.id('room-actions-view'))).toBeVisible();
|
await expect(element(by.id('room-actions-view'))).toBeVisible();
|
||||||
await expect(element(by.id('room-actions-info'))).toBeVisible();
|
await expect(element(by.id('room-actions-info'))).toBeVisible();
|
||||||
// await expect(element(by.id('room-actions-voice'))).toBeVisible();
|
|
||||||
// await expect(element(by.id('room-actions-video'))).toBeVisible();
|
|
||||||
await expect(element(by.id('room-actions-members'))).toBeVisible();
|
await expect(element(by.id('room-actions-members'))).toBeVisible();
|
||||||
await expect(element(by.id('room-actions-files'))).toBeVisible();
|
await expect(element(by.id('room-actions-files'))).toBeVisible();
|
||||||
await expect(element(by.id('room-actions-mentioned'))).toBeVisible();
|
await expect(element(by.id('room-actions-mentioned'))).toBeVisible();
|
||||||
await expect(element(by.id('room-actions-starred'))).toBeVisible();
|
await expect(element(by.id('room-actions-starred'))).toBeVisible();
|
||||||
await element(by.id('room-actions-scrollview')).swipe('down');
|
|
||||||
await expect(element(by.id('room-actions-share'))).toBeVisible();
|
await expect(element(by.id('room-actions-share'))).toBeVisible();
|
||||||
await expect(element(by.id('room-actions-pinned'))).toBeVisible();
|
await expect(element(by.id('room-actions-pinned'))).toBeVisible();
|
||||||
await expect(element(by.id('room-actions-notifications'))).toBeVisible();
|
await expect(element(by.id('room-actions-notifications'))).toBeVisible();
|
||||||
|
await element(by.id('room-actions-scrollview')).scrollTo('bottom');
|
||||||
await expect(element(by.id('room-actions-leave-channel'))).toBeVisible();
|
await expect(element(by.id('room-actions-leave-channel'))).toBeVisible();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should leave room', async () => {
|
it('should leave room', async () => {
|
||||||
await element(by.id('room-actions-leave-channel')).tap();
|
await element(by.id('room-actions-leave-channel')).tap();
|
||||||
await waitFor(element(by.text('Yes, leave it!')))
|
await waitFor(element(by[textMatcher]('Yes, leave it!').and(by.type(alertButtonType))))
|
||||||
.toBeVisible()
|
.toBeVisible()
|
||||||
.withTimeout(5000);
|
.withTimeout(5000);
|
||||||
await expect(element(by.text('Yes, leave it!'))).toBeVisible();
|
await element(by[textMatcher]('Yes, leave it!').and(by.type(alertButtonType))).tap();
|
||||||
await element(by.text('Yes, leave it!')).tap();
|
|
||||||
await waitFor(element(by.id('rooms-list-view')))
|
await waitFor(element(by.id('rooms-list-view')))
|
||||||
.toBeVisible()
|
.toBeVisible()
|
||||||
.withTimeout(10000);
|
.withTimeout(10000);
|
||||||
await waitFor(element(by.id(`rooms-list-view-item-${room}`)))
|
await waitFor(element(by.id(`rooms-list-view-item-${room}`)))
|
||||||
.toBeNotVisible()
|
.toBeNotVisible()
|
||||||
.withTimeout(60000);
|
.withTimeout(60000); // flaky on Android
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -45,8 +45,9 @@ describe('Status screen', () => {
|
||||||
.withTimeout(2000);
|
.withTimeout(2000);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// TODO: flaky
|
||||||
it('should change status text', async () => {
|
it('should change status text', async () => {
|
||||||
await element(by.id('status-view-input')).typeText('status-text-new');
|
await element(by.id('status-view-input')).replaceText('status-text-new');
|
||||||
await element(by.id('status-view-submit')).tap();
|
await element(by.id('status-view-submit')).tap();
|
||||||
await waitForToast();
|
await waitForToast();
|
||||||
await waitFor(element(by.label('status-text-new').withAncestor(by.id('sidebar-custom-status'))))
|
await waitFor(element(by.label('status-text-new').withAncestor(by.id('sidebar-custom-status'))))
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
const data = require('../../data');
|
const data = require('../../data');
|
||||||
const { navigateToLogin, login, checkServer } = require('../../helpers/app');
|
const { navigateToLogin, login, checkServer, platformTypes } = require('../../helpers/app');
|
||||||
|
|
||||||
const reopenAndCheckServer = async server => {
|
const reopenAndCheckServer = async server => {
|
||||||
await device.launchApp({ permissions: { notifications: 'YES' } });
|
await device.launchApp({ permissions: { notifications: 'YES' }, newInstance: true });
|
||||||
await waitFor(element(by.id('rooms-list-view')))
|
await waitFor(element(by.id('rooms-list-view')))
|
||||||
.toBeVisible()
|
.toBeVisible()
|
||||||
.withTimeout(10000);
|
.withTimeout(10000);
|
||||||
|
@ -37,7 +37,8 @@ describe('Change server', () => {
|
||||||
await waitFor(element(by.id('new-server-view')))
|
await waitFor(element(by.id('new-server-view')))
|
||||||
.toBeVisible()
|
.toBeVisible()
|
||||||
.withTimeout(6000);
|
.withTimeout(6000);
|
||||||
await element(by.id('new-server-view-input')).typeText(`${data.alternateServer}\n`);
|
await element(by.id('new-server-view-input')).replaceText(`${data.alternateServer}`);
|
||||||
|
await element(by.id('new-server-view-input')).tapReturnKey();
|
||||||
await waitFor(element(by.id('workspace-view')))
|
await waitFor(element(by.id('workspace-view')))
|
||||||
.toBeVisible()
|
.toBeVisible()
|
||||||
.withTimeout(10000);
|
.withTimeout(10000);
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
const data = require('../../data');
|
const data = require('../../data');
|
||||||
const { navigateToLogin, login, mockMessage, searchRoom } = require('../../helpers/app');
|
const { navigateToLogin, login, mockMessage, searchRoom, sleep } = require('../../helpers/app');
|
||||||
|
|
||||||
const testuser = data.users.regular;
|
const testuser = data.users.regular;
|
||||||
const room = data.channels.detoxpublicprotected.name;
|
const room = data.channels.detoxpublicprotected.name;
|
||||||
|
@ -9,15 +9,25 @@ async function navigateToRoom() {
|
||||||
await searchRoom(room);
|
await searchRoom(room);
|
||||||
await element(by.id(`rooms-list-view-item-${room}`)).tap();
|
await element(by.id(`rooms-list-view-item-${room}`)).tap();
|
||||||
await waitFor(element(by.id('room-view')))
|
await waitFor(element(by.id('room-view')))
|
||||||
.toBeVisible()
|
.toExist()
|
||||||
.withTimeout(5000);
|
.withTimeout(5000);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function openJoinCode() {
|
async function openJoinCode() {
|
||||||
|
await waitFor(element(by.id('room-view-join-button')))
|
||||||
|
.toExist()
|
||||||
|
.withTimeout(2000);
|
||||||
|
let n = 0;
|
||||||
|
while (n < 3) {
|
||||||
|
try {
|
||||||
await element(by.id('room-view-join-button')).tap();
|
await element(by.id('room-view-join-button')).tap();
|
||||||
await waitFor(element(by.id('join-code')))
|
await waitFor(element(by.id('join-code')))
|
||||||
.toBeVisible()
|
.toBeVisible()
|
||||||
.withTimeout(5000);
|
.withTimeout(500);
|
||||||
|
} catch (error) {
|
||||||
|
n += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
describe('Join protected room', () => {
|
describe('Join protected room', () => {
|
||||||
|
|
|
@ -10,7 +10,7 @@ async function navigateToRoom(search) {
|
||||||
.withTimeout(10000);
|
.withTimeout(10000);
|
||||||
await sleep(300); // app takes some time to animate
|
await sleep(300); // app takes some time to animate
|
||||||
await element(by.id(`directory-view-item-${search}`)).tap();
|
await element(by.id(`directory-view-item-${search}`)).tap();
|
||||||
await waitFor(element(by.id('room-view')))
|
await waitFor(element(by.id('room-view')).atIndex(0))
|
||||||
.toExist()
|
.toExist()
|
||||||
.withTimeout(5000);
|
.withTimeout(5000);
|
||||||
await waitFor(element(by.id(`room-view-title-${search}`)))
|
await waitFor(element(by.id(`room-view-title-${search}`)))
|
||||||
|
@ -44,20 +44,20 @@ describe('Join room from directory', () => {
|
||||||
.toExist()
|
.toExist()
|
||||||
.withTimeout(2000);
|
.withTimeout(2000);
|
||||||
await element(by.id('directory-view-dropdown')).tap();
|
await element(by.id('directory-view-dropdown')).tap();
|
||||||
await element(by.label('Users')).tap();
|
await element(by.label('Users')).atIndex(0).tap();
|
||||||
await element(by.label('Search by')).tap();
|
await element(by.label('Search by')).atIndex(0).tap();
|
||||||
await navigateToRoom(data.users.alternate.username);
|
await navigateToRoom(data.users.alternate.username);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should search user and navigate', async () => {
|
it('should search team and navigate', async () => {
|
||||||
await tapBack();
|
await tapBack();
|
||||||
await element(by.id('rooms-list-view-directory')).tap();
|
await element(by.id('rooms-list-view-directory')).tap();
|
||||||
await waitFor(element(by.id('directory-view')))
|
await waitFor(element(by.id('directory-view')))
|
||||||
.toExist()
|
.toExist()
|
||||||
.withTimeout(2000);
|
.withTimeout(2000);
|
||||||
await element(by.id('directory-view-dropdown')).tap();
|
await element(by.id('directory-view-dropdown')).tap();
|
||||||
await element(by.label('Teams')).tap();
|
await element(by.label('Teams')).atIndex(0).tap();
|
||||||
await element(by.label('Search by')).tap();
|
await element(by.label('Search by')).atIndex(0).tap();
|
||||||
await navigateToRoom(data.teams.private.name);
|
await navigateToRoom(data.teams.private.name);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,9 +1,12 @@
|
||||||
const data = require('../../data');
|
const data = require('../../data');
|
||||||
const { sleep, navigateToLogin, login, checkServer } = require('../../helpers/app');
|
const { sleep, navigateToLogin, login, checkServer, platformTypes } = require('../../helpers/app');
|
||||||
|
|
||||||
describe('Delete server', () => {
|
describe('Delete server', () => {
|
||||||
|
let alertButtonType;
|
||||||
|
let textMatcher;
|
||||||
before(async () => {
|
before(async () => {
|
||||||
await device.launchApp({ permissions: { notifications: 'YES' }, delete: true });
|
await device.launchApp({ permissions: { notifications: 'YES' }, delete: true });
|
||||||
|
({ alertButtonType, textMatcher } = platformTypes[device.getPlatform()]);
|
||||||
await navigateToLogin();
|
await navigateToLogin();
|
||||||
await login(data.users.regular.username, data.users.regular.password);
|
await login(data.users.regular.username, data.users.regular.password);
|
||||||
});
|
});
|
||||||
|
@ -23,7 +26,8 @@ describe('Delete server', () => {
|
||||||
await waitFor(element(by.id('new-server-view')))
|
await waitFor(element(by.id('new-server-view')))
|
||||||
.toBeVisible()
|
.toBeVisible()
|
||||||
.withTimeout(10000);
|
.withTimeout(10000);
|
||||||
await element(by.id('new-server-view-input')).typeText(`${data.alternateServer}\n`);
|
await element(by.id('new-server-view-input')).replaceText(`${data.alternateServer}`);
|
||||||
|
await element(by.id('new-server-view-input')).tapReturnKey();
|
||||||
await waitFor(element(by.id('workspace-view')))
|
await waitFor(element(by.id('workspace-view')))
|
||||||
.toBeVisible()
|
.toBeVisible()
|
||||||
.withTimeout(10000);
|
.withTimeout(10000);
|
||||||
|
@ -36,7 +40,7 @@ describe('Delete server', () => {
|
||||||
await element(by.id('register-view-name')).replaceText(data.registeringUser3.username);
|
await element(by.id('register-view-name')).replaceText(data.registeringUser3.username);
|
||||||
await element(by.id('register-view-username')).replaceText(data.registeringUser3.username);
|
await element(by.id('register-view-username')).replaceText(data.registeringUser3.username);
|
||||||
await element(by.id('register-view-email')).replaceText(data.registeringUser3.email);
|
await element(by.id('register-view-email')).replaceText(data.registeringUser3.email);
|
||||||
await element(by.id('register-view-password')).typeText(data.registeringUser3.password);
|
await element(by.id('register-view-password')).replaceText(data.registeringUser3.password);
|
||||||
await element(by.id('register-view-submit')).tap();
|
await element(by.id('register-view-submit')).tap();
|
||||||
await waitFor(element(by.id('rooms-list-view')))
|
await waitFor(element(by.id('rooms-list-view')))
|
||||||
.toBeVisible()
|
.toBeVisible()
|
||||||
|
@ -51,7 +55,7 @@ describe('Delete server', () => {
|
||||||
.toBeVisible()
|
.toBeVisible()
|
||||||
.withTimeout(5000);
|
.withTimeout(5000);
|
||||||
await element(by.id(`rooms-list-header-server-${data.server}`)).longPress(1500);
|
await element(by.id(`rooms-list-header-server-${data.server}`)).longPress(1500);
|
||||||
await element(by.label('Delete').and(by.type('_UIAlertControllerActionView'))).tap();
|
await element(by[textMatcher]('Delete').and(by.type(alertButtonType))).tap();
|
||||||
await element(by.id('rooms-list-header-server-dropdown-button')).tap();
|
await element(by.id('rooms-list-header-server-dropdown-button')).tap();
|
||||||
await waitFor(element(by.id('rooms-list-header-server-dropdown')))
|
await waitFor(element(by.id('rooms-list-header-server-dropdown')))
|
||||||
.toBeVisible()
|
.toBeVisible()
|
||||||
|
|
|
@ -1,10 +1,13 @@
|
||||||
const data = require('../../data');
|
const data = require('../../data');
|
||||||
const { tapBack, checkServer, navigateToRegister } = require('../../helpers/app');
|
const { tapBack, checkServer, navigateToRegister, platformTypes } = require('../../helpers/app');
|
||||||
const { get, login, sendMessage } = require('../../helpers/data_setup');
|
const { get, login, sendMessage } = require('../../helpers/data_setup');
|
||||||
|
|
||||||
const DEEPLINK_METHODS = { AUTH: 'auth', ROOM: 'room' };
|
const DEEPLINK_METHODS = { AUTH: 'auth', ROOM: 'room' };
|
||||||
|
|
||||||
|
let amp = '&';
|
||||||
|
|
||||||
const getDeepLink = (method, server, params) => {
|
const getDeepLink = (method, server, params) => {
|
||||||
const deeplink = `rocketchat://${method}?host=${server.replace(/^(http:\/\/|https:\/\/)/, '')}&${params}`;
|
const deeplink = `rocketchat://${method}?host=${server.replace(/^(http:\/\/|https:\/\/)/, '')}${amp}${params}`;
|
||||||
console.log(`Deeplinking to: ${deeplink}`);
|
console.log(`Deeplinking to: ${deeplink}`);
|
||||||
return deeplink;
|
return deeplink;
|
||||||
};
|
};
|
||||||
|
@ -12,11 +15,17 @@ const getDeepLink = (method, server, params) => {
|
||||||
describe('Deep linking', () => {
|
describe('Deep linking', () => {
|
||||||
let userId;
|
let userId;
|
||||||
let authToken;
|
let authToken;
|
||||||
|
let scrollViewType;
|
||||||
let threadId;
|
let threadId;
|
||||||
|
let textMatcher;
|
||||||
|
let alertButtonType;
|
||||||
const threadMessage = `to-thread-${data.random}`;
|
const threadMessage = `to-thread-${data.random}`;
|
||||||
before(async () => {
|
before(async () => {
|
||||||
const loginResult = await login(data.users.regular.username, data.users.regular.password);
|
const loginResult = await login(data.users.regular.username, data.users.regular.password);
|
||||||
({ userId, authToken } = loginResult);
|
({ userId, authToken } = loginResult);
|
||||||
|
const deviceType = device.getPlatform();
|
||||||
|
amp = deviceType === 'android' ? '\\&' : '&';
|
||||||
|
({ scrollViewType, textMatcher, alertButtonType } = platformTypes[deviceType]);
|
||||||
// create a thread with api
|
// create a thread with api
|
||||||
const result = await sendMessage(data.users.regular, data.groups.alternate2.name, threadMessage);
|
const result = await sendMessage(data.users.regular, data.groups.alternate2.name, threadMessage);
|
||||||
threadId = result.message._id;
|
threadId = result.message._id;
|
||||||
|
@ -28,10 +37,9 @@ describe('Deep linking', () => {
|
||||||
await device.launchApp({
|
await device.launchApp({
|
||||||
permissions: { notifications: 'YES' },
|
permissions: { notifications: 'YES' },
|
||||||
delete: true,
|
delete: true,
|
||||||
url: getDeepLink(DEEPLINK_METHODS.AUTH, data.server, 'userId=123&token=abc'),
|
url: getDeepLink(DEEPLINK_METHODS.AUTH, data.server, `userId=123${amp}token=abc`)
|
||||||
sourceApp: 'com.apple.mobilesafari'
|
|
||||||
});
|
});
|
||||||
await waitFor(element(by.text("You've been logged out by the server. Please log in again.")))
|
await waitFor(element(by[textMatcher]("You've been logged out by the server. Please log in again.")))
|
||||||
.toExist()
|
.toExist()
|
||||||
.withTimeout(10000); // TODO: we need to improve this message
|
.withTimeout(10000); // TODO: we need to improve this message
|
||||||
});
|
});
|
||||||
|
@ -43,9 +51,8 @@ describe('Deep linking', () => {
|
||||||
url: getDeepLink(
|
url: getDeepLink(
|
||||||
DEEPLINK_METHODS.AUTH,
|
DEEPLINK_METHODS.AUTH,
|
||||||
data.server,
|
data.server,
|
||||||
`userId=${userId}&token=${authToken}&path=group/${data.groups.private.name}`
|
`userId=${userId}${amp}token=${authToken}${amp}path=group/${data.groups.private.name}`
|
||||||
),
|
)
|
||||||
sourceApp: 'com.apple.mobilesafari'
|
|
||||||
});
|
});
|
||||||
await waitFor(element(by.id(`room-view-title-${data.groups.private.name}`)))
|
await waitFor(element(by.id(`room-view-title-${data.groups.private.name}`)))
|
||||||
.toExist()
|
.toExist()
|
||||||
|
@ -56,7 +63,7 @@ describe('Deep linking', () => {
|
||||||
.withTimeout(10000);
|
.withTimeout(10000);
|
||||||
await checkServer(data.server);
|
await checkServer(data.server);
|
||||||
await waitFor(element(by.id(`rooms-list-view-item-${data.groups.private.name}`)))
|
await waitFor(element(by.id(`rooms-list-view-item-${data.groups.private.name}`)))
|
||||||
.toBeVisible()
|
.toExist()
|
||||||
.withTimeout(2000);
|
.withTimeout(2000);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -70,7 +77,8 @@ describe('Deep linking', () => {
|
||||||
await element(by.id('register-view-name')).replaceText(data.registeringUser4.username);
|
await element(by.id('register-view-name')).replaceText(data.registeringUser4.username);
|
||||||
await element(by.id('register-view-username')).replaceText(data.registeringUser4.username);
|
await element(by.id('register-view-username')).replaceText(data.registeringUser4.username);
|
||||||
await element(by.id('register-view-email')).replaceText(data.registeringUser4.email);
|
await element(by.id('register-view-email')).replaceText(data.registeringUser4.email);
|
||||||
await element(by.id('register-view-password')).typeText(data.registeringUser4.password);
|
await element(by.id('register-view-password')).replaceText(data.registeringUser4.password);
|
||||||
|
await element(by.type(scrollViewType)).atIndex(0).scrollTo('bottom');
|
||||||
await element(by.id('register-view-submit')).tap();
|
await element(by.id('register-view-submit')).tap();
|
||||||
await waitFor(element(by.id('rooms-list-view')))
|
await waitFor(element(by.id('rooms-list-view')))
|
||||||
.toBeVisible()
|
.toBeVisible()
|
||||||
|
@ -85,8 +93,7 @@ describe('Deep linking', () => {
|
||||||
await device.launchApp({
|
await device.launchApp({
|
||||||
permissions: { notifications: 'YES' },
|
permissions: { notifications: 'YES' },
|
||||||
newInstance: true,
|
newInstance: true,
|
||||||
url: getDeepLink(DEEPLINK_METHODS.ROOM, data.server, `path=group/${data.groups.private.name}`),
|
url: getDeepLink(DEEPLINK_METHODS.ROOM, data.server, `path=group/${data.groups.private.name}`)
|
||||||
sourceApp: 'com.apple.mobilesafari'
|
|
||||||
});
|
});
|
||||||
await waitFor(element(by.id(`room-view-title-${data.groups.private.name}`)))
|
await waitFor(element(by.id(`room-view-title-${data.groups.private.name}`)))
|
||||||
.toExist()
|
.toExist()
|
||||||
|
@ -97,8 +104,7 @@ describe('Deep linking', () => {
|
||||||
await device.launchApp({
|
await device.launchApp({
|
||||||
permissions: { notifications: 'YES' },
|
permissions: { notifications: 'YES' },
|
||||||
newInstance: true,
|
newInstance: true,
|
||||||
url: getDeepLink(DEEPLINK_METHODS.ROOM, data.server, `path=group/${data.groups.alternate2.name}/thread/${threadId}`),
|
url: getDeepLink(DEEPLINK_METHODS.ROOM, data.server, `path=group/${data.groups.alternate2.name}/thread/${threadId}`)
|
||||||
sourceApp: 'com.apple.mobilesafari'
|
|
||||||
});
|
});
|
||||||
await waitFor(element(by.id(`room-view-title-${threadMessage}`)))
|
await waitFor(element(by.id(`room-view-title-${threadMessage}`)))
|
||||||
.toExist()
|
.toExist()
|
||||||
|
@ -110,8 +116,7 @@ describe('Deep linking', () => {
|
||||||
await device.launchApp({
|
await device.launchApp({
|
||||||
permissions: { notifications: 'YES' },
|
permissions: { notifications: 'YES' },
|
||||||
newInstance: true,
|
newInstance: true,
|
||||||
url: getDeepLink(DEEPLINK_METHODS.ROOM, data.server, `rid=${roomResult.data.group._id}`),
|
url: getDeepLink(DEEPLINK_METHODS.ROOM, data.server, `rid=${roomResult.data.group._id}`)
|
||||||
sourceApp: 'com.apple.mobilesafari'
|
|
||||||
});
|
});
|
||||||
await waitFor(element(by.id(`room-view-title-${data.groups.private.name}`)))
|
await waitFor(element(by.id(`room-view-title-${data.groups.private.name}`)))
|
||||||
.toExist()
|
.toExist()
|
||||||
|
@ -135,8 +140,7 @@ describe('Deep linking', () => {
|
||||||
await device.launchApp({
|
await device.launchApp({
|
||||||
permissions: { notifications: 'YES' },
|
permissions: { notifications: 'YES' },
|
||||||
newInstance: true,
|
newInstance: true,
|
||||||
url: getDeepLink(DEEPLINK_METHODS.ROOM, data.server, `path=group/${data.groups.private.name}`),
|
url: getDeepLink(DEEPLINK_METHODS.ROOM, data.server, `path=group/${data.groups.private.name}`)
|
||||||
sourceApp: 'com.apple.mobilesafari'
|
|
||||||
});
|
});
|
||||||
await waitFor(element(by.id(`room-view-title-${data.groups.private.name}`)))
|
await waitFor(element(by.id(`room-view-title-${data.groups.private.name}`)))
|
||||||
.toExist()
|
.toExist()
|
||||||
|
@ -147,8 +151,7 @@ describe('Deep linking', () => {
|
||||||
await device.launchApp({
|
await device.launchApp({
|
||||||
permissions: { notifications: 'YES' },
|
permissions: { notifications: 'YES' },
|
||||||
newInstance: true,
|
newInstance: true,
|
||||||
url: getDeepLink(DEEPLINK_METHODS.ROOM, 'https://google.com'),
|
url: getDeepLink(DEEPLINK_METHODS.ROOM, 'https://google.com')
|
||||||
sourceApp: 'com.apple.mobilesafari'
|
|
||||||
});
|
});
|
||||||
await waitFor(element(by.id('rooms-list-view')))
|
await waitFor(element(by.id('rooms-list-view')))
|
||||||
.toBeVisible()
|
.toBeVisible()
|
||||||
|
|
|
@ -29,6 +29,9 @@ const navToLanguage = async () => {
|
||||||
describe('i18n', () => {
|
describe('i18n', () => {
|
||||||
describe('OS language', () => {
|
describe('OS language', () => {
|
||||||
it("OS set to 'en' and proper translate to 'en'", async () => {
|
it("OS set to 'en' and proper translate to 'en'", async () => {
|
||||||
|
if (device.getPlatform() === 'android') {
|
||||||
|
return; // FIXME: Passing language with launch parameters doesn't work with Android
|
||||||
|
}
|
||||||
await device.launchApp({
|
await device.launchApp({
|
||||||
...defaultLaunchArgs,
|
...defaultLaunchArgs,
|
||||||
languageAndLocale: {
|
languageAndLocale: {
|
||||||
|
@ -44,6 +47,9 @@ describe('i18n', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it("OS set to unavailable language and fallback to 'en'", async () => {
|
it("OS set to unavailable language and fallback to 'en'", async () => {
|
||||||
|
if (device.getPlatform() === 'android') {
|
||||||
|
return; // FIXME: Passing language with launch parameters doesn't work with Android
|
||||||
|
}
|
||||||
await device.launchApp({
|
await device.launchApp({
|
||||||
...defaultLaunchArgs,
|
...defaultLaunchArgs,
|
||||||
languageAndLocale: {
|
languageAndLocale: {
|
||||||
|
@ -74,7 +80,7 @@ describe('i18n', () => {
|
||||||
|
|
||||||
describe('Rocket.Chat language', () => {
|
describe('Rocket.Chat language', () => {
|
||||||
before(async () => {
|
before(async () => {
|
||||||
await device.launchApp(defaultLaunchArgs);
|
await device.launchApp({ ...defaultLaunchArgs, delete: true });
|
||||||
await navigateToLogin();
|
await navigateToLogin();
|
||||||
await login(testuser.username, testuser.password);
|
await login(testuser.username, testuser.password);
|
||||||
});
|
});
|
||||||
|
@ -113,7 +119,7 @@ describe('i18n', () => {
|
||||||
|
|
||||||
it("should set unsupported language and fallback to 'en'", async () => {
|
it("should set unsupported language and fallback to 'en'", async () => {
|
||||||
await post('users.setPreferences', { data: { language: 'eo' } }); // Set language to Esperanto
|
await post('users.setPreferences', { data: { language: 'eo' } }); // Set language to Esperanto
|
||||||
await device.launchApp(defaultLaunchArgs);
|
await device.launchApp({ ...defaultLaunchArgs, newInstance: true });
|
||||||
await waitFor(element(by.id('rooms-list-view')))
|
await waitFor(element(by.id('rooms-list-view')))
|
||||||
.toBeVisible()
|
.toBeVisible()
|
||||||
.withTimeout(10000);
|
.withTimeout(10000);
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
const { login, navigateToLogin } = require('../../helpers/app');
|
const { login, navigateToLogin, sleep } = require('../../helpers/app');
|
||||||
const data = require('../../data');
|
const data = require('../../data');
|
||||||
|
|
||||||
const goToDisplayPref = async () => {
|
const goToDisplayPref = async () => {
|
||||||
|
@ -14,7 +14,7 @@ const goToRoomList = async () => {
|
||||||
await element(by.id('sidebar-chats')).tap();
|
await element(by.id('sidebar-chats')).tap();
|
||||||
};
|
};
|
||||||
|
|
||||||
describe('Rooms list screen', () => {
|
describe('Display prefs', () => {
|
||||||
before(async () => {
|
before(async () => {
|
||||||
await device.launchApp({ permissions: { notifications: 'YES' }, newInstance: true, delete: true });
|
await device.launchApp({ permissions: { notifications: 'YES' }, newInstance: true, delete: true });
|
||||||
await navigateToLogin();
|
await navigateToLogin();
|
||||||
|
@ -89,7 +89,9 @@ describe('Rooms list screen', () => {
|
||||||
await expect(element(by.id('display-pref-view-avatar-switch'))).toBeVisible();
|
await expect(element(by.id('display-pref-view-avatar-switch'))).toBeVisible();
|
||||||
await element(by.id('display-pref-view-avatar-switch')).tap();
|
await element(by.id('display-pref-view-avatar-switch')).tap();
|
||||||
await goToRoomList();
|
await goToRoomList();
|
||||||
await expect(element(by.id('avatar'))).not.toBeVisible();
|
await waitFor(element(by.id('avatar').withAncestor(by.id('rooms-list-view-item-general'))))
|
||||||
|
.not.toBeVisible()
|
||||||
|
.withTimeout(2000);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -3,9 +3,11 @@ const adapter = require('detox/runners/mocha/adapter');
|
||||||
|
|
||||||
const config = require('../../package.json').detox;
|
const config = require('../../package.json').detox;
|
||||||
const { setup } = require('../helpers/data_setup');
|
const { setup } = require('../helpers/data_setup');
|
||||||
|
const { prepareAndroid } = require('../helpers/app');
|
||||||
|
|
||||||
before(async () => {
|
before(async () => {
|
||||||
await Promise.all([setup(), detox.init(config, { launchApp: false })]);
|
await Promise.all([setup(), detox.init(config, { launchApp: false })]);
|
||||||
|
await prepareAndroid(); // Make Android less flaky
|
||||||
// await dataSetup()
|
// await dataSetup()
|
||||||
// await detox.init(config, { launchApp: false });
|
// await detox.init(config, { launchApp: false });
|
||||||
// await device.launchApp({ permissions: { notifications: 'YES' } });
|
// await device.launchApp({ permissions: { notifications: 'YES' } });
|
||||||
|
|
|
@ -1,8 +1,12 @@
|
||||||
const data = require('../../data');
|
const data = require('../../data');
|
||||||
|
const { platformTypes } = require('../../helpers/app');
|
||||||
|
|
||||||
describe('Onboarding', () => {
|
describe('Onboarding', () => {
|
||||||
|
let alertButtonType;
|
||||||
|
let textMatcher;
|
||||||
before(async () => {
|
before(async () => {
|
||||||
await device.launchApp({ permissions: { notifications: 'YES' }, delete: true });
|
await device.launchApp({ permissions: { notifications: 'YES' }, delete: true });
|
||||||
|
({ alertButtonType, textMatcher } = platformTypes[device.getPlatform()]);
|
||||||
await waitFor(element(by.id('new-server-view')))
|
await waitFor(element(by.id('new-server-view')))
|
||||||
.toBeVisible()
|
.toBeVisible()
|
||||||
.withTimeout(20000);
|
.withTimeout(20000);
|
||||||
|
@ -19,17 +23,13 @@ describe('Onboarding', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('Usage', () => {
|
describe('Usage', () => {
|
||||||
// it('should navigate to create new workspace', async() => {
|
|
||||||
// // webviews are not supported by detox: https://github.com/wix/detox/issues/136#issuecomment-306591554
|
|
||||||
// });
|
|
||||||
|
|
||||||
it('should enter an invalid server and get error', async () => {
|
it('should enter an invalid server and get error', async () => {
|
||||||
await element(by.id('new-server-view-input')).typeText('invalidtest\n');
|
await element(by.id('new-server-view-input')).replaceText('invalidtest');
|
||||||
const errorText = 'Oops!';
|
await element(by.id('new-server-view-input')).tapReturnKey();
|
||||||
await waitFor(element(by.text(errorText)))
|
await waitFor(element(by[textMatcher]('Oops!')))
|
||||||
.toBeVisible()
|
.toExist()
|
||||||
.withTimeout(60000);
|
.withTimeout(10000);
|
||||||
await element(by.text('OK')).tap();
|
await element(by[textMatcher]('OK').and(by.type(alertButtonType))).tap();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should tap on "Join our open workspace" and navigate', async () => {
|
it('should tap on "Join our open workspace" and navigate', async () => {
|
||||||
|
@ -44,7 +44,8 @@ describe('Onboarding', () => {
|
||||||
await waitFor(element(by.id('new-server-view')))
|
await waitFor(element(by.id('new-server-view')))
|
||||||
.toBeVisible()
|
.toBeVisible()
|
||||||
.withTimeout(5000);
|
.withTimeout(5000);
|
||||||
await element(by.id('new-server-view-input')).typeText(`${data.server}\n`);
|
await element(by.id('new-server-view-input')).replaceText(data.server);
|
||||||
|
await element(by.id('new-server-view-input')).tapReturnKey();
|
||||||
await waitFor(element(by.id('workspace-view')))
|
await waitFor(element(by.id('workspace-view')))
|
||||||
.toBeVisible()
|
.toBeVisible()
|
||||||
.withTimeout(60000);
|
.withTimeout(60000);
|
||||||
|
|
|
@ -1,9 +1,12 @@
|
||||||
const data = require('../../data');
|
const data = require('../../data');
|
||||||
const { navigateToLogin } = require('../../helpers/app');
|
const { navigateToLogin, platformTypes } = require('../../helpers/app');
|
||||||
|
|
||||||
describe('Forgot password screen', () => {
|
describe('Forgot password screen', () => {
|
||||||
|
let alertButtonType;
|
||||||
|
let textMatcher;
|
||||||
before(async () => {
|
before(async () => {
|
||||||
await device.launchApp({ permissions: { notifications: 'YES' }, delete: true });
|
await device.launchApp({ permissions: { notifications: 'YES' }, delete: true });
|
||||||
|
({ alertButtonType, textMatcher } = platformTypes[device.getPlatform()]);
|
||||||
await navigateToLogin();
|
await navigateToLogin();
|
||||||
await element(by.id('login-view-forgot-password')).tap();
|
await element(by.id('login-view-forgot-password')).tap();
|
||||||
await waitFor(element(by.id('forgot-password-view')))
|
await waitFor(element(by.id('forgot-password-view')))
|
||||||
|
@ -29,10 +32,10 @@ describe('Forgot password screen', () => {
|
||||||
it('should reset password and navigate to login', async () => {
|
it('should reset password and navigate to login', async () => {
|
||||||
await element(by.id('forgot-password-view-email')).replaceText(data.users.existing.email);
|
await element(by.id('forgot-password-view-email')).replaceText(data.users.existing.email);
|
||||||
await element(by.id('forgot-password-view-submit')).tap();
|
await element(by.id('forgot-password-view-submit')).tap();
|
||||||
await waitFor(element(by.text('OK')))
|
await waitFor(element(by[textMatcher]('OK')))
|
||||||
.toExist()
|
.toExist()
|
||||||
.withTimeout(10000);
|
.withTimeout(10000);
|
||||||
await element(by.text('OK')).tap();
|
await element(by[textMatcher]('OK').and(by.type(alertButtonType))).tap();
|
||||||
await waitFor(element(by.id('login-view')))
|
await waitFor(element(by.id('login-view')))
|
||||||
.toBeVisible()
|
.toBeVisible()
|
||||||
.withTimeout(60000);
|
.withTimeout(60000);
|
||||||
|
|
|
@ -1,9 +1,12 @@
|
||||||
const { navigateToRegister } = require('../../helpers/app');
|
const { navigateToRegister, platformTypes } = require('../../helpers/app');
|
||||||
const data = require('../../data');
|
const data = require('../../data');
|
||||||
|
|
||||||
describe('Create user screen', () => {
|
describe('Create user screen', () => {
|
||||||
|
let alertButtonType;
|
||||||
|
let textMatcher;
|
||||||
before(async () => {
|
before(async () => {
|
||||||
await device.launchApp({ permissions: { notifications: 'YES' }, delete: true });
|
await device.launchApp({ permissions: { notifications: 'YES' }, delete: true });
|
||||||
|
({ alertButtonType, textMatcher } = platformTypes[device.getPlatform()]);
|
||||||
await navigateToRegister();
|
await navigateToRegister();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -50,10 +53,10 @@ describe('Create user screen', () => {
|
||||||
await element(by.id('register-view-email')).replaceText(data.users.existing.email);
|
await element(by.id('register-view-email')).replaceText(data.users.existing.email);
|
||||||
await element(by.id('register-view-password')).replaceText(data.registeringUser.password);
|
await element(by.id('register-view-password')).replaceText(data.registeringUser.password);
|
||||||
await element(by.id('register-view-submit')).tap();
|
await element(by.id('register-view-submit')).tap();
|
||||||
await waitFor(element(by.text('Email already exists. [403]')).atIndex(0))
|
await waitFor(element(by[textMatcher]('Email already exists. [403]')).atIndex(0))
|
||||||
.toExist()
|
.toExist()
|
||||||
.withTimeout(10000);
|
.withTimeout(10000);
|
||||||
await element(by.text('OK')).tap();
|
await element(by[textMatcher]('OK').and(by.type(alertButtonType))).tap();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should submit username already taken and raise error', async () => {
|
it('should submit username already taken and raise error', async () => {
|
||||||
|
@ -62,10 +65,10 @@ describe('Create user screen', () => {
|
||||||
await element(by.id('register-view-email')).replaceText(data.registeringUser.email);
|
await element(by.id('register-view-email')).replaceText(data.registeringUser.email);
|
||||||
await element(by.id('register-view-password')).replaceText(data.registeringUser.password);
|
await element(by.id('register-view-password')).replaceText(data.registeringUser.password);
|
||||||
await element(by.id('register-view-submit')).tap();
|
await element(by.id('register-view-submit')).tap();
|
||||||
await waitFor(element(by.text('Username is already in use')).atIndex(0))
|
await waitFor(element(by[textMatcher]('Username is already in use')).atIndex(0))
|
||||||
.toExist()
|
.toExist()
|
||||||
.withTimeout(10000);
|
.withTimeout(10000);
|
||||||
await element(by.text('OK')).tap();
|
await element(by[textMatcher]('OK').and(by.type(alertButtonType))).tap();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should register', async () => {
|
it('should register', async () => {
|
||||||
|
|
|
@ -1,9 +1,12 @@
|
||||||
const { navigateToLogin, tapBack } = require('../../helpers/app');
|
const { navigateToLogin, tapBack, platformTypes } = require('../../helpers/app');
|
||||||
const data = require('../../data');
|
const data = require('../../data');
|
||||||
|
|
||||||
describe('Login screen', () => {
|
describe('Login screen', () => {
|
||||||
|
let alertButtonType;
|
||||||
|
let textMatcher;
|
||||||
before(async () => {
|
before(async () => {
|
||||||
await device.launchApp({ permissions: { notifications: 'YES' }, newInstance: true, delete: true });
|
await device.launchApp({ permissions: { notifications: 'YES' }, newInstance: true, delete: true });
|
||||||
|
({ alertButtonType, textMatcher } = platformTypes[device.getPlatform()]);
|
||||||
await navigateToLogin();
|
await navigateToLogin();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -58,10 +61,10 @@ describe('Login screen', () => {
|
||||||
await element(by.id('login-view-email')).replaceText(data.users.regular.username);
|
await element(by.id('login-view-email')).replaceText(data.users.regular.username);
|
||||||
await element(by.id('login-view-password')).replaceText('NotMyActualPassword');
|
await element(by.id('login-view-password')).replaceText('NotMyActualPassword');
|
||||||
await element(by.id('login-view-submit')).tap();
|
await element(by.id('login-view-submit')).tap();
|
||||||
await waitFor(element(by.text('Your credentials were rejected! Please try again.')))
|
await waitFor(element(by[textMatcher]('Your credentials were rejected! Please try again.')))
|
||||||
.toBeVisible()
|
.toBeVisible()
|
||||||
.withTimeout(10000);
|
.withTimeout(10000);
|
||||||
await element(by.text('OK')).tap();
|
await element(by[textMatcher]('OK').and(by.type(alertButtonType))).tap();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should login with success', async () => {
|
it('should login with success', async () => {
|
||||||
|
|
|
@ -14,7 +14,9 @@ describe('Rooms list screen', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should have room item', async () => {
|
it('should have room item', async () => {
|
||||||
await expect(element(by.id('rooms-list-view-item-general'))).toExist();
|
await waitFor(element(by.id('rooms-list-view-item-general')))
|
||||||
|
.toExist()
|
||||||
|
.withTimeout(10000);
|
||||||
});
|
});
|
||||||
|
|
||||||
// Render - Header
|
// Render - Header
|
||||||
|
|
|
@ -25,10 +25,10 @@ describe('Server history', () => {
|
||||||
|
|
||||||
it('should tap on a server history and navigate to login', async () => {
|
it('should tap on a server history and navigate to login', async () => {
|
||||||
await element(by.id(`server-history-${data.server}`)).tap();
|
await element(by.id(`server-history-${data.server}`)).tap();
|
||||||
await waitFor(element(by.id('login-view')))
|
await waitFor(element(by.id('login-view-email')))
|
||||||
.toBeVisible()
|
.toBeVisible()
|
||||||
.withTimeout(5000);
|
.withTimeout(5000);
|
||||||
await expect(element(by.id('login-view-email'))).toHaveText(data.users.regular.username);
|
await expect(element(by.label(data.users.regular.username).withAncestor(by.id('login-view-email'))));
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should delete server from history', async () => {
|
it('should delete server from history', async () => {
|
||||||
|
|
|
@ -1,9 +1,12 @@
|
||||||
const data = require('../../data');
|
const data = require('../../data');
|
||||||
const { tapBack, navigateToLogin, login, tryTapping } = require('../../helpers/app');
|
const { tapBack, navigateToLogin, login, tryTapping, platformTypes } = require('../../helpers/app');
|
||||||
|
|
||||||
describe('Create room screen', () => {
|
describe('Create room screen', () => {
|
||||||
|
let alertButtonType;
|
||||||
|
let textMatcher;
|
||||||
before(async () => {
|
before(async () => {
|
||||||
await device.launchApp({ permissions: { notifications: 'YES' }, delete: true });
|
await device.launchApp({ permissions: { notifications: 'YES' }, delete: true });
|
||||||
|
({ alertButtonType, textMatcher } = platformTypes[device.getPlatform()]);
|
||||||
await navigateToLogin();
|
await navigateToLogin();
|
||||||
await login(data.users.regular.username, data.users.regular.password);
|
await login(data.users.regular.username, data.users.regular.password);
|
||||||
});
|
});
|
||||||
|
@ -121,20 +124,26 @@ describe('Create room screen', () => {
|
||||||
|
|
||||||
describe('Usage', () => {
|
describe('Usage', () => {
|
||||||
it('should get invalid room', async () => {
|
it('should get invalid room', async () => {
|
||||||
await element(by.id('create-channel-name')).typeText('general');
|
await element(by.id('create-channel-name')).replaceText('general');
|
||||||
|
await waitFor(element(by.id('create-channel-submit')))
|
||||||
|
.toExist()
|
||||||
|
.withTimeout(2000);
|
||||||
await element(by.id('create-channel-submit')).tap();
|
await element(by.id('create-channel-submit')).tap();
|
||||||
await waitFor(element(by.text('A channel with name general exists')))
|
await waitFor(element(by[textMatcher]('A channel with name general exists')))
|
||||||
.toExist()
|
.toExist()
|
||||||
.withTimeout(60000);
|
.withTimeout(60000);
|
||||||
await expect(element(by.text('A channel with name general exists'))).toExist();
|
await expect(element(by[textMatcher]('A channel with name general exists'))).toExist();
|
||||||
await element(by.text('OK')).tap();
|
await element(by[textMatcher]('OK').and(by.type(alertButtonType))).tap();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should create public room', async () => {
|
it('should create public room', async () => {
|
||||||
const room = `public${data.random}`;
|
const room = `public${data.random}`;
|
||||||
await element(by.id('create-channel-name')).replaceText('');
|
await element(by.id('create-channel-name')).replaceText('');
|
||||||
await element(by.id('create-channel-name')).typeText(room);
|
await element(by.id('create-channel-name')).replaceText(room);
|
||||||
await element(by.id('create-channel-type')).tap();
|
await element(by.id('create-channel-type')).tap();
|
||||||
|
await waitFor(element(by.id('create-channel-submit')))
|
||||||
|
.toExist()
|
||||||
|
.withTimeout(2000);
|
||||||
await element(by.id('create-channel-submit')).tap();
|
await element(by.id('create-channel-submit')).tap();
|
||||||
await waitFor(element(by.id('room-view')))
|
await waitFor(element(by.id('room-view')))
|
||||||
.toExist()
|
.toExist()
|
||||||
|
@ -175,7 +184,10 @@ describe('Create room screen', () => {
|
||||||
await waitFor(element(by.id('create-channel-view')))
|
await waitFor(element(by.id('create-channel-view')))
|
||||||
.toExist()
|
.toExist()
|
||||||
.withTimeout(5000);
|
.withTimeout(5000);
|
||||||
await element(by.id('create-channel-name')).typeText(room);
|
await element(by.id('create-channel-name')).replaceText(room);
|
||||||
|
await waitFor(element(by.id('create-channel-submit')))
|
||||||
|
.toExist()
|
||||||
|
.withTimeout(2000);
|
||||||
await element(by.id('create-channel-submit')).tap();
|
await element(by.id('create-channel-submit')).tap();
|
||||||
await waitFor(element(by.id('room-view')))
|
await waitFor(element(by.id('room-view')))
|
||||||
.toExist()
|
.toExist()
|
||||||
|
@ -213,7 +225,10 @@ describe('Create room screen', () => {
|
||||||
await waitFor(element(by.id('create-channel-view')))
|
await waitFor(element(by.id('create-channel-view')))
|
||||||
.toExist()
|
.toExist()
|
||||||
.withTimeout(10000);
|
.withTimeout(10000);
|
||||||
await element(by.id('create-channel-name')).typeText(room);
|
await element(by.id('create-channel-name')).replaceText(room);
|
||||||
|
await waitFor(element(by.id('create-channel-submit')))
|
||||||
|
.toExist()
|
||||||
|
.withTimeout(2000);
|
||||||
await element(by.id('create-channel-submit')).tap();
|
await element(by.id('create-channel-submit')).tap();
|
||||||
await waitFor(element(by.id('room-view')))
|
await waitFor(element(by.id('room-view')))
|
||||||
.toExist()
|
.toExist()
|
||||||
|
|
|
@ -9,7 +9,8 @@ const {
|
||||||
starMessage,
|
starMessage,
|
||||||
pinMessage,
|
pinMessage,
|
||||||
dismissReviewNag,
|
dismissReviewNag,
|
||||||
tryTapping
|
tryTapping,
|
||||||
|
platformTypes
|
||||||
} = require('../../helpers/app');
|
} = require('../../helpers/app');
|
||||||
|
|
||||||
async function navigateToRoom(roomName) {
|
async function navigateToRoom(roomName) {
|
||||||
|
@ -22,9 +23,12 @@ async function navigateToRoom(roomName) {
|
||||||
|
|
||||||
describe('Room screen', () => {
|
describe('Room screen', () => {
|
||||||
const mainRoom = data.groups.private.name;
|
const mainRoom = data.groups.private.name;
|
||||||
|
let alertButtonType;
|
||||||
|
let textMatcher;
|
||||||
|
|
||||||
before(async () => {
|
before(async () => {
|
||||||
await device.launchApp({ permissions: { notifications: 'YES' }, delete: true });
|
await device.launchApp({ permissions: { notifications: 'YES' }, delete: true });
|
||||||
|
({ alertButtonType, textMatcher } = platformTypes[device.getPlatform()]);
|
||||||
await navigateToLogin();
|
await navigateToLogin();
|
||||||
await login(data.users.regular.username, data.users.regular.password);
|
await login(data.users.regular.username, data.users.regular.password);
|
||||||
await navigateToRoom(mainRoom);
|
await navigateToRoom(mainRoom);
|
||||||
|
@ -79,7 +83,7 @@ describe('Room screen', () => {
|
||||||
describe('Messagebox', () => {
|
describe('Messagebox', () => {
|
||||||
it('should send message', async () => {
|
it('should send message', async () => {
|
||||||
await mockMessage('message');
|
await mockMessage('message');
|
||||||
await expect(element(by.label(`${data.random}message`)).atIndex(0)).toExist();
|
await expect(element(by[textMatcher](`${data.random}message`)).atIndex(0)).toExist();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should show/hide emoji keyboard', async () => {
|
it('should show/hide emoji keyboard', async () => {
|
||||||
|
@ -100,8 +104,8 @@ describe('Room screen', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should show/hide emoji autocomplete', async () => {
|
it('should show/hide emoji autocomplete', async () => {
|
||||||
await element(by.id('messagebox-input')).tap();
|
|
||||||
await element(by.id('messagebox-input')).typeText(':joy');
|
await element(by.id('messagebox-input')).typeText(':joy');
|
||||||
|
await sleep(300);
|
||||||
await waitFor(element(by.id('messagebox-container')))
|
await waitFor(element(by.id('messagebox-container')))
|
||||||
.toExist()
|
.toExist()
|
||||||
.withTimeout(10000);
|
.withTimeout(10000);
|
||||||
|
@ -112,9 +116,8 @@ describe('Room screen', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should show and tap on emoji autocomplete', async () => {
|
it('should show and tap on emoji autocomplete', async () => {
|
||||||
await element(by.id('messagebox-input')).tap();
|
await element(by.id('messagebox-input')).typeText(':joy');
|
||||||
await element(by.id('messagebox-input')).replaceText(':');
|
await sleep(300);
|
||||||
await element(by.id('messagebox-input')).typeText('joy'); // workaround for number keyboard
|
|
||||||
await waitFor(element(by.id('messagebox-container')))
|
await waitFor(element(by.id('messagebox-container')))
|
||||||
.toExist()
|
.toExist()
|
||||||
.withTimeout(10000);
|
.withTimeout(10000);
|
||||||
|
@ -124,9 +127,8 @@ describe('Room screen', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should not show emoji autocomplete on semicolon in middle of a string', async () => {
|
it('should not show emoji autocomplete on semicolon in middle of a string', async () => {
|
||||||
await element(by.id('messagebox-input')).tap();
|
|
||||||
// await element(by.id('messagebox-input')).replaceText(':');
|
|
||||||
await element(by.id('messagebox-input')).typeText('name:is');
|
await element(by.id('messagebox-input')).typeText('name:is');
|
||||||
|
await sleep(300);
|
||||||
await waitFor(element(by.id('messagebox-container')))
|
await waitFor(element(by.id('messagebox-container')))
|
||||||
.toNotExist()
|
.toNotExist()
|
||||||
.withTimeout(20000);
|
.withTimeout(20000);
|
||||||
|
@ -135,8 +137,11 @@ describe('Room screen', () => {
|
||||||
|
|
||||||
it('should show and tap on user autocomplete and send mention', async () => {
|
it('should show and tap on user autocomplete and send mention', async () => {
|
||||||
const { username } = data.users.regular;
|
const { username } = data.users.regular;
|
||||||
await element(by.id('messagebox-input')).tap();
|
const messageMention = `@${username}`;
|
||||||
|
const message = `${data.random}mention`;
|
||||||
|
const fullMessage = `${messageMention} ${message}`;
|
||||||
await element(by.id('messagebox-input')).typeText(`@${username}`);
|
await element(by.id('messagebox-input')).typeText(`@${username}`);
|
||||||
|
await sleep(300);
|
||||||
await waitFor(element(by.id('messagebox-container')))
|
await waitFor(element(by.id('messagebox-container')))
|
||||||
.toExist()
|
.toExist()
|
||||||
.withTimeout(4000);
|
.withTimeout(4000);
|
||||||
|
@ -144,15 +149,24 @@ describe('Room screen', () => {
|
||||||
.toBeVisible()
|
.toBeVisible()
|
||||||
.withTimeout(4000);
|
.withTimeout(4000);
|
||||||
await tryTapping(element(by.id(`mention-item-${username}`)), 2000, true);
|
await tryTapping(element(by.id(`mention-item-${username}`)), 2000, true);
|
||||||
await expect(element(by.id('messagebox-input'))).toHaveText(`@${username} `);
|
await expect(element(by.id('messagebox-input'))).toHaveText(`${messageMention} `);
|
||||||
await tryTapping(element(by.id('messagebox-input')), 2000);
|
await tryTapping(element(by.id('messagebox-input')), 2000);
|
||||||
await element(by.id('messagebox-input')).typeText(`${data.random}mention`);
|
if (device.getPlatform() === 'ios') {
|
||||||
|
await element(by.id('messagebox-input')).typeText(message);
|
||||||
await element(by.id('messagebox-send-message')).tap();
|
await element(by.id('messagebox-send-message')).tap();
|
||||||
// await waitFor(element(by.label(`@${ data.user } ${ data.random }mention`)).atIndex(0)).toExist().withTimeout(60000);
|
const fullMessageMatcher = fullMessage.substr(1); // removes `@`
|
||||||
|
await waitFor(element(by[textMatcher](fullMessageMatcher)))
|
||||||
|
.toExist()
|
||||||
|
.withTimeout(60000);
|
||||||
|
await expect(element(by[textMatcher](fullMessageMatcher))).toExist();
|
||||||
|
await element(by[textMatcher](fullMessageMatcher)).atIndex(0).tap();
|
||||||
|
} else {
|
||||||
|
await element(by.id('messagebox-input')).replaceText(fullMessage);
|
||||||
|
await element(by.id('messagebox-send-message')).tap();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should not show user autocomplete on @ in the middle of a string', async () => {
|
it('should not show user autocomplete on @ in the middle of a string', async () => {
|
||||||
await element(by.id('messagebox-input')).tap();
|
|
||||||
await element(by.id('messagebox-input')).typeText('email@gmail');
|
await element(by.id('messagebox-input')).typeText('email@gmail');
|
||||||
await waitFor(element(by.id('messagebox-container')))
|
await waitFor(element(by.id('messagebox-container')))
|
||||||
.toNotExist()
|
.toNotExist()
|
||||||
|
@ -161,9 +175,7 @@ describe('Room screen', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should show and tap on room autocomplete', async () => {
|
it('should show and tap on room autocomplete', async () => {
|
||||||
await element(by.id('messagebox-input')).tap();
|
|
||||||
await element(by.id('messagebox-input')).typeText('#general');
|
await element(by.id('messagebox-input')).typeText('#general');
|
||||||
// await waitFor(element(by.id('messagebox-container'))).toExist().withTimeout(4000);
|
|
||||||
await waitFor(element(by.id('mention-item-general')))
|
await waitFor(element(by.id('mention-item-general')))
|
||||||
.toBeVisible()
|
.toBeVisible()
|
||||||
.withTimeout(4000);
|
.withTimeout(4000);
|
||||||
|
@ -181,7 +193,6 @@ describe('Room screen', () => {
|
||||||
await element(by.id('messagebox-input')).clearText();
|
await element(by.id('messagebox-input')).clearText();
|
||||||
});
|
});
|
||||||
it('should draft message', async () => {
|
it('should draft message', async () => {
|
||||||
await element(by.id('messagebox-input')).tap();
|
|
||||||
await element(by.id('messagebox-input')).typeText(`${data.random}draft`);
|
await element(by.id('messagebox-input')).typeText(`${data.random}draft`);
|
||||||
await tapBack();
|
await tapBack();
|
||||||
|
|
||||||
|
@ -197,25 +208,29 @@ describe('Room screen', () => {
|
||||||
|
|
||||||
describe('Message', () => {
|
describe('Message', () => {
|
||||||
it('should copy permalink', async () => {
|
it('should copy permalink', async () => {
|
||||||
await element(by.label(`${data.random}message`))
|
await element(by[textMatcher](`${data.random}message`))
|
||||||
.atIndex(0)
|
.atIndex(0)
|
||||||
.longPress();
|
.longPress();
|
||||||
await expect(element(by.id('action-sheet'))).toExist();
|
await waitFor(element(by.id('action-sheet')))
|
||||||
|
.toExist()
|
||||||
|
.withTimeout(2000);
|
||||||
await expect(element(by.id('action-sheet-handle'))).toBeVisible();
|
await expect(element(by.id('action-sheet-handle'))).toBeVisible();
|
||||||
await element(by.id('action-sheet-handle')).swipe('up', 'fast', 0.5);
|
await element(by.id('action-sheet-handle')).swipe('up', 'fast', 0.5);
|
||||||
await element(by.label('Permalink')).atIndex(0).tap();
|
await element(by[textMatcher]('Permalink')).atIndex(0).tap();
|
||||||
|
|
||||||
// TODO: test clipboard
|
// TODO: test clipboard
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should copy message', async () => {
|
it('should copy message', async () => {
|
||||||
await element(by.label(`${data.random}message`))
|
await element(by[textMatcher](`${data.random}message`))
|
||||||
.atIndex(0)
|
.atIndex(0)
|
||||||
.longPress();
|
.longPress();
|
||||||
await expect(element(by.id('action-sheet'))).toExist();
|
await waitFor(element(by.id('action-sheet')))
|
||||||
|
.toExist()
|
||||||
|
.withTimeout(2000);
|
||||||
await expect(element(by.id('action-sheet-handle'))).toBeVisible();
|
await expect(element(by.id('action-sheet-handle'))).toBeVisible();
|
||||||
await element(by.id('action-sheet-handle')).swipe('up', 'fast', 0.5);
|
await element(by.id('action-sheet-handle')).swipe('up', 'fast', 0.5);
|
||||||
await element(by.label('Copy')).atIndex(0).tap();
|
await element(by[textMatcher]('Copy')).atIndex(0).tap();
|
||||||
|
|
||||||
// TODO: test clipboard
|
// TODO: test clipboard
|
||||||
});
|
});
|
||||||
|
@ -224,23 +239,33 @@ describe('Room screen', () => {
|
||||||
await starMessage('message');
|
await starMessage('message');
|
||||||
|
|
||||||
await sleep(1000); // https://github.com/RocketChat/Rocket.Chat.ReactNative/issues/2324
|
await sleep(1000); // https://github.com/RocketChat/Rocket.Chat.ReactNative/issues/2324
|
||||||
await element(by.label(`${data.random}message`))
|
await element(by[textMatcher](`${data.random}message`))
|
||||||
.atIndex(0)
|
.atIndex(0)
|
||||||
.longPress();
|
.longPress();
|
||||||
await expect(element(by.id('action-sheet'))).toExist();
|
await waitFor(element(by.id('action-sheet')))
|
||||||
|
.toExist()
|
||||||
|
.withTimeout(2000);
|
||||||
await expect(element(by.id('action-sheet-handle'))).toBeVisible();
|
await expect(element(by.id('action-sheet-handle'))).toBeVisible();
|
||||||
await element(by.id('action-sheet-handle')).swipe('up', 'slow', 0.5);
|
await element(by.id('action-sheet-handle')).swipe('up', 'slow', 0.5);
|
||||||
await waitFor(element(by.label('Unstar')).atIndex(0))
|
await waitFor(element(by[textMatcher]('Unstar')).atIndex(0))
|
||||||
.toExist()
|
.toExist()
|
||||||
.withTimeout(6000);
|
.withTimeout(6000);
|
||||||
await element(by.id('action-sheet-handle')).swipe('down', 'fast', 0.8);
|
await element(by.id('action-sheet-handle')).swipe('down', 'fast', 0.8);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should react to message', async () => {
|
it('should react to message', async () => {
|
||||||
await element(by.label(`${data.random}message`))
|
await waitFor(element(by[textMatcher](`${data.random}message`)))
|
||||||
|
.toExist()
|
||||||
|
.withTimeout(60000);
|
||||||
|
await element(by[textMatcher](`${data.random}message`))
|
||||||
|
.atIndex(0)
|
||||||
|
.tap();
|
||||||
|
await element(by[textMatcher](`${data.random}message`))
|
||||||
.atIndex(0)
|
.atIndex(0)
|
||||||
.longPress();
|
.longPress();
|
||||||
await expect(element(by.id('action-sheet'))).toExist();
|
await waitFor(element(by.id('action-sheet')))
|
||||||
|
.toExist()
|
||||||
|
.withTimeout(2000);
|
||||||
await expect(element(by.id('action-sheet-handle'))).toBeVisible();
|
await expect(element(by.id('action-sheet-handle'))).toBeVisible();
|
||||||
await element(by.id('action-sheet-handle')).swipe('up', 'fast', 0.5);
|
await element(by.id('action-sheet-handle')).swipe('up', 'fast', 0.5);
|
||||||
await element(by.id('add-reaction')).tap();
|
await element(by.id('add-reaction')).tap();
|
||||||
|
@ -258,10 +283,12 @@ describe('Room screen', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should react to message with frequently used emoji', async () => {
|
it('should react to message with frequently used emoji', async () => {
|
||||||
await element(by.label(`${data.random}message`))
|
await element(by[textMatcher](`${data.random}message`))
|
||||||
.atIndex(0)
|
.atIndex(0)
|
||||||
.longPress();
|
.longPress();
|
||||||
await expect(element(by.id('action-sheet'))).toExist();
|
await waitFor(element(by.id('action-sheet')))
|
||||||
|
.toExist()
|
||||||
|
.withTimeout(2000);
|
||||||
await expect(element(by.id('action-sheet-handle'))).toBeVisible();
|
await expect(element(by.id('action-sheet-handle'))).toBeVisible();
|
||||||
await element(by.id('action-sheet-handle')).swipe('up', 'fast', 0.5);
|
await element(by.id('action-sheet-handle')).swipe('up', 'fast', 0.5);
|
||||||
await waitFor(element(by.id('message-actions-emoji-+1')))
|
await waitFor(element(by.id('message-actions-emoji-+1')))
|
||||||
|
@ -273,7 +300,7 @@ describe('Room screen', () => {
|
||||||
.withTimeout(60000);
|
.withTimeout(60000);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should show reaction picker on add reaction button pressed and have frequently used emoji', async () => {
|
it('should show reaction picker on add reaction button pressed and have frequently used emoji, and dismiss review nag', async () => {
|
||||||
await element(by.id('message-add-reaction')).tap();
|
await element(by.id('message-add-reaction')).tap();
|
||||||
await waitFor(element(by.id('reaction-picker')))
|
await waitFor(element(by.id('reaction-picker')))
|
||||||
.toExist()
|
.toExist()
|
||||||
|
@ -291,10 +318,6 @@ describe('Room screen', () => {
|
||||||
.withTimeout(60000);
|
.withTimeout(60000);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should ask for review', async () => {
|
|
||||||
await dismissReviewNag(); // TODO: Create a proper test for this elsewhere.
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should remove reaction', async () => {
|
it('should remove reaction', async () => {
|
||||||
await element(by.id('message-reaction-:grinning:')).tap();
|
await element(by.id('message-reaction-:grinning:')).tap();
|
||||||
await waitFor(element(by.id('message-reaction-:grinning:')))
|
await waitFor(element(by.id('message-reaction-:grinning:')))
|
||||||
|
@ -302,32 +325,43 @@ describe('Room screen', () => {
|
||||||
.withTimeout(60000);
|
.withTimeout(60000);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should ask for review', async () => {
|
||||||
|
await dismissReviewNag(); // TODO: Create a proper test for this elsewhere.
|
||||||
|
});
|
||||||
|
|
||||||
it('should edit message', async () => {
|
it('should edit message', async () => {
|
||||||
await mockMessage('edit');
|
await mockMessage('edit');
|
||||||
await element(by.label(`${data.random}edit`))
|
await element(by[textMatcher](`${data.random}edit`))
|
||||||
.atIndex(0)
|
.atIndex(0)
|
||||||
.longPress();
|
.longPress();
|
||||||
await expect(element(by.id('action-sheet'))).toExist();
|
await waitFor(element(by.id('action-sheet')))
|
||||||
|
.toExist()
|
||||||
|
.withTimeout(2000);
|
||||||
await expect(element(by.id('action-sheet-handle'))).toBeVisible();
|
await expect(element(by.id('action-sheet-handle'))).toBeVisible();
|
||||||
await element(by.id('action-sheet-handle')).swipe('up', 'fast', 0.5);
|
await element(by.id('action-sheet-handle')).swipe('up', 'fast', 0.5);
|
||||||
await element(by.label('Edit')).atIndex(0).tap();
|
await element(by[textMatcher]('Edit')).atIndex(0).tap();
|
||||||
await element(by.id('messagebox-input')).typeText('ed');
|
await element(by.id('messagebox-input')).replaceText(`${data.random}edited`);
|
||||||
await element(by.id('messagebox-send-message')).tap();
|
await element(by.id('messagebox-send-message')).tap();
|
||||||
await waitFor(element(by.label(`${data.random}edited (edited)`)).atIndex(0))
|
await waitFor(element(by[textMatcher](`${data.random}edited (edited)`)).atIndex(0))
|
||||||
.toExist()
|
.toExist()
|
||||||
.withTimeout(60000);
|
.withTimeout(60000);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should quote message', async () => {
|
it('should quote message', async () => {
|
||||||
await mockMessage('quote');
|
await mockMessage('quote');
|
||||||
await element(by.label(`${data.random}quote`))
|
await element(by[textMatcher](`${data.random}quote`))
|
||||||
.atIndex(0)
|
.atIndex(0)
|
||||||
.longPress();
|
.longPress();
|
||||||
await expect(element(by.id('action-sheet'))).toExist();
|
await waitFor(element(by.id('action-sheet')))
|
||||||
|
.toExist()
|
||||||
|
.withTimeout(2000);
|
||||||
await expect(element(by.id('action-sheet-handle'))).toBeVisible();
|
await expect(element(by.id('action-sheet-handle'))).toBeVisible();
|
||||||
await element(by.id('action-sheet-handle')).swipe('up', 'fast', 0.5);
|
await element(by.id('action-sheet-handle')).swipe('up', 'fast', 0.5);
|
||||||
await element(by.label('Quote')).atIndex(0).tap();
|
await element(by[textMatcher]('Quote')).atIndex(0).tap();
|
||||||
await element(by.id('messagebox-input')).typeText(`${data.random}quoted`);
|
await element(by.id('messagebox-input')).replaceText(`${data.random}quoted`);
|
||||||
|
await waitFor(element(by.id('messagebox-send-message')))
|
||||||
|
.toExist()
|
||||||
|
.withTimeout(2000);
|
||||||
await element(by.id('messagebox-send-message')).tap();
|
await element(by.id('messagebox-send-message')).tap();
|
||||||
|
|
||||||
// TODO: test if quote was sent
|
// TODO: test if quote was sent
|
||||||
|
@ -337,13 +371,13 @@ describe('Room screen', () => {
|
||||||
await mockMessage('pin');
|
await mockMessage('pin');
|
||||||
await pinMessage('pin');
|
await pinMessage('pin');
|
||||||
|
|
||||||
await waitFor(element(by.label(`${data.random}pin`)).atIndex(0))
|
await waitFor(element(by[textMatcher](`${data.random}pin`)).atIndex(0))
|
||||||
.toExist()
|
.toExist()
|
||||||
.withTimeout(5000);
|
.withTimeout(5000);
|
||||||
await waitFor(element(by.label(`${data.users.regular.username} Message pinned`)).atIndex(0))
|
await waitFor(element(by[textMatcher](`${data.users.regular.username} Message pinned`)).atIndex(0))
|
||||||
.toExist()
|
.toExist()
|
||||||
.withTimeout(5000);
|
.withTimeout(5000);
|
||||||
await element(by.label(`${data.random}pin`))
|
await element(by[textMatcher](`${data.random}pin`))
|
||||||
.atIndex(0)
|
.atIndex(0)
|
||||||
.longPress();
|
.longPress();
|
||||||
await waitFor(element(by.id('action-sheet')))
|
await waitFor(element(by.id('action-sheet')))
|
||||||
|
@ -351,7 +385,7 @@ describe('Room screen', () => {
|
||||||
.withTimeout(1000);
|
.withTimeout(1000);
|
||||||
await expect(element(by.id('action-sheet-handle'))).toBeVisible();
|
await expect(element(by.id('action-sheet-handle'))).toBeVisible();
|
||||||
await element(by.id('action-sheet-handle')).swipe('up', 'fast', 0.5);
|
await element(by.id('action-sheet-handle')).swipe('up', 'fast', 0.5);
|
||||||
await waitFor(element(by.label('Unpin')).atIndex(0))
|
await waitFor(element(by[textMatcher]('Unpin')).atIndex(0))
|
||||||
.toExist()
|
.toExist()
|
||||||
.withTimeout(2000);
|
.withTimeout(2000);
|
||||||
await element(by.id('action-sheet-handle')).swipe('down', 'fast', 0.8);
|
await element(by.id('action-sheet-handle')).swipe('down', 'fast', 0.8);
|
||||||
|
@ -359,26 +393,26 @@ describe('Room screen', () => {
|
||||||
|
|
||||||
it('should delete message', async () => {
|
it('should delete message', async () => {
|
||||||
await mockMessage('delete');
|
await mockMessage('delete');
|
||||||
|
await waitFor(element(by[textMatcher](`${data.random}delete`)).atIndex(0)).toBeVisible();
|
||||||
await waitFor(element(by.label(`${data.random}delete`)).atIndex(0)).toBeVisible();
|
await element(by[textMatcher](`${data.random}delete`))
|
||||||
await element(by.label(`${data.random}delete`))
|
|
||||||
.atIndex(0)
|
.atIndex(0)
|
||||||
.longPress();
|
.longPress();
|
||||||
await expect(element(by.id('action-sheet'))).toExist();
|
await waitFor(element(by.id('action-sheet')))
|
||||||
|
.toExist()
|
||||||
|
.withTimeout(2000);
|
||||||
await expect(element(by.id('action-sheet-handle'))).toBeVisible();
|
await expect(element(by.id('action-sheet-handle'))).toBeVisible();
|
||||||
await element(by.id('action-sheet-handle')).swipe('up', 'fast', 0.5);
|
await element(by.id('action-sheet-handle')).swipe('up', 'fast', 0.5);
|
||||||
await waitFor(element(by.label('Delete')))
|
await waitFor(element(by[textMatcher]('Delete')))
|
||||||
.toExist()
|
.toExist()
|
||||||
.withTimeout(1000);
|
.withTimeout(1000);
|
||||||
await element(by.label('Delete')).atIndex(0).tap();
|
await element(by[textMatcher]('Delete')).atIndex(0).tap();
|
||||||
|
|
||||||
const deleteAlertMessage = 'You will not be able to recover this message!';
|
const deleteAlertMessage = 'You will not be able to recover this message!';
|
||||||
await waitFor(element(by.text(deleteAlertMessage)).atIndex(0))
|
await waitFor(element(by[textMatcher](deleteAlertMessage)).atIndex(0))
|
||||||
.toExist()
|
.toExist()
|
||||||
.withTimeout(10000);
|
.withTimeout(10000);
|
||||||
await element(by.text('Delete')).tap();
|
await element(by[textMatcher]('Delete').and(by.type(alertButtonType))).tap();
|
||||||
|
await waitFor(element(by[textMatcher](`${data.random}delete`)).atIndex(0))
|
||||||
await waitFor(element(by.label(`${data.random}delete`)).atIndex(0))
|
|
||||||
.toNotExist()
|
.toNotExist()
|
||||||
.withTimeout(2000);
|
.withTimeout(2000);
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,5 +1,15 @@
|
||||||
const data = require('../../data');
|
const data = require('../../data');
|
||||||
const { navigateToLogin, login, tapBack, sleep, searchRoom, mockMessage, starMessage, pinMessage } = require('../../helpers/app');
|
const {
|
||||||
|
navigateToLogin,
|
||||||
|
login,
|
||||||
|
tapBack,
|
||||||
|
sleep,
|
||||||
|
searchRoom,
|
||||||
|
mockMessage,
|
||||||
|
starMessage,
|
||||||
|
pinMessage,
|
||||||
|
platformTypes
|
||||||
|
} = require('../../helpers/app');
|
||||||
const { sendMessage } = require('../../helpers/data_setup');
|
const { sendMessage } = require('../../helpers/data_setup');
|
||||||
|
|
||||||
async function navigateToRoomActions(type) {
|
async function navigateToRoomActions(type) {
|
||||||
|
@ -43,10 +53,13 @@ async function waitForToast() {
|
||||||
}
|
}
|
||||||
|
|
||||||
describe('Room actions screen', () => {
|
describe('Room actions screen', () => {
|
||||||
|
let alertButtonType;
|
||||||
|
let textMatcher;
|
||||||
before(async () => {
|
before(async () => {
|
||||||
await device.launchApp({ permissions: { notifications: 'YES' }, delete: true });
|
await device.launchApp({ permissions: { notifications: 'YES' }, delete: true });
|
||||||
await navigateToLogin();
|
await navigateToLogin();
|
||||||
await login(data.users.regular.username, data.users.regular.password);
|
await login(data.users.regular.username, data.users.regular.password);
|
||||||
|
({ alertButtonType, textMatcher } = platformTypes[device.getPlatform()]);
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('Render', () => {
|
describe('Render', () => {
|
||||||
|
@ -172,36 +185,12 @@ describe('Room actions screen', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('Usage', () => {
|
describe('Usage', () => {
|
||||||
describe('TDB', async () => {
|
|
||||||
// TODO: test into a jitsi call
|
|
||||||
// it('should NOT navigate to voice call', async() => {
|
|
||||||
// await waitFor(element(by.id('room-actions-voice'))).toExist();
|
|
||||||
// await element(by.id('room-actions-voice')).tap();
|
|
||||||
// await waitFor(element(by.id('room-actions-view'))).toExist().withTimeout(2000);
|
|
||||||
// await expect(element(by.id('room-actions-view'))).toExist();
|
|
||||||
// });
|
|
||||||
// TODO: test into a jitsi call
|
|
||||||
// it('should NOT navigate to video call', async() => {
|
|
||||||
// await element(by.id('room-actions-video')).tap();
|
|
||||||
// await waitFor(element(by.id('room-actions-view'))).toExist().withTimeout(2000);
|
|
||||||
// await expect(element(by.id('room-actions-view'))).toExist();
|
|
||||||
// });
|
|
||||||
// TODO: test share room link
|
|
||||||
// it('should NOT navigate to share room', async() => {
|
|
||||||
// await waitFor(element(by.id('room-actions-share'))).toExist();
|
|
||||||
// await element(by.id('room-actions-share')).tap();
|
|
||||||
// await waitFor(element(by.id('room-actions-view'))).toExist().withTimeout(2000);
|
|
||||||
// await expect(element(by.id('room-actions-view'))).toExist();
|
|
||||||
// });
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('Common', () => {
|
describe('Common', () => {
|
||||||
it('should show mentioned messages', async () => {
|
it('should show mentioned messages', async () => {
|
||||||
await element(by.id('room-actions-mentioned')).tap();
|
await element(by.id('room-actions-mentioned')).tap();
|
||||||
await waitFor(element(by.id('mentioned-messages-view')))
|
await waitFor(element(by.id('mentioned-messages-view')))
|
||||||
.toExist()
|
.toExist()
|
||||||
.withTimeout(2000);
|
.withTimeout(2000);
|
||||||
// await waitFor(element(by.text(` ${ data.random }mention`))).toExist().withTimeout(60000);
|
|
||||||
await backToActions();
|
await backToActions();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -220,23 +209,25 @@ describe('Room actions screen', () => {
|
||||||
.withTimeout(5000);
|
.withTimeout(5000);
|
||||||
|
|
||||||
// Go to starred messages
|
// Go to starred messages
|
||||||
|
await element(by.id('room-actions-view')).swipe('up');
|
||||||
|
await waitFor(element(by.id('room-actions-starred'))).toExist();
|
||||||
await element(by.id('room-actions-starred')).tap();
|
await element(by.id('room-actions-starred')).tap();
|
||||||
await waitFor(element(by.id('starred-messages-view')))
|
await waitFor(element(by.id('starred-messages-view')))
|
||||||
.toExist()
|
.toExist()
|
||||||
.withTimeout(2000);
|
.withTimeout(2000);
|
||||||
await waitFor(element(by.label(`${data.random}messageToStar`).withAncestor(by.id('starred-messages-view'))))
|
await waitFor(element(by[textMatcher](`${data.random}messageToStar`).withAncestor(by.id('starred-messages-view'))))
|
||||||
.toExist()
|
.toExist()
|
||||||
.withTimeout(60000);
|
.withTimeout(60000);
|
||||||
|
|
||||||
// Unstar message
|
// Unstar message
|
||||||
await element(by.label(`${data.random}messageToStar`))
|
await element(by[textMatcher](`${data.random}messageToStar`))
|
||||||
.atIndex(0)
|
.atIndex(0)
|
||||||
.longPress();
|
.longPress();
|
||||||
await expect(element(by.id('action-sheet'))).toExist();
|
await expect(element(by.id('action-sheet'))).toExist();
|
||||||
await expect(element(by.id('action-sheet-handle'))).toBeVisible();
|
await expect(element(by.id('action-sheet-handle'))).toBeVisible();
|
||||||
await element(by.label('Unstar')).atIndex(0).tap();
|
await element(by[textMatcher]('Unstar')).atIndex(0).tap();
|
||||||
|
|
||||||
await waitFor(element(by.label(`${data.random}messageToStar`).withAncestor(by.id('starred-messages-view'))))
|
await waitFor(element(by[textMatcher](`${data.random}messageToStar`).withAncestor(by.id('starred-messages-view'))))
|
||||||
.toBeNotVisible()
|
.toBeNotVisible()
|
||||||
.withTimeout(60000);
|
.withTimeout(60000);
|
||||||
await backToActions();
|
await backToActions();
|
||||||
|
@ -261,40 +252,22 @@ describe('Room actions screen', () => {
|
||||||
await waitFor(element(by.id('pinned-messages-view')))
|
await waitFor(element(by.id('pinned-messages-view')))
|
||||||
.toExist()
|
.toExist()
|
||||||
.withTimeout(2000);
|
.withTimeout(2000);
|
||||||
await waitFor(element(by.label(`${data.random}messageToPin`).withAncestor(by.id('pinned-messages-view'))))
|
await waitFor(element(by[textMatcher](`${data.random}messageToPin`).withAncestor(by.id('pinned-messages-view'))))
|
||||||
.toExist()
|
.toExist()
|
||||||
.withTimeout(6000);
|
.withTimeout(6000);
|
||||||
await element(by.label(`${data.random}messageToPin`).withAncestor(by.id('pinned-messages-view')))
|
await element(by[textMatcher](`${data.random}messageToPin`).withAncestor(by.id('pinned-messages-view')))
|
||||||
.atIndex(0)
|
.atIndex(0)
|
||||||
.longPress();
|
.longPress();
|
||||||
|
|
||||||
await expect(element(by.id('action-sheet'))).toExist();
|
await expect(element(by.id('action-sheet'))).toExist();
|
||||||
await expect(element(by.id('action-sheet-handle'))).toBeVisible();
|
await expect(element(by.id('action-sheet-handle'))).toBeVisible();
|
||||||
await element(by.label('Unpin')).atIndex(0).tap();
|
await element(by[textMatcher]('Unpin')).atIndex(0).tap();
|
||||||
|
|
||||||
await waitFor(element(by.label(`${data.random}messageToPin`).withAncestor(by.id('pinned-messages-view'))))
|
await waitFor(element(by[textMatcher](`${data.random}messageToPin`).withAncestor(by.id('pinned-messages-view'))))
|
||||||
.not.toExist()
|
.not.toExist()
|
||||||
.withTimeout(6000);
|
.withTimeout(6000);
|
||||||
await backToActions();
|
await backToActions();
|
||||||
});
|
});
|
||||||
|
|
||||||
// it('should search and find a message', async() => {
|
|
||||||
|
|
||||||
// //Go back to room and send a message
|
|
||||||
// await tapBack();
|
|
||||||
// await mockMessage('messageToFind');
|
|
||||||
|
|
||||||
// //Back into Room Actions
|
|
||||||
// await element(by.id('room-header')).tap();
|
|
||||||
// await waitFor(element(by.id('room-actions-view'))).toExist().withTimeout(5000);
|
|
||||||
|
|
||||||
// await element(by.id('room-actions-search')).tap();
|
|
||||||
// await waitFor(element(by.id('search-messages-view'))).toExist().withTimeout(2000);
|
|
||||||
// await expect(element(by.id('search-message-view-input'))).toExist();
|
|
||||||
// await element(by.id('search-message-view-input')).replaceText(`/${ data.random }messageToFind/`);
|
|
||||||
// await waitFor(element(by.label(`${ data.random }messageToFind`).withAncestor(by.id('search-messages-view')))).toExist().withTimeout(60000);
|
|
||||||
// await backToActions();
|
|
||||||
// });
|
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('Notification', () => {
|
describe('Notification', () => {
|
||||||
|
@ -370,14 +343,14 @@ describe('Room actions screen', () => {
|
||||||
.toExist()
|
.toExist()
|
||||||
.withTimeout(2000);
|
.withTimeout(2000);
|
||||||
await element(by.id('room-actions-leave-channel')).tap();
|
await element(by.id('room-actions-leave-channel')).tap();
|
||||||
await waitFor(element(by.text('Yes, leave it!')))
|
await waitFor(element(by[textMatcher]('Yes, leave it!')))
|
||||||
.toExist()
|
.toExist()
|
||||||
.withTimeout(2000);
|
.withTimeout(2000);
|
||||||
await element(by.text('Yes, leave it!')).tap();
|
await element(by[textMatcher]('Yes, leave it!').and(by.type(alertButtonType))).tap();
|
||||||
await waitFor(element(by.text('You are the last owner. Please set new owner before leaving the room.')))
|
await waitFor(element(by[textMatcher]('You are the last owner. Please set new owner before leaving the room.')))
|
||||||
.toExist()
|
.toExist()
|
||||||
.withTimeout(8000);
|
.withTimeout(8000);
|
||||||
await element(by.text('OK')).tap();
|
await element(by[textMatcher]('OK').and(by.type(alertButtonType))).tap();
|
||||||
await waitFor(element(by.id('room-actions-view')))
|
await waitFor(element(by.id('room-actions-view')))
|
||||||
.toExist()
|
.toExist()
|
||||||
.withTimeout(2000);
|
.withTimeout(2000);
|
||||||
|
@ -404,6 +377,7 @@ describe('Room actions screen', () => {
|
||||||
.withTimeout(4000);
|
.withTimeout(4000);
|
||||||
await element(by.id('select-users-view-search')).tap();
|
await element(by.id('select-users-view-search')).tap();
|
||||||
await element(by.id('select-users-view-search')).replaceText(user.username);
|
await element(by.id('select-users-view-search')).replaceText(user.username);
|
||||||
|
await sleep(300);
|
||||||
await waitFor(element(by.id(`select-users-view-item-${user.username}`)))
|
await waitFor(element(by.id(`select-users-view-item-${user.username}`)))
|
||||||
.toExist()
|
.toExist()
|
||||||
.withTimeout(10000);
|
.withTimeout(10000);
|
||||||
|
@ -437,14 +411,30 @@ describe('Room actions screen', () => {
|
||||||
await waitFor(element(by.id(`room-members-view-item-${username}`)))
|
await waitFor(element(by.id(`room-members-view-item-${username}`)))
|
||||||
.toExist()
|
.toExist()
|
||||||
.withTimeout(5000);
|
.withTimeout(5000);
|
||||||
|
let n = 0;
|
||||||
|
while (n < 3) {
|
||||||
|
// Max tries three times, in case it does not register the click
|
||||||
|
try {
|
||||||
await element(by.id(`room-members-view-item-${username}`)).tap();
|
await element(by.id(`room-members-view-item-${username}`)).tap();
|
||||||
await sleep(300);
|
await sleep(300);
|
||||||
await expect(element(by.id('action-sheet'))).toExist();
|
await waitFor(element(by.id('action-sheet')))
|
||||||
|
.toExist()
|
||||||
|
.withTimeout(5000);
|
||||||
await expect(element(by.id('action-sheet-handle'))).toBeVisible();
|
await expect(element(by.id('action-sheet-handle'))).toBeVisible();
|
||||||
|
await element(by.id('action-sheet-handle')).swipe('up');
|
||||||
|
return;
|
||||||
|
} catch (e) {
|
||||||
|
n += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const closeActionSheet = async () => {
|
const closeActionSheet = async () => {
|
||||||
await element(by.id('action-sheet-handle')).swipe('down', 'fast', 0.6);
|
await element(by.id('action-sheet-handle')).swipe('down', 'fast', 0.6);
|
||||||
|
await waitFor(element(by.id('action-sheet')))
|
||||||
|
.toBeNotVisible()
|
||||||
|
.withTimeout(1000);
|
||||||
|
await sleep(100);
|
||||||
};
|
};
|
||||||
|
|
||||||
it('should show all users', async () => {
|
it('should show all users', async () => {
|
||||||
|
@ -471,11 +461,14 @@ describe('Room actions screen', () => {
|
||||||
|
|
||||||
it('should remove user from room', async () => {
|
it('should remove user from room', async () => {
|
||||||
await openActionSheet('rocket.cat');
|
await openActionSheet('rocket.cat');
|
||||||
await element(by.label('Remove from room')).atIndex(0).tap();
|
await waitFor(element(by[textMatcher]('Remove from room')))
|
||||||
await waitFor(element(by.label('Are you sure?')))
|
.toExist()
|
||||||
|
.withTimeout(2000);
|
||||||
|
await element(by[textMatcher]('Remove from room')).atIndex(0).tap();
|
||||||
|
await waitFor(element(by[textMatcher]('Are you sure?')))
|
||||||
.toExist()
|
.toExist()
|
||||||
.withTimeout(5000);
|
.withTimeout(5000);
|
||||||
await element(by.label('Yes, remove user!').and(by.type('_UIAlertControllerActionView'))).tap();
|
await element(by[textMatcher]('Yes, remove user!').and(by.type(alertButtonType))).tap();
|
||||||
await waitFor(element(by.id('room-members-view-item-rocket.cat')))
|
await waitFor(element(by.id('room-members-view-item-rocket.cat')))
|
||||||
.toBeNotVisible()
|
.toBeNotVisible()
|
||||||
.withTimeout(60000);
|
.withTimeout(60000);
|
||||||
|
@ -548,24 +541,24 @@ describe('Room actions screen', () => {
|
||||||
|
|
||||||
it('should set/remove as mute', async () => {
|
it('should set/remove as mute', async () => {
|
||||||
await openActionSheet(user.username);
|
await openActionSheet(user.username);
|
||||||
await element(by.label('Mute')).atIndex(0).tap();
|
await element(by[textMatcher]('Mute')).atIndex(0).tap();
|
||||||
await waitFor(element(by.label('Are you sure?')))
|
await waitFor(element(by[textMatcher]('Are you sure?')))
|
||||||
.toExist()
|
.toExist()
|
||||||
.withTimeout(5000);
|
.withTimeout(5000);
|
||||||
await element(by.label('Mute').and(by.type('_UIAlertControllerActionView'))).tap();
|
await element(by[textMatcher]('Mute').and(by.type(alertButtonType))).tap();
|
||||||
await waitForToast();
|
await waitForToast();
|
||||||
|
|
||||||
await openActionSheet(user.username);
|
await openActionSheet(user.username);
|
||||||
await element(by.label('Unmute')).atIndex(0).tap();
|
await element(by[textMatcher]('Unmute')).atIndex(0).tap();
|
||||||
await waitFor(element(by.label('Are you sure?')))
|
await waitFor(element(by[textMatcher]('Are you sure?')))
|
||||||
.toExist()
|
.toExist()
|
||||||
.withTimeout(5000);
|
.withTimeout(5000);
|
||||||
await element(by.label('Unmute').and(by.type('_UIAlertControllerActionView'))).tap();
|
await element(by[textMatcher]('Unmute').and(by.type(alertButtonType))).tap();
|
||||||
await waitForToast();
|
await waitForToast();
|
||||||
|
|
||||||
await openActionSheet(user.username);
|
await openActionSheet(user.username);
|
||||||
// Tests if Remove as mute worked
|
// Tests if Remove as mute worked
|
||||||
await waitFor(element(by.label('Mute')))
|
await waitFor(element(by[textMatcher]('Mute')))
|
||||||
.toExist()
|
.toExist()
|
||||||
.withTimeout(5000);
|
.withTimeout(5000);
|
||||||
await closeActionSheet();
|
await closeActionSheet();
|
||||||
|
@ -576,21 +569,21 @@ describe('Room actions screen', () => {
|
||||||
const channelName = `#${data.groups.private.name}`;
|
const channelName = `#${data.groups.private.name}`;
|
||||||
await sendMessage(user, channelName, message);
|
await sendMessage(user, channelName, message);
|
||||||
await openActionSheet(user.username);
|
await openActionSheet(user.username);
|
||||||
await element(by.label('Ignore')).atIndex(0).tap();
|
await element(by[textMatcher]('Ignore')).atIndex(0).tap();
|
||||||
await waitForToast();
|
await waitForToast();
|
||||||
await backToActions();
|
await backToActions();
|
||||||
await tapBack();
|
await tapBack();
|
||||||
await waitFor(element(by.id('room-view')))
|
await waitFor(element(by.id('room-view')))
|
||||||
.toExist()
|
.toExist()
|
||||||
.withTimeout(60000);
|
.withTimeout(60000);
|
||||||
await waitFor(element(by.label('Message ignored. Tap to display it.')).atIndex(0))
|
await waitFor(element(by[textMatcher]('Message ignored. Tap to display it.')).atIndex(0))
|
||||||
.toExist()
|
.toExist()
|
||||||
.withTimeout(60000);
|
.withTimeout(60000);
|
||||||
await element(by.label('Message ignored. Tap to display it.')).atIndex(0).tap();
|
await element(by[textMatcher]('Message ignored. Tap to display it.')).atIndex(0).tap();
|
||||||
await waitFor(element(by.label(message)).atIndex(0))
|
await waitFor(element(by[textMatcher](message)).atIndex(0))
|
||||||
.toExist()
|
.toExist()
|
||||||
.withTimeout(60000);
|
.withTimeout(60000);
|
||||||
await element(by.label(message)).atIndex(0).tap();
|
await element(by[textMatcher](message)).atIndex(0).tap();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should navigate to direct message', async () => {
|
it('should navigate to direct message', async () => {
|
||||||
|
@ -607,7 +600,7 @@ describe('Room actions screen', () => {
|
||||||
.toExist()
|
.toExist()
|
||||||
.withTimeout(60000);
|
.withTimeout(60000);
|
||||||
await openActionSheet(user.username);
|
await openActionSheet(user.username);
|
||||||
await element(by.label('Direct message')).atIndex(0).tap();
|
await element(by[textMatcher]('Direct message')).atIndex(0).tap();
|
||||||
await waitFor(element(by.id('room-view')))
|
await waitFor(element(by.id('room-view')))
|
||||||
.toExist()
|
.toExist()
|
||||||
.withTimeout(60000);
|
.withTimeout(60000);
|
||||||
|
@ -630,11 +623,11 @@ describe('Room actions screen', () => {
|
||||||
it('should block/unblock user', async () => {
|
it('should block/unblock user', async () => {
|
||||||
await waitFor(element(by.id('room-actions-block-user'))).toExist();
|
await waitFor(element(by.id('room-actions-block-user'))).toExist();
|
||||||
await element(by.id('room-actions-block-user')).tap();
|
await element(by.id('room-actions-block-user')).tap();
|
||||||
await waitFor(element(by.label('Unblock user')))
|
await waitFor(element(by[textMatcher]('Unblock user')))
|
||||||
.toExist()
|
.toExist()
|
||||||
.withTimeout(60000);
|
.withTimeout(60000);
|
||||||
await element(by.id('room-actions-block-user')).tap();
|
await element(by.id('room-actions-block-user')).tap();
|
||||||
await waitFor(element(by.label('Block user')))
|
await waitFor(element(by[textMatcher]('Block user')))
|
||||||
.toExist()
|
.toExist()
|
||||||
.withTimeout(60000);
|
.withTimeout(60000);
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
const { navigateToLogin, login, mockMessage, tapBack, searchRoom } = require('../../helpers/app');
|
const { navigateToLogin, login, mockMessage, tapBack, searchRoom, platformTypes } = require('../../helpers/app');
|
||||||
const data = require('../../data');
|
const data = require('../../data');
|
||||||
|
|
||||||
const channel = data.groups.private.name;
|
const channel = data.groups.private.name;
|
||||||
|
@ -12,8 +12,10 @@ const navigateToRoom = async () => {
|
||||||
};
|
};
|
||||||
|
|
||||||
describe('Discussion', () => {
|
describe('Discussion', () => {
|
||||||
|
let textMatcher;
|
||||||
before(async () => {
|
before(async () => {
|
||||||
await device.launchApp({ permissions: { notifications: 'YES' }, newInstance: true, delete: true });
|
await device.launchApp({ permissions: { notifications: 'YES' }, newInstance: true, delete: true });
|
||||||
|
({ textMatcher } = platformTypes[device.getPlatform()]);
|
||||||
await navigateToLogin();
|
await navigateToLogin();
|
||||||
await login(data.users.regular.username, data.users.regular.password);
|
await login(data.users.regular.username, data.users.regular.password);
|
||||||
});
|
});
|
||||||
|
@ -24,12 +26,12 @@ describe('Discussion', () => {
|
||||||
await waitFor(element(by.id('new-message-view')))
|
await waitFor(element(by.id('new-message-view')))
|
||||||
.toExist()
|
.toExist()
|
||||||
.withTimeout(2000);
|
.withTimeout(2000);
|
||||||
await element(by.label('Create Discussion')).atIndex(0).tap();
|
await element(by[textMatcher]('Create Discussion')).atIndex(0).tap();
|
||||||
await waitFor(element(by.id('create-discussion-view')))
|
await waitFor(element(by.id('create-discussion-view')))
|
||||||
.toExist()
|
.toExist()
|
||||||
.withTimeout(60000);
|
.withTimeout(60000);
|
||||||
await expect(element(by.id('create-discussion-view'))).toExist();
|
await expect(element(by.id('create-discussion-view'))).toExist();
|
||||||
await element(by.label('Select a Channel...')).tap();
|
await element(by[textMatcher]('Select a Channel...')).tap();
|
||||||
await element(by.id('multi-select-search')).replaceText(`${channel}`);
|
await element(by.id('multi-select-search')).replaceText(`${channel}`);
|
||||||
await waitFor(element(by.id(`multi-select-item-${channel}`)))
|
await waitFor(element(by.id(`multi-select-item-${channel}`)))
|
||||||
.toExist()
|
.toExist()
|
||||||
|
@ -59,7 +61,7 @@ describe('Discussion', () => {
|
||||||
await waitFor(element(by.id('action-sheet')))
|
await waitFor(element(by.id('action-sheet')))
|
||||||
.toExist()
|
.toExist()
|
||||||
.withTimeout(2000);
|
.withTimeout(2000);
|
||||||
await element(by.label('Create Discussion')).atIndex(0).tap();
|
await element(by[textMatcher]('Create Discussion')).atIndex(0).tap();
|
||||||
await waitFor(element(by.id('create-discussion-view')))
|
await waitFor(element(by.id('create-discussion-view')))
|
||||||
.toExist()
|
.toExist()
|
||||||
.withTimeout(2000);
|
.withTimeout(2000);
|
||||||
|
@ -86,11 +88,11 @@ describe('Discussion', () => {
|
||||||
|
|
||||||
it('should create discussion', async () => {
|
it('should create discussion', async () => {
|
||||||
const discussionName = `${data.random}message`;
|
const discussionName = `${data.random}message`;
|
||||||
await element(by.label(discussionName)).atIndex(0).longPress();
|
await element(by[textMatcher](discussionName)).atIndex(0).longPress();
|
||||||
await waitFor(element(by.id('action-sheet')))
|
await waitFor(element(by.id('action-sheet')))
|
||||||
.toExist()
|
.toExist()
|
||||||
.withTimeout(2000);
|
.withTimeout(2000);
|
||||||
await element(by.label('Start a Discussion')).atIndex(0).tap();
|
await element(by[textMatcher]('Start a Discussion')).atIndex(0).tap();
|
||||||
await waitFor(element(by.id('create-discussion-view')))
|
await waitFor(element(by.id('create-discussion-view')))
|
||||||
.toExist()
|
.toExist()
|
||||||
.withTimeout(2000);
|
.withTimeout(2000);
|
||||||
|
@ -136,6 +138,7 @@ describe('Discussion', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should have starred', async () => {
|
it('should have starred', async () => {
|
||||||
|
await element(by.id('room-actions-scrollview')).swipe('up', 'slow', 0.5);
|
||||||
await expect(element(by.id('room-actions-starred'))).toBeVisible();
|
await expect(element(by.id('room-actions-starred'))).toBeVisible();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,14 @@
|
||||||
const data = require('../../data');
|
const data = require('../../data');
|
||||||
const { navigateToLogin, login, mockMessage, tapBack, sleep, searchRoom, dismissReviewNag } = require('../../helpers/app');
|
const {
|
||||||
|
navigateToLogin,
|
||||||
|
login,
|
||||||
|
mockMessage,
|
||||||
|
tapBack,
|
||||||
|
sleep,
|
||||||
|
searchRoom,
|
||||||
|
platformTypes,
|
||||||
|
dismissReviewNag
|
||||||
|
} = require('../../helpers/app');
|
||||||
|
|
||||||
async function navigateToRoom(roomName) {
|
async function navigateToRoom(roomName) {
|
||||||
await device.launchApp({ permissions: { notifications: 'YES' }, delete: true });
|
await device.launchApp({ permissions: { notifications: 'YES' }, delete: true });
|
||||||
|
@ -7,21 +16,22 @@ async function navigateToRoom(roomName) {
|
||||||
await login(data.users.regular.username, data.users.regular.password);
|
await login(data.users.regular.username, data.users.regular.password);
|
||||||
await searchRoom(`${roomName}`);
|
await searchRoom(`${roomName}`);
|
||||||
await element(by.id(`rooms-list-view-item-${roomName}`)).tap();
|
await element(by.id(`rooms-list-view-item-${roomName}`)).tap();
|
||||||
await waitFor(element(by.id('room-view')))
|
await waitFor(element(by.id(`room-view-title-${roomName}`)))
|
||||||
.toBeVisible()
|
.toExist()
|
||||||
.withTimeout(5000);
|
.withTimeout(5000);
|
||||||
}
|
}
|
||||||
|
|
||||||
describe('Threads', () => {
|
describe('Threads', () => {
|
||||||
const mainRoom = data.groups.private.name;
|
const mainRoom = data.groups.private.name;
|
||||||
|
let textMatcher;
|
||||||
|
|
||||||
before(async () => {
|
before(async () => {
|
||||||
|
({ textMatcher } = platformTypes[device.getPlatform()]);
|
||||||
await navigateToRoom(mainRoom);
|
await navigateToRoom(mainRoom);
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('Render', () => {
|
describe('Render', () => {
|
||||||
it('should have room screen', async () => {
|
it('should have room screen', async () => {
|
||||||
await expect(element(by.id('room-view'))).toExist();
|
|
||||||
await waitFor(element(by.id(`room-view-title-${mainRoom}`)))
|
await waitFor(element(by.id(`room-view-title-${mainRoom}`)))
|
||||||
.toExist()
|
.toExist()
|
||||||
.withTimeout(5000);
|
.withTimeout(5000);
|
||||||
|
@ -69,12 +79,15 @@ describe('Threads', () => {
|
||||||
const thread = `${data.random}thread`;
|
const thread = `${data.random}thread`;
|
||||||
it('should create thread', async () => {
|
it('should create thread', async () => {
|
||||||
await mockMessage('thread');
|
await mockMessage('thread');
|
||||||
await element(by.label(thread)).atIndex(0).longPress();
|
await element(by[textMatcher](thread)).atIndex(0).longPress();
|
||||||
await expect(element(by.id('action-sheet'))).toExist();
|
await expect(element(by.id('action-sheet'))).toExist();
|
||||||
await expect(element(by.id('action-sheet-handle'))).toBeVisible();
|
await expect(element(by.id('action-sheet-handle'))).toBeVisible();
|
||||||
await element(by.id('action-sheet-handle')).swipe('up', 'fast', 0.5);
|
await element(by.id('action-sheet-handle')).swipe('up', 'fast', 0.5);
|
||||||
await element(by.label('Reply in Thread')).atIndex(0).tap();
|
await element(by[textMatcher]('Reply in Thread')).atIndex(0).tap();
|
||||||
await element(by.id('messagebox-input')).typeText('replied');
|
await element(by.id('messagebox-input')).replaceText('replied');
|
||||||
|
await waitFor(element(by.id('messagebox-send-message')))
|
||||||
|
.toExist()
|
||||||
|
.withTimeout(2000);
|
||||||
await element(by.id('messagebox-send-message')).tap();
|
await element(by.id('messagebox-send-message')).tap();
|
||||||
await waitFor(element(by.id(`message-thread-button-${thread}`)))
|
await waitFor(element(by.id(`message-thread-button-${thread}`)))
|
||||||
.toExist()
|
.toExist()
|
||||||
|
@ -84,9 +97,6 @@ describe('Threads', () => {
|
||||||
|
|
||||||
it('should navigate to thread from button', async () => {
|
it('should navigate to thread from button', async () => {
|
||||||
await element(by.id(`message-thread-button-${thread}`)).tap();
|
await element(by.id(`message-thread-button-${thread}`)).tap();
|
||||||
await waitFor(element(by.id('room-view')))
|
|
||||||
.toExist()
|
|
||||||
.withTimeout(5000);
|
|
||||||
await waitFor(element(by.id(`room-view-title-${thread}`)))
|
await waitFor(element(by.id(`room-view-title-${thread}`)))
|
||||||
.toExist()
|
.toExist()
|
||||||
.withTimeout(5000);
|
.withTimeout(5000);
|
||||||
|
@ -96,13 +106,9 @@ describe('Threads', () => {
|
||||||
|
|
||||||
it('should toggle follow thread', async () => {
|
it('should toggle follow thread', async () => {
|
||||||
await element(by.id(`message-thread-button-${thread}`)).tap();
|
await element(by.id(`message-thread-button-${thread}`)).tap();
|
||||||
await waitFor(element(by.id('room-view')))
|
|
||||||
.toExist()
|
|
||||||
.withTimeout(5000);
|
|
||||||
await waitFor(element(by.id(`room-view-title-${thread}`)))
|
await waitFor(element(by.id(`room-view-title-${thread}`)))
|
||||||
.toExist()
|
.toExist()
|
||||||
.withTimeout(5000);
|
.withTimeout(5000);
|
||||||
await expect(element(by.id(`room-view-title-${thread}`))).toExist();
|
|
||||||
await element(by.id('room-view-header-unfollow')).tap();
|
await element(by.id('room-view-header-unfollow')).tap();
|
||||||
await waitFor(element(by.id('room-view-header-follow')))
|
await waitFor(element(by.id('room-view-header-follow')))
|
||||||
.toExist()
|
.toExist()
|
||||||
|
@ -119,14 +125,13 @@ describe('Threads', () => {
|
||||||
const messageText = 'threadonly';
|
const messageText = 'threadonly';
|
||||||
await mockMessage(messageText, true);
|
await mockMessage(messageText, true);
|
||||||
await tapBack();
|
await tapBack();
|
||||||
await waitFor(element(by.id('room-header').and(by.label(`${mainRoom}`))))
|
await waitFor(element(by.id(`room-view-title-${data.random}thread`)))
|
||||||
.toBeVisible()
|
.not.toExist()
|
||||||
.withTimeout(2000);
|
.withTimeout(5000);
|
||||||
await waitFor(element(by.id('room-header').and(by.label(`${data.random}thread`))))
|
await waitFor(element(by.id(`room-view-title-${mainRoom}`)))
|
||||||
.toBeNotVisible()
|
.toExist()
|
||||||
.withTimeout(2000);
|
.withTimeout(5000);
|
||||||
await sleep(500); // TODO: Find a better way to wait for the animation to finish and the messagebox-input to be available and usable :(
|
await waitFor(element(by[textMatcher](`${data.random}${messageText}`)).atIndex(0))
|
||||||
await waitFor(element(by.label(`${data.random}${messageText}`)).atIndex(0))
|
|
||||||
.toNotExist()
|
.toNotExist()
|
||||||
.withTimeout(2000);
|
.withTimeout(2000);
|
||||||
});
|
});
|
||||||
|
@ -137,40 +142,39 @@ describe('Threads', () => {
|
||||||
await waitFor(element(by.id('messagebox-input-thread')))
|
await waitFor(element(by.id('messagebox-input-thread')))
|
||||||
.toExist()
|
.toExist()
|
||||||
.withTimeout(5000);
|
.withTimeout(5000);
|
||||||
await element(by.id('messagebox-input-thread')).typeText(messageText);
|
await element(by.id('messagebox-input-thread')).replaceText(messageText);
|
||||||
await element(by.id('messagebox-send-to-channel')).tap();
|
await element(by.id('messagebox-send-to-channel')).tap();
|
||||||
await element(by.id('messagebox-send-message')).tap();
|
await element(by.id('messagebox-send-message')).tap();
|
||||||
await tapBack();
|
await tapBack();
|
||||||
await waitFor(element(by.id('room-header').and(by.label(`${mainRoom}`))))
|
await waitFor(element(by.id(`room-view-title-${data.random}thread`)))
|
||||||
.toBeVisible()
|
.not.toExist()
|
||||||
.withTimeout(2000);
|
.withTimeout(5000);
|
||||||
await waitFor(element(by.id('room-header').and(by.label(`${data.random}thread`))))
|
await waitFor(element(by.id(`room-view-title-${mainRoom}`)))
|
||||||
.toBeNotVisible()
|
.toExist()
|
||||||
.withTimeout(2000);
|
.withTimeout(5000);
|
||||||
await sleep(500); // TODO: Find a better way to wait for the animation to finish and the messagebox-input to be available and usable :(
|
await waitFor(element(by[textMatcher](messageText)).atIndex(0))
|
||||||
await waitFor(element(by.label(messageText)).atIndex(0))
|
|
||||||
.toExist()
|
.toExist()
|
||||||
.withTimeout(2000);
|
.withTimeout(2000);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should navigate to thread from thread name', async () => {
|
it('should navigate to thread from thread name', async () => {
|
||||||
const messageText = 'navthreadname';
|
const messageText = 'navthreadname';
|
||||||
await mockMessage('dummymessagebetweenthethread');
|
await mockMessage('dummymessagebetweenthethread'); // TODO: Create a proper test for this elsewhere.
|
||||||
await dismissReviewNag(); // TODO: Create a proper test for this elsewhere.
|
await dismissReviewNag();
|
||||||
await element(by.id(`message-thread-button-${thread}`)).tap();
|
await element(by.id(`message-thread-button-${thread}`)).tap();
|
||||||
await waitFor(element(by.id('messagebox-input-thread')))
|
await waitFor(element(by.id('messagebox-input-thread')))
|
||||||
.toExist()
|
.toExist()
|
||||||
.withTimeout(5000);
|
.withTimeout(5000);
|
||||||
await element(by.id('messagebox-input-thread')).typeText(messageText);
|
await element(by.id('messagebox-input-thread')).replaceText(messageText);
|
||||||
await element(by.id('messagebox-send-to-channel')).tap();
|
await element(by.id('messagebox-send-to-channel')).tap();
|
||||||
await element(by.id('messagebox-send-message')).tap();
|
await element(by.id('messagebox-send-message')).tap();
|
||||||
await tapBack();
|
await tapBack();
|
||||||
await waitFor(element(by.id('room-header').and(by.label(`${mainRoom}`))))
|
await waitFor(element(by.id(`room-view-title-${data.random}thread`)))
|
||||||
.toBeVisible()
|
.not.toExist()
|
||||||
.withTimeout(2000);
|
.withTimeout(5000);
|
||||||
await waitFor(element(by.id('room-header').and(by.label(`${data.random}thread`))))
|
await waitFor(element(by.id(`room-view-title-${mainRoom}`)))
|
||||||
.toBeNotVisible()
|
.toExist()
|
||||||
.withTimeout(2000);
|
.withTimeout(5000);
|
||||||
await waitFor(element(by.id(`message-thread-replied-on-${thread}`)))
|
await waitFor(element(by.id(`message-thread-replied-on-${thread}`)))
|
||||||
.toBeVisible()
|
.toBeVisible()
|
||||||
.withTimeout(2000);
|
.withTimeout(2000);
|
||||||
|
@ -211,7 +215,7 @@ describe('Threads', () => {
|
||||||
await waitFor(element(by.id(`room-view-title-${thread}`)))
|
await waitFor(element(by.id(`room-view-title-${thread}`)))
|
||||||
.toExist()
|
.toExist()
|
||||||
.withTimeout(5000);
|
.withTimeout(5000);
|
||||||
await element(by.id('messagebox-input-thread')).typeText(`${thread}draft`);
|
await element(by.id('messagebox-input-thread')).replaceText(`${thread}draft`);
|
||||||
await tapBack();
|
await tapBack();
|
||||||
|
|
||||||
await element(by.id(`message-thread-button-${thread}`)).tap();
|
await element(by.id(`message-thread-button-${thread}`)).tap();
|
||||||
|
|
|
@ -1,9 +1,11 @@
|
||||||
const data = require('../../data');
|
const data = require('../../data');
|
||||||
const { navigateToLogin, login } = require('../../helpers/app');
|
const { navigateToLogin, login, platformTypes } = require('../../helpers/app');
|
||||||
|
|
||||||
describe('Group DM', () => {
|
describe('Group DM', () => {
|
||||||
|
let textMatcher;
|
||||||
before(async () => {
|
before(async () => {
|
||||||
await device.launchApp({ permissions: { notifications: 'YES' }, delete: true });
|
await device.launchApp({ permissions: { notifications: 'YES' }, delete: true });
|
||||||
|
({ textMatcher } = platformTypes[device.getPlatform()]);
|
||||||
await navigateToLogin();
|
await navigateToLogin();
|
||||||
await login(data.users.regular.username, data.users.regular.password);
|
await login(data.users.regular.username, data.users.regular.password);
|
||||||
});
|
});
|
||||||
|
@ -29,7 +31,7 @@ describe('Group DM', () => {
|
||||||
|
|
||||||
describe('Usage', () => {
|
describe('Usage', () => {
|
||||||
it('should navigate to create DM', async () => {
|
it('should navigate to create DM', async () => {
|
||||||
await element(by.label('Create Direct Messages')).tap();
|
await element(by[textMatcher]('Create Direct Messages')).tap();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should add users', async () => {
|
it('should add users', async () => {
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
const data = require('../../data');
|
const data = require('../../data');
|
||||||
const { navigateToLogin, login, searchRoom, sleep } = require('../../helpers/app');
|
const { navigateToLogin, login, searchRoom, sleep, platformTypes } = require('../../helpers/app');
|
||||||
const { sendMessage } = require('../../helpers/data_setup');
|
const { sendMessage } = require('../../helpers/data_setup');
|
||||||
|
|
||||||
async function navigateToRoom(user) {
|
async function navigateToRoom(user) {
|
||||||
|
@ -12,9 +12,11 @@ async function navigateToRoom(user) {
|
||||||
|
|
||||||
describe('Mark as unread', () => {
|
describe('Mark as unread', () => {
|
||||||
const user = data.users.alternate.username;
|
const user = data.users.alternate.username;
|
||||||
|
let textMatcher;
|
||||||
|
|
||||||
before(async () => {
|
before(async () => {
|
||||||
await device.launchApp({ permissions: { notifications: 'YES' }, delete: true });
|
await device.launchApp({ permissions: { notifications: 'YES' }, delete: true });
|
||||||
|
({ textMatcher } = platformTypes[device.getPlatform()]);
|
||||||
await navigateToLogin();
|
await navigateToLogin();
|
||||||
await login(data.users.regular.username, data.users.regular.password);
|
await login(data.users.regular.username, data.users.regular.password);
|
||||||
await navigateToRoom(user);
|
await navigateToRoom(user);
|
||||||
|
@ -26,16 +28,16 @@ describe('Mark as unread', () => {
|
||||||
const message = `${data.random}message-mark-as-unread`;
|
const message = `${data.random}message-mark-as-unread`;
|
||||||
const channelName = `@${data.users.regular.username}`;
|
const channelName = `@${data.users.regular.username}`;
|
||||||
await sendMessage(data.users.alternate, channelName, message);
|
await sendMessage(data.users.alternate, channelName, message);
|
||||||
await waitFor(element(by.label(message)).atIndex(0))
|
await waitFor(element(by[textMatcher](message)).atIndex(0))
|
||||||
.toExist()
|
.toExist()
|
||||||
.withTimeout(30000);
|
.withTimeout(30000);
|
||||||
await sleep(300);
|
await sleep(300);
|
||||||
await element(by.label(message)).atIndex(0).longPress();
|
await element(by[textMatcher](message)).atIndex(0).longPress();
|
||||||
await waitFor(element(by.id('action-sheet-handle')))
|
await waitFor(element(by.id('action-sheet-handle')))
|
||||||
.toBeVisible()
|
.toBeVisible()
|
||||||
.withTimeout(3000);
|
.withTimeout(3000);
|
||||||
await element(by.id('action-sheet-handle')).swipe('up', 'fast', 0.5);
|
await element(by.id('action-sheet-handle')).swipe('up', 'fast', 0.5);
|
||||||
await element(by.label('Mark Unread')).atIndex(0).tap();
|
await element(by[textMatcher]('Mark Unread')).atIndex(0).tap();
|
||||||
await waitFor(element(by.id('rooms-list-view')))
|
await waitFor(element(by.id('rooms-list-view')))
|
||||||
.toExist()
|
.toExist()
|
||||||
.withTimeout(5000);
|
.withTimeout(5000);
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
const data = require('../../data');
|
const data = require('../../data');
|
||||||
const { navigateToLogin, login, tapBack, sleep, searchRoom } = require('../../helpers/app');
|
const { navigateToLogin, login, tapBack, sleep, searchRoom, platformTypes } = require('../../helpers/app');
|
||||||
|
|
||||||
const privateRoomName = data.groups.private.name;
|
const privateRoomName = data.groups.private.name;
|
||||||
|
|
||||||
|
@ -25,17 +25,20 @@ async function navigateToRoomInfo(type) {
|
||||||
.withTimeout(2000);
|
.withTimeout(2000);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function swipe(direction) {
|
||||||
|
await element(by.id('room-info-edit-view-list')).swipe(direction, 'fast', 0.8);
|
||||||
|
}
|
||||||
|
|
||||||
async function waitForToast() {
|
async function waitForToast() {
|
||||||
// await waitFor(element(by.id('toast'))).toExist().withTimeout(10000);
|
|
||||||
// await expect(element(by.id('toast'))).toExist();
|
|
||||||
// await waitFor(element(by.id('toast'))).toBeNotVisible().withTimeout(10000);
|
|
||||||
// await expect(element(by.id('toast'))).toBeNotVisible();
|
|
||||||
await sleep(300);
|
await sleep(300);
|
||||||
}
|
}
|
||||||
|
|
||||||
describe('Room info screen', () => {
|
describe('Room info screen', () => {
|
||||||
|
let alertButtonType;
|
||||||
|
let textMatcher;
|
||||||
before(async () => {
|
before(async () => {
|
||||||
await device.launchApp({ permissions: { notifications: 'YES' }, delete: true });
|
await device.launchApp({ permissions: { notifications: 'YES' }, delete: true });
|
||||||
|
({ alertButtonType, textMatcher } = platformTypes[device.getPlatform()]);
|
||||||
await navigateToLogin();
|
await navigateToLogin();
|
||||||
await login(data.users.regular.username, data.users.regular.password);
|
await login(data.users.regular.username, data.users.regular.password);
|
||||||
});
|
});
|
||||||
|
@ -72,15 +75,15 @@ describe('Room info screen', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should have description', async () => {
|
it('should have description', async () => {
|
||||||
await expect(element(by.label('Description'))).toExist();
|
await expect(element(by[textMatcher]('Description'))).toExist();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should have topic', async () => {
|
it('should have topic', async () => {
|
||||||
await expect(element(by.label('Topic'))).toExist();
|
await expect(element(by[textMatcher]('Topic'))).toExist();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should have announcement', async () => {
|
it('should have announcement', async () => {
|
||||||
await expect(element(by.label('Announcement'))).toExist();
|
await expect(element(by[textMatcher]('Announcement'))).toExist();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should have edit button', async () => {
|
it('should have edit button', async () => {
|
||||||
|
@ -124,8 +127,7 @@ describe('Room info screen', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should have type switch', async () => {
|
it('should have type switch', async () => {
|
||||||
// Ugly hack to scroll on detox
|
await swipe('up');
|
||||||
await element(by.id('room-info-edit-view-list')).swipe('up', 'fast', 0.8);
|
|
||||||
await expect(element(by.id('room-info-edit-view-t'))).toExist();
|
await expect(element(by.id('room-info-edit-view-t'))).toExist();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -150,44 +152,33 @@ describe('Room info screen', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
after(async () => {
|
after(async () => {
|
||||||
// Ugly hack to scroll on detox
|
await swipe('down');
|
||||||
await element(by.id('room-info-edit-view-list')).swipe('down', 'fast', 0.8);
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('Usage', () => {
|
describe('Usage', () => {
|
||||||
// it('should enter "invalid name" and get error', async() => {
|
|
||||||
// await element(by.type('UIScrollView')).atIndex(1).swipe('down');
|
|
||||||
// await element(by.id('room-info-edit-view-name')).replaceText('invalid name');
|
|
||||||
// await element(by.type('UIScrollView')).atIndex(1).swipe('up');
|
|
||||||
// await element(by.id('room-info-edit-view-submit')).tap();
|
|
||||||
// await waitFor(element(by.text('There was an error while saving settings!'))).toExist().withTimeout(60000);
|
|
||||||
// await expect(element(by.text('There was an error while saving settings!'))).toExist();
|
|
||||||
// await element(by.text('OK')).tap();
|
|
||||||
// await waitFor(element(by.text('There was an error while saving settings!'))).toBeNotVisible().withTimeout(10000);
|
|
||||||
// await element(by.type('UIScrollView')).atIndex(1).swipe('down');
|
|
||||||
// });
|
|
||||||
|
|
||||||
it('should change room name', async () => {
|
it('should change room name', async () => {
|
||||||
await element(by.id('room-info-edit-view-name')).replaceText(`${privateRoomName}new`);
|
await element(by.id('room-info-edit-view-name')).replaceText(`${privateRoomName}new`);
|
||||||
await element(by.id('room-info-edit-view-list')).swipe('up', 'fast', 0.5);
|
await element(by.id('room-info-edit-view-list')).swipe('up', 'fast', 0.5);
|
||||||
|
await swipe('up');
|
||||||
await element(by.id('room-info-edit-view-submit')).tap();
|
await element(by.id('room-info-edit-view-submit')).tap();
|
||||||
await waitForToast();
|
await waitForToast();
|
||||||
await tapBack();
|
await tapBack();
|
||||||
await waitFor(element(by.id('room-info-view')))
|
await waitFor(element(by.id('room-info-view')))
|
||||||
.toExist()
|
.toExist()
|
||||||
.withTimeout(2000);
|
.withTimeout(2000);
|
||||||
await expect(element(by.id('room-info-view-name'))).toHaveLabel(`${privateRoomName}new`);
|
const matcher = device.getPlatform() === 'android' ? 'toHaveText' : 'toHaveLabel';
|
||||||
|
await expect(element(by.id('room-info-view-name')))[matcher](`${privateRoomName}new`);
|
||||||
// change name to original
|
// change name to original
|
||||||
await element(by.id('room-info-view-edit-button')).tap();
|
await element(by.id('room-info-view-edit-button')).tap();
|
||||||
await waitFor(element(by.id('room-info-edit-view')))
|
await waitFor(element(by.id('room-info-edit-view')))
|
||||||
.toExist()
|
.toExist()
|
||||||
.withTimeout(2000);
|
.withTimeout(2000);
|
||||||
await element(by.id('room-info-edit-view-name')).replaceText(`${privateRoomName}`);
|
await element(by.id('room-info-edit-view-name')).replaceText(`${privateRoomName}`);
|
||||||
await element(by.id('room-info-edit-view-list')).swipe('up', 'fast', 0.5);
|
await swipe('up');
|
||||||
await element(by.id('room-info-edit-view-submit')).tap();
|
await element(by.id('room-info-edit-view-submit')).tap();
|
||||||
await waitForToast();
|
await waitForToast();
|
||||||
await element(by.id('room-info-edit-view-list')).swipe('down', 'fast', 0.8);
|
await swipe('down');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should reset form', async () => {
|
it('should reset form', async () => {
|
||||||
|
@ -196,10 +187,11 @@ describe('Room info screen', () => {
|
||||||
await element(by.id('room-info-edit-view-topic')).replaceText('abc');
|
await element(by.id('room-info-edit-view-topic')).replaceText('abc');
|
||||||
await element(by.id('room-info-edit-view-announcement')).replaceText('abc');
|
await element(by.id('room-info-edit-view-announcement')).replaceText('abc');
|
||||||
await element(by.id('room-info-edit-view-password')).replaceText('abc');
|
await element(by.id('room-info-edit-view-password')).replaceText('abc');
|
||||||
await element(by.id('room-info-edit-view-list')).swipe('up', 'fast', 0.5);
|
|
||||||
await element(by.id('room-info-edit-view-t')).tap();
|
await element(by.id('room-info-edit-view-t')).tap();
|
||||||
|
await swipe('up');
|
||||||
await element(by.id('room-info-edit-view-ro')).longPress(); // https://github.com/facebook/react-native/issues/28032
|
await element(by.id('room-info-edit-view-ro')).longPress(); // https://github.com/facebook/react-native/issues/28032
|
||||||
await element(by.id('room-info-edit-view-react-when-ro')).tap();
|
await element(by.id('room-info-edit-view-react-when-ro')).tap();
|
||||||
|
await swipe('up');
|
||||||
await element(by.id('room-info-edit-view-reset')).tap();
|
await element(by.id('room-info-edit-view-reset')).tap();
|
||||||
// after reset
|
// after reset
|
||||||
await expect(element(by.id('room-info-edit-view-name'))).toHaveText(privateRoomName);
|
await expect(element(by.id('room-info-edit-view-name'))).toHaveText(privateRoomName);
|
||||||
|
@ -207,22 +199,23 @@ describe('Room info screen', () => {
|
||||||
await expect(element(by.id('room-info-edit-view-topic'))).toHaveText('');
|
await expect(element(by.id('room-info-edit-view-topic'))).toHaveText('');
|
||||||
await expect(element(by.id('room-info-edit-view-announcement'))).toHaveText('');
|
await expect(element(by.id('room-info-edit-view-announcement'))).toHaveText('');
|
||||||
await expect(element(by.id('room-info-edit-view-password'))).toHaveText('');
|
await expect(element(by.id('room-info-edit-view-password'))).toHaveText('');
|
||||||
await expect(element(by.id('room-info-edit-view-t'))).toHaveValue('1');
|
// await swipe('down');
|
||||||
await expect(element(by.id('room-info-edit-view-ro'))).toHaveValue('0');
|
await expect(element(by.id('room-info-edit-view-t'))).toHaveToggleValue(true);
|
||||||
|
await expect(element(by.id('room-info-edit-view-ro'))).toHaveToggleValue(false);
|
||||||
await expect(element(by.id('room-info-edit-view-react-when-ro'))).toBeNotVisible();
|
await expect(element(by.id('room-info-edit-view-react-when-ro'))).toBeNotVisible();
|
||||||
await element(by.id('room-info-edit-view-list')).swipe('down', 'fast', 0.8);
|
await swipe('down');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should change room description', async () => {
|
it('should change room description', async () => {
|
||||||
await element(by.id('room-info-edit-view-description')).replaceText('new description');
|
await element(by.id('room-info-edit-view-description')).replaceText('new description');
|
||||||
await element(by.id('room-info-edit-view-list')).swipe('up', 'fast', 0.5);
|
await swipe('up');
|
||||||
await element(by.id('room-info-edit-view-submit')).tap();
|
await element(by.id('room-info-edit-view-submit')).tap();
|
||||||
await waitForToast();
|
await waitForToast();
|
||||||
await tapBack();
|
await tapBack();
|
||||||
await waitFor(element(by.id('room-info-view')))
|
await waitFor(element(by.id('room-info-view')))
|
||||||
.toExist()
|
.toExist()
|
||||||
.withTimeout(2000);
|
.withTimeout(2000);
|
||||||
await expect(element(by.label('new description').withAncestor(by.id('room-info-view-description')))).toExist();
|
await expect(element(by[textMatcher]('new description').withAncestor(by.id('room-info-view-description')))).toExist();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should change room topic', async () => {
|
it('should change room topic', async () => {
|
||||||
|
@ -234,14 +227,14 @@ describe('Room info screen', () => {
|
||||||
.toExist()
|
.toExist()
|
||||||
.withTimeout(2000);
|
.withTimeout(2000);
|
||||||
await element(by.id('room-info-edit-view-topic')).replaceText('new topic');
|
await element(by.id('room-info-edit-view-topic')).replaceText('new topic');
|
||||||
await element(by.id('room-info-edit-view-list')).swipe('up', 'fast', 0.5);
|
await swipe('up');
|
||||||
await element(by.id('room-info-edit-view-submit')).tap();
|
await element(by.id('room-info-edit-view-submit')).tap();
|
||||||
await waitForToast();
|
await waitForToast();
|
||||||
await tapBack();
|
await tapBack();
|
||||||
await waitFor(element(by.id('room-info-view')))
|
await waitFor(element(by.id('room-info-view')))
|
||||||
.toExist()
|
.toExist()
|
||||||
.withTimeout(2000);
|
.withTimeout(2000);
|
||||||
await expect(element(by.label('new topic').withAncestor(by.id('room-info-view-topic')))).toExist();
|
await expect(element(by[textMatcher]('new topic').withAncestor(by.id('room-info-view-topic')))).toExist();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should change room announcement', async () => {
|
it('should change room announcement', async () => {
|
||||||
|
@ -253,14 +246,14 @@ describe('Room info screen', () => {
|
||||||
.toExist()
|
.toExist()
|
||||||
.withTimeout(2000);
|
.withTimeout(2000);
|
||||||
await element(by.id('room-info-edit-view-announcement')).replaceText('new announcement');
|
await element(by.id('room-info-edit-view-announcement')).replaceText('new announcement');
|
||||||
await element(by.id('room-info-edit-view-list')).swipe('up', 'fast', 0.5);
|
await swipe('up');
|
||||||
await element(by.id('room-info-edit-view-submit')).tap();
|
await element(by.id('room-info-edit-view-submit')).tap();
|
||||||
await waitForToast();
|
await waitForToast();
|
||||||
await tapBack();
|
await tapBack();
|
||||||
await waitFor(element(by.id('room-info-view')))
|
await waitFor(element(by.id('room-info-view')))
|
||||||
.toExist()
|
.toExist()
|
||||||
.withTimeout(2000);
|
.withTimeout(2000);
|
||||||
await expect(element(by.label('new announcement').withAncestor(by.id('room-info-view-announcement')))).toExist();
|
await expect(element(by[textMatcher]('new announcement').withAncestor(by.id('room-info-view-announcement')))).toExist();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should change room password', async () => {
|
it('should change room password', async () => {
|
||||||
|
@ -271,61 +264,45 @@ describe('Room info screen', () => {
|
||||||
await waitFor(element(by.id('room-info-edit-view')))
|
await waitFor(element(by.id('room-info-edit-view')))
|
||||||
.toExist()
|
.toExist()
|
||||||
.withTimeout(2000);
|
.withTimeout(2000);
|
||||||
await element(by.id('room-info-edit-view-list')).swipe('up', 'fast', 0.5);
|
|
||||||
await element(by.id('room-info-edit-view-password')).replaceText('password');
|
await element(by.id('room-info-edit-view-password')).replaceText('password');
|
||||||
|
await swipe('up');
|
||||||
await element(by.id('room-info-edit-view-submit')).tap();
|
await element(by.id('room-info-edit-view-submit')).tap();
|
||||||
await waitForToast();
|
await waitForToast();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should change room type', async () => {
|
it('should change room type', async () => {
|
||||||
await element(by.id('room-info-edit-view-list')).swipe('up', 'fast', 0.5);
|
await swipe('down');
|
||||||
await element(by.id('room-info-edit-view-t')).tap();
|
await element(by.id('room-info-edit-view-t')).tap();
|
||||||
|
await swipe('up');
|
||||||
await element(by.id('room-info-edit-view-submit')).tap();
|
await element(by.id('room-info-edit-view-submit')).tap();
|
||||||
await waitForToast();
|
await waitForToast();
|
||||||
|
await swipe('down');
|
||||||
await element(by.id('room-info-edit-view-t')).tap();
|
await element(by.id('room-info-edit-view-t')).tap();
|
||||||
|
await swipe('up');
|
||||||
await element(by.id('room-info-edit-view-submit')).tap();
|
await element(by.id('room-info-edit-view-submit')).tap();
|
||||||
await waitForToast();
|
await waitForToast();
|
||||||
});
|
});
|
||||||
|
|
||||||
// it('should change room read only and allow reactions', async() => {
|
|
||||||
// await sleep(1000);
|
|
||||||
// await element(by.type('UIScrollView')).atIndex(1).swipe('up');
|
|
||||||
// await element(by.id('room-info-edit-view-ro')).tap();
|
|
||||||
// await waitFor(element(by.id('room-info-edit-view-react-when-ro'))).toExist().withTimeout(2000);
|
|
||||||
// await expect(element(by.id('room-info-edit-view-react-when-ro'))).toExist();
|
|
||||||
// await element(by.id('room-info-edit-view-react-when-ro')).tap();
|
|
||||||
// await element(by.id('room-info-edit-view-submit')).tap();
|
|
||||||
// await waitForToast();
|
|
||||||
// // TODO: test if it's possible to react
|
|
||||||
// });
|
|
||||||
|
|
||||||
it('should archive room', async () => {
|
it('should archive room', async () => {
|
||||||
await element(by.id('room-info-edit-view-list')).swipe('up', 'fast', 0.5);
|
await element(by.id('room-info-edit-view-list')).swipe('up', 'fast', 0.5);
|
||||||
await element(by.id('room-info-edit-view-archive')).tap();
|
await element(by.id('room-info-edit-view-archive')).tap();
|
||||||
await waitFor(element(by.text('Yes, archive it!')))
|
await waitFor(element(by[textMatcher]('Yes, archive it!')))
|
||||||
.toExist()
|
.toExist()
|
||||||
.withTimeout(5000);
|
.withTimeout(5000);
|
||||||
await element(by.text('Yes, archive it!')).tap();
|
await element(by[textMatcher]('Yes, archive it!').and(by.type(alertButtonType))).tap();
|
||||||
await waitFor(element(by.id('room-info-edit-view-unarchive')))
|
await waitFor(element(by.id('room-info-edit-view-unarchive')))
|
||||||
.toExist()
|
.toExist()
|
||||||
.withTimeout(60000);
|
.withTimeout(60000);
|
||||||
await expect(element(by.id('room-info-edit-view-archive'))).toBeNotVisible();
|
await expect(element(by.id('room-info-edit-view-archive'))).toBeNotVisible();
|
||||||
// TODO: needs permission to unarchive
|
|
||||||
// await element(by.id('room-info-edit-view-archive')).tap();
|
|
||||||
// await waitFor(element(by.text('Yes, unarchive it!'))).toExist().withTimeout(5000);
|
|
||||||
// await expect(element(by.text('Yes, unarchive it!'))).toExist();
|
|
||||||
// await element(by.text('Yes, unarchive it!')).tap();
|
|
||||||
// await waitFor(element(by.text('ARCHIVE'))).toExist().withTimeout(60000);
|
|
||||||
// await expect(element(by.text('ARCHIVE'))).toExist();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should delete room', async () => {
|
it('should delete room', async () => {
|
||||||
await element(by.id('room-info-edit-view-list')).swipe('up', 'fast', 0.5);
|
await swipe('up');
|
||||||
await element(by.id('room-info-edit-view-delete')).tap();
|
await element(by.id('room-info-edit-view-delete')).tap();
|
||||||
await waitFor(element(by.text('Yes, delete it!')))
|
await waitFor(element(by[textMatcher]('Yes, delete it!')))
|
||||||
.toExist()
|
.toExist()
|
||||||
.withTimeout(5000);
|
.withTimeout(5000);
|
||||||
await element(by.text('Yes, delete it!')).tap();
|
await element(by[textMatcher]('Yes, delete it!').and(by.type(alertButtonType))).tap();
|
||||||
await waitFor(element(by.id('rooms-list-view')))
|
await waitFor(element(by.id('rooms-list-view')))
|
||||||
.toExist()
|
.toExist()
|
||||||
.withTimeout(10000);
|
.withTimeout(10000);
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
const data = require('../../data');
|
const data = require('../../data');
|
||||||
const { navigateToLogin, tapBack, login, searchRoom } = require('../../helpers/app');
|
const { navigateToLogin, tapBack, login, searchRoom, sleep, platformTypes } = require('../../helpers/app');
|
||||||
|
|
||||||
async function navigateToRoom(roomName) {
|
async function navigateToRoom(roomName) {
|
||||||
await searchRoom(`${roomName}`);
|
await searchRoom(`${roomName}`);
|
||||||
|
@ -7,8 +7,14 @@ async function navigateToRoom(roomName) {
|
||||||
await waitFor(element(by.id('room-view')))
|
await waitFor(element(by.id('room-view')))
|
||||||
.toBeVisible()
|
.toBeVisible()
|
||||||
.withTimeout(5000);
|
.withTimeout(5000);
|
||||||
|
await waitFor(element(by.id(`room-view-title-${roomName}`)))
|
||||||
|
.toExist()
|
||||||
|
.withTimeout(5000);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let textMatcher;
|
||||||
|
let alertButtonType;
|
||||||
|
|
||||||
async function clearCache() {
|
async function clearCache() {
|
||||||
await waitFor(element(by.id('room-view')))
|
await waitFor(element(by.id('room-view')))
|
||||||
.toBeVisible()
|
.toBeVisible()
|
||||||
|
@ -26,10 +32,10 @@ async function clearCache() {
|
||||||
.toBeVisible()
|
.toBeVisible()
|
||||||
.withTimeout(2000);
|
.withTimeout(2000);
|
||||||
await element(by.id('settings-view-clear-cache')).tap();
|
await element(by.id('settings-view-clear-cache')).tap();
|
||||||
await waitFor(element(by.text('This will clear all your offline data.')))
|
await waitFor(element(by[textMatcher]('This will clear all your offline data.')))
|
||||||
.toExist()
|
.toExist()
|
||||||
.withTimeout(2000);
|
.withTimeout(2000);
|
||||||
await element(by.label('Clear').and(by.type('_UIAlertControllerActionView'))).tap();
|
await element(by[textMatcher]('Clear').and(by.type(alertButtonType))).tap();
|
||||||
await waitFor(element(by.id('rooms-list-view')))
|
await waitFor(element(by.id('rooms-list-view')))
|
||||||
.toBeVisible()
|
.toBeVisible()
|
||||||
.withTimeout(5000);
|
.withTimeout(5000);
|
||||||
|
@ -39,6 +45,10 @@ async function clearCache() {
|
||||||
}
|
}
|
||||||
|
|
||||||
async function waitForLoading() {
|
async function waitForLoading() {
|
||||||
|
if (device.getPlatform() === 'android') {
|
||||||
|
await sleep(10000);
|
||||||
|
return; // FIXME: Loading indicator doesn't animate properly on android
|
||||||
|
}
|
||||||
await waitFor(element(by.id('loading')))
|
await waitFor(element(by.id('loading')))
|
||||||
.toBeVisible()
|
.toBeVisible()
|
||||||
.withTimeout(5000);
|
.withTimeout(5000);
|
||||||
|
@ -50,21 +60,22 @@ async function waitForLoading() {
|
||||||
describe('Room', () => {
|
describe('Room', () => {
|
||||||
before(async () => {
|
before(async () => {
|
||||||
await device.launchApp({ permissions: { notifications: 'YES' }, delete: true });
|
await device.launchApp({ permissions: { notifications: 'YES' }, delete: true });
|
||||||
|
({ alertButtonType, textMatcher } = platformTypes[device.getPlatform()]);
|
||||||
await navigateToLogin();
|
await navigateToLogin();
|
||||||
await login(data.adminUser, data.adminPassword);
|
await login(data.adminUser, data.adminPassword);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should jump to an old message and load its surroundings', async () => {
|
it('should jump to an old message and load its surroundings', async () => {
|
||||||
await navigateToRoom('jumping');
|
await navigateToRoom('jumping');
|
||||||
await waitFor(element(by.label('Quote first message')))
|
await waitFor(element(by[textMatcher]('300')))
|
||||||
.toExist()
|
.toExist()
|
||||||
.withTimeout(5000);
|
.withTimeout(5000);
|
||||||
await element(by.label('1')).atIndex(0).tap();
|
await element(by[textMatcher]('1')).atIndex(0).tap();
|
||||||
await waitForLoading();
|
await waitForLoading();
|
||||||
await waitFor(element(by.label('1')).atIndex(0))
|
await waitFor(element(by[textMatcher]('1')).atIndex(0))
|
||||||
.toExist()
|
.toExist()
|
||||||
.withTimeout(10000);
|
.withTimeout(10000);
|
||||||
await expect(element(by.label('2'))).toExist();
|
await expect(element(by[textMatcher]('2'))).toExist();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should tap FAB and scroll to bottom', async () => {
|
it('should tap FAB and scroll to bottom', async () => {
|
||||||
|
@ -72,7 +83,7 @@ describe('Room', () => {
|
||||||
.toExist()
|
.toExist()
|
||||||
.withTimeout(5000);
|
.withTimeout(5000);
|
||||||
await element(by.id('nav-jump-to-bottom')).tap();
|
await element(by.id('nav-jump-to-bottom')).tap();
|
||||||
await waitFor(element(by.label('Quote first message')))
|
await waitFor(element(by[textMatcher]('Quote first message')))
|
||||||
.toExist()
|
.toExist()
|
||||||
.withTimeout(5000);
|
.withTimeout(5000);
|
||||||
await clearCache();
|
await clearCache();
|
||||||
|
@ -83,14 +94,15 @@ describe('Room', () => {
|
||||||
await waitFor(element(by.id('room-view-messages')))
|
await waitFor(element(by.id('room-view-messages')))
|
||||||
.toExist()
|
.toExist()
|
||||||
.withTimeout(5000);
|
.withTimeout(5000);
|
||||||
await waitFor(element(by.label('300')))
|
await waitFor(element(by[textMatcher]('300')))
|
||||||
.toExist()
|
.toExist()
|
||||||
.withTimeout(5000);
|
.withTimeout(5000);
|
||||||
let found = false;
|
let found = false;
|
||||||
while (!found) {
|
while (!found) {
|
||||||
await element(by.id('room-view-messages')).atIndex(0).scroll(500, 'up');
|
|
||||||
try {
|
try {
|
||||||
await expect(element(by.label('249'))).toExist();
|
const direction = device.getPlatform() === 'android' ? 'down' : 'up';
|
||||||
|
await element(by.id('room-view-messages')).scroll(500, direction);
|
||||||
|
await expect(element(by[textMatcher]('249'))).toExist();
|
||||||
found = true;
|
found = true;
|
||||||
} catch {
|
} catch {
|
||||||
//
|
//
|
||||||
|
@ -101,107 +113,130 @@ describe('Room', () => {
|
||||||
|
|
||||||
it('should search for old message and load its surroundings', async () => {
|
it('should search for old message and load its surroundings', async () => {
|
||||||
await navigateToRoom('jumping');
|
await navigateToRoom('jumping');
|
||||||
|
await sleep(1000); // wait for proper load the room
|
||||||
await element(by.id('room-view-search')).tap();
|
await element(by.id('room-view-search')).tap();
|
||||||
await waitFor(element(by.id('search-messages-view')))
|
await waitFor(element(by.id('search-messages-view')))
|
||||||
.toExist()
|
.toExist()
|
||||||
.withTimeout(5000);
|
.withTimeout(5000);
|
||||||
await element(by.id('search-message-view-input')).typeText('30\n');
|
await element(by.id('search-message-view-input')).replaceText('30');
|
||||||
await waitFor(element(by.label('30')).atIndex(0))
|
await waitFor(element(by[textMatcher]('30')).atIndex(1))
|
||||||
.toExist()
|
.toExist()
|
||||||
.withTimeout(5000);
|
.withTimeout(30000);
|
||||||
await element(by.label('30')).atIndex(0).tap();
|
await element(by[textMatcher]('30')).atIndex(1).tap();
|
||||||
await waitForLoading();
|
await waitForLoading();
|
||||||
await expect(element(by.label('30'))).toExist();
|
await waitFor(element(by[textMatcher]('30')).atIndex(0))
|
||||||
await expect(element(by.label('31'))).toExist();
|
.toExist()
|
||||||
await expect(element(by.label('32'))).toExist();
|
.withTimeout(30000);
|
||||||
|
await expect(element(by[textMatcher]('31'))).toExist();
|
||||||
|
await expect(element(by[textMatcher]('32'))).toExist();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should load newer and older messages', async () => {
|
it('should load newer and older messages', async () => {
|
||||||
await element(by.id('room-view-messages')).atIndex(0).swipe('down', 'fast', 0.8);
|
// TODO: couldn't make it work on Android :(
|
||||||
await waitFor(element(by.label('5')))
|
if (device.getPlatform() === 'android') {
|
||||||
.toExist()
|
return;
|
||||||
.withTimeout(10000);
|
}
|
||||||
await waitFor(element(by.label('Load Older')))
|
let found = false;
|
||||||
.toExist()
|
while (!found) {
|
||||||
.withTimeout(5000);
|
try {
|
||||||
await element(by.label('Load Older')).atIndex(0).tap();
|
// it doesn't recognize this list
|
||||||
await waitFor(element(by.label('4')))
|
await element(by.id('room-view-messages')).scroll(500, 'up');
|
||||||
|
await expect(element(by[textMatcher]('Load Older'))).toBeVisible();
|
||||||
|
await expect(element(by[textMatcher]('5'))).toExist();
|
||||||
|
found = true;
|
||||||
|
} catch {
|
||||||
|
//
|
||||||
|
}
|
||||||
|
}
|
||||||
|
await element(by[textMatcher]('Load Older')).atIndex(0).tap();
|
||||||
|
await waitFor(element(by[textMatcher]('4')))
|
||||||
.toExist()
|
.toExist()
|
||||||
.withTimeout(5000);
|
.withTimeout(5000);
|
||||||
await element(by.id('room-view-messages')).atIndex(0).swipe('down', 'fast', 0.5);
|
await element(by.id('room-view-messages')).atIndex(0).swipe('down', 'fast', 0.5);
|
||||||
await waitFor(element(by.label('1')))
|
await waitFor(element(by[textMatcher]('1')))
|
||||||
.toExist()
|
.toExist()
|
||||||
.withTimeout(5000);
|
.withTimeout(5000);
|
||||||
await element(by.id('room-view-messages')).atIndex(0).swipe('up', 'fast', 0.5);
|
await element(by.id('room-view-messages')).atIndex(0).swipe('up', 'fast', 0.5);
|
||||||
await waitFor(element(by.label('25')))
|
await waitFor(element(by[textMatcher]('25')))
|
||||||
.toExist()
|
.toExist()
|
||||||
.withTimeout(5000);
|
.withTimeout(5000);
|
||||||
await element(by.id('room-view-messages')).atIndex(0).swipe('up', 'fast', 0.5);
|
await element(by.id('room-view-messages')).atIndex(0).swipe('up', 'fast', 0.5);
|
||||||
await waitFor(element(by.label('50')))
|
await waitFor(element(by[textMatcher]('50')))
|
||||||
.toExist()
|
.toExist()
|
||||||
.withTimeout(5000);
|
.withTimeout(5000);
|
||||||
await element(by.id('room-view-messages')).atIndex(0).swipe('up', 'slow', 0.5);
|
await element(by.id('room-view-messages')).atIndex(0).swipe('up', 'slow', 0.5);
|
||||||
await waitFor(element(by.label('Load Newer')))
|
await waitFor(element(by[textMatcher]('Load Newer')))
|
||||||
.toExist()
|
.toExist()
|
||||||
.withTimeout(5000);
|
.withTimeout(5000);
|
||||||
await element(by.label('Load Newer')).atIndex(0).tap();
|
await element(by[textMatcher]('Load Newer')).atIndex(0).tap();
|
||||||
await waitFor(element(by.label('104')))
|
await waitFor(element(by[textMatcher]('104')))
|
||||||
.toExist()
|
.toExist()
|
||||||
.withTimeout(5000);
|
.withTimeout(5000);
|
||||||
await waitFor(element(by.label('Load Newer')))
|
await waitFor(element(by[textMatcher]('Load Newer')))
|
||||||
.toExist()
|
.toExist()
|
||||||
.withTimeout(5000);
|
.withTimeout(5000);
|
||||||
await element(by.label('Load Newer')).atIndex(0).tap();
|
await element(by[textMatcher]('Load Newer')).atIndex(0).tap();
|
||||||
await waitFor(element(by.label('154')))
|
await waitFor(element(by[textMatcher]('154')))
|
||||||
.toExist()
|
.toExist()
|
||||||
.withTimeout(5000);
|
.withTimeout(5000);
|
||||||
await waitFor(element(by.label('Load Newer')))
|
await waitFor(element(by[textMatcher]('Load Newer')))
|
||||||
.toExist()
|
.toExist()
|
||||||
.withTimeout(5000);
|
.withTimeout(5000);
|
||||||
await element(by.label('Load Newer')).atIndex(0).tap();
|
await element(by[textMatcher]('Load Newer')).atIndex(0).tap();
|
||||||
await waitFor(element(by.label('Load Newer')))
|
await waitFor(element(by[textMatcher]('Load Newer')))
|
||||||
.toNotExist()
|
.toNotExist()
|
||||||
.withTimeout(5000);
|
.withTimeout(5000);
|
||||||
await expect(element(by.label('Load More'))).toNotExist();
|
await expect(element(by[textMatcher]('Load More'))).toNotExist();
|
||||||
await expect(element(by.label('201'))).toExist();
|
await expect(element(by[textMatcher]('201'))).toExist();
|
||||||
await expect(element(by.label('202'))).toExist();
|
await expect(element(by[textMatcher]('202'))).toExist();
|
||||||
await tapBack();
|
await tapBack();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
const expectThreadMessages = async message => {
|
const expectThreadMessages = async message => {
|
||||||
await waitFor(element(by.id('room-view-title-jumping-thread')))
|
await waitFor(element(by.id('room-view-title-thread 1')))
|
||||||
.toExist()
|
.toExist()
|
||||||
.withTimeout(5000);
|
.withTimeout(5000);
|
||||||
await expect(element(by.label(message))).toExist();
|
await waitForLoading();
|
||||||
|
await expect(element(by[textMatcher](message)).atIndex(0)).toExist();
|
||||||
|
await element(by[textMatcher](message)).atIndex(0).tap();
|
||||||
};
|
};
|
||||||
|
|
||||||
describe('Threads', () => {
|
describe('Threads', () => {
|
||||||
|
before(async () => {
|
||||||
|
await device.launchApp({ permissions: { notifications: 'YES' }, newInstance: true });
|
||||||
|
});
|
||||||
|
|
||||||
it('should navigate to a thread from another room', async () => {
|
it('should navigate to a thread from another room', async () => {
|
||||||
await navigateToRoom('jumping');
|
await navigateToRoom('jumping');
|
||||||
await waitFor(element(by.label("Go to jumping-thread's thread")).atIndex(0))
|
await waitFor(element(by[textMatcher]("Go to jumping-thread's thread")).atIndex(0))
|
||||||
.toExist()
|
.toExist()
|
||||||
.withTimeout(5000);
|
.withTimeout(5000);
|
||||||
await element(by.label("Go to jumping-thread's thread")).atIndex(0).tap();
|
await element(by[textMatcher]("Go to jumping-thread's thread")).atIndex(0).tap();
|
||||||
await waitForLoading();
|
|
||||||
await expectThreadMessages("Go to jumping-thread's thread");
|
await expectThreadMessages("Go to jumping-thread's thread");
|
||||||
await tapBack();
|
await tapBack();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should tap on thread message from main room', async () => {
|
it('should tap on thread message from main room', async () => {
|
||||||
await waitFor(element(by.label('thread message sent to main room')).atIndex(0))
|
await waitFor(element(by.id('room-view-title-jumping-thread')))
|
||||||
.toExist()
|
.toExist()
|
||||||
.withTimeout(5000);
|
.withTimeout(5000);
|
||||||
await element(by.label('thread message sent to main room')).atIndex(0).tap();
|
await waitFor(element(by[textMatcher]('thread message sent to main room')))
|
||||||
|
.toExist()
|
||||||
|
.withTimeout(10000);
|
||||||
|
await element(by[textMatcher]('thread message sent to main room')).atIndex(0).tap();
|
||||||
await expectThreadMessages('thread message sent to main room');
|
await expectThreadMessages('thread message sent to main room');
|
||||||
await tapBack();
|
await tapBack();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should tap on quote', async () => {
|
it('should tap on quote', async () => {
|
||||||
await waitFor(element(by.label('quoted')))
|
await waitFor(element(by.id('room-view-title-jumping-thread')))
|
||||||
.toExist()
|
.toExist()
|
||||||
.withTimeout(5000);
|
.withTimeout(5000);
|
||||||
await element(by.label('quoted')).atIndex(0).tap();
|
await waitFor(element(by[textMatcher]('quoted')))
|
||||||
|
.toExist()
|
||||||
|
.withTimeout(5000);
|
||||||
|
await element(by[textMatcher]('quoted')).atIndex(0).tap();
|
||||||
await expectThreadMessages('quoted');
|
await expectThreadMessages('quoted');
|
||||||
await tapBack();
|
await tapBack();
|
||||||
});
|
});
|
||||||
|
@ -214,11 +249,11 @@ describe('Threads', () => {
|
||||||
await waitFor(element(by.id('search-messages-view')))
|
await waitFor(element(by.id('search-messages-view')))
|
||||||
.toExist()
|
.toExist()
|
||||||
.withTimeout(5000);
|
.withTimeout(5000);
|
||||||
await element(by.id('search-message-view-input')).typeText('to be searched\n');
|
await element(by.id('search-message-view-input')).replaceText('to be searched');
|
||||||
await waitFor(element(by.label('to be searched')))
|
await waitFor(element(by[textMatcher]('to be searched')).atIndex(1))
|
||||||
.toExist()
|
.toExist()
|
||||||
.withTimeout(5000);
|
.withTimeout(30000);
|
||||||
await element(by.label('to be searched')).atIndex(1).tap();
|
await element(by[textMatcher]('to be searched')).atIndex(1).tap();
|
||||||
await expectThreadMessages('to be searched');
|
await expectThreadMessages('to be searched');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -1,11 +1,14 @@
|
||||||
const data = require('../../data');
|
const data = require('../../data');
|
||||||
const { navigateToLogin, login } = require('../../helpers/app');
|
const { navigateToLogin, login, platformTypes } = require('../../helpers/app');
|
||||||
|
|
||||||
const teamName = `team-${data.random}`;
|
const teamName = `team-${data.random}`;
|
||||||
|
|
||||||
describe('Create team screen', () => {
|
describe('Create team screen', () => {
|
||||||
|
let alertButtonType;
|
||||||
|
let textMatcher;
|
||||||
before(async () => {
|
before(async () => {
|
||||||
await device.launchApp({ permissions: { notifications: 'YES' }, delete: true });
|
await device.launchApp({ permissions: { notifications: 'YES' }, delete: true });
|
||||||
|
({ alertButtonType, textMatcher } = platformTypes[device.getPlatform()]);
|
||||||
await navigateToLogin();
|
await navigateToLogin();
|
||||||
await login(data.users.regular.username, data.users.regular.password);
|
await login(data.users.regular.username, data.users.regular.password);
|
||||||
});
|
});
|
||||||
|
@ -41,17 +44,23 @@ describe('Create team screen', () => {
|
||||||
describe('Create Team', () => {
|
describe('Create Team', () => {
|
||||||
describe('Usage', () => {
|
describe('Usage', () => {
|
||||||
it('should get invalid team name', async () => {
|
it('should get invalid team name', async () => {
|
||||||
await element(by.id('create-channel-name')).typeText(`${data.teams.private.name}`);
|
await element(by.id('create-channel-name')).replaceText(`${data.teams.private.name}`);
|
||||||
|
await waitFor(element(by.id('create-channel-submit')))
|
||||||
|
.toExist()
|
||||||
|
.withTimeout(2000);
|
||||||
await element(by.id('create-channel-submit')).tap();
|
await element(by.id('create-channel-submit')).tap();
|
||||||
await waitFor(element(by.text('OK')))
|
await waitFor(element(by[textMatcher]('OK').and(by.type(alertButtonType))))
|
||||||
.toBeVisible()
|
.toBeVisible()
|
||||||
.withTimeout(5000);
|
.withTimeout(5000);
|
||||||
await element(by.text('OK')).tap();
|
await element(by[textMatcher]('OK').and(by.type(alertButtonType))).tap();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should create private team', async () => {
|
it('should create private team', async () => {
|
||||||
await element(by.id('create-channel-name')).replaceText('');
|
await element(by.id('create-channel-name')).replaceText('');
|
||||||
await element(by.id('create-channel-name')).typeText(teamName);
|
await element(by.id('create-channel-name')).replaceText(teamName);
|
||||||
|
await waitFor(element(by.id('create-channel-submit')))
|
||||||
|
.toExist()
|
||||||
|
.withTimeout(2000);
|
||||||
await element(by.id('create-channel-submit')).tap();
|
await element(by.id('create-channel-submit')).tap();
|
||||||
await waitFor(element(by.id('room-view')))
|
await waitFor(element(by.id('room-view')))
|
||||||
.toExist()
|
.toExist()
|
||||||
|
@ -81,10 +90,10 @@ describe('Create team screen', () => {
|
||||||
await element(by.id('room-info-view-edit-button')).tap();
|
await element(by.id('room-info-view-edit-button')).tap();
|
||||||
await element(by.id('room-info-edit-view-list')).swipe('up', 'fast', 0.5);
|
await element(by.id('room-info-edit-view-list')).swipe('up', 'fast', 0.5);
|
||||||
await element(by.id('room-info-edit-view-delete')).tap();
|
await element(by.id('room-info-edit-view-delete')).tap();
|
||||||
await waitFor(element(by.text('Yes, delete it!')))
|
await waitFor(element(by[textMatcher]('Yes, delete it!')))
|
||||||
.toExist()
|
.toExist()
|
||||||
.withTimeout(5000);
|
.withTimeout(5000);
|
||||||
await element(by.text('Yes, delete it!')).tap();
|
await element(by[textMatcher]('Yes, delete it!').and(by.type(alertButtonType))).tap();
|
||||||
await waitFor(element(by.id('rooms-list-view')))
|
await waitFor(element(by.id('rooms-list-view')))
|
||||||
.toExist()
|
.toExist()
|
||||||
.withTimeout(10000);
|
.withTimeout(10000);
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
const data = require('../../data');
|
const data = require('../../data');
|
||||||
const { navigateToLogin, login, tapBack, sleep, searchRoom } = require('../../helpers/app');
|
const { navigateToLogin, login, tapBack, sleep, searchRoom, platformTypes } = require('../../helpers/app');
|
||||||
|
|
||||||
async function navigateToRoom(roomName) {
|
async function navigateToRoom(roomName) {
|
||||||
await searchRoom(`${roomName}`);
|
await searchRoom(`${roomName}`);
|
||||||
|
@ -17,6 +17,7 @@ async function openActionSheet(username) {
|
||||||
await sleep(300);
|
await sleep(300);
|
||||||
await expect(element(by.id('action-sheet'))).toExist();
|
await expect(element(by.id('action-sheet'))).toExist();
|
||||||
await expect(element(by.id('action-sheet-handle'))).toBeVisible();
|
await expect(element(by.id('action-sheet-handle'))).toBeVisible();
|
||||||
|
await element(by.id('action-sheet-handle')).swipe('up');
|
||||||
}
|
}
|
||||||
|
|
||||||
async function navigateToRoomActions() {
|
async function navigateToRoomActions() {
|
||||||
|
@ -37,20 +38,41 @@ async function backToActions() {
|
||||||
}
|
}
|
||||||
async function closeActionSheet() {
|
async function closeActionSheet() {
|
||||||
await element(by.id('action-sheet-handle')).swipe('down', 'fast', 0.6);
|
await element(by.id('action-sheet-handle')).swipe('down', 'fast', 0.6);
|
||||||
|
await waitFor(element(by.id('action-sheet-handle')))
|
||||||
|
.toBeNotVisible()
|
||||||
|
.withTimeout(3000);
|
||||||
|
await sleep(200);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function waitForToast() {
|
async function waitForToast() {
|
||||||
await sleep(1000);
|
await sleep(1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function swipeTillVisible(container, find, direction = 'up', delta = 0.3, speed = 'slow') {
|
||||||
|
let found = false;
|
||||||
|
while (!found) {
|
||||||
|
try {
|
||||||
|
await element(container).swipe(direction, speed, delta);
|
||||||
|
await sleep(200);
|
||||||
|
await expect(element(find)).toBeVisible();
|
||||||
|
found = true;
|
||||||
|
} catch (e) {
|
||||||
|
//
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
describe('Team', () => {
|
describe('Team', () => {
|
||||||
const team = data.teams.private.name;
|
const team = data.teams.private.name;
|
||||||
const user = data.users.alternate;
|
const user = data.users.alternate;
|
||||||
const room = `private${data.random}-channel-team`;
|
const room = `private${data.random}-channel-team`;
|
||||||
const existingRoom = data.groups.alternate.name;
|
const existingRoom = data.groups.alternate.name;
|
||||||
|
let alertButtonType;
|
||||||
|
let textMatcher;
|
||||||
|
|
||||||
before(async () => {
|
before(async () => {
|
||||||
await device.launchApp({ permissions: { notifications: 'YES' }, delete: true });
|
await device.launchApp({ permissions: { notifications: 'YES' }, delete: true });
|
||||||
|
({ alertButtonType, textMatcher } = platformTypes[device.getPlatform()]);
|
||||||
await navigateToLogin();
|
await navigateToLogin();
|
||||||
await login(data.users.regular.username, data.users.regular.password);
|
await login(data.users.regular.username, data.users.regular.password);
|
||||||
await navigateToRoom(team);
|
await navigateToRoom(team);
|
||||||
|
@ -86,7 +108,7 @@ describe('Team', () => {
|
||||||
|
|
||||||
describe('Team Channels Header', () => {
|
describe('Team Channels Header', () => {
|
||||||
it('should have actions button ', async () => {
|
it('should have actions button ', async () => {
|
||||||
await expect(element(by.id('room-header'))).toExist();
|
await expect(element(by.id('room-header')).atIndex(0)).toExist();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should have team channels button ', async () => {
|
it('should have team channels button ', async () => {
|
||||||
|
@ -124,6 +146,9 @@ describe('Team', () => {
|
||||||
await element(by.id('add-channel-team-view-create-channel')).tap();
|
await element(by.id('add-channel-team-view-create-channel')).tap();
|
||||||
|
|
||||||
await element(by.id('select-users-view-search')).replaceText('rocket.cat');
|
await element(by.id('select-users-view-search')).replaceText('rocket.cat');
|
||||||
|
await waitFor(element(by.id('select-users-view-item-rocket.cat')))
|
||||||
|
.toBeVisible()
|
||||||
|
.withTimeout(5000);
|
||||||
await element(by.id('select-users-view-item-rocket.cat')).tap();
|
await element(by.id('select-users-view-item-rocket.cat')).tap();
|
||||||
await waitFor(element(by.id('selected-user-rocket.cat')))
|
await waitFor(element(by.id('selected-user-rocket.cat')))
|
||||||
.toBeVisible()
|
.toBeVisible()
|
||||||
|
@ -134,7 +159,10 @@ describe('Team', () => {
|
||||||
.toExist()
|
.toExist()
|
||||||
.withTimeout(10000);
|
.withTimeout(10000);
|
||||||
await element(by.id('create-channel-name')).replaceText('');
|
await element(by.id('create-channel-name')).replaceText('');
|
||||||
await element(by.id('create-channel-name')).typeText(room);
|
await element(by.id('create-channel-name')).replaceText(room);
|
||||||
|
await waitFor(element(by.id('create-channel-submit')))
|
||||||
|
.toExist()
|
||||||
|
.withTimeout(10000);
|
||||||
await element(by.id('create-channel-submit')).tap();
|
await element(by.id('create-channel-submit')).tap();
|
||||||
|
|
||||||
await waitFor(element(by.id('room-view')))
|
await waitFor(element(by.id('room-view')))
|
||||||
|
@ -156,9 +184,9 @@ describe('Team', () => {
|
||||||
.toExist()
|
.toExist()
|
||||||
.withTimeout(60000);
|
.withTimeout(60000);
|
||||||
await expect(element(by.id(`room-view-title-${room}`))).toExist();
|
await expect(element(by.id(`room-view-title-${room}`))).toExist();
|
||||||
await expect(element(by.id('room-view-header-team-channels'))).toExist();
|
await expect(element(by.id('room-view-header-team-channels')).atIndex(0)).toExist();
|
||||||
await expect(element(by.id('room-view-header-threads'))).toExist();
|
await expect(element(by.id('room-view-header-threads')).atIndex(0)).toExist();
|
||||||
await expect(element(by.id('room-view-search'))).toExist();
|
await expect(element(by.id('room-view-search')).atIndex(0)).toExist();
|
||||||
await tapBack();
|
await tapBack();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -186,7 +214,7 @@ describe('Team', () => {
|
||||||
await expect(element(by.id('room-view-header-team-channels'))).toExist();
|
await expect(element(by.id('room-view-header-team-channels'))).toExist();
|
||||||
await element(by.id('room-view-header-team-channels')).tap();
|
await element(by.id('room-view-header-team-channels')).tap();
|
||||||
|
|
||||||
await waitFor(element(by.id(`rooms-list-view-item-${existingRoom}`)))
|
await waitFor(element(by.id(`rooms-list-view-item-${existingRoom}`)).atIndex(0))
|
||||||
.toExist()
|
.toExist()
|
||||||
.withTimeout(10000);
|
.withTimeout(10000);
|
||||||
});
|
});
|
||||||
|
@ -195,7 +223,8 @@ describe('Team', () => {
|
||||||
await element(by.id(`rooms-list-view-item-${existingRoom}`))
|
await element(by.id(`rooms-list-view-item-${existingRoom}`))
|
||||||
.atIndex(0)
|
.atIndex(0)
|
||||||
.longPress();
|
.longPress();
|
||||||
|
await sleep(500);
|
||||||
|
await swipeTillVisible(by.id('action-sheet-remove-from-team'), by.id('action-sheet-delete'));
|
||||||
await waitFor(element(by.id('action-sheet-auto-join')))
|
await waitFor(element(by.id('action-sheet-auto-join')))
|
||||||
.toBeVisible()
|
.toBeVisible()
|
||||||
.withTimeout(5000);
|
.withTimeout(5000);
|
||||||
|
@ -224,7 +253,7 @@ describe('Team', () => {
|
||||||
await waitFor(element(by.id('auto-join-tag')))
|
await waitFor(element(by.id('auto-join-tag')))
|
||||||
.toBeNotVisible()
|
.toBeNotVisible()
|
||||||
.withTimeout(5000);
|
.withTimeout(5000);
|
||||||
await waitFor(element(by.id(`rooms-list-view-item-${existingRoom}`)))
|
await waitFor(element(by.id(`rooms-list-view-item-${existingRoom}`)).atIndex(0))
|
||||||
.toExist()
|
.toExist()
|
||||||
.withTimeout(6000);
|
.withTimeout(6000);
|
||||||
});
|
});
|
||||||
|
@ -298,22 +327,22 @@ describe('Team', () => {
|
||||||
|
|
||||||
await waitFor(
|
await waitFor(
|
||||||
element(
|
element(
|
||||||
by.label(
|
by[textMatcher](
|
||||||
'You are the last owner of this channel. Once you leave the team, the channel will be kept inside the team but you will be managing it from outside.'
|
'You are the last owner of this channel. Once you leave the team, the channel will be kept inside the team but you will be managing it from outside.'
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
.toExist()
|
.toExist()
|
||||||
.withTimeout(2000);
|
.withTimeout(2000);
|
||||||
await element(by.text('OK')).tap();
|
await element(by[textMatcher]('OK').and(by.type(alertButtonType))).tap();
|
||||||
await waitFor(element(by.id('select-list-view-submit')))
|
await waitFor(element(by.id('select-list-view-submit')))
|
||||||
.toExist()
|
.toExist()
|
||||||
.withTimeout(2000);
|
.withTimeout(2000);
|
||||||
await element(by.id('select-list-view-submit')).tap();
|
await element(by.id('select-list-view-submit')).tap();
|
||||||
await waitFor(element(by.text('Last owner cannot be removed')))
|
await waitFor(element(by[textMatcher]('Last owner cannot be removed')))
|
||||||
.toExist()
|
.toExist()
|
||||||
.withTimeout(8000);
|
.withTimeout(8000);
|
||||||
await element(by.text('OK')).tap();
|
await element(by[textMatcher]('OK').and(by.type(alertButtonType))).tap();
|
||||||
await tapBack();
|
await tapBack();
|
||||||
await waitFor(element(by.id('room-actions-view')))
|
await waitFor(element(by.id('room-actions-view')))
|
||||||
.toExist()
|
.toExist()
|
||||||
|
@ -352,6 +381,9 @@ describe('Team', () => {
|
||||||
|
|
||||||
it('should remove member from team', async () => {
|
it('should remove member from team', async () => {
|
||||||
await openActionSheet('rocket.cat');
|
await openActionSheet('rocket.cat');
|
||||||
|
await waitFor(element(by.id('action-sheet-remove-from-team')))
|
||||||
|
.toBeVisible()
|
||||||
|
.withTimeout(2000);
|
||||||
await element(by.id('action-sheet-remove-from-team')).tap();
|
await element(by.id('action-sheet-remove-from-team')).tap();
|
||||||
await waitFor(element(by.id('select-list-view')))
|
await waitFor(element(by.id('select-list-view')))
|
||||||
.toExist()
|
.toExist()
|
||||||
|
@ -406,14 +438,14 @@ describe('Team', () => {
|
||||||
|
|
||||||
await waitFor(
|
await waitFor(
|
||||||
element(
|
element(
|
||||||
by.label(
|
by[textMatcher](
|
||||||
'You are the last owner of this channel. Once you leave the team, the channel will be kept inside the team but you will be managing it from outside.'
|
'You are the last owner of this channel. Once you leave the team, the channel will be kept inside the team but you will be managing it from outside.'
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
.toExist()
|
.toExist()
|
||||||
.withTimeout(2000);
|
.withTimeout(2000);
|
||||||
await element(by.text('OK')).tap();
|
await element(by[textMatcher]('OK').and(by.type(alertButtonType))).tap();
|
||||||
await waitFor(element(by.id('select-list-view-submit')))
|
await waitFor(element(by.id('select-list-view-submit')))
|
||||||
.toExist()
|
.toExist()
|
||||||
.withTimeout(2000);
|
.withTimeout(2000);
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
const data = require('../../data');
|
const data = require('../../data');
|
||||||
const { navigateToLogin, login, tapBack, searchRoom, sleep } = require('../../helpers/app');
|
const { navigateToLogin, login, tapBack, searchRoom, sleep, platformTypes } = require('../../helpers/app');
|
||||||
|
|
||||||
const toBeConverted = `to-be-converted-${data.random}`;
|
const toBeConverted = `to-be-converted-${data.random}`;
|
||||||
const toBeMoved = `to-be-moved-${data.random}`;
|
const toBeMoved = `to-be-moved-${data.random}`;
|
||||||
|
@ -17,7 +17,10 @@ const createChannel = async room => {
|
||||||
await waitFor(element(by.id('create-channel-view')))
|
await waitFor(element(by.id('create-channel-view')))
|
||||||
.toExist()
|
.toExist()
|
||||||
.withTimeout(10000);
|
.withTimeout(10000);
|
||||||
await element(by.id('create-channel-name')).typeText(room);
|
await element(by.id('create-channel-name')).replaceText(room);
|
||||||
|
await waitFor(element(by.id('create-channel-submit')))
|
||||||
|
.toExist()
|
||||||
|
.withTimeout(10000);
|
||||||
await element(by.id('create-channel-submit')).tap();
|
await element(by.id('create-channel-submit')).tap();
|
||||||
await waitFor(element(by.id('room-view')))
|
await waitFor(element(by.id('room-view')))
|
||||||
.toExist()
|
.toExist()
|
||||||
|
@ -51,8 +54,11 @@ async function navigateToRoomActions(room) {
|
||||||
}
|
}
|
||||||
|
|
||||||
describe('Move/Convert Team', () => {
|
describe('Move/Convert Team', () => {
|
||||||
|
let alertButtonType;
|
||||||
|
let textMatcher;
|
||||||
before(async () => {
|
before(async () => {
|
||||||
await device.launchApp({ permissions: { notifications: 'YES' }, delete: true });
|
await device.launchApp({ permissions: { notifications: 'YES' }, delete: true });
|
||||||
|
({ alertButtonType, textMatcher } = platformTypes[device.getPlatform()]);
|
||||||
await navigateToLogin();
|
await navigateToLogin();
|
||||||
await login(data.users.regular.username, data.users.regular.password);
|
await login(data.users.regular.username, data.users.regular.password);
|
||||||
});
|
});
|
||||||
|
@ -69,10 +75,10 @@ describe('Move/Convert Team', () => {
|
||||||
.toExist()
|
.toExist()
|
||||||
.withTimeout(2000);
|
.withTimeout(2000);
|
||||||
await element(by.id('room-actions-convert-to-team')).tap();
|
await element(by.id('room-actions-convert-to-team')).tap();
|
||||||
await waitFor(element(by.label('You are converting this Channel to a Team. All Members will be kept.')))
|
await waitFor(element(by[textMatcher]('You are converting this Channel to a Team. All Members will be kept.')))
|
||||||
.toExist()
|
.toExist()
|
||||||
.withTimeout(2000);
|
.withTimeout(2000);
|
||||||
await element(by.text('Convert')).tap();
|
await element(by[textMatcher]('Convert').and(by.type(alertButtonType))).tap();
|
||||||
await waitFor(element(by.id('room-view')))
|
await waitFor(element(by.id('room-view')))
|
||||||
.toExist()
|
.toExist()
|
||||||
.withTimeout(20000);
|
.withTimeout(20000);
|
||||||
|
@ -101,12 +107,14 @@ describe('Move/Convert Team', () => {
|
||||||
.toExist()
|
.toExist()
|
||||||
.withTimeout(2000);
|
.withTimeout(2000);
|
||||||
await element(by.id('room-actions-move-to-team')).tap();
|
await element(by.id('room-actions-move-to-team')).tap();
|
||||||
await waitFor(element(by.id('select-list-view')))
|
await waitFor(element(by[textMatcher]('Move to Team')).atIndex(0))
|
||||||
|
.toExist()
|
||||||
|
.withTimeout(2000);
|
||||||
|
await waitFor(element(by.id('select-list-view-submit')))
|
||||||
.toExist()
|
.toExist()
|
||||||
.withTimeout(2000);
|
.withTimeout(2000);
|
||||||
await element(by.id('select-list-view-submit')).tap();
|
await element(by.id('select-list-view-submit')).tap();
|
||||||
await sleep(2000);
|
await waitFor(element(by[textMatcher]('Select Team')))
|
||||||
await waitFor(element(by.id('select-list-view')))
|
|
||||||
.toExist()
|
.toExist()
|
||||||
.withTimeout(2000);
|
.withTimeout(2000);
|
||||||
await waitFor(element(by.id(`select-list-view-item-${toBeConverted}`)))
|
await waitFor(element(by.id(`select-list-view-item-${toBeConverted}`)))
|
||||||
|
@ -116,14 +124,14 @@ describe('Move/Convert Team', () => {
|
||||||
await element(by.id('select-list-view-submit')).atIndex(0).tap();
|
await element(by.id('select-list-view-submit')).atIndex(0).tap();
|
||||||
await waitFor(
|
await waitFor(
|
||||||
element(
|
element(
|
||||||
by.label(
|
by[textMatcher](
|
||||||
'After reading the previous intructions about this behavior, do you still want to move this channel to the selected team?'
|
'After reading the previous intructions about this behavior, do you still want to move this channel to the selected team?'
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
.toExist()
|
.toExist()
|
||||||
.withTimeout(2000);
|
.withTimeout(2000);
|
||||||
await element(by.text('Yes, move it!')).tap();
|
await element(by[textMatcher]('Yes, move it!').and(by.type(alertButtonType))).tap();
|
||||||
await waitFor(element(by.id('room-view-header-team-channels')))
|
await waitFor(element(by.id('room-view-header-team-channels')))
|
||||||
.toExist()
|
.toExist()
|
||||||
.withTimeout(10000);
|
.withTimeout(10000);
|
||||||
|
@ -141,12 +149,11 @@ describe('Move/Convert Team', () => {
|
||||||
it('should convert a team to a channel', async () => {
|
it('should convert a team to a channel', async () => {
|
||||||
await navigateToRoomActions(toBeConverted);
|
await navigateToRoomActions(toBeConverted);
|
||||||
await element(by.id('room-actions-scrollview')).scrollTo('bottom');
|
await element(by.id('room-actions-scrollview')).scrollTo('bottom');
|
||||||
await waitFor(element(by.id('room-actions-convert-channel-to-team')))
|
await waitFor(element(by[textMatcher]('Convert to Channel')))
|
||||||
.toExist()
|
.toExist()
|
||||||
.withTimeout(2000);
|
.withTimeout(2000);
|
||||||
await element(by.id('room-actions-convert-channel-to-team')).tap();
|
await element(by[textMatcher]('Convert to Channel')).atIndex(0).tap();
|
||||||
await sleep(2000);
|
await waitFor(element(by[textMatcher]('Converting Team to Channel')))
|
||||||
await waitFor(element(by.id('select-list-view')))
|
|
||||||
.toExist()
|
.toExist()
|
||||||
.withTimeout(2000);
|
.withTimeout(2000);
|
||||||
await waitFor(element(by.id(`select-list-view-item-${toBeMoved}`)))
|
await waitFor(element(by.id(`select-list-view-item-${toBeMoved}`)))
|
||||||
|
@ -157,10 +164,10 @@ describe('Move/Convert Team', () => {
|
||||||
.toExist()
|
.toExist()
|
||||||
.withTimeout(2000);
|
.withTimeout(2000);
|
||||||
await element(by.id('select-list-view-submit')).tap();
|
await element(by.id('select-list-view-submit')).tap();
|
||||||
await waitFor(element(by.label('You are converting this Team to a Channel')))
|
await waitFor(element(by[textMatcher]('You are converting this Team to a Channel')))
|
||||||
.toExist()
|
.toExist()
|
||||||
.withTimeout(2000);
|
.withTimeout(2000);
|
||||||
await element(by.text('Convert')).tap();
|
await element(by[textMatcher]('Convert').and(by.type(alertButtonType))).tap();
|
||||||
await waitFor(element(by.id('room-view')))
|
await waitFor(element(by.id('room-view')))
|
||||||
.toExist()
|
.toExist()
|
||||||
.withTimeout(20000);
|
.withTimeout(20000);
|
||||||
|
|
12
package.json
12
package.json
|
@ -239,6 +239,18 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"and.emu.debug": {
|
||||||
|
"device": "Pixel_API_28_AOSP",
|
||||||
|
"type": "android.emulator",
|
||||||
|
"binaryPath": "android/app/build/outputs/apk/e2ePlay/debug/app-e2e-play-debug.apk",
|
||||||
|
"build": "cd android && ./gradlew app:assembleE2ePlayDebug app:assembleE2ePlayDebugAndroidTest -DtestBuildType=debug && cd .."
|
||||||
|
},
|
||||||
|
"and.emu.release": {
|
||||||
|
"device": "Pixel_API_28_AOSP",
|
||||||
|
"type": "android.emulator",
|
||||||
|
"binaryPath": "android/app/build/outputs/apk/e2ePlay/release/app-e2e-play-release.apk",
|
||||||
|
"build": "cd android && ./gradlew app:assembleE2ePlayRelease app:assembleE2ePlayReleaseAndroidTest -DtestBuildType=release && cd .."
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue