dupe 0.3.7 → 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.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
|