3

I am using capybara with Selenium as its driver. I am trying to click on an element, which when clicked it will reveal a div, but the click never invokes javascript to do just that.

Below is the code I have

scenario 'currently used transport mode cannot be re-selected' do

expect(page).to have_css("h2.summary")
expect(find('h2.summary').text).to eq("Single event")
expect(page).to have_content("Change journey")
page.click_link("Change journey")
expect(find('#travel-times-preview').visible?).to be_truthy # FAILS here because of previous step not working

end

error message

Capybara::ElementNotFound: Unable to find css "#travel-times-preview"

html

<a class="change-journey gray-text" href="#">Change journey</a>

javascript code to execute

$(".change-journey").on("click", function(e){
      var target = $(this).data("preview-target");
      $('[data-preview-toggle="'+ target +'"]').toggleClass("hidden");
      if($(this).text().indexOf('Change journey') > -1){
        $(this).text("Close Preview");
      }else{
        $(this).text("Change journey");
      }
    e.preventDefault();
  });

database cleaner setup

config.before(:suite) do
    if config.use_transactional_fixtures?

      raise(<<-MSG)
        Delete line `config.use_transactional_fixtures = true` from rails_helper.rb
        (or set it to false) to prevent uncommitted transactions being used in
        JavaScript-dependent specs.
        During testing, the Ruby app server that the JavaScript browser driver
        connects to uses a different database connection to the database connection
        used by the spec.

        This Ruby app server database connection would not be able to see data that
        has been setup by the spec's database connection inside an uncommitted
        transaction.
        Disabling the use_transactional_fixtures setting helps avoid uncommitted
        transactions in JavaScript-dependent specs, meaning that the Ruby app server
        database connection can see any data set up by the specs.
      MSG

    end
  end

  config.before(:suite) do
    DatabaseCleaner.clean_with(:truncation)
  end

  config.before(:each) do
    DatabaseCleaner.strategy = :transaction
  end

  config.before(:each, type: :feature) do
    # :rack_test driver's Rack app under test shares database connection
    # with the specs, so we can use transaction strategy for speed.
    driver_shares_db_connection_with_specs = Capybara.current_driver == :rack_test

    if driver_shares_db_connection_with_specs
      DatabaseCleaner.strategy = :transaction
    else
      # Non-:rack_test driver is probably a driver for a JavaScript browser
      # with a Rack app under test that does *not* share a database
      # connection with the specs, so we must use truncation strategy.
      DatabaseCleaner.strategy = :truncation
    end
  end

  config.before(:each) do
    DatabaseCleaner.start
  end

  config.after(:each) do
    DatabaseCleaner.clean
  end

While i can see the link being clicked, the underlying javascript is not executed.

3
  • Are you sure you click on proper element? This code means nothing for us without HTML Commented Jan 23, 2017 at 12:42
  • @Andersson i added the html link. Note that without using a testing environment and testing manually it works. Seems to be an error with e.preventDefault() not triggering - which instead reloads the page when clicking that link. Commented Jan 23, 2017 at 12:46
  • You should tag this question with "capybara" as well since that's what you're using - not straight selenium Commented Jan 23, 2017 at 16:07

1 Answer 1

1

Assuming you've looked into the dev console in the firefox window that opens and there are no JS errors, there are a few potential reasons for the behavior you're seeing, none of which have anything to do with e.preventDefault() (When you hear hoofs think horses, not zebras)

  1. The link you show doesn't have a data-preview-target attribute so there is nothing for the click handler to read and append to data-preview-toggle= so nothing gets toggled. It's possible that data is added by other JS in your app so is set as a property and wasn't an attribute in the HTML (or you just chose to leave that detail out of the element you showed) which moves to #2

  2. Your .on JS code is running before the element exists, and therefore not attaching. This can show up in test mode when it concatenates all the JS into one file because the JS is loaded faster than when multiple requests are made in dev mode. This would show up as the link text not changing since the click handler isn't run at all. If that is the case delay attaching the listener until the DOM is loaded.

  3. This is the first JS supporting test you're writing, the elements being hidden/shown are generated from database records, and you haven't disabled transactional tests and/or configured database_cleaner correctly. This leads to objects you create in your tests not actually being visible in your app, so the element you're expecting to be on the page isn't actually there. You can verify that by pausing the test and looking in the HTML to see if it is or is not actually on the page.

  4. Based on the error you provided this is not the cause of your issue, just adding for completeness of the answer: click_link clicks the link and returns immediately. That means the test continues running while the action triggered by the click continues. This can lead to a race condition in your code (if you have Capybara.ignore_hidden_elements = false set - bad idea) where your code finds the element and checks its visibility before it's changed. Because of that your final step should be written as below because it will wait/retry for the element to become visible

    expect(page).to have_css('#travel-times-preview', visible: true)
    

As an aside, your test code can be improved and sped up by using the features Capybara provides

scenario 'currently used transport mode cannot be re-selected' do

  expect(page).to have_css("h2.summary", text: "Single event")  # do it in one query
  page.click_link("Change journey") # click_link will find the content anyway so no need to check for it before
  expect(page).to have_css('#travel-times-preview') # By default Capybara only finds visible elements so checking visibility is pointeless, if you've changed that default see #4

end
Sign up to request clarification or add additional context in comments.

11 Comments

Hey Thomas thank you for your detailed answer i would like to reply back as the culprit is yet to be found. I will answer each point you made. 1. you are right, i left out data-preview-toggle. 2. the whole function is wrapped in another function which is called on the "turbolinks:load" event. 3. Yes this is my first acceptance test ever - I will edit the post and add the database cleaner configuration - however using the command save_and_open_page or by using selenium when it opens the browser, i can see the record there. 4.The code you provided still does not do the trick.
@PetrosKyriakou Your database_cleaner config after block should be append_after as shown in the database_cleaner docs - github.com/DatabaseCleaner/… . It wouldn't be causing your current issue but it would make your tests flaky going forward. Have you confirmed no errors in the firefox console when you pause the test after the click_link? What version of turbolinks are you using? Also, you don't show the scenario as tagged with js: true - I assume it is higher up the tree (or firefox would not be opening when you run the test)
Hey i am using Capybara.current_driver = :selenium in the background(:all) block of this spec - nothing else and it opens up firefox. Yes checked no errors in console. I am using Rails 5 think its turbolinks 5 (whatever is shipped with rails 5). BTW with the code you provided the error is slightly different expected to find css "#travel-times-preview" but there were no matches. Also found "", which matched the selector but not all filters. thanks for the database cleaner tip though will check it out. Is it possible its because of turbolinks event?
The reason i thought its e.preventDefault() etc not triggering its because the page clearly refreshes as the welcome flash message i have disappears after clicking the link.
EDIT: command rake assets:clobber did the trick, thank you so much for the help!
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.