I've got a simple scheduling application. I've got a request spec set up to run through the flow of adding a new workout to the schedule, and the form appears to hang on submit and the script bails after a few seconds. Running through it manually works fine, and my controller and model specs are all passing without complaint.
The only funky thing is I'm using execute_script to interact with the jquery datepicker, which seems to be working okay. Watching the execution shows that no error is happening, it's just hangs waiting for 127.0.0.1 to respond which doesn't seem to happen.
describe "Workouts" do
describe 'Create Workouts', js: true do
it 'Creates a new workout and displays the workout\'s page' do
visit workouts_path
expect {
click_link "New Workout"
fill_in 'workout_name', with: 'Workout!'
fill_in '', with: '05/01/2012'
page.execute_script %Q{ $('#workout_show_date').trigger("focus") }
page.execute_script %Q{ $("a.ui-state-default:contains('15')").trigger("click") }
select('6', from: 'workout_time_4i')
select('15', from: 'workout_time_5i')
click_button 'Create Workout'
}.to change(Workout,:count).by(1)
end
end
end
So after putting a sleep in the spec the error started returning that the database was locked, which google revealed to be a problem related to transactional fixtures being turned on. Turned that off and now all my specs are passing
Related
Question about how to send a jQuery callback with an onSuccess: refresh from a textInput when the user presses [Enter]. We use the [Enter] press to trigger a search callback.
Our GS Seaside app uses HAProxy. This means the onSuccess: script is handled by a different gem than the one that handles the callback. Because of this, users will sometimes get the refresh because the callback, which to them looks like a lost input (a browser F5 refresh shows the right state). If running single gem or in a VW / Pharo image this problem does not come up.
I can work around the problem by using...
async: false;
...but that prevents me from show any kind of waiting feedback (I normally use a busy gif).
So, the question is: in a multi-web server configuration, how can you code a callback to...
1 - show a busy gif
2 - trigger the search callback
3 - refresh the display when done
...all in that order.
Using a form submission callback is a problem because multiple text inputs can trigger the search, since the callback is 'set value + do search', by virtual of the default [Enter] press.
For the JS callback, I'm using...
self onKeyPress: (
(JSStream
on: '(window.event ? window.event.keyCode : event.which) == 13')
then: (canvas jQuery ajax callback: aBlock value: canvas jQuery this value))
It all works fine, except for the missing busy gif, due to the 'async: false'.
Any suggestions?
You can define a beforeSend and a complete handler to show and hide the loading indicator while the request is being processed. The global parameter set to false is meant to ignore your existing handlers to process request start and end (the mentioned spinner), and only use these defined in the particular instance of the JQAjax object.
((html jQuery ajax)
async: false;
global: false; "https://api.jquery.com/category/ajax/global-ajax-event-handlers/"
callback: aBlock value: canvas jQuery this value;
onBeforeSend: (html jQuery id: 'indicator') show;
onSuccess: ((html jQuery id: 'fieldId') load html: [:h | ]);
onComplete: (html jQuery id: 'indicator') hide;
That said, keep in mind that doing a synchronous AJAX call is discouraged since it will block the whole UI thread until the request is resolved.
So it's not completely clear how you manage the state in different worker images (gems, in this case) returning different things (probably because of having different sessions), so it's also not clear to me why doing an async XHR request will be served differently to doing it synchronously, I never experienced that.
From the small sample you mention, it can't be deduced what is the "refresh" part of your code. So maybe, providing more context will help us give you more accurate answers.
Fix ended up being trivial: needed to include 'event.preventDefault();' in the [Enter] key script. Seems obvious in hindsight.
if ((window.event ? window.event.keyCode : event.which) == 13) {
event.preventDefault();
};'
This problem is confirmed to be a narrow configuration symptom: GemStone with multiple gems. On every other configuration Seaside / javascript behaves as expected. I will follow this up as a vendor problem. Thanks to everyone that looked at it (this was also posted on other forums).
I have a test that fills out some fields and then is supposed to click a button. This is all done after loading up a modal window. However, it seems that it just skips over it and doesn't click the button. I have tried debugging it manually and calling it myself and it'll work fine but when I run the test by itself it doesn't click it.
Given /^I login with "(.*?)" and "(.*?)"$/ do |email, password|
within "#signin_fields" do
fill_in("custom_fields_email", :with => email)
fill_in("custom_fields_password", :with => password)
end
click_button("Sign In") if page.should have_selector(".btn-signin")
end
I even added a check to make sure it was on the page but since the removal of wait_until, I'm not sure how I'm supposed to let the page load and then make sure it clicks the button properly. Any ideas would heavily appreciated.
This post may help: How do you get rspec to output what it encountered rather than it "didn't find what it expected"? Basically, for debugging, you can add the line save and open page and inspect what the spec is finding and whether it differs from the results of your own debugging.
The following row from your code is incorrect as have_selector is a RSpec matcher:
click_button("Sign In") if page.should have_selector(".btn-signin")
Instead you should use any of Capybara::Node::Matchers like:
click_button("Sign In") if page.has_selector?(".btn-signin")
page.should have_selector(".btn-signin") isn't going to return true or false and therefor the button will never be clicked. Just do this:
click_button(".btn-signin")
If it should be there then the test will fail if it doesn't appear on the page.
In Rails 3.2 I'm using rspec (2.11.0) and capybara 1.1.2 (and have not installed webrat) and it's doing something strange when I click a link on my web page.
I'm trying to click on link on my home page to go to another page. Below is the basic rspec test.
it "should go to agents page" do
visit 'home'
#puts page.body
#links = page.all('a')
#links.each do |l|
# puts l.text
#end
page.find_by_id('menu_agents').click
puts page.body
#<various content asserts on page currently commented out>
end
I basically go to a page, grab a link and click
The link exists. As you can see from the commented out statements I've confirmed by looking at the page in the console and also looking at the list of links. I've tried clicking not only with the link above, but also using click_link and referencing the id. Looking at both the code and the html of the page when I run the code I see the id of the element.
In all cases I get the following result:
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
When running the software with rails s clicking the link does load the correct page. Likewise when I visit the home page in the test it loads correctly as well, since when I print the body to the console I see the right html.
It seems like something is going wrong with the page load when I click the link and the page load has some type of failure (although the test itself does not fail). Any ideas?
Please try this:
Page load will take some time. Use sleep function. It makes some time to wait.
Then use page.find("#menu_agents").click instead of page.find_by_id('menu_agents').click
Verify menu_agents id name is not present any other places in result page.
Note: make sure menu_agents id is unique.
it "should go to agents page" do
visit 'home'
sleep 5
page.find("#menu_agents").click
puts page.body
#<various content asserts on page currently commented out
end
I have written some RSpec test for my rails 3.2 application and because I was annyoed by the Browser popping up ich tried to change from firefox to capybara-webkit.
After this all tests still run, except one. The line that is failing is:
expect { click_button "Create" }.to change(Answer, :count).by(count)
If I remove the expect and add a method to take a screenshot before and after, I can see that the test is run correctly. But if I step trough with the Debugger the log shows me that the records get created after the second screenshot line. I can wait forever the click_button and corresponding Controller action is run after the line next line is executed.
The "create" button is a standard html button, no JS is involved in the create action. Does sb have a explaination for this strange behaviour?
There is a race condition here between Capybara sending the click action to the server and your test checking the database.
The simplest way to resolve this is to wait before checking:
expect { click_button "Create"; sleep 2 }.to change(Answer, :count).by(count)
I don't like this. A better way to test this would be to check from the end user's perspective.
For example, after clicking 'Create', does the user see the answer on the answers page?
fill_in :title, :with => "My answer"
click_button 'Create'
page.should have_text "My answer"
Trying to get started on view testing in Rails 3. I want to validate that I have a form getting kicked out in the view that has the right URL for the action. So I am using assert_select. I actually got a failing test first, using this syntax in the spec (using Rspec):
response.should assert_select "form[action=#{my_model_path}]"
Looking at the rendered HTML, sure enough, the view was rendering the 'edit' url, not the 'new' url due to the wrong model being passed down. Groovy, start red.
I make the model a 'new' one, and I look at my rendered output, and it's what I'd expect, BUT the test fails, and the error message says:
NoMethodError:
undefined method `matches?' for #<Array:0x0000012a1a5d58>
I've looked all over the web for this, found one guy that mentioned the error, but got no resolution. Any ideas?
Figured out that I could get this to work by nesting my assert_select calls, like so:
response.should assert_select "form" do
assert_select "[action=?]", my_model_path
end