flexirest 1.6.7 → 1.6.8

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,517 @@
1
+ require 'spec_helper'
2
+
3
+ class EmptyExample < Flexirest::BaseWithoutValidation
4
+ whiny_missing true
5
+ end
6
+
7
+ class TranslatorExample
8
+ def self.all(object)
9
+ ret = {}
10
+ ret["first_name"] = object["name"]
11
+ ret
12
+ end
13
+ end
14
+
15
+ class AlteringClientExample < Flexirest::BaseWithoutValidation
16
+ translator TranslatorExample
17
+ base_url "http://www.example.com"
18
+
19
+ get :all, "/all", fake:"{\"name\":\"Billy\"}"
20
+ get :list, "/list", fake:"{\"name\":\"Billy\", \"country\":\"United Kingdom\"}"
21
+ get :iterate, "/iterate", fake:"{\"name\":\"Billy\", \"country\":\"United Kingdom\"}"
22
+ get :find, "/find/:id"
23
+ end
24
+
25
+ class RecordResponseExample < Flexirest::BaseWithoutValidation
26
+ base_url "http://www.example.com"
27
+
28
+ record_response do |url, response|
29
+ raise Exception.new("#{url}|#{response.body}")
30
+ end
31
+
32
+ get :all, "/all"
33
+ end
34
+
35
+ class NonHostnameBaseUrlExample < Flexirest::BaseWithoutValidation
36
+ base_url "http://www.example.com/v1/"
37
+ get :all, "/all"
38
+ end
39
+
40
+ class InstanceMethodExample < Flexirest::BaseWithoutValidation
41
+ base_url "http://www.example.com/v1/"
42
+ get :all, "/all"
43
+ end
44
+
45
+ class WhitelistedDateExample < Flexirest::BaseWithoutValidation
46
+ parse_date :updated_at
47
+ end
48
+
49
+
50
+ describe Flexirest::BaseWithoutValidation do
51
+ it 'should instantiate a new descendant' do
52
+ expect{EmptyExample.new}.to_not raise_error
53
+ end
54
+
55
+ it "should not instantiate a new base class" do
56
+ expect{Flexirest::Base.new}.to raise_error(Exception)
57
+ end
58
+
59
+ it "should save attributes passed in constructor" do
60
+ client = EmptyExample.new(test: "Something")
61
+ expect(client._attributes[:test]).to be_a(String)
62
+ end
63
+
64
+ it "should allow attribute reading using missing method names" do
65
+ client = EmptyExample.new(test: "Something")
66
+ expect(client.test).to eq("Something")
67
+ end
68
+
69
+ it "should allow attribute reading using [] array notation" do
70
+ client = EmptyExample.new(test: "Something")
71
+ expect(client["test"]).to eq("Something")
72
+ end
73
+
74
+ it "allows iteration over attributes using each" do
75
+ client = AlteringClientExample.iterate
76
+ expect(client).to be_respond_to(:each)
77
+ keys = []
78
+ values = []
79
+ client.each do |key, value|
80
+ keys << key ; values << value
81
+ end
82
+ expect(keys).to eq(%w{name country}.map(&:to_sym))
83
+ expect(values).to eq(["Billy", "United Kingdom"])
84
+ end
85
+
86
+ it "should automatically parse ISO 8601 format date and time" do
87
+ t = Time.now
88
+ client = EmptyExample.new(test: t.iso8601)
89
+ expect(client["test"]).to be_an_instance_of(DateTime)
90
+ expect(client["test"].to_s).to eq(t.to_datetime.to_s)
91
+ end
92
+
93
+ it "should automatically parse ISO 8601 format date and time with milliseconds" do
94
+ t = Time.now
95
+ client = EmptyExample.new(test: t.iso8601(3))
96
+ expect(client["test"]).to be_an_instance_of(DateTime)
97
+ expect(client["test"].to_s).to eq(t.to_datetime.to_s)
98
+ end
99
+
100
+ it "should automatically parse ISO 8601 format dates" do
101
+ d = Date.today
102
+ client = EmptyExample.new(test: d.iso8601)
103
+ expect(client["test"]).to be_an_instance_of(Date)
104
+ expect(client["test"]).to eq(d)
105
+ end
106
+
107
+ it "should automatically parse date/time strings regardless if the date portion has no delimiters" do
108
+ client = EmptyExample.new(test: "20151230T09:48:50-05:00")
109
+ expect(client["test"]).to be_an_instance_of(DateTime)
110
+ end
111
+
112
+ it "should allow strings of 4 digits and not intepret them as dates" do
113
+ client = EmptyExample.new(test: "2015")
114
+ expect(client["test"]).to be_an_instance_of(String)
115
+ end
116
+
117
+ it "should allow strings of 8 digits and not intepret them as dates" do
118
+ client = EmptyExample.new(test: "1266129")
119
+ expect(client["test"]).to be_an_instance_of(String)
120
+ end
121
+
122
+ it "should store attributes set using missing method names and mark them as dirty" do
123
+ client = EmptyExample.new()
124
+ client.test = "Something"
125
+ expect(client.test.to_s).to eq("Something")
126
+ expect(client).to be_dirty
127
+ end
128
+
129
+ it "should store attribute set using []= array notation and mark them as dirty" do
130
+ client = EmptyExample.new()
131
+ client["test"] = "Something"
132
+ expect(client["test"].to_s).to eq("Something")
133
+ expect(client).to be_dirty
134
+ end
135
+
136
+ it "should track changed attributes and provide access to previous values (similar to ActiveRecord/Mongoid)" do
137
+ client = EmptyExample.new()
138
+ client["test"] = "Something"
139
+
140
+ client._clean! # force a clean state so we can proceed with tests
141
+
142
+ expect(client).to_not be_dirty # clean state should have set in (dirty?)
143
+ expect(client).to_not be_changed # clean state should have set in (changed?)
144
+ expect(client["test"].to_s).to eq("Something") # verify attribute value persists
145
+
146
+ client["test"] = "SomethingElse" # change the attribute value
147
+ expect(client["test"].to_s).to eq("SomethingElse") # most current set value should be returned
148
+ expect(client).to be_dirty # an attribute was changed, so the entire object is dirty
149
+ expect(client).to be_changed # an attribute was changed, so the entire object is changed
150
+ expect(client.changed).to be_a(Array) # the list of changed attributes should be an Array
151
+ expect(client.changed).to eq([:test]) # the list of changed attributes should provide the name of the changed attribute
152
+ expect(client.changes).to be_a(Hash) # changes are returned as a hash
153
+ expect(client.changes).to eq({test: ["Something", "SomethingElse"]}) # changes include [saved,unsaved] values, keyed by attribute name
154
+ expect(client.test_was).to eq("Something") # dynamic *_was notation provides original value
155
+
156
+ client["test"] = "SomethingElseAgain" # change the attribute value again
157
+ expect(client.test_was).to eq("Something") # dynamic *_was notation provides original value (from most recent save/load, not most recent change)
158
+ expect(client.changes).to eq({test: ["Something", "SomethingElseAgain"]}) # changes include [saved,unsaved] values, keyed by attribute name
159
+
160
+ # resets the test attribute back to the original value
161
+ expect( client.reset_test! ).to eq(["Something", "SomethingElseAgain"]) # reseting an attribute returns the previous pending changeset
162
+ expect(client).to_not be_dirty # reseting an attribute should makeit not dirty again
163
+ end
164
+
165
+ it "should overwrite attributes already set and mark them as dirty" do
166
+ client = EmptyExample.new(hello: "World")
167
+ client._clean!
168
+ expect(client).to_not be_dirty
169
+
170
+ client.hello = "Everybody"
171
+ expect(client).to be_dirty
172
+ end
173
+
174
+ it 'should respond_to? attributes defined in the response' do
175
+ client = EmptyExample.new(hello: "World")
176
+ expect(client.respond_to?(:hello)).to be_truthy
177
+ expect(client.respond_to?(:world)).to be_falsey
178
+ end
179
+
180
+ it "should save the base URL for the API server" do
181
+ class BaseExample < Flexirest::Base
182
+ base_url "https://www.example.com/api/v1"
183
+ end
184
+ expect(BaseExample.base_url).to eq("https://www.example.com/api/v1")
185
+ end
186
+
187
+ it "should allow changing the base_url while running" do
188
+ class OutsideBaseExample < Flexirest::Base ; end
189
+
190
+ Flexirest::Base.base_url = "https://www.example.com/api/v1"
191
+ expect(OutsideBaseExample.base_url).to eq("https://www.example.com/api/v1")
192
+
193
+ Flexirest::Base.base_url = "https://www.example.com/api/v2"
194
+ expect(OutsideBaseExample.base_url).to eq("https://www.example.com/api/v2")
195
+ end
196
+
197
+ it "should include the Mapping module" do
198
+ expect(EmptyExample).to respond_to(:_calls)
199
+ expect(EmptyExample).to_not respond_to(:_non_existant)
200
+ end
201
+
202
+ it "should be able to easily clean all attributes" do
203
+ client = EmptyExample.new(hello:"World", goodbye:"Everyone")
204
+ expect(client).to be_dirty
205
+ client._clean!
206
+ expect(client).to_not be_dirty
207
+ end
208
+
209
+ it "should not overly pollute the instance method namespace to reduce chances of clashing (<13 instance methods)" do
210
+ instance_methods = EmptyExample.instance_methods - Object.methods
211
+ instance_methods = instance_methods - instance_methods.grep(/^_/)
212
+ expect(instance_methods.size).to be < 13
213
+ end
214
+
215
+ it "should raise an exception for missing attributes if whiny_missing is enabled" do
216
+ expect{EmptyExample.new.first_name}.to raise_error(Flexirest::NoAttributeException)
217
+ end
218
+
219
+ it "should be able to lazy instantiate an object from a prefixed lazy_ method call" do
220
+ expect_any_instance_of(Flexirest::Connection).to receive(:get).with('/find/1', anything).and_return(::FaradayResponseMock.new(OpenStruct.new(status:200, response_headers:{}, body:"{\"first_name\":\"Billy\"}")))
221
+ example = AlteringClientExample.lazy_find(1)
222
+ expect(example).to be_an_instance_of(Flexirest::LazyLoader)
223
+ expect(example.first_name).to eq("Billy")
224
+ end
225
+
226
+ it "should be able to lazy instantiate an object from a prefixed lazy_ method call from an instance" do
227
+ expect_any_instance_of(Flexirest::Connection).to receive(:get).with('/find/1', anything).and_return(::FaradayResponseMock.new(OpenStruct.new(status:200, response_headers:{}, body:"{\"first_name\":\"Billy\"}")))
228
+ example = AlteringClientExample.new.lazy_find(1)
229
+ expect(example).to be_an_instance_of(Flexirest::LazyLoader)
230
+ expect(example.first_name).to eq("Billy")
231
+ end
232
+
233
+ context "#inspect output" do
234
+ it "displays a nice version" do
235
+ object = EmptyExample.new(id: 1, name: "John Smith")
236
+ expect(object.inspect).to match(/#<EmptyExample id: 1, name: "John Smith"/)
237
+ end
238
+
239
+ it "shows dirty attributes as a list of names at the end" do
240
+ object = EmptyExample.new(id: 1, name: "John Smith")
241
+ expect(object.inspect).to match(/#<EmptyExample id: 1, name: "John Smith" \(unsaved: id, name\)/)
242
+ end
243
+
244
+ it "doesn't show an empty list of dirty attributes" do
245
+ object = EmptyExample.new(id: 1, name: "John Smith")
246
+ object.instance_variable_set(:@dirty_attributes, Set.new)
247
+ expect(object.inspect).to_not match(/\(unsaved: id, name\)/)
248
+ end
249
+
250
+ it "shows dates in a nice format" do
251
+ object = EmptyExample.new(dob: Time.new(2015, 01, 02, 03, 04, 05))
252
+ expect(object.inspect).to match(/#<EmptyExample dob: "2015\-01\-02 03:04:05"/)
253
+ end
254
+
255
+ it "shows the etag if one is set" do
256
+ object = EmptyExample.new(id: 1)
257
+ object.instance_variable_set(:@_etag, "sample_etag")
258
+ expect(object.inspect).to match(/#<EmptyExample id: 1, ETag: sample_etag/)
259
+ end
260
+
261
+ it "shows the HTTP status code if one is set" do
262
+ object = EmptyExample.new(id: 1)
263
+ object.instance_variable_set(:@_status, 200)
264
+ expect(object.inspect).to match(/#<EmptyExample id: 1, Status: 200/)
265
+ end
266
+
267
+ it "shows [uninitialized] for new objects" do
268
+ object = EmptyExample.new
269
+ expect(object.inspect).to match(/#<EmptyExample \[uninitialized\]/)
270
+ end
271
+
272
+ it "truncates the long Strings" do
273
+ object = EmptyExample.new(id: 1, name: "x" * 100)
274
+ expect(object.inspect).to match(/#<EmptyExample id: 1, name: "x{51}\.\.\."/)
275
+ end
276
+
277
+ end
278
+
279
+ context "accepts a Translator to reformat JSON" do
280
+ it "should log a deprecation warning when using a translator" do
281
+ expect(Flexirest::Logger).to receive(:warn) do |message|
282
+ expect(message).to start_with("DEPRECATION")
283
+ end
284
+ Proc.new do
285
+ class DummyExample < Flexirest::Base
286
+ translator TranslatorExample
287
+ end
288
+ end.call
289
+ end
290
+
291
+ it "should call Translator#method when calling the mapped method if it responds to it" do
292
+ expect(TranslatorExample).to receive(:all).with(an_instance_of(Hash)).and_return({})
293
+ AlteringClientExample.all
294
+ end
295
+
296
+ it "should not raise errors when calling Translator#method if it does not respond to it" do
297
+ expect {AlteringClientExample.list}.to_not raise_error
298
+ end
299
+
300
+ it "should translate JSON returned through the Translator" do
301
+ ret = AlteringClientExample.all
302
+ expect(ret.first_name).to eq("Billy")
303
+ expect(ret.name).to be_nil
304
+ end
305
+
306
+ it "should return original JSON for items that aren't handled by the Translator" do
307
+ ret = AlteringClientExample.list
308
+ expect(ret.name).to eq("Billy")
309
+ expect(ret.first_name).to be_nil
310
+ end
311
+ end
312
+
313
+ context "directly call a URL, rather than via a mapped method" do
314
+ it "should be able to directly call a URL" do
315
+ expect_any_instance_of(Flexirest::Request).to receive(:do_request).with(any_args).and_return(::FaradayResponseMock.new(OpenStruct.new(status:200, response_headers:{}, body:"{\"first_name\":\"Billy\"}")))
316
+ EmptyExample._request("http://api.example.com/")
317
+ end
318
+
319
+ it "allows already encoded bodies" do
320
+ Flexirest::ConnectionManager.reset!
321
+ connection = double("Connection")
322
+ allow(connection).to receive(:base_url).and_return("http://api.example.com")
323
+ expect(Flexirest::ConnectionManager).to receive(:get_connection).with("http://api.example.com/").and_return(connection)
324
+ expect(connection).
325
+ to receive(:post).
326
+ with("http://api.example.com/", "{\"test\":\"value\"}",an_instance_of(Hash)).
327
+ and_return(::FaradayResponseMock.new(OpenStruct.new(body:"{\"first_name\":\"John\", \"id\":1234}", response_headers:{}, status:200)))
328
+ EmptyExample._request("http://api.example.com/", :post, {test: "value"}.to_json, request_body_type: :json)
329
+ end
330
+
331
+ it "passes headers" do
332
+ stub_request(:get, "http://api.example.com/v1").
333
+ with(headers: {'Accept'=>'application/hal+json, application/json;q=0.5', 'Accept-Encoding'=>'gzip;q=1.0,deflate;q=0.6,identity;q=0.3', 'Connection'=>'Keep-Alive', 'Content-Type'=>'application/x-www-form-urlencoded', 'X-Something'=>'foo/bar', 'User-Agent'=>/Flexirest\//}).
334
+ to_return(status: 200, body: "", headers: {})
335
+ EmptyExample._request("http://api.example.com/v1", :get, {}, {headers: {"X-Something" => "foo/bar"}})
336
+ end
337
+
338
+ it "passes headers if the response is unparsed" do
339
+ stub_request(:get, "http://api.example.com/v1").
340
+ with(headers: {'Accept'=>'application/hal+json, application/json;q=0.5', 'Accept-Encoding'=>'gzip;q=1.0,deflate;q=0.6,identity;q=0.3', 'Connection'=>'Keep-Alive', 'Content-Type'=>'application/x-www-form-urlencoded', 'X-Something'=>'foo/bar', 'User-Agent'=>/Flexirest\//}).
341
+ to_return(status: 200, body: "", headers: {})
342
+ EmptyExample._plain_request("http://api.example.com/v1", :get, {}, {headers: {"X-Something" => "foo/bar"}})
343
+ end
344
+
345
+ it "runs callbacks as usual" do
346
+ expect_any_instance_of(Flexirest::Request).to receive(:do_request).with(any_args).and_return(::FaradayResponseMock.new(OpenStruct.new(status:200, response_headers:{}, body:"{\"first_name\":\"Billy\"}")))
347
+ expect(EmptyExample).to receive(:_callback_request).with(any_args).exactly(2).times
348
+ EmptyExample._request("http://api.example.com/")
349
+ end
350
+
351
+ it "should make an HTTP request" do
352
+ expect_any_instance_of(Flexirest::Connection).to receive(:get).with(any_args).and_return(::FaradayResponseMock.new(OpenStruct.new(status:200, response_headers:{}, body:"{\"first_name\":\"Billy\"}")))
353
+ EmptyExample._request("http://api.example.com/")
354
+ end
355
+
356
+ it "should make an HTTP request including the path in the base_url" do
357
+ expect_any_instance_of(Flexirest::Connection).to receive(:get).with('/v1/all', anything).and_return(::FaradayResponseMock.new(OpenStruct.new(status:200, response_headers:{}, body:"{\"first_name\":\"Billy\"}")))
358
+ NonHostnameBaseUrlExample.all
359
+ end
360
+
361
+ it "should map the response from the directly called URL in the normal way" do
362
+ expect_any_instance_of(Flexirest::Request).to receive(:do_request).with(any_args).and_return(::FaradayResponseMock.new(OpenStruct.new(status:200, response_headers:{}, body:"{\"first_name\":\"Billy\"}")))
363
+ example = EmptyExample._request("http://api.example.com/")
364
+ expect(example.first_name).to eq("Billy")
365
+ end
366
+
367
+ it "should be able to pass the plain response from the directly called URL bypassing JSON loading" do
368
+ response_body = "This is another non-JSON string"
369
+ expect_any_instance_of(Flexirest::Connection).to receive(:post).with(any_args).and_return(::FaradayResponseMock.new(OpenStruct.new(status:200, response_headers:{}, body:response_body)))
370
+ expect(EmptyExample._plain_request("http://api.example.com/", :post, {id:1234})).to eq(response_body)
371
+ end
372
+
373
+ it "should return a PlainResponse from the directly called URL bypassing JSON loading" do
374
+ response_body = "This is another non-JSON string"
375
+ expect_any_instance_of(Flexirest::Connection).to receive(:post).with(any_args).and_return(::FaradayResponseMock.new(OpenStruct.new(status:200, response_headers:{}, body:response_body)))
376
+ expect(EmptyExample._plain_request("http://api.example.com/", :post, {id:1234})).to be_a(Flexirest::PlainResponse)
377
+ end
378
+
379
+ context "Simulating Faraday connection in_parallel" do
380
+ it "should be able to pass the plain response from the directly called URL bypassing JSON loading" do
381
+ response_body = "This is another non-JSON string"
382
+ response = ::FaradayResponseMock.new(
383
+ OpenStruct.new(status:200, response_headers:{}, body:response_body),
384
+ false)
385
+ expect_any_instance_of(Flexirest::Connection).to receive(:post).with(any_args).and_return(response)
386
+ result = EmptyExample._plain_request("http://api.example.com/", :post, {id:1234})
387
+
388
+ expect(result).to eq(nil)
389
+
390
+ response.finish
391
+ expect(result).to eq(response_body)
392
+ end
393
+ end
394
+
395
+ it "should cache plain requests separately" do
396
+ perform_caching = EmptyExample.perform_caching
397
+ cache_store = EmptyExample.cache_store
398
+ begin
399
+ response = "This is a non-JSON string"
400
+ other_response = "This is another non-JSON string"
401
+ allow_any_instance_of(Flexirest::Connection).to receive(:get) do |instance, url, others|
402
+ if url["/?test=1"]
403
+ ::FaradayResponseMock.new(OpenStruct.new(status:200, response_headers:{}, body:response))
404
+ else
405
+ ::FaradayResponseMock.new(OpenStruct.new(status:200, response_headers:{}, body:other_response))
406
+ end
407
+ end
408
+ EmptyExample.perform_caching = true
409
+ EmptyExample.cache_store = TestCacheStore.new
410
+ expect(EmptyExample._plain_request("http://api.example.com/?test=1")).to eq(response)
411
+ expect(EmptyExample._plain_request("http://api.example.com/?test=2")).to eq(other_response)
412
+ ensure
413
+ EmptyExample.perform_caching = perform_caching
414
+ EmptyExample.cache_store = cache_store
415
+ end
416
+ end
417
+
418
+ it "should work with caching if instance methods are used" do
419
+ perform_caching = InstanceMethodExample.perform_caching
420
+ cache_store = InstanceMethodExample.cache_store
421
+ begin
422
+ response = "{\"id\": 1, \"name\":\"test\"}"
423
+ allow_any_instance_of(Flexirest::Connection).to receive(:get).and_return( ::FaradayResponseMock.new(OpenStruct.new(status:200, response_headers:{"Etag" => "12345678", "Content-type" => "application/json"}, body:response)))
424
+ e = InstanceMethodExample.new
425
+ e.all(1)
426
+ expect(e.id).to eq(1)
427
+ ensure
428
+ InstanceMethodExample.perform_caching = perform_caching
429
+ InstanceMethodExample.cache_store = cache_store
430
+ end
431
+ end
432
+
433
+ it "should be able to lazy load a direct URL request" do
434
+ expect_any_instance_of(Flexirest::Request).to receive(:do_request).with(any_args).and_return(::FaradayResponseMock.new(OpenStruct.new(status:200, response_headers:{}, body:"{\"first_name\":\"Billy\"}")))
435
+ example = EmptyExample._lazy_request("http://api.example.com/")
436
+ expect(example).to be_an_instance_of(Flexirest::LazyLoader)
437
+ expect(example.first_name).to eq("Billy")
438
+ end
439
+
440
+ it "should be able to specify a method and parameters for the call" do
441
+ expect_any_instance_of(Flexirest::Connection).to receive(:post).with(any_args).and_return(::FaradayResponseMock.new(OpenStruct.new(status:200, response_headers:{}, body:"{\"first_name\":\"Billy\"}")))
442
+ EmptyExample._request("http://api.example.com/", :post, {id:1234})
443
+ end
444
+
445
+ it "should be able to replace parameters in the URL for the call" do
446
+ expect_any_instance_of(Flexirest::Connection).to receive(:post).with("http://api.example.com/1234", "", any_args).and_return(::FaradayResponseMock.new(OpenStruct.new(status:200, response_headers:{}, body:"{\"first_name\":\"Billy\"}")))
447
+ EmptyExample._request("http://api.example.com/:id", :post, {id:1234})
448
+ end
449
+
450
+ it "should be able to use mapped methods to create a request to pass in to _lazy_request" do
451
+ expect_any_instance_of(Flexirest::Connection).to receive(:get).with('/find/1', anything).and_return(::FaradayResponseMock.new(OpenStruct.new(status:200, response_headers:{}, body:"{\"first_name\":\"Billy\"}")))
452
+ request = AlteringClientExample._request_for(:find, id: 1)
453
+ example = AlteringClientExample._lazy_request(request)
454
+ expect(example.first_name).to eq("Billy")
455
+ end
456
+ end
457
+
458
+ context "Recording a response" do
459
+ it "calls back to the record_response callback with the url and response body" do
460
+ expect_any_instance_of(Flexirest::Connection).to receive(:get).with(any_args).and_return(::FaradayResponseMock.new(OpenStruct.new(status:200, response_headers:{}, body:"Hello world")))
461
+ expect{RecordResponseExample.all}.to raise_error(Exception, "/all|Hello world")
462
+ end
463
+ end
464
+
465
+ context "JSON output" do
466
+ let(:student1) { EmptyExample.new(name:"John Smith", age:31) }
467
+ let(:student2) { EmptyExample.new(name:"Bob Brown", age:29) }
468
+ let(:location) { EmptyExample.new(place:"Room 1408") }
469
+ let(:lazy) { Laz }
470
+ let(:object) { EmptyExample.new(name:"Programming 101", location:location, students:[student1, student2]) }
471
+ let(:json_parsed_object) { MultiJson.load(object.to_json) }
472
+
473
+ it "should be able to export to valid json" do
474
+ expect(object.to_json).to_not be_blank
475
+ expect{MultiJson.load(object.to_json)}.to_not raise_error
476
+ end
477
+
478
+ it "should not be using Object's #to_json method" do
479
+ expect(json_parsed_object["dirty_attributes"]).to be_nil
480
+ end
481
+
482
+ it "should recursively convert nested objects" do
483
+ expect(json_parsed_object["location"]["place"]).to eq(location.place)
484
+ end
485
+
486
+ it "should include arrayed objects" do
487
+ expect(json_parsed_object["students"]).to be_an_instance_of(Array)
488
+ expect(json_parsed_object["students"].size).to eq(2)
489
+ expect(json_parsed_object["students"].first["name"]).to eq(student1.name)
490
+ expect(json_parsed_object["students"].second["name"]).to eq(student2.name)
491
+ end
492
+
493
+ it "should set integers as a native JSON type" do
494
+ expect(json_parsed_object["students"].first["age"]).to eq(student1.age)
495
+ expect(json_parsed_object["students"].second["age"]).to eq(student2.age)
496
+ end
497
+ end
498
+
499
+ describe "instantiating object" do
500
+ context "no whitelist specified" do
501
+ it "should convert dates automatically" do
502
+ client = EmptyExample.new(test: Time.now.iso8601)
503
+ expect(client["test"]).to be_an_instance_of(DateTime)
504
+ end
505
+ end
506
+
507
+ context "whitelist specified" do
508
+ it "should only convert specified dates" do
509
+ time = Time.now.iso8601
510
+ client = WhitelistedDateExample.new(updated_at: time, created_at: time)
511
+ expect(client["updated_at"]).to be_an_instance_of(DateTime)
512
+ expect(client["created_at"]).to be_an_instance_of(String)
513
+ end
514
+ end
515
+ end
516
+
517
+ end