terrific 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (56) hide show
  1. checksums.yaml +7 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README.md +36 -0
  4. data/Rakefile +23 -0
  5. data/lib/terrific.rb +5 -0
  6. data/lib/terrific/error.rb +42 -0
  7. data/lib/terrific/locales.rb +1 -0
  8. data/lib/terrific/locales/en.yml +10 -0
  9. data/lib/terrific/mappable.rb +29 -0
  10. data/lib/terrific/version.rb +3 -0
  11. data/spec/dummy/README.rdoc +28 -0
  12. data/spec/dummy/Rakefile +6 -0
  13. data/spec/dummy/app/assets/javascripts/application.js +13 -0
  14. data/spec/dummy/app/assets/stylesheets/application.css +15 -0
  15. data/spec/dummy/app/controllers/application_controller.rb +5 -0
  16. data/spec/dummy/app/helpers/application_helper.rb +2 -0
  17. data/spec/dummy/app/models/user.rb +3 -0
  18. data/spec/dummy/app/views/layouts/application.html.erb +14 -0
  19. data/spec/dummy/bin/bundle +3 -0
  20. data/spec/dummy/bin/rails +4 -0
  21. data/spec/dummy/bin/rake +4 -0
  22. data/spec/dummy/bin/setup +29 -0
  23. data/spec/dummy/config.ru +4 -0
  24. data/spec/dummy/config/application.rb +32 -0
  25. data/spec/dummy/config/boot.rb +5 -0
  26. data/spec/dummy/config/database.yml +25 -0
  27. data/spec/dummy/config/environment.rb +5 -0
  28. data/spec/dummy/config/environments/development.rb +41 -0
  29. data/spec/dummy/config/environments/production.rb +79 -0
  30. data/spec/dummy/config/environments/test.rb +42 -0
  31. data/spec/dummy/config/initializers/assets.rb +11 -0
  32. data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
  33. data/spec/dummy/config/initializers/cookies_serializer.rb +3 -0
  34. data/spec/dummy/config/initializers/filter_parameter_logging.rb +4 -0
  35. data/spec/dummy/config/initializers/inflections.rb +16 -0
  36. data/spec/dummy/config/initializers/mime_types.rb +4 -0
  37. data/spec/dummy/config/initializers/session_store.rb +3 -0
  38. data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
  39. data/spec/dummy/config/locales/en.yml +27 -0
  40. data/spec/dummy/config/routes.rb +56 -0
  41. data/spec/dummy/config/secrets.yml +22 -0
  42. data/spec/dummy/db/development.sqlite3 +0 -0
  43. data/spec/dummy/db/migrate/20150216205144_create_users.rb +9 -0
  44. data/spec/dummy/db/schema.rb +22 -0
  45. data/spec/dummy/db/test.sqlite3 +0 -0
  46. data/spec/dummy/log/development.log +32 -0
  47. data/spec/dummy/log/test.log +1796 -0
  48. data/spec/dummy/public/404.html +67 -0
  49. data/spec/dummy/public/422.html +67 -0
  50. data/spec/dummy/public/500.html +66 -0
  51. data/spec/dummy/public/favicon.ico +0 -0
  52. data/spec/requests/errors_spec.rb +81 -0
  53. data/spec/spec_helper.rb +17 -0
  54. data/spec/support/request_helper.rb +27 -0
  55. data/spec/terrific/error_spec.rb +85 -0
  56. metadata +185 -0
@@ -0,0 +1,67 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>The page you were looking for doesn't exist (404)</title>
5
+ <meta name="viewport" content="width=device-width,initial-scale=1">
6
+ <style>
7
+ body {
8
+ background-color: #EFEFEF;
9
+ color: #2E2F30;
10
+ text-align: center;
11
+ font-family: arial, sans-serif;
12
+ margin: 0;
13
+ }
14
+
15
+ div.dialog {
16
+ width: 95%;
17
+ max-width: 33em;
18
+ margin: 4em auto 0;
19
+ }
20
+
21
+ div.dialog > div {
22
+ border: 1px solid #CCC;
23
+ border-right-color: #999;
24
+ border-left-color: #999;
25
+ border-bottom-color: #BBB;
26
+ border-top: #B00100 solid 4px;
27
+ border-top-left-radius: 9px;
28
+ border-top-right-radius: 9px;
29
+ background-color: white;
30
+ padding: 7px 12% 0;
31
+ box-shadow: 0 3px 8px rgba(50, 50, 50, 0.17);
32
+ }
33
+
34
+ h1 {
35
+ font-size: 100%;
36
+ color: #730E15;
37
+ line-height: 1.5em;
38
+ }
39
+
40
+ div.dialog > p {
41
+ margin: 0 0 1em;
42
+ padding: 1em;
43
+ background-color: #F7F7F7;
44
+ border: 1px solid #CCC;
45
+ border-right-color: #999;
46
+ border-left-color: #999;
47
+ border-bottom-color: #999;
48
+ border-bottom-left-radius: 4px;
49
+ border-bottom-right-radius: 4px;
50
+ border-top-color: #DADADA;
51
+ color: #666;
52
+ box-shadow: 0 3px 8px rgba(50, 50, 50, 0.17);
53
+ }
54
+ </style>
55
+ </head>
56
+
57
+ <body>
58
+ <!-- This file lives in public/404.html -->
59
+ <div class="dialog">
60
+ <div>
61
+ <h1>The page you were looking for doesn't exist.</h1>
62
+ <p>You may have mistyped the address or the page may have moved.</p>
63
+ </div>
64
+ <p>If you are the application owner check the logs for more information.</p>
65
+ </div>
66
+ </body>
67
+ </html>
@@ -0,0 +1,67 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>The change you wanted was rejected (422)</title>
5
+ <meta name="viewport" content="width=device-width,initial-scale=1">
6
+ <style>
7
+ body {
8
+ background-color: #EFEFEF;
9
+ color: #2E2F30;
10
+ text-align: center;
11
+ font-family: arial, sans-serif;
12
+ margin: 0;
13
+ }
14
+
15
+ div.dialog {
16
+ width: 95%;
17
+ max-width: 33em;
18
+ margin: 4em auto 0;
19
+ }
20
+
21
+ div.dialog > div {
22
+ border: 1px solid #CCC;
23
+ border-right-color: #999;
24
+ border-left-color: #999;
25
+ border-bottom-color: #BBB;
26
+ border-top: #B00100 solid 4px;
27
+ border-top-left-radius: 9px;
28
+ border-top-right-radius: 9px;
29
+ background-color: white;
30
+ padding: 7px 12% 0;
31
+ box-shadow: 0 3px 8px rgba(50, 50, 50, 0.17);
32
+ }
33
+
34
+ h1 {
35
+ font-size: 100%;
36
+ color: #730E15;
37
+ line-height: 1.5em;
38
+ }
39
+
40
+ div.dialog > p {
41
+ margin: 0 0 1em;
42
+ padding: 1em;
43
+ background-color: #F7F7F7;
44
+ border: 1px solid #CCC;
45
+ border-right-color: #999;
46
+ border-left-color: #999;
47
+ border-bottom-color: #999;
48
+ border-bottom-left-radius: 4px;
49
+ border-bottom-right-radius: 4px;
50
+ border-top-color: #DADADA;
51
+ color: #666;
52
+ box-shadow: 0 3px 8px rgba(50, 50, 50, 0.17);
53
+ }
54
+ </style>
55
+ </head>
56
+
57
+ <body>
58
+ <!-- This file lives in public/422.html -->
59
+ <div class="dialog">
60
+ <div>
61
+ <h1>The change you wanted was rejected.</h1>
62
+ <p>Maybe you tried to change something you didn't have access to.</p>
63
+ </div>
64
+ <p>If you are the application owner check the logs for more information.</p>
65
+ </div>
66
+ </body>
67
+ </html>
@@ -0,0 +1,66 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>We're sorry, but something went wrong (500)</title>
5
+ <meta name="viewport" content="width=device-width,initial-scale=1">
6
+ <style>
7
+ body {
8
+ background-color: #EFEFEF;
9
+ color: #2E2F30;
10
+ text-align: center;
11
+ font-family: arial, sans-serif;
12
+ margin: 0;
13
+ }
14
+
15
+ div.dialog {
16
+ width: 95%;
17
+ max-width: 33em;
18
+ margin: 4em auto 0;
19
+ }
20
+
21
+ div.dialog > div {
22
+ border: 1px solid #CCC;
23
+ border-right-color: #999;
24
+ border-left-color: #999;
25
+ border-bottom-color: #BBB;
26
+ border-top: #B00100 solid 4px;
27
+ border-top-left-radius: 9px;
28
+ border-top-right-radius: 9px;
29
+ background-color: white;
30
+ padding: 7px 12% 0;
31
+ box-shadow: 0 3px 8px rgba(50, 50, 50, 0.17);
32
+ }
33
+
34
+ h1 {
35
+ font-size: 100%;
36
+ color: #730E15;
37
+ line-height: 1.5em;
38
+ }
39
+
40
+ div.dialog > p {
41
+ margin: 0 0 1em;
42
+ padding: 1em;
43
+ background-color: #F7F7F7;
44
+ border: 1px solid #CCC;
45
+ border-right-color: #999;
46
+ border-left-color: #999;
47
+ border-bottom-color: #999;
48
+ border-bottom-left-radius: 4px;
49
+ border-bottom-right-radius: 4px;
50
+ border-top-color: #DADADA;
51
+ color: #666;
52
+ box-shadow: 0 3px 8px rgba(50, 50, 50, 0.17);
53
+ }
54
+ </style>
55
+ </head>
56
+
57
+ <body>
58
+ <!-- This file lives in public/500.html -->
59
+ <div class="dialog">
60
+ <div>
61
+ <h1>We're sorry, but something went wrong.</h1>
62
+ </div>
63
+ <p>If you are the application owner check the logs for more information.</p>
64
+ </div>
65
+ </body>
66
+ </html>
File without changes
@@ -0,0 +1,81 @@
1
+ require "spec_helper"
2
+
3
+ Unrecognized = Class.new(StandardError)
4
+ Parent = Class.new(StandardError)
5
+ Child = Class.new(Parent)
6
+
7
+ class TestController < ApplicationController
8
+ map_error Child, to: :unprocessable_entity, type: :first, message: "first"
9
+ map_error Parent, to: :unprocessable_entity, type: :second, message: "second"
10
+
11
+ def unrecognized_exception
12
+ raise Unrecognized
13
+ end
14
+
15
+ def record_not_found
16
+ raise ActiveRecord::RecordNotFound
17
+ end
18
+
19
+ def record_invalid
20
+ User.create!
21
+ end
22
+
23
+ def overridden
24
+ raise Child
25
+ end
26
+ end
27
+
28
+ describe "Errors" do
29
+ before do
30
+ Rails.application.routes.draw do
31
+ get "/unrecognized_exception" => "test#unrecognized_exception"
32
+ get "/record_not_found" => "test#record_not_found"
33
+ get "/record_invalid" => "test#record_invalid"
34
+ get "/overridden" => "test#overridden"
35
+ end
36
+ end
37
+
38
+ after do
39
+ Rails.application.reload_routes!
40
+ end
41
+
42
+ context "when there is an unrecognized exception" do
43
+ it "responds with a server_error" do
44
+ j_get("/unrecognized_exception")
45
+
46
+ expect_status(500)
47
+ expect_type("server_error")
48
+ expect_message("Something went wrong")
49
+ end
50
+ end
51
+
52
+ context "when a record is not found" do
53
+ it "responds with a record_not_found" do
54
+ j_get("/record_not_found")
55
+
56
+ expect_status(404)
57
+ expect_type("record_not_found")
58
+ expect_message("No such record")
59
+ end
60
+ end
61
+
62
+ context "when an attribute is not valid" do
63
+ it "responds with a record_invalid" do
64
+ j_get("/record_invalid")
65
+
66
+ expect_status(422)
67
+ expect_type("record_invalid")
68
+ expect_message("Name can't be blank")
69
+ end
70
+ end
71
+
72
+ context "when an error is mapped twice" do
73
+ it "responds with the last mapping" do
74
+ j_get("/overridden")
75
+
76
+ expect_status(422)
77
+ expect_type("second")
78
+ expect_message("second")
79
+ end
80
+ end
81
+ end
@@ -0,0 +1,17 @@
1
+ ENV["RAILS_ENV"] ||= "test"
2
+
3
+ require File.expand_path("../dummy/config/environment.rb", __FILE__)
4
+
5
+ require "rspec/rails"
6
+
7
+ Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each { |f| require f }
8
+
9
+ RSpec.configure do |config|
10
+ config.include RequestHelper, type: :request
11
+
12
+ config.infer_spec_type_from_file_location!
13
+ config.mock_with :rspec
14
+ config.use_transactional_fixtures = true
15
+ config.infer_base_class_for_anonymous_controllers = false
16
+ config.order = :random
17
+ end
@@ -0,0 +1,27 @@
1
+ module RequestHelper
2
+ def json
3
+ @json ||= JSON.parse(response.body, symbolize_names: true)
4
+ end
5
+
6
+ def expect_status(status)
7
+ expect(response.status).to eq(status)
8
+ end
9
+
10
+ def expect_type(type)
11
+ expect(json[:error][:type]).to eq(type)
12
+ end
13
+
14
+ def expect_message(message)
15
+ expect(json[:error][:message]).to eq(message)
16
+ end
17
+
18
+ def j_get(path, params = nil, headers = {})
19
+ json_request(:get, path, params, headers)
20
+ end
21
+
22
+ def json_request(method, path, params = nil, headers = {})
23
+ send(method, path, params, headers.merge({
24
+ "CONTENT_TYPE" => "application/json"
25
+ }))
26
+ end
27
+ end
@@ -0,0 +1,85 @@
1
+ require 'spec_helper'
2
+
3
+ describe Terrific::Error do
4
+ let(:exception) { Exception.new }
5
+
6
+ describe "#as_json" do
7
+ let(:error) { Terrific::Error.new(exception) }
8
+
9
+ before do
10
+ expect(error).to receive(:message) { "message" }
11
+ expect(error).to receive(:type) { "type" }
12
+ end
13
+
14
+ it "returns message and type" do
15
+ expect(error.as_json).to eq({
16
+ type: "type",
17
+ message: "message"
18
+ })
19
+ end
20
+ end
21
+
22
+ describe "#message" do
23
+ context "when it is explictly provided" do
24
+ let(:error) { Terrific::Error.new(exception, message: "explicit message") }
25
+
26
+ it "is the value specified" do
27
+ expect(error.message).to eq("explicit message")
28
+ end
29
+ end
30
+
31
+ context "when it is provided as lambda" do
32
+ let(:lambda) { ->(e) { "lambda message" } }
33
+ let(:error) { Terrific::Error.new(exception, message: lambda) }
34
+
35
+ it "is the result of the lambda" do
36
+ expect(error.message).to eq("lambda message")
37
+ end
38
+ end
39
+
40
+ context "when it is not provided" do
41
+ context "but a translation is available" do
42
+ let(:error) { Terrific::Error.new(Exception.new("message")) }
43
+
44
+ it "is the translated message" do
45
+ expect(error.message).to eq("translated message")
46
+ end
47
+ end
48
+
49
+ context "and there is no translation available" do
50
+ let(:error) { Terrific::Error.new(StandardError.new("message")) }
51
+
52
+ it "is the exception message" do
53
+ expect(error.message).to eq("message")
54
+ end
55
+ end
56
+ end
57
+ end
58
+
59
+ describe "#type" do
60
+ context "when it is explictly provided" do
61
+ let(:error) { Terrific::Error.new(exception, type: "explicit") }
62
+
63
+ it "is the value specified" do
64
+ expect(error.type).to eq("explicit")
65
+ end
66
+ end
67
+
68
+ context "when it is provided as lambda" do
69
+ let(:lambda) { ->(e) { "lambda" } }
70
+ let(:error) { Terrific::Error.new(exception, type: lambda) }
71
+
72
+ it "is the result of the lambda" do
73
+ expect(error.type).to eq("lambda")
74
+ end
75
+ end
76
+
77
+ context "when it is not provided" do
78
+ let(:error) { Terrific::Error.new(exception) }
79
+
80
+ it "is uses the default" do
81
+ expect(error.type).to eq("exception")
82
+ end
83
+ end
84
+ end
85
+ end
metadata ADDED
@@ -0,0 +1,185 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: terrific
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Jason Kriss
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-02-16 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rails
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: 4.2.0
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: 4.2.0
27
+ - !ruby/object:Gem::Dependency
28
+ name: sqlite3
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rspec-rails
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ description:
56
+ email:
57
+ - jasonkriss@gmail.com
58
+ executables: []
59
+ extensions: []
60
+ extra_rdoc_files: []
61
+ files:
62
+ - MIT-LICENSE
63
+ - README.md
64
+ - Rakefile
65
+ - lib/terrific.rb
66
+ - lib/terrific/error.rb
67
+ - lib/terrific/locales.rb
68
+ - lib/terrific/locales/en.yml
69
+ - lib/terrific/mappable.rb
70
+ - lib/terrific/version.rb
71
+ - spec/dummy/README.rdoc
72
+ - spec/dummy/Rakefile
73
+ - spec/dummy/app/assets/javascripts/application.js
74
+ - spec/dummy/app/assets/stylesheets/application.css
75
+ - spec/dummy/app/controllers/application_controller.rb
76
+ - spec/dummy/app/helpers/application_helper.rb
77
+ - spec/dummy/app/models/user.rb
78
+ - spec/dummy/app/views/layouts/application.html.erb
79
+ - spec/dummy/bin/bundle
80
+ - spec/dummy/bin/rails
81
+ - spec/dummy/bin/rake
82
+ - spec/dummy/bin/setup
83
+ - spec/dummy/config.ru
84
+ - spec/dummy/config/application.rb
85
+ - spec/dummy/config/boot.rb
86
+ - spec/dummy/config/database.yml
87
+ - spec/dummy/config/environment.rb
88
+ - spec/dummy/config/environments/development.rb
89
+ - spec/dummy/config/environments/production.rb
90
+ - spec/dummy/config/environments/test.rb
91
+ - spec/dummy/config/initializers/assets.rb
92
+ - spec/dummy/config/initializers/backtrace_silencers.rb
93
+ - spec/dummy/config/initializers/cookies_serializer.rb
94
+ - spec/dummy/config/initializers/filter_parameter_logging.rb
95
+ - spec/dummy/config/initializers/inflections.rb
96
+ - spec/dummy/config/initializers/mime_types.rb
97
+ - spec/dummy/config/initializers/session_store.rb
98
+ - spec/dummy/config/initializers/wrap_parameters.rb
99
+ - spec/dummy/config/locales/en.yml
100
+ - spec/dummy/config/routes.rb
101
+ - spec/dummy/config/secrets.yml
102
+ - spec/dummy/db/development.sqlite3
103
+ - spec/dummy/db/migrate/20150216205144_create_users.rb
104
+ - spec/dummy/db/schema.rb
105
+ - spec/dummy/db/test.sqlite3
106
+ - spec/dummy/log/development.log
107
+ - spec/dummy/log/test.log
108
+ - spec/dummy/public/404.html
109
+ - spec/dummy/public/422.html
110
+ - spec/dummy/public/500.html
111
+ - spec/dummy/public/favicon.ico
112
+ - spec/requests/errors_spec.rb
113
+ - spec/spec_helper.rb
114
+ - spec/support/request_helper.rb
115
+ - spec/terrific/error_spec.rb
116
+ homepage: https://github.com/jasonkriss/terrific
117
+ licenses:
118
+ - MIT
119
+ metadata: {}
120
+ post_install_message:
121
+ rdoc_options: []
122
+ require_paths:
123
+ - lib
124
+ required_ruby_version: !ruby/object:Gem::Requirement
125
+ requirements:
126
+ - - ">="
127
+ - !ruby/object:Gem::Version
128
+ version: '0'
129
+ required_rubygems_version: !ruby/object:Gem::Requirement
130
+ requirements:
131
+ - - ">="
132
+ - !ruby/object:Gem::Version
133
+ version: '0'
134
+ requirements: []
135
+ rubyforge_project:
136
+ rubygems_version: 2.4.3
137
+ signing_key:
138
+ specification_version: 4
139
+ summary: Exception handling for your Rails API.
140
+ test_files:
141
+ - spec/dummy/app/assets/javascripts/application.js
142
+ - spec/dummy/app/assets/stylesheets/application.css
143
+ - spec/dummy/app/controllers/application_controller.rb
144
+ - spec/dummy/app/helpers/application_helper.rb
145
+ - spec/dummy/app/models/user.rb
146
+ - spec/dummy/app/views/layouts/application.html.erb
147
+ - spec/dummy/bin/bundle
148
+ - spec/dummy/bin/rails
149
+ - spec/dummy/bin/rake
150
+ - spec/dummy/bin/setup
151
+ - spec/dummy/config/application.rb
152
+ - spec/dummy/config/boot.rb
153
+ - spec/dummy/config/database.yml
154
+ - spec/dummy/config/environment.rb
155
+ - spec/dummy/config/environments/development.rb
156
+ - spec/dummy/config/environments/production.rb
157
+ - spec/dummy/config/environments/test.rb
158
+ - spec/dummy/config/initializers/assets.rb
159
+ - spec/dummy/config/initializers/backtrace_silencers.rb
160
+ - spec/dummy/config/initializers/cookies_serializer.rb
161
+ - spec/dummy/config/initializers/filter_parameter_logging.rb
162
+ - spec/dummy/config/initializers/inflections.rb
163
+ - spec/dummy/config/initializers/mime_types.rb
164
+ - spec/dummy/config/initializers/session_store.rb
165
+ - spec/dummy/config/initializers/wrap_parameters.rb
166
+ - spec/dummy/config/locales/en.yml
167
+ - spec/dummy/config/routes.rb
168
+ - spec/dummy/config/secrets.yml
169
+ - spec/dummy/config.ru
170
+ - spec/dummy/db/development.sqlite3
171
+ - spec/dummy/db/migrate/20150216205144_create_users.rb
172
+ - spec/dummy/db/schema.rb
173
+ - spec/dummy/db/test.sqlite3
174
+ - spec/dummy/log/development.log
175
+ - spec/dummy/log/test.log
176
+ - spec/dummy/public/404.html
177
+ - spec/dummy/public/422.html
178
+ - spec/dummy/public/500.html
179
+ - spec/dummy/public/favicon.ico
180
+ - spec/dummy/Rakefile
181
+ - spec/dummy/README.rdoc
182
+ - spec/requests/errors_spec.rb
183
+ - spec/spec_helper.rb
184
+ - spec/support/request_helper.rb
185
+ - spec/terrific/error_spec.rb