Rails, ActionController::UnknownFormat when testing a post (create) request - ruby-on-rails

I am testing my rails application and so far this test is failing all the others pass.
The test is as follows:
test "should create broadcast" do
assert_difference('Broadcast.count') do
post :create, broadcast: { title: "title", content: "content", user_id: #broadcast.user_id}
end
assert_redirected_to broadcast_path(assigns(:broadcast))
end
and the controller has this snippet:
feed_result = []
if params.has_key?(:feeds)
feed_result = params[:feeds]
else
feed_result = ["None"]
end
if #broadcast.save
# Only after saving do we try and do the real broadcast. Could have been
# done using an observer, but I wanted this to be more explicit
results = BroadcastService.broadcast(#broadcast, feed_result)
if results.length > 0
# Something went wrong when trying to broadcast to one or more of the
# feeds.
#broadcast.errors[:base] << ("#{I18n.t('broadcasts.unable-message')}: #{results.inspect}")
flash[:error] = I18n.t('broadcasts.saved-but-message')
else
flash[:notice] = I18n.t('broadcasts.saved-message')
no_errors = true
end
if no_errors
format.html { redirect_to(broadcasts_url(page: #current_page)) }
format.json { render json: #broadcast, status: :created, location: #broadcast }
else
format.html { render :new }
format.xml {
# Either say it partly worked but send back the errors or else send
# back complete failure indicator (couldn't even save)
if results
render json: #broadcast.errors, status: :created, location: #broadcast
else
render json: #broadcast.errors, status: :unprocessable_entity
end
}
end
end
end
I have left out information that is unnecessary. it must be noted that if i am not running a test, and i am in fact running the live server this create method functions as expected and no error is thrown.
i have tried the following:
post :create, broadcast: { title: "title", content: "content", user_id: #broadcast.user_id, format: :html}
post :create, broadcast: { title: "title", content: "content", user_id: #broadcast.user_id, format: :json}
post :create, broadcast: { title: "title", content: "content", user_id: #broadcast.user_id, format: 'html'}
post :create, broadcast: { title: "title", content: "content", user_id: #broadcast.user_id, format: 'json'}
And the error persists.
If anyone has any ideas, id love to hear them!
Thanks,
Chris.

Related

how to write test case for create and update actions in rspec?

Restaurant and Location models contains HABTM association.
how to write test cases for locations controller
def create
#restaurant = Restaurant.find(params[:restaurant_id])
#location = #restaurant.locations.create(location_params)
if #location.save
flash[:notice] = 'Location added!'
redirect_to admin_locations_path
else
flash[:error] = 'Failed to edit location!'
render :new
end
end
def update
#location = Location.find(params[:id])
if #location.update_attributes(location_params)
flash[:notice] = 'Location updated!'
redirect_to admin_locations_path
else
flash[:error] = 'Failed to edit Location!'
render :edit
end
end
Try the following code to create
restaurant = FactoryBot.create(:restaurant, name: Faker::Name.name)
post :create, params: { restaurant_id: restaurant.id, location: {restaurant_ids:[restaurant.id]}, format: 'js' }
expect(response).to have_http_status(:success)
Try the following code to update
restaurant = FactoryBot.create(:restaurant, name: Faker::Name.name)
location = FactoryBot.create(:location, restaurant_id: restaurant.id)
patch :update, params: { id: location.id, location: {restaurant_ids:[restaurant.id]}, format: 'js' }
expect(response).to have_http_status(:success)
You can simply create the spec using the following code snippet :
Restaurant = FactoryBot.create(:Restaurant, name: Faker::Name.name)
post :create, params: { location: {restaurant_ids:[Restaurant.id]}, format: 'json'
expect(response.status).to eq(200)
For simple controllers like this, I also like to ensure that the records are being created, so I would also test this:
restaurant = FactoryBot.create(:restaurant, name: Faker::Name.name)
expect {
post(
:create,
params: {
restaurant_id: restaurant.id,
location: { restaurant_ids:[restaurant.id] },
format: 'js'
}
)
}.to change{ Location.count }.by(1)

Trouble testing for an error thrown from AASM gem

I'm having trouble testing for a thrown AASM error.
Here is my controller method:
# controllers/jobs_controller.rb
def change_state
respond_to do |format|
if #job.close && #job.save
format.html { redirect_to #job, notice: 'Job has been closed.' }
format.json { render :show, status: :ok, location: #job }
else
format.html { render :show, notice: 'Job could not be closed.' }
format.json { render json: #job.errors, status: :unprocessable_entity }
end
end
end
My spec looks like this:
# spec/controllers/jobs_controller_spec.rb
describe "POST #change_state" do
it "cannot transition job from closed" do
job.aasm_state = "closed"
job.save!
post :change_state, params: {id: job.hash_id, user_id: user.id}
expect { response }.to raise_error(AASM::InvalidTransition)
end
end
The test fails (with the expected/desired failure):
Failure/Error: if #job.close && #job.save
AASM::InvalidTransition:Event 'close' cannot transition from 'closed'.
I'm just unable to figure out the right syntax to pass the test. I've tried a few variations of the expect line but can't seem to piece it together.
Any guidance is appreciated.
The exception is happening before the expect statement. Try it:
expect {
post(:change_state, params: { id: job.hash_id, user_id: user.id })
}.to(
raise_error(AASM::InvalidTransition)
)

Rails responds with status code 406

I have been working on a test for my function inside Ruby on Rails. However, the test (which expects a status code of :success) fails after receiving a status code 406. Here's the exact failure log:
Failure: Expected response to be a <:success>, but was <406>.
test_should_post_comment_through_token_successfully(CommentControllerTest)
test/functional/comment_controller_test.rb:271:in `block in <class:CommentControllerTest>'
I read a little about the 406 response, and found out that it stands of "Not Acceptable". so I tried setting the Accept, Content-Type, Accept-Language and Accept-Charset headers but I have had no luck.
Here's the code for my test:
test 'should post comment through token successfully' do
#params = {
id: 1,
body: "Test Comment",
username: "Bob"
}
#headers = {
"Accept" => "application/json",
"Accept-Language" => "en-US",
"Accept-Charset" => "utf-8",
"Content-Type" => "application/json",
"Token" => "abcdefg12345"
}
get :create_by_token, #params, #headers
assert_response :success
end
The create_by_token function inside the controller:
def create_by_token
#node = Node.find params[:id]
#user = User.find_by_username params[:username]
#body = params[:body]
#token = request.headers['Token']
p request.headers["Accept"]
p request.headers["Content-Type"]
p request.headers["Token"]
if #user && #user.token == #token
begin
#comment = create_comment(#node, #user, #body)
msg = {
status: :created,
message: "Created"
}
respond_to do |format|
format.xml { render xml: msg.to_xml }
format.json { render json: msg.to_json }
end
rescue CommentError
msg = {
status: :bad_request,
message: "Bad Request"
}
respond_to do |format|
format.xml { render xml: msg.to_xml }
format.json { render json: msg.to_json }
end
end
else
msg = {
status: :unauthorized,
message: "Unauthorized"
}
respond_to do |format|
format.xml { render xml: msg.to_xml }
format.json { render json: msg.to_json }
end
end
end
My route:
post '/bot/comment.:format', to: 'comment#create_by_token'
Am I missing something crucial? How do I go about solving this issue?
I would be happy to provide any other information you would need.
Seems this might be an error with respond_to do block. Kindly check with the routes whether you have configured as resources or resource.
Do update to resources than singular which will help with respond_to do block.
You can also try update your routes as/;
resources :samples, defaults: {format: :json}
Oh, stupid me. I realized that among all the params I was passing, the format was also being passed inside the URL. However, as in the test I was not mentioning a URL which I could pass in the format as the suffix (.xml or .json), I would have to mention the format inside the params explicitly. Here's the updated test code:
test 'should post comment through token successfully' do
#params = {
id: 1,
body: "Test Comment",
username: "Bob",
format: 'json'
}
#headers = {
"token" => "abcdefg12345"
}
post :create_by_token, #params, #headers
assert_response :success
end
Kudos #Sowmiya for leading me to this conclusion. Your answer was not exactly the solution I needed, but it provoked me to think.

Not able to call a controller action in Rspec

I have been trying to implement an RSpec for a Controller called "Estimate controller" to test whether my mailing functionality (sending estimate) working properly or not. But I'm not able to call the controller action from my RSpec. I need to set some values (to, subject, message, cc, current_user, attachments) in a hash and send that hash to Estimate controller.Here is what I tried..
estimates_controller_spec.rb
describe "post 'send_estimate'" do
it "should send estimate " do
#estimate = Fabricate(:estimate, id: Faker::Number.number(10), validity: "12/12/2014", total_value: 1222.00, user_id:#user.id, project_id: #project_id)
est_params = {
to: "rspec#rails.com",
subject: "Estimate",
message: "Check out the Estiamte details",
cc: "respec#rails.com",
current_user: #user,
attachments: ""
}
expect{
post :send_estimate, estimate: est_params
}.to change { ActionMailer::Base.deliveries.count }.by(1)
end
end
estimates_controller.rb
def send_estimate
respond_to do |format|
if #estimate.send_email(params[:to], params[:subject], params[:message], params[:cc], current_user, params[:attachments])
#estimate.create_activity :send_estimate, owner: current_user, recipient: #estimate.project
format.html { redirect_to lead_path(#estimate.project), notice: "Email sent Successfully"}
format.json { head :no_content, status: :ok}
else
format.json { render json: #estimate.errors }
format.html { redirect_to contacts_path, notice: 'Something went wrong' }
end
end
end

Functional Testing Rails, No route matches error

I am trying to fix the following rails functional test:
test "should create broadcast" do
login_as(:one_details)
assert_difference('Broadcast.count') do
post :create, feeds: [:twitter, {alumni_email: 'test#email.com'}], broadcast: {id: 2, content: #broadcast.content, user: #user_details.user_id}
end
assert_redirected_to "#{broadcast_path}?page=1"
end
Here is the error:
1) Error:
BroadcastsControllerTest#test_should_create_broadcast:
ActionController::UrlGenerationError: No route matches {:action=>"show", :controller=>"broadcasts"} missing required keys: [:id]
test/controllers/broadcasts_controller_test.rb:35:in `block in <class:BroadcastsControllerTest>'
I have this in the routes file:
resources :broadcasts, except: [:edit, :update]
In the broadcasts_controller the show method looks like this:
def show
if is_admin?
respond_to do |format|
format.js { render partial: 'show_local',
locals: {broadcast: #broadcast, current_page: #current_page},
layout: false }
format.html # show.html.erb
format.json # show.json.builder
end
else
indicate_illegal_request I18n.t('not allowed to view this')
end
end
The broadcast controller create method:
def create
#broadcast = Broadcast.new(broadcast_params)
# Wire up broadcast with the current user (an administrator)
# Will be an admin user (see before_filter)
# Note the current_user is a user_detail object so we need
# to navigate to its user object
#broadcast.user = current_user.user
# Doing the next line forces a save automatically. I want to defer this
# until the "if" statement
#current_user.user.broadcasts << #broadcast
no_errors = false
respond_to do |format|
if #broadcast.save
# Only after saving do we try and do the real broadcast. Could have been
# done using an observer, but I wanted this to be more explicit
results = BroadcastService.broadcast(#broadcast, params[:feeds])
if results.length > 0
# Something went wrong when trying to broadcast to one or more of the
# feeds.
#broadcast.errors[:base] << ("#{I18n.t('broadcasts.unable-message')}: #{results.inspect}")
flash[:error] = I18n.t('broadcasts.saved-but-message')
else
flash[:notice] = I18n.t('broadcasts.saved-message')
no_errors = true
end
if no_errors
format.html { redirect_to(broadcasts_url(page: #current_page)) }
format.json { render json: #broadcast, status: :created, location: #broadcast }
else
format.html { render :new }
format.xml {
# Either say it partly worked but send back the errors or else send
# back complete failure indicator (couldn't even save)
if results
render json: #broadcast.errors, status: :created, location: #broadcast
else
render json: #broadcast.errors, status: :unprocessable_entity
end
}
end
end
end
end
Change
assert_redirected_to "#{broadcast_path}?page=1"
to
 assert_redirected_to "#{broadcasts_path}?page=1"
also change
post :create, feeds: [:twitter, {alumni_email: 'test#email.com'}], broadcast: {id: 2, content: #broadcast.content, user: #user_details.user_id}
to
post :create, feeds: [:twitter, {alumni_email: 'test#email.com'}], broadcast_params: {id: 2, content: #broadcast.content, user: #user_details.user_id}
you are not passing an id in the redirect check so you either make it broadcasts_path

Resources