Calabash not touching buttons properly after background

485 views Asked by At

My environment: Xcode: 7.2.1 Simulator: iOS iPad Air 9.1 Calabash: 0.17.1

Currently, I'm having an issue with my iOS application not touching buttons correctly after I background my application. Here are the general cucumber steps where the issue happens:

When I send the app to the background for 2 seconds
And I skip logging in to MyApp
And I wait and wait
And I should see "Speed"
And I wait for 10 seconds
And I touch "Speed"

Here is the code for the sending the app to background step:

Given /^I send the app to the background for ([\d\.]+) second(?:s)?$/ do |num_seconds|
  num_seconds = num_seconds.to_f
  send_app_to_background(num_seconds)
end

Basically the touching hits a snag only after I send the app to background. If I take that step out, Calabash touches the button like expected. I included the step where it sees "Speed", just to make sure that Calabash can actually see the button, which it could, since it goes green for that step, as well as the waiting step. But on touching "Speed", Calabash goes into a state where it keeps trying to touch it, but since it doesn't, it hangs on that step indefinitely. I suspect this may be either be a Calabash or UIAutomation bug (https://github.com/calabash/calabash-ios/issues/836), since everything works as expected until or unless I send my app to background, but I wanted to be 100% sure, in case I'm doing something wrong that I'm not seeing.

Does anyone have any ideas as to what the issue may be?

Update:

According to https://groups.google.com/forum/#!topic/calabash-ios/NZAmTp6ckrk, sending app to background is still unimplemented, and when I check the code for send_app_to_background, it does look like it:

def send_app_to_background(secs)
  raise 'Not implemented when running without instruments / UIA'
end

Does anyone have a way to work around this for their tests? Running this on a physical device is not an option for me, it has to be done with a simulator.

Update:

Following https://github.com/calabash/calabash-ios/issues/556, I changed sending the app to background code to follow a workaround:

Given /^I send the app to the background for ([\d\.]+) second(?:s)?$/ do |num_seconds|
  num_seconds = num_seconds.to_f
  uia_send_app_to_background(num_seconds)
end

And the implementation of uia_send_app_to_background is:

def uia_send_app_to_background(secs)
  #uia_handle_command(:deactivate, secs)
  #Temporary workaround: https://github.com/calabash/calabash-ios/issues/556
  js_deactivate = %Q[var x = target.deactivateAppForDuration(#{secs}); var MAX_RETRY=5, retry_count = 0; while (!x && retry_count < MAX_RETRY) { x = target.deactivateAppForDuration(#{secs}); retry_count += 1}; x]
  uia(js_deactivate)
end

However, for me, this workaround doesn't seem to work. The app gets pushed to the background, but never goes back to foreground. When I stop that step in irb after a few minutes of waiting, I get this error:

When I send the app to the background for 2 seconds        # features/step_definitions/common.rb:91
  Could not parse response ''; the app has probably crashed (RuntimeError)
  ./features/step_definitions/common.rb:93:in `/^I send the app to the background for ([\d\.]+) second(?:s)?$/'
  features/display_mapping_units_from_2630.feature:216:in `When I send the app to the background for 2 seconds'

Update

I tried these workaround steps, but touching after backgrounding still doesn't work, and I also tried this on 8.4 simulator, where it doesn't work either, which makes me suspect even more it's an Xcode 7+ issue that needs to be resolved:

When(/^I background the app$/) do
  open_app_via_simctl("com.apple.mobilesafari")
  sleep(2)
end

When(/^I launch the app$/) do
  open_app_via_simctl("com.me.MyApp-cal")
  sleep(2)
end

Steps:

And I background the app
And I wait
And I launch the app
And I wait
And I should see "Button1"
And I wait for 10 seconds
And I touch "Button1"

Calabash succeeds in seeing Button1, but when it tries to touch Button1, in 9.1 simulator, Calabash hangs indefinitely, trying to find the button, and in 8.4 simulator, I get an error right away that Calabash can't find the view "Button1".

1

There are 1 answers

12
jmoody On BEST ANSWER

Issue #836 was closed fixed in November. The Google forum post from 2013 and issue #556 is from 2014. Anything later than a couple months ago should be treated with suspicion.

Don't call the uia_send_app_to_background, that API is broken (by Apple). In general stick with the non-UIA API (don't call uia_* methods unless absolutely necessary).

Update Calabash to latest released version (0.18.1 as of today) and try your tests again.

$ be calabash-ios console
> start_test_server_in_background

# Can touch before background
> touch("view marked:'my view'")

> send_app_to_background(1)

# Can touch after resuming from background
> touch("view marked:'my view'")

The solutions below will not work. Your app will go to the background if you open another app. However, if you open your app with simctl, instruments will no longer have a connection to the application and gestures will fail.

When(/^I background the app$/) do
  open_app_via_simctl("com.apple.mobilesafari")
  sleep(2)
end

When(/^I launch the app$/) do
  open_app_via_simctl("com.me.MyApp-cal")
  sleep(2)
end