4

I do have a problem using detox, and I have absolutely no idea why. I know this kind of issue has been posted before but none of them really seem to answer my problem. I'll first explain it with details and then post some code & configurations.

Explanation

I'd like to first try the login functionality of my app. I have a first screen where the user inputs his team and presses a button to go to another screen to login. I'm requesting a server to check if the team exists. If the team is wrong, he'll get an error message. I'd like to test that this error message shows up.

When running the following test, the red error message IS displayed, but the test ends in a timeout. This image shows you where the test stops.

This image

Code

Here is the test:

describe('Login', () => {
  it('should show error message after bad team', async () => {
    await element(by.id('selectTeam_teamInput')).typeText('failingTeam');
    await element(by.id('selectTeam_domainInput')).replaceText('mydomain.cloud');
    await element(by.id('selectTeam_nextButton')).tap();
    await expect(element(by.id('selectTeam_errorMessage'))).toExist();
    await expect(element(by.id('selectTeam_errorMessage'))).toBeVisible();
  });
});

Here is the view (The goToLogin method triggers the async call that changes the prop organisationInfosStatus to either success or error. When it's error, I display this error message):

<TouchableWithoutFeedback onPress={Keyboard.dismiss}>
  <View>
    {this.props.organisationInfosStatus === 'error' && (
      <View
        testID="selectTeam_errorMessage"
        style={{
          height: 24,
          marginBottom: 24,
          alignItems: 'center',
          justifyContent: 'center',
          borderWidth: 2,
          borderColor: 'white',
        }}
      >
        <Text style={{ color: theme.color.red.shade500, fontWeight: '500' }}>
          <Trad id="login.invalidTeam">Invalid team</Trad>
        </Text>
      </View>
    )}
    <View>
      <Text
        style={{
          marginHorizontal: 16,
          marginBottom: 24,
          fontSize: 18,
          lineHeight: 21,
          textAlign: 'center',
        }}
      >
        <Trad id="login.selectTeam">Please insert your team name</Trad>
      </Text>
      <View
        style={{
          paddingRight: 8,
          paddingLeft: 16,
          justifyContent: 'space-between',
          flexDirection: 'row',
          borderTopWidth: theme.border.width,
          borderBottomWidth: theme.border.width,
          borderColor: theme.color.grey.shade300,
        }}
      >
        <TextInput
          testID="selectTeam_teamInput"
          style={{ paddingVertical: 16, flex: 1 }}
          placeholder={TradSingleton.getTrad('login.organizationName')() || 'organization'}
          autoCapitalize="none"
          autoCorrect={false}
          onChangeText={teamName => this.setState({ teamName })}
          onSubmitEditing={this.goToLogin}
          returnKeyType="go"
          underlineColorAndroid="transparent"
          value={this.state.teamName}
        />
        <Text style={{ paddingVertical: 16 }}>.</Text>
        <View style={[{ flexDirection: 'row', justifyContent: 'space-between' }]}>
          <TextInput
            testID="selectTeam_domainInput"
            style={{
              paddingVertical: 16,
              marginRight: 8,
              minWidth: 50,
              maxWidth: 200,
            }}
            placeholder={TradSingleton.getTrad('login.domain')() || 'domain'}
            autoCapitalize="none"
            autoCorrect={false}
            onChangeText={domain => this.setState({ domain })}
            onSubmitEditing={this.goToLogin}
            returnKeyType="go"
            underlineColorAndroid="transparent"
            value={this.state.domain}
            keyboardType="email-address"
            ref="domainField"
          />
          <TouchableOpacity
            style={{
              backgroundColor: 'white',
              padding: 4,
              justifyContent: 'center',
              alignItems: 'center',
            }}
            onPress={() => {
              this.setState({ domain: '' });
              this.refs.domainField.focus();
            }}
            hitSlop={functions.hitSlop()}
          >
            <Icon
              icon={icon.get('close')}
              iconStyle={{ height: 12, width: 12, tintColor: theme.color.grey.shade500 }}
            />
          </TouchableOpacity>
        </View>
      </View>
      <Button
        onPress={this.goToLogin}
        testID="selectTeam_nextButton"
        containerStyle={[styleSheet.loginButton, { marginTop: 24 }]}
        disabled={this.state.loginButtonDisabled}
        textStyle={styleSheet.loginButtonText}
        tradId="utils.next"
      >
        Next
      </Button>
    </View>
  </View>
</TouchableWithoutFeedback>

Here is my init.js:

require('babel-polyfill');
const detox = require('detox');
const config = require('../package.json').detox;

before(async () => {
  await detox.init(config);
});

after(async () => {
  await detox.cleanup();
});

And finally my mocha.opts:

--recursive
--timeout 20000
--bail
--file e2e/init.js

I'm using react-native-router-flux but here are the different versions installer:

"react": "16.8.3",
"react-native": "^0.59.4",
"react-native-router-flux": "4.1.0-beta.5",
"react-navigation": "3.6.1",
"detox": "^12.1.3",

Other informations

Before upgrading to 0.59 I was on 0.57.1, same issue. Had the previous version or the router 4.0.6, same issue. I tried with expect, with waitFor and a timeout, same issue :/

I also tried the same test with a valid team, to see if it finds the next view basically. It ends in a timeout the exact same way.

Tell me if you need more informations :)

Thanks in advance !

Guillaume Munsch
  • 1,233
  • 17
  • 37
  • I guess you might need to ensure `done()` is called? Can you try changing your test to: `it('should show error message after bad team', async (done) => {` and calling `done()` at the end? – dbramwell Apr 09 '19 at 14:45
  • Yep, tried it as well. It's never reached. It looks like the `await expect(element(by.id('selectTeam_errorMessage'))).toExist();` leads into an infinite loop even though the message is displayed – Guillaume Munsch Apr 09 '19 at 15:02
  • How about with [wait for](https://github.com/wix/Detox/blob/master/docs/APIRef.waitFor.md#toexist)? `waitFor(expect(element(by.id('selectTeam_errorMessage'))).toExist().withTimeout(2000);` – dbramwell Apr 09 '19 at 15:14
  • Tried as well. Same issue. `await waitFor(element(by.id('selectTeam_errorMessage'))) .toExist() .withTimeout(2000); await waitFor(element(by.id('selectTeam_errorMessage'))) .toBeVisible() .withTimeout(2000); done();` Test looked like this. Times out the exact same way – Guillaume Munsch Apr 09 '19 at 15:19

0 Answers0