Commit 4eed9f659ac29a043be191286cb7f3c1e34ca779

Authored by Michał Młoźniak
1 parent 0945dadc
Exists in master and in 1 other branch production

Add controller specs for V3 api

I've also did some other minor changes:

* Move json payload to fixture file
* Add status code to error cases in controller
* Move v3 api route outside of api namespace. I've some problems with making this
  work in tests.
* Fix issue with custom exception class
app/controllers/api/v3/notices_controller.rb
@@ -23,12 +23,12 @@ class Api::V3::NoticesController < ApplicationController @@ -23,12 +23,12 @@ class Api::V3::NoticesController < ApplicationController
23 render text: 'Notice for old app version ignored' 23 render text: 'Notice for old app version ignored'
24 end 24 end
25 else 25 else
26 - render text: 'Your API key is unknown', :status => 422 26 + render text: 'Your API key is unknown', status: 422
27 end 27 end
28 else 28 else
29 render nothing: true 29 render nothing: true
30 end 30 end
31 rescue AirbrakeApi::ParamsError 31 rescue AirbrakeApi::ParamsError
32 - render text: 'Invalid request' 32 + render text: 'Invalid request', status: 400
33 end 33 end
34 end 34 end
config/routes.rb
@@ -58,10 +58,10 @@ Rails.application.routes.draw do @@ -58,10 +58,10 @@ Rails.application.routes.draw do
58 end 58 end
59 end 59 end
60 end 60 end
61 -  
62 - match '/v3/projects/:project_id/notices' => 'v3/notices#create', via: [:post, :options]  
63 end 61 end
64 62
  63 + match '/api/v3/projects/:project_id/notices' => 'api/v3/notices#create', via: [:post, :options]
  64 +
65 root :to => 'apps#index' 65 root :to => 'apps#index'
66 end 66 end
67 67
lib/airbrake_api/v3/notice_parser.rb
@@ -27,7 +27,7 @@ module AirbrakeApi @@ -27,7 +27,7 @@ module AirbrakeApi
27 private 27 private
28 28
29 def error 29 def error
30 - raise ParamsError unless params.has_key?('errors') && params['errors'].any? 30 + raise AirbrakeApi::ParamsError unless params.has_key?('errors') && params['errors'].any?
31 @error ||= params['errors'].first 31 @error ||= params['errors'].first
32 end 32 end
33 33
spec/controllers/api/v3/notices_controller_spec.rb 0 → 100644
@@ -0,0 +1,54 @@ @@ -0,0 +1,54 @@
  1 +describe Api::V3::NoticesController, type: :controller do
  2 + let(:app) { Fabricate(:app) }
  3 +
  4 + it 'responds to OPTIONS request and sets CORS headers' do
  5 + process :create, 'OPTIONS', project_id: app.api_key
  6 + expect(response).to be_success
  7 + expect(response.headers['Access-Control-Allow-Origin']).to eq('*')
  8 + expect(response.headers['Access-Control-Allow-Headers']).to eq('origin, content-type, accept')
  9 + end
  10 +
  11 + it 'sets CORS headers on POST request' do
  12 + post :create, project_id: 'invalid id'
  13 + expect(response.headers['Access-Control-Allow-Origin']).to eq('*')
  14 + expect(response.headers['Access-Control-Allow-Headers']).to eq('origin, content-type, accept')
  15 + end
  16 +
  17 + it 'returns created notice id in json format' do
  18 + json = Rails.root.join('spec', 'fixtures', 'api_v3_request.json').read
  19 + data = JSON.parse(json)
  20 + data['project_id'] = app.api_key
  21 + data['key'] = app.api_key
  22 + post :create, data
  23 + notice = Notice.last
  24 + expect(response.body).to eq({ notice: { id: notice.id } }.to_json)
  25 + end
  26 +
  27 + it 'responds with 400 when request attributes are not valid' do
  28 + allow_any_instance_of(AirbrakeApi::V3::NoticeParser).to receive(:report).and_raise(AirbrakeApi::ParamsError)
  29 + post :create, project_id: 'ID'
  30 + expect(response.status).to eq(400)
  31 + expect(response.body).to eq('Invalid request')
  32 + end
  33 +
  34 + it 'responds with 422 when api_key or project_id is invalid' do
  35 + json = Rails.root.join('spec', 'fixtures', 'api_v3_request.json').read
  36 + data = JSON.parse(json)
  37 + data['project_id'] = 'invalid'
  38 + data.delete('key')
  39 + post :create, data
  40 + expect(response.status).to eq(422)
  41 + expect(response.body).to eq('Your API key is unknown')
  42 + end
  43 +
  44 + it 'ignores notices for older api' do
  45 + upgraded_app = Fabricate(:app, current_app_version: '2.0')
  46 + json = Rails.root.join('spec', 'fixtures', 'api_v3_request.json').read
  47 + data = JSON.parse(json)
  48 + data['project_id'] = upgraded_app.api_key
  49 + data['key'] = upgraded_app.api_key
  50 + post :create, data
  51 + expect(response.body).to eq('Notice for old app version ignored')
  52 + expect(Notice.count).to eq(0)
  53 + end
  54 +end
0 \ No newline at end of file 55 \ No newline at end of file
spec/fixtures/api_v3_request.json 0 → 100644
@@ -0,0 +1,38 @@ @@ -0,0 +1,38 @@
  1 +{
  2 + "notifier":{"name":"airbrake-js-v8","version":"0.3.10","url":"https://github.com/airbrake/airbrake-js"},
  3 + "errors":[
  4 + {
  5 + "type":"Error",
  6 + "message":"Error: TestError",
  7 + "backtrace":[
  8 + {"function":"d","file":"http://localhost:3000/assets/application.js","line":11234,"column":24},
  9 + {"function":"c","file":"http://localhost:3000/assets/application.js","line":11233,"column":18},
  10 + {"function":"b","file":"http://localhost:3000/assets/application.js","line":11232,"column":18},
  11 + {"function":"a","file":"http://localhost:3000/assets/application.js","line":11231,"column":18},
  12 + {"function":"HTMLDocument.<anonymous>","file":"http://localhost:3000/assets/application.js","line":11236,"column":3},
  13 + {"function":"fire","file":"http://localhost:3000/assets/application.js","line":1018,"column":34},
  14 + {"function":"Object.self.fireWith [as resolveWith]","file":"http://localhost:3000/assets/application.js","line":1128,"column":13},
  15 + {"function":"Function.jQuery.extend.ready","file":"http://localhost:3000/assets/application.js","line":417,"column":15},
  16 + {"function":"HTMLDocument.DOMContentLoaded","file":"http://localhost:3000/assets/application.js","line":93,"column":14}
  17 + ]
  18 + }
  19 + ],
  20 + "context":{
  21 + "language":"JavaScript",
  22 + "sourceMapEnabled":true,
  23 + "userAgent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.99 Safari/537.36",
  24 + "url":"http://localhost:3000/kontakt",
  25 + "userId":1,"userUsername":"john",
  26 + "userName":"John Doe",
  27 + "userUsername": "john",
  28 + "userEmail":"john.doe@example.org",
  29 + "version":"1.0",
  30 + "component":"ContactsController",
  31 + "action":"show"
  32 + },
  33 + "params":{"returnTo":"dashboard"},
  34 + "environment":{"navigator_vendor":"Google Inc."},
  35 + "session":{"isAdmin":true},
  36 + "key":"a3969bfbf65f073921e",
  37 + "project_id":"a3969bfbf65f073921e"
  38 +}
0 \ No newline at end of file 39 \ No newline at end of file
spec/lib/airbrake_api/v3/notice_parser_spec.rb
@@ -4,15 +4,15 @@ describe AirbrakeApi::V3::NoticeParser do @@ -4,15 +4,15 @@ describe AirbrakeApi::V3::NoticeParser do
4 it 'raises error when errors attribute is missing' do 4 it 'raises error when errors attribute is missing' do
5 expect { 5 expect {
6 AirbrakeApi::V3::NoticeParser.new({}).report 6 AirbrakeApi::V3::NoticeParser.new({}).report
7 - }.to raise_error(AirbrakeApi::V3::NoticeParser::ParamsError) 7 + }.to raise_error(AirbrakeApi::ParamsError)
8 8
9 expect { 9 expect {
10 AirbrakeApi::V3::NoticeParser.new({'errors' => []}).report 10 AirbrakeApi::V3::NoticeParser.new({'errors' => []}).report
11 - }.to raise_error(AirbrakeApi::V3::NoticeParser::ParamsError) 11 + }.to raise_error(AirbrakeApi::ParamsError)
12 end 12 end
13 13
14 it 'parses JSON payload and returns ErrorReport' do 14 it 'parses JSON payload and returns ErrorReport' do
15 - params = build_params(api_key: app.api_key) 15 + params = build_params(key: app.api_key)
16 16
17 report = AirbrakeApi::V3::NoticeParser.new(params).report 17 report = AirbrakeApi::V3::NoticeParser.new(params).report
18 notice = report.generate_notice! 18 notice = report.generate_notice!
@@ -30,52 +30,19 @@ describe AirbrakeApi::V3::NoticeParser do @@ -30,52 +30,19 @@ describe AirbrakeApi::V3::NoticeParser do
30 end 30 end
31 31
32 it 'parses JSON payload when api_key is missing but project_id is present' do 32 it 'parses JSON payload when api_key is missing but project_id is present' do
33 - params = build_params(api_key: nil, project_id: app.api_key) 33 + params = build_params(key: nil, project_id: app.api_key)
34 34
35 report = AirbrakeApi::V3::NoticeParser.new(params).report 35 report = AirbrakeApi::V3::NoticeParser.new(params).report
36 expect(report).to be_valid 36 expect(report).to be_valid
37 end 37 end
38 38
39 def build_params(options = {}) 39 def build_params(options = {})
40 - JSON.parse(<<-EOL)  
41 - {  
42 - "notifier":{"name":"airbrake-js-v8","version":"0.3.10","url":"https://github.com/airbrake/airbrake-js"},  
43 - "errors":[  
44 - {  
45 - "type":"Error",  
46 - "message":"Error: TestError",  
47 - "backtrace":[  
48 - {"function":"d","file":"http://localhost:3000/assets/application.js","line":11234,"column":24},  
49 - {"function":"c","file":"http://localhost:3000/assets/application.js","line":11233,"column":18},  
50 - {"function":"b","file":"http://localhost:3000/assets/application.js","line":11232,"column":18},  
51 - {"function":"a","file":"http://localhost:3000/assets/application.js","line":11231,"column":18},  
52 - {"function":"HTMLDocument.<anonymous>","file":"http://localhost:3000/assets/application.js","line":11236,"column":3},  
53 - {"function":"fire","file":"http://localhost:3000/assets/application.js","line":1018,"column":34},  
54 - {"function":"Object.self.fireWith [as resolveWith]","file":"http://localhost:3000/assets/application.js","line":1128,"column":13},  
55 - {"function":"Function.jQuery.extend.ready","file":"http://localhost:3000/assets/application.js","line":417,"column":15},  
56 - {"function":"HTMLDocument.DOMContentLoaded","file":"http://localhost:3000/assets/application.js","line":93,"column":14}  
57 - ]  
58 - }  
59 - ],  
60 - "context":{  
61 - "language":"JavaScript",  
62 - "sourceMapEnabled":true,  
63 - "userAgent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.99 Safari/537.36",  
64 - "url":"http://localhost:3000/kontakt",  
65 - "userId":1,"userUsername":"john",  
66 - "userName":"John Doe",  
67 - "userUsername": "john",  
68 - "userEmail":"john.doe@example.org",  
69 - "version":"1.0",  
70 - "component":"ContactsController",  
71 - "action":"show"  
72 - },  
73 - "params":{"returnTo":"dashboard"},  
74 - "environment":{"navigator_vendor":"Google Inc."},  
75 - "session":{"isAdmin":true},  
76 - "key":"#{options[:api_key]}",  
77 - "project_id":"#{options[:project_id]}"  
78 - }  
79 - EOL 40 + json = Rails.root.join('spec', 'fixtures', 'api_v3_request.json').read
  41 + data = JSON.parse(json)
  42 +
  43 + data['key'] = options[:key] if options.has_key?(:key)
  44 + data['project_id'] = options[:project_id] if options.has_key?(:project_id)
  45 +
  46 + data
80 end 47 end
81 end 48 end
82 \ No newline at end of file 49 \ No newline at end of file