0

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.

Ryzokuken
  • 40
  • 1
  • 11
  • 1
    Without seeing the actual controller code we unlikely could help. – Aleksei Matiushkin Jul 10 '17 at 06:42
  • @mudasobwa I will add the concerned function too. – Ryzokuken Jul 10 '17 at 06:43
  • @mudasobwa done. – Ryzokuken Jul 10 '17 at 06:45
  • 1
    I don't know about your particular problem but I'd advise you to start digging for the root of the problem yourself by debugging. Install `pry-byebug` (which is the debugger I use for rails apps, there are other solutions) and set [debug] breakpoints using `binding.pry`. Start setting breakpoints in a top-down manner, if you can't isolate the problematic parts on first glance (-> if-clause) thus incrementally analysing the flow through the [controller] code. Most times this is way faster than posting on SO and waiting for a response. Hope that helps, good luck – A. Neumann Jul 10 '17 at 06:52
  • Thanks, @A.Neumann. I will definitely try that. – Ryzokuken Jul 10 '17 at 06:56
  • If you experience any problems during debugging don't hesitate to ask for further help by starting a chat! – A. Neumann Jul 10 '17 at 07:00
  • @A.Neumann need atleast 20 reputation to do that :/ Thanks anyway. – Ryzokuken Jul 10 '17 at 07:05
  • Why do you test creation with **`GET`** request: `get :create_by_token, @params, @headers`? It should be **`POST`**, shouldn’t it? – Aleksei Matiushkin Jul 10 '17 at 07:06
  • @Ryzokuken in this particular case the debugger is of very little help, unless you are to put a breakpoint deeply inside Rails middleware. – Aleksei Matiushkin Jul 10 '17 at 07:07
  • @mudasobwa I will try using POST instead, thanks. Although, I doubt that's the issue because in that case, it would have thrown a 405 "Method Not Allowed" status. – Ryzokuken Jul 10 '17 at 07:11
  • @mudasobwa yep, no luck. – Ryzokuken Jul 10 '17 at 07:12
  • @mudasobwa: You surely do not need to digg into the middleware to test basic HTTP request handling by the controller... simply put breakpoints into the relevant parts of the controller and see what's happening in the context of your test/spec. – A. Neumann Jul 10 '17 at 07:15
  • Show your `routes.rb`. – Aleksei Matiushkin Jul 10 '17 at 07:21
  • @A.Neumann this request is evidently **not handled by a controller**, Rails returns a response without even getting into a controller. I believe you’d better learn a bit of Rails before using words like “surely.” – Aleksei Matiushkin Jul 10 '17 at 07:21
  • @mudasobwa would I need to add a route for this for this purpose? I did not add one yet, I think. – Ryzokuken Jul 10 '17 at 07:27
  • If you expect the request to be routed, then yes, you need to add a route. Rails does a lot of magic, but it does not code for you :) – Aleksei Matiushkin Jul 10 '17 at 07:29
  • @mudasobwa I knew I would need a route later when I wanted to use it, but not if I wanted to test it. Adding a route. Do I need to add all params in the route URL, or will `/api/comment.:format` work? – Ryzokuken Jul 10 '17 at 07:31
  • It heavily depends on your intent. For `POST` with a body as above, `/api/comment.:format` would work. – Aleksei Matiushkin Jul 10 '17 at 07:44

2 Answers2

0

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}
0

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.

Ryzokuken
  • 40
  • 1
  • 11