looks like I am losing 'San Francisco' at the start of the Update test in this example - not sure why - when I do a puts response.body at the end the Post Test everything looks ok - here is my flights_spec.rb:
require 'rails_helper'
require 'spec_helper'
require 'flight'
RSpec.describe FlightsController, type: :controller do
render_views
let(:flight0) { Flight.create(:destination => "Las Vegas") }
it "Get Test" do
puts 'Get Test'
get :index, :format => :json
puts "Body = " + response.body
expect(response.body).to include('Las Vegas')
end
it "Post Test" do
puts 'Post Test'
post :create, :flight => {:destination => "San Francisco"}
puts "Post status:" + response.status.to_s
expect(response).to redirect_to(assigns(:flight))
redirect_to(response.headers['Location'])
get :index, :format => :json
puts "Body = " + response.body
expect(response.body).to include("San Francisco")
end
it "Update Test" do
puts 'Delete Test'
get :index, :format => :json
puts "Body = " + response.body
expect(response.body).to include("San Francisco")
end
end
RSpec assumes that you are writing each test to be independent of the other tests. However, the way you have it here, Update Test relies on Post Test to create the data it needs. RSpec automatically undoes any changes you made between each test. You can think of each it block as resetting everything back to the initial state.
A quick fix would be to simply aim the delete at the Las Vegas object instead since this flight is already being recreated for each test because of the let statement:
it "Update Test" do
puts 'Delete Test'
get :index, :format => :json
puts "Body = " + response.body
expect(response.body).to include("Las Vegas")
# rest of your test
end
Also I just would note that you may run into issues with the let statement because it is lazily instantiated, meaning it may not actually create a Las Vegas flight until you actually try to use the flight0 variable in your test. You can fix that by simply adding a bang to the end, like this let!(:flight_0) {}.
Related
When writing a unit test in phoenix framework how do you check if a json response contains a list.
Existing test is below which fails because children gets populated. I just want the test to tell me that my json response contains children and children is a list.
test "shows chosen resource", %{conn: conn} do
parent = Repo.insert! %Parent{}
conn = get conn, parent_path(conn, :show, parent)
assert json_response(conn, 200)["data"] == %{"id" => parent.id,
"children" => []}
end
I would use three asserts for this, using a pattern match assert first to assert the basic structure and extract id and children:
assert %{"id" => id, "children" => children} = json_response(conn, 200)["data"]
assert id == parent.id
assert is_list(children)
Note that this test will pass even if the map contains keys other than id and children.
With [json schema][2] you can generate a json to use with (https://github.com/jonasschmidt/ex_json_schema) to validate a full json structure.
iex> schema = %{
"type" => "object",
"properties" => %{
"foo" => %{
"type" => "string"
}
}
} |> ExJsonSchema.Schema.resolve
and
iex> ExJsonSchema.Validator.valid?(schema, %{"foo" => "bar"})
and remember have only one logical assertion per test” (http://blog.stevensanderson.com/2009/08/24/writing-great-unit-tests-best-and-worst-practises/)
I keep getting the same error since I upgraded to:
gem 'twilio-ruby', '~> 5.0.0.rc4'
The call was successful set to Twilio, but the getting some error.
app/controllers/home_controller.rb:59:in `rescue in call'
require "rubygems"
require "twilio-ruby"
def call
#twilio = Twilio::REST::Client.new account_sid, auth_token
begin
#call = #twilio.account.calls.create({
:to => ,
:from => twilio_number,
:url => url,
:method => "GET",
:if_machine => "Hangup",
:timeout => "20"
})
# Getting current call status (seems like error here...!)
get_status(#call.sid)
rescue Twilio::REST::RequestError => error
#err_msg = error.message
puts #err_msg
#returned error is like below:
#NameError (uninitialized constant Twilio::REST::RequestError)
end
end
Code for getting current call status:
def get_status(sid)
#twilio = Twilio::REST::Client.new account_sid, auth_token
#call = #twilio.account.calls.get(sid)
puts "Process Status : " + #call.status
return #call.status
end
Please help to figure it out.
Thank you!
For version 5, Try Twilio::REST::RestError.
This is documented here:
There are new classes to rescue errors from. The new library now uses the Twilio::REST::RestError class.
I have a simple spec testing the creation of an object of the Baseline class.
it "allows a user to create a baseline score with valid content" do
expect(#user.baselines.count).to eq(0)
#baseline = post(:create, :user_id => #user.id, :baseline => valid_attributes)
expect(response).to redirect_to '/patients/list'
expect(flash[:notice]).to eq("Baseline scores for case #{#baseline.case_id} was successfully created.")
expect(Baseline.all.count).to eq(1)
end
But I get this. I am uncertain where to begin with this - I am uncertain why I can't access the case_id attribute of #baseline.
NoMethodError:undefined method `case_id' for <ActionController::TestResponse:0x007f8f5ab4f3c0>
Just to show...these are the valid attributes
let(:valid_attributes) do {
:dx1 => "IPF",
:dxcon1 => 100,
:db1 => "Progressive",
:dbcon1 => 100,
:mgt=> "Drugs",
:biopsy => "Yes",
:patient_id => #patient.id,
:case_id => #patient.case,
}
end
post doesn't return a model instance it returns a TestResponse object which gives you access to headers, status code, etc. To access the object created as a side effect of calling the :create action you can do Baseline.last (in this case Baseline.first would also work since there are no existing baseline objects)
Also note - if you have an instance variable named #baseline that is assigned in the controller you can access that with assigns(:baseline)
expect(assigns[:baseline]).to be_a(Baseline)
If have some static pages in a tree structure. The ones at the first level are served using static_pages_controller.rb and in my routes.rb I have :
get '/static_pages/news' , :to => 'static_pages#news' , :as => 'news'
get '/static_pages/index' , :to => 'static_pages#index' , :as => 'index'
....
The above exist in
app\views\static_pages\news.html.erb
app\views\static_pages\index.html.erb
....
Now, I pasted some other static pages underneath the static_pages root:
app\views\static_pages\ermis\news.html.erb
app\views\static_pages\ermis\index.html.erb
....
I added in routes.rb this:
get '/static_pages/ermis/news' , :to => 'static_pages#news' , :as => 'news'
get '/static_pages/ermis/index' , :to => 'static_pages#index' , :as => 'index'
The above doesnt work because the actions already exist (parent folders). So I went the painful step of renaming the files to (there must be a better way though?!?)
app\views\static_pages\ermis\ermisnews.html.erb
app\views\static_pages\ermis\ermisindex.html.erb
....
and my routes.rb became
get '/static_pages/ermis/news' , :to => 'static_pages#ermisnews' , :as => 'ermisnews'
get '/static_pages/ermis/index', :to => 'static_pages#ermisindex', :as => 'ermisindex'
....
the controller is empty
class StaticPagesController < ApplicationController
end
Why cant the pages be served ? what am I missing?
When I click on
<%= link_to("Ermis", ermisnews_path, class: 'pictureTitle') %>
I get
"The action 'ermisnews' could not be found for StaticPagesController"
Here my routes.rb
Prefix Verb URI Pattern Controller#Action
root GET / static_pages#index
ermisindex GET /static_pages/ermis/index(.:format) static_pages#ermisindex
ermisnews GET /static_pages/ermis/news(.:format) static_pages#ermisnews
news GET /static_pages/news(.:format) static_pages#news
index GET /static_pages/index(.:format) static_pages#index
NOTE: I do not get an error when using link directly pointing to .erb files on static_pages
<%= link_to("News" , news_path , class: 'pictureTitle')
Question:
1) How can I use the same controller to also serve static pages underneath /static_pages eg. /static_pages/ermis
2) Am I obliged to actually rename the files to have them represent unique actions?
In route.rb, change your routes as:
resources :static_pages do
resources :ermis do
get 'ermisnews' , :on => :collection
end
end
match '/ermisnews' => 'static_pages#ermisnews', :as => :news
And then run rake routes.
Eventually I found a solution to my issue:
created the following namespace:
namespace :sp do
resources: ixanos
resources: ermis
end
created the following controllers
class Sp::IxanosController < ApplicationController
end
class Sp::ErmisController < ApplicationController
end
Placed the controllers under app/controllers/sp/
Created the directories app/views/sp/ixanos and app/views/sp/ermis and copied my files in them.
(*) This way I can have as many static pages as I want underneath the given roots (ermis and ixanos). I haven't tested the situation whereby I will have sub-directories like sp/ermis/dir1/dir2 ...
I am having trouble testing my mailer. It appears assigning attributes [:to, :from, :reply_to] with a email in the format described as email-with-name doesn't work.
Here is a simple example.
class MessageMailer < ActionMailer::Base
def simple
mail(
from: "Aaron Test <aaron#test.com>",
to: "Aaron Test <aaron#test.com>",
reply_to: "Aaron Test <aaron#test.com>"
)
end
end
message_mailer_spec.rb
EXPECTED = "Aaron Test <aaron#test.com>"
describe MessageMailer do
before do
#email = MessageMailer.simple
end
it "expect `from` to eq #{EXPECTED}" do
expect( #email.from ).to eq(EXPECTED)
end
it "expect `to` to eq #{EXPECTED}" do
expect( #email.to ).to eq(EXPECTED)
end
it "expect `reply_to` to eq #{EXPECTED}" do
expect( #email.reply_to ).to eq(EXPECTED)
end
end
Test results all the same
1) MessageMailer expect `reply_to` to eq Aaron Test <aaron#test.com>
Failure/Error: expect( #email.reply_to ).to eq(EXPECTED)
expected: "Aaron Test <aaron#test.com>"
got: ["aaron#test.com"]
(compared using ==)
Anyone know how to assign [to:, from:, reply_to:] in the email-with-name format?
Am I missing something?
Are there different methods that hold the email headers that I can test against?
Ok I got it by testing against the header hash of the email.
This is how to test the values of 'from', 'reply_to' and 'to' in rspec.
describe MessageMailer do
before do
#email = MessageMailer.simple
end
it "expect `from` to be formatted correctly" do
expect( #email.header['From'].to_s ).to eq("Aaron Test <aaron#test.com>")
end
it "expect `reply_to` to be formatted correctly" do
expect( #email.header['Reply-To'].to_s ).to eq("Aaron Test <aaron#test.com>")
end
it "expect `to` to be formatted correctly" do
expect( #email.header['To'].to_s ).to eq("Aaron Test <aaron#test.com>")
end
end
* Update:
The square brackets you're getting indicate that you're receiving an array. So you need to extract the values out of the array to verify their validity. The reason for this is that you could have multiple addressees, so for example the object could return:
["Aaron Test ", "Renoir "]
As far as I understand, you don't need to use the square brackets, and you don't need to include the quote marks in the string.
These should work:
from: "Aaron Test <aaron#test.com>",
reply_to: "Aaron Test <aaron#test.com>"