test_track_rails_client 0.9.7 → 0.9.8

Sign up to get free protection for your applications and to get access to all the features.
Files changed (113) hide show
  1. checksums.yaml +8 -8
  2. data/README.md +11 -8
  3. data/lib/test_track_rails_client/version.rb +1 -1
  4. data/vendor/gems/fakeable_her/fakeable_her.gemspec +22 -0
  5. data/vendor/gems/fakeable_her/lib/fakeable_her/model.rb +148 -0
  6. data/vendor/gems/fakeable_her/lib/fakeable_her/version.rb +3 -0
  7. data/vendor/gems/fakeable_her/lib/fakeable_her.rb +5 -0
  8. data/vendor/gems/her/CONTRIBUTING.md +26 -0
  9. data/vendor/gems/her/Gemfile +10 -0
  10. data/vendor/gems/her/LICENSE +7 -0
  11. data/vendor/gems/her/README.md +1023 -0
  12. data/vendor/gems/her/Rakefile +11 -0
  13. data/vendor/gems/her/UPGRADE.md +101 -0
  14. data/vendor/gems/her/gemfiles/Gemfile.activemodel-3.2.x +7 -0
  15. data/vendor/gems/her/gemfiles/Gemfile.activemodel-4.0 +7 -0
  16. data/vendor/gems/her/gemfiles/Gemfile.activemodel-4.1 +7 -0
  17. data/vendor/gems/her/gemfiles/Gemfile.activemodel-4.2 +7 -0
  18. data/vendor/gems/her/her.gemspec +31 -0
  19. data/vendor/gems/her/lib/her/api.rb +119 -0
  20. data/vendor/gems/her/lib/her/collection.rb +12 -0
  21. data/vendor/gems/her/lib/her/error_collection.rb +15 -0
  22. data/vendor/gems/her/lib/her/errors.rb +40 -0
  23. data/vendor/gems/her/lib/her/json_api/model.rb +46 -0
  24. data/vendor/gems/her/lib/her/middleware/accept_json.rb +17 -0
  25. data/vendor/gems/her/lib/her/middleware/first_level_parse_json.rb +36 -0
  26. data/vendor/gems/her/lib/her/middleware/json_api_parser.rb +36 -0
  27. data/vendor/gems/her/lib/her/middleware/parse_json.rb +21 -0
  28. data/vendor/gems/her/lib/her/middleware/second_level_parse_json.rb +36 -0
  29. data/vendor/gems/her/lib/her/middleware.rb +12 -0
  30. data/vendor/gems/her/lib/her/model/active_model_overrides.rb +13 -0
  31. data/vendor/gems/her/lib/her/model/associations/association.rb +106 -0
  32. data/vendor/gems/her/lib/her/model/associations/association_proxy.rb +46 -0
  33. data/vendor/gems/her/lib/her/model/associations/belongs_to_association.rb +96 -0
  34. data/vendor/gems/her/lib/her/model/associations/has_many_association.rb +100 -0
  35. data/vendor/gems/her/lib/her/model/associations/has_one_association.rb +79 -0
  36. data/vendor/gems/her/lib/her/model/associations.rb +141 -0
  37. data/vendor/gems/her/lib/her/model/attributes.rb +304 -0
  38. data/vendor/gems/her/lib/her/model/base.rb +33 -0
  39. data/vendor/gems/her/lib/her/model/deprecated_methods.rb +61 -0
  40. data/vendor/gems/her/lib/her/model/http.rb +117 -0
  41. data/vendor/gems/her/lib/her/model/introspection.rb +65 -0
  42. data/vendor/gems/her/lib/her/model/nested_attributes.rb +45 -0
  43. data/vendor/gems/her/lib/her/model/orm.rb +219 -0
  44. data/vendor/gems/her/lib/her/model/parse.rb +215 -0
  45. data/vendor/gems/her/lib/her/model/paths.rb +126 -0
  46. data/vendor/gems/her/lib/her/model/relation.rb +251 -0
  47. data/vendor/gems/her/lib/her/model.rb +81 -0
  48. data/vendor/gems/her/lib/her/version.rb +3 -0
  49. data/vendor/gems/her/lib/her.rb +20 -0
  50. data/vendor/gems/her/spec/api_spec.rb +114 -0
  51. data/vendor/gems/her/spec/collection_spec.rb +26 -0
  52. data/vendor/gems/her/spec/error_collection_spec.rb +33 -0
  53. data/vendor/gems/her/spec/json_api/model_spec.rb +168 -0
  54. data/vendor/gems/her/spec/middleware/accept_json_spec.rb +10 -0
  55. data/vendor/gems/her/spec/middleware/first_level_parse_json_spec.rb +62 -0
  56. data/vendor/gems/her/spec/middleware/json_api_parser_spec.rb +32 -0
  57. data/vendor/gems/her/spec/middleware/second_level_parse_json_spec.rb +35 -0
  58. data/vendor/gems/her/spec/model/associations/association_proxy_spec.rb +31 -0
  59. data/vendor/gems/her/spec/model/associations_spec.rb +504 -0
  60. data/vendor/gems/her/spec/model/attributes_spec.rb +404 -0
  61. data/vendor/gems/her/spec/model/callbacks_spec.rb +145 -0
  62. data/vendor/gems/her/spec/model/dirty_spec.rb +110 -0
  63. data/vendor/gems/her/spec/model/http_spec.rb +165 -0
  64. data/vendor/gems/her/spec/model/introspection_spec.rb +76 -0
  65. data/vendor/gems/her/spec/model/nested_attributes_spec.rb +134 -0
  66. data/vendor/gems/her/spec/model/orm_spec.rb +791 -0
  67. data/vendor/gems/her/spec/model/parse_spec.rb +372 -0
  68. data/vendor/gems/her/spec/model/paths_spec.rb +347 -0
  69. data/vendor/gems/her/spec/model/relation_spec.rb +226 -0
  70. data/vendor/gems/her/spec/model/validations_spec.rb +42 -0
  71. data/vendor/gems/her/spec/model_spec.rb +31 -0
  72. data/vendor/gems/her/spec/spec_helper.rb +27 -0
  73. data/vendor/gems/her/spec/support/extensions/array.rb +5 -0
  74. data/vendor/gems/her/spec/support/extensions/hash.rb +5 -0
  75. data/vendor/gems/her/spec/support/macros/her_macros.rb +17 -0
  76. data/vendor/gems/her/spec/support/macros/model_macros.rb +36 -0
  77. data/vendor/gems/her/spec/support/macros/request_macros.rb +27 -0
  78. data/vendor/gems/publicsuffix-ruby/CHANGELOG.md +236 -0
  79. data/vendor/gems/publicsuffix-ruby/Gemfile +3 -0
  80. data/vendor/gems/publicsuffix-ruby/LICENSE.txt +22 -0
  81. data/vendor/gems/publicsuffix-ruby/README.md +151 -0
  82. data/vendor/gems/publicsuffix-ruby/Rakefile +109 -0
  83. data/vendor/gems/publicsuffix-ruby/lib/definitions.txt +11467 -0
  84. data/vendor/gems/publicsuffix-ruby/lib/public_suffix/domain.rb +387 -0
  85. data/vendor/gems/publicsuffix-ruby/lib/public_suffix/errors.rb +53 -0
  86. data/vendor/gems/publicsuffix-ruby/lib/public_suffix/list.rb +302 -0
  87. data/vendor/gems/publicsuffix-ruby/lib/public_suffix/rule.rb +373 -0
  88. data/vendor/gems/publicsuffix-ruby/lib/public_suffix/version.rb +23 -0
  89. data/vendor/gems/publicsuffix-ruby/lib/public_suffix.rb +131 -0
  90. data/vendor/gems/publicsuffix-ruby/public_suffix.gemspec +39 -0
  91. data/vendor/gems/publicsuffix-ruby/test/acceptance_test.rb +42 -0
  92. data/vendor/gems/publicsuffix-ruby/test/test_helper.rb +6 -0
  93. data/vendor/gems/publicsuffix-ruby/test/unit/domain_test.rb +170 -0
  94. data/vendor/gems/publicsuffix-ruby/test/unit/errors_test.rb +23 -0
  95. data/vendor/gems/publicsuffix-ruby/test/unit/list_test.rb +179 -0
  96. data/vendor/gems/publicsuffix-ruby/test/unit/public_suffix_test.rb +115 -0
  97. data/vendor/gems/publicsuffix-ruby/test/unit/rule_test.rb +307 -0
  98. data/vendor/gems/ruby_spec_helpers/lib/ruby_spec_helpers/capybara_configuration.rb +98 -0
  99. data/vendor/gems/ruby_spec_helpers/lib/ruby_spec_helpers/matchers.rb +151 -0
  100. data/vendor/gems/ruby_spec_helpers/lib/ruby_spec_helpers/rspec_configuration.rb +34 -0
  101. data/vendor/gems/ruby_spec_helpers/lib/ruby_spec_helpers/rubocop/cop/betterment/html_safe.rb +15 -0
  102. data/vendor/gems/ruby_spec_helpers/lib/ruby_spec_helpers/rubocop/cop/betterment/raw.rb +15 -0
  103. data/vendor/gems/ruby_spec_helpers/lib/ruby_spec_helpers/rubocop/cop/betterment/safe_concat.rb +15 -0
  104. data/vendor/gems/ruby_spec_helpers/lib/ruby_spec_helpers/rubocop.rb +3 -0
  105. data/vendor/gems/ruby_spec_helpers/lib/ruby_spec_helpers/shared_examples/betterment_application_examples.rb +47 -0
  106. data/vendor/gems/ruby_spec_helpers/lib/ruby_spec_helpers/shared_examples.rb +1 -0
  107. data/vendor/gems/ruby_spec_helpers/lib/ruby_spec_helpers/site_prism_configuration.rb +42 -0
  108. data/vendor/gems/ruby_spec_helpers/lib/ruby_spec_helpers/site_prism_dropdown.rb +17 -0
  109. data/vendor/gems/ruby_spec_helpers/lib/ruby_spec_helpers/version.rb +3 -0
  110. data/vendor/gems/ruby_spec_helpers/lib/ruby_spec_helpers/webmock_configuration.rb +8 -0
  111. data/vendor/gems/ruby_spec_helpers/lib/ruby_spec_helpers.rb +2 -0
  112. data/vendor/gems/ruby_spec_helpers/ruby_spec_helpers.gemspec +25 -0
  113. metadata +110 -1
@@ -0,0 +1,347 @@
1
+ # encoding: utf-8
2
+ require File.join(File.dirname(__FILE__), "../spec_helper.rb")
3
+
4
+ describe Her::Model::Paths do
5
+ context "building request paths" do
6
+ context "simple model" do
7
+ before do
8
+ spawn_model "Foo::User"
9
+ end
10
+
11
+ describe "#request_path" do
12
+ it "builds paths with defaults" do
13
+ Foo::User.new(:id => "foo").request_path.should == "users/foo"
14
+ Foo::User.new(:id => nil).request_path.should == "users"
15
+ Foo::User.new().request_path.should == "users"
16
+ end
17
+
18
+ it "builds paths with custom collection path" do
19
+ Foo::User.collection_path "/utilisateurs"
20
+ Foo::User.new(:id => "foo").request_path.should == "/utilisateurs/foo"
21
+ Foo::User.new().request_path.should == "/utilisateurs"
22
+ end
23
+
24
+ it "builds paths with custom relative collection path" do
25
+ Foo::User.collection_path "utilisateurs"
26
+ Foo::User.new(:id => "foo").request_path.should == "utilisateurs/foo"
27
+ Foo::User.new().request_path.should == "utilisateurs"
28
+ end
29
+
30
+ it "builds paths with custom collection path with multiple variables" do
31
+ Foo::User.collection_path "/organizations/:organization_id/utilisateurs"
32
+
33
+ Foo::User.new(:id => "foo").request_path(:_organization_id => "acme").should == "/organizations/acme/utilisateurs/foo"
34
+ Foo::User.new().request_path(:_organization_id => "acme").should == "/organizations/acme/utilisateurs"
35
+
36
+ Foo::User.new(:id => "foo", :organization_id => "acme").request_path.should == "/organizations/acme/utilisateurs/foo"
37
+ Foo::User.new(:organization_id => "acme").request_path.should == "/organizations/acme/utilisateurs"
38
+ end
39
+
40
+ it "builds paths with custom relative collection path with multiple variables" do
41
+ Foo::User.collection_path "organizations/:organization_id/utilisateurs"
42
+
43
+ Foo::User.new(:id => "foo").request_path(:_organization_id => "acme").should == "organizations/acme/utilisateurs/foo"
44
+ Foo::User.new().request_path(:_organization_id => "acme").should == "organizations/acme/utilisateurs"
45
+
46
+ Foo::User.new(:id => "foo", :organization_id => "acme").request_path.should == "organizations/acme/utilisateurs/foo"
47
+ Foo::User.new(:organization_id => "acme").request_path.should == "organizations/acme/utilisateurs"
48
+ end
49
+
50
+ it "builds paths with custom item path" do
51
+ Foo::User.resource_path "/utilisateurs/:id"
52
+ Foo::User.new(:id => "foo").request_path.should == "/utilisateurs/foo"
53
+ Foo::User.new().request_path.should == "users"
54
+ end
55
+
56
+ it "builds paths with custom relative item path" do
57
+ Foo::User.resource_path "utilisateurs/:id"
58
+ Foo::User.new(:id => "foo").request_path.should == "utilisateurs/foo"
59
+ Foo::User.new().request_path.should == "users"
60
+ end
61
+
62
+ it "raises exceptions when building a path without required custom variables" do
63
+ Foo::User.collection_path "/organizations/:organization_id/utilisateurs"
64
+ expect { Foo::User.new(:id => "foo").request_path }.to raise_error(Her::Errors::PathError, "Missing :_organization_id parameter to build the request path. Path is `/organizations/:organization_id/utilisateurs/:id`. Parameters are `{:id=>\"foo\"}`.")
65
+ end
66
+
67
+ it "escapes the variable values" do
68
+ Foo::User.collection_path "organizations/:organization_id/utilisateurs"
69
+ Foo::User.new(:id => "Привет").request_path(:_organization_id => 'лол').should == "organizations/%D0%BB%D0%BE%D0%BB/utilisateurs/%D0%9F%D1%80%D0%B8%D0%B2%D0%B5%D1%82"
70
+ Foo::User.new(:organization_id => 'лол', :id => "Привет").request_path.should == "organizations/%D0%BB%D0%BE%D0%BB/utilisateurs/%D0%9F%D1%80%D0%B8%D0%B2%D0%B5%D1%82"
71
+ end
72
+ end
73
+ end
74
+
75
+ context "simple model with multiple words" do
76
+ before do
77
+ spawn_model "Foo::AdminUser"
78
+ end
79
+
80
+ describe "#request_path" do
81
+ it "builds paths with defaults" do
82
+ Foo::AdminUser.new(:id => "foo").request_path.should == "admin_users/foo"
83
+ Foo::AdminUser.new().request_path.should == "admin_users"
84
+ end
85
+
86
+ it "builds paths with custom collection path" do
87
+ Foo::AdminUser.collection_path "/users"
88
+ Foo::AdminUser.new(:id => "foo").request_path.should == "/users/foo"
89
+ Foo::AdminUser.new().request_path.should == "/users"
90
+ end
91
+
92
+ it "builds paths with custom relative collection path" do
93
+ Foo::AdminUser.collection_path "users"
94
+ Foo::AdminUser.new(:id => "foo").request_path.should == "users/foo"
95
+ Foo::AdminUser.new().request_path.should == "users"
96
+ end
97
+
98
+ it "builds paths with custom collection path with multiple variables" do
99
+ Foo::AdminUser.collection_path "/organizations/:organization_id/users"
100
+ Foo::AdminUser.new(:id => "foo").request_path(:_organization_id => "acme").should == "/organizations/acme/users/foo"
101
+ Foo::AdminUser.new().request_path(:_organization_id => "acme").should == "/organizations/acme/users"
102
+ end
103
+
104
+ it "builds paths with custom relative collection path with multiple variables" do
105
+ Foo::AdminUser.collection_path "organizations/:organization_id/users"
106
+ Foo::AdminUser.new(:id => "foo").request_path(:_organization_id => "acme").should == "organizations/acme/users/foo"
107
+ Foo::AdminUser.new().request_path(:_organization_id => "acme").should == "organizations/acme/users"
108
+ end
109
+
110
+ it "builds paths with custom item path" do
111
+ Foo::AdminUser.resource_path "/users/:id"
112
+ Foo::AdminUser.new(:id => "foo").request_path.should == "/users/foo"
113
+ Foo::AdminUser.new().request_path.should == "admin_users"
114
+ end
115
+
116
+ it "builds paths with custom relative item path" do
117
+ Foo::AdminUser.resource_path "users/:id"
118
+ Foo::AdminUser.new(:id => "foo").request_path.should == "users/foo"
119
+ Foo::AdminUser.new().request_path.should == "admin_users"
120
+ end
121
+
122
+ it "raises exceptions when building a path without required custom variables" do
123
+ Foo::AdminUser.collection_path "/organizations/:organization_id/users"
124
+ expect { Foo::AdminUser.new(:id => "foo").request_path }.to raise_error(Her::Errors::PathError, "Missing :_organization_id parameter to build the request path. Path is `/organizations/:organization_id/users/:id`. Parameters are `{:id=>\"foo\"}`.")
125
+ end
126
+
127
+ it "raises exceptions when building a relative path without required custom variables" do
128
+ Foo::AdminUser.collection_path "organizations/:organization_id/users"
129
+ expect { Foo::AdminUser.new(:id => "foo").request_path }.to raise_error(Her::Errors::PathError, "Missing :_organization_id parameter to build the request path. Path is `organizations/:organization_id/users/:id`. Parameters are `{:id=>\"foo\"}`.")
130
+ end
131
+ end
132
+ end
133
+
134
+ context "children model" do
135
+ before do
136
+ Her::API.setup :url => "https://api.example.com" do |builder|
137
+ builder.use Her::Middleware::FirstLevelParseJSON
138
+ builder.use Faraday::Request::UrlEncoded
139
+ builder.adapter :test do |stub|
140
+ stub.get("/users/foo") { |env| [200, {}, { :id => 'foo' }.to_json] }
141
+ end
142
+ end
143
+
144
+ spawn_model("Foo::Model") { include_root_in_json true }
145
+
146
+ class User < Foo::Model; end
147
+ @spawned_models << :User
148
+ end
149
+
150
+ it "builds path using the children model name" do
151
+ User.find('foo').id.should == 'foo'
152
+ User.find('foo').id.should == 'foo'
153
+ end
154
+ end
155
+
156
+ context "nested model" do
157
+ before do
158
+ spawn_model "Foo::User"
159
+ end
160
+
161
+ describe "#request_path" do
162
+ it "builds paths with defaults" do
163
+ Foo::User.new(:id => "foo").request_path.should == "users/foo"
164
+ Foo::User.new.request_path.should == "users"
165
+ end
166
+ end
167
+ end
168
+
169
+ context 'custom primary key' do
170
+ before do
171
+ spawn_model 'User' do
172
+ primary_key 'UserId'
173
+ resource_path 'users/:UserId'
174
+ end
175
+
176
+ spawn_model 'Customer' do
177
+ primary_key :customer_id
178
+ resource_path 'customers/:id'
179
+ end
180
+ end
181
+
182
+ describe '#request_path' do
183
+ it 'uses the correct primary key attribute' do
184
+ User.new(:UserId => 'foo').request_path.should == 'users/foo'
185
+ User.new(:id => 'foo').request_path.should == 'users'
186
+ end
187
+
188
+ it 'replaces :id with the appropriate primary key' do
189
+ Customer.new(:customer_id => 'joe').request_path.should == 'customers/joe'
190
+ Customer.new(:id => 'joe').request_path.should == 'customers'
191
+ end
192
+ end
193
+ end
194
+ end
195
+
196
+ context "making subdomain HTTP requests" do
197
+ before do
198
+ Her::API.setup :url => "https://api.example.com/" do |builder|
199
+ builder.use Her::Middleware::FirstLevelParseJSON
200
+ builder.use Faraday::Request::UrlEncoded
201
+ builder.adapter :test do |stub|
202
+ stub.get("organizations/2/users") { |env| [200, {}, [{ :id => 1, :fullname => "Tobias Fünke", :organization_id => 2 }, { :id => 2, :fullname => "Lindsay Fünke", :organization_id => 2 }].to_json] }
203
+ stub.post("organizations/2/users") { |env| [200, {}, { :id => 1, :fullname => "Tobias Fünke", :organization_id => 2 }.to_json] }
204
+ stub.put("organizations/2/users/1") { |env| [200, {}, { :id => 1, :fullname => "Lindsay Fünke", :organization_id => 2 }.to_json] }
205
+ stub.get("organizations/2/users/1") { |env| [200, {}, { :id => 1, :fullname => "Tobias Fünke", :organization_id => 2, :active => true }.to_json] }
206
+ stub.delete("organizations/2/users/1") { |env| [200, {}, { :id => 1, :fullname => "Lindsay Fünke", :organization_id => 2, :active => false }.to_json] }
207
+ end
208
+ end
209
+
210
+ spawn_model "Foo::User" do
211
+ collection_path "organizations/:organization_id/users"
212
+ end
213
+ end
214
+
215
+ describe "fetching a resource" do
216
+ it "maps a single resource to a Ruby object" do
217
+ @user = Foo::User.find(1, :_organization_id => 2)
218
+ @user.id.should == 1
219
+ @user.fullname.should == "Tobias Fünke"
220
+ end
221
+
222
+ it "maps a single resource using a scope to a Ruby object" do
223
+ Foo::User.scope :for_organization, lambda { |o| where(:organization_id => o) }
224
+ @user = Foo::User.for_organization(2).find(1)
225
+ @user.id.should == 1
226
+ @user.fullname.should == "Tobias Fünke"
227
+ end
228
+ end
229
+
230
+ describe "fetching a collection" do
231
+ it "maps a collection of resources to an array of Ruby objects" do
232
+ @users = Foo::User.where(:_organization_id => 2).all
233
+ @users.length.should == 2
234
+ @users.first.fullname.should == "Tobias Fünke"
235
+ end
236
+ end
237
+
238
+ describe "handling new resource" do
239
+ it "handles new resource" do
240
+ @new_user = Foo::User.new(:fullname => "Tobias Fünke", :organization_id => 2)
241
+ @new_user.new?.should be_truthy
242
+
243
+ @existing_user = Foo::User.find(1, :_organization_id => 2)
244
+ @existing_user.new?.should be_falsey
245
+ end
246
+ end
247
+
248
+ describe "creating resources" do
249
+ it "handle one-line resource creation" do
250
+ @user = Foo::User.create(:fullname => "Tobias Fünke", :organization_id => 2)
251
+ @user.id.should == 1
252
+ @user.fullname.should == "Tobias Fünke"
253
+ end
254
+
255
+ it "handle resource creation through Model.new + #save" do
256
+ @user = Foo::User.new(:fullname => "Tobias Fünke", :organization_id => 2)
257
+ @user.save
258
+ @user.fullname.should == "Tobias Fünke"
259
+ end
260
+ end
261
+
262
+ context "updating resources" do
263
+ it "handle resource data update without saving it" do
264
+ @user = Foo::User.find(1, :_organization_id => 2)
265
+ @user.fullname.should == "Tobias Fünke"
266
+ @user.fullname = "Kittie Sanchez"
267
+ @user.fullname.should == "Kittie Sanchez"
268
+ end
269
+
270
+ it "handle resource update through the .update class method" do
271
+ @user = Foo::User.save_existing(1, { :fullname => "Lindsay Fünke", :organization_id => 2 })
272
+ @user.fullname.should == "Lindsay Fünke"
273
+ end
274
+
275
+ it "handle resource update through #save on an existing resource" do
276
+ @user = Foo::User.find(1, :_organization_id => 2)
277
+ @user.fullname = "Lindsay Fünke"
278
+ @user.save
279
+ @user.fullname.should == "Lindsay Fünke"
280
+ end
281
+ end
282
+
283
+ context "deleting resources" do
284
+ it "handle resource deletion through the .destroy class method" do
285
+ @user = Foo::User.destroy_existing(1, :_organization_id => 2)
286
+ @user.active.should be_falsey
287
+ end
288
+
289
+ it "handle resource deletion through #destroy on an existing resource" do
290
+ @user = Foo::User.find(1, :_organization_id => 2)
291
+ @user.destroy
292
+ @user.active.should be_falsey
293
+ end
294
+ end
295
+ end
296
+
297
+ context "making path HTTP requests" do
298
+ before do
299
+ Her::API.setup :url => "https://example.com/api/" do |builder|
300
+ builder.use Her::Middleware::FirstLevelParseJSON
301
+ builder.use Faraday::Request::UrlEncoded
302
+ builder.adapter :test do |stub|
303
+ stub.get("/api/organizations/2/users") { |env| [200, {}, [{ :id => 1, :fullname => "Tobias Fünke", :organization_id => 2 }, { :id => 2, :fullname => "Lindsay Fünke", :organization_id => 2 }].to_json] }
304
+ stub.get("/api/organizations/2/users/1") { |env| [200, {}, { :id => 1, :fullname => "Tobias Fünke", :organization_id => 2, :active => true }.to_json] }
305
+ end
306
+ end
307
+
308
+ spawn_model "Foo::User" do
309
+ collection_path "organizations/:organization_id/users"
310
+ end
311
+ end
312
+
313
+ describe "fetching a resource" do
314
+ it "maps a single resource to a Ruby object" do
315
+ @user = Foo::User.find(1, :_organization_id => 2)
316
+ @user.id.should == 1
317
+ @user.fullname.should == "Tobias Fünke"
318
+ end
319
+ end
320
+
321
+ describe "fetching a collection" do
322
+ it "maps a collection of resources to an array of Ruby objects" do
323
+ @users = Foo::User.where(:_organization_id => 2).all
324
+ @users.length.should == 2
325
+ @users.first.fullname.should == "Tobias Fünke"
326
+ end
327
+ end
328
+
329
+ describe "fetching a resource with absolute path" do
330
+ it "maps a single resource to a Ruby object" do
331
+ Foo::User.resource_path '/api/' + Foo::User.resource_path
332
+ @user = Foo::User.find(1, :_organization_id => 2)
333
+ @user.id.should == 1
334
+ @user.fullname.should == "Tobias Fünke"
335
+ end
336
+ end
337
+
338
+ describe "fetching a collection with absolute path" do
339
+ it "maps a collection of resources to an array of Ruby objects" do
340
+ Foo::User.collection_path '/api/' + Foo::User.collection_path
341
+ @users = Foo::User.where(:_organization_id => 2).all
342
+ @users.length.should == 2
343
+ @users.first.fullname.should == "Tobias Fünke"
344
+ end
345
+ end
346
+ end
347
+ end
@@ -0,0 +1,226 @@
1
+ # encoding: utf-8
2
+ require File.join(File.dirname(__FILE__), "../spec_helper.rb")
3
+
4
+ describe Her::Model::Relation do
5
+ describe :where do
6
+ context "for base classes" do
7
+ before do
8
+ Her::API.setup :url => "https://api.example.com" do |builder|
9
+ builder.use Her::Middleware::FirstLevelParseJSON
10
+ builder.adapter :test do |stub|
11
+ stub.get("/users?foo=1&bar=2") { |env| ok! [{ :id => 2, :fullname => "Tobias Fünke" }] }
12
+ stub.get("/users?admin=1") { |env| ok! [{ :id => 1, :fullname => "Tobias Fünke" }] }
13
+
14
+ stub.get("/users") do |env|
15
+ ok! [
16
+ { :id => 1, :fullname => "Tobias Fünke" },
17
+ { :id => 2, :fullname => "Lindsay Fünke" },
18
+ @created_user,
19
+ ].compact
20
+ end
21
+
22
+ stub.post('/users') do |env|
23
+ @created_user = { :id => 3, :fullname => 'George Michael Bluth' }
24
+ ok! @created_user
25
+ end
26
+ end
27
+ end
28
+
29
+ spawn_model "Foo::User"
30
+ end
31
+
32
+ it "doesn't fetch the data immediatly" do
33
+ Foo::User.should_receive(:request).never
34
+ @users = Foo::User.where(:admin => 1)
35
+ end
36
+
37
+ it "fetches the data and passes query parameters" do
38
+ Foo::User.should_receive(:request).once.and_call_original
39
+ @users = Foo::User.where(:admin => 1)
40
+ @users.should respond_to(:length)
41
+ @users.size.should eql 1
42
+ end
43
+
44
+ it "chains multiple where statements" do
45
+ @user = Foo::User.where(:foo => 1).where(:bar => 2).first
46
+ @user.id.should == 2
47
+ end
48
+
49
+ it "does not reuse relations" do
50
+ Foo::User.all.size.should eql 2
51
+ Foo::User.create(:fullname => 'George Michael Bluth').id.should == 3
52
+ Foo::User.all.size.should eql 3
53
+ end
54
+ end
55
+
56
+ context "for parent class" do
57
+ before do
58
+ Her::API.setup :url => "https://api.example.com" do |builder|
59
+ builder.use Her::Middleware::FirstLevelParseJSON
60
+ builder.adapter :test do |stub|
61
+ stub.get("/users?page=2") { |env| ok! [{ :id => 1, :fullname => "Tobias Fünke" }, { :id => 2, :fullname => "Lindsay Fünke" }] }
62
+ end
63
+ end
64
+
65
+ spawn_model("Foo::Model") do
66
+ scope :page, lambda { |page| where(:page => page) }
67
+ end
68
+
69
+ class User < Foo::Model; end
70
+ @spawned_models << :User
71
+ end
72
+
73
+ it "propagates the scopes through its children" do
74
+ @users = User.page(2)
75
+ @users.length.should == 2
76
+ end
77
+ end
78
+ end
79
+
80
+ describe :create do
81
+ before do
82
+ Her::API.setup :url => "https://api.example.com" do |builder|
83
+ builder.use Her::Middleware::FirstLevelParseJSON
84
+ builder.use Faraday::Request::UrlEncoded
85
+ builder.adapter :test do |stub|
86
+ stub.post("/users") { |env| ok! :id => 1, :fullname => params(env)[:fullname], :email => params(env)[:email] }
87
+ end
88
+ end
89
+
90
+ spawn_model "Foo::User"
91
+ end
92
+
93
+ context "with a single where call" do
94
+ it "creates a resource and passes the query parameters" do
95
+ @user = Foo::User.where(:fullname => "Tobias Fünke", :email => "tobias@bluth.com").create
96
+ @user.id.should == 1
97
+ @user.fullname.should == "Tobias Fünke"
98
+ @user.email.should == "tobias@bluth.com"
99
+ end
100
+ end
101
+
102
+ context "with multiple where calls" do
103
+ it "creates a resource and passes the query parameters" do
104
+ @user = Foo::User.where(:fullname => "Tobias Fünke").create(:email => "tobias@bluth.com")
105
+ @user.id.should == 1
106
+ @user.fullname.should == "Tobias Fünke"
107
+ @user.email.should == "tobias@bluth.com"
108
+ end
109
+ end
110
+ end
111
+
112
+ describe :build do
113
+ before { spawn_model "Foo::User" }
114
+
115
+ it "handles new resource with build" do
116
+ @new_user = Foo::User.where(:fullname => "Tobias Fünke").build
117
+ @new_user.new?.should be_truthy
118
+ @new_user.fullname.should == "Tobias Fünke"
119
+ end
120
+ end
121
+
122
+ describe :scope do
123
+ before do
124
+ Her::API.setup :url => "https://api.example.com" do |builder|
125
+ builder.use Her::Middleware::FirstLevelParseJSON
126
+ builder.adapter :test do |stub|
127
+ stub.get("/users?what=4&where=3") { |env| ok! [{ :id => 3, :fullname => "Maeby Fünke" }] }
128
+ stub.get("/users?what=2") { |env| ok! [{ :id => 2, :fullname => "Lindsay Fünke" }] }
129
+ stub.get("/users?where=6") { |env| ok! [{ :id => 4, :fullname => "Tobias Fünke" }] }
130
+ end
131
+ end
132
+
133
+ spawn_model 'Foo::User' do
134
+ scope :foo, lambda { |v| where(:what => v) }
135
+ scope :bar, lambda { |v| where(:where => v) }
136
+ scope :baz, lambda { bar(6) }
137
+ end
138
+ end
139
+
140
+ it "passes query parameters" do
141
+ @user = Foo::User.foo(2).first
142
+ @user.id.should == 2
143
+ end
144
+
145
+ it "passes multiple query parameters" do
146
+ @user = Foo::User.foo(4).bar(3).first
147
+ @user.id.should == 3
148
+ end
149
+
150
+ it "handles embedded scopes" do
151
+ @user = Foo::User.baz.first
152
+ @user.id.should == 4
153
+ end
154
+ end
155
+
156
+ describe :default_scope do
157
+ context "for new objects" do
158
+ before do
159
+ spawn_model 'Foo::User' do
160
+ default_scope lambda { where(:active => true) }
161
+ default_scope lambda { where(:admin => true) }
162
+ end
163
+ end
164
+
165
+ it "should apply the scope to the attributes" do
166
+ Foo::User.new.should be_active
167
+ Foo::User.new.should be_admin
168
+ end
169
+ end
170
+
171
+ context "for fetched resources" do
172
+ before do
173
+ Her::API.setup :url => "https://api.example.com" do |builder|
174
+ builder.use Her::Middleware::FirstLevelParseJSON
175
+ builder.use Faraday::Request::UrlEncoded
176
+ builder.adapter :test do |stub|
177
+ stub.post("/users") { |env| ok! :id => 3, :active => (params(env)[:active] == "true" ? true : false) }
178
+ end
179
+ end
180
+
181
+ spawn_model 'Foo::User' do
182
+ default_scope lambda { where(:active => true) }
183
+ end
184
+ end
185
+
186
+ it("should apply the scope to the request") { Foo::User.create.should be_active }
187
+ end
188
+
189
+ context "for fetched collections" do
190
+ before do
191
+ Her::API.setup :url => "https://api.example.com" do |builder|
192
+ builder.use Her::Middleware::FirstLevelParseJSON
193
+ builder.use Faraday::Request::UrlEncoded
194
+ builder.adapter :test do |stub|
195
+ stub.get("/users?active=true") { |env| ok! [{ :id => 3, :active => (params(env)[:active] == "true" ? true : false) }] }
196
+ end
197
+ end
198
+
199
+ spawn_model 'Foo::User' do
200
+ default_scope lambda { where(:active => true) }
201
+ end
202
+ end
203
+
204
+ it("should apply the scope to the request") { Foo::User.all.first.should be_active }
205
+ end
206
+ end
207
+
208
+ describe :map do
209
+ before do
210
+ Her::API.setup :url => "https://api.example.com" do |builder|
211
+ builder.use Her::Middleware::FirstLevelParseJSON
212
+ builder.adapter :test do |stub|
213
+ stub.get("/users") do |env|
214
+ ok! [{ :id => 1, :fullname => "Tobias Fünke" }, { :id => 2, :fullname => "Lindsay Fünke" }]
215
+ end
216
+ end
217
+ end
218
+
219
+ spawn_model 'Foo::User'
220
+ end
221
+
222
+ it "delegates the method to the fetched collection" do
223
+ Foo::User.all.map(&:fullname).should == ["Tobias Fünke", "Lindsay Fünke"]
224
+ end
225
+ end
226
+ end
@@ -0,0 +1,42 @@
1
+ # encoding: utf-8
2
+ require File.join(File.dirname(__FILE__), "../spec_helper.rb")
3
+
4
+ describe "Her::Model and ActiveModel::Validations" do
5
+ context "validating attributes" do
6
+ before do
7
+ spawn_model "Foo::User" do
8
+ attributes :fullname, :email
9
+ validates_presence_of :fullname
10
+ validates_presence_of :email
11
+ end
12
+ end
13
+
14
+ it "validates attributes when calling #valid?" do
15
+ user = Foo::User.new
16
+ user.should_not be_valid
17
+ user.errors.full_messages.should include("Fullname can't be blank")
18
+ user.errors.full_messages.should include("Email can't be blank")
19
+ user.fullname = "Tobias Fünke"
20
+ user.email = "tobias@bluthcompany.com"
21
+ user.should be_valid
22
+ end
23
+ end
24
+
25
+ context "handling server errors" do
26
+ before do
27
+ spawn_model("Foo::Model") do
28
+ def errors
29
+ @response_errors
30
+ end
31
+ end
32
+
33
+ class User < Foo::Model; end
34
+ @spawned_models << :User
35
+ end
36
+
37
+ it "validates attributes when calling #valid?" do
38
+ user = User.new(:_errors => ["Email cannot be blank"])
39
+ user.errors.should include("Email cannot be blank")
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,31 @@
1
+ # encoding: utf-8
2
+ require 'spec_helper'
3
+
4
+ describe Her::Model do
5
+ before do
6
+ Her::API.setup :url => "https://api.example.com" do |connection|
7
+ connection.use Her::Middleware::FirstLevelParseJSON
8
+ connection.adapter :test do |stub|
9
+ stub.get("/users/1") { |env| [200, {}, { :id => 1, :name => "Tobias Fünke" }.to_json] }
10
+ stub.get("/users/1/comments") { |env| [200, {}, [{ :id => 4, :body => "They're having a FIRESALE?" }].to_json] }
11
+ end
12
+ end
13
+
14
+ spawn_model("Foo::User") { has_many :comments }
15
+ spawn_model("Foo::Comment")
16
+ end
17
+ subject { Foo::User.find(1) }
18
+
19
+ describe :has_key? do
20
+ it { should_not have_key(:unknown_method_for_a_user) }
21
+ it { should_not have_key(:unknown_method_for_a_user) }
22
+ it { should have_key(:name) }
23
+ it { should have_key(:comments) }
24
+ end
25
+
26
+ describe :[] do
27
+ it { should_not have_key(:unknown_method_for_a_user) }
28
+ specify { subject[:name].should == "Tobias Fünke" }
29
+ specify { subject[:comments].first.body.should == "They're having a FIRESALE?" }
30
+ end
31
+ end
@@ -0,0 +1,27 @@
1
+ $:.unshift File.join(File.dirname(__FILE__), *%w[.. lib])
2
+
3
+ require "rspec"
4
+ require "rspec/its"
5
+ require "her"
6
+ require "pry"
7
+
8
+ # Require everything in `spec/support`
9
+ Dir[File.expand_path('../../spec/support/**/*.rb', __FILE__)].map(&method(:require))
10
+
11
+ # Remove ActiveModel deprecation message
12
+ I18n.enforce_available_locales = false
13
+
14
+ RSpec.configure do |config|
15
+ config.include Her::Testing::Macros::ModelMacros
16
+ config.include Her::Testing::Macros::RequestMacros
17
+
18
+ config.before :each do
19
+ @spawned_models = []
20
+ end
21
+
22
+ config.after :each do
23
+ @spawned_models.each do |model|
24
+ Object.instance_eval { remove_const model } if Object.const_defined?(model)
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,5 @@
1
+ class Array
2
+ def to_json
3
+ MultiJson.dump(self)
4
+ end
5
+ end
@@ -0,0 +1,5 @@
1
+ class Hash
2
+ def to_json
3
+ MultiJson.dump(self)
4
+ end
5
+ end