2

Is there an easy way to reference @current_page in both the step_definition.rb files and the PageObject.rb files?

Examples using the @current_page in the Calabash docs force you to always do something like:

@current_page = @current_page.login(user)

After login you are on a new page and you must pass back a reference to this for the @current_page. It would be nice to just set @current_page in the login method and not have to do that @current_page = @current_page.login(user) assignment every time you call a method that brings you to a new page.

Is there a good way to do this?

slindsey3000
  • 4,053
  • 5
  • 36
  • 56

1 Answers1

4

Is there a good way to do this?

It is not recommended that you keep a reference to the current page.

I could demonstrate a number of ways to keep a reference, but I don't want to because it is not a good pattern.

At risk of getting my response marked as a non-answer, I will try to explain why.

Examples using the @current_page in the Calabash docs force you to always do something like:

In my opinion, the docs are not good. I have been trying to get them changed. There is general agreement on this topic among the Calabash developers, but none of us has had the time to change them.

It is not a best practice to use @current_page to track the current page between steps. The reason is that the reader can never know what the value of the @current_page is just by looking at it: it could have been set to anything by subsequent step.

The best practice is to create a temporary page object whenever you need one.

# Bad
@current_page = @current_page.login(user)

# Good
login_page = page(LoginPage).await
some_other_page = login_page.login(user)
some_other_page.await

force you to always do something like:

The @current_page is a Cucumber World variable; there is nothing special about it. It could have been called: @page or @screen or @foobar. When I say there is nothing special I mean that Calabash does not use @current_page anywhere internally.

It would be nice to just set @current_page in the login method and not have to do that @current_page = @current_page.login(user) assignment every time you call a method that brings you to a new page.

Is there a good way to do this?

In general, it is not a good idea save state in your cucumber tests or page model. If you need a piece of information in a Step or method, you should ask for it by querying the app.

There are, of course, exceptions. Imagine an app with a Dashboard page that has a Reminders icon with badge count that represents the number of unread reminders.

 Scenario:  Verify the reminders badge count
   Given I am looking at the Dashboard
   And I make a note of the reminders badge count
   When I go to the reminders page
   Then the reminders badge count should match the unread reminders

It is reasonable to store the badge count in a Cucumber World variable so you can use it in a subsequent Step.

 And(/^I make a note of the reminders badge count$/) do
   dashboard = page(Dashboard).await
   @reminder_badge_count = dashboard.reminder_badge_count
 end

 When(/^I go to the reminders page$/) do
   dashboard = page(Dashboard).await
   dashboard.navigate_to(:reminders)
 end

 Then(/^the reminders badge count should match the unread reminders$/) do
   reminders_page = page(Reminders).await
   unread_actual = reminders_page.unread_reminders
   unless unread_actual == @reminder_badge_count
     screenshot_and_raise("Expected badge count '#{@reminder_badge_count}' to match unread count '#{unread_actual}") 
   end
 end
jmoody
  • 2,480
  • 1
  • 16
  • 22
  • 1
    Thank you very much. You really addressed a lot of things I was thinking about. I agree on the documentation. Our teams have all struggled at times getting Calabash running. Updated docs would for sure get a lot more people using Calabash. I do enjoy it now that we have it running! – slindsey3000 Mar 24 '15 at 13:43
  • 1
    +1 this is a test/Ruby architecture question more than a Calabash-specific issue. @slindsey3000 please continue to post questions and I'll do my best to chime in. Getting Calabash running for Android was nearly automatic, but the iOS implementation (with pods) was much more complicated - all due to things that were already complicated with iOS. – adam reed Mar 24 '15 at 14:35
  • yes @adamreed the Android setup was pretty painless for us. And yes iOS was tough I believe because of (pods). I was able to get the sample apps up and running for Android and iOS very easily for Calabash. Our application would not fire up correctly though with Calabash. I am not an iOS developer so I had some difficulties getting a build that I could test. – slindsey3000 Mar 24 '15 at 15:44
  • @jmoody I have implemented a BasePage class for methods common to all pages. Do you recommend this? I did have to add `require_relative '../ios/pages/_base.rb'` in 01_launch.rb. Do you feel this is a best practice? an underscore `_base` is just so it sits at the top of the file list. – slindsey3000 Mar 24 '15 at 15:47
  • 1
    Your experiences with CocoaPods + Calabash iOS has mirrored my own. I usually manage the calabash.framework without CocoaPods. – jmoody Mar 24 '15 at 16:15
  • 1
    @jmoody we had some conversations over IRC a few weeks back and now that I've had the experience of configuring our app, over half the complication was the app itself. I've been able to configure other apps with no difficulty in minutes since then, even with pods. – adam reed Mar 24 '15 at 20:12
  • @adamreed how do you go about getting a build for QA with the Calabash framework mixed in... with CocoaPods – slindsey3000 Mar 26 '15 at 20:03
  • 1
    @slindsey3000 - if you post another question I'd be happy to share it there, I think we're way down in a rabbit hole here which may make it difficult for people to find the answer! – adam reed Mar 26 '15 at 20:09