superdupe 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|