RSpec/Capybara: Not detecting - ruby-on-rails

I'm running feature test in my rails app with Rspec and capybara. I'm filling out a form, which includes the following code:
<%= f.collection_select(:model_id, Model.all, :id, :name) %>
This code works COMPLETELY fine when I actually go to the view, and it shows all of the expected name.
I'm trying to fill it out in my Rspec feature test like so:
select('Option', :from 'model[model_attributes][model_id]')
However, capybara always gives me the error
Capybara::ElementNotFound:
Unale to find option 'option'
When capybara gives me a screenshot and I go to the screenshot, the select element from that form just appears as a blank form (all the other ones besides the collection_select appear fine). Since it doesn't appear in the screenshot, does that mean Capybara simply doesn't support the collection_select at the moment?
Thank you in advance.

UPDATE: Solved my own question.
I simply had to initialize objects with FactoryGirl before visiting the page and submitting the form. That way, the collection select had something to look for.

Related

How to test that a form successfully submitted using Rspec?

I'm writing feature specs for my Article form.
In one test, I have RSpec look for certain form inputs using the labels:
expect(find_field("Title")).to_not be_nil
Now I'd like to know if the form was submitted properly. How can I do this using RSpec, if you aren't supposed to check the database from a feature spec?
For example, what if I mistyped the name attribute on the Title input? The label would still be found by my find_field() call, and controller specs would have me specify the title in a hash.
In this case one would assume a Title would be required for an Article so if the name attribute was misspelled the creation of the Article would fail and you'd end up on an error page (Also an unpermitted parameter would raise in the creation by default in test mode with strong parameters). If its a field not required for creation of the Article then the assumption is that the info is displayed in the app somewhere and can be checked for on that page.
As an aside your sample expect would read much clearer if rewritten as
expect(page).to have_field('Title')
There are loads of way to approach this:
expect(page).to have_field('Title')
expect(page).to have_css('#someSelector')
expect(current_path).to eq article_path (for example)
expect(page).to have_content "ABC" (i.e. some content which will be rendered)
The Capybara readme on Github is a really good one full of easy to follow examples - https://github.com/jnicklas/capybara.

Rspec view test does not render changes

I am testing a view in my rails 3.2 application with rspec.
I have wrote tests for my view to include some additional input fields, and they correctly failed. However, after adding the desired input fields, the tests still fail the same way. They output the form in the terminal, and it is as if I hadn't changed anything in the views.
When inspecting the view in the browser, the fields are in fact there, so the tests should pass.
Has rspec not loaded the latest views?
Here is some code (I have reduced it to two fields):
it "renders the form to sign up" do
rendered.should have_selector("form", action: "/users", method: "post") do |form|
form.should have_selector("input#user_email", name: "user[email]", type: "email")
form.should have_selector("input#user_city", name: "user[city]", type: "text")
end
end
The email input is an old input that I had before, and it does recognize it. The city input is new, and it doesn't even appear in the terminal's view output.
What am I doing wrong?
Wow, this was a tricky one.
I am using devise and wanted to test its views. In my view tests, I said:
describe "devise/registrations/new" do
# code here
end
However, the other day I switched to scoped views, and changed the view folder name from devise to users accordingly. Scoped views are good if you have different user models such as user and admin and need different views for them. You can turn on scoped views in config/initializers/devise.rb by replacing the existing scope line with:
config.scoped_views = true
Hence, I also had to change my spec description to
describe "users/registrations/new" do # change to "users" instead of "devise"
# code here
end
Since I didn't do this, it still rendered devise's standard views, which it renders when it doesn't find any views in my views folder - hence the source code output in my terminal, that suggested it could render the right views, but lacked the updated code.

Rails: errors.add displays HTML tags

Today, i have started getting a strange issue on validations.
Here is the code.
self.errors.add("", 'Must confirm your current password to set a new one')
But i am getting HTML tags in output. Like the one below.
<div id="errorList" class="errorList"><div class="errorListInner"><h5>1 error prohibited saving your profile</h5><ul><li> Must confirm your current password to set a new one</li></ul></div></div>
CSS isn't getting applied, i think. I am working on rails 3.1.3 and ruby 1.9.2.
Can anyone help me out.
Thanks in advance.
Found the answer with a simple fix.
Dont do anything with this in model. Just put "raw" in you view where these errors are being populated.
Like
<%= raw a_helper_function_for_errors %>

Creating a path with an object id to map with cucumber scenario

I'm trying to create a cucumber scenario that checks to see if elements are loaded for an 'edit posting' page. My trouble, however, is that I don't know how to create a path that will direct it to the page.
The general path is something like: /posting/id/edit
i.e. /posting/11/edit
Here is my posting.feature scenario
# Editing existing post
Scenario: Saving the edits to an existing post
Given I am logged in
Given there is a posting
Given I am on the edit posting page
When I fill in "posting_title" with "blah"
And I fill in "posting_location" with "blegh"
When I press "Update posting"
Then I should see "Posting was successfully updated."
I dabbled around with some Factory Girl stuff, but I don't have the knowledge to use it appropriately (if it offers a solution), and wasn't able to find a relevant example.
I've also seen a lot of suggestions with regards to 'Pickle', but if possible I'd like to avoid that route to keep things simple seeing as I have very limited experience. Thanks!
Is there a link on your website that would take someone to the edit page? Then you could do something like:
Given I am on the homepage
And I follow "Posts"
And I follow "Edit"
This assumes that there is a link on your homepage whose text is Posts, and then another one in the resulting page called Edit. This is the best way to accomplish this, because there should be a direct route to whatever page you are testing. Those steps are also provided in web_steps.rb
You could also make a custom step like you did there with Given I am on the edit posting page and the code would be something like:
Given /^I am on the edit posting page$/ do
visit("/posting/11/edit")
end
Which you of course could also generalize like I am on the edit posting page for posting 11. But in general, cucumber tests are acceptance tests, which means not bypassing things like this. You should have a link to the edit page that can be clicked.
I came up with a solution, but I am not sure of its validity in terms of how clean it is. I ended up using Factory Girl (installed the gem).
I kept my scenario the same.
Under features/step_definitions I created posting_steps.rb
Given /^there is a posting$/ do
Factory(:posting)
end
Under features/support I created a file factories.rb with the following inside:
Factory.define :posting do |f|
f.association :user
f.title 'blah'
f.location 'Some place'
end
In my paths.rb I used
when /the edit posting page/
edit_posting_path(Posting.first)
How it works (or at least how I think it works) is that as
Given there is a posting
is executed, the posting_step.rb is invoked (Factory(:posting) is basically Factory.create(:posting)), which in turn uses the factory definition I created in factories.rb. This leads to an instance of a posting being created.
Then in my paths.rb
when /the edit posting page/
edit_posting_path(Posting.first)
gets passed the id from the instance, to ultimately get a path that could resemble /posting/1/edit , and the test continues on its way!
If there are any corrections to be made, please let me know as I am just learning the ropes.
Hopefully this will help other newbies out there!

Cucumber step ambiguity when using built in 'within' step scoper

I've created a custom cucumber step for checking the destination for a link, and I'm using Cucumber's new built in support in web_steps for scoping these lookups. So I have two cucumber steps involved:
# My step to verify the link
Then /^"([^\"]*)" should link to (.*)$/ do |link_text,page_name|
page.should have_link(link_text, :href => path_to(page_name))
end
# Cucumber's built in step to scope things
# Single-line step scoper
When /^(.*) within ([^:]+)$/ do |step, parent|
with_scope(parent) { When step }
end
I use this by having cucumber scripts that do things like
And "home" should link to the home page within the "Email Signature" section
My problem is that I'm getting ambiguous matches on the above between these two steps, because the 'within' clause can't be told apart from the "the home page", because the latter doesn't have any bounding quotes.
I've tried changing the link step to read like this, thinking it might resolve the ambiguity by not matching the 'within', but I think the 'within' gets swallowed by the preceeding group instead:
Then /^"([^\"]*)" should link to (.*)(?!within)$/ do |link_text,page_name|
page.should have_link(link_text, :href => path_to(page_name))
end
Any thoughts on how to resolve this?
Not directly an answer to the question I posed (for that see Qtax's answer), but here's what I've wound up doing. I think it's a nicer solution anyway, for what it's worth...
I've created a custom version of the scoping helper that looks like this:
Then /^within ([^,]*), (.+)$/ do |parent, step|
with_scope(parent) { When step }
end
This allows me to write steps like this:
And within the "Email Signature" section, "home" should link to the home page
Which I think (a) reads more naturally (it's clearer that we're talking about the link being in the e-mail signature section, not the home page), and (b) works around the problem I was having, because the unquoted 'within' selector is well out of the way of the unquoted page name.
Try something like:
/^"([^"]*)" should link to ((?:(?!within).)+)$/
Don't know anything about Cucumber, I'm just going by what you tried to do.

Resources