I'm new to rails programming and i'm trying to use rails status code when raising a grape exception but my tests are failing. I couldn't find any example on grape documentation so this may be impossible.
I want to know if it is possible and if not, why so?
This works:
rescue_from Example::IsExampleWorking do |_e|
error!({ messages: ["Example is not working because it was not found"] }, 404)
end
But this does not:
rescue_from Example::IsExampleWorking do |_e|
error!({ messages: ["Example is not working because it was not found"] }, :not_found)
end
My test is:
it "return a 404 Not Found status" do
expect(response).to have_http_status(:not_found)
end
edit: guys, I forgot to mention that the error message from he test is
undefined method `to_i' for :not_acceptable:Symbol
Did you mean? to_s
But I didn't find any documentation on grape's docs to make sure they accept only integer as second param.
Thank you :)
Grape allows specification of type when defining parameters.
params do
# Basic usage: require a parameter of a certain type
requires :param_name, type: Integer
end
See: https://www.rubydoc.info/github/ruby-grape/grape/Grape%2FDSL%2FParameters:requires
Http status code are always integer only. That is the industry standard. You can not change the http status code or send http status code as string.
Find the list of http status codes here.
https://www.restapitutorial.com/httpstatuscodes.html
And this is not specific to rails or grape or any other framework.
Related
I'm very confused about latest rspec versions. I've found several answers to this same question but being several years old they apparently don't work anymore.
I have a request spec that tests an endpoint that is behind http_basic_authenticate_with. I couldn't find a way to make this work.
My latest attempt is:
it "returns data_services" do
request.headers.merge!(authenticated_header(ENV.fetch('HTTP_USERNAME'), ENV.fetch('HTTP_PASSWORD')))
get data_services_path
expect(response).to have_http_status(:ok)
end
Unfortunately there's no request object, which exists only after the get is performed. I've tried to pass the headers to the get method too, but no luck.
Is there any way to have requests specs for actions behing http simple auth?
If you're in a request spec (recommended from Rails v5+), you need to pass your headers to the get method as a keyword argument:
get data_services_path, headers: authenticated_header(...)
The syntax you're trying with request.headers is for controller specs, and the rspec docs recommend switching to request specs and not setting headers in controller specs.
I'm working on a Rails 5 JSON API, and I've noticed that it's providing sensible exception-handling out of the box.
For example, ActiveRecord::RecordNotFound results in a 404, ActionController::ParameterMissing results in 400, and these are all returned as well-formed JSON responses.
I've found plenty of documentation on rescue_from, can't locate what's providing this exception-handling for me.
I've dug around in the Rails guides, the docs, as well as in the rails console, e.g.
ActionController::API.new.rescue_handlers
=> []
ApplicationController.new.rescue_handlers
=> []
I'd like to know where the exception-handling is coming from because I've noticed that it's gracefully applied for real requests, but not in controller specs.
For example, if I run a local server and send it a malformed request with curl, I get a sensible error response. But if I try to reproduce that in a controller spec,
it "returns 404 if Yogurt doesn't exist" do
put :update, params: { id: 293459 }
end
the test throws the raw exception (ActiveRecord::RecordNotFound in this case).
When you set up a Rails 5 app with the --api option you end up using ActionController::API. https://github.com/rails/rails/blob/master/actionpack/lib/action_controller/api.rb
The modules are built here: https://github.com/rails/rails/blob/a0061d2389a178b093f0d3f64f58236ffbe088e0/actionpack/lib/action_controller/api.rb#L104 so that's where your responses are coming ultimately from. Looks like the rendering is being handed off to metal at some point.
API actions are configured to return :json by default, so that's why your test is behaving differently than your browser.
For your spec to work the same way you'll have to supply a format:
put :update, params: { id: 293459 }, format: :json
In app we use 3-th part service, what sometimes get broken. We regular testing app by Capybara, Poltergeist. But for tests be more specific in error log I need catch in tests data response from get/post api calls to that 3-th par service. I know about Poltergeist method page.driver.network_traffic but there are no data here, useful for me only response.url and response.status , but also I want somehow get data. Thanks in advance.
Capybara is not suited or designed for API testing, see this blog post http://www.elabs.se/blog/34-capybara-and-testing-apis. There is no access to the get and post requests or responses without hacking the underlying code. Instead, try RackTest. RackTest was created to specifically test APIs: https://github.com/brynary/rack-test.
Edit: with rack-test the homepage documentation is not clear but you can use the Rack::Test::Methods mixin to get the response, see http://www.rubydoc.info/github/brynary/rack-test/Rack/Test/Methods.
For example:
require 'rack/test'
class MyTest < Test::Unit::TestCase
include Rack::Test::Methods
def app
MyApp.new
end
def my_test
get '/'
assert last_response.ok?
assert_equal '<expected_response>', last_response.body
end
end
I have a Rails 4.2 application....I was adding content compression via this thoughtbot blog post, but I get an error such as:
undefined method `get' for #<RSpec::ExampleGroups::Compression:0x00000009aa4cc8>
Perusing over the capybara docs, it seems like you shouldn't be using get. Any idea how to test the below then in Rails 4?
# spec/integration/compression_spec.rb
require 'spec_helper'
feature 'Compression' do
scenario "a visitor has a browser that supports compression" do
['deflate','gzip', 'deflate,gzip','gzip,deflate'].each do|compression_method|
get root_path, {}, {'HTTP_ACCEPT_ENCODING' => compression_method }
response.headers['Content-Encoding'].should be
end
end
scenario "a visitor's browser does not support compression" do
get root_path
response.headers['Content-Encoding'].should_not be
end
end
In a capybara test you would use visit not get (as described here), but that answer won't actually help you because the test you've written above is not an integration test, it's a controller test.
Move it to spec/controllers and use the controller-specific helpers describe/context/it etc. to construct your tests for your controller. You can set the headers and do the sorts of checks that you're doing in the code you're showing.
I'm working on a Rails 2.1 app. This app uses 'rspec', '1.2.9' and 'rspec-rails', '1.2.9' . This app uses restful authentication plugin. There is a :login_required before filter method that I have in my Application Controller which basically does the authentication check before allowing access to controller method.
I referred to some older stack overflow(so) questions where users had similar issues, PFB the errors that I got when I tried each of the recommended solutions with respect to those questions.
1 How to stub Restul-authentication's current_user method?
The error I got -
undefined method `stub!' for #<User:0xf5a9c07c>
2 Rails, Restful Authentication & RSpec - How to test new models that require authentication
With respect to this question, I added the below line of code as given in the second answer to the same.
The error I got when I added the above line is -
controller.stub!(:authenticate).and_return(true)
undefined method `stub!' for Controller_NameController:Class
On closer observation, I find that something's wrong with why my test cases aren't able to pick up the stub method.
Here's my code below that I've written to call a specific action within a controller.
Here Controller_Name refers to a controller name like Users controller and in that sense the Controller_NameController basically will stand for UsersController.
require 'spec_helper'
describe Controller_NameController do
describe "What action to test" do
describe "what specific field to update as part of action" do
before do
#Controller_NameController.stub!(:login_required).and_return(true) #this line throws error wrt point 2
#does some stuff
end
it "should update the flag by calling the update method" do
##user_session = login_as(stub_model(User))
#UserSession.stubs(:new).returns(#user_session) - these two lines throws errors wrt point 1
put :update_flag, :id => #obj.id, :obj => {:flag_name => 1}
#obj.updated_at.hour.should == Time.now.hour
end
end
end
end
I'm not sure what's exactly wrong here. Any pointers on how to get this working would be very helpful.
Thank you.