Commit 4eed9f659ac29a043be191286cb7f3c1e34ca779
1 parent
0945dadc
Exists in
master
and in
1 other branch
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
Showing
6 changed files
with
108 additions
and
49 deletions
Show diff stats
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 |
| @@ -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 |
| @@ -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 |