slindsey3000
slindsey3000

Reputation: 4271

Share @variable in step_definitions and PageObject methods possible?

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?

Upvotes: 2

Views: 360

Answers (1)

jmoody
jmoody

Reputation: 2480

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

Upvotes: 4

Related Questions