Detox tests E2E (#283)
This commit is contained in:
parent
a9acbec05c
commit
182ab69d6f
|
@ -35,6 +35,52 @@ jobs:
|
|||
command: |
|
||||
npx codecov
|
||||
|
||||
e2e-test:
|
||||
macos:
|
||||
xcode: "9.0"
|
||||
|
||||
environment:
|
||||
BASH_ENV: "~/.nvm/nvm.sh"
|
||||
|
||||
steps:
|
||||
- checkout
|
||||
|
||||
- run:
|
||||
name: Install Node 8
|
||||
command: |
|
||||
curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.33.6/install.sh | bash
|
||||
source ~/.nvm/nvm.sh
|
||||
# https://github.com/creationix/nvm/issues/1394
|
||||
set +e
|
||||
nvm install 8
|
||||
|
||||
- run:
|
||||
name: Install appleSimUtils
|
||||
command: |
|
||||
brew update
|
||||
brew tap wix/brew
|
||||
brew install applesimutils
|
||||
|
||||
- run:
|
||||
name: Install NPM modules
|
||||
command: |
|
||||
rm -rf node_modules
|
||||
npm install
|
||||
npm install -g detox-cli
|
||||
|
||||
- run:
|
||||
name: Build
|
||||
command: |
|
||||
detox build
|
||||
|
||||
- run:
|
||||
name: Test
|
||||
command: |
|
||||
detox test
|
||||
|
||||
- store_artifacts:
|
||||
path: /tmp/screenshots
|
||||
|
||||
android-build:
|
||||
<<: *defaults
|
||||
docker:
|
||||
|
@ -215,10 +261,14 @@ workflows:
|
|||
build-and-test:
|
||||
jobs:
|
||||
- lint-testunit
|
||||
- e2e-test:
|
||||
requires:
|
||||
- lint-testunit
|
||||
|
||||
- ios-build:
|
||||
requires:
|
||||
- lint-testunit
|
||||
- e2e-test
|
||||
- ios-testflight:
|
||||
requires:
|
||||
- ios-build
|
||||
|
@ -235,3 +285,4 @@ workflows:
|
|||
- android-build:
|
||||
requires:
|
||||
- lint-testunit
|
||||
- e2e-test
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
__tests__
|
||||
node_modules
|
||||
coverage
|
||||
e2e
|
||||
|
|
13
README.md
13
README.md
|
@ -38,6 +38,19 @@ Follow the [React Native Getting Started Guide](https://facebook.github.io/react
|
|||
$ npm run android
|
||||
```
|
||||
|
||||
# Detox (end-to-end tests)
|
||||
- Build your app
|
||||
|
||||
```bash
|
||||
$ detox build
|
||||
```
|
||||
|
||||
- Run tests
|
||||
|
||||
```bash
|
||||
$ detox test
|
||||
```
|
||||
|
||||
# Storybook
|
||||
- General requirements
|
||||
- Install storybook
|
||||
|
|
|
@ -12,5 +12,6 @@ if (__DEV__) {
|
|||
.connect();
|
||||
// Running on android device
|
||||
// $ adb reverse tcp:9090 tcp:9090
|
||||
console.warn = Reactotron.log;
|
||||
// Reactotron.clear();
|
||||
// console.warn = Reactotron.log;
|
||||
}
|
||||
|
|
|
@ -60,7 +60,7 @@ export default class Button extends React.PureComponent {
|
|||
|
||||
render() {
|
||||
const {
|
||||
title, type, onPress, disabled
|
||||
title, type, onPress, disabled, ...otherProps
|
||||
} = this.props;
|
||||
return (
|
||||
<Touch
|
||||
|
@ -68,6 +68,7 @@ export default class Button extends React.PureComponent {
|
|||
accessibilityTraits='button'
|
||||
style={Platform.OS === 'ios' && styles.margin}
|
||||
disabled={disabled}
|
||||
{...otherProps}
|
||||
>
|
||||
<View
|
||||
style={[
|
||||
|
|
|
@ -24,7 +24,11 @@ export default class CloseModalButton extends React.PureComponent {
|
|||
|
||||
render() {
|
||||
return (
|
||||
<TouchableOpacity onPress={() => this.props.navigation.dispatch(NavigationActions.back())} style={styles.button}>
|
||||
<TouchableOpacity
|
||||
onPress={() => this.props.navigation.dispatch(NavigationActions.back())}
|
||||
style={styles.button}
|
||||
testID='close-modal-button'
|
||||
>
|
||||
<Icon
|
||||
style={styles.icon}
|
||||
name='close'
|
||||
|
|
|
@ -49,6 +49,7 @@ export default class EmojiCategory extends React.Component {
|
|||
activeOpacity={0.7}
|
||||
key={emoji.isCustom ? emoji.content : emoji}
|
||||
onPress={() => this.props.onEmojiSelected(emoji)}
|
||||
testID={`reaction-picker-${ emoji.isCustom ? emoji.content : emoji }`}
|
||||
>
|
||||
{renderEmoji(emoji, size)}
|
||||
</TouchableOpacity>);
|
||||
|
|
|
@ -20,6 +20,7 @@ export default class TabBar extends React.PureComponent {
|
|||
key={tab}
|
||||
onPress={() => this.props.goToPage(i)}
|
||||
style={styles.tab}
|
||||
testID={`reaction-picker-${ tab }`}
|
||||
>
|
||||
<Text style={[styles.tabEmoji, this.props.tabEmojiStyle]}>{tab}</Text>
|
||||
{this.props.activeTab === i ? <View style={styles.activeTabLine} /> : <View style={styles.tabLine} />}
|
||||
|
|
|
@ -337,6 +337,7 @@ export default class MessageActions extends React.Component {
|
|||
<ActionSheet
|
||||
ref={o => this.ActionSheet = o}
|
||||
title='Messages actions'
|
||||
testID='message-actions'
|
||||
options={this.options}
|
||||
cancelButtonIndex={this.CANCEL_INDEX}
|
||||
destructiveButtonIndex={this.DELETE_INDEX}
|
||||
|
|
|
@ -13,7 +13,7 @@ export default class EmojiKeyboard extends React.PureComponent {
|
|||
render() {
|
||||
return (
|
||||
<Provider store={store}>
|
||||
<View style={styles.emojiKeyboardContainer}>
|
||||
<View style={styles.emojiKeyboardContainer} testID='messagebox-keyboard-emoji'>
|
||||
<EmojiPicker onEmojiSelected={emoji => this.onEmojiSelected(emoji)} />
|
||||
</View>
|
||||
</Provider>
|
||||
|
|
|
@ -100,7 +100,8 @@ export default class extends React.PureComponent {
|
|||
render() {
|
||||
return (
|
||||
<SafeAreaView
|
||||
key='messagebox'
|
||||
key='messagebox-recording'
|
||||
testID='messagebox-recording'
|
||||
style={styles.textBox}
|
||||
>
|
||||
<View style={[styles.textArea, { backgroundColor: '#F6F7F9' }]}>
|
||||
|
|
|
@ -88,7 +88,6 @@ export default class MessageBox extends React.PureComponent {
|
|||
const regexp = /(#|@|:)([a-z0-9._-]+)$/im;
|
||||
|
||||
const result = lastNativeText.substr(0, cursor).match(regexp);
|
||||
|
||||
if (!result) {
|
||||
return this.stopTrackingMention();
|
||||
}
|
||||
|
@ -111,6 +110,7 @@ export default class MessageBox extends React.PureComponent {
|
|||
accessibilityLabel='Cancel editing'
|
||||
accessibilityTraits='button'
|
||||
onPress={() => this.editCancel()}
|
||||
testID='messagebox-cancel-editing'
|
||||
/>);
|
||||
}
|
||||
return !this.state.showEmojiKeyboard ? (<Icon
|
||||
|
@ -119,12 +119,14 @@ export default class MessageBox extends React.PureComponent {
|
|||
accessibilityLabel='Open emoji selector'
|
||||
accessibilityTraits='button'
|
||||
name='mood'
|
||||
testID='messagebox-open-emoji'
|
||||
/>) : (<Icon
|
||||
onPress={() => this.closeEmoji()}
|
||||
style={styles.actionButtons}
|
||||
accessibilityLabel='Close emoji selector'
|
||||
accessibilityTraits='button'
|
||||
name='keyboard'
|
||||
testID='messagebox-close-emoji'
|
||||
/>);
|
||||
}
|
||||
get rightButtons() {
|
||||
|
@ -138,6 +140,7 @@ export default class MessageBox extends React.PureComponent {
|
|||
accessibilityLabel='Send message'
|
||||
accessibilityTraits='button'
|
||||
onPress={() => this.submit(this.state.text)}
|
||||
testID='messagebox-send-message'
|
||||
/>);
|
||||
return icons;
|
||||
}
|
||||
|
@ -148,6 +151,7 @@ export default class MessageBox extends React.PureComponent {
|
|||
accessibilityLabel='Send audio message'
|
||||
accessibilityTraits='button'
|
||||
onPress={() => this.recordAudioMessage()}
|
||||
testID='messagebox-send-audio'
|
||||
/>);
|
||||
icons.push(<MyIcon
|
||||
style={[styles.actionButtons, { color: '#2F343D', fontSize: 16 }]}
|
||||
|
@ -156,6 +160,7 @@ export default class MessageBox extends React.PureComponent {
|
|||
accessibilityLabel='Message actions'
|
||||
accessibilityTraits='button'
|
||||
onPress={() => this.addFile()}
|
||||
testID='messagebox-actions'
|
||||
/>);
|
||||
return icons;
|
||||
}
|
||||
|
@ -438,6 +443,7 @@ export default class MessageBox extends React.PureComponent {
|
|||
<TouchableOpacity
|
||||
style={styles.mentionItem}
|
||||
onPress={() => this._onPressMention(item)}
|
||||
testID={`mention-item-${ this.state.trackingType === MENTIONS_TRACKING_TYPE_EMOJIS ? item.name || item : item.username || item.name }`}
|
||||
>
|
||||
{this.state.trackingType === MENTIONS_TRACKING_TYPE_EMOJIS ?
|
||||
[
|
||||
|
@ -463,14 +469,15 @@ export default class MessageBox extends React.PureComponent {
|
|||
return null;
|
||||
}
|
||||
return (
|
||||
<View key='messagebox-container' testID='messagebox-container'>
|
||||
<FlatList
|
||||
key='messagebox-container'
|
||||
style={styles.mentionList}
|
||||
data={mentions}
|
||||
renderItem={({ item }) => this.renderMentionItem(item)}
|
||||
keyExtractor={item => item._id || item}
|
||||
keyboardShouldPersistTaps='always'
|
||||
/>
|
||||
</View>
|
||||
);
|
||||
};
|
||||
|
||||
|
@ -481,7 +488,11 @@ export default class MessageBox extends React.PureComponent {
|
|||
return (
|
||||
[
|
||||
this.renderMentions(),
|
||||
<View key='messagebox' style={[styles.textArea, this.props.editing && styles.editing]}>
|
||||
<View
|
||||
key='messagebox'
|
||||
style={[styles.textArea, this.props.editing && styles.editing]}
|
||||
testID='messagebox'
|
||||
>
|
||||
{this.leftButtons}
|
||||
<TextInput
|
||||
ref={component => this.component = component}
|
||||
|
@ -496,6 +507,7 @@ export default class MessageBox extends React.PureComponent {
|
|||
defaultValue=''
|
||||
multiline
|
||||
placeholderTextColor='#9EA2A8'
|
||||
testID='messagebox-input'
|
||||
/>
|
||||
{this.rightButtons}
|
||||
</View>
|
||||
|
|
|
@ -67,7 +67,7 @@ export default class Sidebar extends Component {
|
|||
|
||||
onPressItem = (item) => {
|
||||
this.props.selectServer(item.id);
|
||||
this.props.navigation.dispatch(DrawerActions.closeDrawer());
|
||||
this.closeDrawer();
|
||||
}
|
||||
|
||||
getState = () => ({
|
||||
|
@ -78,12 +78,17 @@ export default class Sidebar extends Component {
|
|||
this.setState(this.getState());
|
||||
}
|
||||
|
||||
closeDrawer = () => {
|
||||
this.props.navigation.dispatch(DrawerActions.closeDrawer());
|
||||
}
|
||||
|
||||
renderItem = ({ item, separators }) => (
|
||||
|
||||
<TouchableHighlight
|
||||
onShowUnderlay={separators.highlight}
|
||||
onHideUnderlay={separators.unhighlight}
|
||||
onPress={() => { this.onPressItem(item); }}
|
||||
testID={`sidebar-${ item.id }`}
|
||||
>
|
||||
<View style={[styles.serverItem, (item.id === this.props.server ? styles.selectedServer : null)]}>
|
||||
<Text>
|
||||
|
@ -96,14 +101,18 @@ export default class Sidebar extends Component {
|
|||
render() {
|
||||
return (
|
||||
<ScrollView style={styles.scrollView}>
|
||||
<View style={{ paddingBottom: 20 }}>
|
||||
<View style={{ paddingBottom: 20 }} testID='sidebar'>
|
||||
<FlatList
|
||||
data={this.state.servers}
|
||||
renderItem={this.renderItem}
|
||||
keyExtractor={keyExtractor}
|
||||
/>
|
||||
<TouchableHighlight
|
||||
onPress={() => { this.props.logout(); }}
|
||||
onPress={() => {
|
||||
this.closeDrawer();
|
||||
this.props.logout();
|
||||
}}
|
||||
testID='sidebar-logout'
|
||||
>
|
||||
<View style={styles.serverItem}>
|
||||
<Text>
|
||||
|
@ -112,7 +121,11 @@ export default class Sidebar extends Component {
|
|||
</View>
|
||||
</TouchableHighlight>
|
||||
<TouchableHighlight
|
||||
onPress={() => { this.props.navigation.navigate({ key: 'AddServer', routeName: 'AddServer' }); }}
|
||||
onPress={() => {
|
||||
this.closeDrawer();
|
||||
this.props.navigation.navigate({ key: 'AddServer', routeName: 'AddServer' });
|
||||
}}
|
||||
testID='sidebar-add-server'
|
||||
>
|
||||
<View style={styles.serverItem}>
|
||||
<Text>
|
||||
|
|
|
@ -75,22 +75,37 @@ export default class RCTextInput extends React.PureComponent {
|
|||
showPassword: false
|
||||
}
|
||||
|
||||
icon = ({ name, onPress, style }) => <Icon name={name} style={[styles.icon, style]} size={20} onPress={onPress} />
|
||||
icon = ({
|
||||
name,
|
||||
onPress,
|
||||
style,
|
||||
testID
|
||||
}) => <Icon name={name} style={[styles.icon, style]} size={20} onPress={onPress} testID={testID} />
|
||||
|
||||
iconLeft = name => this.icon({ name, onPress: null, style: { left: 0 } });
|
||||
iconLeft = name => this.icon({
|
||||
name,
|
||||
onPress: null,
|
||||
style: { left: 0 },
|
||||
testID: this.props.testID ? `${ this.props.testID }-icon-left` : null
|
||||
});
|
||||
|
||||
iconPassword = name => this.icon({ name, onPress: () => this.tooglePassword(), style: { right: 0 } });
|
||||
iconPassword = name => this.icon({
|
||||
name,
|
||||
onPress: () => this.tooglePassword(),
|
||||
style: { right: 0 },
|
||||
testID: this.props.testID ? `${ this.props.testID }-icon-right` : null
|
||||
});
|
||||
|
||||
tooglePassword = () => this.setState({ showPassword: !this.state.showPassword });
|
||||
|
||||
render() {
|
||||
const {
|
||||
label, error, secureTextEntry, containerStyle, inputRef, iconLeft, inputStyle, ...inputProps
|
||||
label, error, secureTextEntry, containerStyle, inputRef, iconLeft, inputStyle, testID, placeholder, ...inputProps
|
||||
} = this.props;
|
||||
const { showPassword } = this.state;
|
||||
return (
|
||||
<View style={[styles.inputContainer, containerStyle]}>
|
||||
{ label && <Text style={[styles.label, error.error && styles.labelError]}>{label}</Text> }
|
||||
{label && <Text contentDescription={null} accessibilityLabel={null} style={[styles.label, error.error && styles.labelError]}>{label}</Text> }
|
||||
<View style={styles.wrap}>
|
||||
<TextInput
|
||||
style={[
|
||||
|
@ -105,6 +120,10 @@ export default class RCTextInput extends React.PureComponent {
|
|||
autoCapitalize='none'
|
||||
underlineColorAndroid='transparent'
|
||||
secureTextEntry={secureTextEntry && !showPassword}
|
||||
testID={testID}
|
||||
accessibilityLabel={placeholder}
|
||||
placeholder={placeholder}
|
||||
contentDescription={placeholder}
|
||||
{...inputProps}
|
||||
/>
|
||||
{iconLeft && this.iconLeft(iconLeft)}
|
||||
|
|
|
@ -270,6 +270,7 @@ export default class Message extends React.Component {
|
|||
onPress={() => this.onReactionPress(reaction.emoji)}
|
||||
onLongPress={() => this.onReactionLongPress()}
|
||||
key={reaction.emoji}
|
||||
testID={`message-reaction-${ reaction.emoji }`}
|
||||
>
|
||||
<View style={[styles.reactionContainer, reactedContainerStyle]}>
|
||||
<Emoji
|
||||
|
@ -292,7 +293,8 @@ export default class Message extends React.Component {
|
|||
{this.props.item.reactions.map(this.renderReaction)}
|
||||
<TouchableOpacity
|
||||
onPress={() => this.props.toggleReactionPicker(this.parseMessage())}
|
||||
key='add-reaction'
|
||||
key='message-add-reaction'
|
||||
testID='message-add-reaction'
|
||||
style={styles.reactionContainer}
|
||||
>
|
||||
<Icon name='insert-emoticon' color='#aaaaaa' size={15} />
|
||||
|
|
|
@ -40,6 +40,7 @@ async function canOpenRoomDDP(...args) {
|
|||
|
||||
export default async function canOpenRoom({ rid, path }) {
|
||||
const { database: db } = database;
|
||||
|
||||
const room = db.objects('subscriptions').filtered('rid == $0', rid);
|
||||
if (room.length) {
|
||||
return true;
|
||||
|
|
|
@ -15,7 +15,7 @@ export const merge = (subscription, room) => {
|
|||
subscription.joinCodeRequired = room.joinCodeRequired;
|
||||
|
||||
if (room.muted && room.muted.length) {
|
||||
subscription.muted = room.muted.filter(role => role).map(role => ({ value: role }));
|
||||
subscription.muted = room.muted.filter(user => user).map(user => ({ value: user }));
|
||||
}
|
||||
}
|
||||
if (subscription.roles && subscription.roles.length) {
|
||||
|
|
|
@ -21,9 +21,13 @@ export const getMessage = (rid, msg = {}) => {
|
|||
username: reduxStore.getState().login.user.username
|
||||
}
|
||||
};
|
||||
try {
|
||||
database.write(() => {
|
||||
database.create('messages', message, true);
|
||||
});
|
||||
} catch (error) {
|
||||
console.warn('getMessage', error);
|
||||
}
|
||||
return message;
|
||||
};
|
||||
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
import Random from 'react-native-meteor/lib/Random';
|
||||
import database from '../../realm';
|
||||
import { merge } from '../helpers/mergeSubscriptionsRooms';
|
||||
import protectedFunction from '../helpers/protectedFunction';
|
||||
import messagesStatus from '../../../constants/messagesStatus';
|
||||
import log from '../../../utils/log';
|
||||
|
||||
export default async function subscribeRooms(id) {
|
||||
|
@ -26,7 +28,9 @@ export default async function subscribeRooms(id) {
|
|||
}, 5000);
|
||||
};
|
||||
|
||||
if (this.ddp) {
|
||||
if (!this.ddp && this._login) {
|
||||
loop();
|
||||
} else {
|
||||
this.ddp.on('logged', () => {
|
||||
clearTimeout(timer);
|
||||
timer = false;
|
||||
|
@ -48,7 +52,7 @@ export default async function subscribeRooms(id) {
|
|||
const [, ev] = ddpMessage.fields.eventName.split('/');
|
||||
if (/subscriptions/.test(ev)) {
|
||||
const tpm = merge(data);
|
||||
return database.write(() => {
|
||||
database.write(() => {
|
||||
database.create('subscriptions', tpm, true);
|
||||
});
|
||||
}
|
||||
|
@ -58,6 +62,25 @@ export default async function subscribeRooms(id) {
|
|||
merge(sub, data);
|
||||
});
|
||||
}
|
||||
if (/message/.test(ev)) {
|
||||
const [args] = ddpMessage.fields.args;
|
||||
const _id = Random.id();
|
||||
const message = {
|
||||
_id,
|
||||
rid: args.rid,
|
||||
msg: args.msg,
|
||||
ts: new Date(),
|
||||
_updatedAt: new Date(),
|
||||
status: messagesStatus.SENT,
|
||||
u: {
|
||||
_id,
|
||||
username: 'rocket.cat'
|
||||
}
|
||||
};
|
||||
requestAnimationFrame(() => database.write(() => {
|
||||
database.create('messages', message, true);
|
||||
}));
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
import { AsyncStorage, Platform } from 'react-native';
|
||||
import { hashPassword } from 'react-native-meteor/lib/utils';
|
||||
import foreach from 'lodash/forEach';
|
||||
import Random from 'react-native-meteor/lib/Random';
|
||||
import RNFetchBlob from 'react-native-fetch-blob';
|
||||
|
||||
import reduxStore from './createStore';
|
||||
|
@ -23,8 +22,6 @@ import { someoneTyping, roomMessageReceived } from '../actions/room';
|
|||
import { setRoles } from '../actions/roles';
|
||||
import Ddp from './ddp';
|
||||
|
||||
import normalizeMessage from './methods/helpers/normalizeMessage';
|
||||
|
||||
import subscribeRooms from './methods/subscriptions/rooms';
|
||||
import subscribeRoom from './methods/subscriptions/room';
|
||||
|
||||
|
@ -167,9 +164,11 @@ const RocketChat = {
|
|||
|
||||
this.ddp.on('disconnected', protectedFunction(() => {
|
||||
reduxStore.dispatch(disconnect());
|
||||
console.warn(this.ddp);
|
||||
}));
|
||||
|
||||
this.ddp.on('stream-room-messages', (ddpMessage) => {
|
||||
// TODO: debounce
|
||||
const message = _buildMessage(ddpMessage.fields.args[0]);
|
||||
requestAnimationFrame(() => reduxStore.dispatch(roomMessageReceived(message)));
|
||||
});
|
||||
|
@ -182,65 +181,66 @@ const RocketChat = {
|
|||
return reduxStore.dispatch(someoneTyping({ _rid, username: ddpMessage.fields.args[0], typing: ddpMessage.fields.args[1] }));
|
||||
}));
|
||||
|
||||
this.ddp.on('stream-notify-user', protectedFunction((ddpMessage) => {
|
||||
const [type, data] = ddpMessage.fields.args;
|
||||
const [, ev] = ddpMessage.fields.eventName.split('/');
|
||||
if (/subscriptions/.test(ev)) {
|
||||
if (data.roles) {
|
||||
data.roles = data.roles.map(role => ({ value: role }));
|
||||
}
|
||||
if (data.blocker) {
|
||||
data.blocked = true;
|
||||
} else {
|
||||
data.blocked = false;
|
||||
}
|
||||
if (data.mobilePushNotifications === 'nothing') {
|
||||
data.notifications = true;
|
||||
} else {
|
||||
data.notifications = false;
|
||||
}
|
||||
database.write(() => {
|
||||
database.create('subscriptions', data, true);
|
||||
});
|
||||
}
|
||||
if (/rooms/.test(ev) && type === 'updated') {
|
||||
const sub = database.objects('subscriptions').filtered('rid == $0', data._id)[0];
|
||||
// this.ddp.on('stream-notify-user', protectedFunction((ddpMessage) => {
|
||||
// console.warn('rc.stream-notify-user')
|
||||
// const [type, data] = ddpMessage.fields.args;
|
||||
// const [, ev] = ddpMessage.fields.eventName.split('/');
|
||||
// if (/subscriptions/.test(ev)) {
|
||||
// if (data.roles) {
|
||||
// data.roles = data.roles.map(role => ({ value: role }));
|
||||
// }
|
||||
// if (data.blocker) {
|
||||
// data.blocked = true;
|
||||
// } else {
|
||||
// data.blocked = false;
|
||||
// }
|
||||
// if (data.mobilePushNotifications === 'nothing') {
|
||||
// data.notifications = true;
|
||||
// } else {
|
||||
// data.notifications = false;
|
||||
// }
|
||||
// database.write(() => {
|
||||
// database.create('subscriptions', data, true);
|
||||
// });
|
||||
// }
|
||||
// if (/rooms/.test(ev) && type === 'updated') {
|
||||
// const sub = database.objects('subscriptions').filtered('rid == $0', data._id)[0];
|
||||
|
||||
database.write(() => {
|
||||
sub.roomUpdatedAt = data._updatedAt;
|
||||
sub.lastMessage = normalizeMessage(data.lastMessage);
|
||||
sub.ro = data.ro;
|
||||
sub.description = data.description;
|
||||
sub.topic = data.topic;
|
||||
sub.announcement = data.announcement;
|
||||
sub.reactWhenReadOnly = data.reactWhenReadOnly;
|
||||
sub.archived = data.archived;
|
||||
sub.joinCodeRequired = data.joinCodeRequired;
|
||||
if (data.muted) {
|
||||
sub.muted = data.muted.map(m => ({ value: m }));
|
||||
}
|
||||
});
|
||||
}
|
||||
if (/message/.test(ev)) {
|
||||
const [args] = ddpMessage.fields.args;
|
||||
const _id = Random.id();
|
||||
const message = {
|
||||
_id,
|
||||
rid: args.rid,
|
||||
msg: args.msg,
|
||||
ts: new Date(),
|
||||
_updatedAt: new Date(),
|
||||
status: messagesStatus.SENT,
|
||||
u: {
|
||||
_id,
|
||||
username: 'rocket.cat'
|
||||
}
|
||||
};
|
||||
requestAnimationFrame(() => database.write(() => {
|
||||
database.create('messages', message, true);
|
||||
}));
|
||||
}
|
||||
}));
|
||||
// database.write(() => {
|
||||
// sub.roomUpdatedAt = data._updatedAt;
|
||||
// sub.lastMessage = normalizeMessage(data.lastMessage);
|
||||
// sub.ro = data.ro;
|
||||
// sub.description = data.description;
|
||||
// sub.topic = data.topic;
|
||||
// sub.announcement = data.announcement;
|
||||
// sub.reactWhenReadOnly = data.reactWhenReadOnly;
|
||||
// sub.archived = data.archived;
|
||||
// sub.joinCodeRequired = data.joinCodeRequired;
|
||||
// if (data.muted) {
|
||||
// sub.muted = data.muted.map(m => ({ value: m }));
|
||||
// }
|
||||
// });
|
||||
// }
|
||||
// if (/message/.test(ev)) {
|
||||
// const [args] = ddpMessage.fields.args;
|
||||
// const _id = Random.id();
|
||||
// const message = {
|
||||
// _id,
|
||||
// rid: args.rid,
|
||||
// msg: args.msg,
|
||||
// ts: new Date(),
|
||||
// _updatedAt: new Date(),
|
||||
// status: messagesStatus.SENT,
|
||||
// u: {
|
||||
// _id,
|
||||
// username: 'rocket.cat'
|
||||
// }
|
||||
// };
|
||||
// requestAnimationFrame(() => database.write(() => {
|
||||
// database.create('messages', message, true);
|
||||
// }));
|
||||
// }
|
||||
// }));
|
||||
|
||||
this.ddp.on('rocketchat_starred_message', protectedFunction((ddpMessage) => {
|
||||
if (ddpMessage.msg === 'added') {
|
||||
|
|
|
@ -171,7 +171,8 @@ export default class RoomItem extends React.Component {
|
|||
onLongPress: PropTypes.func,
|
||||
user: PropTypes.object,
|
||||
avatarSize: PropTypes.number,
|
||||
statusStyle: ViewPropTypes.style
|
||||
statusStyle: ViewPropTypes.style,
|
||||
testID: PropTypes.string
|
||||
}
|
||||
|
||||
static defaultProps = {
|
||||
|
@ -238,7 +239,7 @@ export default class RoomItem extends React.Component {
|
|||
|
||||
render() {
|
||||
const {
|
||||
favorite, unread, userMentions, name, _updatedAt, alert, type
|
||||
favorite, unread, userMentions, name, _updatedAt, alert, type, testID
|
||||
} = this.props;
|
||||
|
||||
const date = this.formatDate(_updatedAt);
|
||||
|
@ -266,6 +267,7 @@ export default class RoomItem extends React.Component {
|
|||
activeOpacity={0.5}
|
||||
accessibilityLabel={accessibilityLabel}
|
||||
accessibilityTraits='selected'
|
||||
testID={testID}
|
||||
>
|
||||
<View style={[styles.container, favorite && styles.favorite]}>
|
||||
{this.icon}
|
||||
|
|
|
@ -164,7 +164,7 @@ const watchLoginOpen = function* watchLoginOpen() {
|
|||
}
|
||||
const sub = yield RocketChat.subscribe('meteor.loginServiceConfiguration');
|
||||
yield take(types.LOGIN.CLOSE);
|
||||
sub.unsubscribe();
|
||||
yield sub.unsubscribe().catch(err => console.warn(err));
|
||||
} catch (e) {
|
||||
log('watchLoginOpen', e);
|
||||
}
|
||||
|
|
|
@ -140,12 +140,16 @@ const updateLastOpen = function* updateLastOpen() {
|
|||
const goRoomsListAndDelete = function* goRoomsListAndDelete(rid) {
|
||||
NavigationService.goRoomsList();
|
||||
yield delay(1000);
|
||||
try {
|
||||
database.write(() => {
|
||||
const messages = database.objects('messages').filtered('rid = $0', rid);
|
||||
database.delete(messages);
|
||||
const subscription = database.objects('subscriptions').filtered('rid = $0', rid);
|
||||
database.delete(subscription);
|
||||
});
|
||||
} catch (error) {
|
||||
console.warn('goRoomsListAndDelete', error);
|
||||
}
|
||||
};
|
||||
|
||||
const handleLeaveRoom = function* handleLeaveRoom({ rid }) {
|
||||
|
|
|
@ -62,7 +62,7 @@ export default class CreateChannelView extends LoggedView {
|
|||
}
|
||||
|
||||
return (
|
||||
<Text style={[styles.label_white, styles.label_error]}>
|
||||
<Text style={[styles.label_white, styles.label_error]} testID='create-channel-error'>
|
||||
{this.props.createChannel.error.reason}
|
||||
</Text>
|
||||
);
|
||||
|
@ -75,6 +75,7 @@ export default class CreateChannelView extends LoggedView {
|
|||
style={[{ flexGrow: 0, flexShrink: 1 }]}
|
||||
value={this.state.type}
|
||||
onValueChange={type => this.setState({ type })}
|
||||
testID='create-channel-type'
|
||||
/>
|
||||
<Text style={[styles.label_white, styles.switchLabel]}>
|
||||
{this.state.type ? 'Public' : 'Private'}
|
||||
|
@ -90,7 +91,7 @@ export default class CreateChannelView extends LoggedView {
|
|||
keyboardVerticalOffset={128}
|
||||
>
|
||||
<ScrollView {...scrollPersistTaps} contentContainerStyle={styles.containerScrollView}>
|
||||
<SafeAreaView>
|
||||
<SafeAreaView testID='create-channel-view'>
|
||||
<RCTextInput
|
||||
label='Channel Name'
|
||||
value={this.state.channelName}
|
||||
|
@ -98,6 +99,7 @@ export default class CreateChannelView extends LoggedView {
|
|||
placeholder='Type the channel name here'
|
||||
returnKeyType='done'
|
||||
autoFocus
|
||||
testID='create-channel-name'
|
||||
/>
|
||||
{this.renderChannelNameError()}
|
||||
{this.renderTypeSwitch()}
|
||||
|
@ -126,6 +128,7 @@ export default class CreateChannelView extends LoggedView {
|
|||
? styles.disabledButton
|
||||
: styles.enabledButton
|
||||
]}
|
||||
testID='create-channel-submit'
|
||||
>
|
||||
<Text style={styles.button_white}>CREATE</Text>
|
||||
</TouchableOpacity>
|
||||
|
|
|
@ -80,7 +80,7 @@ export default class ForgotPasswordView extends LoggedView {
|
|||
keyboardVerticalOffset={128}
|
||||
>
|
||||
<ScrollView {...scrollPersistTaps} contentContainerStyle={styles.containerScrollView}>
|
||||
<SafeAreaView>
|
||||
<SafeAreaView testID='forgot-password-view'>
|
||||
<View style={styles.loginView}>
|
||||
<View style={styles.formContainer}>
|
||||
<TextInput
|
||||
|
@ -91,6 +91,7 @@ export default class ForgotPasswordView extends LoggedView {
|
|||
returnKeyType='next'
|
||||
onChangeText={email => this.validate(email)}
|
||||
onSubmitEditing={() => this.resetPassword()}
|
||||
testID='forgot-password-view-email'
|
||||
/>
|
||||
|
||||
<View style={styles.alignItemsFlexStart}>
|
||||
|
@ -98,6 +99,7 @@ export default class ForgotPasswordView extends LoggedView {
|
|||
title='Reset password'
|
||||
type='primary'
|
||||
onPress={this.resetPassword}
|
||||
testID='forgot-password-view-submit'
|
||||
/>
|
||||
</View>
|
||||
|
||||
|
|
|
@ -209,7 +209,7 @@ class ListServerView extends LoggedView {
|
|||
|
||||
render() {
|
||||
return (
|
||||
<SafeAreaView style={styles.view}>
|
||||
<SafeAreaView style={styles.view} testID='list-server-view'>
|
||||
<SectionList
|
||||
style={styles.list}
|
||||
sections={this.state.sections}
|
||||
|
|
|
@ -277,7 +277,7 @@ export default class LoginSignupView extends LoggedView {
|
|||
style={[sharedStyles.container, sharedStyles.containerScrollView]}
|
||||
{...scrollPersistTaps}
|
||||
>
|
||||
<SafeAreaView>
|
||||
<SafeAreaView testID='welcome-view'>
|
||||
<View style={styles.container}>
|
||||
<Image
|
||||
source={require('../static/images/logo.png')}
|
||||
|
@ -294,11 +294,13 @@ export default class LoginSignupView extends LoggedView {
|
|||
title='I have an account'
|
||||
type='primary'
|
||||
onPress={() => this.props.navigation.navigate({ key: 'Login', routeName: 'Login' })}
|
||||
testID='welcome-view-login'
|
||||
/>
|
||||
<Button
|
||||
title='Create account'
|
||||
type='secondary'
|
||||
onPress={() => this.props.navigation.navigate({ key: 'Register', routeName: 'Register' })}
|
||||
testID='welcome-view-register'
|
||||
/>
|
||||
{this.renderServices()}
|
||||
</View>
|
||||
|
|
|
@ -83,7 +83,7 @@ export default class LoginView extends LoggedView {
|
|||
key='login-view'
|
||||
>
|
||||
<ScrollView {...scrollPersistTaps} contentContainerStyle={styles.containerScrollView}>
|
||||
<SafeAreaView>
|
||||
<SafeAreaView testID='login-view'>
|
||||
<CloseModalButton navigation={this.props.navigation} />
|
||||
<Text style={[styles.loginText, styles.loginTitle]}>Login</Text>
|
||||
<TextInput
|
||||
|
@ -94,6 +94,7 @@ export default class LoginView extends LoggedView {
|
|||
iconLeft='at'
|
||||
onChangeText={username => this.setState({ username })}
|
||||
onSubmitEditing={() => { this.password.focus(); }}
|
||||
testID='login-view-email'
|
||||
/>
|
||||
|
||||
<TextInput
|
||||
|
@ -105,6 +106,7 @@ export default class LoginView extends LoggedView {
|
|||
secureTextEntry
|
||||
onSubmitEditing={this.submit}
|
||||
onChangeText={password => this.setState({ password })}
|
||||
testID='login-view-password'
|
||||
/>
|
||||
|
||||
{this.renderTOTP()}
|
||||
|
@ -114,17 +116,20 @@ export default class LoginView extends LoggedView {
|
|||
title='Login'
|
||||
type='primary'
|
||||
onPress={this.submit}
|
||||
testID='login-view-submit'
|
||||
/>
|
||||
<Text style={[styles.loginText, { marginTop: 10 }]}>New in Rocket.Chat?
|
||||
<Text
|
||||
style={{ color: COLOR_BUTTON_PRIMARY }}
|
||||
style={[styles.loginText, { marginTop: 10 }]}
|
||||
testID='login-view-register'
|
||||
onPress={() => this.props.navigation.navigate('Register')}
|
||||
>Sign Up
|
||||
>New in Rocket.Chat?
|
||||
<Text style={{ color: COLOR_BUTTON_PRIMARY }}>Sign Up
|
||||
</Text>
|
||||
</Text>
|
||||
<Text
|
||||
style={[styles.loginText, { marginTop: 20, fontSize: 13 }]}
|
||||
onPress={() => this.props.navigation.navigate('ForgotPassword')}
|
||||
testID='login-view-forgot-password'
|
||||
>Forgot password
|
||||
</Text>
|
||||
</View>
|
||||
|
|
|
@ -73,7 +73,7 @@ export default class MentionedMessagesView extends LoggedView {
|
|||
}
|
||||
|
||||
renderEmpty = () => (
|
||||
<View style={styles.listEmptyContainer}>
|
||||
<View style={styles.listEmptyContainer} testID='mentioned-messages-view'>
|
||||
<Text>No mentioned messages</Text>
|
||||
</View>
|
||||
)
|
||||
|
@ -99,8 +99,10 @@ export default class MentionedMessagesView extends LoggedView {
|
|||
}
|
||||
|
||||
return (
|
||||
[
|
||||
<FlatList
|
||||
key='mentioned-messages-view-list'
|
||||
testID='mentioned-messages-view'
|
||||
data={messages}
|
||||
renderItem={this.renderItem}
|
||||
style={styles.list}
|
||||
|
@ -109,6 +111,7 @@ export default class MentionedMessagesView extends LoggedView {
|
|||
ListHeaderComponent={loading && <RCActivityIndicator />}
|
||||
ListFooterComponent={loadingMore && <RCActivityIndicator />}
|
||||
/>
|
||||
]
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -106,7 +106,7 @@ export default class NewServerView extends LoggedView {
|
|||
keyboardVerticalOffset={128}
|
||||
>
|
||||
<ScrollView {...scrollPersistTaps} contentContainerStyle={styles.containerScrollView}>
|
||||
<SafeAreaView>
|
||||
<SafeAreaView testID='new-server-view'>
|
||||
<Text style={[styles.loginText, styles.loginTitle]}>Sign in your server</Text>
|
||||
<TextInput
|
||||
inputRef={e => this.input = e}
|
||||
|
@ -115,6 +115,7 @@ export default class NewServerView extends LoggedView {
|
|||
placeholder={this.state.defaultServer}
|
||||
returnKeyType='done'
|
||||
onChangeText={this.onChangeText}
|
||||
testID='new-server-view-input'
|
||||
onSubmitEditing={this.submit}
|
||||
/>
|
||||
{this.renderValidation()}
|
||||
|
@ -124,6 +125,7 @@ export default class NewServerView extends LoggedView {
|
|||
type='primary'
|
||||
onPress={this.submit}
|
||||
disabled={!validInstance}
|
||||
testID='new-server-view-button'
|
||||
/>
|
||||
</View>
|
||||
<Loading visible={this.props.addingServer} />
|
||||
|
|
|
@ -97,7 +97,7 @@ export default class PinnedMessagesView extends LoggedView {
|
|||
}
|
||||
|
||||
renderEmpty = () => (
|
||||
<View style={styles.listEmptyContainer}>
|
||||
<View style={styles.listEmptyContainer} testID='pinned-messages-view'>
|
||||
<Text>No pinned messages</Text>
|
||||
</View>
|
||||
)
|
||||
|
@ -126,6 +126,7 @@ export default class PinnedMessagesView extends LoggedView {
|
|||
[
|
||||
<FlatList
|
||||
key='pinned-messages-view-list'
|
||||
testID='pinned-messages-view'
|
||||
data={messages}
|
||||
renderItem={this.renderItem}
|
||||
style={styles.list}
|
||||
|
|
|
@ -108,6 +108,7 @@ export default class RegisterView extends LoggedView {
|
|||
iconLeft='account'
|
||||
onChangeText={name => this.setState({ name })}
|
||||
onSubmitEditing={() => { this.email.focus(); }}
|
||||
testID='register-view-name'
|
||||
/>
|
||||
<TextInput
|
||||
inputRef={(e) => { this.email = e; }}
|
||||
|
@ -119,6 +120,7 @@ export default class RegisterView extends LoggedView {
|
|||
onChangeText={email => this.setState({ email })}
|
||||
onSubmitEditing={() => { this.password.focus(); }}
|
||||
error={this.invalidEmail()}
|
||||
testID='register-view-email'
|
||||
/>
|
||||
<TextInput
|
||||
inputRef={(e) => { this.password = e; }}
|
||||
|
@ -129,6 +131,7 @@ export default class RegisterView extends LoggedView {
|
|||
secureTextEntry
|
||||
onChangeText={password => this.setState({ password })}
|
||||
onSubmitEditing={() => { this.confirmPassword.focus(); }}
|
||||
testID='register-view-password'
|
||||
/>
|
||||
<TextInput
|
||||
inputRef={(e) => { this.confirmPassword = e; }}
|
||||
|
@ -144,6 +147,7 @@ export default class RegisterView extends LoggedView {
|
|||
secureTextEntry
|
||||
onChangeText={confirmPassword => this.setState({ confirmPassword })}
|
||||
onSubmitEditing={this.submit}
|
||||
testID='register-view-repeat-password'
|
||||
/>
|
||||
|
||||
<View style={styles.alignItemsFlexStart}>
|
||||
|
@ -157,10 +161,9 @@ export default class RegisterView extends LoggedView {
|
|||
title='Register'
|
||||
type='primary'
|
||||
onPress={this.submit}
|
||||
testID='register-view-submit'
|
||||
/>
|
||||
</View>
|
||||
|
||||
{this.props.login.failure && <Text style={styles.error}>{this.props.login.error.reason}</Text>}
|
||||
</View>
|
||||
);
|
||||
}
|
||||
|
@ -179,6 +182,7 @@ export default class RegisterView extends LoggedView {
|
|||
iconLeft='at'
|
||||
onChangeText={username => this.setState({ username })}
|
||||
onSubmitEditing={() => { this.usernameSubmit(); }}
|
||||
testID='register-view-username'
|
||||
/>
|
||||
|
||||
<View style={styles.alignItemsFlexStart}>
|
||||
|
@ -186,10 +190,9 @@ export default class RegisterView extends LoggedView {
|
|||
title='Register'
|
||||
type='primary'
|
||||
onPress={this.usernameSubmit}
|
||||
testID='register-view-submit-username'
|
||||
/>
|
||||
</View>
|
||||
|
||||
{this.props.login.failure && <Text style={styles.error}>{this.props.login.error.reason}</Text>}
|
||||
</View>
|
||||
);
|
||||
}
|
||||
|
@ -198,11 +201,16 @@ export default class RegisterView extends LoggedView {
|
|||
return (
|
||||
<KeyboardView contentContainerStyle={styles.container}>
|
||||
<ScrollView {...scrollPersistTaps} contentContainerStyle={styles.containerScrollView}>
|
||||
<SafeAreaView>
|
||||
<SafeAreaView testID='register-view'>
|
||||
<CloseModalButton navigation={this.props.navigation} />
|
||||
<Text style={[styles.loginText, styles.loginTitle]}>Sign Up</Text>
|
||||
{this._renderRegister()}
|
||||
{this._renderUsername()}
|
||||
{this.props.login.failure &&
|
||||
<Text style={styles.error} testID='register-view-error'>
|
||||
{this.props.login.error.reason}
|
||||
</Text>
|
||||
}
|
||||
<Loading visible={this.props.login.isFetching} />
|
||||
</SafeAreaView>
|
||||
</ScrollView>
|
||||
|
|
|
@ -134,13 +134,24 @@ export default class RoomActionsView extends LoggedView {
|
|||
icon: 'ios-star',
|
||||
name: 'USER',
|
||||
route: 'RoomInfo',
|
||||
params: { rid }
|
||||
params: { rid },
|
||||
testID: 'room-actions-info'
|
||||
}],
|
||||
renderItem: this.renderRoomInfo
|
||||
}, {
|
||||
data: [
|
||||
{ icon: 'ios-call-outline', name: 'Voice call', disabled: true },
|
||||
{ icon: 'ios-videocam-outline', name: 'Video call', disabled: true }
|
||||
{
|
||||
icon: 'ios-call-outline',
|
||||
name: 'Voice call',
|
||||
disabled: true,
|
||||
testID: 'room-actions-voice'
|
||||
},
|
||||
{
|
||||
icon: 'ios-videocam-outline',
|
||||
name: 'Video call',
|
||||
disabled: true,
|
||||
testID: 'room-actions-video'
|
||||
}
|
||||
],
|
||||
renderItem: this.renderItem
|
||||
}, {
|
||||
|
@ -149,43 +160,55 @@ export default class RoomActionsView extends LoggedView {
|
|||
icon: 'ios-attach',
|
||||
name: 'Files',
|
||||
route: 'RoomFiles',
|
||||
params: { rid }
|
||||
params: { rid },
|
||||
testID: 'room-actions-files'
|
||||
},
|
||||
{
|
||||
icon: 'ios-at-outline',
|
||||
name: 'Mentions',
|
||||
route: 'MentionedMessages',
|
||||
params: { rid }
|
||||
params: { rid },
|
||||
testID: 'room-actions-mentioned'
|
||||
},
|
||||
{
|
||||
icon: 'ios-star-outline',
|
||||
name: 'Starred',
|
||||
route: 'StarredMessages',
|
||||
params: { rid }
|
||||
params: { rid },
|
||||
testID: 'room-actions-starred'
|
||||
},
|
||||
{
|
||||
icon: 'ios-search',
|
||||
name: 'Search',
|
||||
route: 'SearchMessages',
|
||||
params: { rid }
|
||||
params: { rid },
|
||||
testID: 'room-actions-search'
|
||||
},
|
||||
{
|
||||
icon: 'ios-share-outline',
|
||||
name: 'Share',
|
||||
disabled: true,
|
||||
testID: 'room-actions-share'
|
||||
},
|
||||
{ icon: 'ios-share-outline', name: 'Share', disabled: true },
|
||||
{
|
||||
icon: 'ios-pin',
|
||||
name: 'Pinned',
|
||||
route: 'PinnedMessages',
|
||||
params: { rid }
|
||||
params: { rid },
|
||||
testID: 'room-actions-pinned'
|
||||
},
|
||||
{
|
||||
icon: 'ios-code',
|
||||
name: 'Snippets',
|
||||
route: 'SnippetedMessages',
|
||||
params: { rid }
|
||||
params: { rid },
|
||||
testID: 'room-actions-snippeted'
|
||||
},
|
||||
{
|
||||
icon: `ios-notifications${ notifications ? '' : '-off' }-outline`,
|
||||
name: `${ notifications ? 'Enable' : 'Disable' } notifications`,
|
||||
event: () => this.toggleNotifications()
|
||||
event: () => this.toggleNotifications(),
|
||||
testID: 'room-actions-notifications'
|
||||
}
|
||||
],
|
||||
renderItem: this.renderItem
|
||||
|
@ -198,7 +221,8 @@ export default class RoomActionsView extends LoggedView {
|
|||
icon: 'block',
|
||||
name: `${ blocked ? 'Unblock' : 'Block' } user`,
|
||||
type: 'danger',
|
||||
event: () => this.toggleBlockUser()
|
||||
event: () => this.toggleBlockUser(),
|
||||
testID: 'room-actions-block-user'
|
||||
}
|
||||
],
|
||||
renderItem: this.renderItem
|
||||
|
@ -209,7 +233,8 @@ export default class RoomActionsView extends LoggedView {
|
|||
name: 'Members',
|
||||
description: (onlineMembers.length === 1 ? `${ onlineMembers.length } member` : `${ onlineMembers.length } members`),
|
||||
route: 'RoomMembers',
|
||||
params: { rid, members: onlineMembers }
|
||||
params: { rid, members: onlineMembers },
|
||||
testID: 'room-actions-members'
|
||||
}];
|
||||
|
||||
if (this.canAddUser) {
|
||||
|
@ -229,7 +254,8 @@ export default class RoomActionsView extends LoggedView {
|
|||
this.props.setLoadingInvite(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
testID: 'room-actions-add-user'
|
||||
});
|
||||
}
|
||||
sections[2].data = [...actions, ...sections[2].data];
|
||||
|
@ -239,7 +265,8 @@ export default class RoomActionsView extends LoggedView {
|
|||
icon: 'block',
|
||||
name: 'Leave channel',
|
||||
type: 'danger',
|
||||
event: () => this.leaveChannel()
|
||||
event: () => this.leaveChannel(),
|
||||
testID: 'room-actions-leave-channel'
|
||||
}
|
||||
],
|
||||
renderItem: this.renderItem
|
||||
|
@ -248,7 +275,7 @@ export default class RoomActionsView extends LoggedView {
|
|||
return sections;
|
||||
}
|
||||
|
||||
toggleBlockUser = () => {
|
||||
toggleBlockUser = async() => {
|
||||
const { rid, blocked } = this.state.room;
|
||||
const { member } = this.state;
|
||||
try {
|
||||
|
@ -316,6 +343,7 @@ export default class RoomActionsView extends LoggedView {
|
|||
activeOpacity={0.5}
|
||||
accessibilityLabel={item.name}
|
||||
accessibilityTraits='button'
|
||||
testID={item.testID}
|
||||
>
|
||||
<View style={[styles.sectionItem, item.disabled && styles.sectionItemDisabled]}>
|
||||
{subview}
|
||||
|
@ -348,6 +376,7 @@ export default class RoomActionsView extends LoggedView {
|
|||
|
||||
render() {
|
||||
return (
|
||||
<View testID='room-actions-view'>
|
||||
<SectionList
|
||||
style={styles.container}
|
||||
stickySectionHeadersEnabled={false}
|
||||
|
@ -355,7 +384,9 @@ export default class RoomActionsView extends LoggedView {
|
|||
SectionSeparatorComponent={this.renderSectionSeparator}
|
||||
ItemSeparatorComponent={renderSeparator}
|
||||
keyExtractor={item => item.name}
|
||||
testID='room-actions-list'
|
||||
/>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -73,7 +73,7 @@ export default class RoomFilesView extends LoggedView {
|
|||
}
|
||||
|
||||
renderEmpty = () => (
|
||||
<View style={styles.listEmptyContainer}>
|
||||
<View style={styles.listEmptyContainer} testID='room-files-view'>
|
||||
<Text>No files</Text>
|
||||
</View>
|
||||
)
|
||||
|
@ -97,8 +97,10 @@ export default class RoomFilesView extends LoggedView {
|
|||
|
||||
const { loading, loadingMore } = this.state;
|
||||
return (
|
||||
[
|
||||
<FlatList
|
||||
key='room-files-view-list'
|
||||
testID='room-files-view'
|
||||
data={messages}
|
||||
renderItem={this.renderItem}
|
||||
style={styles.list}
|
||||
|
@ -107,6 +109,7 @@ export default class RoomFilesView extends LoggedView {
|
|||
ListHeaderComponent={loading && <RCActivityIndicator />}
|
||||
ListFooterComponent={loadingMore && <RCActivityIndicator />}
|
||||
/>
|
||||
]
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,12 +13,13 @@ export default class SwitchContainer extends React.PureComponent {
|
|||
leftLabelSecondary: PropTypes.string,
|
||||
rightLabelPrimary: PropTypes.string,
|
||||
rightLabelSecondary: PropTypes.string,
|
||||
onValueChange: PropTypes.func
|
||||
onValueChange: PropTypes.func,
|
||||
testID: PropTypes.string
|
||||
}
|
||||
|
||||
render() {
|
||||
const {
|
||||
value, disabled, onValueChange, leftLabelPrimary, leftLabelSecondary, rightLabelPrimary, rightLabelSecondary
|
||||
value, disabled, onValueChange, leftLabelPrimary, leftLabelSecondary, rightLabelPrimary, rightLabelSecondary, testID
|
||||
} = this.props;
|
||||
return (
|
||||
[
|
||||
|
@ -32,6 +33,7 @@ export default class SwitchContainer extends React.PureComponent {
|
|||
onValueChange={onValueChange}
|
||||
value={value}
|
||||
disabled={disabled}
|
||||
testID={testID}
|
||||
/>
|
||||
<View style={styles.switchLabelContainer}>
|
||||
<Text style={styles.switchLabelPrimary}>{rightLabelPrimary}</Text>
|
||||
|
|
|
@ -74,9 +74,9 @@ export default class RoomInfoEditView extends LoggedView {
|
|||
this.rooms.removeAllListeners();
|
||||
}
|
||||
|
||||
updateRoom = () => {
|
||||
updateRoom = async() => {
|
||||
const [room] = this.rooms;
|
||||
this.setState({ room });
|
||||
await this.setState({ room });
|
||||
}
|
||||
|
||||
init = () => {
|
||||
|
@ -259,8 +259,12 @@ export default class RoomInfoEditView extends LoggedView {
|
|||
contentContainerStyle={sharedStyles.container}
|
||||
keyboardVerticalOffset={128}
|
||||
>
|
||||
<ScrollView {...scrollPersistTaps} contentContainerStyle={sharedStyles.containerScrollView}>
|
||||
<SafeAreaView>
|
||||
<ScrollView
|
||||
contentContainerStyle={sharedStyles.containerScrollView}
|
||||
testID='room-info-edit-view-list'
|
||||
{...scrollPersistTaps}
|
||||
>
|
||||
<SafeAreaView testID='room-info-edit-view'>
|
||||
<View style={sharedStyles.formContainer}>
|
||||
<RCTextInput
|
||||
inputRef={(e) => { this.name = e; }}
|
||||
|
@ -269,6 +273,7 @@ export default class RoomInfoEditView extends LoggedView {
|
|||
onChangeText={value => this.setState({ name: value })}
|
||||
onSubmitEditing={() => { this.description.focus(); }}
|
||||
error={nameError}
|
||||
testID='room-info-edit-view-name'
|
||||
/>
|
||||
<RCTextInput
|
||||
inputRef={(e) => { this.description = e; }}
|
||||
|
@ -276,6 +281,7 @@ export default class RoomInfoEditView extends LoggedView {
|
|||
value={description}
|
||||
onChangeText={value => this.setState({ description: value })}
|
||||
onSubmitEditing={() => { this.topic.focus(); }}
|
||||
testID='room-info-edit-view-description'
|
||||
/>
|
||||
<RCTextInput
|
||||
inputRef={(e) => { this.topic = e; }}
|
||||
|
@ -283,6 +289,7 @@ export default class RoomInfoEditView extends LoggedView {
|
|||
value={topic}
|
||||
onChangeText={value => this.setState({ topic: value })}
|
||||
onSubmitEditing={() => { this.announcement.focus(); }}
|
||||
testID='room-info-edit-view-topic'
|
||||
/>
|
||||
<RCTextInput
|
||||
inputRef={(e) => { this.announcement = e; }}
|
||||
|
@ -290,6 +297,7 @@ export default class RoomInfoEditView extends LoggedView {
|
|||
value={announcement}
|
||||
onChangeText={value => this.setState({ announcement: value })}
|
||||
onSubmitEditing={() => { this.joinCode.focus(); }}
|
||||
testID='room-info-edit-view-announcement'
|
||||
/>
|
||||
<RCTextInput
|
||||
inputRef={(e) => { this.joinCode = e; }}
|
||||
|
@ -298,6 +306,7 @@ export default class RoomInfoEditView extends LoggedView {
|
|||
onChangeText={value => this.setState({ joinCode: value })}
|
||||
onSubmitEditing={this.submit}
|
||||
secureTextEntry
|
||||
testID='room-info-edit-view-password'
|
||||
/>
|
||||
<SwitchContainer
|
||||
value={t}
|
||||
|
@ -306,6 +315,7 @@ export default class RoomInfoEditView extends LoggedView {
|
|||
rightLabelPrimary='Private'
|
||||
rightLabelSecondary='Just invited people can access this channel'
|
||||
onValueChange={value => this.setState({ t: value })}
|
||||
testID='room-info-edit-view-t'
|
||||
/>
|
||||
<SwitchContainer
|
||||
value={ro}
|
||||
|
@ -315,6 +325,7 @@ export default class RoomInfoEditView extends LoggedView {
|
|||
rightLabelSecondary='Only authorized users can write new messages'
|
||||
onValueChange={value => this.setState({ ro: value })}
|
||||
disabled={!this.permissions[PERMISSION_SET_READONLY]}
|
||||
testID='room-info-edit-view-ro'
|
||||
/>
|
||||
{ro &&
|
||||
<SwitchContainer
|
||||
|
@ -325,12 +336,14 @@ export default class RoomInfoEditView extends LoggedView {
|
|||
rightLabelSecondary='Reactions are enabled'
|
||||
onValueChange={value => this.setState({ reactWhenReadOnly: value })}
|
||||
disabled={!this.permissions[PERMISSION_SET_REACT_WHEN_READONLY]}
|
||||
testID='room-info-edit-view-react-when-ro'
|
||||
/>
|
||||
}
|
||||
<TouchableOpacity
|
||||
style={[sharedStyles.buttonContainer, !this.formIsChanged() && styles.buttonContainerDisabled]}
|
||||
onPress={this.submit}
|
||||
disabled={!this.formIsChanged()}
|
||||
testID='room-info-edit-view-submit'
|
||||
>
|
||||
<Text style={sharedStyles.button} accessibilityTraits='button'>SAVE</Text>
|
||||
</TouchableOpacity>
|
||||
|
@ -338,6 +351,7 @@ export default class RoomInfoEditView extends LoggedView {
|
|||
<TouchableOpacity
|
||||
style={[sharedStyles.buttonContainer_inverted, styles.buttonInverted, { flex: 1 }]}
|
||||
onPress={this.reset}
|
||||
testID='room-info-edit-view-reset'
|
||||
>
|
||||
<Text style={sharedStyles.button_inverted} accessibilityTraits='button'>RESET</Text>
|
||||
</TouchableOpacity>
|
||||
|
@ -350,6 +364,7 @@ export default class RoomInfoEditView extends LoggedView {
|
|||
]}
|
||||
onPress={this.toggleArchive}
|
||||
disabled={!this.hasArchivePermission()}
|
||||
testID='room-info-edit-view-archive'
|
||||
>
|
||||
<Text style={[sharedStyles.button_inverted, styles.colorDanger]} accessibilityTraits='button'>
|
||||
{ room.archived ? 'UNARCHIVE' : 'ARCHIVE' }
|
||||
|
@ -366,6 +381,7 @@ export default class RoomInfoEditView extends LoggedView {
|
|||
]}
|
||||
onPress={this.delete}
|
||||
disabled={!this.hasDeletePermission()}
|
||||
testID='room-info-edit-view-delete'
|
||||
>
|
||||
<Text style={[sharedStyles.button_inverted, styles.colorDanger]} accessibilityTraits='button'>DELETE</Text>
|
||||
</TouchableOpacity>
|
||||
|
|
|
@ -20,7 +20,10 @@ import RoomTypeIcon from '../../containers/RoomTypeIcon';
|
|||
const PERMISSION_EDIT_ROOM = 'edit-room';
|
||||
|
||||
const camelize = str => str.replace(/^(.)/, (match, chr) => chr.toUpperCase());
|
||||
const getRoomTitle = room => (room.t === 'd' ? <Text>{room.fname}</Text> : <Text><RoomTypeIcon type={room.t} /> {room.name}</Text>);
|
||||
const getRoomTitle = room => (room.t === 'd' ?
|
||||
<Text testID='room-info-view-name'>{room.fname}</Text> :
|
||||
[<RoomTypeIcon type={room.t} />, <Text testID='room-info-view-name'>{room.name}</Text>]
|
||||
);
|
||||
@connect(state => ({
|
||||
baseUrl: state.settings.Site_Url || state.server ? state.server.server : '',
|
||||
user: state.login.user,
|
||||
|
@ -52,6 +55,7 @@ export default class RoomInfoView extends LoggedView {
|
|||
activeOpacity={0.5}
|
||||
accessibilityLabel='edit'
|
||||
accessibilityTraits='button'
|
||||
testID='room-info-view-edit-button'
|
||||
>
|
||||
<View style={styles.headerButton}>
|
||||
<MaterialIcon name='edit' size={20} />
|
||||
|
@ -129,7 +133,11 @@ export default class RoomInfoView extends LoggedView {
|
|||
renderItem = (key, room) => (
|
||||
<View style={styles.item}>
|
||||
<Text style={styles.itemLabel}>{camelize(key)}</Text>
|
||||
<Text style={[styles.itemContent, !room[key] && styles.itemContent__empty]}>{ room[key] ? room[key] : `No ${ key } provided.` }</Text>
|
||||
<Text
|
||||
style={[styles.itemContent, !room[key] && styles.itemContent__empty]}
|
||||
testID={`room-info-view-${ key }`}
|
||||
>{ room[key] ? room[key] : `No ${ key } provided.` }
|
||||
</Text>
|
||||
</View>
|
||||
);
|
||||
|
||||
|
@ -183,9 +191,9 @@ export default class RoomInfoView extends LoggedView {
|
|||
}
|
||||
return (
|
||||
<ScrollView style={styles.container}>
|
||||
<View style={styles.avatarContainer}>
|
||||
<View style={styles.avatarContainer} testID='room-info-view'>
|
||||
{this.renderAvatar(room, roomUser)}
|
||||
<Text style={styles.roomTitle}>{ getRoomTitle(room) }</Text>
|
||||
<View style={styles.roomTitle}>{ getRoomTitle(room) }</View>
|
||||
</View>
|
||||
{!this.isDirect() && this.renderItem('description', room)}
|
||||
{!this.isDirect() && this.renderItem('topic', room)}
|
||||
|
|
|
@ -31,7 +31,8 @@ export default StyleSheet.create({
|
|||
},
|
||||
roomTitle: {
|
||||
fontSize: 18,
|
||||
paddingTop: 20
|
||||
paddingTop: 20,
|
||||
flexDirection: 'row'
|
||||
},
|
||||
roomDescription: {
|
||||
fontSize: 14,
|
||||
|
|
|
@ -39,6 +39,7 @@ export default class MentionedMessagesView extends LoggedView {
|
|||
accessibilityLabel={label}
|
||||
accessibilityTraits='button'
|
||||
style={styles.headerButtonTouchable}
|
||||
testID='room-members-view-toggle-status'
|
||||
>
|
||||
<View style={styles.headerButton}>
|
||||
<Text style={styles.headerButtonText}>{label}</Text>
|
||||
|
@ -168,6 +169,7 @@ export default class MentionedMessagesView extends LoggedView {
|
|||
blurOnSubmit
|
||||
autoCorrect={false}
|
||||
autoCapitalize='none'
|
||||
testID='room-members-view-search'
|
||||
/>
|
||||
</View>
|
||||
)
|
||||
|
@ -185,6 +187,7 @@ export default class MentionedMessagesView extends LoggedView {
|
|||
showLastMessage={false}
|
||||
avatarSize={30}
|
||||
statusStyle={styles.status}
|
||||
testID={`room-members-view-item-${ item.username }`}
|
||||
/>
|
||||
)
|
||||
|
||||
|
@ -194,6 +197,7 @@ export default class MentionedMessagesView extends LoggedView {
|
|||
[
|
||||
<FlatList
|
||||
key='room-members-view-list'
|
||||
testID='room-members-view'
|
||||
data={filtering ? membersFiltered : members}
|
||||
renderItem={this.renderItem}
|
||||
style={styles.list}
|
||||
|
|
|
@ -136,7 +136,8 @@ export default class RoomHeaderView extends React.PureComponent {
|
|||
style={styles.titleContainer}
|
||||
accessibilityLabel={accessibilityLabel}
|
||||
accessibilityTraits='header'
|
||||
onPress={() => this.props.navigation.navigate({ key: 'RoomInfo', routeName: 'RoomInfo', params: this.state.room })}
|
||||
onPress={() => this.props.navigation.navigate({ key: 'RoomInfo', routeName: 'RoomInfo', params: { rid: this.state.room.rid } })}
|
||||
testID='room-view-header-title'
|
||||
>
|
||||
|
||||
<Avatar
|
||||
|
@ -151,10 +152,12 @@ export default class RoomHeaderView extends React.PureComponent {
|
|||
}
|
||||
</Avatar>
|
||||
<View style={styles.titleTextContainer}>
|
||||
<Text style={styles.title} allowFontScaling={false}>
|
||||
<RoomTypeIcon type={this.state.room.t} size={13} />
|
||||
<View style={{ flexDirection: 'row' }}>
|
||||
<RoomTypeIcon type={this.state.room.t} size={13} />
|
||||
<Text style={styles.title} allowFontScaling={false} testID='room-view-title'>
|
||||
{this.state.room.name}
|
||||
</Text>
|
||||
</View>
|
||||
|
||||
{ t && <Text style={styles.userStatus} allowFontScaling={false} numberOfLines={1}>{t}</Text>}
|
||||
|
||||
|
@ -176,6 +179,7 @@ export default class RoomHeaderView extends React.PureComponent {
|
|||
}}
|
||||
accessibilityLabel='Star room'
|
||||
accessibilityTraits='button'
|
||||
testID='room-view-header-star'
|
||||
>
|
||||
<Icon
|
||||
name={`${ Platform.OS === 'ios' ? 'ios' : 'md' }-star${ this.state.room.f ? '' : '-outline' }`}
|
||||
|
@ -189,6 +193,7 @@ export default class RoomHeaderView extends React.PureComponent {
|
|||
onPress={() => this.props.navigation.navigate({ key: 'RoomActions', routeName: 'RoomActions', params: { rid: this.state.room.rid } })}
|
||||
accessibilityLabel='Room actions'
|
||||
accessibilityTraits='button'
|
||||
testID='room-view-header-actions'
|
||||
>
|
||||
<Icon
|
||||
name={Platform.OS === 'ios' ? 'ios-more' : 'md-more'}
|
||||
|
@ -202,7 +207,7 @@ export default class RoomHeaderView extends React.PureComponent {
|
|||
|
||||
render() {
|
||||
return (
|
||||
<View style={styles.header}>
|
||||
<View style={styles.header} testID='room-view-header'>
|
||||
{this.renderLeft()}
|
||||
{this.renderCenter()}
|
||||
{this.renderRight()}
|
||||
|
|
|
@ -77,6 +77,7 @@ export class List extends React.Component {
|
|||
renderRow={(item, previousItem) => this.props.renderRow(item, previousItem)}
|
||||
initialListSize={20}
|
||||
pageSize={20}
|
||||
testID='room-view-messages'
|
||||
{...scrollPersistTaps}
|
||||
/>);
|
||||
}
|
||||
|
|
|
@ -48,7 +48,10 @@ export default class ReactionPicker extends React.Component {
|
|||
animationIn='fadeIn'
|
||||
animationOut='fadeOut'
|
||||
>
|
||||
<View style={[styles.reactionPickerContainer, { width: width - margin, height: Math.min(width, height) - (margin * 2) }]}>
|
||||
<View
|
||||
style={[styles.reactionPickerContainer, { width: width - margin, height: Math.min(width, height) - (margin * 2) }]}
|
||||
testID='reaction-picker'
|
||||
>
|
||||
<EmojiPicker
|
||||
tabEmojiStyle={tabEmojiStyle}
|
||||
width={Math.min(width, height) - margin}
|
||||
|
|
|
@ -74,8 +74,8 @@ export default class RoomView extends LoggedView {
|
|||
this.onReactionPress = this.onReactionPress.bind(this);
|
||||
}
|
||||
|
||||
async componentDidMount() {
|
||||
await this.updateRoom();
|
||||
componentDidMount() {
|
||||
this.updateRoom();
|
||||
this.rooms.addListener(this.updateRoom);
|
||||
}
|
||||
shouldComponentUpdate(nextProps, nextState) {
|
||||
|
@ -197,7 +197,7 @@ export default class RoomView extends LoggedView {
|
|||
}
|
||||
render() {
|
||||
return (
|
||||
<View style={styles.container}>
|
||||
<View style={styles.container} testID='room-view'>
|
||||
<List
|
||||
key='room-view-messages'
|
||||
end={this.state.end}
|
||||
|
|
|
@ -121,7 +121,13 @@ export default class RoomsListHeaderView extends React.PureComponent {
|
|||
}
|
||||
|
||||
return (
|
||||
<View style={styles.left} accessible accessibilityLabel="Server's list" accessibilityTraits='button'>
|
||||
<View
|
||||
style={styles.left}
|
||||
accessible
|
||||
accessibilityLabel={`Connected to ${ this.props.baseUrl }. Tap to view servers list.`}
|
||||
accessibilityTraits='button'
|
||||
testID='rooms-list-view-sidebar'
|
||||
>
|
||||
<TouchableOpacity
|
||||
style={styles.headerButton}
|
||||
onPress={() => this.props.navigation.openDrawer()}
|
||||
|
@ -150,10 +156,15 @@ export default class RoomsListHeaderView extends React.PureComponent {
|
|||
|
||||
const t = title(offline, connecting, authenticating, logged);
|
||||
|
||||
const accessibilityLabel = `${ user.username }, ${ this.getUserStatusLabel() }, double tap to change status`;
|
||||
const accessibilityLabel = `${ user.username }, ${ this.getUserStatusLabel() }, tap to change status`;
|
||||
return (
|
||||
|
||||
<TouchableOpacity style={styles.titleContainer} onPress={() => this.showModal()} accessibilityLabel={accessibilityLabel} accessibilityTraits='header'>
|
||||
<TouchableOpacity
|
||||
style={styles.titleContainer}
|
||||
onPress={() => this.showModal()}
|
||||
accessibilityLabel={accessibilityLabel}
|
||||
accessibilityTraits='header'
|
||||
testID='rooms-list-view-user'
|
||||
>
|
||||
<Avatar
|
||||
text={user.username}
|
||||
size={24}
|
||||
|
@ -195,6 +206,7 @@ export default class RoomsListHeaderView extends React.PureComponent {
|
|||
onPress={() => this.createChannel()}
|
||||
accessibilityLabel='Create channel'
|
||||
accessibilityTraits='button'
|
||||
testID='rooms-list-view-create-channel'
|
||||
>
|
||||
<Icon
|
||||
name='ios-add'
|
||||
|
@ -215,6 +227,7 @@ export default class RoomsListHeaderView extends React.PureComponent {
|
|||
<TouchableOpacity
|
||||
style={styles.modalButton}
|
||||
onPress={() => this.onPressModalButton(status)}
|
||||
testID={`rooms-list-view-user-presence-${ status }`}
|
||||
>
|
||||
<View style={statusStyle} />
|
||||
<Text style={textStyle}>
|
||||
|
@ -251,7 +264,7 @@ export default class RoomsListHeaderView extends React.PureComponent {
|
|||
|
||||
render() {
|
||||
return (
|
||||
<View style={styles.header}>
|
||||
<View style={styles.header} testID='rooms-list-view-header'>
|
||||
{this.renderLeft()}
|
||||
{this.renderCenter()}
|
||||
{this.renderRight()}
|
||||
|
@ -262,6 +275,7 @@ export default class RoomsListHeaderView extends React.PureComponent {
|
|||
style={{ alignItems: 'center' }}
|
||||
onModalHide={() => this.hideModal()}
|
||||
onBackdropPress={() => this.hideModal()}
|
||||
testID='rooms-list-view-user-presence-modal'
|
||||
>
|
||||
<View style={styles.modal}>
|
||||
{this.renderModalButton('online')}
|
||||
|
|
|
@ -158,6 +158,7 @@ export default class RoomsListView extends LoggedView {
|
|||
blurOnSubmit
|
||||
autoCorrect={false}
|
||||
autoCapitalize='none'
|
||||
testID='rooms-list-view-search'
|
||||
/>
|
||||
</View>
|
||||
);
|
||||
|
@ -177,6 +178,7 @@ export default class RoomsListView extends LoggedView {
|
|||
type={item.t}
|
||||
baseUrl={this.props.Site_Url}
|
||||
onPress={() => this._onPressItem(item)}
|
||||
testID={`rooms-list-view-item-${ item.name }`}
|
||||
/>);
|
||||
}
|
||||
|
||||
|
@ -191,6 +193,7 @@ export default class RoomsListView extends LoggedView {
|
|||
enableEmptySections
|
||||
removeClippedSubviews
|
||||
keyboardShouldPersistTaps='always'
|
||||
testID='rooms-list-view-list'
|
||||
/>
|
||||
)
|
||||
|
||||
|
@ -203,7 +206,7 @@ export default class RoomsListView extends LoggedView {
|
|||
);
|
||||
|
||||
render = () => (
|
||||
<View style={styles.container}>
|
||||
<View style={styles.container} testID='rooms-list-view'>
|
||||
{this.renderList()}
|
||||
{Platform.OS === 'android' && this.renderCreateButtons()}
|
||||
</View>)
|
||||
|
|
|
@ -109,6 +109,7 @@ export default class SearchMessagesView extends LoggedView {
|
|||
return (
|
||||
<View
|
||||
style={styles.container}
|
||||
testID='search-messages-view'
|
||||
>
|
||||
<View style={styles.searchContainer}>
|
||||
<RCTextInput
|
||||
|
@ -116,6 +117,7 @@ export default class SearchMessagesView extends LoggedView {
|
|||
label='Search'
|
||||
onChangeText={this.onChangeSearch}
|
||||
placeholder='Search Messages'
|
||||
testID='search-message-view-input'
|
||||
/>
|
||||
<Markdown msg='You can search using RegExp. e.g. `/^text$/i`' />
|
||||
<View style={styles.divider} />
|
||||
|
|
|
@ -103,6 +103,7 @@ export default class SelectedUsersView extends LoggedView {
|
|||
onPress={() => params.nextAction()}
|
||||
accessibilityLabel='Submit'
|
||||
accessibilityTraits='button'
|
||||
testID='selected-users-view-submit'
|
||||
>
|
||||
<Icon
|
||||
name='ios-add'
|
||||
|
@ -229,6 +230,7 @@ export default class SelectedUsersView extends LoggedView {
|
|||
placeholder='Search'
|
||||
clearButtonMode='while-editing'
|
||||
blurOnSubmit
|
||||
testID='select-users-view-search'
|
||||
autoCorrect={false}
|
||||
autoCapitalize='none'
|
||||
/>
|
||||
|
@ -255,6 +257,7 @@ export default class SelectedUsersView extends LoggedView {
|
|||
key={item._id}
|
||||
style={styles.selectItemView}
|
||||
onPress={() => this._onPressSelectedItem(item)}
|
||||
testID={`selected-user-${ item.name }`}
|
||||
>
|
||||
<Avatar text={item.name} size={40} />
|
||||
<Text ellipsizeMode='tail' numberOfLines={1} style={{ fontSize: 10 }}>
|
||||
|
@ -273,6 +276,7 @@ export default class SelectedUsersView extends LoggedView {
|
|||
showLastMessage={false}
|
||||
avatarSize={30}
|
||||
statusStyle={styles.status}
|
||||
testID={`select-users-view-item-${ item.name }`}
|
||||
/>
|
||||
);
|
||||
renderList = () => (
|
||||
|
@ -300,7 +304,7 @@ export default class SelectedUsersView extends LoggedView {
|
|||
);
|
||||
};
|
||||
render = () => (
|
||||
<View style={styles.container}>
|
||||
<View style={styles.container} testID='select-users-view'>
|
||||
<SafeAreaView style={styles.safeAreaView}>
|
||||
{this.renderList()}
|
||||
{this.renderCreateButton()}
|
||||
|
|
|
@ -73,7 +73,7 @@ export default class SnippetedMessagesView extends LoggedView {
|
|||
}
|
||||
|
||||
renderEmpty = () => (
|
||||
<View style={styles.listEmptyContainer}>
|
||||
<View style={styles.listEmptyContainer} testID='snippeted-messages-view'>
|
||||
<Text>No snippeted messages</Text>
|
||||
</View>
|
||||
)
|
||||
|
@ -99,8 +99,10 @@ export default class SnippetedMessagesView extends LoggedView {
|
|||
}
|
||||
|
||||
return (
|
||||
[
|
||||
<FlatList
|
||||
key='snippet-messages-view-list'
|
||||
key='snippeted-messages-view-list'
|
||||
testID='snippeted-messages-view'
|
||||
data={messages}
|
||||
renderItem={this.renderItem}
|
||||
style={styles.list}
|
||||
|
@ -109,6 +111,7 @@ export default class SnippetedMessagesView extends LoggedView {
|
|||
ListHeaderComponent={loading && <RCActivityIndicator />}
|
||||
ListFooterComponent={loadingMore && <RCActivityIndicator />}
|
||||
/>
|
||||
]
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -97,7 +97,7 @@ export default class StarredMessagesView extends LoggedView {
|
|||
}
|
||||
|
||||
renderEmpty = () => (
|
||||
<View style={styles.listEmptyContainer}>
|
||||
<View style={styles.listEmptyContainer} testID='starred-messages-view'>
|
||||
<Text>No starred messages</Text>
|
||||
</View>
|
||||
)
|
||||
|
@ -126,6 +126,7 @@ export default class StarredMessagesView extends LoggedView {
|
|||
[
|
||||
<FlatList
|
||||
key='starred-messages-view-list'
|
||||
testID='starred-messages-view'
|
||||
data={messages}
|
||||
renderItem={this.renderItem}
|
||||
style={styles.list}
|
||||
|
|
|
@ -0,0 +1,50 @@
|
|||
const {
|
||||
device, expect, element, by, waitFor
|
||||
} = require('detox');
|
||||
const { takeScreenshot } = require('./helpers/screenshot');
|
||||
const data = require('./data');
|
||||
|
||||
describe('Add server', () => {
|
||||
before(async() => {
|
||||
await waitFor(element(by.id('new-server-view'))).toBeVisible().withTimeout(2000);
|
||||
});
|
||||
|
||||
describe('Render', async() => {
|
||||
it('should have add server screen', async() => {
|
||||
await expect(element(by.id('new-server-view'))).toBeVisible();
|
||||
});
|
||||
|
||||
it('should have server input', async() => {
|
||||
await expect(element(by.id('new-server-view-input'))).toBeVisible();
|
||||
});
|
||||
|
||||
it('should have submit button', async() => {
|
||||
await expect(element(by.id('new-server-view-button'))).toBeVisible();
|
||||
});
|
||||
|
||||
after(async() => {
|
||||
takeScreenshot();
|
||||
});
|
||||
});
|
||||
|
||||
describe('Usage', async() => {
|
||||
it('should insert "invalidtest" and get an invalid instance', async() => {
|
||||
await element(by.id('new-server-view-input')).replaceText('invalidtest');
|
||||
await waitFor(element(by.text(' is not a valid Rocket.Chat instance'))).toBeVisible().withTimeout(60000);
|
||||
await expect(element(by.text(' is not a valid Rocket.Chat instance'))).toBeVisible();
|
||||
});
|
||||
|
||||
it('should have a button to add a new server', async() => {
|
||||
await element(by.id('new-server-view-input')).replaceText(data.server);
|
||||
await waitFor(element(by.text(' is a valid Rocket.Chat instance'))).toBeVisible().withTimeout(60000);
|
||||
await expect(element(by.id('new-server-view-button'))).toBeVisible();
|
||||
await element(by.id('new-server-view-button')).tap();
|
||||
await waitFor(element(by.id('welcome-view'))).toBeVisible().withTimeout(60000);
|
||||
await expect(element(by.id('welcome-view'))).toBeVisible();
|
||||
});
|
||||
|
||||
afterEach(async() => {
|
||||
takeScreenshot();
|
||||
});
|
||||
});
|
||||
});
|
|
@ -0,0 +1,46 @@
|
|||
const {
|
||||
device, expect, element, by, waitFor
|
||||
} = require('detox');
|
||||
const { takeScreenshot } = require('./helpers/screenshot');
|
||||
|
||||
describe('Welcome screen', () => {
|
||||
describe('Render', async() => {
|
||||
it('should have welcome screen', async() => {
|
||||
await expect(element(by.id('welcome-view'))).toBeVisible();
|
||||
});
|
||||
|
||||
it('should have register button', async() => {
|
||||
await expect(element(by.id('welcome-view-register'))).toBeVisible();
|
||||
});
|
||||
|
||||
it('should have login button', async() => {
|
||||
await expect(element(by.id('welcome-view-login'))).toBeVisible();
|
||||
});
|
||||
|
||||
// TODO: oauth
|
||||
|
||||
after(async() => {
|
||||
takeScreenshot();
|
||||
});
|
||||
});
|
||||
|
||||
describe('Usage', async() => {
|
||||
it('should navigate to login', async() => {
|
||||
await element(by.id('welcome-view-login')).tap();
|
||||
await waitFor(element(by.id('login-view'))).toBeVisible().withTimeout(2000);
|
||||
await expect(element(by.id('login-view'))).toBeVisible();
|
||||
await element(by.id('close-modal-button')).tap();
|
||||
});
|
||||
|
||||
it('should navigate to register', async() => {
|
||||
await element(by.id('welcome-view-register')).tap();
|
||||
await waitFor(element(by.id('register-view'))).toBeVisible().withTimeout(2000);
|
||||
await expect(element(by.id('register-view'))).toBeVisible();
|
||||
await element(by.id('close-modal-button')).tap();
|
||||
});
|
||||
|
||||
afterEach(async() => {
|
||||
takeScreenshot();
|
||||
});
|
||||
});
|
||||
});
|
|
@ -0,0 +1,45 @@
|
|||
const {
|
||||
device, expect, element, by, waitFor
|
||||
} = require('detox');
|
||||
const { takeScreenshot } = require('./helpers/screenshot');
|
||||
const data = require('./data');
|
||||
|
||||
describe('Forgot password screen', () => {
|
||||
before(async() => {
|
||||
await element(by.id('welcome-view-login')).tap();
|
||||
await waitFor(element(by.id('login-view'))).toBeVisible().withTimeout(2000);
|
||||
await element(by.id('login-view-forgot-password')).tap();
|
||||
await waitFor(element(by.id('forgot-password-view'))).toBeVisible().withTimeout(2000);
|
||||
});
|
||||
|
||||
describe('Render', async() => {
|
||||
it('should have forgot password screen', async() => {
|
||||
await expect(element(by.id('forgot-password-view'))).toBeVisible();
|
||||
});
|
||||
|
||||
it('should have email input', async() => {
|
||||
await expect(element(by.id('forgot-password-view-email'))).toBeVisible();
|
||||
});
|
||||
|
||||
it('should have submit button', async() => {
|
||||
await expect(element(by.id('forgot-password-view-submit'))).toBeVisible();
|
||||
});
|
||||
|
||||
after(async() => {
|
||||
takeScreenshot();
|
||||
});
|
||||
});
|
||||
|
||||
describe('Usage', async() => {
|
||||
it('should reset password and navigate to login', async() => {
|
||||
await element(by.id('forgot-password-view-email')).replaceText(data.email);
|
||||
await element(by.id('forgot-password-view-submit')).tap();
|
||||
await waitFor(element(by.id('login-view'))).toBeVisible().withTimeout(60000);
|
||||
await expect(element(by.id('login-view'))).toBeVisible();
|
||||
});
|
||||
|
||||
afterEach(async() => {
|
||||
takeScreenshot();
|
||||
});
|
||||
});
|
||||
});
|
|
@ -0,0 +1,148 @@
|
|||
const {
|
||||
device, expect, element, by, waitFor
|
||||
} = require('detox');
|
||||
const { takeScreenshot } = require('./helpers/screenshot');
|
||||
const { logout } = require('./helpers/app');
|
||||
const data = require('./data');
|
||||
|
||||
async function navigateToRegister() {
|
||||
await waitFor(element(by.id('welcome-view'))).toBeVisible().withTimeout(2000);
|
||||
await element(by.id('welcome-view-register')).tap();
|
||||
await waitFor(element(by.id('register-view'))).toBeVisible().withTimeout(2000);
|
||||
}
|
||||
|
||||
describe('Create user screen', () => {
|
||||
before(async() => {
|
||||
await device.reloadReactNative();
|
||||
await navigateToRegister();
|
||||
});
|
||||
|
||||
describe('Render', () => {
|
||||
it('should have create user screen', async() => {
|
||||
await expect(element(by.id('register-view'))).toBeVisible();
|
||||
});
|
||||
|
||||
it('should have name input', async() => {
|
||||
await expect(element(by.id('register-view-name'))).toBeVisible();
|
||||
});
|
||||
|
||||
it('should have email input', async() => {
|
||||
await expect(element(by.id('register-view-email'))).toBeVisible();
|
||||
});
|
||||
|
||||
it('should have password input', async() => {
|
||||
await expect(element(by.id('register-view-password'))).toBeVisible();
|
||||
});
|
||||
|
||||
it('should have show password icon', async() => {
|
||||
await expect(element(by.id('register-view-password-icon-right'))).toBeVisible();
|
||||
});
|
||||
|
||||
it('should have repeat password input', async() => {
|
||||
await expect(element(by.id('register-view-repeat-password'))).toBeVisible();
|
||||
});
|
||||
|
||||
it('should have repeat password icon', async() => {
|
||||
await expect(element(by.id('register-view-repeat-password-icon-right'))).toBeVisible();
|
||||
});
|
||||
|
||||
it('should have submit button', async() => {
|
||||
await expect(element(by.id('register-view-submit'))).toBeVisible();
|
||||
});
|
||||
|
||||
it('should have close modal', async() => {
|
||||
await expect(element(by.id('close-modal-button'))).toBeVisible();
|
||||
});
|
||||
|
||||
after(async() => {
|
||||
takeScreenshot();
|
||||
});
|
||||
});
|
||||
|
||||
describe('Usage', () => {
|
||||
it('should navigate to welcome', async() => {
|
||||
await element(by.id('close-modal-button')).tap();
|
||||
await waitFor(element(by.id('welcome-view'))).toBeVisible().withTimeout(2000);
|
||||
await expect(element(by.id('welcome-view'))).toBeVisible();
|
||||
});
|
||||
|
||||
it('should submit empty form and raise error', async() => {
|
||||
await navigateToRegister();
|
||||
await element(by.id('register-view-submit')).tap();
|
||||
await waitFor(element(by.text('Some field is invalid or empty'))).toBeVisible().withTimeout(10000);
|
||||
await expect(element(by.text('Some field is invalid or empty'))).toBeVisible();
|
||||
});
|
||||
|
||||
it('should submit different passwords and raise error', async() => {
|
||||
await element(by.id('register-view-name')).replaceText(data.user);
|
||||
await element(by.id('register-view-email')).replaceText(data.email);
|
||||
await element(by.id('register-view-password')).replaceText('abc');
|
||||
await element(by.id('register-view-repeat-password')).replaceText('xyz');
|
||||
await element(by.id('register-view-submit')).tap();
|
||||
await waitFor(element(by.text('Some field is invalid or empty'))).toBeVisible().withTimeout(10000);
|
||||
await expect(element(by.text('Some field is invalid or empty'))).toBeVisible();
|
||||
});
|
||||
|
||||
it('should submit invalid email and raise error', async() => {
|
||||
await element(by.id('register-view-name')).replaceText(data.user);
|
||||
await element(by.id('register-view-email')).replaceText('invalidemail');
|
||||
await element(by.id('register-view-password')).replaceText(data.password);
|
||||
await element(by.id('register-view-repeat-password')).replaceText(data.password);
|
||||
await element(by.id('register-view-submit')).tap();
|
||||
await waitFor(element(by.id('register-view-error'))).toBeVisible().withTimeout(60000);
|
||||
await expect(element(by.id('register-view-error'))).toBeVisible();
|
||||
await expect(element(by.id('register-view-error'))).toHaveText('Invalid email invalidemail');
|
||||
});
|
||||
|
||||
it('should submit email already taken and raise error', async() => {
|
||||
await element(by.id('register-view-name')).replaceText(data.user);
|
||||
await element(by.id('register-view-email')).replaceText('diego.mello@rocket.chat');
|
||||
await element(by.id('register-view-password')).replaceText(data.password);
|
||||
await element(by.id('register-view-repeat-password')).replaceText(data.password);
|
||||
await element(by.id('register-view-submit')).tap();
|
||||
await waitFor(element(by.id('register-view-error'))).toBeVisible().withTimeout(60000);
|
||||
await expect(element(by.id('register-view-error'))).toBeVisible();
|
||||
await expect(element(by.id('register-view-error'))).toHaveText('Email already exists.');
|
||||
});
|
||||
|
||||
it('should complete first part of register', async() => {
|
||||
await element(by.id('register-view-name')).replaceText(data.user);
|
||||
await element(by.id('register-view-email')).replaceText(data.email);
|
||||
await element(by.id('register-view-password')).replaceText(data.password);
|
||||
await element(by.id('register-view-repeat-password')).replaceText(data.password);
|
||||
await element(by.id('register-view-submit')).tap();
|
||||
await waitFor(element(by.id('register-view-username'))).toBeVisible().withTimeout(60000);
|
||||
await expect(element(by.id('register-view-username'))).toBeVisible();
|
||||
});
|
||||
|
||||
it('should submit empty username and raise error', async() => {
|
||||
await element(by.id('register-view-submit-username')).tap();
|
||||
await waitFor(element(by.text('Username is empty'))).toBeVisible().withTimeout(10000);
|
||||
await expect(element(by.text('Username is empty'))).toBeVisible();
|
||||
});
|
||||
|
||||
it('should submit already taken username and raise error', async() => {
|
||||
await element(by.id('register-view-username')).replaceText('diego.mello');
|
||||
await element(by.id('register-view-submit-username')).tap();
|
||||
await waitFor(element(by.id('register-view-error'))).toBeVisible().withTimeout(60000);
|
||||
await expect(element(by.id('register-view-error'))).toBeVisible();
|
||||
});
|
||||
|
||||
it('should finish register', async() => {
|
||||
await element(by.id('register-view-username')).replaceText(data.user);
|
||||
await element(by.id('register-view-submit-username')).tap();
|
||||
await waitFor(element(by.id('rooms-list-view'))).toBeVisible().withTimeout(60000);
|
||||
await expect(element(by.id('rooms-list-view'))).toBeVisible();
|
||||
});
|
||||
|
||||
// TODO: terms and privacy
|
||||
|
||||
afterEach(async() => {
|
||||
takeScreenshot();
|
||||
});
|
||||
|
||||
after(async() => {
|
||||
await logout();
|
||||
});
|
||||
});
|
||||
});
|
|
@ -0,0 +1,92 @@
|
|||
const {
|
||||
device, expect, element, by, waitFor
|
||||
} = require('detox');
|
||||
const { takeScreenshot } = require('./helpers/screenshot');
|
||||
const { navigateToLogin } = require('./helpers/app');
|
||||
const data = require('./data');
|
||||
|
||||
describe('Login screen', () => {
|
||||
before(async() => {
|
||||
await navigateToLogin();
|
||||
});
|
||||
|
||||
describe('Render', () => {
|
||||
it('should have login screen', async() => {
|
||||
await expect(element(by.id('login-view'))).toBeVisible();
|
||||
});
|
||||
|
||||
it('should have email input', async() => {
|
||||
await expect(element(by.id('login-view-email'))).toBeVisible();
|
||||
});
|
||||
|
||||
it('should have password input', async() => {
|
||||
await expect(element(by.id('login-view-password'))).toBeVisible();
|
||||
});
|
||||
|
||||
it('should have show password icon', async() => {
|
||||
await expect(element(by.id('login-view-password-icon-right'))).toBeVisible();
|
||||
});
|
||||
|
||||
it('should have submit button', async() => {
|
||||
await expect(element(by.id('login-view-submit'))).toBeVisible();
|
||||
});
|
||||
|
||||
it('should have register button', async() => {
|
||||
await expect(element(by.id('login-view-register'))).toBeVisible();
|
||||
});
|
||||
|
||||
it('should have forgot password button', async() => {
|
||||
await expect(element(by.id('login-view-forgot-password'))).toBeVisible();
|
||||
});
|
||||
|
||||
it('should have close modal button', async() => {
|
||||
await expect(element(by.id('close-modal-button'))).toBeVisible();
|
||||
});
|
||||
|
||||
after(async() => {
|
||||
takeScreenshot();
|
||||
});
|
||||
});
|
||||
|
||||
describe('Usage', () => {
|
||||
it('should navigate to register', async() => {
|
||||
await element(by.id('login-view-register')).tap();
|
||||
await waitFor(element(by.id('register-view'))).toBeVisible().withTimeout(2000);
|
||||
await expect(element(by.id('register-view'))).toBeVisible();
|
||||
await element(by.id('close-modal-button').withAncestor(by.id('register-view'))).tap();
|
||||
});
|
||||
|
||||
it('should navigate to forgot password', async() => {
|
||||
await element(by.id('login-view-forgot-password')).tap();
|
||||
await waitFor(element(by.id('forgot-password-view'))).toBeVisible().withTimeout(2000);
|
||||
await expect(element(by.id('forgot-password-view'))).toBeVisible();
|
||||
await element(by.id('header-back')).tap();
|
||||
});
|
||||
|
||||
it('should navigate to welcome', async() => {
|
||||
await element(by.id('close-modal-button')).tap();
|
||||
await waitFor(element(by.id('welcome-view'))).toBeVisible().withTimeout(2000);
|
||||
await expect(element(by.id('welcome-view'))).toBeVisible();
|
||||
await navigateToLogin();
|
||||
});
|
||||
|
||||
it('should insert wrong password and get error', async() => {
|
||||
await element(by.id('login-view-email')).replaceText(data.user);
|
||||
await element(by.id('login-view-password')).replaceText('error');
|
||||
await element(by.id('login-view-submit')).tap();
|
||||
await waitFor(element(by.text('User or Password incorrect'))).toBeVisible().withTimeout(10000);
|
||||
await expect(element(by.text('User or Password incorrect'))).toBeVisible();
|
||||
});
|
||||
|
||||
it('should login with success', async() => {
|
||||
await element(by.id('login-view-password')).replaceText(data.password);
|
||||
await element(by.id('login-view-submit')).tap();
|
||||
await waitFor(element(by.id('rooms-list-view'))).toBeVisible().withTimeout(60000);
|
||||
await expect(element(by.id('rooms-list-view'))).toBeVisible();
|
||||
});
|
||||
|
||||
afterEach(async() => {
|
||||
takeScreenshot();
|
||||
});
|
||||
});
|
||||
});
|
|
@ -0,0 +1,112 @@
|
|||
const {
|
||||
device, expect, element, by, waitFor
|
||||
} = require('detox');
|
||||
const { takeScreenshot } = require('./helpers/screenshot');
|
||||
const { login, navigateToLogin } = require('./helpers/app');
|
||||
const data = require('./data');
|
||||
|
||||
describe('Rooms list screen', () => {
|
||||
before(async() => {
|
||||
await device.reloadReactNative(); // TODO: remove this after fix logout subscription
|
||||
});
|
||||
|
||||
describe('Render', async() => {
|
||||
it('should have rooms list screen', async() => {
|
||||
await expect(element(by.id('rooms-list-view'))).toBeVisible();
|
||||
});
|
||||
|
||||
it('should have rooms list', async() => {
|
||||
await expect(element(by.id('rooms-list-view-list'))).toBeVisible();
|
||||
});
|
||||
|
||||
it('should have room item', async() => {
|
||||
await expect(element(by.id('rooms-list-view-item-general'))).toExist();
|
||||
});
|
||||
|
||||
// Render - Header
|
||||
describe('Header', async() => {
|
||||
it('should have header', async() => {
|
||||
await expect(element(by.id('rooms-list-view-header'))).toBeVisible();
|
||||
});
|
||||
|
||||
it('should have create channel button', async() => {
|
||||
await expect(element(by.id('rooms-list-view-create-channel'))).toBeVisible();
|
||||
});
|
||||
|
||||
it('should have user', async() => {
|
||||
await expect(element(by.id('rooms-list-view-user'))).toBeVisible();
|
||||
});
|
||||
|
||||
it('should have sidebar button', async() => {
|
||||
await expect(element(by.id('rooms-list-view-sidebar'))).toBeVisible();
|
||||
await expect(element(by.id('rooms-list-view-sidebar'))).toHaveLabel(`Connected to ${ data.server }. Tap to view servers list.`);
|
||||
});
|
||||
});
|
||||
|
||||
after(async() => {
|
||||
takeScreenshot();
|
||||
});
|
||||
});
|
||||
|
||||
describe('Usage', async() => {
|
||||
it('should change user presence modal', async() => {
|
||||
await waitFor(element(by.label(`${ data.user }, Online, tap to change status`))).toBeVisible().withTimeout(60000);
|
||||
await expect(element(by.label(`${ data.user }, Online, tap to change status`))).toBeVisible();
|
||||
await element(by.id('rooms-list-view-user')).tap();
|
||||
await waitFor(element(by.id('rooms-list-view-user-presence-modal'))).toBeVisible().withTimeout(2000);
|
||||
await expect(element(by.id('rooms-list-view-user-presence-modal'))).toBeVisible();
|
||||
await element(by.id('rooms-list-view-user-presence-busy')).tap();
|
||||
await waitFor(element(by.id('rooms-list-view-user-presence-modal'))).toBeNotVisible().withTimeout(10000);
|
||||
await expect(element(by.id('rooms-list-view-user-presence-modal'))).toBeNotVisible();
|
||||
await waitFor(element(by.label(`${ data.user }, Busy, tap to change status`))).toBeVisible().withTimeout(60000);
|
||||
await expect(element(by.label(`${ data.user }, Busy, tap to change status`))).toBeVisible();
|
||||
});
|
||||
|
||||
it('should search room and navigate', async() => {
|
||||
await element(by.id('rooms-list-view-list')).swipe('down');
|
||||
await waitFor(element(by.id('rooms-list-view-search'))).toBeVisible().withTimeout(2000);
|
||||
await expect(element(by.id('rooms-list-view-search'))).toBeVisible();
|
||||
await element(by.id('rooms-list-view-search')).replaceText('rocket.cat');
|
||||
await waitFor(element(by.id('rooms-list-view-item-rocket.cat'))).toBeVisible().withTimeout(10000);
|
||||
await expect(element(by.id('rooms-list-view-item-rocket.cat'))).toBeVisible();
|
||||
await element(by.id('rooms-list-view-item-rocket.cat')).tap();
|
||||
await waitFor(element(by.id('room-view'))).toBeVisible().withTimeout(10000);
|
||||
await expect(element(by.id('room-view'))).toBeVisible();
|
||||
await waitFor(element(by.id('room-view-title'))).toHaveText('rocket.cat').withTimeout(60000);
|
||||
await expect(element(by.id('room-view-title'))).toHaveText('rocket.cat');
|
||||
await element(by.id('header-back')).atIndex(0).tap();
|
||||
await waitFor(element(by.id('rooms-list-view'))).toBeVisible().withTimeout(2000);
|
||||
await expect(element(by.id('rooms-list-view'))).toBeVisible();
|
||||
await waitFor(element(by.id('rooms-list-view-item-rocket.cat'))).toBeVisible().withTimeout(60000);
|
||||
await expect(element(by.id('rooms-list-view-item-rocket.cat'))).toBeVisible();
|
||||
});
|
||||
|
||||
// Usage - Sidebar
|
||||
describe('Sidebar', async() => {
|
||||
it('should navigate to add server', async() => {
|
||||
await element(by.id('rooms-list-view-sidebar')).tap();
|
||||
await waitFor(element(by.id('sidebar'))).toBeVisible().withTimeout(2000);
|
||||
await element(by.id('sidebar-add-server')).tap();
|
||||
await waitFor(element(by.id('new-server-view'))).toBeVisible().withTimeout(2000);
|
||||
await expect(element(by.id('new-server-view'))).toBeVisible();
|
||||
await element(by.id('header-back')).atIndex(0).tap();
|
||||
await waitFor(element(by.id('rooms-list-view'))).toBeVisible().withTimeout(2000);
|
||||
await expect(element(by.id('rooms-list-view'))).toBeVisible();
|
||||
});
|
||||
|
||||
it('should logout', async() => {
|
||||
await element(by.id('rooms-list-view-sidebar')).tap();
|
||||
await waitFor(element(by.id('sidebar'))).toBeVisible().withTimeout(2000);
|
||||
await element(by.id('sidebar-logout')).tap();
|
||||
await waitFor(element(by.id('welcome-view'))).toBeVisible().withTimeout(60000);
|
||||
await expect(element(by.id('welcome-view'))).toBeVisible();
|
||||
await navigateToLogin();
|
||||
await login();
|
||||
});
|
||||
});
|
||||
|
||||
afterEach(async() => {
|
||||
takeScreenshot();
|
||||
});
|
||||
});
|
||||
});
|
|
@ -0,0 +1,109 @@
|
|||
const {
|
||||
device, expect, element, by, waitFor
|
||||
} = require('detox');
|
||||
const { takeScreenshot } = require('./helpers/screenshot');
|
||||
const data = require('./data');
|
||||
|
||||
describe('Create room screen', () => {
|
||||
before(async() => {
|
||||
await device.reloadReactNative(); // TODO: remove this after fix logout subscription
|
||||
await element(by.id('rooms-list-view-create-channel')).tap();
|
||||
await waitFor(element(by.id('select-users-view'))).toBeVisible().withTimeout(2000);
|
||||
});
|
||||
|
||||
describe('Render', async() => {
|
||||
it('should have select users screen', async() => {
|
||||
await expect(element(by.id('select-users-view'))).toBeVisible();
|
||||
});
|
||||
|
||||
it('should have search input', async() => {
|
||||
await expect(element(by.id('select-users-view-search'))).toBeVisible();
|
||||
});
|
||||
|
||||
after(async() => {
|
||||
takeScreenshot();
|
||||
});
|
||||
});
|
||||
|
||||
describe('Usage', async() => {
|
||||
it('should back to rooms list', async() => {
|
||||
await element(by.id('header-back')).tap();
|
||||
await waitFor(element(by.id('rooms-list-view'))).toBeVisible().withTimeout(2000);
|
||||
await expect(element(by.id('rooms-list-view'))).toBeVisible();
|
||||
await element(by.id('rooms-list-view-create-channel')).tap();
|
||||
await waitFor(element(by.id('select-users-view'))).toBeVisible().withTimeout(2000);
|
||||
});
|
||||
|
||||
it('should search users', async() => {
|
||||
await element(by.id('select-users-view-search')).replaceText('rocket.cat');
|
||||
await waitFor(element(by.id(`select-users-view-item-rocket.cat`))).toBeVisible().withTimeout(10000);
|
||||
await expect(element(by.id(`select-users-view-item-rocket.cat`))).toBeVisible();
|
||||
});
|
||||
|
||||
it('should select/unselect user', async() => {
|
||||
await element(by.id('select-users-view-item-rocket.cat')).tap();
|
||||
await waitFor(element(by.id('selected-user-rocket.cat'))).toBeVisible().withTimeout(5000);
|
||||
await expect(element(by.id('selected-user-rocket.cat'))).toBeVisible();
|
||||
await expect(element(by.id('selected-users-view-submit'))).toBeVisible();
|
||||
await element(by.id('selected-user-rocket.cat')).tap();
|
||||
await waitFor(element(by.id('selected-user-rocket.cat'))).toBeNotVisible().withTimeout(5000);
|
||||
await expect(element(by.id('selected-user-rocket.cat'))).toBeNotVisible();
|
||||
await expect(element(by.id('selected-users-view-submit'))).toBeNotVisible();
|
||||
await element(by.id('select-users-view-item-rocket.cat')).tap();
|
||||
await waitFor(element(by.id('selected-user-rocket.cat'))).toBeVisible().withTimeout(5000);
|
||||
});
|
||||
|
||||
it('should navigate to create channel view', async() => {
|
||||
await element(by.id('selected-users-view-submit')).tap();
|
||||
await waitFor(element(by.id('create-channel-view'))).toBeVisible().withTimeout(5000);
|
||||
await expect(element(by.id('create-channel-view'))).toBeVisible();
|
||||
await expect(element(by.id('create-channel-name'))).toBeVisible();
|
||||
await expect(element(by.id('create-channel-type'))).toBeVisible();
|
||||
await expect(element(by.id('create-channel-submit'))).toBeVisible();
|
||||
});
|
||||
|
||||
it('should get invalid room', async() => {
|
||||
await element(by.id('create-channel-name')).replaceText('general');
|
||||
await element(by.id('create-channel-submit')).tap();
|
||||
await waitFor(element(by.id('create-channel-error'))).toBeVisible().withTimeout(60000);
|
||||
await expect(element(by.id('create-channel-error'))).toBeVisible();
|
||||
});
|
||||
|
||||
it('should create private room', async() => {
|
||||
await element(by.id('create-channel-name')).replaceText(`private${ data.random }`);
|
||||
await element(by.id('create-channel-type')).tap();
|
||||
await element(by.id('create-channel-submit')).tap();
|
||||
await waitFor(element(by.id('room-view'))).toBeVisible().withTimeout(60000);
|
||||
await expect(element(by.id('room-view'))).toBeVisible();
|
||||
await waitFor(element(by.id('room-view-title'))).toHaveText(`private${ data.random }`).withTimeout(60000);
|
||||
await expect(element(by.id('room-view-title'))).toHaveText(`private${ data.random }`);
|
||||
await element(by.id('header-back')).tap();
|
||||
await waitFor(element(by.id('rooms-list-view'))).toBeVisible().withTimeout(2000);
|
||||
await waitFor(element(by.id(`rooms-list-view-item-private${ data.random }`))).toBeVisible().withTimeout(60000);
|
||||
await expect(element(by.id(`rooms-list-view-item-private${ data.random }`))).toBeVisible();
|
||||
});
|
||||
|
||||
it('should create public room', async() => {
|
||||
await element(by.id('rooms-list-view-create-channel')).tap();
|
||||
await waitFor(element(by.id('select-users-view'))).toBeVisible().withTimeout(2000);
|
||||
await element(by.id('select-users-view-item-rocket.cat')).tap();
|
||||
await waitFor(element(by.id('selected-user-rocket.cat'))).toBeVisible().withTimeout(5000);
|
||||
await element(by.id('selected-users-view-submit')).tap();
|
||||
await waitFor(element(by.id('create-channel-view'))).toBeVisible().withTimeout(5000);
|
||||
await element(by.id('create-channel-name')).replaceText(`public${ data.random }`);
|
||||
await element(by.id('create-channel-submit')).tap();
|
||||
await waitFor(element(by.id('room-view'))).toBeVisible().withTimeout(60000);
|
||||
await expect(element(by.id('room-view'))).toBeVisible();
|
||||
await waitFor(element(by.id('room-view-title'))).toHaveText(`public${ data.random }`).withTimeout(60000);
|
||||
await expect(element(by.id('room-view-title'))).toHaveText(`public${ data.random }`);
|
||||
await element(by.id('header-back')).tap();
|
||||
await waitFor(element(by.id('rooms-list-view'))).toBeVisible().withTimeout(2000);
|
||||
await waitFor(element(by.id(`rooms-list-view-item-public${ data.random }`))).toBeVisible().withTimeout(60000);
|
||||
await expect(element(by.id(`rooms-list-view-item-public${ data.random }`))).toBeVisible();
|
||||
});
|
||||
|
||||
afterEach(async() => {
|
||||
takeScreenshot();
|
||||
});
|
||||
});
|
||||
});
|
|
@ -0,0 +1,318 @@
|
|||
const {
|
||||
device, expect, element, by, waitFor
|
||||
} = require('detox');
|
||||
const { takeScreenshot } = require('./helpers/screenshot');
|
||||
const data = require('./data');
|
||||
|
||||
async function mockMessage(message) {
|
||||
await element(by.id('messagebox-input')).tap();
|
||||
await element(by.id('messagebox-input')).typeText(`${ data.random }${ message }`);
|
||||
await element(by.id('messagebox-send-message')).tap();
|
||||
await waitFor(element(by.text(`${ data.random }${ message }`))).toBeVisible().withTimeout(60000);
|
||||
};
|
||||
|
||||
async function navigateToRoom() {
|
||||
await waitFor(element(by.id(`rooms-list-view-item-private${ data.random }`))).toBeVisible().withTimeout(60000);
|
||||
await element(by.id(`rooms-list-view-item-private${ data.random }`)).tap();
|
||||
await waitFor(element(by.id('room-view'))).toBeVisible().withTimeout(5000);
|
||||
}
|
||||
|
||||
describe('Room screen', () => {
|
||||
before(async() => {
|
||||
await navigateToRoom();
|
||||
});
|
||||
|
||||
describe('Render', async() => {
|
||||
it('should have room screen', async() => {
|
||||
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
|
||||
describe('Header', async() => {
|
||||
it('should have room header', async() => {
|
||||
await expect(element(by.id('room-view-header'))).toBeVisible();
|
||||
});
|
||||
|
||||
it('should have back button', async() => {
|
||||
await expect(element(by.id('header-back'))).toBeVisible();
|
||||
});
|
||||
|
||||
it('should have title', async() => {
|
||||
await expect(element(by.id('room-view-header-title'))).toBeVisible();
|
||||
await expect(element(by.id('room-view-title'))).toHaveText(`private${ data.random }`);
|
||||
});
|
||||
|
||||
it('should have star button', async() => {
|
||||
await expect(element(by.id('room-view-header-star'))).toBeVisible();
|
||||
});
|
||||
|
||||
it('should have actions button ', async() => {
|
||||
await expect(element(by.id('room-view-header-actions'))).toBeVisible();
|
||||
});
|
||||
});
|
||||
|
||||
// Render - Messagebox
|
||||
describe('Messagebox', async() => {
|
||||
it('should have messagebox', async() => {
|
||||
await expect(element(by.id('messagebox'))).toBeVisible();
|
||||
});
|
||||
|
||||
it('should have open emoji button', async() => {
|
||||
await expect(element(by.id('messagebox-open-emoji'))).toBeVisible();
|
||||
});
|
||||
|
||||
it('should have message input', async() => {
|
||||
await expect(element(by.id('messagebox-input'))).toBeVisible();
|
||||
});
|
||||
|
||||
it('should have audio button', async() => {
|
||||
await expect(element(by.id('messagebox-send-audio'))).toBeVisible();
|
||||
});
|
||||
|
||||
it('should have actions button', async() => {
|
||||
await expect(element(by.id('messagebox-actions'))).toBeVisible();
|
||||
});
|
||||
});
|
||||
|
||||
after(async() => {
|
||||
takeScreenshot();
|
||||
});
|
||||
});
|
||||
|
||||
describe('Usage', async() => {
|
||||
describe('Header', async() => {
|
||||
it('should back to rooms list', async() => {
|
||||
await element(by.id('header-back')).tap();
|
||||
await waitFor(element(by.id('rooms-list-view'))).toBeVisible().withTimeout(2000);
|
||||
await expect(element(by.id('rooms-list-view'))).toBeVisible();
|
||||
await navigateToRoom();
|
||||
});
|
||||
|
||||
it('should tap on title and navigate to room info', async() => {
|
||||
await element(by.id('room-view-header-title')).tap();
|
||||
await waitFor(element(by.id('room-info-view'))).toBeVisible().withTimeout(2000);
|
||||
await expect(element(by.id('room-info-view'))).toBeVisible();
|
||||
await element(by.id('header-back')).atIndex(0).tap();
|
||||
await waitFor(element(by.id('rooms-list-view'))).toBeVisible().withTimeout(2000);
|
||||
});
|
||||
|
||||
it('should tap on more and navigate to room actions', async() => {
|
||||
await element(by.id('room-view-header-actions')).tap();
|
||||
await waitFor(element(by.id('room-actions-view'))).toBeVisible().withTimeout(2000);
|
||||
await expect(element(by.id('room-actions-view'))).toBeVisible();
|
||||
await element(by.id('header-back')).atIndex(0).tap();
|
||||
await waitFor(element(by.id('rooms-list-view'))).toBeVisible().withTimeout(2000);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Messagebox', async() => {
|
||||
it('should send message', async() => {
|
||||
await mockMessage('message');
|
||||
await waitFor(element(by.text(`${ data.random }message`))).toBeVisible().withTimeout(60000);
|
||||
await expect(element(by.text(`${ data.random }message`))).toBeVisible();
|
||||
});
|
||||
|
||||
it('should show/hide emoji keyboard', async() => {
|
||||
await element(by.id('messagebox-open-emoji')).tap();
|
||||
await waitFor(element(by.id('messagebox-keyboard-emoji'))).toBeVisible().withTimeout(10000);
|
||||
await expect(element(by.id('messagebox-keyboard-emoji'))).toBeVisible();
|
||||
await expect(element(by.id('messagebox-close-emoji'))).toBeVisible();
|
||||
await expect(element(by.id('messagebox-open-emoji'))).toBeNotVisible();
|
||||
await element(by.id('messagebox-close-emoji')).tap();
|
||||
await waitFor(element(by.id('messagebox-keyboard-emoji'))).toBeNotVisible().withTimeout(10000);
|
||||
await expect(element(by.id('messagebox-keyboard-emoji'))).toBeNotVisible();
|
||||
await expect(element(by.id('messagebox-close-emoji'))).toBeNotVisible();
|
||||
await expect(element(by.id('messagebox-open-emoji'))).toBeVisible();
|
||||
});
|
||||
|
||||
it('should show/hide emoji autocomplete', async() => {
|
||||
await element(by.id('messagebox-input')).tap();
|
||||
await element(by.id('messagebox-input')).replaceText(':');
|
||||
await element(by.id('messagebox-input')).typeText('joy'); // workaround for number keyboard
|
||||
await waitFor(element(by.id('messagebox-container'))).toBeVisible().withTimeout(10000);
|
||||
await expect(element(by.id('messagebox-container'))).toBeVisible();
|
||||
await element(by.id('messagebox-input')).clearText();
|
||||
await waitFor(element(by.id('messagebox-container'))).toBeNotVisible().withTimeout(10000);
|
||||
await expect(element(by.id('messagebox-container'))).toBeNotVisible();
|
||||
});
|
||||
|
||||
it('should show and tap on emoji autocomplete', async() => {
|
||||
await element(by.id('messagebox-input')).tap();
|
||||
await element(by.id('messagebox-input')).replaceText(':');
|
||||
await element(by.id('messagebox-input')).typeText('joy'); // workaround for number keyboard
|
||||
await waitFor(element(by.id('messagebox-container'))).toBeVisible().withTimeout(10000);
|
||||
await expect(element(by.id('messagebox-container'))).toBeVisible();
|
||||
await element(by.id('mention-item-joy')).tap();
|
||||
await expect(element(by.id('messagebox-input'))).toHaveText(':joy: ');
|
||||
await element(by.id('messagebox-input')).clearText();
|
||||
});
|
||||
|
||||
it('should show and tap on user autocomplete and send mention', async() => {
|
||||
await element(by.id('messagebox-input')).tap();
|
||||
await element(by.id('messagebox-input')).typeText(`@${ data.user }`);
|
||||
await waitFor(element(by.id('messagebox-container'))).toBeVisible().withTimeout(60000);
|
||||
await expect(element(by.id('messagebox-container'))).toBeVisible();
|
||||
await element(by.id(`mention-item-${ data.user }`)).tap();
|
||||
await expect(element(by.id('messagebox-input'))).toHaveText(`@${ data.user } `);
|
||||
await element(by.id('messagebox-input')).tap();
|
||||
await element(by.id('messagebox-input')).typeText('test');
|
||||
await element(by.id('messagebox-send-message')).tap();
|
||||
await waitFor(element(by.text(`@${ data.user } test`))).toBeVisible().withTimeout(60000);
|
||||
});
|
||||
|
||||
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 waitFor(element(by.id('messagebox-container'))).toBeVisible().withTimeout(60000);
|
||||
await expect(element(by.id('messagebox-container'))).toBeVisible();
|
||||
await element(by.id('mention-item-general')).tap();
|
||||
await expect(element(by.id('messagebox-input'))).toHaveText('#general ');
|
||||
await element(by.id('messagebox-input')).clearText();
|
||||
});
|
||||
});
|
||||
|
||||
describe('Message', async() => {
|
||||
before(async() => {
|
||||
await mockMessage('reply');
|
||||
await mockMessage('edit');
|
||||
await mockMessage('quote');
|
||||
});
|
||||
|
||||
it('should show message actions', async() => {
|
||||
await element(by.text(`${ data.random }message`)).longPress();
|
||||
await waitFor(element(by.text('Messages actions'))).toBeVisible().withTimeout(5000);
|
||||
await expect(element(by.text('Messages actions'))).toBeVisible();
|
||||
await element(by.text('Cancel')).tap();
|
||||
await waitFor(element(by.text('Cancel'))).toBeNotVisible().withTimeout(2000);
|
||||
});
|
||||
|
||||
it('should reply message', async() => {
|
||||
await element(by.text(`${ data.random }reply`)).longPress();
|
||||
await waitFor(element(by.text('Messages actions'))).toBeVisible().withTimeout(5000);
|
||||
await expect(element(by.text('Messages actions'))).toBeVisible();
|
||||
await element(by.text('Reply')).tap();
|
||||
await element(by.id('messagebox-input')).typeText('replied');
|
||||
await element(by.id('messagebox-send-message')).tap();
|
||||
// TODO: test if reply was sent
|
||||
});
|
||||
|
||||
it('should edit message', async() => {
|
||||
await element(by.text(`${ data.random }edit`)).longPress();
|
||||
await waitFor(element(by.text('Messages actions'))).toBeVisible().withTimeout(5000);
|
||||
await expect(element(by.text('Messages actions'))).toBeVisible();
|
||||
await element(by.text('Edit')).tap();
|
||||
await element(by.id('messagebox-input')).typeText('ed');
|
||||
await element(by.id('messagebox-send-message')).tap();
|
||||
await waitFor(element(by.text(`${ data.random }edited`))).toBeVisible().withTimeout(60000);
|
||||
await expect(element(by.text(`${ data.random }edited`))).toBeVisible();
|
||||
});
|
||||
|
||||
it('should copy permalink', async() => {
|
||||
await element(by.text(`${ data.random }message`)).longPress();
|
||||
await waitFor(element(by.text('Messages actions'))).toBeVisible().withTimeout(5000);
|
||||
await expect(element(by.text('Messages actions'))).toBeVisible();
|
||||
await element(by.text('Copy Permalink')).tap();
|
||||
await expect(element(by.text('Permalink copied to clipboard!'))).toBeVisible();
|
||||
await waitFor(element(by.text('Permalink copied to clipboard!'))).toBeNotVisible().withTimeout(5000);
|
||||
|
||||
// TODO: test clipboard
|
||||
});
|
||||
|
||||
it('should copy message', async() => {
|
||||
await element(by.text(`${ data.random }message`)).longPress();
|
||||
await waitFor(element(by.text('Messages actions'))).toBeVisible().withTimeout(5000);
|
||||
await expect(element(by.text('Messages actions'))).toBeVisible();
|
||||
await element(by.text('Copy Message')).tap();
|
||||
await expect(element(by.text('Copied to clipboard!'))).toBeVisible();
|
||||
await waitFor(element(by.text('Copied to clipboard!'))).toBeNotVisible().withTimeout(5000);
|
||||
// TODO: test clipboard
|
||||
});
|
||||
|
||||
it('should quote message', async() => {
|
||||
await element(by.text(`${ data.random }quote`)).longPress();
|
||||
await waitFor(element(by.text('Messages actions'))).toBeVisible().withTimeout(5000);
|
||||
await expect(element(by.text('Messages actions'))).toBeVisible();
|
||||
await element(by.text('Quote')).tap();
|
||||
await element(by.id('messagebox-input')).typeText(`${ data.random }quoted`);
|
||||
await element(by.id('messagebox-send-message')).tap();
|
||||
// TODO: test if quote was sent
|
||||
});
|
||||
|
||||
it('should star message', async() => {
|
||||
await element(by.text(`${ data.random }message`)).longPress();
|
||||
await waitFor(element(by.text('Messages actions'))).toBeVisible().withTimeout(5000);
|
||||
await expect(element(by.text('Messages actions'))).toBeVisible();
|
||||
await element(by.text('Star')).tap();
|
||||
await waitFor(element(by.text('Messages actions'))).toBeNotVisible().withTimeout(5000);
|
||||
await element(by.text(`${ data.random }message`)).longPress();
|
||||
await waitFor(element(by.text('Unstar'))).toBeVisible().withTimeout(2000);
|
||||
await expect(element(by.text('Unstar'))).toBeVisible();
|
||||
await element(by.text('Cancel')).tap();
|
||||
await waitFor(element(by.text('Cancel'))).toBeNotVisible().withTimeout(2000);
|
||||
});
|
||||
|
||||
it('should react to message', async() => {
|
||||
await element(by.text(`${ data.random }message`)).longPress();
|
||||
await waitFor(element(by.text('Messages actions'))).toBeVisible().withTimeout(5000);
|
||||
await expect(element(by.text('Messages actions'))).toBeVisible();
|
||||
await element(by.text('Add Reaction')).tap();
|
||||
await waitFor(element(by.id('reaction-picker'))).toBeVisible().withTimeout(2000);
|
||||
await expect(element(by.id('reaction-picker'))).toBeVisible();
|
||||
await element(by.id('reaction-picker-😃')).tap();
|
||||
await waitFor(element(by.id('reaction-picker-grinning'))).toBeVisible().withTimeout(2000);
|
||||
await expect(element(by.id('reaction-picker-grinning'))).toBeVisible();
|
||||
await element(by.id('reaction-picker-grinning')).tap();
|
||||
await waitFor(element(by.id('message-reaction-:grinning:'))).toBeVisible().withTimeout(60000);
|
||||
await expect(element(by.id('message-reaction-:grinning:'))).toBeVisible();
|
||||
});
|
||||
|
||||
it('should show reaction picker on add reaction button pressed and have frequently used emoji', async() => {
|
||||
await element(by.id('message-add-reaction')).tap();
|
||||
await waitFor(element(by.id('reaction-picker'))).toBeVisible().withTimeout(2000);
|
||||
await expect(element(by.id('reaction-picker'))).toBeVisible();
|
||||
await waitFor(element(by.id('reaction-picker-grinning'))).toBeVisible().withTimeout(2000);
|
||||
await expect(element(by.id('reaction-picker-grinning'))).toBeVisible();
|
||||
await element(by.id('reaction-picker-😃')).tap();
|
||||
await waitFor(element(by.id('reaction-picker-grimacing'))).toBeVisible().withTimeout(2000);
|
||||
await element(by.id('reaction-picker-grimacing')).tap();
|
||||
await waitFor(element(by.id('message-reaction-:grimacing:'))).toBeVisible().withTimeout(60000);
|
||||
});
|
||||
|
||||
it('should remove reaction', async() => {
|
||||
await element(by.id('message-reaction-:grinning:')).tap();
|
||||
await waitFor(element(by.id('message-reaction-:grinning:'))).toBeNotVisible().withTimeout(60000);
|
||||
await expect(element(by.id('message-reaction-:grinning:'))).toBeNotVisible();
|
||||
});
|
||||
|
||||
it('should pin message', async() => {
|
||||
await element(by.text(`${ data.random }edited`)).longPress();
|
||||
await waitFor(element(by.text('Messages actions'))).toBeVisible().withTimeout(5000);
|
||||
await expect(element(by.text('Messages actions'))).toBeVisible();
|
||||
await element(by.text('Pin')).tap();
|
||||
await waitFor(element(by.text('Messages actions'))).toBeNotVisible().withTimeout(5000);
|
||||
await waitFor(element(by.text(`${ data.random }edited`)).atIndex(1)).toBeVisible().withTimeout(60000);
|
||||
await element(by.text(`${ data.random }edited`)).atIndex(0).longPress();
|
||||
await waitFor(element(by.text('Unpin'))).toBeVisible().withTimeout(2000);
|
||||
await expect(element(by.text('Unpin'))).toBeVisible();
|
||||
await element(by.text('Cancel')).tap();
|
||||
await waitFor(element(by.text('Cancel'))).toBeNotVisible().withTimeout(2000);
|
||||
});
|
||||
|
||||
// TODO: delete message - swipe on action sheet missing
|
||||
});
|
||||
|
||||
afterEach(async() => {
|
||||
takeScreenshot();
|
||||
});
|
||||
|
||||
after(async() => {
|
||||
await element(by.id('header-back')).tap();
|
||||
await waitFor(element(by.id('rooms-list-view'))).toBeVisible().withTimeout(2000);
|
||||
await expect(element(by.id('rooms-list-view'))).toBeVisible();
|
||||
});
|
||||
});
|
||||
});
|
|
@ -0,0 +1,403 @@
|
|||
const {
|
||||
device, expect, element, by, waitFor
|
||||
} = require('detox');
|
||||
const { takeScreenshot } = require('./helpers/screenshot');
|
||||
const data = require('./data');
|
||||
|
||||
const scrollDown = 200;
|
||||
|
||||
async function navigateToRoomActions(type) {
|
||||
let room;
|
||||
if (type === 'd') {
|
||||
room = 'rocket.cat';
|
||||
} else {
|
||||
room = `private${ data.random }`;
|
||||
}
|
||||
await waitFor(element(by.id(`rooms-list-view-item-${ room }`))).toBeVisible().withTimeout(2000);
|
||||
await element(by.id(`rooms-list-view-item-${ room }`)).tap();
|
||||
await waitFor(element(by.id('room-view'))).toBeVisible().withTimeout(2000);
|
||||
await element(by.id('room-view-header-actions')).tap();
|
||||
await waitFor(element(by.id('room-actions-view'))).toBeVisible().withTimeout(5000);
|
||||
}
|
||||
|
||||
async function backToActions() {
|
||||
await element(by.id('header-back')).atIndex(0).tap();
|
||||
await waitFor(element(by.id('rooms-actions-view'))).toBeVisible().withTimeout(2000);
|
||||
}
|
||||
|
||||
async function backToRoomsList() {
|
||||
await element(by.id('header-back')).atIndex(0).tap();
|
||||
await waitFor(element(by.id('room-view'))).toBeVisible().withTimeout(2000);
|
||||
await element(by.id('header-back')).atIndex(0).tap();
|
||||
await waitFor(element(by.id('rooms-list-view'))).toBeVisible().withTimeout(2000);
|
||||
}
|
||||
|
||||
describe('Room actions screen', () => {
|
||||
describe('Render', async() => {
|
||||
describe('Direct', async() => {
|
||||
before(async() => {
|
||||
await navigateToRoomActions('d');
|
||||
});
|
||||
|
||||
it('should have room actions screen', async() => {
|
||||
await expect(element(by.id('room-actions-view'))).toBeVisible();
|
||||
});
|
||||
|
||||
it('should have info', async() => {
|
||||
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 files', async() => {
|
||||
await expect(element(by.id('room-actions-files'))).toBeVisible();
|
||||
});
|
||||
|
||||
it('should have mentions', async() => {
|
||||
await expect(element(by.id('room-actions-mentioned'))).toBeVisible();
|
||||
});
|
||||
|
||||
it('should have starred', async() => {
|
||||
await expect(element(by.id('room-actions-starred'))).toBeVisible();
|
||||
});
|
||||
|
||||
it('should have search', async() => {
|
||||
await expect(element(by.id('room-actions-search'))).toBeVisible();
|
||||
});
|
||||
|
||||
it('should have share', async() => {
|
||||
await waitFor(element(by.id('room-actions-share'))).toBeVisible().whileElement(by.id('room-actions-list')).scroll(scrollDown, 'down');
|
||||
await expect(element(by.id('room-actions-share'))).toBeVisible();
|
||||
});
|
||||
|
||||
it('should have pinned', async() => {
|
||||
await waitFor(element(by.id('room-actions-pinned'))).toBeVisible().whileElement(by.id('room-actions-list')).scroll(scrollDown, 'down');
|
||||
await expect(element(by.id('room-actions-pinned'))).toBeVisible();
|
||||
});
|
||||
|
||||
it('should have snippeted', async() => {
|
||||
await waitFor(element(by.id('room-actions-snippeted'))).toBeVisible().whileElement(by.id('room-actions-list')).scroll(scrollDown, 'down');
|
||||
await expect(element(by.id('room-actions-snippeted'))).toBeVisible();
|
||||
});
|
||||
|
||||
it('should have notifications', async() => {
|
||||
await waitFor(element(by.id('room-actions-notifications'))).toBeVisible().whileElement(by.id('room-actions-list')).scroll(scrollDown, 'down');
|
||||
await expect(element(by.id('room-actions-notifications'))).toBeVisible();
|
||||
});
|
||||
|
||||
it('should have block user', async() => {
|
||||
await waitFor(element(by.id('room-actions-block-user'))).toBeVisible().whileElement(by.id('room-actions-list')).scroll(scrollDown, 'down');
|
||||
await expect(element(by.id('room-actions-block-user'))).toBeVisible();
|
||||
});
|
||||
|
||||
after(async() => {
|
||||
await backToRoomsList();
|
||||
});
|
||||
});
|
||||
|
||||
describe('Channel/Group', async() => {
|
||||
before(async() => {
|
||||
await navigateToRoomActions('c');
|
||||
});
|
||||
|
||||
it('should have room actions screen', async() => {
|
||||
await expect(element(by.id('room-actions-view'))).toBeVisible();
|
||||
});
|
||||
|
||||
it('should have info', async() => {
|
||||
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() => {
|
||||
await expect(element(by.id('room-actions-members'))).toBeVisible();
|
||||
});
|
||||
|
||||
it('should have add user', async() => {
|
||||
await expect(element(by.id('room-actions-add-user'))).toBeVisible();
|
||||
});
|
||||
|
||||
it('should have files', async() => {
|
||||
await expect(element(by.id('room-actions-files'))).toBeVisible();
|
||||
});
|
||||
|
||||
it('should have mentions', async() => {
|
||||
await expect(element(by.id('room-actions-mentioned'))).toBeVisible();
|
||||
});
|
||||
|
||||
it('should have starred', async() => {
|
||||
await expect(element(by.id('room-actions-starred'))).toBeVisible();
|
||||
});
|
||||
|
||||
it('should have search', async() => {
|
||||
await expect(element(by.id('room-actions-search'))).toBeVisible();
|
||||
});
|
||||
|
||||
it('should have share', async() => {
|
||||
await waitFor(element(by.id('room-actions-share'))).toBeVisible().whileElement(by.id('room-actions-list')).scroll(scrollDown, 'down');
|
||||
await expect(element(by.id('room-actions-share'))).toBeVisible();
|
||||
});
|
||||
|
||||
it('should have pinned', async() => {
|
||||
await waitFor(element(by.id('room-actions-pinned'))).toBeVisible().whileElement(by.id('room-actions-list')).scroll(scrollDown, 'down');
|
||||
await expect(element(by.id('room-actions-pinned'))).toBeVisible();
|
||||
});
|
||||
|
||||
it('should have snippeted', async() => {
|
||||
await waitFor(element(by.id('room-actions-snippeted'))).toBeVisible().whileElement(by.id('room-actions-list')).scroll(scrollDown, 'down');
|
||||
await expect(element(by.id('room-actions-snippeted'))).toBeVisible();
|
||||
});
|
||||
|
||||
it('should have notifications', async() => {
|
||||
await waitFor(element(by.id('room-actions-notifications'))).toBeVisible().whileElement(by.id('room-actions-list')).scroll(scrollDown, 'down');
|
||||
await expect(element(by.id('room-actions-notifications'))).toBeVisible();
|
||||
});
|
||||
|
||||
it('should have leave channel', async() => {
|
||||
await waitFor(element(by.id('room-actions-leave-channel'))).toBeVisible().whileElement(by.id('room-actions-list')).scroll(scrollDown, 'down');
|
||||
await expect(element(by.id('room-actions-leave-channel'))).toBeVisible();
|
||||
});
|
||||
});
|
||||
|
||||
afterEach(async() => {
|
||||
takeScreenshot();
|
||||
});
|
||||
});
|
||||
|
||||
describe('Usage', async() => {
|
||||
describe('TDB', async() => {
|
||||
it('should NOT navigate to voice call', async() => {
|
||||
await waitFor(element(by.id('room-actions-voice'))).toBeVisible().whileElement(by.id('room-actions-list')).scroll(scrollDown, 'up');
|
||||
await element(by.id('room-actions-voice')).tap();
|
||||
await waitFor(element(by.id('room-actions-view'))).toBeVisible().withTimeout(2000);
|
||||
await expect(element(by.id('room-actions-view'))).toBeVisible();
|
||||
});
|
||||
|
||||
it('should NOT navigate to video call', async() => {
|
||||
await element(by.id('room-actions-video')).tap();
|
||||
await waitFor(element(by.id('room-actions-view'))).toBeVisible().withTimeout(2000);
|
||||
await expect(element(by.id('room-actions-view'))).toBeVisible();
|
||||
});
|
||||
|
||||
it('should NOT navigate to share messages', async() => {
|
||||
await waitFor(element(by.id('room-actions-share'))).toBeVisible().whileElement(by.id('room-actions-list')).scroll(scrollDown, 'down');
|
||||
await element(by.id('room-actions-share')).tap();
|
||||
await waitFor(element(by.id('room-actions-view'))).toBeVisible().withTimeout(2000);
|
||||
await expect(element(by.id('room-actions-view'))).toBeVisible();
|
||||
});
|
||||
|
||||
after(async() => {
|
||||
takeScreenshot();
|
||||
});
|
||||
});
|
||||
|
||||
describe('Common', async() => {
|
||||
it('should show mentioned messages', async() => {
|
||||
await element(by.id('room-actions-mentioned')).tap();
|
||||
await waitFor(element(by.id('mentioned-messages-view'))).toExist().withTimeout(2000);
|
||||
await waitFor(element(by.text(`@${ data.user } test`).withAncestor(by.id('mentioned-messages-view')))).toBeVisible().withTimeout(60000);
|
||||
await expect(element(by.text(`@${ data.user } test`).withAncestor(by.id('mentioned-messages-view')))).toBeVisible();
|
||||
await backToActions();
|
||||
});
|
||||
|
||||
it('should show starred message and unstar it', async() => {
|
||||
await element(by.id('room-actions-starred')).tap();
|
||||
await waitFor(element(by.id('starred-messages-view'))).toExist().withTimeout(2000);
|
||||
await waitFor(element(by.text(`${ data.random }message`).withAncestor(by.id('starred-messages-view')))).toBeVisible().withTimeout(60000);
|
||||
await expect(element(by.text(`${ data.random }message`).withAncestor(by.id('starred-messages-view')))).toBeVisible();
|
||||
await element(by.text(`${ data.random }message`).withAncestor(by.id('starred-messages-view'))).longPress();
|
||||
await waitFor(element(by.text('Unstar'))).toBeVisible().withTimeout(2000);
|
||||
await expect(element(by.text('Unstar'))).toBeVisible();
|
||||
await element(by.text('Unstar')).tap();
|
||||
await waitFor(element(by.text(`${ data.random }message`).withAncestor(by.id('starred-messages-view')))).toBeNotVisible().withTimeout(60000);
|
||||
await expect(element(by.text(`${ data.random }message`).withAncestor(by.id('starred-messages-view')))).toBeNotVisible();
|
||||
await backToActions();
|
||||
});
|
||||
|
||||
it('should show pinned message and unpin it', async() => {
|
||||
await waitFor(element(by.id('room-actions-pinned'))).toBeVisible().whileElement(by.id('room-actions-list')).scroll(scrollDown, 'down');
|
||||
await element(by.id('room-actions-pinned')).tap();
|
||||
await waitFor(element(by.id('pinned-messages-view'))).toExist().withTimeout(2000);
|
||||
await waitFor(element(by.text(`${ data.random }edited`).withAncestor(by.id('pinned-messages-view'))).atIndex(0)).toBeVisible().withTimeout(60000);
|
||||
await expect(element(by.text(`${ data.random }edited`).withAncestor(by.id('pinned-messages-view')))).toBeVisible();
|
||||
await element(by.text(`${ data.random }edited`).withAncestor(by.id('pinned-messages-view'))).longPress();
|
||||
await waitFor(element(by.text('Unpin'))).toBeVisible().withTimeout(2000);
|
||||
await expect(element(by.text('Unpin'))).toBeVisible();
|
||||
await element(by.text('Unpin')).tap();
|
||||
await waitFor(element(by.text(`${ data.random }edited`).withAncestor(by.id('pinned-messages-view'))).atIndex(0)).toBeNotVisible().withTimeout(60000);
|
||||
await expect(element(by.text(`${ data.random }edited`).withAncestor(by.id('pinned-messages-view')))).toBeNotVisible();
|
||||
await backToActions();
|
||||
});
|
||||
|
||||
it('should search and find a message', async() => {
|
||||
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'))).toBeVisible();
|
||||
await element(by.id('search-message-view-input')).tap();
|
||||
await element(by.id('search-message-view-input')).replaceText(`/${ data.random }message/`);
|
||||
await waitFor(element(by.text(`${ data.random }message`).withAncestor(by.id('search-messages-view'))).atIndex(0)).toBeVisible().withTimeout(60000);
|
||||
await expect(element(by.text(`${ data.random }message`).withAncestor(by.id('search-messages-view'))).atIndex(0)).toBeVisible();
|
||||
await backToActions();
|
||||
});
|
||||
|
||||
it('should enable/disable notifications', async() => {
|
||||
await waitFor(element(by.id('room-actions-notifications'))).toBeVisible().whileElement(by.id('room-actions-list')).scroll(scrollDown, 'down');
|
||||
await expect(element(by.text('Disable notifications'))).toBeVisible();
|
||||
await element(by.id('room-actions-notifications')).tap();
|
||||
await waitFor(element(by.text('Enable notifications'))).toBeVisible().withTimeout(60000);
|
||||
await expect(element(by.text('Enable notifications'))).toBeVisible();
|
||||
await element(by.id('room-actions-notifications')).tap();
|
||||
await waitFor(element(by.text('Disable notifications'))).toBeVisible().withTimeout(60000);
|
||||
await expect(element(by.text('Disable notifications'))).toBeVisible();
|
||||
});
|
||||
|
||||
afterEach(async() => {
|
||||
takeScreenshot();
|
||||
});
|
||||
});
|
||||
|
||||
describe('Channel/Group', async() => {
|
||||
// Currently, there's no way to add more owners to the room
|
||||
// So we test only for the 'You are the last owner...' message
|
||||
it('should tap on leave channel and raise alert', async() => {
|
||||
await waitFor(element(by.id('room-actions-leave-channel'))).toBeVisible().whileElement(by.id('room-actions-list')).scroll(scrollDown, 'down');
|
||||
await expect(element(by.id('room-actions-leave-channel'))).toBeVisible();
|
||||
await element(by.id('room-actions-leave-channel')).tap();
|
||||
await waitFor(element(by.text('Yes, leave it!'))).toBeVisible().withTimeout(2000);
|
||||
await expect(element(by.text('Yes, leave it!'))).toBeVisible();
|
||||
await element(by.text('Yes, leave it!')).tap();
|
||||
await waitFor(element(by.text('You are the last owner. Please set new owner before leaving the room.'))).toBeVisible().withTimeout(60000);
|
||||
await expect(element(by.text('You are the last owner. Please set new owner before leaving the room.'))).toBeVisible();
|
||||
await takeScreenshot();
|
||||
await element(by.text('OK')).tap();
|
||||
await waitFor(element(by.id('rooms-actions-view'))).toBeVisible().withTimeout(2000);
|
||||
});
|
||||
|
||||
describe('Add User', async() => {
|
||||
it('should add user to the room', async() => {
|
||||
const user = 'detoxrn';
|
||||
await waitFor(element(by.id('room-actions-add-user'))).toBeVisible().whileElement(by.id('room-actions-list')).scroll(scrollDown, 'up');
|
||||
await element(by.id('room-actions-add-user')).tap();
|
||||
await element(by.id('select-users-view-search')).tap();
|
||||
await element(by.id('select-users-view-search')).replaceText(user);
|
||||
await waitFor(element(by.id(`select-users-view-item-${ user }`))).toBeVisible().withTimeout(60000);
|
||||
await expect(element(by.id(`select-users-view-item-${ user }`))).toBeVisible();
|
||||
await element(by.id(`select-users-view-item-${ user }`)).tap();
|
||||
await waitFor(element(by.id(`selected-user-${ user }`))).toBeVisible().withTimeout(5000);
|
||||
await expect(element(by.id(`selected-user-${ user }`))).toBeVisible();
|
||||
await element(by.id('selected-users-view-submit')).tap();
|
||||
await waitFor(element(by.id('room-view'))).toBeVisible().withTimeout(60000);
|
||||
await element(by.id('room-view-header-actions')).tap();
|
||||
await waitFor(element(by.id('room-actions-view'))).toBeVisible().withTimeout(2000);
|
||||
await element(by.id('room-actions-members')).tap();
|
||||
await element(by.id('room-members-view-toggle-status')).tap();
|
||||
await waitFor(element(by.id(`room-members-view-item-${ user }`))).toBeVisible().withTimeout(60000);
|
||||
await expect(element(by.id(`room-members-view-item-${ user }`))).toBeVisible();
|
||||
await backToActions();
|
||||
});
|
||||
|
||||
after(async() => {
|
||||
takeScreenshot();
|
||||
});
|
||||
});
|
||||
|
||||
describe('Room Members', async() => {
|
||||
const user = 'detoxrn';
|
||||
before(async() => {
|
||||
await element(by.id('room-actions-members')).tap();
|
||||
await waitFor(element(by.id('room-members-view'))).toExist().withTimeout(2000);
|
||||
await expect(element(by.id('room-members-view'))).toExist();
|
||||
});
|
||||
|
||||
it('should show/hide all users', async() => {
|
||||
await element(by.id('room-members-view-toggle-status')).tap();
|
||||
await waitFor(element(by.id(`room-members-view-item-${ user }`))).toBeVisible().withTimeout(60000);
|
||||
await expect(element(by.id(`room-members-view-item-${ user }`))).toBeVisible();
|
||||
await element(by.id('room-members-view-toggle-status')).tap();
|
||||
await waitFor(element(by.id(`room-members-view-item-${ user }`))).toBeNotVisible().withTimeout(60000);
|
||||
await expect(element(by.id(`room-members-view-item-${ user }`))).toBeNotVisible();
|
||||
});
|
||||
|
||||
it('should filter user', async() => {
|
||||
await element(by.id('room-members-view-toggle-status')).tap();
|
||||
await waitFor(element(by.id(`room-members-view-item-${ user }`))).toBeVisible().withTimeout(60000);
|
||||
await expect(element(by.id(`room-members-view-item-${ user }`))).toBeVisible();
|
||||
await element(by.id('room-members-view-search')).replaceText('rocket');
|
||||
await waitFor(element(by.id(`room-members-view-item-${ user }`))).toBeNotVisible().withTimeout(60000);
|
||||
await expect(element(by.id(`room-members-view-item-${ user }`))).toBeNotVisible();
|
||||
await element(by.id('room-members-view-search')).tap();
|
||||
await element(by.id('room-members-view-search')).clearText('');
|
||||
await waitFor(element(by.id(`room-members-view-item-${ user }`))).toBeVisible().withTimeout(60000);
|
||||
await expect(element(by.id(`room-members-view-item-${ user }`))).toBeVisible();
|
||||
});
|
||||
|
||||
it('should mute user', async() => {
|
||||
await element(by.id(`room-members-view-item-${ user }`)).longPress();
|
||||
await waitFor(element(by.text('Mute'))).toBeVisible().withTimeout(5000);
|
||||
await expect(element(by.text('Mute'))).toBeVisible();
|
||||
await element(by.text('Mute')).tap();
|
||||
await waitFor(element(by.text('User has been muted!'))).toBeVisible().withTimeout(60000);
|
||||
await expect(element(by.text('User has been muted!'))).toBeVisible();
|
||||
await waitFor(element(by.text('User has been muted!'))).toBeNotVisible().withTimeout(60000);
|
||||
await expect(element(by.text('User has been muted!'))).toBeNotVisible();
|
||||
await element(by.id(`room-members-view-item-${ user }`)).longPress();
|
||||
await waitFor(element(by.text('Unmute'))).toBeVisible().withTimeout(2000);
|
||||
await expect(element(by.text('Unmute'))).toBeVisible();
|
||||
await element(by.text('Unmute')).tap();
|
||||
await waitFor(element(by.text('User has been unmuted!'))).toBeVisible().withTimeout(60000);
|
||||
await expect(element(by.text('User has been unmuted!'))).toBeVisible();
|
||||
await waitFor(element(by.text('User has been unmuted!'))).toBeNotVisible().withTimeout(5000);
|
||||
await expect(element(by.text('User has been unmuted!'))).toBeNotVisible();
|
||||
});
|
||||
|
||||
it('should navigate to direct room', async() => {
|
||||
await waitFor(element(by.id(`room-members-view-item-${ user }`))).toExist().withTimeout(5000);
|
||||
await element(by.id(`room-members-view-item-${ user }`)).tap();
|
||||
await waitFor(element(by.id('room-view'))).toBeVisible().withTimeout(60000);
|
||||
await expect(element(by.id('room-view'))).toBeVisible();
|
||||
await waitFor(element(by.id('room-view-title'))).toHaveText(user).withTimeout(60000);
|
||||
await expect(element(by.id('room-view-title'))).toHaveText(user);
|
||||
await element(by.id('header-back')).atIndex(0).tap();
|
||||
await waitFor(element(by.id('room-list-view'))).toBeVisible().withTimeout(2000);
|
||||
});
|
||||
|
||||
afterEach(async() => {
|
||||
takeScreenshot();
|
||||
});
|
||||
});
|
||||
})
|
||||
|
||||
describe('Direct', async() => {
|
||||
before(async() => {
|
||||
await navigateToRoomActions('d');
|
||||
});
|
||||
|
||||
it('should block/unblock user', async() => {
|
||||
await waitFor(element(by.id('room-actions-block-user'))).toBeVisible().whileElement(by.id('room-actions-list')).scroll(scrollDown, 'down');
|
||||
await element(by.id('room-actions-block-user')).tap();
|
||||
await waitFor(element(by.text('Unblock user'))).toBeVisible().withTimeout(60000);
|
||||
await expect(element(by.text('Unblock user'))).toBeVisible();
|
||||
await element(by.id('room-actions-block-user')).tap();
|
||||
await waitFor(element(by.text('Block user'))).toBeVisible().withTimeout(60000);
|
||||
await expect(element(by.text('Block user'))).toBeVisible();
|
||||
});
|
||||
|
||||
after(async() => {
|
||||
takeScreenshot();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
|
@ -0,0 +1,326 @@
|
|||
const {
|
||||
device, expect, element, by, waitFor
|
||||
} = require('detox');
|
||||
const { takeScreenshot } = require('./helpers/screenshot');
|
||||
const data = require('./data');
|
||||
|
||||
async function navigateToRoomInfo() {
|
||||
const room = `private${ data.random }`;
|
||||
await waitFor(element(by.id(`rooms-list-view-item-${ room }`))).toBeVisible().withTimeout(2000);
|
||||
await element(by.id(`rooms-list-view-item-${ room }`)).tap();
|
||||
await waitFor(element(by.id('room-view'))).toBeVisible().withTimeout(2000);
|
||||
await element(by.id('room-view-header-title')).tap();
|
||||
await waitFor(element(by.id('room-info-view'))).toBeVisible().withTimeout(2000);
|
||||
}
|
||||
|
||||
async function backToRoomsList() {
|
||||
await element(by.id('header-back')).atIndex(0).tap();
|
||||
await waitFor(element(by.id('room-actions-view'))).toBeVisible().withTimeout(2000);
|
||||
await element(by.id('header-back')).atIndex(0).tap();
|
||||
await waitFor(element(by.id('room-view'))).toBeVisible().withTimeout(2000);
|
||||
await element(by.id('header-back')).atIndex(0).tap();
|
||||
await waitFor(element(by.id('rooms-list-view'))).toBeVisible().withTimeout(2000);
|
||||
}
|
||||
|
||||
describe('Room info screen', () => {
|
||||
describe('Direct', async() => {
|
||||
before(async() => {
|
||||
// last test positioned simulator at rooms-list-actions on a direct room
|
||||
await waitFor(element(by.id('room-actions-info'))).toBeVisible().whileElement(by.id('room-actions-list')).scroll(500, 'up');
|
||||
await element(by.id('room-actions-info')).tap();
|
||||
await waitFor(element(by.id('room-info-view'))).toBeVisible().withTimeout(2000);
|
||||
});
|
||||
|
||||
it('should navigate to room info', async() => {
|
||||
await expect(element(by.id('room-info-view'))).toBeVisible();
|
||||
await expect(element(by.id('room-info-view-name'))).toBeVisible();
|
||||
});
|
||||
|
||||
after(async() => {
|
||||
await takeScreenshot();
|
||||
await backToRoomsList();
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
describe('Channel/Group', async() => {
|
||||
before(async() => {
|
||||
await navigateToRoomInfo();
|
||||
});
|
||||
|
||||
describe('Render', async() => {
|
||||
it('should have room info view', async() => {
|
||||
await expect(element(by.id('room-info-view'))).toBeVisible();
|
||||
});
|
||||
|
||||
it('should have name', async() => {
|
||||
await expect(element(by.id('room-info-view-name'))).toBeVisible();
|
||||
});
|
||||
|
||||
it('should have description', async() => {
|
||||
await expect(element(by.id('room-info-view-description'))).toBeVisible();
|
||||
});
|
||||
|
||||
it('should have topic', async() => {
|
||||
await expect(element(by.id('room-info-view-topic'))).toBeVisible();
|
||||
});
|
||||
|
||||
it('should have announcement', async() => {
|
||||
await expect(element(by.id('room-info-view-announcement'))).toBeVisible();
|
||||
});
|
||||
|
||||
it('should have edit button', async() => {
|
||||
await expect(element(by.id('room-info-view-edit-button'))).toBeVisible();
|
||||
});
|
||||
|
||||
after(async() => {
|
||||
takeScreenshot();
|
||||
});
|
||||
});
|
||||
|
||||
describe('Render Edit', async() => {
|
||||
before(async() => {
|
||||
await waitFor(element(by.id('room-info-view-edit-button'))).toBeVisible().withTimeout(10000);
|
||||
await element(by.id('room-info-view-edit-button')).tap();
|
||||
await waitFor(element(by.id('room-info-edit-view'))).toBeVisible().withTimeout(2000);
|
||||
});
|
||||
|
||||
it('should have room info edit view', async() => {
|
||||
await expect(element(by.id('room-info-edit-view'))).toExist();
|
||||
});
|
||||
|
||||
it('should have name input', async() => {
|
||||
await expect(element(by.id('room-info-edit-view-name'))).toBeVisible();
|
||||
});
|
||||
|
||||
it('should have description input', async() => {
|
||||
await expect(element(by.id('room-info-edit-view-description'))).toBeVisible();
|
||||
});
|
||||
|
||||
it('should have topic input', async() => {
|
||||
await expect(element(by.id('room-info-edit-view-topic'))).toBeVisible();
|
||||
});
|
||||
|
||||
it('should have announcement input', async() => {
|
||||
await expect(element(by.id('room-info-edit-view-announcement'))).toBeVisible();
|
||||
});
|
||||
|
||||
it('should have password input', async() => {
|
||||
await expect(element(by.id('room-info-edit-view-password'))).toBeVisible();
|
||||
});
|
||||
|
||||
it('should have type switch', async() => {
|
||||
await element(by.id('room-info-edit-view-list')).swipe('up');
|
||||
await expect(element(by.id('room-info-edit-view-t'))).toBeVisible();
|
||||
});
|
||||
|
||||
it('should have ready only switch', async() => {
|
||||
await expect(element(by.id('room-info-edit-view-ro'))).toBeVisible();
|
||||
});
|
||||
|
||||
it('should have submit button', async() => {
|
||||
await expect(element(by.id('room-info-edit-view-submit'))).toBeVisible();
|
||||
});
|
||||
|
||||
it('should have reset button', async() => {
|
||||
await expect(element(by.id('room-info-edit-view-reset'))).toBeVisible();
|
||||
});
|
||||
|
||||
it('should have archive button', async() => {
|
||||
await expect(element(by.id('room-info-edit-view-archive'))).toBeVisible();
|
||||
});
|
||||
|
||||
it('should have delete button', async() => {
|
||||
await expect(element(by.id('room-info-edit-view-delete'))).toBeVisible();
|
||||
});
|
||||
|
||||
after(async() => {
|
||||
await takeScreenshot();
|
||||
await element(by.id('room-info-edit-view-list')).swipe('down');
|
||||
});
|
||||
});
|
||||
|
||||
describe('Usage', async() => {
|
||||
const room = `private${ data.random }`;
|
||||
// it('should enter "invalid name" and get error', async() => {
|
||||
// await element(by.id('room-info-edit-view-list')).swipe('down');
|
||||
// await element(by.id('room-info-edit-view-name')).replaceText('invalid name');
|
||||
// await element(by.id('room-info-edit-view-list')).swipe('up');
|
||||
// await element(by.id('room-info-edit-view-submit')).tap();
|
||||
// await waitFor(element(by.text('There was an error while saving settings!'))).toBeVisible().withTimeout(60000);
|
||||
// await expect(element(by.text('There was an error while saving settings!'))).toBeVisible();
|
||||
// await element(by.text('OK')).tap();
|
||||
// await waitFor(element(by.text('There was an error while saving settings!'))).toBeNotVisible().withTimeout(10000);
|
||||
// await element(by.id('room-info-edit-view-list')).swipe('down');
|
||||
// });
|
||||
|
||||
it('should change room name', async() => {
|
||||
await element(by.id('room-info-edit-view-name')).replaceText(`${ room }new`);
|
||||
await element(by.id('room-info-edit-view-list')).swipe('up');
|
||||
await element(by.id('room-info-edit-view-submit')).tap();
|
||||
await waitFor(element(by.text('Settings succesfully changed!'))).toBeVisible().withTimeout(60000);
|
||||
await expect(element(by.text('Settings succesfully changed!'))).toBeVisible();
|
||||
await waitFor(element(by.text('Settings succesfully changed!'))).toBeNotVisible().withTimeout(10000);
|
||||
await expect(element(by.text('Settings succesfully changed!'))).toBeNotVisible();
|
||||
await element(by.id('header-back')).atIndex(0).tap();
|
||||
await waitFor(element(by.id('room-info-view'))).toBeVisible().withTimeout(2000);
|
||||
await waitFor(element(by.id('room-info-view-name'))).toHaveText(`${ room }new`).withTimeout(60000);
|
||||
await expect(element(by.id('room-info-view-name'))).toHaveText(`${ room }new`);
|
||||
// change name to original
|
||||
await element(by.id('room-info-view-edit-button')).tap();
|
||||
await waitFor(element(by.id('room-info-edit-view'))).toBeVisible().withTimeout(2000);
|
||||
await element(by.id('room-info-edit-view-name')).replaceText(`${ room }`);
|
||||
await element(by.id('room-info-edit-view-list')).swipe('up');
|
||||
await element(by.id('room-info-edit-view-submit')).tap();
|
||||
await waitFor(element(by.text('Settings succesfully changed!'))).toBeVisible().withTimeout(60000);
|
||||
await expect(element(by.text('Settings succesfully changed!'))).toBeVisible();
|
||||
await waitFor(element(by.text('Settings succesfully changed!'))).toBeNotVisible().withTimeout(10000);
|
||||
await expect(element(by.text('Settings succesfully changed!'))).toBeNotVisible();
|
||||
await element(by.id('room-info-edit-view-list')).swipe('down');
|
||||
});
|
||||
|
||||
it('should reset form', async() => {
|
||||
await element(by.id('room-info-edit-view-name')).replaceText('abc');
|
||||
await element(by.id('room-info-edit-view-description')).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-password')).replaceText('abc');
|
||||
await element(by.id('room-info-edit-view-list')).swipe('up');
|
||||
await element(by.id('room-info-edit-view-t')).tap();
|
||||
await element(by.id('room-info-edit-view-ro')).tap();
|
||||
await element(by.id('room-info-edit-view-react-when-ro')).tap();
|
||||
await element(by.id('room-info-edit-view-reset')).tap();
|
||||
// after reset
|
||||
await expect(element(by.id('room-info-edit-view-name'))).toHaveText(room);
|
||||
await expect(element(by.id('room-info-edit-view-description'))).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-password'))).toHaveText('');
|
||||
await expect(element(by.id('room-info-edit-view-t'))).toHaveValue('1');
|
||||
await expect(element(by.id('room-info-edit-view-ro'))).toHaveValue('0');
|
||||
await expect(element(by.id('room-info-edit-view-react-when-ro'))).toBeNotVisible();
|
||||
await element(by.id('room-info-edit-view-list')).swipe('down');
|
||||
});
|
||||
|
||||
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-list')).swipe('up');
|
||||
await element(by.id('room-info-edit-view-submit')).tap();
|
||||
await waitFor(element(by.text('Settings succesfully changed!'))).toBeVisible().withTimeout(60000);
|
||||
await expect(element(by.text('Settings succesfully changed!'))).toBeVisible();
|
||||
await waitFor(element(by.text('Settings succesfully changed!'))).toBeNotVisible().withTimeout(10000);
|
||||
await expect(element(by.text('Settings succesfully changed!'))).toBeNotVisible();
|
||||
await element(by.id('header-back')).atIndex(0).tap();
|
||||
await waitFor(element(by.id('room-info-view'))).toBeVisible().withTimeout(2000);
|
||||
await waitFor(element(by.id('room-info-view-description'))).toHaveText('new description').withTimeout(60000);
|
||||
await expect(element(by.id('room-info-view-description'))).toHaveText('new description');
|
||||
await waitFor(element(by.id('room-info-view-edit-button'))).toBeVisible().withTimeout(10000);
|
||||
await element(by.id('room-info-view-edit-button')).tap();
|
||||
await waitFor(element(by.id('room-info-edit-view'))).toBeVisible().withTimeout(2000);
|
||||
});
|
||||
|
||||
it('should change room topic', async() => {
|
||||
await element(by.id('room-info-edit-view-topic')).replaceText('new topic');
|
||||
await element(by.id('room-info-edit-view-list')).swipe('up');
|
||||
await element(by.id('room-info-edit-view-submit')).tap();
|
||||
await waitFor(element(by.text('Settings succesfully changed!'))).toBeVisible().withTimeout(60000);
|
||||
await expect(element(by.text('Settings succesfully changed!'))).toBeVisible();
|
||||
await waitFor(element(by.text('Settings succesfully changed!'))).toBeNotVisible().withTimeout(10000);
|
||||
await expect(element(by.text('Settings succesfully changed!'))).toBeNotVisible();
|
||||
await element(by.id('header-back')).atIndex(0).tap();
|
||||
await waitFor(element(by.id('room-info-view'))).toBeVisible().withTimeout(2000);
|
||||
await waitFor(element(by.id('room-info-view-topic'))).toHaveText('new topic').withTimeout(60000);
|
||||
await expect(element(by.id('room-info-view-topic'))).toHaveText('new topic');
|
||||
await waitFor(element(by.id('room-info-view-edit-button'))).toBeVisible().withTimeout(10000);
|
||||
await element(by.id('room-info-view-edit-button')).tap();
|
||||
await waitFor(element(by.id('room-info-edit-view'))).toBeVisible().withTimeout(2000);
|
||||
});
|
||||
|
||||
it('should change room announcement', async() => {
|
||||
await element(by.id('room-info-edit-view-announcement')).replaceText('new announcement');
|
||||
await element(by.id('room-info-edit-view-list')).swipe('up');
|
||||
await element(by.id('room-info-edit-view-submit')).tap();
|
||||
await waitFor(element(by.text('Settings succesfully changed!'))).toBeVisible().withTimeout(60000);
|
||||
await expect(element(by.text('Settings succesfully changed!'))).toBeVisible();
|
||||
await waitFor(element(by.text('Settings succesfully changed!'))).toBeNotVisible().withTimeout(10000);
|
||||
await expect(element(by.text('Settings succesfully changed!'))).toBeNotVisible();
|
||||
await element(by.id('header-back')).atIndex(0).tap();
|
||||
await waitFor(element(by.id('room-info-view'))).toBeVisible().withTimeout(2000);
|
||||
await waitFor(element(by.id('room-info-view-announcement'))).toHaveText('new announcement').withTimeout(60000);
|
||||
await expect(element(by.id('room-info-view-announcement'))).toHaveText('new announcement');
|
||||
await waitFor(element(by.id('room-info-view-edit-button'))).toBeVisible().withTimeout(10000);
|
||||
await element(by.id('room-info-view-edit-button')).tap();
|
||||
await waitFor(element(by.id('room-info-edit-view'))).toBeVisible().withTimeout(2000);
|
||||
});
|
||||
|
||||
it('should change room password', async() => {
|
||||
await element(by.id('room-info-edit-view-list')).swipe('up');
|
||||
await element(by.id('room-info-edit-view-password')).replaceText('password');
|
||||
await element(by.id('room-info-edit-view-submit')).tap();
|
||||
await waitFor(element(by.text('Settings succesfully changed!'))).toBeVisible().withTimeout(60000);
|
||||
await expect(element(by.text('Settings succesfully changed!'))).toBeVisible();
|
||||
await waitFor(element(by.text('Settings succesfully changed!'))).toBeNotVisible().withTimeout(10000);
|
||||
await expect(element(by.text('Settings succesfully changed!'))).toBeNotVisible();
|
||||
});
|
||||
|
||||
it('should change room type', async() => {
|
||||
await element(by.id('room-info-edit-view-t')).tap();
|
||||
await element(by.id('room-info-edit-view-submit')).tap();
|
||||
await waitFor(element(by.text('Settings succesfully changed!'))).toBeVisible().withTimeout(60000);
|
||||
await expect(element(by.text('Settings succesfully changed!'))).toBeVisible();
|
||||
await waitFor(element(by.text('Settings succesfully changed!'))).toBeNotVisible().withTimeout(10000);
|
||||
await expect(element(by.text('Settings succesfully changed!'))).toBeNotVisible();
|
||||
await element(by.id('room-info-edit-view-t')).tap();
|
||||
await element(by.id('room-info-edit-view-submit')).tap();
|
||||
await waitFor(element(by.text('Settings succesfully changed!'))).toBeVisible().withTimeout(60000);
|
||||
await expect(element(by.text('Settings succesfully changed!'))).toBeVisible();
|
||||
await waitFor(element(by.text('Settings succesfully changed!'))).toBeNotVisible().withTimeout(10000);
|
||||
await expect(element(by.text('Settings succesfully changed!'))).toBeNotVisible();
|
||||
});
|
||||
|
||||
it('should change room read only and allow reactions', async() => {
|
||||
await element(by.id('room-info-edit-view-ro')).tap();
|
||||
await waitFor(element(by.id('room-info-edit-view-react-when-ro'))).toBeVisible().withTimeout(2000);
|
||||
await expect(element(by.id('room-info-edit-view-react-when-ro'))).toBeVisible();
|
||||
await element(by.id('room-info-edit-view-react-when-ro')).tap();
|
||||
await element(by.id('room-info-edit-view-submit')).tap();
|
||||
await waitFor(element(by.text('Settings succesfully changed!'))).toBeVisible().withTimeout(60000);
|
||||
await expect(element(by.text('Settings succesfully changed!'))).toBeVisible();
|
||||
await waitFor(element(by.text('Settings succesfully changed!'))).toBeNotVisible().withTimeout(10000);
|
||||
await expect(element(by.text('Settings succesfully changed!'))).toBeNotVisible();
|
||||
// TODO: test if it's possible to react
|
||||
});
|
||||
|
||||
it('should archive room', async() => {
|
||||
await element(by.id('room-info-edit-view-archive')).tap();
|
||||
await waitFor(element(by.text('Yes, archive it!'))).toBeVisible().withTimeout(5000);
|
||||
await expect(element(by.text('Yes, archive it!'))).toBeVisible();
|
||||
await element(by.text('Yes, archive it!')).tap();
|
||||
await waitFor(element(by.text('UNARCHIVE'))).toBeVisible().withTimeout(60000);
|
||||
await expect(element(by.text('UNARCHIVE'))).toBeVisible();
|
||||
// TODO: needs permission to unarchive
|
||||
// await element(by.id('room-info-edit-view-archive')).tap();
|
||||
// await waitFor(element(by.text('Yes, unarchive it!'))).toBeVisible().withTimeout(5000);
|
||||
// await expect(element(by.text('Yes, unarchive it!'))).toBeVisible();
|
||||
// await element(by.text('Yes, unarchive it!')).tap();
|
||||
// await waitFor(element(by.text('ARCHIVE'))).toBeVisible().withTimeout(60000);
|
||||
// await expect(element(by.text('ARCHIVE'))).toBeVisible();
|
||||
});
|
||||
|
||||
it('should delete room', async() => {
|
||||
await element(by.id('room-info-edit-view-list')).swipe('up');
|
||||
await element(by.id('room-info-edit-view-delete')).tap();
|
||||
await waitFor(element(by.text('Yes, delete it!'))).toBeVisible().withTimeout(5000);
|
||||
await expect(element(by.text('Yes, delete it!'))).toBeVisible();
|
||||
await element(by.text('Yes, delete it!')).tap();
|
||||
await waitFor(element(by.id('rooms-list-view'))).toBeVisible().withTimeout(2000);
|
||||
await waitFor(element(by.id(`rooms-list-view-item-${ room }`))).toBeNotVisible().withTimeout(60000);
|
||||
await expect(element(by.id(`rooms-list-view-item-${ room }`))).toBeNotVisible();
|
||||
});
|
||||
|
||||
after(async() => {
|
||||
takeScreenshot();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
|
@ -0,0 +1,60 @@
|
|||
const {
|
||||
device, expect, element, by, waitFor
|
||||
} = require('detox');
|
||||
const { takeScreenshot } = require('./helpers/screenshot');
|
||||
const data = require('./data');
|
||||
|
||||
describe('Change server', () => {
|
||||
before(async() => {
|
||||
await device.reloadReactNative();
|
||||
});
|
||||
|
||||
it('should add server and create new user', async() => {
|
||||
// Navigate to add server
|
||||
await element(by.id('rooms-list-view-sidebar')).tap();
|
||||
await waitFor(element(by.id('sidebar'))).toBeVisible().withTimeout(2000);
|
||||
await element(by.id('sidebar-add-server')).tap();
|
||||
await waitFor(element(by.id('new-server-view'))).toBeVisible().withTimeout(2000);
|
||||
// Add server
|
||||
await element(by.id('new-server-view-input')).replaceText(data.alternateServer);
|
||||
await waitFor(element(by.text(' is a valid Rocket.Chat instance'))).toBeVisible().withTimeout(60000);
|
||||
await element(by.id('new-server-view-button')).tap();
|
||||
// Navigate to register
|
||||
await waitFor(element(by.id('welcome-view'))).toBeVisible().withTimeout(2000);
|
||||
await element(by.id('welcome-view-register')).tap();
|
||||
await waitFor(element(by.id('register-view'))).toBeVisible().withTimeout(2000);
|
||||
// Register new user
|
||||
await element(by.id('register-view-name')).replaceText(data.user);
|
||||
await element(by.id('register-view-email')).replaceText(data.email);
|
||||
await element(by.id('register-view-password')).replaceText(data.password);
|
||||
await element(by.id('register-view-repeat-password')).replaceText(data.password);
|
||||
await element(by.id('register-view-submit')).tap();
|
||||
await waitFor(element(by.id('register-view-username'))).toBeVisible().withTimeout(60000);
|
||||
await element(by.id('register-view-username')).replaceText(data.user);
|
||||
await element(by.id('register-view-submit-username')).tap();
|
||||
await waitFor(element(by.id('rooms-list-view'))).toBeVisible().withTimeout(60000);
|
||||
await expect(element(by.id('rooms-list-view'))).toBeVisible();
|
||||
await expect(element(by.id('rooms-list-view-sidebar'))).toHaveLabel(`Connected to ${ data.alternateServer }. Tap to view servers list.`);
|
||||
// For a sanity test, to make sure roomslist is showing correct rooms
|
||||
// app CANNOT show public room created on previous tests
|
||||
await waitFor(element(by.id(`rooms-list-view-item-public${ data.random }`))).toBeNotVisible().withTimeout(60000);
|
||||
await expect(element(by.id(`rooms-list-view-item-public${ data.random }`))).toBeNotVisible();
|
||||
});
|
||||
|
||||
it('should change server', async() => {
|
||||
await element(by.id('rooms-list-view-sidebar')).tap();
|
||||
await waitFor(element(by.id('sidebar'))).toBeVisible().withTimeout(2000);
|
||||
await element(by.id(`sidebar-${ data.server }`)).tap();
|
||||
await waitFor(element(by.id('rooms-list-view'))).toBeVisible().withTimeout(10000);
|
||||
await waitFor(element(by.id('rooms-list-view-sidebar').and(by.label(`Connected to ${ data.server }. Tap to view servers list.`)))).toBeVisible().withTimeout(60000);
|
||||
await expect(element(by.id('rooms-list-view-sidebar'))).toHaveLabel(`Connected to ${ data.server }. Tap to view servers list.`);
|
||||
// For a sanity test, to make sure roomslist is showing correct rooms
|
||||
// app MUST show public room created on previous tests
|
||||
await waitFor(element(by.id(`rooms-list-view-item-public${ data.random }`))).toBeVisible().withTimeout(60000);
|
||||
await expect(element(by.id(`rooms-list-view-item-public${ data.random }`))).toBeVisible();
|
||||
});
|
||||
|
||||
afterEach(async() => {
|
||||
takeScreenshot();
|
||||
});
|
||||
});
|
|
@ -0,0 +1,11 @@
|
|||
const random = require('./helpers/random');
|
||||
const value = random(20);
|
||||
const data = {
|
||||
server: 'https://unstable.rocket.chat',
|
||||
alternateServer: 'https://stable.rocket.chat',
|
||||
user: `user${ value }`,
|
||||
password: `password${ value }`,
|
||||
email: `detoxrn+${ value }@rocket.chat`,
|
||||
random: value
|
||||
}
|
||||
module.exports = data;
|
|
@ -0,0 +1,41 @@
|
|||
const {
|
||||
device, expect, element, by, waitFor
|
||||
} = require('detox');
|
||||
const data = require('../data');
|
||||
|
||||
async function addServer() {
|
||||
await waitFor(element(by.id('new-server-view'))).toBeVisible().withTimeout(2000);
|
||||
await element(by.id('new-server-view-input')).replaceText(data.server);
|
||||
await waitFor(element(by.text(' is a valid Rocket.Chat instance'))).toBeVisible().withTimeout(2000);
|
||||
await waitFor(element(by.id('new-server-view-button'))).toBeVisible().withTimeout(2000);
|
||||
await element(by.id('new-server-view-button')).tap();
|
||||
}
|
||||
|
||||
async function navigateToLogin() {
|
||||
await waitFor(element(by.id('welcome-view'))).toBeVisible().withTimeout(2000);
|
||||
await element(by.id('welcome-view-login')).tap();
|
||||
await waitFor(element(by.id('login-view'))).toBeVisible().withTimeout(2000);
|
||||
}
|
||||
|
||||
async function login() {
|
||||
await waitFor(element(by.id('login-view'))).toBeVisible().withTimeout(2000);
|
||||
await element(by.id('login-view-email')).replaceText(data.user);
|
||||
await element(by.id('login-view-password')).replaceText(data.password);
|
||||
await element(by.id('login-view-submit')).tap();
|
||||
await waitFor(element(by.id('rooms-list-view'))).toBeVisible().withTimeout(10000);
|
||||
}
|
||||
|
||||
async function logout() {
|
||||
await element(by.id('rooms-list-view-sidebar')).tap();
|
||||
await waitFor(element(by.id('sidebar'))).toBeVisible().withTimeout(2000);
|
||||
await element(by.id('sidebar-logout')).tap();
|
||||
await waitFor(element(by.id('welcome-view'))).toBeVisible().withTimeout(2000);
|
||||
await expect(element(by.id('welcome-view'))).toBeVisible();
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
addServer,
|
||||
navigateToLogin,
|
||||
login,
|
||||
logout
|
||||
};
|
|
@ -0,0 +1,9 @@
|
|||
function random(length) {
|
||||
let text = '';
|
||||
const possible = 'abcdefghijklmnopqrstuvwxyz';
|
||||
for (let i = 0; i < length; i += 1) {
|
||||
text += possible.charAt(Math.floor(Math.random() * possible.length));
|
||||
}
|
||||
return text;
|
||||
}
|
||||
module.exports = random;
|
|
@ -0,0 +1,23 @@
|
|||
const { execSync } = require('child_process');
|
||||
const { existsSync, mkdirSync } = require('fs');
|
||||
|
||||
const SCREENSHOT_DIR = '/tmp/screenshots';
|
||||
|
||||
const SCREENSHOT_OPTIONS = {
|
||||
timeout: 2000,
|
||||
killSignal: 'SIGKILL'
|
||||
};
|
||||
|
||||
let screenshotIndex = 0;
|
||||
|
||||
const takeScreenshot = () => {
|
||||
if (!existsSync(SCREENSHOT_DIR)) { mkdirSync(SCREENSHOT_DIR); }
|
||||
const screenshotFilename = `${ SCREENSHOT_DIR }/screenshot-${ screenshotIndex++ }.png`;
|
||||
try {
|
||||
execSync(`xcrun simctl io booted screenshot ${ screenshotFilename }`, SCREENSHOT_OPTIONS);
|
||||
} catch (error) {
|
||||
console.log('erro');
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = { takeScreenshot };
|
|
@ -0,0 +1,11 @@
|
|||
const detox = require('detox');
|
||||
const config = require('../package.json').detox;
|
||||
|
||||
before(async() => {
|
||||
await detox.init(config);
|
||||
await device.launchApp({ permissions: { notifications: 'YES' } });
|
||||
});
|
||||
|
||||
after(async() => {
|
||||
await detox.cleanup();
|
||||
});
|
|
@ -0,0 +1 @@
|
|||
--recursive --timeout 120000
|
|
@ -3619,6 +3619,12 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"browser-stdout": {
|
||||
"version": "1.3.1",
|
||||
"resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz",
|
||||
"integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==",
|
||||
"dev": true
|
||||
},
|
||||
"browserify-aes": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz",
|
||||
|
@ -3941,6 +3947,29 @@
|
|||
"resolved": "https://registry.npmjs.org/chardet/-/chardet-0.4.2.tgz",
|
||||
"integrity": "sha1-tUc7M9yXxCTl2Y3IfVXU2KKci/I="
|
||||
},
|
||||
"child-process-promise": {
|
||||
"version": "2.2.1",
|
||||
"resolved": "https://registry.npmjs.org/child-process-promise/-/child-process-promise-2.2.1.tgz",
|
||||
"integrity": "sha1-RzChHvYQ+tRQuPIjx50x172tgHQ=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"cross-spawn": "4.0.2",
|
||||
"node-version": "1.1.3",
|
||||
"promise-polyfill": "6.1.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"cross-spawn": {
|
||||
"version": "4.0.2",
|
||||
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-4.0.2.tgz",
|
||||
"integrity": "sha1-e5JHYhwjrf3ThWAEqCPL45dCTUE=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"lru-cache": "4.1.1",
|
||||
"which": "1.3.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"chokidar": {
|
||||
"version": "2.0.3",
|
||||
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.0.3.tgz",
|
||||
|
@ -5534,6 +5563,59 @@
|
|||
"defined": "1.0.0"
|
||||
}
|
||||
},
|
||||
"detox": {
|
||||
"version": "7.3.5",
|
||||
"resolved": "https://registry.npmjs.org/detox/-/detox-7.3.5.tgz",
|
||||
"integrity": "sha512-qFAlpFAR7KOZLFoVyGHUfvvfeC6ULzdFCMnM/qlCt2rRkCC4hB1KEtzsPng92N+Si+ZNeByJ+mjWt68nbamsUQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"child-process-promise": "2.2.1",
|
||||
"commander": "2.15.1",
|
||||
"detox-server": "7.0.0",
|
||||
"fs-extra": "4.0.3",
|
||||
"get-port": "2.1.0",
|
||||
"ini": "1.3.5",
|
||||
"lodash": "4.17.10",
|
||||
"npmlog": "4.1.2",
|
||||
"shell-utils": "1.0.9",
|
||||
"tail": "1.2.3",
|
||||
"telnet-client": "0.15.3",
|
||||
"ws": "1.1.5"
|
||||
},
|
||||
"dependencies": {
|
||||
"fs-extra": {
|
||||
"version": "4.0.3",
|
||||
"resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-4.0.3.tgz",
|
||||
"integrity": "sha512-q6rbdDd1o2mAnQreO7YADIxf/Whx4AHBiRf6d+/cVT8h44ss+lHgxf1FemcqDnQt9X3ct4McHr+JMGlYSsK7Cg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"graceful-fs": "4.1.11",
|
||||
"jsonfile": "4.0.0",
|
||||
"universalify": "0.1.1"
|
||||
}
|
||||
},
|
||||
"jsonfile": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz",
|
||||
"integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"graceful-fs": "4.1.11"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"detox-server": {
|
||||
"version": "7.0.0",
|
||||
"resolved": "https://registry.npmjs.org/detox-server/-/detox-server-7.0.0.tgz",
|
||||
"integrity": "sha512-zs9ZP/MgeEmaZD/+MCl5PVcYHRjUtFBkBx3xQRPcsjJ/PmpCKy/BvygjLO6tRsR/2SC9UYay6W+BdguEYeft8g==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"lodash": "4.17.10",
|
||||
"npmlog": "4.1.2",
|
||||
"ws": "1.1.5"
|
||||
}
|
||||
},
|
||||
"diff": {
|
||||
"version": "3.5.0",
|
||||
"resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz",
|
||||
|
@ -7901,6 +7983,15 @@
|
|||
"resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.2.tgz",
|
||||
"integrity": "sha1-9wLmMSfn4jHBYKgMFVSstw1QR+U="
|
||||
},
|
||||
"get-port": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/get-port/-/get-port-2.1.0.tgz",
|
||||
"integrity": "sha1-h4P53OvR7qSVozThpqJR54iHqxo=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"pinkie-promise": "2.0.1"
|
||||
}
|
||||
},
|
||||
"get-stdin": {
|
||||
"version": "5.0.1",
|
||||
"resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-5.0.1.tgz",
|
||||
|
@ -8063,6 +8154,12 @@
|
|||
"lodash": "4.17.10"
|
||||
}
|
||||
},
|
||||
"growl": {
|
||||
"version": "1.10.3",
|
||||
"resolved": "https://registry.npmjs.org/growl/-/growl-1.10.3.tgz",
|
||||
"integrity": "sha512-hKlsbA5Vu3xsh1Cg3J7jSmX/WaW6A5oBeqzM88oNbCRQFz+zUaXm6yxS4RVytp1scBoJzSYl4YAEOQIt6O8V1Q==",
|
||||
"dev": true
|
||||
},
|
||||
"growly": {
|
||||
"version": "1.3.0",
|
||||
"resolved": "https://registry.npmjs.org/growly/-/growly-1.3.0.tgz",
|
||||
|
@ -11452,6 +11549,51 @@
|
|||
"resolved": "https://registry.npmjs.org/mobx/-/mobx-2.7.0.tgz",
|
||||
"integrity": "sha1-zz2C0YwMp/RY2PKiQIF7PcflSgE="
|
||||
},
|
||||
"mocha": {
|
||||
"version": "5.1.1",
|
||||
"resolved": "https://registry.npmjs.org/mocha/-/mocha-5.1.1.tgz",
|
||||
"integrity": "sha512-kKKs/H1KrMMQIEsWNxGmb4/BGsmj0dkeyotEvbrAuQ01FcWRLssUNXCEUZk6SZtyJBi6EE7SL0zDDtItw1rGhw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"browser-stdout": "1.3.1",
|
||||
"commander": "2.11.0",
|
||||
"debug": "3.1.0",
|
||||
"diff": "3.5.0",
|
||||
"escape-string-regexp": "1.0.5",
|
||||
"glob": "7.1.2",
|
||||
"growl": "1.10.3",
|
||||
"he": "1.1.1",
|
||||
"minimatch": "3.0.4",
|
||||
"mkdirp": "0.5.1",
|
||||
"supports-color": "4.4.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"commander": {
|
||||
"version": "2.11.0",
|
||||
"resolved": "https://registry.npmjs.org/commander/-/commander-2.11.0.tgz",
|
||||
"integrity": "sha512-b0553uYA5YAEGgyYIGYROzKQ7X5RAqedkfjiZxwi0kL1g3bOaBNNZfYkzt/CL0umgD5wc9Jec2FbB98CjkMRvQ==",
|
||||
"dev": true
|
||||
},
|
||||
"debug": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz",
|
||||
"integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"ms": "2.0.0"
|
||||
}
|
||||
},
|
||||
"supports-color": {
|
||||
"version": "4.4.0",
|
||||
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.4.0.tgz",
|
||||
"integrity": "sha512-rKC3+DyXWgK0ZLKwmRsrkyHVZAjNkfzeehuFWdGGcqGDTZFH73+RH6S/RDAAxl9GusSjZSUWYLmT9N5pzXFOXQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"has-flag": "2.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"moment": {
|
||||
"version": "2.22.1",
|
||||
"resolved": "https://registry.npmjs.org/moment/-/moment-2.22.1.tgz",
|
||||
|
@ -11890,6 +12032,12 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"node-version": {
|
||||
"version": "1.1.3",
|
||||
"resolved": "https://registry.npmjs.org/node-version/-/node-version-1.1.3.tgz",
|
||||
"integrity": "sha512-rEwE51JWn0yN3Wl5BXeGn5d52OGbSXzWiiXRjAQeuyvcGKyvuSILW2rb3G7Xh+nexzLwhTpek6Ehxd6IjvHePg==",
|
||||
"dev": true
|
||||
},
|
||||
"nopt": {
|
||||
"version": "4.0.1",
|
||||
"resolved": "https://registry.npmjs.org/nopt/-/nopt-4.0.1.tgz",
|
||||
|
@ -13769,6 +13917,12 @@
|
|||
"resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz",
|
||||
"integrity": "sha1-mEcocL8igTL8vdhoEputEsPAKeM="
|
||||
},
|
||||
"promise-polyfill": {
|
||||
"version": "6.1.0",
|
||||
"resolved": "https://registry.npmjs.org/promise-polyfill/-/promise-polyfill-6.1.0.tgz",
|
||||
"integrity": "sha1-36lpQ+qcEh/KTem1hoyznTRy4Fc=",
|
||||
"dev": true
|
||||
},
|
||||
"prop-types": {
|
||||
"version": "15.6.1",
|
||||
"resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.6.1.tgz",
|
||||
|
@ -16137,6 +16291,15 @@
|
|||
"jsonify": "0.0.0"
|
||||
}
|
||||
},
|
||||
"shell-utils": {
|
||||
"version": "1.0.9",
|
||||
"resolved": "https://registry.npmjs.org/shell-utils/-/shell-utils-1.0.9.tgz",
|
||||
"integrity": "sha512-JbTHnKpMyj9TUUbL+Us2Rx2iVHFvH5QyQoke9SN1L0pueiZeO2Gzlzopmloi7oqObL4qtvdSuZPE3UfdIzmlag==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"lodash": "4.17.10"
|
||||
}
|
||||
},
|
||||
"shelljs": {
|
||||
"version": "0.8.2",
|
||||
"resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.8.2.tgz",
|
||||
|
@ -17243,6 +17406,12 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"tail": {
|
||||
"version": "1.2.3",
|
||||
"resolved": "https://registry.npmjs.org/tail/-/tail-1.2.3.tgz",
|
||||
"integrity": "sha1-sI1vp5+5KIaWMaNBpRwUSXwcQlU=",
|
||||
"dev": true
|
||||
},
|
||||
"tapable": {
|
||||
"version": "0.2.8",
|
||||
"resolved": "https://registry.npmjs.org/tapable/-/tapable-0.2.8.tgz",
|
||||
|
@ -17287,6 +17456,15 @@
|
|||
"xtend": "4.0.1"
|
||||
}
|
||||
},
|
||||
"telnet-client": {
|
||||
"version": "0.15.3",
|
||||
"resolved": "https://registry.npmjs.org/telnet-client/-/telnet-client-0.15.3.tgz",
|
||||
"integrity": "sha512-GSfdzQV0BKIYsmeXq7bJFJ2wHeJud6icaIxCUf6QCGQUD6R0BBGbT1+yLDhq67JRdgRpwyPwUbV7JxFeRrZomQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"bluebird": "3.5.1"
|
||||
}
|
||||
},
|
||||
"temp": {
|
||||
"version": "0.8.3",
|
||||
"resolved": "https://registry.npmjs.org/temp/-/temp-0.8.3.tgz",
|
||||
|
|
15
package.json
15
package.json
|
@ -87,6 +87,7 @@
|
|||
"babel-preset-es2015": "^6.24.1",
|
||||
"babel-preset-react-native": "^4.0.0",
|
||||
"codecov": "^3.0.2",
|
||||
"detox": "^7.3.5",
|
||||
"eslint": "^4.19.1",
|
||||
"eslint-config-airbnb": "^16.1.0",
|
||||
"eslint-plugin-import": "^2.12.0",
|
||||
|
@ -96,6 +97,7 @@
|
|||
"identity-obj-proxy": "^3.0.0",
|
||||
"jest": "^22.4.4",
|
||||
"jest-cli": "^22.4.4",
|
||||
"mocha": "^5.1.1",
|
||||
"react-dom": "^16.3.2",
|
||||
"react-native-bundle-visualizer": "^1.2.0",
|
||||
"react-test-renderer": "^16.3.2",
|
||||
|
@ -104,6 +106,9 @@
|
|||
"reactotron-redux-saga": "^1.13.0"
|
||||
},
|
||||
"jest": {
|
||||
"testPathIgnorePatterns": [
|
||||
"e2e"
|
||||
],
|
||||
"preset": "react-native",
|
||||
"coverageDirectory": "./coverage/",
|
||||
"collectCoverage": true,
|
||||
|
@ -115,5 +120,15 @@
|
|||
"engines": {
|
||||
"node": ">=8.x",
|
||||
"npm": ">=4.x"
|
||||
},
|
||||
"detox": {
|
||||
"configurations": {
|
||||
"ios.sim.debug": {
|
||||
"binaryPath": "ios/build/Build/Products/Debug-iphonesimulator/RocketChatRN.app",
|
||||
"build": "xcodebuild -project ios/RocketChatRN.xcodeproj -scheme RocketChatRN -configuration Debug -sdk iphonesimulator -derivedDataPath ios/build",
|
||||
"type": "ios.simulator",
|
||||
"name": "iPhone 7"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue