0
votes

I have below spec code for testing user login feature.

feature "User login" do
    context "using browser", :js => true do
        before(:each) do
            visit "/"
            first(:link, "Login", visible: :any).click
        end
        scenario "with valid details" do
          ...
          # rest of code.
        end
    end
end

It is working fine in my local machine with headless chrome. Here is my Capybara javascript_driver config in spec_helper.rb.

Capybara.register_driver :headless_chrome do |app|
  options = Selenium::WebDriver::Chrome::Options.new(
    args: %w[headless disable-gpu no-sandbox]
  )
  Capybara::Selenium::Driver.new(app, browser: :chrome, options: options)
end

Capybara.javascript_driver = :headless_chrome

But not working with gitlab-ci, below is error i am getting.

Failure/Error: first(:link, "Login", visible: :any).click

NoMethodError: undefined method 'click' for nil:NilClass ./spec/features/user_login_spec.rb:6:in 'block (3 levels) in ' /usr/local/bundle/gems/rspec-retry-0.5.6/lib/rspec/retry.rb:115:in 'block in run' /usr/local/bundle/gems/rspec-retry-0.5.6/lib/rspec/retry.rb:104:in 'loop' /usr/local/bundle/gems/rspec-retry-0.5.6/lib/rspec/retry.rb:104:in 'run' /usr/local/bundle/gems/rspec-retry-0.5.6/lib/rspec_ext/rspec_ext.rb:12:in 'run_with_retry'

I found this blog to use headless chrome but nothing helped.

Here are the versions of dependencies i am using.

google-chrome-stable (63.0.3239.108-1)
chromedriver (2.34)
1

1 Answers

1
votes

By default first doesn't have waiting/retrying behavior, which means if a matching link doesn't exist when it runs it won't wait for one to appear. Additionally passing visible: :any to find an element that you're then going to call click on doesn't make any sense since you can't click on non-visible elements so that would cause an error too. If you do actually need/want to use first (multiple matching links that you can't scope down to one) then you should be using

before(:each) do
  visit "/"
  first(:link, "Login", minimum: 1).click
end

The minimum: 1 option will trigger first to wait/retry up to Capybara.default_max_wait_time seconds for a matching link to appear on the page. This is one of the reasons using first and all are generally bad choices when looking for elements to actually interact with (unless you've done a previous find for something that guarantees the page is in a stable state, or use any of the count options to trigger waiting/retrying behavior). If there aren't actually more than one matching link on the page then you should just be using

before(:each) do
  visit "/"
  click_link('Login') # same as find(:link, 'Login').click
end