Search code examples
calabashcalabash-android

How can I test field validation?


I have validation code which sets the error of the EditText when it doesn't satisfy the requirements.

field.setError(errorMessage);

This puts a little red circle with an exclamation point over the field, and when I touch the field, it displays my error message in a black box. Great!

Now I want calabash to verify that the field failed validation. For the moment at least I'm not concerned about the specific error message - I just want to know that an error message is displayed (or I would be happy to settle for the exclamation point, but since I can't find it using query in console, I suspect that would be harder).

This query:

query("android.widget.PopupWindow$PopupViewContainer")

finds the error message window if it is present.

But it's only present if the field with the error has focus. And I only set the error when the field loses focus. That should be OK - my step can enter text into the field, leave the field, and come back. When I do these things manually, the error message window is displayed. What I have not yet been able to do is to write a step which does these things and reliably displays the error message window. I have tried

query("EditText id:'#{field_id}'", {:setText => bad_text})
touch(query("* id:'#{another_field_id}'")[0])
touch(query("* id:'#{field_id}'")[0])

and

query("EditText id:'#{field_id}'", {:setText => bad_text})
system("#{default_device.adb_command} shell input keyevent KEYCODE_TAB")
touch(query("* id:'#{field_id}'")[0])

and both of these behave correctly for the first EditText, but fail to show the error message window for subsequent EditTexts. Why? What's the right way to do this?


Solution

  • There are multiple things with your calabash commands that could cause your tests to fail.

    1) Do not use touch(query(...

    # bad
    touch(query("q"))
    # good
    touch("q")
    

    2) Do not use 'setText' to simulate entering text

    # bad
    query("EditText", {:setText => 'bad_text'})
    # good
    enter_text("EditText", 'bad_text')
    

    3) Do not use any input events

    Input events like system("#{default_device.adb_command} shell input keyevent KEYCODE_TAB") are impossible for the user to perform on most devices, as very few Android devices have a physical keyboard. Use press_user_action_button to simulate the user pressing the input key appearing instead of the enter key.