mhyousefi
mhyousefi

Reputation: 1234

Detox _ Failed to type string because keyboard was not shown on screen

I'm trying to test my react-native app using detox, waiting for a text input to be visible and typing text in it. My spec JS file looks like this:

describe('FiestTest', () => {
  beforeEach(async () => {
    await device.reloadReactNative()
  })

  it('Login to a test account', async () => {
    // LoginPage: entering phone number moving to next page
    await expect(element(by.id('LoginPage-phoneInput'))).toBeVisible()
    await element(by.id('LoginPage-phoneInput')).typeText('<someNumber>')
  })
})

And the error I get is:

FiestTest
    1) Enter phone number and tap on button


  0 passing (15s)
  1 failing

  1) FiestTest Enter phone number and tap on button:
     Error: An action failed. Please refer to the error trace below.
Exception with Action: {
  "Action Name" : "Type '6219'",
  "Element Matcher" : "(((respondsToSelector(accessibilityIdentifier) && accessibilityID('ValidatePage-txtField')) && !(kindOfClass('RCTScrollView'))) || (kindOfClass('UIScrollView') && ((kindOfClass('UIView') || respondsToSelector(accessibilityContainer)) && ancestorThatMatches(((respondsToSelector(accessibilityIdentifier) && accessibilityID('ValidatePage-txtField')) && kindOfClass('RCTScrollView'))))))"
}

Error Trace: [
  {
    "Description" : "Failed to type string '6219', because keyboard was not shown on screen.",
    "Error Domain" : "com.google.earlgrey.ElementInteractionErrorDomain",
    "Error Code" : "2",
    "File Name" : "GREYKeyboard.m",
    "Function Name" : "+[GREYKeyboard typeString:inFirstResponder:error:]",
    "Line" : "168"
  }
]

I'm using the following tools:

$ npm outdate
Package                                  Current          Wanted         Latest  Location
apollo-client                              1.4.0           1.9.0          1.9.0  <appName>
babel-jest                                19.0.0          19.0.0         20.0.3  <appName>
babel-plugin-module-resolver               2.7.0           2.7.1          2.7.1  <appName>
eslint                                    3.19.0          3.19.0          4.4.1  <appName>
eslint-plugin-import                       2.2.0           2.7.0          2.7.0  <appName>
eslint-plugin-node                         4.2.2           4.2.3          5.1.1  <appName>
eslint-plugin-react                       6.10.3          6.10.3          7.1.0  <appName>
eslint-plugin-react-native                 2.3.2           2.3.2          3.0.1  <appName>
graphql-tag                                2.2.1           2.4.2          2.4.2  <appName>
jest                                      19.0.2          19.0.2         20.0.4  <appName>
moment-jalaali                             0.6.1           0.6.1          0.7.0  <appName>
native-base                                2.1.4           2.3.1          2.3.1  <appName>
react                             16.0.0-alpha.6  16.0.0-alpha.6         15.6.1  <appName>
react-apollo                               1.4.2          1.4.11         1.4.11  <appName>
react-native                              0.44.0          0.44.0         0.47.1  <appName>
react-native-adjust                       4.11.3          4.11.4         4.11.4  <appName>
react-native-fcm                           6.2.3           6.2.3          8.0.0  <appName>
react-native-popup-menu                    0.7.3           0.7.5          0.8.0  <appName>
react-native-router-flux                  3.39.1          3.41.0  4.0.0-beta.16  <appName>
react-native-sentry                       0.12.9         0.12.12         0.15.1  <appName>
react-native-smart-splash-screen           2.3.3           2.3.4          2.3.4  <appName>
react-test-renderer                       15.4.2          15.4.2         15.6.1  <appName>
redux                                      3.6.0           3.7.2          3.7.2  <appName>
redux-persist                              4.6.0           4.8.3          4.8.3  <appName>

And this is my podfile:

# Uncomment this line to define a global platform for your project
# platform :ios, '9.0'

target '<appName>' do
  # Uncomment this line if you're using Swift or would like to use dynamic frameworks
  # use_frameworks!

  # Pods for <appName>

  pod 'Firebase'
  pod 'Firebase/Core'
  pod 'Firebase/Analytics'
  pod 'Firebase/Messaging'

  pod 'Yoga', :path => '../node_modules/react-native/ReactCommon/yoga'
  pod 'React', :path => '../node_modules/react-native', :subspecs => [
    'RCTText',
    'RCTImage',
    'RCTNetwork',
    'RCTWebSocket',
  ]

  #target '<appName>-tvOSTests' do
  #  inherit! :search_paths
    # Pods for testing
  #end

  #target '<appName>Tests' do
  #  inherit! :search_paths
    # Pods for testing
  #end

end

#target '<appName>-tvOS' do
  # Uncomment this line if you're using Swift or would like to use dynamic frameworks
  # use_frameworks!

  # Pods for <appName>-tvOS

#  target '<appName>-tvOSTests' do
#    inherit! :search_paths
    # Pods for testing
#  end

#end

For now I'm just using a sleep command like bellow in order to give me time to manually insert the string. However, this should not be a permanent solution...

function sleep (ms) {
return new Promise(resolve => setTimeout(resolve, ms))
}

await sleep(milliseconds)
// what needs to happen after I manually enter the code

I've also commented in a Detox issue on GitHub, but was wondering if anyone has had the same experience and has found a solution here.

Thanks for your assistance in advance!

Upvotes: 5

Views: 4560

Answers (4)

Leo
Leo

Reputation: 10833

I tried the various solutions listed here, but no avail.

What worked consistently for me was:

  • Tap on any text field in your app
  • Simulator > Hardware > Keyboard > Toggle Software Keyboard (⌘K)

The reason this works is because it automatically toggles the builtin keyboard on anytime a text field element is tapped, which is a mandatory prerequisite when calling typeText.

I've added a pull request to update the documentation which has now been approved.

Upvotes: 0

all9lives
all9lives

Reputation: 33

I wasn't able to get get the software keyboard work consistently but .replaceText() did work pretty well for me. waitFor() was also very useful.

Upvotes: -1

Just01
Just01

Reputation: 79

please checkout here: https://github.com/wix/detox/blob/master/docs/APIRef.ActionsOnElement.md

on typeText() method

Note: Make sure hardware keyboard is disconnected. Otherwise, Detox may fail when attempting to type text.

To make sure hardware keyboard is disconnected, open the simulator from Xcode and make sure Hardware -> Keyboard -> Connect Hardware Keyboard is deselected (or press ⇧⌘K).

Upvotes: 6

Mircea
Mircea

Reputation: 187

You should run

await element(by.id('LoginPage-phoneInput')).tap();

before

await element(by.id('LoginPage-phoneInput')).typeText('<someNumber>')

Upvotes: 5

Related Questions