I am trying to learn Rspec-Cucumber tutorial by referring to "The Pragmatic Programmers - The Rspec Book". I am on the 4th chapter and seems to be stuck with an error and not able to move forward.I have followed exactly as per the tutorial but it is showing the below error (in line : output.messages.should include(message)) when I try to run cucumber feature in my console.
undefined local variable or method `message' for #<Object:0x9c0c05c> (NameError)
My codebreaker_steps.rb file is as follows.
Then /^I should see "([^"]*)"$/ do |arg1|
output.messages.should include(message)
end
class Output
def messages
#messages ||= []
end
def puts(message)
messages << message
end
end
def output
#output ||= Output.new
end
It would be very helpful to you if you take time to familiarize yourself with the basics of ruby. To answer your question, you should change the step definition like this
Then /^I should see "([^"]*)"$/ do |arg1|
output.messages.should include(arg1)
end
or like this
Then /^I should see "([^"]*)"$/ do |message|
output.messages.should include(message)
end
Related
For my personal website build with Rails 5, I'm trying to implement a job for sending a contact form. I'm using the delayed_job_active_record gem.
I generated a job ContactMessageJob:
app/jobs/contact_message_job.rb
class ContactMessageJob < ApplicationJob
queue_as :contact_message
def perform(message)
MessageMailer.send_message(message).deliver_now
end
end
Then in the MessagesController I'm calling the perform_later method on ContactMessageJob:
app/controllers/messages_controller.rb
...
def create
#message = Message.new(message_params)
if #message.valid?
ContactMessageJob.perform_later(#message)
redirect_to contact_path, notice: "Your message has been sent."
else
flash[:alert] = "An error occured while delivering this message."
render :new
end
end
but when I'm trying to send a message through the contact form, I getting this error when executing ContactMessageJob.perform_later(#message):
ActiveJob::SerializationError at /contact
Unsupported argument type: Message
I'm a bit new to using ActiveJob, so I'm not sure how I can fix this. Any suggestions are very welcome.
my repo is at: https://github.com/acandael/personalsite/tree/job
greetings,
Anthony
Rails' ActiveJob does serialization using GlobalID and GlobalID know how to serialize primitive values (string, number) and ActiveRecord objects. Your Message class is an basic model which GID cannot serialize.
Probably easier option for you is to pass to the job the message_params directly and use them from the job itself
MessageMailer.send_message(message_params[:name], message_params[:email], message_params[:content]).deliver_later
*) You don't need the job class on contact_message_job.rb as you can send async email using the deliver_later method
I upgraded my Rails Application from 4.2 -> 5.0.0.1.
Other TESTS works fine (e.g. Model, Helper, Feature), but havinf trouble with my Controller Test.
I have read about Keyword arguments in controller & integration tests in Rails 5. So I changed the code structure as given below...
ActionView::Template::Error: nil is not a valid asset source
setup do
#logo = plogos(:main_logo)
end
test "should get edit" do
puts #logo.id // just to check...working fine
get :edit, params: {id: #logo.id}
assert_response :success
end
But I got new error with ActionView.
Is there anyone encountered and fixed the same issue, please help!
Thank you!
You may want to add some logtrace, probably it hints you where it went wrong.
May it be that the main_logo-fixture doesn't have an image? Since Rails 5 image_tag raises this error when given an nil-value, see also: Rails, "nil is not a valid asset source" for a particular image_tag (Carrierwave)
Besides that, typically the new scaffolded code would look as follows:
require 'test_helper'
class LogosControllerTest < ActionDispatch::IntegrationTest
setup do
#logo = plogos(:main_logo)
end
#...
test "should get edit" do
get edit_logo_url(#logo)
assert_response :success
end
#...
end
I am developing this Rails 3.2 application using the Apartment gem as middleware. The application itself works perfectly and all the RSpec examples also work perfectly when ran individually. However, when I run all the tests at the same time using the bundle exec rspec command, there are two examples that fail in two different controller specs and they do exactly the same thing. Here are the two examples in question:
In the issues_controller_spec.rb file:
describe "GET 'new'" do
# ...
context "for authenticated users" do
before(:each) do
controller.log_in(create(:user))
get :new
end
# ...
it "should create a new issue instance and put it in an instance variable" do
assigns(:issue).should be_an_instance_of Issue
end
end
end
In the users_controller_spec.rb file:
describe "GET 'new'" do
# ...
context "for authenticated users" do
# ...
context "for admin users" do
before(:each) do
admin = create(:admin)
admin.add_role :admin
controller.log_in(admin)
get :new
end
# ...
it "should create a new User instance and put it in an instance variable" do
assigns(:user).should be_an_instance_of User
end
end
end
end
These two examples are affected by a before hook:
before(:each) do
client = create(:client)
#request.host = "#{client.account_name}.lvh.me"
end
When creating a new Client, there is an after_create callback:
# Create the client database (Apartment) for multi-tenancy
def create_client_database
begin
Apartment::Database.create(self.account_name)
rescue Apartment::SchemaExists
return
rescue
self.destroy
end
end
And there is where the examples fail. Now if I remove the begin...rescue...end block and keep the line Apartment::Database.create(self.account_name) I get the following exception in the failling examples:
ActiveRecord::StatementInvalid:
PG::Error: ERROR: current transaction is aborted, commands ignored until end of transaction block
: SET search_path TO public
Again, if I run the examples individually, they pass but if I run all the examples, the two examples above fail.
Does anyone know what I am doing wrong please?
Note: The whole application code can be found here.
I solved this problem by wrapping the line client = create(:client) in a begin, rescue, end block like so:
before(:each) do
begin
client = create(:client)
rescue
client = Client.create!(attributes_for(:client))
end
#request.host = "#{client.account_name}.lvh.me"
end
I don't know how or why this works but I know it works.
For my Rails 3 application I use FactoryGirl together with shoulda context (1.0.0.beta1) and matchers (1.0.0.beta3) for my functional tests.
My problem: in the code example below, the assign_to test fails because #user - to my surprise - turns out to be nil. In the outer setup block, #user is assigned a valid model instance, but from within the should assign_to statement the instance variable is not accessible. Why is that and what is the correct way to write that test?
class UsersControllerTest < ActionController::TestCase
context "as admin" do
setup do
#user = Factory.create(:user)
end
context "getting index" do
setup do
get :index
end
should assign_to(:users).with([#user])
end
end
I discovered that passing the value as a black miraculously works. However, after digging into the actual AssignToMatcher code, it doesn't seem to make sense why the parameter method wouldn't work while the block method would.
For the sake of the +250 rep I'm investing in this, I'd still like an answer that explains why the param method isn't working (and how to fix it), but until then, at least I have a workaround.
#dblp1, hopefully this works for you too. Here's an example specific to your code:
class UsersControllerTest < ActionController::TestCase
context "as admin" do
setup do
#user = Factory.create(:user)
end
context "getting index" do
setup do
get :index
end
should assign_to(:users).with { [#user] }
end
end
end
(I am pasting as an answer as it is fairly long)
I mocked a bit your test and checked what was the results passed.
Interestingly enough, when I call the matcher #post=null (as I believe in your case). The issues I think (after a while of investigation), it coming from the the order the setup do block is called and the fact that the variables defined in one context are not visible in the nested context.
modified class
context "as admin" do
setup do
#post = Post.new
puts "Step 1 - inside setup do"
puts #post.class
end
puts "Step 2 - outside setup do 1"
puts #post.class
context "getting index" do
setup do
get :index
end
puts "Step 3 - calling shoulda"
puts #post.class
should assign_to(:posts).with([#post])
#should assign_to(:posts).with { [#post] }
end
end
And the results in the console
ruby -I test test/functional/posts_controller_test.rb
Step 2 - outside setup do 1
NilClass
Step 3 - calling shoulda
NilClass
Loaded suite test/functional/posts_controller_test
Started
Step 1 - inside setup do
Post
So the setup cycle is called at the end (and not at the beginning) and then your is Nil when passed to the matcher.
Even if I remove the first setup do does not work pretty well.
Step 1 - inside setup do
Post
Step 2 - outside setup do 1
Post
Step 3 - calling shoulda
NilClass
Finally, putting the post in the inner context
Step 3 - calling shoulda
Post
If you call #user = Factory.create(:user) directly inside the "getting index" context, I believe it will work.
When you are working with indexes you should use the plural of the instance variable.
#users rather than #user
You should also populate it as an array.
Finally, Shoulda matchers should start with "it" and be contained in braces, at least in the RSpec world, which is what I use. Not sure if this is the case with Test::Unit or whether your formatting above will work.
Try something like this.
class UsersControllerTest < ActionController::TestCase
context "as admin" do
setup do
#user = Factory.create(:user)
end
context "getting index" do
setup do
#users = Array.new(3) { Factory(:user) }
get :index
end
it { should assign_to(:users).with(#users) }
end
end
Here is some sample tests from my rspec 1.x code:
[:email, :contact_type_id].each do |attr|
it "requires #{attr}" do
e = EmailAddress.new
e.should_not be_valid
# i don't care how many errors there are,
# just that there were errors for this attr.
e.errors(attr).should_not be_nil
end
end
RSpec 2.6.x is forcing me to do this:
[:email, :contact_type_id].each do |attr|
it "requires #{attr}" do
e = EmailAddress.new
e.should_not be_valid
# have expects that I pass a number here :(
e.should have(n).error_on(attr)
end
end
I don't care HOW many errors there are, just that errors showed up when trying to validate the model. It would be cool if I could do something like:
e.should have.errors_on(attr)
Anyone got any ideas?
You can try this:
e.should have_at_least(1).error_on(attr)