superdupe 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README.markdown +10 -0
- data/lib/superdupe/active_resource_extensions.rb +161 -0
- data/lib/superdupe/attribute_template.rb +71 -0
- data/lib/superdupe/cucumber_hooks.rb +16 -0
- data/lib/superdupe/custom_mocks.rb +116 -0
- data/lib/superdupe/database.rb +69 -0
- data/lib/superdupe/dupe.rb +534 -0
- data/lib/superdupe/hash_pruner.rb +37 -0
- data/lib/superdupe/log.rb +38 -0
- data/lib/superdupe/mock.rb +127 -0
- data/lib/superdupe/model.rb +59 -0
- data/lib/superdupe/network.rb +56 -0
- data/lib/superdupe/record.rb +42 -0
- data/lib/superdupe/rest_validation.rb +16 -0
- data/lib/superdupe/schema.rb +52 -0
- data/lib/superdupe/sequence.rb +20 -0
- data/lib/superdupe/singular_plural_detection.rb +9 -0
- data/lib/superdupe/string.rb +7 -0
- data/lib/superdupe/symbol.rb +3 -0
- data/lib/superdupe.rb +20 -0
- data/rails_generators/dupe/dupe_generator.rb +20 -0
- data/rails_generators/dupe/templates/custom_mocks.rb +4 -0
- data/rails_generators/dupe/templates/definitions.rb +9 -0
- data/rails_generators/dupe/templates/load_dupe.rb +9 -0
- data/spec/lib_specs/active_resource_extensions_spec.rb +141 -0
- data/spec/lib_specs/attribute_template_spec.rb +173 -0
- data/spec/lib_specs/database_spec.rb +163 -0
- data/spec/lib_specs/dupe_spec.rb +522 -0
- data/spec/lib_specs/hash_pruner_spec.rb +73 -0
- data/spec/lib_specs/log_spec.rb +78 -0
- data/spec/lib_specs/logged_request_spec.rb +22 -0
- data/spec/lib_specs/mock_definitions_spec.rb +58 -0
- data/spec/lib_specs/mock_spec.rb +194 -0
- data/spec/lib_specs/model_spec.rb +95 -0
- data/spec/lib_specs/network_spec.rb +130 -0
- data/spec/lib_specs/record_spec.rb +70 -0
- data/spec/lib_specs/rest_validation_spec.rb +17 -0
- data/spec/lib_specs/schema_spec.rb +109 -0
- data/spec/lib_specs/sequence_spec.rb +39 -0
- data/spec/lib_specs/string_spec.rb +31 -0
- data/spec/lib_specs/symbol_spec.rb +17 -0
- data/spec/spec_helper.rb +8 -0
- metadata +142 -0
@@ -0,0 +1,58 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
|
2
|
+
|
3
|
+
describe "Mock Definition Methods" do
|
4
|
+
before do
|
5
|
+
Dupe.reset
|
6
|
+
end
|
7
|
+
|
8
|
+
describe "Get" do
|
9
|
+
it "should require a url pattern that is a regex" do
|
10
|
+
proc { Get() }.should raise_error(ArgumentError)
|
11
|
+
proc { Get 'not a regexp' }.should raise_error(ArgumentError)
|
12
|
+
proc { Get %r{/some_url} }.should_not raise_error
|
13
|
+
end
|
14
|
+
|
15
|
+
it "should create and return a Dupe::Network::Mock of type :get" do
|
16
|
+
Dupe.network.mocks[:get].should be_empty
|
17
|
+
@book = Dupe.create :book, :label => 'rooby'
|
18
|
+
Dupe.network.mocks[:get].should_not be_empty
|
19
|
+
Dupe.network.mocks[:get].length.should == 2
|
20
|
+
|
21
|
+
mock = Get %r{/books/([^&]+)\.xml} do |label|
|
22
|
+
Dupe.find(:book) {|b| b.label == label}
|
23
|
+
end
|
24
|
+
|
25
|
+
Dupe.network.mocks[:get].length.should == 3
|
26
|
+
Dupe.network.mocks[:get].last.should == mock
|
27
|
+
Dupe.network.mocks[:get].last.url_pattern.should == %r{/books/([^&]+)\.xml}
|
28
|
+
book = Dupe.find(:book)
|
29
|
+
Dupe.network.request(:get, '/books/rooby.xml').should == book.to_xml_safe(:root => 'book')
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
describe "Post" do
|
34
|
+
it "should require a url pattern that is a regex" do
|
35
|
+
proc { Post() }.should raise_error(ArgumentError)
|
36
|
+
proc { Post 'not a regexp' }.should raise_error(ArgumentError)
|
37
|
+
proc { Post %r{/some_url} }.should_not raise_error
|
38
|
+
end
|
39
|
+
|
40
|
+
it "should create and return a Dupe::Network::Mock of type :post" do
|
41
|
+
@book = Dupe.create :book, :label => 'rooby'
|
42
|
+
Dupe.network.mocks[:post].should_not be_empty
|
43
|
+
Dupe.network.mocks[:post].length.should == 1
|
44
|
+
|
45
|
+
mock = Post %r{/books\.xml} do |post_data|
|
46
|
+
Dupe.create(:book, post_data)
|
47
|
+
end
|
48
|
+
|
49
|
+
Dupe.network.mocks[:post].length.should == 2
|
50
|
+
Dupe.network.mocks[:post].first.should == mock
|
51
|
+
Dupe.network.mocks[:post].first.url_pattern.should == %r{/books\.xml}
|
52
|
+
book_post = Dupe.create(:book, {:title => "Rooby", :label => "rooby"})
|
53
|
+
book_post.delete(:id)
|
54
|
+
book_response = Dupe.create(:book, {:title => "Rooby", :label => "rooby"})
|
55
|
+
Dupe.network.request(:post, '/books.xml', book_post).should == [Dupe.find(:book) {|b| b.id == 4}.to_xml_safe(:root => 'book'), "/books/4.xml"]
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,194 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
|
2
|
+
|
3
|
+
describe Dupe::Network::Mock do
|
4
|
+
before do
|
5
|
+
Dupe.reset
|
6
|
+
end
|
7
|
+
|
8
|
+
describe "new" do
|
9
|
+
it "should require the url be a kind of regular expression" do
|
10
|
+
proc { Dupe::Network::Mock.new '', proc {} }.should raise_error(
|
11
|
+
ArgumentError,
|
12
|
+
"The URL pattern parameter must be a type of regular expression."
|
13
|
+
)
|
14
|
+
end
|
15
|
+
|
16
|
+
it "should set the, @url, and @response parameters accordingly" do
|
17
|
+
url_pattern = /\//
|
18
|
+
response = proc {}
|
19
|
+
mock = Dupe::Network::Mock.new url_pattern, response
|
20
|
+
mock.url_pattern.should == url_pattern
|
21
|
+
mock.response.should == response
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
describe "match?" do
|
26
|
+
it "should determine if a given string matches the mock's url pattern" do
|
27
|
+
url = %r{/blogs/(\d+).xml}
|
28
|
+
response = proc {}
|
29
|
+
mock = Dupe::Network::Mock.new url, response
|
30
|
+
mock.match?('/blogs/1.xml').should == true
|
31
|
+
mock.match?('/bogs/1.xml').should == false
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
describe Dupe::Network::GetMock do
|
37
|
+
before do
|
38
|
+
Dupe.reset
|
39
|
+
end
|
40
|
+
|
41
|
+
describe "mocked_response" do
|
42
|
+
describe "on a mock object whose response returns a Dupe.find with actual results" do
|
43
|
+
it "should convert the response result to xml" do
|
44
|
+
url_pattern = %r{/books/(\d+)\.xml}
|
45
|
+
response = proc {|id| Dupe.find(:book) {|b| b.id == id.to_i}}
|
46
|
+
book = Dupe.create :book
|
47
|
+
mock = Dupe::Network::GetMock.new url_pattern, response
|
48
|
+
mock.mocked_response('/books/1.xml').should == book.to_xml(:root => 'book')
|
49
|
+
|
50
|
+
proc { mock.mocked_response('/books/2.xml') }.should raise_error(Dupe::Network::GetMock::ResourceNotFoundError)
|
51
|
+
|
52
|
+
Dupe.define :author
|
53
|
+
mock = Dupe::Network::GetMock.new %r{/authors\.xml$}, proc {Dupe.find :authors}
|
54
|
+
mock.mocked_response('/authors.xml').should == [].to_xml(:root => 'results')
|
55
|
+
end
|
56
|
+
|
57
|
+
it "should add a request to the Dupe::Network#log" do
|
58
|
+
url_pattern = %r{/books/([a-zA-Z0-9-]+)\.xml}
|
59
|
+
response = proc {|label| Dupe.find(:book) {|b| b.label == label}}
|
60
|
+
book = Dupe.create :book, :label => 'rooby'
|
61
|
+
mock = Dupe::Network::GetMock.new url_pattern, response
|
62
|
+
Dupe.network.log.requests.length.should == 0
|
63
|
+
mock.mocked_response('/books/rooby.xml')
|
64
|
+
Dupe.network.log.requests.length.should == 1
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
describe "on a mock object whose response returns nil" do
|
69
|
+
it "should raise an error" do
|
70
|
+
url_pattern = %r{/authors/(\d+)\.xml}
|
71
|
+
response = proc { |id| Dupe.find(:author) {|a| a.id == id.to_i}}
|
72
|
+
Dupe.define :author
|
73
|
+
mock = Dupe::Network::GetMock.new url_pattern, response
|
74
|
+
proc {mock.mocked_response('/authors/1.xml')}.should raise_error(Dupe::Network::GetMock::ResourceNotFoundError)
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
describe "on a mock object whose response returns an empty array" do
|
79
|
+
it "should convert the empty array to an xml array record set with root 'results'" do
|
80
|
+
Dupe.define :author
|
81
|
+
mock = Dupe::Network::GetMock.new %r{/authors\.xml$}, proc {Dupe.find :authors}
|
82
|
+
mock.mocked_response('/authors.xml').should == [].to_xml(:root => 'results')
|
83
|
+
end
|
84
|
+
|
85
|
+
it "should add a request to the Dupe::Network#log" do
|
86
|
+
Dupe.define :author
|
87
|
+
mock = Dupe::Network::GetMock.new %r{/authors\.xml$}, proc {Dupe.find :authors}
|
88
|
+
Dupe.network.log.requests.length.should == 0
|
89
|
+
mock.mocked_response('/authors.xml')
|
90
|
+
Dupe.network.log.requests.length.should == 1
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
describe "on a mock object whose response returns an array of duped records" do
|
95
|
+
it "should convert the array to xml" do
|
96
|
+
Dupe.create :author
|
97
|
+
mock = Dupe::Network::GetMock.new %r{/authors\.xml$}, proc {Dupe.find :authors}
|
98
|
+
mock.mocked_response('/authors.xml').should == Dupe.find(:authors).to_xml(:root => 'authors')
|
99
|
+
end
|
100
|
+
|
101
|
+
it "should add a request to the Dupe::Network#log" do
|
102
|
+
Dupe.create :author
|
103
|
+
mock = Dupe::Network::GetMock.new %r{/authors\.xml$}, proc {Dupe.find :authors}
|
104
|
+
Dupe.network.log.requests.length.should == 0
|
105
|
+
mock.mocked_response('/authors.xml')
|
106
|
+
Dupe.network.log.requests.length.should == 1
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
describe Dupe::Network::PostMock do
|
113
|
+
before do
|
114
|
+
Dupe.reset
|
115
|
+
end
|
116
|
+
|
117
|
+
describe "mocked_response" do
|
118
|
+
describe "on a mock object whose response returns a location of a new record" do
|
119
|
+
it "should convert the new post to xml" do
|
120
|
+
Dupe.define :author
|
121
|
+
mock = Dupe::Network::PostMock.new %r{/authors\.xml$}, proc {|post_data| Dupe.create(:author, post_data)}
|
122
|
+
resp, url = mock.mocked_response('/authors.xml', {:name => "Rachel"})
|
123
|
+
resp.should == Dupe.find(:authors).first.to_xml_safe(:root => 'author')
|
124
|
+
url.should == "/authors/1.xml"
|
125
|
+
end
|
126
|
+
|
127
|
+
it "should add a request to the Dupe::Network#log" do
|
128
|
+
Dupe.define :author
|
129
|
+
mock = Dupe::Network::PostMock.new %r{/authors\.xml$}, proc {|post_data| Dupe.create(:author, post_data)}
|
130
|
+
Dupe.network.log.requests.length.should == 0
|
131
|
+
mock.mocked_response('/authors.xml', {:name => "Rachel"})
|
132
|
+
Dupe.network.log.requests.length.should == 1
|
133
|
+
end
|
134
|
+
end
|
135
|
+
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
|
@@ -0,0 +1,95 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
|
2
|
+
|
3
|
+
describe Dupe::Model do
|
4
|
+
describe "new" do
|
5
|
+
it "should require a model name" do
|
6
|
+
proc { Dupe::Model.new }.should raise_error(ArgumentError)
|
7
|
+
end
|
8
|
+
|
9
|
+
it "should set the model name to what was passed in during initialization" do
|
10
|
+
m = Dupe::Model.new :book
|
11
|
+
m.name.should == :book
|
12
|
+
end
|
13
|
+
|
14
|
+
it "should initialize an empty schema" do
|
15
|
+
m = Dupe::Model.new :book
|
16
|
+
m.schema.should be_kind_of(Dupe::Model::Schema)
|
17
|
+
end
|
18
|
+
|
19
|
+
it "should setup an id_sequence initialized to 0" do
|
20
|
+
m = Dupe::Model.new :book
|
21
|
+
m.id_sequence.current_value.should == 1
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
describe "define" do
|
26
|
+
describe "when passed a proc" do
|
27
|
+
before do
|
28
|
+
@model = Dupe::Model.new :book
|
29
|
+
@definition = proc { |attrs|
|
30
|
+
attrs.author('Anonymous') do |dont_care|
|
31
|
+
'Flying Spaghetti Monster'
|
32
|
+
end
|
33
|
+
}
|
34
|
+
end
|
35
|
+
|
36
|
+
it "should pass that proc off to it's schema" do
|
37
|
+
@model.schema.should_receive(:method_missing).once
|
38
|
+
@model.define @definition
|
39
|
+
end
|
40
|
+
|
41
|
+
it "should result in a schema with the desired attribute templates" do
|
42
|
+
@model.define @definition
|
43
|
+
@model.schema.attribute_templates[:author].name.should == :author
|
44
|
+
@model.schema.attribute_templates[:author].default.should == 'Anonymous'
|
45
|
+
@model.schema.attribute_templates[:author].transformer.call(
|
46
|
+
'dont care'
|
47
|
+
).should == 'Flying Spaghetti Monster'
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
describe "create" do
|
53
|
+
before do
|
54
|
+
Dupe.define :book do |attrs|
|
55
|
+
attrs.title 'Untitled'
|
56
|
+
attrs.author 'Anon' do |author|
|
57
|
+
"Author: #{author}"
|
58
|
+
end
|
59
|
+
attrs.after_create do |book|
|
60
|
+
book.label = book.title.downcase.gsub(/\ +/, '-')
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
@book_model = Dupe.models[:book]
|
65
|
+
end
|
66
|
+
|
67
|
+
it "shouldn't require any parameters" do
|
68
|
+
proc {
|
69
|
+
@book_model.create
|
70
|
+
}.should_not raise_error
|
71
|
+
end
|
72
|
+
|
73
|
+
it "should return a Dupe::Database::Record instance with the desired parameters" do
|
74
|
+
book = @book_model.create
|
75
|
+
book.should be_kind_of(Dupe::Database::Record)
|
76
|
+
book.__model__.name.should == :book
|
77
|
+
book.id.should == 1
|
78
|
+
book.title.should == 'Untitled'
|
79
|
+
book.author.should == 'Anon'
|
80
|
+
|
81
|
+
# the callback shouldn't get run until the database record is inserted into the duped 'database'
|
82
|
+
book.label.should == nil
|
83
|
+
|
84
|
+
book = @book_model.create :title => 'Rooby On Rails', :author => 'Matt Parker'
|
85
|
+
book.__model__.name.should == :book
|
86
|
+
book.id.should == 2
|
87
|
+
book.title.should == 'Rooby On Rails'
|
88
|
+
|
89
|
+
# the callback shouldn't get run until the database record is inserted into the duped 'database'
|
90
|
+
book.label.should == nil
|
91
|
+
|
92
|
+
book.author.should == 'Author: Matt Parker'
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
@@ -0,0 +1,130 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
|
2
|
+
|
3
|
+
describe Dupe::Network do
|
4
|
+
|
5
|
+
describe "new" do
|
6
|
+
before do
|
7
|
+
@network = Dupe::Network.new
|
8
|
+
end
|
9
|
+
|
10
|
+
it "should initialize @mocks to a hash of empty arrays keyed with valid REST verbs" do
|
11
|
+
Dupe::Network::VERBS.each do |verb|
|
12
|
+
@network.mocks[verb].should == []
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
it "should initialize @log to a new Dupe::Network::Log" do
|
17
|
+
@network.log.should be_kind_of(Dupe::Network::Log)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
describe "request" do
|
22
|
+
before do
|
23
|
+
@network = Dupe::Network.new
|
24
|
+
end
|
25
|
+
|
26
|
+
it "should require a valid REST verb" do
|
27
|
+
proc { @network.request }.should raise_error
|
28
|
+
proc { @network.request :invalid_rest_verb, '/some_url' }.should raise_error(Dupe::Network::UnknownRestVerbError)
|
29
|
+
proc { @network.request :get, '/some_url' }.should_not raise_error(Dupe::Network::UnknownRestVerbError)
|
30
|
+
proc { @network.request :post, '/some_url', 'some body' }.should_not raise_error(Dupe::Network::UnknownRestVerbError)
|
31
|
+
proc { @network.request :put, '/some_url' }.should_not raise_error(Dupe::Network::UnknownRestVerbError)
|
32
|
+
proc { @network.request :delete, '/some_url' }.should_not raise_error(Dupe::Network::UnknownRestVerbError)
|
33
|
+
end
|
34
|
+
|
35
|
+
it "should require a URL" do
|
36
|
+
proc { @network.request :get }.should raise_error(ArgumentError)
|
37
|
+
proc { @network.request :get, 'some_url'}.should_not raise_error(ArgumentError)
|
38
|
+
proc { @network.request :post, 'some_url', 'some body'}.should_not raise_error(ArgumentError)
|
39
|
+
proc { @network.request :put, 'some_url'}.should_not raise_error(ArgumentError)
|
40
|
+
proc { @network.request :delete, 'some_url'}.should_not raise_error(ArgumentError)
|
41
|
+
end
|
42
|
+
|
43
|
+
it "should raise an exception if the network has no mocks that match the url" do
|
44
|
+
proc { @network.request(:get, '/some_url')}.should raise_error(Dupe::Network::RequestNotFoundError)
|
45
|
+
proc { @network.request(:post, '/some_url', 'some body')}.should raise_error(Dupe::Network::RequestNotFoundError)
|
46
|
+
proc { @network.request(:put, '/some_url')}.should raise_error(Dupe::Network::RequestNotFoundError)
|
47
|
+
proc { @network.request(:delete, '/some_url')}.should raise_error(Dupe::Network::RequestNotFoundError)
|
48
|
+
end
|
49
|
+
|
50
|
+
it "should return the appropriate mock response if a mock matches the url" do
|
51
|
+
@network.define_service_mock :get, %r{/greeting$}, proc { "hello" }
|
52
|
+
@network.request(:get, '/greeting').should == 'hello'
|
53
|
+
|
54
|
+
@network.define_service_mock :post, %r{/greeting$}, proc { |post_data| Dupe.create(:greeting, post_data) }
|
55
|
+
resp, url = @network.request(:post, '/greeting', {} )
|
56
|
+
resp.should == Dupe.find(:greeting).to_xml_safe(:root => 'greeting')
|
57
|
+
url.should == "/greetings/1.xml"
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
describe "define_service_mock" do
|
62
|
+
before do
|
63
|
+
@network = Dupe::Network.new
|
64
|
+
end
|
65
|
+
|
66
|
+
it "should require a valid REST verb" do
|
67
|
+
proc { @network.define_service_mock }.should raise_error
|
68
|
+
proc { @network.define_service_mock :invalid_rest_verb, // }.should raise_error(Dupe::Network::UnknownRestVerbError)
|
69
|
+
proc { @network.define_service_mock :get, // }.should_not raise_error(Dupe::Network::UnknownRestVerbError)
|
70
|
+
proc { @network.define_service_mock :post, // }.should_not raise_error(Dupe::Network::UnknownRestVerbError)
|
71
|
+
proc { @network.define_service_mock :put, // }.should_not raise_error(Dupe::Network::UnknownRestVerbError)
|
72
|
+
end
|
73
|
+
|
74
|
+
it "should require a valid Regexp url pattern" do
|
75
|
+
proc { @network.define_service_mock :get, 'not a regular expression' }.should raise_error(ArgumentError)
|
76
|
+
proc { @network.define_service_mock :post, 'not a regular expression' }.should raise_error(ArgumentError)
|
77
|
+
proc { @network.define_service_mock :get, // }.should_not raise_error
|
78
|
+
proc { @network.define_service_mock :post, // }.should_not raise_error
|
79
|
+
end
|
80
|
+
|
81
|
+
it "should create and return a new get service mock when given valid parameters" do
|
82
|
+
verb = :get
|
83
|
+
pattern = //
|
84
|
+
response = proc { 'test' }
|
85
|
+
@network.mocks[:get].should be_empty
|
86
|
+
mock = @network.define_service_mock verb, pattern, response
|
87
|
+
@network.mocks[:get].should_not be_empty
|
88
|
+
@network.mocks[:get].first.class.should == Dupe::Network::GetMock
|
89
|
+
@network.mocks[:get].length.should == 1
|
90
|
+
@network.mocks[:get].first.should == mock
|
91
|
+
end
|
92
|
+
|
93
|
+
it "should create and return a new post service mock when given valid parameters" do
|
94
|
+
verb = :post
|
95
|
+
pattern = //
|
96
|
+
response = proc { 'test' }
|
97
|
+
@network.mocks[:post].should be_empty
|
98
|
+
mock = @network.define_service_mock verb, pattern, response
|
99
|
+
@network.mocks[:post].should_not be_empty
|
100
|
+
@network.mocks[:post].first.class.should == Dupe::Network::PostMock
|
101
|
+
@network.mocks[:post].length.should == 1
|
102
|
+
@network.mocks[:post].first.should == mock
|
103
|
+
end
|
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
|
128
|
+
end
|
129
|
+
|
130
|
+
end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
|
2
|
+
|
3
|
+
describe Dupe::Database::Record do
|
4
|
+
describe "new" do
|
5
|
+
it "should create an object that is a kind of Hash" do
|
6
|
+
Dupe::Database::Record.new.should be_kind_of(Hash)
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
describe "id" do
|
11
|
+
it "should allow us to set the record id (and not the object id)" do
|
12
|
+
d = Dupe::Database::Record.new
|
13
|
+
d.id.should == nil
|
14
|
+
d[:id].should == nil
|
15
|
+
d.id = 1
|
16
|
+
d.id.should == 1
|
17
|
+
d[:id].should == 1
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
describe "method_missing" do
|
22
|
+
it "should allow us to access hash keys as if they were object attributes" do
|
23
|
+
d = Dupe::Database::Record.new
|
24
|
+
d[:some_key].should == nil
|
25
|
+
d.some_key.should == nil
|
26
|
+
d.some_key = 1
|
27
|
+
d.some_key.should == 1
|
28
|
+
d[:some_key].should == 1
|
29
|
+
d[:another_key] = 2
|
30
|
+
d.another_key.should == 2
|
31
|
+
d[:another_key].should == 2
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
describe "inspect" do
|
36
|
+
it "should show the class name" do
|
37
|
+
d = Dupe::Database::Record.new
|
38
|
+
d.inspect.should match(/^<#Dupe::Database::Record/)
|
39
|
+
end
|
40
|
+
|
41
|
+
it "should show the key/value pairs as attributes" do
|
42
|
+
d = Dupe::Database::Record.new
|
43
|
+
d.title = 'test'
|
44
|
+
d.inspect.should match(/title="test"/)
|
45
|
+
d.author = Dupe::Database::Record.new
|
46
|
+
d.inspect.should match(/author=<#Dupe::Database::Record/)
|
47
|
+
end
|
48
|
+
|
49
|
+
it "should show Fake::<model_name> when the record has a model" do
|
50
|
+
b = Dupe.create :book
|
51
|
+
b.inspect.should match(/^<#Duped::Book/)
|
52
|
+
b.author = Dupe.create :author
|
53
|
+
b.inspect.should match(/^<#Duped::Book/)
|
54
|
+
b.inspect.should match(/author=<#Duped::Author/)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
describe "__model__" do
|
59
|
+
it "should have a __model__ instance variable" do
|
60
|
+
proc {Dupe::Database::Record.new.__model__}.should_not raise_error
|
61
|
+
end
|
62
|
+
|
63
|
+
it "should all you to set the __model_name__ instance variable" do
|
64
|
+
r = Dupe::Database::Record.new
|
65
|
+
proc {r.__model__ = :book}.should_not raise_error
|
66
|
+
r.__model__.should == :book
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
|
2
|
+
|
3
|
+
describe Dupe::Network::RestValidation do
|
4
|
+
before do
|
5
|
+
class TestRestValidation
|
6
|
+
include Dupe::Network::RestValidation
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
describe "validate_request_type" do
|
11
|
+
it "should raise an exception if the request type isn't :get, :post, :put, or :delete" do
|
12
|
+
proc {
|
13
|
+
TestRestValidation.new.validate_request_type(:unknown_request_type)
|
14
|
+
}.should raise_error(Dupe::Network::UnknownRestVerbError)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,109 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
|
2
|
+
|
3
|
+
describe Dupe::Model::Schema do
|
4
|
+
describe "new" do
|
5
|
+
it "should initialize attribute_templates to an empty hash" do
|
6
|
+
Dupe::Model::Schema.new.attribute_templates.should == {}
|
7
|
+
end
|
8
|
+
|
9
|
+
it "should initialize after_create_callbacks to an empty array" do
|
10
|
+
Dupe::Model::Schema.new.after_create_callbacks.should == []
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
describe "dynamic attribute_template creation methods" do
|
15
|
+
before do
|
16
|
+
@schema = Dupe::Model::Schema.new
|
17
|
+
end
|
18
|
+
|
19
|
+
describe "called with no parameters" do
|
20
|
+
it "should create a new attribute template with no transformer and no default value" do
|
21
|
+
@schema.title
|
22
|
+
@schema.attribute_templates[:title].should be_kind_of(Dupe::Model::Schema::AttributeTemplate)
|
23
|
+
@schema.attribute_templates[:title].name.should == :title
|
24
|
+
@schema.attribute_templates[:title].default.should be_nil
|
25
|
+
@schema.attribute_templates[:title].transformer.should be_nil
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
describe "called with a single parameter, but no block" do
|
30
|
+
it "should create a new attribute template with a default value but no transformer" do
|
31
|
+
@schema.title 'Untitled'
|
32
|
+
@schema.attribute_templates[:title].should be_kind_of(Dupe::Model::Schema::AttributeTemplate)
|
33
|
+
@schema.attribute_templates[:title].name.should == :title
|
34
|
+
@schema.attribute_templates[:title].default.should == 'Untitled'
|
35
|
+
@schema.attribute_templates[:title].transformer.should be_nil
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
describe "called with a block that accepts a parameter" do
|
40
|
+
it "should create a new attribute template without a default value, but with a tranformer" do
|
41
|
+
@schema.title {|dont_care| 'test'}
|
42
|
+
@schema.attribute_templates[:title].should be_kind_of(Dupe::Model::Schema::AttributeTemplate)
|
43
|
+
@schema.attribute_templates[:title].name.should == :title
|
44
|
+
@schema.attribute_templates[:title].default.should be_nil
|
45
|
+
@schema.attribute_templates[:title].transformer.should be_kind_of(Proc)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
describe "called with a block that doesn't accept a parameter" do
|
50
|
+
it "should create a new attribute template without a transformer, and with the block as the default value" do
|
51
|
+
@schema.title { 'knock' * 3 }
|
52
|
+
@schema.attribute_templates[:title].should be_kind_of(Dupe::Model::Schema::AttributeTemplate)
|
53
|
+
@schema.attribute_templates[:title].name.should == :title
|
54
|
+
@schema.attribute_templates[:title].default.should be_kind_of(Proc)
|
55
|
+
@schema.attribute_templates[:title].default.call.should == "knockknockknock"
|
56
|
+
@schema.attribute_templates[:title].transformer.should be_nil
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
describe "called with a block and a parameter" do
|
61
|
+
it "should create a new attribute template with a default value AND with a tranformer" do
|
62
|
+
@schema.title('Untitled') {|dont_care| 'test'}
|
63
|
+
@schema.attribute_templates[:title].should be_kind_of(Dupe::Model::Schema::AttributeTemplate)
|
64
|
+
@schema.attribute_templates[:title].name.should == :title
|
65
|
+
@schema.attribute_templates[:title].default.should == 'Untitled'
|
66
|
+
@schema.attribute_templates[:title].transformer.should be_kind_of(Proc)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
describe "#after_create" do
|
72
|
+
before do
|
73
|
+
@schema = Dupe::Model::Schema.new
|
74
|
+
end
|
75
|
+
|
76
|
+
it "should require a block that accepts a single parameter" do
|
77
|
+
proc { @schema.after_create }.should raise_error(ArgumentError)
|
78
|
+
proc { @schema.after_create { "parameterless block" } }.should raise_error(ArgumentError)
|
79
|
+
proc { @schema.after_create {|s| s.title = 'test' } }.should_not raise_error
|
80
|
+
end
|
81
|
+
|
82
|
+
it "should add the callback to the list of after_create_callbacks" do
|
83
|
+
@schema.after_create_callbacks.should be_empty
|
84
|
+
@schema.after_create {|s| s.title = 'test'}
|
85
|
+
@schema.after_create_callbacks.length.should == 1
|
86
|
+
@schema.after_create_callbacks.first.should be_kind_of(Proc)
|
87
|
+
end
|
88
|
+
|
89
|
+
end
|
90
|
+
|
91
|
+
describe "#uniquify" do
|
92
|
+
before do
|
93
|
+
@schema = Dupe::Model::Schema.new
|
94
|
+
end
|
95
|
+
|
96
|
+
it "should only accept a list of symbols" do
|
97
|
+
proc { @schema.uniquify }.should raise_error(ArgumentError, "You must pass at least one attribute to uniquify.")
|
98
|
+
proc { @schema.uniquify :hash => 'value' }.should raise_error(ArgumentError, "You may only pass symbols to uniquify.")
|
99
|
+
proc { @schema.uniquify :one, :two}.should_not raise_error
|
100
|
+
end
|
101
|
+
|
102
|
+
it "should create after_create_callbacks for each symbol passed to it" do
|
103
|
+
@schema.after_create_callbacks.should be_empty
|
104
|
+
@schema.uniquify :title, :label
|
105
|
+
@schema.after_create_callbacks.length.should == 2
|
106
|
+
@schema.after_create_callbacks.first.should be_kind_of(Proc)
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|