3

I recently discovered SitePrism via the rubyweekly email. It looks amazing. I can see its going to be the future.

The examples I have seen are mostly for cucumber steps. I am trying to figure out how one would go about using SitePrism with rspec.

Assuming @home_page for the home page, and @login_page for the login_page I can understand that

@home_page.load # => visit @home.expanded_url

however, the part I am not sure about, is if I think click on for example the "login" link, and the browser in Capybara goes to the login page - how I can then access an instance of the login page, without loading it.

    @home_page = HomePage.new
    @home_page.load
    @home.login_link.click
    # Here I know the login page should be loaded, so I can perhaps do 

    @login_page = LoginPage.new
    @login_page.should be_displayed
    @login_page.email_field.set("some@email.com")
    @login_page.password_field.set("password")
    @login_page.submit_button.click

etc...

That seems like it might work. So, when you know you are supposed to be on a specific page, you create an instance of that page, and somehow the capybara "page" context, as in page.find("a[href='/sessions/new']") is transferred to the last SitePrism object?

I just feel like I am missing something here. I'll play around and see what I can figure out - just figured I might be missing something. I am looking through the source, but if anyone has figured this out... feel free to share :)

Nat Ritmeyer
  • 5,634
  • 8
  • 45
  • 58
Apie
  • 6,371
  • 7
  • 27
  • 25

1 Answers1

4

What you've assumed turns out to be exactly how SitePrism works :) Though you may want to check the epilogue of the readme that explains how to save yourself from having to instantiate page objects all over your test code. Here's an example:

# our pages

class Home < SitePrism::Page
  #...
end

class SearchResults < SitePrism::Page
  #...
end

# here's the app class that represents our entire site:

class App
  def home
    Home.new
  end

  def results_page
    SearchResults.new
  end
end

# and here's how to use it:

#first line of the test...
@app = App.new
@app.home.load
@app.home.search_field.set "sausages"
@app.home.search_button.click
@app.results_page.should be_displayed
Nat Ritmeyer
  • 5,634
  • 8
  • 45
  • 58
  • I don't really like that with such pattern every invocation of `home` returns a new object. I'd prefer to preserve knowlegde about current state of page inside page object – Andrei Botalov Apr 06 '13 at 09:08
  • 2
    It looks to me that code above violates some priciples of [Page Object](https://code.google.com/p/selenium/wiki/PageObjects): "Try not to expose the internals of the page", "The public methods represent the services that the page offers". Code in answer exposes `search_field` and `search_button`. It should be a service method with signature e.g. `search(keyword)` instead. – Andrei Botalov Apr 06 '13 at 14:15
  • 1
    The way I have used this so far is to treat the page objects not as anything more than a presenter for the current page. So, instead of littering my rspec features with css selectors that I have to update in various places if it changes, I can define it in one place. I still take responsibility for what is set in the elements whenever I am on the page. I might be using it wrong though. – Apie Apr 07 '13 at 12:56