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?
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