asserting value of selector - ruby-on-rails

The following Minitest snippet
puts response.body.inspect
# assert response.body.include?("Log out of all other sessions")
assert_select "input[type='submit']" do
assert_select "[value=?]", "Log out of all other sessions"
end
is failing as Expected at least 1 element matching "[value="Log out of all other sessions"]", found 0..
Yet the inspection has the following string:
<form class=\"button_to\" method=\"post\" action=\"/active_sessions/destroy_all\">
<input type=\"hidden\" name=\"_method\" value=\"delete\" autocomplete=\"off\" />
<button type=\"submit\">Log out of all other sessions</button>
</form>
The value in the view is set via i18n:
<%= button_to t('user.auth.session_delete_all'), destroy_all_active_sessions_path, method: :delete %>
uncommenting assert response.body.include?("Log out of all other sessions") asserts.
How should the failing assertion be cast?

Related

Rails RSpec form datepicker and select failing test assertion

I'm getting to grips with testing in rails, and I've been following this tutorial.
However, unlike the tutorial in my form I have a date select field. This seems to be causing a problem where the assert_select doesn't recognise it, and so the test is failing.
The code in new.html.erb_spec:
RSpec.describe "aquatics/new", type: :view do
current_user = User.first_or_create!(email: 'me#mail.com', password: 'password', password_confirmation: 'password')
before(:each) do
assign(:aquatic, Aquatic.new(
nick_name: "nickname",
common_name: "common name",
scientific_name: "scientific name",
sex: 'male',
purchased_on: '2022-02-02',
length: 10,
max_lifespan: 5,
user: current_user,
notes: "These are the testing notes"
))
end
it "renders new aquatic form" do
render
assert_select "form[action=?][method=?]", aquatics_path, "post" do
assert_select "input[name=?]", "aquatic[nick_name]"
assert_select "input[name=?]", "aquatic[common_name]"
assert_select "input[name=?]", "aquatic[scientific_name]"
assert_select "input[name=?]", "aquatic[purchased_on]"
assert_select "input[name=?]", "aquatic[sex]"
assert_select "input[name=?]", "aquatic[length]"
assert_select "input[name=?]", "aquatic[max_lifespan]"
assert_select "input[name=?]", "aquatic[notes]"
end
end
end
The failure:
1) aquatics/new renders new aquatic form
Failure/Error: assert_select "input[name=?]", "aquatic[purchased_on]"
Minitest::Assertion:
Expected at least 1 element matching "input[name="aquatic[purchased_on]"]", found 0..
Expected 0 to be >= 1.
# ./spec/views/aquatics/new.html.erb_spec.rb:26:in `block (3 levels) in <main>'
# ./spec/views/aquatics/new.html.erb_spec.rb:22:in `block (2 levels) in <main>'
I assume this is something to do with it being a selection field rather than an input, because if I comment out the purchased_on test line it throws the same error for the sex field.
I've tried changing the input[name=?] to date_select[name=?] and similar actions, but no luck. TIA.
date_select adds 3 select tags for Year, Month, and Date
You are verifying input tag, you should verify select tags.
date_select("aquatic", "purchased_on")
Above date_select will generate below html
<select id="aquatic_purchased_on_1i" name="aquatic[purchased_on(1i)]">
...
<option value="2021">2021</option>
<option value="2022" selected="selected">2022</option>
<option value="2023">2023</option>
...
</select>
<select id="aquatic_purchased_on_2i" name="aquatic[purchased_on(2i)]">
<option value="1">January</option>
<option value="2" selected="selected">February</option>
...
<option value="12">December</option>
</select>
<select id="aquatic_purchased_on_3i" name="aquatic[purchased_on(3i)]">
...
<option value="10">10</option>
<option value="11" selected="selected">11</option>
<option value="12">12</option>
...
</select>
You can verify it as below
assert_select "select[name=?]", "aquatic[purchased_on(1i)]"
assert_select "select[name=?]", "aquatic[purchased_on(2i)]"
assert_select "select[name=?]", "aquatic[purchased_on(3i)]"

Unable to find field “q” (Capybara::ElementNotFound) via fill_in

Trying to get the "what" form (aka job title), from indeed.com
Error when trying to run the program:
/var/lib/gems/2.3.0/gems/capybara-2.11.0/lib/capybara/node/finders.rb:44:in `block in find': Unable to find field "q" (Capybara::ElementNotFound)
Inspecting element via firefox from indeed.com yields: name="q"
<span class="inwrap">
<input class="input_text" maxlength="512" size="31" aria-labelledby="what_label_top hidden_colon what_label_bot" name="q" autocomplete="off" id="what">
</span>
<div style="width:250px"><!-- --></div>
Which matches the code in the scraper:
def perform_search
# For indeed
fill_in 'q', :with => #skillset
fill_in 'l', :with => #region
find('#fj').click
sleep(1)
end
The entire code can be found at:
https://github.com/jasnow/job-hunter/blob/master/scraper.rb
Now the problem here is the inability to locate name="q" Are there any other ways I could link to that form on indeed.com so I could initiate webscraping? I'm talking xpath or css perhaps.
Your code only allows the URL http://www.indeed.com , but that URL redirects to https://www.indeed.com and also hits http://indeed.com. Therefore your page load is being blocked. Change to config.allow_url("indeed.com") and it should be able to find the input.

Capybara::ElementNotFound: Unable to find field "Key name"

I've read the similar questions to this but they don't solve my issue. I'm new with js testing so I think I might be doing something wrong.
The form produces this HTML
<form class="new_category_item_key" id="new_category_item_key" action="/guides/dungeon-boss/categories?category_id=heroes" accept-charset="UTF-8" data-remote="true" method="post"><input name="utf8" type="hidden" value="✓" /><input type="hidden" name="authenticity_token" value="b7wiF07zYh/Nl727M3y0Uk1TbroMJFuGqTK6fYNlNted/5G4Wmz4BZLb7IazzyP5md/wWRb1D28ePhrzt2uMSA==" />
<label for="category_item_key_name">Key name</label>
<input type="text" name="category_item_key[name]" id="category_item_key_name" />
<select name="category_item_key[key_type]" id="category_item_key_key_type"><option value="1">Value</option>
<option value="2">Text</option>
<option value="3">Image</option></select>
<input type="submit" name="commit" value="Add New Key" />
</form>
and I have the following integration test on the form
setup do
#user = users(:michael)
#user1 = users(:archer)
#guide = Guide.find(1)
#mod_relationship = game_mods_relationships(:mod1)
#category = Category.find(1)
Capybara.current_driver = Capybara.javascript_driver # :selenium by default
end
test "adding keys mod success then fail" do
log_in_as(#user)
get edit_guide_category_path(#guide, #category)
assert_template 'categories/edit'
assert_difference 'CategoryItemKey.count', 1 do
fill_in 'Key name', with: "diablo"
click_button "commit"
end
end
when I run the test I get the following error
Capybara::ElementNotFound: Capybara::ElementNotFound: Unable to find field "Key name"
Looking at the HTML I can see the field is there. If I try using the inputs id it still fails, if I remove the fill in line then it says it cant find the button to click which is also there. I assume its getting the right page because get edit_guide_category_path(#guide, #category) works for the other tests (but they are non js tests and don't use selenium).
Its probably something simple but I cant get it.
You're mixing up two different libraries -- You can't use get with Capybara, you use visit(url) to go to the page. You also shouldn't normally be asserting templates in a feature test, thats for lower level tests.

Rails Capybara not seeing fields

I feel like I'm going insane here. Doing a routine capybara test of my Post model. Specifically, making sure the new page redirects to the newly created post after a valid submission. So in my spec/requests folder, I've got this:
describe "Valid post submission --" do
it "should log in a user and redirect to new post" do
# Sign in works find, so I won't reproduce it
# Make a blogpost
Post.destroy_all
fill_in :name_here, with: "Post Name Here"
fill_in :content_here, with: "This is the content of a really short post."
screenshot_and_open_image
click_on "Post It"
screenshot_and_open_image
puts current_path
page.should have_selector 'h2', text: "prohibited this post"
page.should have_selector 'h1', text: "Post Name Here"
page.should have_selector '.alert', text: "Post was successfully created."
page.should have_selector 'title', text: full_title('Post Name Here')
end
The screenshots and puts are there to clarify what's going on. There are basically two different cases. In
I just leave the fields be and test for the default IDs ("post_name"
and "post_content"); obviously the above test is for case two:
I change the field ids to "name_here" and "content_here" to test if
the label names or anything else is interfering. That's the one the spec of which is
above.
In case 2 the post is getting rejected because Capybara can't find either field.
In case 1, only the content would be empty, but the name field would be filled with the content.
The precise error in case 1 is:
2) Posts Invalid post - should refresh with error if content empty
Screenshot: /Users/myusername/rails/appname/tmp/capybara/screenshot_2013-03-14-22-37-36.634.png
Failure/Error: fill_in :post_name, with: "Post Name Here"
Capybara::ElementNotFound:
cannot fill in, no text field, text area or password field with id, name, or label 'post_name' found
# (eval):2:in `fill_in'
# ./spec/requests/posts_spec.rb:43:in `block (3 levels) in <top (required)>'
Case 2 doesn't throw an error about not finding the appropriate content, I believe because the label has that id as well.
This is ridiculous, because I took a snapshot of the HTML durin the test, just before it errors. Here's case 2 -- both cases look 90% the same here, apart from that ID difference:
<form accept-charset="UTF-8" action="/posts" class="new_post" id="new_post" method="post">
<div style="margin:0;padding:0;display:inline"><input name="utf8" type="hidden" value="✓"></div>
<div class="field">
<label for="post_name">Name</label>
<br><input id="name_here" name="post[name]" size="30" type="text">
</div>
<div class="field text-area">
<label for="post_content">Content</label>
<br><textarea cols="50" id="content_here" name="post[content]" rows="20"></textarea>
</div>
<div class="actions btn-group">
<input class="btn" name="commit" type="submit" value="Post It">
</div>
</form>
Note the clear existence of the post_content field. In cases where both fail (Case 1), there are both content_here and name_here fields. So the fields are there. And capybara is generally working (this sort of thing works find in other parts of my app). And the problem isn't a conflict with the label name, because putting a different id on the input fields doesn't help capybara find them.
By the way, this all works perfectly in reality.
Any idea at all what's going on here? I'm super frustrated/clueless.
UPDATE -- Following user2172816's advice, I changed my HAML so the HTML looks like this:
<form accept-charset="UTF-8" action="/posts" class="new_post" id="new_post" method="post">
<div style="margin:0;padding:0;display:inline"><input name="utf8" type="hidden" value="✓"></div>
<div class="field">
<label for="post_name">Name</label>
<br><input id="name" name="post[name]" size="30" type="text">
</div>
<div class="field text-area">
<label for="post_content">Content</label>
<br><textarea cols="50" id="content" name="post[content]" rows="20"></textarea>
</div>
<div class="actions btn-group">
<input class="btn" name="commit" type="submit" value="Post It">
</div>
</form>
The test now looks like this:
# Make a blogpost
Post.destroy_all
fill_in "Name", with: "Post Name Here"
fill_in "Content", with: "This is the content of a really short post."
page.should have_selector 'h2', text: "prohibited this post"
page.should have_selector 'h1', text: "Post Name Here"
page.should have_selector '.alert', text: "Post was successfully created."
page.should have_selector 'title', text: full_title('Post Name Here')
But it's still erroring (in new parts of the same spec, too!):
1) Posts Invalid post - should refresh with error if content empty
Screenshot: /Users/username/rails/appname/tmp/capybara/screenshot_2013-03-14-23-54-38.072.png
Failure/Error: fill_in :name, with: "Post Name Here"
Capybara::ElementNotFound:
cannot fill in, no text field, text area or password field with id, name, or label 'name' found
# (eval):2:in `fill_in'
# ./spec/requests/posts_spec.rb:43:in `block (3 levels) in <top (required)>'
2) Posts Invalid post - should refresh with error if name empty
Screenshot: /Users/username/rails/appname/tmp/capybara/screenshot_2013-03-14-23-54-38.274.png
Failure/Error: fill_in :name, with: ""
Capybara::ElementNotFound:
cannot fill in, no text field, text area or password field with id, name, or label 'name' found
# (eval):2:in `fill_in'
# ./spec/requests/posts_spec.rb:33:in `block (3 levels) in <top (required)>'
3) Posts Valid post submission -- should log in a user and redirect to new post
Screenshot: /Users/username/rails/appname/tmp/capybara/screenshot_2013-03-14-23-54-38.459.png
Failure/Error: fill_in :name, with: "Post Name Here"
Capybara::ElementNotFound:
cannot fill in, no text field, text area or password field with id, name, or label 'name' found
# (eval):2:in `fill_in'
# ./spec/requests/posts_spec.rb:67:in `block (3 levels) in <top (required)>'
The attribute "for" of label should be the "id" of the input element, i.e.
<label for="name_here">Name</label>
<br><input id="name_here" name="post[name]" size="30" type="text">
And in the spec you should call:
fill_in 'Name', with: "Post Name Here"

Why would this functional test be failing?

My haml :
- for status in current_account.job_statuses.active
= link_to status.name, '#', :class => params[:job_status_id].to_i == status.id ? "current status block" : "status block", :rel => status.id
My html :
<a rel="1" class="status block" href="#">in progress</a>
<a rel="2" class="status block" href="#">in progress</a>
<a rel="3" class="status block" href="#">in progress</a>
<a rel="4" class="status block" href="#">in progress</a>
My Test :
test 'index - job_status: set' do
job_status = #account.job_statuses.create! :name => 'foo'
job_status.reload
#job.update_attribute :job_status_id, job_status.id
#job.reload
get :index, :job_status_id => job_status.id.to_s
assert_response :success
assert_template 'jobs/index'
jobs = assigns(:jobs)
assert jobs.include?(#job)
assert_select 'div.status[rel=?]', job_status.id
end
But I get this failure :
3) Failure:
test_index_-_job_status:_set(NewJobsControllerTest)
[test/functional/new_jobs_controller_test.rb:127:in `block in <class:NewJobsControllerTest>'
test/test_helper.rb:221:in `run'
test/test_helper.rb:221:in `run']:
Expected at least 1 element matching "div.status[rel='16']", found 0.
<false> is not true.
Is this for an obvious dumb reason? I apologize if it is.. I can't figure it out.
Oh. It's always the little things we never think to check... After staring uselessly at that HAML I asked for for five minutes it hit me:
Those ain't DIVs. Those are As.
Cheers!

Resources