msmith1114
msmith1114

Reputation: 3229

Capybara instance of "browser" for Page Object Model?

Im writing a framework using Capybara and the Page Object Model for a web application. It's my first time writing my own framework and using PoM for automation.

My base "Page Object" essentially initializes the driver and is used in every other page object child class (for the individual pages)

class PageObject
    include Capybara::DSL
    BASE_URL = 'https://www.atesturl.com'
    Capybara.default_max_wait_time = 5

    def initialize

        Capybara.register_driver :selenium_chrome do |app|
            Capybara::Selenium::Driver.load_selenium
            browser_options = ::Selenium::WebDriver::Chrome::Options.new.tap do |opts|
              # Workaround https://bugs.chromium.org/p/chromedriver/issues/detail?id=2650&q=load&sort=-id&colspec=ID%20Status%20Pri%20Owner%20Summary
              opts.args << '--disable-site-isolation-trials'
            end
            Capybara::Selenium::Driver.new(app, browser: :chrome, options: browser_options)
          end

        Capybara.register_driver :selenium_chrome_headless do |app|
            Capybara::Selenium::Driver.load_selenium
            browser_options = ::Selenium::WebDriver::Chrome::Options.new.tap do |opts|
              opts.args << '--headless'
              opts.args << 'window-size=2880,1800'
              opts.args << '--disable-gpu' if Gem.win_platform?
              #opts.args << '--remote-debugging-port=9222'
              # Workaround https://bugs.chromium.org/p/chromedriver/issues/detail?id=2650&q=load&sort=-id&colspec=ID%20Status%20Pri%20Owner%20Summary
              opts.args << '--disable-site-isolation-trials'
            end
            Capybara::Selenium::Driver.new(app, browser: :chrome, options: browser_options)
          end

        Capybara.current_driver = :selenium_chrome
    end

    def visit_url
        visit BASE_URL
    end

  end

In most examples of PoM I see the methods returning an instance of that page object, but generally they use some @browser instance variable that is passed around. Within my test scripts I simple call an instance of the Base page object class via let(:p) {PageObject.new} and then p.visit_url then make new instances of the other page objects via new....but this seems like the wrong way to do it.

How exactly do I return a instance of the @browser or driver that I can pass around? And how should I be calling it in my spec?

Upvotes: 0

Views: 857

Answers (1)

Thomas Walpole
Thomas Walpole

Reputation: 49890

You don't want to be registering your drivers in the initialize for the base PageObject since that means every object created will be registering new driver configs - which isn't desirable.

When you include Capybara::DSL into your class you're including methods that end up calling methods on Capybara.current_session. ie visit => Capybara.current_session.visit. The result of Capybara.current_session is the "@browser" instance you're asking about since it encapsulates the driver/browser instance. The issue with the way you've currently implemented that is that if any code changes the current session then all your objects will suddenly refer to the new session. If instead you store a reference to the session you want the object to use in each object and call the Capybara methods on that session rather than using Capybara::DSL (@session.visit ...) then you can be sure the session an object is using doesn't change unexpectedly.

Also note that things like Capybara.default_max_wait_time, `Capybara.current_driver', etc are global settings so setting them inside your PageObject class isn't a great idea.

Upvotes: 1

Related Questions