dupe 0.5.0 → 0.5.1
Sign up to get free protection for your applications and to get access to all the features.
- data/README.rdoc +123 -2
- data/lib/dupe/active_resource_extensions.rb +43 -0
- data/lib/dupe/custom_mocks.rb +9 -1
- data/lib/dupe/database.rb +18 -1
- data/lib/dupe/dupe.rb +16 -2
- data/lib/dupe/mock.rb +67 -29
- data/lib/dupe/network.rb +12 -4
- data/spec/lib_specs/active_resource_extensions_spec.rb +77 -1
- data/spec/lib_specs/database_spec.rb +30 -0
- data/spec/lib_specs/dupe_spec.rb +62 -4
- data/spec/lib_specs/mock_spec.rb +73 -24
- data/spec/lib_specs/network_spec.rb +27 -6
- metadata +2 -2
data/README.rdoc
CHANGED
@@ -38,6 +38,11 @@ It will also place example Dupe definitions in RAILS_ROOT/features/dupe/definiti
|
|
38
38
|
Lastly, it will add a load_dupe.rb file (that loads up the definitions and custom mocks) to RAILS_ROOT/features/support/load_dupe.rb
|
39
39
|
|
40
40
|
|
41
|
+
= Tutorial
|
42
|
+
|
43
|
+
Checkout the {dupe example application}[http://github.com/moonmaster9000/dupe_example_app] for a tutorial on cuking an application with
|
44
|
+
ActiveResource and Dupe.
|
45
|
+
|
41
46
|
= Features
|
42
47
|
|
43
48
|
==Creating resources
|
@@ -508,7 +513,7 @@ Now, when you try to create an Author without a name, it will respond with the a
|
|
508
513
|
irb# a = a.new?
|
509
514
|
==> true
|
510
515
|
|
511
|
-
Because the resource
|
516
|
+
Because our custom Post mock determined that the resource was invalid, Dupe did not mock the resource:
|
512
517
|
|
513
518
|
irb# Dupe.find(:authors)
|
514
519
|
==> []
|
@@ -524,11 +529,127 @@ When we create the Author with the required attributes, it will now be considere
|
|
524
529
|
irb# a.new?
|
525
530
|
==> false
|
526
531
|
|
527
|
-
|
532
|
+
Since our custom Post mock considered the resource valid, it went ahead and created the resource:
|
528
533
|
|
529
534
|
irb# Dupe.find(:authors)
|
530
535
|
==> [<#Duped::Author name="CS Lewis" id=1>]
|
531
536
|
|
537
|
+
|
538
|
+
===PUT requests
|
539
|
+
|
540
|
+
In ActiveResource, when you update a resource that already exists via the "save" method, it translates to a PUT request.
|
541
|
+
Dupe provides basic PUT intercept mocks out of the box, and like GET and POST mocks,
|
542
|
+
it allows you to override the default PUT intercept mock, and create new ones.
|
543
|
+
|
544
|
+
Let's again examine an "author" resource:
|
545
|
+
|
546
|
+
irb# Dupe.define :author
|
547
|
+
|
548
|
+
irb# class Author < ActiveResource::Base; self.site = ''; end
|
549
|
+
==> ""
|
550
|
+
|
551
|
+
irb# Author.create :name => "CS Lewis" # --> Dupe intercepts this POST request
|
552
|
+
==> #<Author:0x1a4ca58 @attributes={"name"=>"CS Lewis", "id"=>1}, @prefix_options={}>
|
553
|
+
|
554
|
+
irb# Dupe.find :authors
|
555
|
+
==> [<#Duped::Author name="CS Lewis" id=1>]
|
556
|
+
|
557
|
+
irb# a = Author.find 1 # --> Dupe intercepts this GET request
|
558
|
+
==> #<Author:0x1a4ca58 @attributes={"name"=>"CS Lewis", "id"=>1}, @prefix_options={}>
|
559
|
+
|
560
|
+
So far, we've created a resource (via dupe's POST intercept mocking), and we've also found the resource we create (via dupe's GET
|
561
|
+
intercept mocking). Now, let's attempt to update (PUT) the resource:
|
562
|
+
|
563
|
+
irb# a.name = "Frank Herbert"
|
564
|
+
|
565
|
+
irb# a.save # --> Dupe intercepts this PUT request
|
566
|
+
==> true
|
567
|
+
|
568
|
+
Dupe intercepted the PUT request that ActiveResource attempted to send, and updated the Duped resource accordingly:
|
569
|
+
|
570
|
+
irb# a
|
571
|
+
==> #<Author:0x1a4ca58 @attributes={"name"=>"Frank Herbert", "id"=>1}, @prefix_options={}>
|
572
|
+
|
573
|
+
irb# Dupe.find :authors
|
574
|
+
==> [<#Duped::Author name="Frank Herbert" id=1>]
|
575
|
+
|
576
|
+
You can also overwrite the default PUT intercept mock for your resource by using the "Put" method:
|
577
|
+
|
578
|
+
irb# Put %r{/authors/(\d+)\.xml} do |id, put_data|
|
579
|
+
raise Dupe::UnprocessableEntity.new(:name => " must be present.") unless put_data[:name]
|
580
|
+
Dupe.find(:author) {|a| a.id == id.to_i}.merge! put_data
|
581
|
+
end
|
582
|
+
==> #<Dupe::Network::PostMock:0x1a1afe4 @url_pattern=/\/authors\.xml/, @response=#<Proc:0x01a1b084@(irb):13>, @verb=:post>
|
583
|
+
|
584
|
+
Now, if we try to update our Author without a name, it will respond with the appropriate errors.
|
585
|
+
|
586
|
+
irb# Dupe.find :authors
|
587
|
+
==> [<#Duped::Author name="Frank Herbert" id=1>]
|
588
|
+
|
589
|
+
irb# a = Author.find 1 # --> Dupe intercepts this GET request
|
590
|
+
==> #<Author:0x1a4ca58 @attributes={"name"=>"Frank Herbert", "id"=>1}, @prefix_options={}>
|
591
|
+
|
592
|
+
irb# a.name = nil
|
593
|
+
|
594
|
+
irb# a.save
|
595
|
+
==> false
|
596
|
+
|
597
|
+
irb# a.errors.on_base
|
598
|
+
==> ["name must be present"]
|
599
|
+
|
600
|
+
Since our Put intercept mock raise the Dupe::UnprocessableEntity exception,
|
601
|
+
the underlying Duped record remains unchanged, just as we would expect the real service to have operated:
|
602
|
+
|
603
|
+
irb# Dupe.find :authors
|
604
|
+
==> [<#Duped::Author name="Frank Herbert" id=1>]
|
605
|
+
|
606
|
+
We can, of course, at this point still update the name to a non-nil value and attempt to save it again:
|
607
|
+
|
608
|
+
irb# a.name = "Matt Parker"
|
609
|
+
|
610
|
+
irb# a.save
|
611
|
+
==> true
|
612
|
+
|
613
|
+
irb# Dupe.find :authors
|
614
|
+
==> [<#Duped::Author name="Matt Parker" id=1>]
|
615
|
+
|
616
|
+
===DELETE requests
|
617
|
+
|
618
|
+
As you might have guessed, Dupe also supports DELETE intercept mocking (ActiveResource::Base#destroy):
|
619
|
+
|
620
|
+
irb# Dupe.define :author
|
621
|
+
|
622
|
+
irb# class Author < ActiveResource::Base; self.site = ''; end
|
623
|
+
==> ""
|
624
|
+
|
625
|
+
irb# Author.create :name => "CS Lewis" # --> Dupe intercepts this POST request
|
626
|
+
==> #<Author:0x1a4ca58 @attributes={"name"=>"CS Lewis", "id"=>1}, @prefix_options={}>
|
627
|
+
|
628
|
+
irb# Dupe.find :authors
|
629
|
+
==> [<#Duped::Author name="CS Lewis" id=1>]
|
630
|
+
|
631
|
+
irb# a = Author.find 1 # --> Dupe intercepts this GET request
|
632
|
+
==> #<Author:0x1a4ca58 @attributes={"name"=>"CS Lewis", "id"=>1}, @prefix_options={}>
|
633
|
+
|
634
|
+
irb# a.destroy
|
635
|
+
==> #<ActiveResource::Response:0x181c1c0 @body="", @message="200", @code=200, @headers={"Content-Length"=>"0"}
|
636
|
+
|
637
|
+
irb# Dupe.find :authors
|
638
|
+
==> []
|
639
|
+
|
640
|
+
And also, as you might have guessed, you can override the default DELETE intercept mock for a resource:
|
641
|
+
|
642
|
+
irb# Delete %r{/books/(\d+)\.xml} do |id|
|
643
|
+
puts "deleting the book with id #{id}"
|
644
|
+
Dupe.delete(:book) {|b| b.id == id.to_i}
|
645
|
+
end
|
646
|
+
|
647
|
+
irb# a = Author.create :name => "some author"
|
648
|
+
|
649
|
+
irb# a.destroy
|
650
|
+
==> "deleting the book with id 1"
|
651
|
+
|
652
|
+
|
532
653
|
== More
|
533
654
|
|
534
655
|
Consult the API documentation at http://moonmaster9000.github.com/dupe/api/
|
@@ -50,5 +50,48 @@ module ActiveResource #:nodoc:
|
|
50
50
|
end
|
51
51
|
response
|
52
52
|
end
|
53
|
+
|
54
|
+
def put(path, body = '', headers = {}) #:nodoc:
|
55
|
+
begin
|
56
|
+
response = request(:put, path, body.to_s, build_request_headers(headers, :put))
|
57
|
+
|
58
|
+
# if the request threw an exception
|
59
|
+
rescue
|
60
|
+
resource_hash = Hash.from_xml(body)
|
61
|
+
resource_hash = resource_hash[resource_hash.keys.first]
|
62
|
+
resource_hash = {} unless resource_hash.kind_of?(Hash)
|
63
|
+
resource_hash.symbolize_keys!
|
64
|
+
|
65
|
+
begin
|
66
|
+
error = false
|
67
|
+
mocked_response, path = Dupe.network.request(:put, path, resource_hash)
|
68
|
+
rescue Dupe::UnprocessableEntity => e
|
69
|
+
mocked_response = {:error => e.message.to_s}.to_xml(:root => 'errors')
|
70
|
+
error = true
|
71
|
+
end
|
72
|
+
ActiveResource::HttpMock.respond_to do |mock|
|
73
|
+
if error
|
74
|
+
mock.put(path, {}, mocked_response, 422, "Content-Type" => 'application/xml')
|
75
|
+
else
|
76
|
+
mock.put(path, {}, mocked_response, 204)
|
77
|
+
end
|
78
|
+
end
|
79
|
+
response = request(:put, path, body.to_s, build_request_headers(headers, :put))
|
80
|
+
ActiveResource::HttpMock.delete_mock(:put, path)
|
81
|
+
end
|
82
|
+
response
|
83
|
+
end
|
84
|
+
|
85
|
+
def delete(path, headers = {})
|
86
|
+
Dupe.network.request(:delete, path)
|
87
|
+
|
88
|
+
ActiveResource::HttpMock.respond_to do |mock|
|
89
|
+
mock.delete(path, {}, nil, 200)
|
90
|
+
end
|
91
|
+
response = request(:delete, path, build_request_headers(headers, :delete))
|
92
|
+
|
93
|
+
ActiveResource::HttpMock.delete_mock(:delete, path)
|
94
|
+
response
|
95
|
+
end
|
53
96
|
end
|
54
97
|
end
|
data/lib/dupe/custom_mocks.rb
CHANGED
@@ -105,4 +105,12 @@ end
|
|
105
105
|
|
106
106
|
def Post(url_pattern, &block)
|
107
107
|
Dupe.network.define_service_mock :post, url_pattern, block
|
108
|
-
end
|
108
|
+
end
|
109
|
+
|
110
|
+
def Put(url_pattern, &block)
|
111
|
+
Dupe.network.define_service_mock :put, url_pattern, block
|
112
|
+
end
|
113
|
+
|
114
|
+
def Delete(url_pattern, &block)
|
115
|
+
Dupe.network.define_service_mock :delete, url_pattern, block
|
116
|
+
end
|
data/lib/dupe/database.rb
CHANGED
@@ -12,6 +12,23 @@ class Dupe
|
|
12
12
|
def initialize
|
13
13
|
@tables = {}
|
14
14
|
end
|
15
|
+
|
16
|
+
# database.delete :books # --> would delete all books
|
17
|
+
# database.delete :book # --> would delete the first book record found
|
18
|
+
# database.delete :book, proc {|b| b.id < 10} # --> would delete all books found who's id is less than 10
|
19
|
+
# database.delete :books, proc {|b| b.id < 10} # --> would delete all books found who's id is less than 10
|
20
|
+
def delete(resource_name, conditions=nil)
|
21
|
+
model_name = resource_name.to_s.singularize.to_sym
|
22
|
+
raise StandardError, "Invalid DELETE operation: The resource #{model_name} has not been defined" unless @tables[model_name]
|
23
|
+
|
24
|
+
if conditions
|
25
|
+
@tables[model_name].reject!(&conditions)
|
26
|
+
elsif resource_name.singular?
|
27
|
+
@tables[model_name].shift
|
28
|
+
elsif resource_name.plural?
|
29
|
+
@tables[model_name] = []
|
30
|
+
end
|
31
|
+
end
|
15
32
|
|
16
33
|
# pass in a Dupe::Database::Record object, and this method will store the record
|
17
34
|
# in the appropriate table
|
@@ -49,4 +66,4 @@ class Dupe
|
|
49
66
|
end
|
50
67
|
|
51
68
|
end
|
52
|
-
end
|
69
|
+
end
|
data/lib/dupe/dupe.rb
CHANGED
@@ -8,7 +8,7 @@ class Dupe
|
|
8
8
|
attr_reader :sequences #:nodoc:
|
9
9
|
attr_reader :database #:nodoc:
|
10
10
|
|
11
|
-
# set this to "true" if you Dupe to spit out mocked requests
|
11
|
+
# set this to "true" if you want Dupe to spit out mocked requests
|
12
12
|
# after each of your cucumber scenario's run
|
13
13
|
attr_accessor :debug
|
14
14
|
|
@@ -184,6 +184,16 @@ class Dupe
|
|
184
184
|
%r{^#{model_name.to_s.titleize.constantize.prefix rescue '/'}#{model_name.to_s.pluralize}\\.xml$},
|
185
185
|
proc { |post_body| Dupe.create(:#{model_name.to_s}, post_body) }
|
186
186
|
)
|
187
|
+
network.define_service_mock(
|
188
|
+
:put,
|
189
|
+
%r{^#{model_name.to_s.titleize.constantize.prefix rescue '/'}#{model_name.to_s.pluralize}/(\\d+)\\.xml$},
|
190
|
+
proc { |id, put_data| Dupe.find(:#{model_name.to_s}) {|resource| resource.id == id.to_i}.merge!(put_data) }
|
191
|
+
)
|
192
|
+
network.define_service_mock(
|
193
|
+
:delete,
|
194
|
+
%r{^#{model_name.to_s.titleize.constantize.prefix rescue '/'}#{model_name.to_s.pluralize}/(\\d+)\\.xml$},
|
195
|
+
proc { |id| Dupe.delete(:#{model_name.to_s}) {|resource| resource.id == id.to_i} }
|
196
|
+
)
|
187
197
|
}
|
188
198
|
eval(mocks)
|
189
199
|
end
|
@@ -392,6 +402,10 @@ class Dupe
|
|
392
402
|
end
|
393
403
|
end
|
394
404
|
|
405
|
+
def delete(resource, &conditions)
|
406
|
+
database.delete resource, conditions
|
407
|
+
end
|
408
|
+
|
395
409
|
def sequence(name, &block)
|
396
410
|
sequences[name.to_sym] = Sequence.new 1, block
|
397
411
|
end
|
@@ -517,4 +531,4 @@ end
|
|
517
531
|
|
518
532
|
class Dupe
|
519
533
|
class UnprocessableEntity < StandardError; end
|
520
|
-
end
|
534
|
+
end
|
data/lib/dupe/mock.rb
CHANGED
@@ -1,24 +1,18 @@
|
|
1
1
|
class Dupe
|
2
2
|
class Network #:nodoc:
|
3
3
|
class Mock #:nodoc:
|
4
|
-
include Dupe::Network::RestValidation
|
5
|
-
|
6
4
|
class ResourceNotFoundError < StandardError; end
|
7
5
|
|
8
|
-
attr_reader :verb
|
9
6
|
attr_reader :url_pattern
|
10
7
|
attr_reader :response
|
11
8
|
|
12
|
-
def initialize(
|
13
|
-
validate_request_type verb
|
14
|
-
|
9
|
+
def initialize(url_pattern, response_proc=nil)
|
15
10
|
raise(
|
16
11
|
ArgumentError,
|
17
12
|
"The URL pattern parameter must be a type of regular expression."
|
18
13
|
) unless url_pattern.kind_of?(Regexp)
|
19
14
|
|
20
15
|
@response = response_proc || proc {}
|
21
|
-
@verb = verb
|
22
16
|
@url_pattern = url_pattern
|
23
17
|
end
|
24
18
|
|
@@ -39,7 +33,7 @@ class Dupe
|
|
39
33
|
end
|
40
34
|
|
41
35
|
def process_response(resp, url)
|
42
|
-
raise NotImplementedError, "
|
36
|
+
raise NotImplementedError, "When you extend Dupe::Network::Mock, you must implement the #process_response instance method."
|
43
37
|
end
|
44
38
|
end
|
45
39
|
end
|
@@ -50,18 +44,21 @@ class Dupe
|
|
50
44
|
class GetMock < Mock #:nodoc:
|
51
45
|
def process_response(resp, url)
|
52
46
|
case resp
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
47
|
+
|
48
|
+
when NilClass
|
49
|
+
raise ResourceNotFoundError, "Failed with 404: the request '#{url}' returned nil."
|
50
|
+
|
51
|
+
when Dupe::Database::Record
|
52
|
+
resp = resp.to_xml_safe(:root => resp.__model__.name.to_s)
|
53
|
+
|
54
|
+
when Array
|
55
|
+
if resp.empty?
|
56
|
+
resp = [].to_xml :root => 'results'
|
57
|
+
else
|
58
|
+
resp = resp.map {|r| HashPruner.prune(r)}.to_xml(:root => resp.first.__model__.name.to_s.pluralize)
|
59
|
+
end
|
63
60
|
end
|
64
|
-
Dupe.network.log.add_request
|
61
|
+
Dupe.network.log.add_request :get, url, resp
|
65
62
|
resp
|
66
63
|
end
|
67
64
|
end
|
@@ -71,19 +68,60 @@ end
|
|
71
68
|
class Dupe
|
72
69
|
class Network
|
73
70
|
class PostMock < Mock #:nodoc:
|
71
|
+
|
72
|
+
# returns a tuple representing the xml of the processed entity, plus the url to the entity.
|
74
73
|
def process_response(resp, url)
|
75
74
|
case resp
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
75
|
+
|
76
|
+
when NilClass
|
77
|
+
raise StandardError, "Failed with 500: the request '#{url}' returned nil."
|
78
|
+
|
79
|
+
when Dupe::Database::Record
|
80
|
+
new_path = "/#{resp.__model__.name.to_s.pluralize}/#{resp.id}.xml"
|
81
|
+
resp = resp.to_xml_safe(:root => resp.__model__.name.to_s)
|
82
|
+
Dupe.network.log.add_request :post, url, resp
|
83
|
+
return resp, new_path
|
84
|
+
|
85
|
+
else
|
86
|
+
raise StandardError, "Unknown PostMock Response. Your Post intercept mocks must return a Duped resource object or nil"
|
85
87
|
end
|
86
88
|
end
|
87
89
|
end
|
88
90
|
end
|
89
|
-
end
|
91
|
+
end
|
92
|
+
|
93
|
+
class Dupe
|
94
|
+
class Network
|
95
|
+
class PutMock < Mock #:nodoc:
|
96
|
+
|
97
|
+
# returns a tuple representing the xml of the processed entity, plus the url to the entity.
|
98
|
+
def process_response(resp, url)
|
99
|
+
case resp
|
100
|
+
|
101
|
+
when NilClass
|
102
|
+
raise StandardError, "Failed with 500: the request '#{url}' returned nil."
|
103
|
+
|
104
|
+
when Dupe::Database::Record
|
105
|
+
resp = nil
|
106
|
+
Dupe.network.log.add_request :put, url, ""
|
107
|
+
return resp, url
|
108
|
+
|
109
|
+
else
|
110
|
+
raise StandardError, "Unknown PutMock Response. Your Post intercept mocks must return a Duped resource object or nil"
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
class Dupe
|
118
|
+
class Network
|
119
|
+
class DeleteMock < Mock #:nodoc:
|
120
|
+
# logs the request
|
121
|
+
def process_response(resp, url)
|
122
|
+
Dupe.network.log.add_request :delete, url, ""
|
123
|
+
nil
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
data/lib/dupe/network.rb
CHANGED
@@ -21,15 +21,23 @@ class Dupe
|
|
21
21
|
validate_request_type verb
|
22
22
|
case verb
|
23
23
|
when :get
|
24
|
-
GetMock.new(
|
24
|
+
GetMock.new(url_pattern, response_proc).tap do |mock|
|
25
25
|
@mocks[verb] << mock
|
26
26
|
end
|
27
27
|
when :post
|
28
|
-
PostMock.new(
|
28
|
+
PostMock.new(url_pattern, response_proc).tap do |mock|
|
29
|
+
@mocks[verb].unshift mock
|
30
|
+
end
|
31
|
+
when :put
|
32
|
+
PutMock.new(url_pattern, response_proc).tap do |mock|
|
33
|
+
@mocks[verb].unshift mock
|
34
|
+
end
|
35
|
+
when :delete
|
36
|
+
DeleteMock.new(url_pattern, response_proc).tap do |mock|
|
29
37
|
@mocks[verb].unshift mock
|
30
38
|
end
|
31
39
|
else
|
32
|
-
raise StandardError, "Dupe does not
|
40
|
+
raise StandardError, "Dupe does not support mocking #{verb.to_s.upcase} requests."
|
33
41
|
end
|
34
42
|
end
|
35
43
|
|
@@ -45,4 +53,4 @@ class Dupe
|
|
45
53
|
end
|
46
54
|
|
47
55
|
end
|
48
|
-
end
|
56
|
+
end
|
@@ -62,4 +62,80 @@ describe ActiveResource::Connection do
|
|
62
62
|
b.errors.should be_empty
|
63
63
|
end
|
64
64
|
end
|
65
|
-
|
65
|
+
|
66
|
+
describe "#put" do
|
67
|
+
before do
|
68
|
+
@book = Dupe.create :book, :label => 'rooby', :title => 'Rooby'
|
69
|
+
class Book < ActiveResource::Base
|
70
|
+
self.site = ''
|
71
|
+
end
|
72
|
+
@ar_book = Book.find(1)
|
73
|
+
end
|
74
|
+
|
75
|
+
it "should pass a request off to the Dupe network if the original request failed" do
|
76
|
+
Dupe.network.should_receive(:request).with(:put, '/books/1.xml', Hash.from_xml(@book.merge(:title => "Rails!").to_xml(:root => 'book'))["book"].symbolize_keys!).once
|
77
|
+
@ar_book.title = 'Rails!'
|
78
|
+
@ar_book.save
|
79
|
+
end
|
80
|
+
|
81
|
+
it "should parse the xml and turn the result into active resource objects" do
|
82
|
+
@book.title.should == "Rooby"
|
83
|
+
@ar_book.title = "Rails!"
|
84
|
+
@ar_book.save
|
85
|
+
@ar_book.new?.should == false
|
86
|
+
@ar_book.valid?.should == true
|
87
|
+
@ar_book.id.should == 1
|
88
|
+
@ar_book.label.should == "rooby"
|
89
|
+
@book.title.should == "Rails!"
|
90
|
+
@book.id.should == 1
|
91
|
+
@book.label.should == 'rooby'
|
92
|
+
end
|
93
|
+
|
94
|
+
it "should make ActiveResource throw an unprocessable entity exception if our Put mock throws a Dupe::UnprocessableEntity exception" do
|
95
|
+
Put %r{/books/(\d+)\.xml} do |id, put_data|
|
96
|
+
raise Dupe::UnprocessableEntity.new(:title => " must be present.") unless put_data[:title]
|
97
|
+
Dupe.find(:book) {|b| b.id == id.to_i}.merge!(put_data)
|
98
|
+
end
|
99
|
+
|
100
|
+
@ar_book.title = nil
|
101
|
+
@ar_book.save.should == false
|
102
|
+
@ar_book.errors.on_base.should_not be_empty
|
103
|
+
|
104
|
+
@ar_book.title = "Rails!"
|
105
|
+
@ar_book.save.should == true
|
106
|
+
# the following line should be true, were it not for a bug in active_resource 2.3.3 - 2.3.5
|
107
|
+
# i reported the bug here: https://rails.lighthouseapp.com/projects/8994-ruby-on-rails/tickets/4169-activeresourcebasesave-put-doesnt-clear-out-errors
|
108
|
+
# @ar_book.errors.should be_empty
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
describe "#delete" do
|
113
|
+
before do
|
114
|
+
@book = Dupe.create :book, :label => 'rooby', :title => 'Rooby'
|
115
|
+
class Book < ActiveResource::Base
|
116
|
+
self.site = ''
|
117
|
+
end
|
118
|
+
@ar_book = Book.find(1)
|
119
|
+
end
|
120
|
+
|
121
|
+
it "should pass a request off to the Dupe network if the original request failed" do
|
122
|
+
Dupe.network.should_receive(:request).with(:delete, '/books/1.xml').once
|
123
|
+
@ar_book.destroy
|
124
|
+
end
|
125
|
+
|
126
|
+
it "trigger a Dupe.delete to delete the mocked resource from the duped database" do
|
127
|
+
Dupe.find(:books).length.should == 1
|
128
|
+
@ar_book.destroy
|
129
|
+
Dupe.find(:books).length.should == 0
|
130
|
+
end
|
131
|
+
|
132
|
+
it "should allow you to override the default DELETE intercept mock" do
|
133
|
+
Delete %r{/books/(\d+)\.xml} do |id|
|
134
|
+
raise StandardError, "Testing Delete override"
|
135
|
+
end
|
136
|
+
|
137
|
+
proc {@ar_book.destroy}.should raise_error(StandardError, "Testing Delete override")
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
end
|
@@ -16,6 +16,36 @@ describe Dupe::Database do
|
|
16
16
|
end
|
17
17
|
end
|
18
18
|
|
19
|
+
describe "delete" do
|
20
|
+
before do
|
21
|
+
Dupe.stub 10, :books
|
22
|
+
end
|
23
|
+
|
24
|
+
it "should delete the first record found if the resource name is singular and there is no conditions proc" do
|
25
|
+
Dupe.find(:books).length.should == 10
|
26
|
+
Dupe.database.delete :book
|
27
|
+
Dupe.find(:books).length.should == 9
|
28
|
+
end
|
29
|
+
|
30
|
+
it "should delete all records if the resource name is plural and there is no conditions proc" do
|
31
|
+
Dupe.find(:books).length.should == 10
|
32
|
+
Dupe.database.delete :books
|
33
|
+
Dupe.find(:books).length.should == 0
|
34
|
+
end
|
35
|
+
|
36
|
+
it "should delete all matching records if there is a conditions proc and the resource name is singular" do
|
37
|
+
Dupe.find(:books).length.should == 10
|
38
|
+
Dupe.database.delete :book, proc {|b| b.id < 3}
|
39
|
+
Dupe.find(:books).length.should == 8
|
40
|
+
end
|
41
|
+
|
42
|
+
it "should delete all matching records if there is a conditions proc and the resource name is plural" do
|
43
|
+
Dupe.find(:books).length.should == 10
|
44
|
+
Dupe.database.delete :books, proc {|b| b.id < 3}
|
45
|
+
Dupe.find(:books).length.should == 8
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
19
49
|
describe "insert" do
|
20
50
|
before do
|
21
51
|
Dupe.define :book
|
data/spec/lib_specs/dupe_spec.rb
CHANGED
@@ -173,15 +173,56 @@ describe Dupe do
|
|
173
173
|
Dupe.network.mocks[:get].length.should == 2
|
174
174
|
|
175
175
|
find_all_mock = Dupe.network.mocks[:get].first
|
176
|
-
find_all_mock.
|
176
|
+
find_all_mock.class.should == Dupe::Network::GetMock
|
177
177
|
find_all_mock.url_pattern.should == %r{^/books\.xml$}
|
178
178
|
find_all_mock.mocked_response('/books.xml').should == Dupe.find(:books).to_xml(:root => 'books')
|
179
179
|
|
180
180
|
find_one_mock = Dupe.network.mocks[:get].last
|
181
|
-
find_one_mock.
|
181
|
+
find_one_mock.class.should == Dupe::Network::GetMock
|
182
182
|
find_one_mock.url_pattern.should == %r{^/books/(\d+)\.xml$}
|
183
183
|
find_one_mock.mocked_response('/books/1.xml').should == Dupe.find(:book).to_xml(:root => 'book')
|
184
184
|
end
|
185
|
+
|
186
|
+
it "should add a POST (create resource) mock to the network" do
|
187
|
+
Dupe.network.mocks[:post].should be_empty
|
188
|
+
Dupe.define :book
|
189
|
+
Dupe.network.mocks[:post].should_not be_empty
|
190
|
+
Dupe.network.mocks[:post].length.should == 1
|
191
|
+
|
192
|
+
post_mock = Dupe.network.mocks[:post].first
|
193
|
+
post_mock.class.should == Dupe::Network::PostMock
|
194
|
+
post_mock.url_pattern.should == %r{^/books\.xml$}
|
195
|
+
resp, url = post_mock.mocked_response('/books.xml', {:title => "Rooby"})
|
196
|
+
resp.should == Dupe.find(:book).to_xml(:root => 'book')
|
197
|
+
url.should == "/books/1.xml"
|
198
|
+
end
|
199
|
+
|
200
|
+
it "should add a PUT (update resource) mock to the network" do
|
201
|
+
Dupe.network.mocks[:put].should be_empty
|
202
|
+
book = Dupe.create :book, :title => 'Rooby!'
|
203
|
+
Dupe.network.mocks[:put].should_not be_empty
|
204
|
+
Dupe.network.mocks[:put].length.should == 1
|
205
|
+
|
206
|
+
put_mock = Dupe.network.mocks[:put].first
|
207
|
+
put_mock.class.should == Dupe::Network::PutMock
|
208
|
+
put_mock.url_pattern.should == %r{^/books/(\d+)\.xml$}
|
209
|
+
resp, url = put_mock.mocked_response('/books/1.xml', {:title => "Rails!"})
|
210
|
+
resp.should == nil
|
211
|
+
url.should == "/books/1.xml"
|
212
|
+
book.title.should == "Rails!"
|
213
|
+
end
|
214
|
+
|
215
|
+
it "should add a DELETE mock to the network" do
|
216
|
+
Dupe.network.mocks[:delete].should be_empty
|
217
|
+
book = Dupe.create :book, :title => 'Rooby!'
|
218
|
+
Dupe.network.mocks[:delete].should_not be_empty
|
219
|
+
Dupe.network.mocks[:delete].length.should == 1
|
220
|
+
|
221
|
+
delete_mock = Dupe.network.mocks[:delete].first
|
222
|
+
delete_mock.class.should == Dupe::Network::DeleteMock
|
223
|
+
delete_mock.url_pattern.should == %r{^/books/(\d+)\.xml$}
|
224
|
+
end
|
225
|
+
|
185
226
|
|
186
227
|
it "should honor ActiveResource site prefix's for the find(:all) and find(<id>) mocks" do
|
187
228
|
Dupe.network.mocks[:get].should be_empty
|
@@ -191,12 +232,12 @@ describe Dupe do
|
|
191
232
|
Dupe.network.mocks[:get].length.should == 2
|
192
233
|
|
193
234
|
find_all_mock = Dupe.network.mocks[:get].first
|
194
|
-
find_all_mock.
|
235
|
+
find_all_mock.class.should == Dupe::Network::GetMock
|
195
236
|
find_all_mock.url_pattern.should == %r{^/book_services/authors\.xml$}
|
196
237
|
find_all_mock.mocked_response('/book_services/authors.xml').should == Dupe.find(:authors).to_xml(:root => 'authors')
|
197
238
|
|
198
239
|
find_one_mock = Dupe.network.mocks[:get].last
|
199
|
-
find_one_mock.
|
240
|
+
find_one_mock.class.should == Dupe::Network::GetMock
|
200
241
|
find_one_mock.url_pattern.should == %r{^/book_services/authors/(\d+)\.xml$}
|
201
242
|
find_one_mock.mocked_response('/book_services/authors/1.xml').should == Dupe.find(:author).to_xml(:root => 'author')
|
202
243
|
end
|
@@ -461,4 +502,21 @@ describe Dupe do
|
|
461
502
|
b2.genre.name.should == 'Science Fiction'
|
462
503
|
end
|
463
504
|
end
|
505
|
+
|
506
|
+
describe "##delete" do
|
507
|
+
it "should remove any resources that match the conditions provided in the block" do
|
508
|
+
Dupe.stub 10, :authors
|
509
|
+
Dupe.find(:authors).length.should == 10
|
510
|
+
Dupe.delete :author
|
511
|
+
Dupe.find(:authors).length.should == 9
|
512
|
+
Dupe.delete :authors
|
513
|
+
Dupe.find(:authors).length.should == 0
|
514
|
+
Dupe.create :author, :name => 'CS Lewis'
|
515
|
+
Dupe.create :author, :name => 'Robert Lewis Stevenson'
|
516
|
+
Dupe.create :author, :name => 'Frank Herbert'
|
517
|
+
Dupe.delete(:author) {|a| a.name.match /Lewis/}
|
518
|
+
Dupe.find(:authors).length.should == 1
|
519
|
+
Dupe.find(:authors).first.name.should == 'Frank Herbert'
|
520
|
+
end
|
521
|
+
end
|
464
522
|
end
|
data/spec/lib_specs/mock_spec.rb
CHANGED
@@ -6,26 +6,17 @@ describe Dupe::Network::Mock do
|
|
6
6
|
end
|
7
7
|
|
8
8
|
describe "new" do
|
9
|
-
it "should require a valid REST type" do
|
10
|
-
proc { Dupe::Network::Mock.new :unknown, /\//, proc {} }.should raise_error(Dupe::Network::UnknownRestVerbError)
|
11
|
-
proc { Dupe::Network::Mock.new :get, /\//, proc {} }.should_not raise_error
|
12
|
-
proc { Dupe::Network::Mock.new :post, /\//, proc {} }.should_not raise_error
|
13
|
-
proc { Dupe::Network::Mock.new :put, /\//, proc {} }.should_not raise_error
|
14
|
-
proc { Dupe::Network::Mock.new :delete, /\//, proc {} }.should_not raise_error
|
15
|
-
end
|
16
|
-
|
17
9
|
it "should require the url be a kind of regular expression" do
|
18
|
-
proc { Dupe::Network::Mock.new
|
10
|
+
proc { Dupe::Network::Mock.new '', proc {} }.should raise_error(
|
19
11
|
ArgumentError,
|
20
12
|
"The URL pattern parameter must be a type of regular expression."
|
21
13
|
)
|
22
14
|
end
|
23
15
|
|
24
|
-
it "should set the
|
16
|
+
it "should set the, @url, and @response parameters accordingly" do
|
25
17
|
url_pattern = /\//
|
26
18
|
response = proc {}
|
27
|
-
mock = Dupe::Network::Mock.new
|
28
|
-
mock.verb.should == :get
|
19
|
+
mock = Dupe::Network::Mock.new url_pattern, response
|
29
20
|
mock.url_pattern.should == url_pattern
|
30
21
|
mock.response.should == response
|
31
22
|
end
|
@@ -35,7 +26,7 @@ describe Dupe::Network::Mock do
|
|
35
26
|
it "should determine if a given string matches the mock's url pattern" do
|
36
27
|
url = %r{/blogs/(\d+).xml}
|
37
28
|
response = proc {}
|
38
|
-
mock = Dupe::Network::Mock.new
|
29
|
+
mock = Dupe::Network::Mock.new url, response
|
39
30
|
mock.match?('/blogs/1.xml').should == true
|
40
31
|
mock.match?('/bogs/1.xml').should == false
|
41
32
|
end
|
@@ -53,13 +44,13 @@ describe Dupe::Network::GetMock do
|
|
53
44
|
url_pattern = %r{/books/(\d+)\.xml}
|
54
45
|
response = proc {|id| Dupe.find(:book) {|b| b.id == id.to_i}}
|
55
46
|
book = Dupe.create :book
|
56
|
-
mock = Dupe::Network::GetMock.new
|
47
|
+
mock = Dupe::Network::GetMock.new url_pattern, response
|
57
48
|
mock.mocked_response('/books/1.xml').should == book.to_xml(:root => 'book')
|
58
49
|
|
59
50
|
proc { mock.mocked_response('/books/2.xml') }.should raise_error(Dupe::Network::GetMock::ResourceNotFoundError)
|
60
51
|
|
61
52
|
Dupe.define :author
|
62
|
-
mock = Dupe::Network::GetMock.new
|
53
|
+
mock = Dupe::Network::GetMock.new %r{/authors\.xml$}, proc {Dupe.find :authors}
|
63
54
|
mock.mocked_response('/authors.xml').should == [].to_xml(:root => 'results')
|
64
55
|
end
|
65
56
|
|
@@ -67,7 +58,7 @@ describe Dupe::Network::GetMock do
|
|
67
58
|
url_pattern = %r{/books/([a-zA-Z0-9-]+)\.xml}
|
68
59
|
response = proc {|label| Dupe.find(:book) {|b| b.label == label}}
|
69
60
|
book = Dupe.create :book, :label => 'rooby'
|
70
|
-
mock = Dupe::Network::GetMock.new
|
61
|
+
mock = Dupe::Network::GetMock.new url_pattern, response
|
71
62
|
Dupe.network.log.requests.length.should == 0
|
72
63
|
mock.mocked_response('/books/rooby.xml')
|
73
64
|
Dupe.network.log.requests.length.should == 1
|
@@ -79,7 +70,7 @@ describe Dupe::Network::GetMock do
|
|
79
70
|
url_pattern = %r{/authors/(\d+)\.xml}
|
80
71
|
response = proc { |id| Dupe.find(:author) {|a| a.id == id.to_i}}
|
81
72
|
Dupe.define :author
|
82
|
-
mock = Dupe::Network::GetMock.new
|
73
|
+
mock = Dupe::Network::GetMock.new url_pattern, response
|
83
74
|
proc {mock.mocked_response('/authors/1.xml')}.should raise_error(Dupe::Network::GetMock::ResourceNotFoundError)
|
84
75
|
end
|
85
76
|
end
|
@@ -87,13 +78,13 @@ describe Dupe::Network::GetMock do
|
|
87
78
|
describe "on a mock object whose response returns an empty array" do
|
88
79
|
it "should convert the empty array to an xml array record set with root 'results'" do
|
89
80
|
Dupe.define :author
|
90
|
-
mock = Dupe::Network::GetMock.new
|
81
|
+
mock = Dupe::Network::GetMock.new %r{/authors\.xml$}, proc {Dupe.find :authors}
|
91
82
|
mock.mocked_response('/authors.xml').should == [].to_xml(:root => 'results')
|
92
83
|
end
|
93
84
|
|
94
85
|
it "should add a request to the Dupe::Network#log" do
|
95
86
|
Dupe.define :author
|
96
|
-
mock = Dupe::Network::GetMock.new
|
87
|
+
mock = Dupe::Network::GetMock.new %r{/authors\.xml$}, proc {Dupe.find :authors}
|
97
88
|
Dupe.network.log.requests.length.should == 0
|
98
89
|
mock.mocked_response('/authors.xml')
|
99
90
|
Dupe.network.log.requests.length.should == 1
|
@@ -103,13 +94,13 @@ describe Dupe::Network::GetMock do
|
|
103
94
|
describe "on a mock object whose response returns an array of duped records" do
|
104
95
|
it "should convert the array to xml" do
|
105
96
|
Dupe.create :author
|
106
|
-
mock = Dupe::Network::GetMock.new
|
97
|
+
mock = Dupe::Network::GetMock.new %r{/authors\.xml$}, proc {Dupe.find :authors}
|
107
98
|
mock.mocked_response('/authors.xml').should == Dupe.find(:authors).to_xml(:root => 'authors')
|
108
99
|
end
|
109
100
|
|
110
101
|
it "should add a request to the Dupe::Network#log" do
|
111
102
|
Dupe.create :author
|
112
|
-
mock = Dupe::Network::GetMock.new
|
103
|
+
mock = Dupe::Network::GetMock.new %r{/authors\.xml$}, proc {Dupe.find :authors}
|
113
104
|
Dupe.network.log.requests.length.should == 0
|
114
105
|
mock.mocked_response('/authors.xml')
|
115
106
|
Dupe.network.log.requests.length.should == 1
|
@@ -127,7 +118,7 @@ describe Dupe::Network::PostMock do
|
|
127
118
|
describe "on a mock object whose response returns a location of a new record" do
|
128
119
|
it "should convert the new post to xml" do
|
129
120
|
Dupe.define :author
|
130
|
-
mock = Dupe::Network::PostMock.new
|
121
|
+
mock = Dupe::Network::PostMock.new %r{/authors\.xml$}, proc {|post_data| Dupe.create(:author, post_data)}
|
131
122
|
resp, url = mock.mocked_response('/authors.xml', {:name => "Rachel"})
|
132
123
|
resp.should == Dupe.find(:authors).first.to_xml_safe(:root => 'author')
|
133
124
|
url.should == "/authors/1.xml"
|
@@ -135,11 +126,69 @@ describe Dupe::Network::PostMock do
|
|
135
126
|
|
136
127
|
it "should add a request to the Dupe::Network#log" do
|
137
128
|
Dupe.define :author
|
138
|
-
mock = Dupe::Network::PostMock.new
|
129
|
+
mock = Dupe::Network::PostMock.new %r{/authors\.xml$}, proc {|post_data| Dupe.create(:author, post_data)}
|
139
130
|
Dupe.network.log.requests.length.should == 0
|
140
131
|
mock.mocked_response('/authors.xml', {:name => "Rachel"})
|
141
132
|
Dupe.network.log.requests.length.should == 1
|
142
133
|
end
|
143
134
|
end
|
144
135
|
end
|
145
|
-
end
|
136
|
+
end
|
137
|
+
|
138
|
+
describe Dupe::Network::PutMock do
|
139
|
+
before do
|
140
|
+
Dupe.reset
|
141
|
+
end
|
142
|
+
|
143
|
+
describe "mocked_response" do
|
144
|
+
describe "on a mock object whose response returns a location of a new record" do
|
145
|
+
before do
|
146
|
+
Dupe.define :author
|
147
|
+
@a = Dupe.create :author, :name => "Matt"
|
148
|
+
@mock = Dupe::Network::PutMock.new %r{/authors/(\d+)\.xml$}, proc {|id, put_data| Dupe.find(:author) {|a| a.id == id.to_i}.merge!(put_data)}
|
149
|
+
end
|
150
|
+
|
151
|
+
it "should convert the put to xml" do
|
152
|
+
resp, url = @mock.mocked_response('/authors/1.xml', {:name => "Rachel"})
|
153
|
+
resp.should == nil
|
154
|
+
@a.name.should == "Rachel"
|
155
|
+
url.should == "/authors/1.xml"
|
156
|
+
end
|
157
|
+
|
158
|
+
it "should add a request to the Dupe::Network#log" do
|
159
|
+
Dupe.network.log.requests.length.should == 0
|
160
|
+
@mock.mocked_response('/authors/1.xml', {:name => "Rachel"})
|
161
|
+
Dupe.network.log.requests.length.should == 1
|
162
|
+
end
|
163
|
+
end
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
167
|
+
describe Dupe::Network::DeleteMock do
|
168
|
+
before do
|
169
|
+
Dupe.reset
|
170
|
+
end
|
171
|
+
|
172
|
+
describe "mocked_response" do
|
173
|
+
describe "on a mock object whose response returns a location of a new record" do
|
174
|
+
before do
|
175
|
+
Dupe.define :author
|
176
|
+
@a = Dupe.create :author, :name => "Matt"
|
177
|
+
@mock = Dupe::Network::DeleteMock.new %r{/authors/(\d+)\.xml$}, proc {|id| Dupe.delete(:author) {|a| a.id == id.to_i}}
|
178
|
+
end
|
179
|
+
|
180
|
+
it "should convert the put to xml" do
|
181
|
+
Dupe.find(:authors).length.should == 1
|
182
|
+
resp = @mock.mocked_response('/authors/1.xml')
|
183
|
+
resp.should == nil
|
184
|
+
Dupe.find(:authors).length.should == 0
|
185
|
+
end
|
186
|
+
|
187
|
+
it "should add a request to the Dupe::Network#log" do
|
188
|
+
Dupe.network.log.requests.length.should == 0
|
189
|
+
@mock.mocked_response('/authors/1.xml')
|
190
|
+
Dupe.network.log.requests.length.should == 1
|
191
|
+
end
|
192
|
+
end
|
193
|
+
end
|
194
|
+
end
|
@@ -68,7 +68,7 @@ describe Dupe::Network do
|
|
68
68
|
proc { @network.define_service_mock :invalid_rest_verb, // }.should raise_error(Dupe::Network::UnknownRestVerbError)
|
69
69
|
proc { @network.define_service_mock :get, // }.should_not raise_error(Dupe::Network::UnknownRestVerbError)
|
70
70
|
proc { @network.define_service_mock :post, // }.should_not raise_error(Dupe::Network::UnknownRestVerbError)
|
71
|
-
|
71
|
+
proc { @network.define_service_mock :put, // }.should_not raise_error(Dupe::Network::UnknownRestVerbError)
|
72
72
|
end
|
73
73
|
|
74
74
|
it "should require a valid Regexp url pattern" do
|
@@ -76,7 +76,6 @@ describe Dupe::Network do
|
|
76
76
|
proc { @network.define_service_mock :post, 'not a regular expression' }.should raise_error(ArgumentError)
|
77
77
|
proc { @network.define_service_mock :get, // }.should_not raise_error
|
78
78
|
proc { @network.define_service_mock :post, // }.should_not raise_error
|
79
|
-
|
80
79
|
end
|
81
80
|
|
82
81
|
it "should create and return a new get service mock when given valid parameters" do
|
@@ -86,7 +85,7 @@ describe Dupe::Network do
|
|
86
85
|
@network.mocks[:get].should be_empty
|
87
86
|
mock = @network.define_service_mock verb, pattern, response
|
88
87
|
@network.mocks[:get].should_not be_empty
|
89
|
-
@network.mocks[:
|
88
|
+
@network.mocks[:get].first.class.should == Dupe::Network::GetMock
|
90
89
|
@network.mocks[:get].length.should == 1
|
91
90
|
@network.mocks[:get].first.should == mock
|
92
91
|
end
|
@@ -98,12 +97,34 @@ describe Dupe::Network do
|
|
98
97
|
@network.mocks[:post].should be_empty
|
99
98
|
mock = @network.define_service_mock verb, pattern, response
|
100
99
|
@network.mocks[:post].should_not be_empty
|
101
|
-
@network.mocks[:post].first.class ==
|
100
|
+
@network.mocks[:post].first.class.should == Dupe::Network::PostMock
|
102
101
|
@network.mocks[:post].length.should == 1
|
103
102
|
@network.mocks[:post].first.should == mock
|
104
103
|
end
|
105
|
-
|
106
104
|
|
105
|
+
it "should create and return a new put service mock when given valid parameters" do
|
106
|
+
verb = :put
|
107
|
+
pattern = //
|
108
|
+
response = proc { 'test' }
|
109
|
+
@network.mocks[:put].should be_empty
|
110
|
+
mock = @network.define_service_mock verb, pattern, response
|
111
|
+
@network.mocks[:put].should_not be_empty
|
112
|
+
@network.mocks[:put].first.class.should == Dupe::Network::PutMock
|
113
|
+
@network.mocks[:put].length.should == 1
|
114
|
+
@network.mocks[:put].first.should == mock
|
115
|
+
end
|
116
|
+
|
117
|
+
it "should create and return a new delete service mock when given valid parameters" do
|
118
|
+
verb = :delete
|
119
|
+
pattern = //
|
120
|
+
response = proc { 'test' }
|
121
|
+
@network.mocks[:delete].should be_empty
|
122
|
+
mock = @network.define_service_mock verb, pattern, response
|
123
|
+
@network.mocks[:delete].should_not be_empty
|
124
|
+
@network.mocks[:delete].first.class.should == Dupe::Network::DeleteMock
|
125
|
+
@network.mocks[:delete].length.should == 1
|
126
|
+
@network.mocks[:delete].first.should == mock
|
127
|
+
end
|
107
128
|
end
|
108
129
|
|
109
|
-
end
|
130
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: dupe
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.5.
|
4
|
+
version: 0.5.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Matt Parker
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2010-03-
|
12
|
+
date: 2010-03-14 00:00:00 -05:00
|
13
13
|
default_executable:
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|