qalam_oauth_engine 2.2.9

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 (60) hide show
  1. checksums.yaml +7 -0
  2. data/MIT-LICENSE +28 -0
  3. data/README.md +110 -0
  4. data/Rakefile +28 -0
  5. data/app/controllers/canvas_oauth/canvas_controller.rb +26 -0
  6. data/app/controllers/canvas_oauth/oauth_application_controller.rb +5 -0
  7. data/app/models/canvas_oauth/authorization.rb +46 -0
  8. data/config/canvas.yml.example +12 -0
  9. data/config/routes.rb +3 -0
  10. data/db/migrate/20121121005358_create_canvas_oauth_authorizations.rb +16 -0
  11. data/lib/canvas_oauth.rb +26 -0
  12. data/lib/canvas_oauth/canvas_api.rb +331 -0
  13. data/lib/canvas_oauth/canvas_api_extensions.rb +9 -0
  14. data/lib/canvas_oauth/canvas_application.rb +73 -0
  15. data/lib/canvas_oauth/canvas_config.rb +34 -0
  16. data/lib/canvas_oauth/config.rb +3 -0
  17. data/lib/canvas_oauth/default_utf8_parser.rb +13 -0
  18. data/lib/canvas_oauth/engine.rb +15 -0
  19. data/lib/canvas_oauth/version.rb +3 -0
  20. data/lib/tasks/canvas_oauth_tasks.rake +1 -0
  21. data/spec/controllers/canvas_oauth/canvas_controller_spec.rb +90 -0
  22. data/spec/dummy/README.rdoc +261 -0
  23. data/spec/dummy/Rakefile +7 -0
  24. data/spec/dummy/app/controllers/application_controller.rb +5 -0
  25. data/spec/dummy/app/controllers/welcome_controller.rb +5 -0
  26. data/spec/dummy/config.ru +4 -0
  27. data/spec/dummy/config/application.rb +57 -0
  28. data/spec/dummy/config/boot.rb +10 -0
  29. data/spec/dummy/config/canvas.yml +12 -0
  30. data/spec/dummy/config/database.yml +25 -0
  31. data/spec/dummy/config/environment.rb +5 -0
  32. data/spec/dummy/config/environments/development.rb +26 -0
  33. data/spec/dummy/config/environments/production.rb +69 -0
  34. data/spec/dummy/config/environments/test.rb +33 -0
  35. data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
  36. data/spec/dummy/config/initializers/inflections.rb +15 -0
  37. data/spec/dummy/config/initializers/mime_types.rb +5 -0
  38. data/spec/dummy/config/initializers/secret_token.rb +7 -0
  39. data/spec/dummy/config/initializers/session_store.rb +8 -0
  40. data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
  41. data/spec/dummy/config/locales/en.yml +5 -0
  42. data/spec/dummy/config/routes.rb +4 -0
  43. data/spec/dummy/db/development.sqlite3 +0 -0
  44. data/spec/dummy/db/migrate/20160711200737_create_canvas_oauth_authorizations.canvas_oauth.rb +16 -0
  45. data/spec/dummy/db/schema.rb +27 -0
  46. data/spec/dummy/db/test.sqlite3 +0 -0
  47. data/spec/dummy/log/development.log +1 -0
  48. data/spec/dummy/log/test.log +1630 -0
  49. data/spec/dummy/public/404.html +26 -0
  50. data/spec/dummy/public/422.html +26 -0
  51. data/spec/dummy/public/500.html +25 -0
  52. data/spec/dummy/public/favicon.ico +0 -0
  53. data/spec/dummy/public/robots.txt +5 -0
  54. data/spec/dummy/script/rails +6 -0
  55. data/spec/lib/canvas_oauth/canvas_api_extensions_spec.rb +13 -0
  56. data/spec/lib/canvas_oauth/canvas_api_spec.rb +364 -0
  57. data/spec/lib/canvas_oauth/default_utf8_parser_spec.rb +21 -0
  58. data/spec/models/canvas_oauth/authorization_spec.rb +47 -0
  59. data/spec/spec_helper.rb +64 -0
  60. metadata +377 -0
@@ -0,0 +1,21 @@
1
+ require 'spec_helper'
2
+
3
+ describe CanvasOauth::DefaultUTF8Parser do
4
+ describe "#parse" do
5
+ it "forces the body passed in to UTF-8 if it is ASCII_8BIT" do
6
+ body = String.new("I am some text", encoding: Encoding::ASCII_8BIT)
7
+
8
+ parser = CanvasOauth::DefaultUTF8Parser.new(body, "text/plain")
9
+ expect(body).to receive(:force_encoding).with("UTF-8")
10
+ parser.parse
11
+ end
12
+
13
+ it "does not force the body passed in to UTF-8 if not ASCII_8BIT" do
14
+ body = String.new("I am some text", encoding: Encoding::US_ASCII)
15
+
16
+ parser = CanvasOauth::DefaultUTF8Parser.new(body, "text/plain")
17
+ expect(body).not_to receive(:force_encoding)
18
+ parser.parse
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,47 @@
1
+ require 'spec_helper'
2
+
3
+ describe CanvasOauth::Authorization do
4
+ it { is_expected.to validate_presence_of :canvas_user_id }
5
+ it { is_expected.to validate_presence_of :token }
6
+ it { is_expected.to validate_presence_of :last_used_at }
7
+
8
+ describe "cache_token" do
9
+ subject { CanvasOauth::Authorization.first }
10
+
11
+ before do
12
+ CanvasOauth::Authorization.cache_token('abc', 123, 'abc123')
13
+ end
14
+
15
+ its(:token) { is_expected.to eq 'abc' }
16
+ its(:canvas_user_id) { is_expected.to eq 123 }
17
+ its(:tool_consumer_instance_guid) { is_expected.to eq 'abc123' }
18
+ its(:last_used_at) { is_expected.to be_present }
19
+ end
20
+
21
+ describe "fetch_token" do
22
+ subject(:token) { CanvasOauth::Authorization.fetch_token(123, 'abc123') }
23
+
24
+ context "when a token exists" do
25
+ before do
26
+ CanvasOauth::Authorization.cache_token('abc', 123, 'abc123')
27
+ CanvasOauth::Authorization.cache_token('def', 123, 'abc123')
28
+ end
29
+
30
+ it "retrieves the latest one" do
31
+ expect(token).to eq 'def'
32
+ end
33
+ end
34
+
35
+ context "when a token exists with a tool_consumer_instance_guid" do
36
+ before do
37
+ CanvasOauth::Authorization.cache_token('abc', 123, 'wrong')
38
+ end
39
+
40
+ it { is_expected.to be_nil }
41
+ end
42
+
43
+ context "when no token exists" do
44
+ it { is_expected.to be_nil }
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,64 @@
1
+ # This file is copied to spec/ when you run 'rails generate rspec:install'
2
+ ENV["RAILS_ENV"] ||= 'test'
3
+ require File.expand_path("../dummy/config/environment", __FILE__)
4
+ require 'rspec/rails'
5
+ require 'rspec/its'
6
+ require 'webmock/rspec'
7
+ require 'shoulda/matchers'
8
+
9
+ # Requires supporting ruby files with custom matchers and macros, etc,
10
+ # in spec/support/ and its subdirectories.
11
+ Dir[Rails.root.join("spec/support/**/*.rb")].each {|f| require f}
12
+
13
+ module CanvasOauth
14
+ module UrlHelpers
15
+ def canvas_oauth
16
+ ::CanvasOauth::Engine.routes.url_helpers
17
+ end
18
+
19
+ def main_app
20
+ ::Dummy::Application.routes.url_helpers
21
+ end
22
+ end
23
+ end
24
+
25
+ Shoulda::Matchers.configure do |config|
26
+ config.integrate do |with|
27
+ with.test_framework :rspec
28
+ with.library :rails
29
+ end
30
+ end
31
+
32
+ RSpec.configure do |config|
33
+ # ## Mock Framework
34
+ #
35
+ # If you prefer to use mocha, flexmock or RR, uncomment the appropriate line:
36
+ #
37
+ # config.mock_with :mocha
38
+ # config.mock_with :flexmock
39
+ # config.mock_with :rr
40
+
41
+ # Remove this line if you're not using ActiveRecord or ActiveRecord fixtures
42
+ config.fixture_path = "#{::Rails.root}/spec/fixtures"
43
+
44
+ # If you're not using ActiveRecord, or you'd prefer not to run each of your
45
+ # examples within a transaction, remove the following line or assign false
46
+ # instead of true.
47
+ config.use_transactional_fixtures = true
48
+
49
+ # If true, the base class of anonymous controllers will be inferred
50
+ # automatically. This will be the default behavior in future versions of
51
+ # rspec-rails.
52
+ config.infer_base_class_for_anonymous_controllers = false
53
+
54
+ # Automatically infer an example group's spec type from the file location
55
+ config.infer_spec_type_from_file_location!
56
+
57
+ # Run specs in random order to surface order dependencies. If you find an
58
+ # order dependency and want to debug it, you can fix the order by providing
59
+ # the seed, which is printed after each run.
60
+ # --seed 1234
61
+ config.order = "random"
62
+
63
+ config.include CanvasOauth::UrlHelpers, type: :controller
64
+ end
metadata ADDED
@@ -0,0 +1,377 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: qalam_oauth_engine
3
+ version: !ruby/object:Gem::Version
4
+ version: 2.2.9
5
+ platform: ruby
6
+ authors:
7
+ - Dave Donahue
8
+ - Adam Anderson
9
+ - Simon Williams
10
+ - Ahmed Abdelhamid
11
+ autorequire:
12
+ bindir: bin
13
+ cert_chain: []
14
+ date: 2021-04-20 00:00:00.000000000 Z
15
+ dependencies:
16
+ - !ruby/object:Gem::Dependency
17
+ name: httparty
18
+ requirement: !ruby/object:Gem::Requirement
19
+ requirements:
20
+ - - ">="
21
+ - !ruby/object:Gem::Version
22
+ version: 0.17.0
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ requirements:
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ version: 0.17.0
30
+ - !ruby/object:Gem::Dependency
31
+ name: link_header
32
+ requirement: !ruby/object:Gem::Requirement
33
+ requirements:
34
+ - - '='
35
+ - !ruby/object:Gem::Version
36
+ version: 0.0.8
37
+ type: :runtime
38
+ prerelease: false
39
+ version_requirements: !ruby/object:Gem::Requirement
40
+ requirements:
41
+ - - '='
42
+ - !ruby/object:Gem::Version
43
+ version: 0.0.8
44
+ - !ruby/object:Gem::Dependency
45
+ name: rails
46
+ requirement: !ruby/object:Gem::Requirement
47
+ requirements:
48
+ - - ">="
49
+ - !ruby/object:Gem::Version
50
+ version: '4.2'
51
+ - - "<"
52
+ - !ruby/object:Gem::Version
53
+ version: '5.3'
54
+ type: :runtime
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - ">="
59
+ - !ruby/object:Gem::Version
60
+ version: '4.2'
61
+ - - "<"
62
+ - !ruby/object:Gem::Version
63
+ version: '5.3'
64
+ - !ruby/object:Gem::Dependency
65
+ name: byebug
66
+ requirement: !ruby/object:Gem::Requirement
67
+ requirements:
68
+ - - ">="
69
+ - !ruby/object:Gem::Version
70
+ version: '0'
71
+ type: :development
72
+ prerelease: false
73
+ version_requirements: !ruby/object:Gem::Requirement
74
+ requirements:
75
+ - - ">="
76
+ - !ruby/object:Gem::Version
77
+ version: '0'
78
+ - !ruby/object:Gem::Dependency
79
+ name: guard-rspec
80
+ requirement: !ruby/object:Gem::Requirement
81
+ requirements:
82
+ - - '='
83
+ - !ruby/object:Gem::Version
84
+ version: 4.6.4
85
+ type: :development
86
+ prerelease: false
87
+ version_requirements: !ruby/object:Gem::Requirement
88
+ requirements:
89
+ - - '='
90
+ - !ruby/object:Gem::Version
91
+ version: 4.6.4
92
+ - !ruby/object:Gem::Dependency
93
+ name: listen
94
+ requirement: !ruby/object:Gem::Requirement
95
+ requirements:
96
+ - - "~>"
97
+ - !ruby/object:Gem::Version
98
+ version: 3.0.6
99
+ type: :development
100
+ prerelease: false
101
+ version_requirements: !ruby/object:Gem::Requirement
102
+ requirements:
103
+ - - "~>"
104
+ - !ruby/object:Gem::Version
105
+ version: 3.0.6
106
+ - !ruby/object:Gem::Dependency
107
+ name: rb-fsevent
108
+ requirement: !ruby/object:Gem::Requirement
109
+ requirements:
110
+ - - ">="
111
+ - !ruby/object:Gem::Version
112
+ version: '0'
113
+ type: :development
114
+ prerelease: false
115
+ version_requirements: !ruby/object:Gem::Requirement
116
+ requirements:
117
+ - - ">="
118
+ - !ruby/object:Gem::Version
119
+ version: '0'
120
+ - !ruby/object:Gem::Dependency
121
+ name: rspec
122
+ requirement: !ruby/object:Gem::Requirement
123
+ requirements:
124
+ - - ">="
125
+ - !ruby/object:Gem::Version
126
+ version: '0'
127
+ type: :development
128
+ prerelease: false
129
+ version_requirements: !ruby/object:Gem::Requirement
130
+ requirements:
131
+ - - ">="
132
+ - !ruby/object:Gem::Version
133
+ version: '0'
134
+ - !ruby/object:Gem::Dependency
135
+ name: rspec-its
136
+ requirement: !ruby/object:Gem::Requirement
137
+ requirements:
138
+ - - ">="
139
+ - !ruby/object:Gem::Version
140
+ version: '0'
141
+ type: :development
142
+ prerelease: false
143
+ version_requirements: !ruby/object:Gem::Requirement
144
+ requirements:
145
+ - - ">="
146
+ - !ruby/object:Gem::Version
147
+ version: '0'
148
+ - !ruby/object:Gem::Dependency
149
+ name: rspec-rails
150
+ requirement: !ruby/object:Gem::Requirement
151
+ requirements:
152
+ - - ">="
153
+ - !ruby/object:Gem::Version
154
+ version: '0'
155
+ type: :development
156
+ prerelease: false
157
+ version_requirements: !ruby/object:Gem::Requirement
158
+ requirements:
159
+ - - ">="
160
+ - !ruby/object:Gem::Version
161
+ version: '0'
162
+ - !ruby/object:Gem::Dependency
163
+ name: rspec-rails-mocha
164
+ requirement: !ruby/object:Gem::Requirement
165
+ requirements:
166
+ - - ">="
167
+ - !ruby/object:Gem::Version
168
+ version: '0'
169
+ type: :development
170
+ prerelease: false
171
+ version_requirements: !ruby/object:Gem::Requirement
172
+ requirements:
173
+ - - ">="
174
+ - !ruby/object:Gem::Version
175
+ version: '0'
176
+ - !ruby/object:Gem::Dependency
177
+ name: shoulda-matchers
178
+ requirement: !ruby/object:Gem::Requirement
179
+ requirements:
180
+ - - "~>"
181
+ - !ruby/object:Gem::Version
182
+ version: 3.0.6
183
+ type: :development
184
+ prerelease: false
185
+ version_requirements: !ruby/object:Gem::Requirement
186
+ requirements:
187
+ - - "~>"
188
+ - !ruby/object:Gem::Version
189
+ version: 3.0.6
190
+ - !ruby/object:Gem::Dependency
191
+ name: sprockets
192
+ requirement: !ruby/object:Gem::Requirement
193
+ requirements:
194
+ - - "~>"
195
+ - !ruby/object:Gem::Version
196
+ version: '3.0'
197
+ type: :development
198
+ prerelease: false
199
+ version_requirements: !ruby/object:Gem::Requirement
200
+ requirements:
201
+ - - "~>"
202
+ - !ruby/object:Gem::Version
203
+ version: '3.0'
204
+ - !ruby/object:Gem::Dependency
205
+ name: sqlite3
206
+ requirement: !ruby/object:Gem::Requirement
207
+ requirements:
208
+ - - ">="
209
+ - !ruby/object:Gem::Version
210
+ version: '0'
211
+ type: :development
212
+ prerelease: false
213
+ version_requirements: !ruby/object:Gem::Requirement
214
+ requirements:
215
+ - - ">="
216
+ - !ruby/object:Gem::Version
217
+ version: '0'
218
+ - !ruby/object:Gem::Dependency
219
+ name: webmock
220
+ requirement: !ruby/object:Gem::Requirement
221
+ requirements:
222
+ - - ">="
223
+ - !ruby/object:Gem::Version
224
+ version: '0'
225
+ type: :development
226
+ prerelease: false
227
+ version_requirements: !ruby/object:Gem::Requirement
228
+ requirements:
229
+ - - ">="
230
+ - !ruby/object:Gem::Version
231
+ version: '0'
232
+ - !ruby/object:Gem::Dependency
233
+ name: colorize
234
+ requirement: !ruby/object:Gem::Requirement
235
+ requirements:
236
+ - - ">="
237
+ - !ruby/object:Gem::Version
238
+ version: '0'
239
+ type: :development
240
+ prerelease: false
241
+ version_requirements: !ruby/object:Gem::Requirement
242
+ requirements:
243
+ - - ">="
244
+ - !ruby/object:Gem::Version
245
+ version: '0'
246
+ description:
247
+ email:
248
+ - adam.anderson@12spokes.com
249
+ - simon@instructure.com
250
+ - a.hamid@nezam.io
251
+ executables: []
252
+ extensions: []
253
+ extra_rdoc_files: []
254
+ files:
255
+ - MIT-LICENSE
256
+ - README.md
257
+ - Rakefile
258
+ - app/controllers/canvas_oauth/canvas_controller.rb
259
+ - app/controllers/canvas_oauth/oauth_application_controller.rb
260
+ - app/models/canvas_oauth/authorization.rb
261
+ - config/canvas.yml.example
262
+ - config/routes.rb
263
+ - db/migrate/20121121005358_create_canvas_oauth_authorizations.rb
264
+ - lib/canvas_oauth.rb
265
+ - lib/canvas_oauth/canvas_api.rb
266
+ - lib/canvas_oauth/canvas_api_extensions.rb
267
+ - lib/canvas_oauth/canvas_application.rb
268
+ - lib/canvas_oauth/canvas_config.rb
269
+ - lib/canvas_oauth/config.rb
270
+ - lib/canvas_oauth/default_utf8_parser.rb
271
+ - lib/canvas_oauth/engine.rb
272
+ - lib/canvas_oauth/version.rb
273
+ - lib/tasks/canvas_oauth_tasks.rake
274
+ - spec/controllers/canvas_oauth/canvas_controller_spec.rb
275
+ - spec/dummy/README.rdoc
276
+ - spec/dummy/Rakefile
277
+ - spec/dummy/app/controllers/application_controller.rb
278
+ - spec/dummy/app/controllers/welcome_controller.rb
279
+ - spec/dummy/config.ru
280
+ - spec/dummy/config/application.rb
281
+ - spec/dummy/config/boot.rb
282
+ - spec/dummy/config/canvas.yml
283
+ - spec/dummy/config/database.yml
284
+ - spec/dummy/config/environment.rb
285
+ - spec/dummy/config/environments/development.rb
286
+ - spec/dummy/config/environments/production.rb
287
+ - spec/dummy/config/environments/test.rb
288
+ - spec/dummy/config/initializers/backtrace_silencers.rb
289
+ - spec/dummy/config/initializers/inflections.rb
290
+ - spec/dummy/config/initializers/mime_types.rb
291
+ - spec/dummy/config/initializers/secret_token.rb
292
+ - spec/dummy/config/initializers/session_store.rb
293
+ - spec/dummy/config/initializers/wrap_parameters.rb
294
+ - spec/dummy/config/locales/en.yml
295
+ - spec/dummy/config/routes.rb
296
+ - spec/dummy/db/development.sqlite3
297
+ - spec/dummy/db/migrate/20160711200737_create_canvas_oauth_authorizations.canvas_oauth.rb
298
+ - spec/dummy/db/schema.rb
299
+ - spec/dummy/db/test.sqlite3
300
+ - spec/dummy/log/development.log
301
+ - spec/dummy/log/test.log
302
+ - spec/dummy/public/404.html
303
+ - spec/dummy/public/422.html
304
+ - spec/dummy/public/500.html
305
+ - spec/dummy/public/favicon.ico
306
+ - spec/dummy/public/robots.txt
307
+ - spec/dummy/script/rails
308
+ - spec/lib/canvas_oauth/canvas_api_extensions_spec.rb
309
+ - spec/lib/canvas_oauth/canvas_api_spec.rb
310
+ - spec/lib/canvas_oauth/default_utf8_parser_spec.rb
311
+ - spec/models/canvas_oauth/authorization_spec.rb
312
+ - spec/spec_helper.rb
313
+ homepage: https://github.com/ahmeddhamid13/qalam_oauth_engine
314
+ licenses: []
315
+ metadata:
316
+ homepage_uri: https://github.com/ahmeddhamid13/qalam_oauth_engine
317
+ source_code_uri: https://github.com/ahmeddhamid13/qalam_oauth_engine
318
+ post_install_message:
319
+ rdoc_options: []
320
+ require_paths:
321
+ - lib
322
+ required_ruby_version: !ruby/object:Gem::Requirement
323
+ requirements:
324
+ - - ">="
325
+ - !ruby/object:Gem::Version
326
+ version: '0'
327
+ required_rubygems_version: !ruby/object:Gem::Requirement
328
+ requirements:
329
+ - - ">="
330
+ - !ruby/object:Gem::Version
331
+ version: '0'
332
+ requirements: []
333
+ rubygems_version: 3.2.3
334
+ signing_key:
335
+ specification_version: 4
336
+ summary: CanvasOauth is a mountable engine for handling the oauth workflow with canvas
337
+ and making api calls from your rails app.
338
+ test_files:
339
+ - spec/controllers/canvas_oauth/canvas_controller_spec.rb
340
+ - spec/dummy/README.rdoc
341
+ - spec/dummy/Rakefile
342
+ - spec/dummy/app/controllers/application_controller.rb
343
+ - spec/dummy/app/controllers/welcome_controller.rb
344
+ - spec/dummy/config/application.rb
345
+ - spec/dummy/config/boot.rb
346
+ - spec/dummy/config/canvas.yml
347
+ - spec/dummy/config/database.yml
348
+ - spec/dummy/config/environment.rb
349
+ - spec/dummy/config/environments/development.rb
350
+ - spec/dummy/config/environments/production.rb
351
+ - spec/dummy/config/environments/test.rb
352
+ - spec/dummy/config/initializers/backtrace_silencers.rb
353
+ - spec/dummy/config/initializers/inflections.rb
354
+ - spec/dummy/config/initializers/mime_types.rb
355
+ - spec/dummy/config/initializers/secret_token.rb
356
+ - spec/dummy/config/initializers/session_store.rb
357
+ - spec/dummy/config/initializers/wrap_parameters.rb
358
+ - spec/dummy/config/locales/en.yml
359
+ - spec/dummy/config/routes.rb
360
+ - spec/dummy/config.ru
361
+ - spec/dummy/db/development.sqlite3
362
+ - spec/dummy/db/migrate/20160711200737_create_canvas_oauth_authorizations.canvas_oauth.rb
363
+ - spec/dummy/db/schema.rb
364
+ - spec/dummy/db/test.sqlite3
365
+ - spec/dummy/log/development.log
366
+ - spec/dummy/log/test.log
367
+ - spec/dummy/public/404.html
368
+ - spec/dummy/public/422.html
369
+ - spec/dummy/public/500.html
370
+ - spec/dummy/public/favicon.ico
371
+ - spec/dummy/public/robots.txt
372
+ - spec/dummy/script/rails
373
+ - spec/lib/canvas_oauth/canvas_api_extensions_spec.rb
374
+ - spec/lib/canvas_oauth/canvas_api_spec.rb
375
+ - spec/lib/canvas_oauth/default_utf8_parser_spec.rb
376
+ - spec/models/canvas_oauth/authorization_spec.rb
377
+ - spec/spec_helper.rb