Uninitialized Constant (NameError) using Cucumber & SitePrism

790 views Asked by At

I am creating a testing automation using Cucumber and SitePrism. I got an error when running cucumber command to start the scenario and got this error:

uninitialized constant HomePage::Navbar (NameError)
.../features/page_object/home_page.rb:4:in `<class:HomePage>'
.../features/page_object/home_page.rb:1:in `<top (required)>'

I have 3 Ruby classes located in a separate files


features/page_object/home_page.rb

class HomePage < SitePrism::Page
  set_url "/"

  section :navbar, Navbar, "header"
  element :flash_message, ".flash__text"
  element :username_link, ".c-nav-list__link.u-fg--yellow"
end

features/page_object/navbar/main.rb

class Navbar < SitePrism::Section
  section :login_section, LoginSection, "#new_user_session"
  element :login_button, :xpath, "//a[@id='login_link']"
end

features/page_object/navbar/login_section.rb

class LoginSection < SitePrism::Section
  element :username_field, :xpath, "//input[@id='user_session_username'"
  element :password_field, :xpath, "//input[@id='user_session_password'"
  element :remember_me_checkbox,
          :xpath, "//input[@id='user_session_remember_me']"
  element :forgot_password_link, :xpath, "//a[text()='Lupa Password?']"
  element :submit_button, :xpath, "//button[@type='submit']"
  element :facebook_login_button, :xpath, "//a[@id='fb_login_link']"
  element :gplus_login_button, :xpath, "//a[@id='gplus_login_link']"

  def login(username, password)
    self.username_field.set(username)
    self.password_field.set(password)
    self.submit_button.click
  end
end

Need help so the automation could run as it should be (with no error). Any solution?

2

There are 2 answers

0
Luke Hill On

In Ruby (And more specifically cucumber), you need to ensure you load your POM inside-out. I.e. Sections first before Pages.

Why??

Because when you use the SitePrism DSL, we are running scripted methods. If you call the Page's scripted methods, they will refer to a Section Class that may or may not have been loaded (Depending on the Autoloader in Cucumber, which you cannot control).

If you define Sections first which don't call any other sections, then there won't be any inherent problems.

Now if you are only using Sections. Or somehow you're confident that you won't ever run into this issue, then you won't encounter any issues. But what we advise (And perhaps we should document this better), is that you should load the smallest items (Sections), first before Pages.

0
Micah Resnick On

The section needs to be loaded before the page object that uses it. You can either put the sections into the same file as the page object that uses them:

features/page_object/home_page.rb

# loads before Navbar class uses it
class LoginSection < SitePrism::Section
  ...  
end

# loads before HomePage class uses it
class Navbar < SitePrism::Section
  section :login_section, LoginSection, "#new_user_session"
  element :login_button, :xpath, "//a[@id='login_link']"
end

class HomePage < SitePrism::Page
  section :navbar, Navbar, "header"
end

Or you can keep the files separate and add require statements to make sure each class loads after the sections it depends on:

features/page_object/home_page.rb

require_rel 'navbar/main'

class HomePage < SitePrism::Page
  set_url "/"

  section :navbar, Navbar, "header"
  element :flash_message, ".flash__text"
  element :username_link, ".c-nav-list__link.u-fg--yellow"
end

features/page_object/navbar/main.rb

require_rel 'login_section'

class Navbar < SitePrism::Section
  section :login_section, LoginSection, "#new_user_session"
  element :login_button, :xpath, "//a[@id='login_link']"
end

features/page_object/navbar/login_section.rb

class LoginSection < SitePrism::Section
  element :username_field, :xpath, "//input[@id='user_session_username'"
  element :password_field, :xpath, "//input[@id='user_session_password'"
  element :remember_me_checkbox,
          :xpath, "//input[@id='user_session_remember_me']"
  element :forgot_password_link, :xpath, "//a[text()='Lupa Password?']"
  element :submit_button, :xpath, "//button[@type='submit']"
  element :facebook_login_button, :xpath, "//a[@id='fb_login_link']"
  element :gplus_login_button, :xpath, "//a[@id='gplus_login_link']"

  def login(username, password)
    self.username_field.set(username)
    self.password_field.set(password)
    self.submit_button.click
  end
end