Rspec/TDD beginner. I have a spec that is failing and I don't know why. Everything works in the browser as it should. I am using Kaminari for pagination, which defaults to 25 items per page.
spec:
describe "Question Pages" do
subject { page }
describe "index page" do
before { visit questions_path }
before { 25.times { FactoryGirl.create(:question) } }
after { Question.delete_all }
it { should have_selector('h1', 'All Questions') }
it "should list the questions" do
Question.page(1).each do |question|
page.should have_link(question.title, href: question_path(question))
end
end
end
end
failure:
1) Question Pages index page should list the questions
Failure/Error: page.should have_link(question.title, href: question_path(question))
Capybara::ExpectationNotMet:
expected to find link "Lorem Ipsum 33" but there were no matches
# ./spec/features/question_pages_spec.rb:17:in `block (4 levels) in <top (required)>'
# ./spec/features/question_pages_spec.rb:16:in `block (3 levels) in <top (required)>'
Why is it failing on item number 33 when I told it to make 25?
factory:
FactoryGirl.define do
factory :question do
sequence(:title) { |i| "Lorem Ipsum #{i}" }
body "Dolor sit amet"
passed false
end
end
view:
<h1>All Questions</h1>
<%= paginate #questions %>
<ul class="questions">
<% #questions.each do |question| %>
<li>
<section class="question_<%= question.id %> clearfix">
<h2><%= link_to truncate(question.title, length: 62), question_path(question) %></h2>
<p><%= truncate(question.body, length: 70) %></p>
</li>
<% end %>
</ul>
controller:
class QuestionsController < ApplicationController
def index
#questions = Question.page(params[:page])
end
end
ruby 1.9.3p429, rails 3.2.13, rspec-rails 2.13.1, capybara 2.1.0, kaminari 0.14.1, faker 1.0.1, factory_girl_rails 4.1.0
can you ensure that you are creating factories before visit ?
Maybe something like instead of
before { visit questions_path }
before { 25.times { FactoryGirl.create(:question) } }
that
before do
25.times { FactoryGirl.create(:question) }
visit questions_path
end
If it will not help maybe you can display content of page?
puts page.inspect
Related
I am working on a back-office app. The apps I am deploying have a model/table of user_messages. The user messages are used to display admin messages from a central app. The idea is that I can use that app to publish messages to the individual apps such as "System will be unavailable from noon to 1 on Friday".
The individual apps use their own schema in the database. for example, the research library would be rl.user_messages etc.
Since I will need to access multiple tables, I set it up so I can access external tables.
production:
adapter: sqlserver
host: server1
port: 1435
database: web
username: XX
password: xXX
schema_search_path: umc
technical_libraries:
adapter: sqlserver
host: server1
port: 1435
database: XXXX
username: XX
password: XXXXXXXX
schema_search_path: tl
The model that lets me connect to the technical library as an external model is
class TechnicalLibrary < ActiveRecord::Base
self.abstract_class = true
def self.table_name_prefix
'tl_'
end
establish_connection "technical_libraries" # TODO might want to name this to a generic
end
class UserMessage < TechnicalLibrary
self.table_name = "tl.user_messages" # for this one, as opposed to the product development, we need to specify the schema.
end
My technical Libraries controller is
class TechnicalLibrariesController < ApplicationController
def index
#user_messages= TechnicalLibrary::UserMessage.all
end
def show
#technical_library = TechnicalLibrary::UserMessage.first # TODO HARDWIRED -
end
def new
#technical_library = TechnicalLibrary::UserMessage.new
end
def edit
#technical_library = TechnicalLibrary::UserMessage.find(params[:id])
end
def create
#technical_library = TechnicalLibrary::UserMessageRl.new(technical_library_params)
respond_to do |format|
if #technical_library.save
format.html { redirect_to #technical_library, notice: 'Technical library was successfully created.' }
format.json { render :show, status: :created, location: #technical_library }
else
format.html { render :new }
format.json { render json: #technical_library.errors, status: :unprocessable_entity }
end
end
end
def update
respond_to do |format|
if #technical_library.update(technical_library_params)
format.html { redirect_to #technical_library, notice: 'technical library was successfully updated.' }
format.json { render :show, status: :ok, location: #technical_library }
else
format.html { render :edit }
format.json { render json: #technical_library.errors, status: :unprocessable_entity }
end
end
end
def destroy
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_technical_library
#technical_library = TechnicalLibrary.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def technical_library_params
params.require(:technical_library).permit(:message, :expires)
end
My technical Libraries form is
<%= form_for(#technical_library) do |f| %>
<% if #technical_library.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#technical_library.errors.count, "error") %> prohibited this technical_library from being saved:</h2>
<ul>
<% #technical_library.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label :message %><br>
<%= f.text_field :message %>
</div>
<div class="field">
<%= f.label :expires %><br>
<%= f.datetime_select :expires %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
<hr>
Controller <%= controller_name %> | <%= action_name %>
<hr>
The form looks as follows. The submit button seems to be wrong. it is pointing to another model.
If I click on the submit button, I get an error message as follows. I suspect that the problem lies in inheriting from another model.
NameError in UserMessagesController#show
uninitialized constant TechnicalLibrary::UserMessageRl
Rails.root: C:/Users/cmendla/RubymineProjects/user_message_console_3
Application Trace | Framework Trace | Full Trace
app/controllers/user_messages_controller.rb:15:in `show'
Request
Parameters:
{"id"=>"1"}
I had a UserMessage model that I'm probably not going to use since I will connect to the individual application's tables.
class UserMessage < ActiveRecord::Base
end
OK - figured it out. I had to specify the controller and action in the form_for statement.
<%= form_for #technical_library, :url => { :controller => "technical_libraries", :action => "update" }, :html => {:method => :post} do |f| %>
That seems to be doing the trick
In my tickets_controller.rb:
def create
#ticket = #project.tickets.build(ticket_params)
#ticket.author = current_user
if #ticket.save
flash[:notice] = "Ticket has been created."
redirect_to [#project, #ticket]
else
flash.now[:alert] = "Ticket has not been created."
render "new"
end
end
So I assumed, I should be OK to pass the test, but it's giving me the errors below.
I'm under impression it's not invoking the email address from current_user.email...
The repo here https://github.com/tenzan/ticketee.
Deployed version here https://github.com/tenzan/ticketee
$ rspec spec/features/creating_tickets_spec.rb
...F
Failures:
1) Users can create new tickets with valid attributes
Failure/Error: expect(page).to have_content "Author: #{user.email}"
expected to find text "Author: test4#example.com" in "Internet Explorer Non-standards compliance My pages are ugly!"
# ./spec/features/creating_tickets_spec.rb:36:in `block (3 levels) in <top (required)>'
# ./spec/features/creating_tickets_spec.rb:35:in `block (2 levels) in <top (required)>'
Finished in 0.64558 seconds (files took 1.3 seconds to load)
4 examples, 1 failure
Failed examples:
rspec ./spec/features/creating_tickets_spec.rb:30 # Users can create new tickets with valid attributes
UPDATE 1:
show.html.erb for ticket:
<header>
<h2><%= #ticket.name %></h2>
<ul class="actions">
<li><%= link_to "Edit Ticket", [:edit, #project, #ticket],
class: "edit" %></li>
<li><%= link_to "Delete Ticket", [#project, #ticket], method: :delete,
data: { confirm: "Are you sure you want to delete this ticket?"},
class: "delete" %></li>
</ul>
</header>
<table id="attributes">
<tr>
<th>Author: </th>
<td><%= #ticket.author.email %></td>
</tr>
<tr>
<th>Created: </th>
<td><%= time_ago_in_words(#ticket.created_at) %> ago</td>
</tr>
</table>
<div id="ticket">
<header>
<h1><%= #project.name %></h1>
</header>
<header>
<h2><%= #ticket.name %></h2>
</header>
<%= simple_format(#ticket.description) %>
</div>
creating_tickets_specs.rb:
require 'rails_helper'
RSpec.feature 'Users can create new tickets' do
let(:user) { FactoryGirl.create(:user) }
before do
login_as(user)
project = FactoryGirl.create(:project, name: "Internet Explorer")
visit project_path(project)
click_link "New Ticket"
end
scenario "with valid attributes" do
fill_in "Name", with: "Non-standards compliance"
fill_in "Description", with: "My pages are ugly!"
click_button "Create Ticket"
expect(page).to have_content "Ticket has been created."
within("#ticket") do
expect(page).to have_content "Author: #{user.email}"
end
end
scenario "when providing invalid attributes" do
click_button "Create Ticket"
expect(page).to have_content "Ticket has not been created."
expect(page).to have_content "Name can't be blank"
expect(page).to have_content "Description can't be blank"
end
scenario "with an invalid description" do
fill_in "Name", with: "Non-standards compliance"
fill_in "Description", with: "It sucks"
click_button "Create Ticket"
expect(page).to have_content "Ticket has not been created."
expect(page).to have_content "Description is too short"
end
end
A couple things
After you set author on ticket, are you calling save?
What is in the show template where it's blowing up?
Typically I would write your controller code as:
current_user.tickets.create ticket_params
Which, assuming the relationships are set up correctly, will automatically set up the relationships as you would expect.
Rspec was looking for "Author: test4#example.com" within ticket tag as per within("#ticket") as described in the creating_tickets_spec.rb, but in my case it was out of that scope.
So, putting it inside solved the issue.
I would appreciate any help why my test is failing. I am doing it based on Michael Hartl tutorial and I tried almost everything and read a lot of about it, but still clueless.
Tahnks
My test:
describe "pagination" do
before(:all) do
sign_in FactoryGirl.create(:user)
30.times { FactoryGirl.create(:user) }
visit users_path
end
after(:all) { User.delete_all }
it 'has the right div' do
page.should have_selector('div.pagination')
end
it "should list each user" do
User.paginate(page: 1).each do |user|
expect{page}.to have_selector('li', text: user.username)
end
end
My view:
<h1>Všichni uživatelé</h1>
<%= will_paginate %>
<ul class="users">
<% #users.each do |user| %>
<li>
<%= gravatar_for user%>
<%= link_to user.username, user %>
</li>
<% end %>
</ul>
<%= will_paginate(:renderer => BootstrapPagination::Rails)%>
My controller:
def index
#users = User.paginate(page: params[:page])
end
My error:
1) User pages index pagination should list each user
Failure/Error: expect{page}.to have_selector('li', text: user.username)
expected css "li" with text "Person 44" to return something
# ./spec/requests/user_pages_spec.rb:122:in `block (5 levels) in <top (required)>'
# ./spec/requests/user_pages_spec.rb:121:in `block (4 levels) in <top (required)>'
I think the line:
expect{page}.to have_selector('li', text: user.username)
Should be:
expect{page}.to have_selector('li', text: user.user.name)
I'm relatively new to rails and am trying to pull off my first polymorphic association with comments.
I am running rails 3.2.3
Edit - When I try to post a comment, my log is returning this error:
Started POST "/comments" for 127.0.0.1 at 2012-05-20 13:17:38 -0700
Processing by CommentsController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"SOLcF71+WpfNLtpBFpz2qOZVaqcVCHL2AVZWwM2w0C4=", "comment"=>{"text"=>"Test this comment"}, "commit"=>"Create Comment"}
User Load (0.3ms) SELECT "users".* FROM "users" WHERE "users"."id" = 101 LIMIT 1
Completed 500 Internal Server Error in 126ms
NoMethodError (undefined method `Comment' for nil:NilClass):
app/controllers/comments_controller.rb:13:in `create'
I have tried out many different solutions offered on SO and elsewhere, including the answer from Jordan below, due, I'm sure, to my own inexperience, but have been unable to resolve the error.
The trace calls out line 13 in the Comments Controller and I commented after that line below to mark the error:
class CommentsController < ApplicationController
def index
#commentable = find_commentable
#comments = #commentable.comments
end
def new
#post = Post.find(params[:post_id])
end
def create
#commentable = find_commentable
#comment = #commentable.comments.build(params[:comment]) #<<<<LINE 13
if #comment.save
flash[:notice] = "Successfully created comment."
redirect_to :id => nil
else
render :action => 'new'
end
end
private
def find_commentable
params.each do |name, value|
if name =~ /(.+)_id$/
return $1.classify.constantize.find(value)
end
end
nil
end
end
Posts Controller:
def show
#post = Post.find(params[:id])
respond_to do |format|
format.html # show.html.erb
format.json { render :json => #post }
end
end
Comment template (in post show)
<ul id="comments">
<% if #comments %>
<h2>Comments</h2>
<% #comments.each do |comment| %>
<li><%= comment.text %></li>
<% end %>
<% else %>
<h2>Comment:</h2>
<% end %>
</ul>
<%= simple_form_for [#commentable,Comment.new], :html => { :class => 'form-horizontal', :multipart => true } do |f| %>
<fieldset>
<%= f.input :text %>
Upload Photo <%= f.file_field :photo %>
</fieldset>
<div class="form-actions">
<%= f.submit nil, :class => 'btn btn-primary' %>
</div>
<% end %>
Post show:
<p id="notice"><%= notice %></p>
<div class="row">
<div class="span2 offset1">
<%= image_tag #post.photo.url(:show) %>
</div>
<div class="span5">
<h1><%= #post.title %></h1>
<p><%= #post.index_text.html_safe %></p>
<p><%= #post.show_text.html_safe %></p>
<%= render "comments/comment" %>
<%= render "comments/form" %>
<% if can? :update, #course %>
<%= link_to 'Edit Post', edit_post_path(#post), :class => 'btn btn-mini' %>
<%= link_to 'Delete Post', #post,
confirm: 'Are you sure?',
method: :delete,
:class => 'btn btn-mini' %>
<%= link_to 'New Post', new_post_path, :class => 'btn btn-mini' %>
<% end %>
</div>
<nav class="span2 offset1">
<ul class="well">
<li>Category 1</li>
<li>Category 2</li>
</ul>
</nav>
</div>
<div class="row offset2">
<%= link_to 'Back to Posts', posts_path, :class => 'btn btn-mini' %>
</div>
Routes:
resources :posts, :has_many => :comments
resources :comments
It is probably something obvious that someone with more experience can resolve. Let me know if anything comes to mind. Brian
The problem is that #commentable is nil, which means that CommentsController#find_commentable is returning nil. I think your regular expression is sound, so that means one of two things is happening in find_commentable:
There aren't any keys in params that match your regex.
Your regex is matching but there aren't any records in the resulting table with the id in value.
Debug this as usual by inspecting params and the records in your database to make sure they look like you expect them to look.
The problem is your find_commentable method.
Here are the params passed to your CommentsController#create:
Started POST "/comments" for 127.0.0.1 at 2012-05-20 13:17:38 -0700
Processing by CommentsController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"SOLcF71+WpfNLtpBFpz2qOZVaqcVCHL2AVZWwM2w0C4=", "comment"=>{"text"=>"Test this comment"}, "commit"=>"Create Comment"}
Here is your CommentsController#create:
def create
#commentable = find_commentable
#comment = #commentable.comments.build(params[:comment]) #<<<<LINE 13
def find_commentable
params.each do |name, value|
if name =~ /(.+)_id$/
return $1.classify.constantize.find(value)
end
end
nil
end
As you can see, find_commentable expects a param like xx_id (for example, comments_id) which it uses to search for an appropriate class (in case of comments_id, it will be Comment), otherwise it returns nil. Refer classify and constantize here.
Your params do not contain any such param. So, you always get a nil object.
Your find_commentable needs some rework. I think in case of nested_fields, it should be an expression like
/(.+)_attributes$/
instead of
/(.+)_id$/.
And you need to have
:accepts_nested_attributes_for :commentable
in your Comment model class.
I tried both of the above answers, but the problem continued.
I ended up consulting with a friend who suggested the following solution, which I like because it's more elegant than my original attempt and easier to read (for later, when I or someone else need to return to the code):
def find_commentable
if params[:post_id]
Post.find(params[:post_id])
#elsif params[:other_id]
# Other.find(params[:other_id])
else
# error out?
end
end
The commented out section will refer to other associations once I get them up and running.
I am attempting to implement Thinking Sphinx 2.0.10 which from my understanding is compatible with Rails 3. I am very new to programming using Ruby on Rails. I have gone through quite a few articles on StackOverflow but could not find a solution to my problem.
I installed the gem without the :require parameter using in my Gemfile.
gem 'thinking-sphinx', '2.0.10'
I have a working Rails application that displays a list that I would like to add a search to.
Here is my code for defining the indexes in my model file.
define_index do
indexes :email, :sortable => true
indexes :name, :sortable => true
indexes microposts.content, :as => :micropost_content
end
Here is the Rails code in my controller file. The commented out line is the original code that is working. I have a default for will_paginate I think in the application controller for 15 records per page.
def index
#users = User.search params[:search], :per_page => 15
# #users = User.paginate(page: params[:page])
end
Here is the search box that I added to my index page.
<p>
<%= text_field_tag :search, params[:search] %>
<%= submit_tag "Search", :name => nil %>
</p>
Here is my rSpec code. This is the original code that I was using before I attempted to implement Thinking Sphinx.
describe "index" do
let(:user) { FactoryGirl.create(:user) }
before(:each) do
sign_in user
visit users_path
end
it { should have_selector('title', text: 'All users') }
describe "pagination" do
before(:all) { 15.times { FactoryGirl.create(:user) } }
after(:all) { User.delete_all }
let(:first_page) { User.paginate(page: 1) }
let(:second_page) { User.paginate(page: 2) }
it { should have_link('Next') }
it { should have_link('2') }
it { should_not have_link('delete') }
it "should list each user" do
User.all[0..2].each do |user|
page.should have_selector('li', text: user.name)
end
end
it "should list the first page of users" do
first_page.each do |user|
page.should have_selector('li', text: user.name)
end
end
it "should not list the second page of users" do
second_page.each do |user|
page.should_not have_selector('li', text: user.name)
end
end
describe "as an admin user" do
let(:admin) { FactoryGirl.create(:admin) }
before do
sign_in admin
visit users_path
end
it { should have_link('delete', href: user_path(User.first)) }
it "should be able to delete another user" do
expect { click_link('delete') }.to change(User, :count).by(-1)
end
it { should_not have_link('delete', href: user_path(admin)) }
end
end
end
When I run my rSpec test I get the following error:
Failure/Error: visit users_path
ActionView::Template::Error:
getaddrinfo: nodename nor servname provided, or not known
The page displays just fine. When I enter text in the search box and click the button nothing happens which is no surprise to me.
I am able to run Sphinx on the terminal. The searches work fine. I just do not know enough to debug this problem with Thinking Sphinx. I have searched many pages on this website and many others the past few days but none of them are dealing with this issue. Any help would be appreciated.
Did you initialize the sphinx database?
Usually you just need to do something like:
rake ts:rebuild
This should automatically run rake ts:conf for you and rebuild your indexes.
You could also use rake ts:in to update the indexes.
A simple way to test if this is working is to run the rails console (rails c) and try manually searching your users (User.search).
If you get any results, the indexes are available and you can troubleshoot your views/controllers next ;)