I'm experimenting with introducing Turbo Drive on a couple of pages in my Rails 6.1 app.
IÍ„'ve got it as expected after moving some legacy JQuery plugin initialization from $(document).ready() calls into document.addEventListener('turbo:load', ..) calls.
When I'm running my Capybara feature specs, however, I can see from the screenshots of the failing specs like the JQuery plugins have not been initialized like they should. One typical example of a test that is failing :
scenario 'element is visible', :js do
visit(my_page_path)
expect(page.find(#some-jquery-plugin-created-element).text).to \
eq 'some expected text from the plugin element'
end
Can anyone help me understand why this is not working in the feature specs? It looks to me like the turbo:load event is not getting triggered at all.
What I've tried
Checking the browser logs
I enabling logging in the driver:
Selenium::WebDriver::Remote::Capabilities.chrome( "goog:loggingPrefs": { browser: 'ALL' } ).
.. but calling page.driver.browser.manage.logs.get(:browser) just before the failing expect call just returns an empty array.
Perhaps I'm doing it wrong?
Making sure Capybara doesn't time out before the page finishes loading
Capybara.default_max_wait_time = 10
By writing your expectations like
expect(page.find(#some-jquery-plugin-created-element).text).to \
eq 'some expected text from the plugin element'
you are defeating Capybaras retry functionality which will lead to lots of failing tests in dynamic pages. You should "never" use the basic RSpec matchers (eq, etc) with Capybara related objects.
In your case the find call is waiting for a matching element to exist, then getting its text and checking it. This will fail because when the element is first added to the page it may not yet have its full text contents. Instead you should be using the Capybara provided matchers which will use Capybaras waiting behavior for things to match
expect(page.find(#some-jquery-plugin-created-element)).to have_text('some expected text from the plugin element')
Related
Recently I switched my cucumber tests from capybara-webkit to headless chrome. Now many features fail with
expected to find text "commented by J. Smitch" in "commented by[two spaces there]J. Smith"
Is there a way to tell Capybara to ignore extra whitespaces?
Or I need to add whitespaces in my step definitions to make the failing tests green?
UPDATE 1
I have spaces in my markup which are not normalized like this
<div>
commented by
<span>J. Smith</span>
</div>
I'm guessing that at the same time you switched from capybara-webkit to selenium with headless chrome you also switched from Capybara 2.x to 3.x. One of the breaking changes in Capybara 3.x is that it attempts to return whitespace more as the user would actually see it. That means that if you have characters in your markup they don't get collapsed with surrounding spaces since the browser doesn't do that. You can use the normalize_ws option to get back results more like 2.x
expect(page).to have_text('blah blah', normalize_ws: true)
however if you're going to the trouble of adding characters to your page you should probably be checking that the text is displaying with the multiple spaces as you intended.
Using Capybara, I would like to simulate a click on the area within an image that is defined by an imagemap's area element. Using .find with or without visible: true on the class/id attributes of that specific element isn't working - I get either a Capybara::Poltergeist::ObsoleteNode error, or a Capybara::ElementNotFound error. Instead if I simply trigger it via Javascript, like so, then my tests do pass:
page.execute_script('$(".ClassSelector").trigger("click")')
So the page is working like it should, but I'd like to know if I can avoid execute_script in writing my tests.
I am using capybara 2.5 and poltergeist 1.7
Current poltergeist doesn't seem to work with image maps (I'll look at fixing that this weekend), and will return an error stating that a different element would be clicked. Selenium does work correctly with the image map so you could have those specs that require image maps run with selenium.
Update - I merged support for clicking on an area element of an image map into poltergeist master branch on Jan 24th, 2016 -- It should be in the next release
After bundle update my tests with js: true fails because Capybara or Poltergeist returns absolute path for links instead of relative.
Example:
expect(edit_link[:href]).to eq(edit_agreement_path agreement)
Fail message:
expected: "/agreements/1/edit"
got: "http://127.0.0.1:55714/agreements/1/edit"
In the failed snapshot i can see that my links are still relative as expected.
Any ideas what is changed and how to fix this? Don`t really like idea to go through all my tests to fix this issue.
For standard not js tests all work as expected - got relative path for links.
Sorry for my English.
Poltergeist was updated to behave the same as selenium (prefer element property over attribute in most cases). You'll need to either revert or update your tests. A better solution is to actually specify the href when finding the link in the first place
expect(page).to have_link('edit', href: edit_agreement_path(agreement))
Or
edit_link = page.find(:link, 'edit', href: edit_agreement_path(agreement))
if you care about the value of href, although the actual value of href really isn't something for integration tests to worry about. They should be more about, if I click it do I end up on a page with the ability to edit the item
A 2.1.1 Grails app has a filter, and in development mode lines like this get printed on every request:
Filter says params are: [controller:book, action:list]
How can I stop this? (I don't think it is anything in my code doing it)
Are you using the functional test plugin? A quick Google search returned the suspect println you're seeing in the functional test plugin's grails-app/conf/TestFilters.groovy filter. If you are using the plugin, it looks like it's been removed/commited in Mar 2012, so you may need an update.
Otherwise if you're not using the functional test plugin, I would inspect your grails-app/conf/ directory for any *Filters.groovy and it's contents.
From time to time I run into the issue that Grails integration tests the name of which ends in "IntegrationTests" don't work coming up with exceptions that show that GORM methods have not been added to domain classes. After renaming those tests to "*IntegrationTest" (no s at the end) they work fine.
A short example:
class MyIntegrationTests {
#Test
void myTest() {
assert MyDomainClass.count() == 0
}
}
Will fail with the following exception:
Failure: myTest(de.myproject.MyIntegrationTests)
groovy.lang.MissingMethodException: No signature of method: de.myproject.MyDomainClass.count() is applicable for argument types: () values: []
Possible solutions: count(), ident(), print(java.io.PrintWriter), print(java.lang.Object), getCount(), wait()
at de.myproject.MyIntegrationTests.myTest(MyIntegrationTests.groovy:9)
After renaming MyIntegrationTests to MyIntegrationTest the test passes.
Is there some kind of magic happening according to the test's name? All I found in Grails documentation is: "Tests can also use the suffix of Test instead of Tests. " Any ideas?
I eventually found the cause for the different behaviour of "*Test" and "*Tests" myself: Different postfixes change the order in which the tests are being run. To make things worse, the exact order is platform-dependent. Thus, my tests ran locally (OSX) in a different order than on my CI machine (Linux), and thereby produced different results.
Why the exception occurrs in some order is a totally different problem, though, which I haven't figured out (yet).
This should work how you had it originally as long as the file is in the integration folder. Are you sure you didn't have it in the unit test folder and then move it into the integration folder on the rename? Or possibly that you're using intellij and you did a "junit" test run rather than a "grails" one?
The error you're getting seems to imply that grails didn't start up when running your test.
Your test won't be executed if it does not has the suffix Tests.
Copied From Grails documentation home page (http://grails.org/doc/latest/guide/testing.html):
The default class name suffix is Tests but as of Grails 1.2.2, the
suffix of Test is also supported.
j-