dupe 0.3.7 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.rdoc +390 -147
- data/lib/dupe/active_resource_extensions.rb +25 -0
- data/lib/dupe/attribute_template.rb +71 -0
- data/lib/dupe/cucumber_hooks.rb +15 -7
- data/lib/dupe/custom_mocks.rb +102 -0
- data/lib/dupe/database.rb +51 -0
- data/lib/dupe/dupe.rb +359 -372
- data/lib/dupe/log.rb +38 -0
- data/lib/dupe/mock.rb +50 -0
- data/lib/dupe/model.rb +55 -0
- data/lib/dupe/network.rb +38 -0
- data/lib/dupe/record.rb +35 -56
- data/lib/dupe/rest_validation.rb +16 -0
- data/lib/dupe/schema.rb +36 -0
- data/lib/dupe/sequence.rb +11 -10
- data/lib/dupe/singular_plural_detection.rb +9 -0
- data/lib/dupe/string.rb +6 -8
- data/lib/dupe/symbol.rb +3 -0
- data/lib/dupe.rb +13 -12
- data/rails_generators/dupe/templates/custom_mocks.rb +4 -34
- data/rails_generators/dupe/templates/dupe_setup.rb +3 -23
- data/spec/lib_specs/active_resource_extensions_spec.rb +29 -0
- data/spec/lib_specs/attribute_template_spec.rb +173 -0
- data/spec/lib_specs/database_spec.rb +133 -0
- data/spec/lib_specs/dupe_spec.rb +307 -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 +32 -0
- data/spec/lib_specs/mock_spec.rb +67 -0
- data/spec/lib_specs/model_spec.rb +90 -0
- data/spec/lib_specs/network_spec.rb +77 -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 +90 -0
- data/spec/lib_specs/sequence_spec.rb +26 -0
- data/spec/lib_specs/string_spec.rb +31 -0
- data/spec/lib_specs/symbol_spec.rb +17 -0
- data/spec/spec_helper.rb +2 -5
- metadata +29 -7
- data/lib/dupe/active_resource.rb +0 -135
- data/lib/dupe/attribute.rb +0 -17
- data/lib/dupe/configuration.rb +0 -20
- data/lib/dupe/mock_service_response.rb +0 -55
- data/spec/lib_specs/dupe_record_spec.rb +0 -57
data/lib/dupe/cucumber_hooks.rb
CHANGED
@@ -1,8 +1,16 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
1
|
+
begin
|
2
|
+
After do |scenario|
|
3
|
+
# print the requests logged during the scenario if in Dupe debug mode
|
4
|
+
if Dupe.debug
|
5
|
+
log = Dupe.network.log.pretty_print
|
6
|
+
puts "\n\n" + log.indent(4) + "\n\n" if log
|
7
|
+
end
|
8
|
+
|
9
|
+
# remove any data created during the scenario from the dupe database
|
10
|
+
Dupe.database.truncate_tables
|
11
|
+
|
12
|
+
# clear out the network log
|
13
|
+
Dupe.network.log.reset
|
5
14
|
end
|
6
|
-
|
7
|
-
|
8
|
-
end
|
15
|
+
rescue
|
16
|
+
end
|
@@ -0,0 +1,102 @@
|
|
1
|
+
# Dupe knows how to handle simple find by id and find :all lookups from ActiveResource. But what about other requests we might potentially make?
|
2
|
+
#
|
3
|
+
# irb# Dupe.create :author, :name => 'Monkey', :published => true
|
4
|
+
# ==> <#Duped::Author name="Monkey" published=true id=1>
|
5
|
+
#
|
6
|
+
# irb# Dupe.create :author, :name => 'Tiger', :published => false
|
7
|
+
# ==> <#Duped::Author name="Tiger" published=false id=2>
|
8
|
+
#
|
9
|
+
# irb# class Author < ActiveResource::Base; self.site = ''; end
|
10
|
+
# ==> ""
|
11
|
+
#
|
12
|
+
# irb# Author.find :all, :from => :published
|
13
|
+
# Dupe::Network::RequestNotFoundError: No mocked service response found for '/authors/published.xml'
|
14
|
+
# from /Library/Ruby/Gems/1.8/gems/dupe-0.4.0/lib/dupe/network.rb:32:in `match'
|
15
|
+
# from /Library/Ruby/Gems/1.8/gems/dupe-0.4.0/lib/dupe/network.rb:17:in `request'
|
16
|
+
# from /Library/Ruby/Gems/1.8/gems/dupe-0.4.0/lib/dupe/active_resource_extensions.rb:15:in `get'
|
17
|
+
# from /Library/Ruby/Gems/1.8/gems/activeresource-2.3.5/lib/active_resource/custom_methods.rb:57:in `get'
|
18
|
+
# from /Library/Ruby/Gems/1.8/gems/activeresource-2.3.5/lib/active_resource/base.rb:632:in `find_every'
|
19
|
+
# from /Library/Ruby/Gems/1.8/gems/activeresource-2.3.5/lib/active_resource/base.rb:582:in `find'
|
20
|
+
# from (irb):12
|
21
|
+
#
|
22
|
+
# Obviously, Dupe had no way of anticipating this possibility. However, you can create your own custom intercept mock for this:
|
23
|
+
#
|
24
|
+
# irb# Get %r{/authors/published.xml} do
|
25
|
+
# --# Dupe.find(:authors) {|a| a.published == true}
|
26
|
+
# --# end
|
27
|
+
# ==> #<Dupe::Network::Mock:0x1833e88 @url_pattern=/\/authors\/published.xml/, @verb=:get, @response=#<Proc:0x01833f14@(irb):13>
|
28
|
+
#
|
29
|
+
# irb# Author.find :all, :from => :published
|
30
|
+
# ==> [#<Author:0x1821d3c @attributes={"name"=>"Monkey", "published"=>true, "id"=>1}, prefix_options{}]
|
31
|
+
#
|
32
|
+
# irb# puts Dupe.network.log.pretty_print
|
33
|
+
#
|
34
|
+
# Logged Requests:
|
35
|
+
# Request: GET /authors/published.xml
|
36
|
+
# Response:
|
37
|
+
# <?xml version="1.0" encoding="UTF-8"?>
|
38
|
+
# <authors type="array">
|
39
|
+
# <author>
|
40
|
+
# <name>Monkey</name>
|
41
|
+
# <published type="boolean">true</published>
|
42
|
+
# <id type="integer">1</id>
|
43
|
+
# </author>
|
44
|
+
# </authors>
|
45
|
+
#
|
46
|
+
#
|
47
|
+
# The "Get" method requires a url pattern and a block. In most cases, your block will return a Dupe.find result. Internally, Dupe will transform that into XML. However, if your "Get" block returns a string, Dupe will use that as the response body and not attempt to do any transformations on it.
|
48
|
+
#
|
49
|
+
# Suppose instead the service expected us to pass published as a query string parameter:
|
50
|
+
#
|
51
|
+
# irb# Author.find :all, :params => {:published => true}
|
52
|
+
# Dupe::Network::RequestNotFoundError: No mocked service response found for '/authors.xml?published=true'
|
53
|
+
# from /Library/Ruby/Gems/1.8/gems/dupe-0.4.0/lib/dupe/network.rb:32:in `match'
|
54
|
+
# from /Library/Ruby/Gems/1.8/gems/dupe-0.4.0/lib/dupe/network.rb:17:in `request'
|
55
|
+
# from /Library/Ruby/Gems/1.8/gems/dupe-0.4.0/lib/dupe/active_resource_extensions.rb:15:in `get'
|
56
|
+
# from /Library/Ruby/Gems/1.8/gems/activeresource-2.3.5/lib/active_resource/base.rb:639:in `find_every'
|
57
|
+
# from /Library/Ruby/Gems/1.8/gems/activeresource-2.3.5/lib/active_resource/base.rb:582:in `find'
|
58
|
+
# from (irb):18
|
59
|
+
#
|
60
|
+
# We can mock this with the following:
|
61
|
+
#
|
62
|
+
# irb# Get %r{/authors\.xml\?published=(true|false)$} do |published|
|
63
|
+
# --# if published == 'true'
|
64
|
+
# --# Dupe.find(:authors) {|a| a.published == true}
|
65
|
+
# --# else
|
66
|
+
# --# Dupe.find(:authors) {|a| a.published == false}
|
67
|
+
# --# end
|
68
|
+
# --# end
|
69
|
+
#
|
70
|
+
# irb# Author.find :all, :params => {:published => true}
|
71
|
+
# ==> [#<Author:0x17db094 @attributes={"name"=>"Monkey", "published"=>true, "id"=>1}, prefix_options{}]
|
72
|
+
#
|
73
|
+
# irb# Author.find :all, :params => {:published => false}
|
74
|
+
# ==> [#<Author:0x17c68c4 @attributes={"name"=>"Tiger", "published"=>false, "id"=>2}, prefix_options{}]
|
75
|
+
#
|
76
|
+
# irb# puts Dupe.network.log.pretty_print
|
77
|
+
#
|
78
|
+
# Logged Requests:
|
79
|
+
# Request: GET /authors.xml?published=true
|
80
|
+
# Response:
|
81
|
+
# <?xml version="1.0" encoding="UTF-8"?>
|
82
|
+
# <authors type="array">
|
83
|
+
# <author>
|
84
|
+
# <name>Monkey</name>
|
85
|
+
# <published type="boolean">true</published>
|
86
|
+
# <id type="integer">1</id>
|
87
|
+
# </author>
|
88
|
+
# </authors>
|
89
|
+
#
|
90
|
+
# Request: GET /authors.xml?published=false
|
91
|
+
# Response:
|
92
|
+
# <?xml version="1.0" encoding="UTF-8"?>
|
93
|
+
# <authors type="array">
|
94
|
+
# <author>
|
95
|
+
# <name>Tiger</name>
|
96
|
+
# <published type="boolean">false</published>
|
97
|
+
# <id type="integer">2</id>
|
98
|
+
# </author>
|
99
|
+
# </authors>
|
100
|
+
def Get(url_pattern, &block)
|
101
|
+
Dupe.network.define_service_mock :get, url_pattern, block
|
102
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
class Dupe
|
2
|
+
class Database #:nodoc:
|
3
|
+
attr_reader :tables
|
4
|
+
|
5
|
+
#:nodoc:
|
6
|
+
class TableDoesNotExistError < StandardError; end
|
7
|
+
|
8
|
+
#:nodoc:
|
9
|
+
class InvalidQueryError < StandardError; end
|
10
|
+
|
11
|
+
# by default, there are not tables in the database
|
12
|
+
def initialize
|
13
|
+
@tables = {}
|
14
|
+
end
|
15
|
+
|
16
|
+
# pass in a Dupe::Database::Record object, and this method will store the record
|
17
|
+
# in the appropriate table
|
18
|
+
def insert(record)
|
19
|
+
if !record.kind_of?(Dupe::Database::Record) || !record.__model__ || !record[:id]
|
20
|
+
raise ArgumentError, "You may only insert well-defined Dupe::Database::Record objects"
|
21
|
+
end
|
22
|
+
@tables[record.__model__.name] ||= []
|
23
|
+
@tables[record.__model__.name] << record
|
24
|
+
end
|
25
|
+
|
26
|
+
# pass in a model_name (e.g., :book) and optionally a proc with
|
27
|
+
# conditions (e.g., {|b| b.genre == 'Science Fiction'})
|
28
|
+
# and recieve a (possibly empty) array of results
|
29
|
+
def select(model_name, conditions=nil)
|
30
|
+
raise TableDoesNotExistError, "The table ':#{model_name}' does not exist." unless @tables[model_name]
|
31
|
+
raise(
|
32
|
+
InvalidQueryError,
|
33
|
+
"There was a problem with your select conditions. Please consult the API."
|
34
|
+
) if conditions and (!conditions.kind_of?(Proc) || conditions.arity != 1)
|
35
|
+
|
36
|
+
return @tables[model_name] if !conditions
|
37
|
+
@tables[model_name].select {|r| conditions.call(r)}
|
38
|
+
end
|
39
|
+
|
40
|
+
def create_table(model_name)
|
41
|
+
@tables[model_name.to_sym] ||= []
|
42
|
+
end
|
43
|
+
|
44
|
+
def truncate_tables
|
45
|
+
@tables.each do |table_name, table_records|
|
46
|
+
@tables[table_name] = []
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
end
|
51
|
+
end
|