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.
Files changed (44) hide show
  1. data/README.rdoc +390 -147
  2. data/lib/dupe/active_resource_extensions.rb +25 -0
  3. data/lib/dupe/attribute_template.rb +71 -0
  4. data/lib/dupe/cucumber_hooks.rb +15 -7
  5. data/lib/dupe/custom_mocks.rb +102 -0
  6. data/lib/dupe/database.rb +51 -0
  7. data/lib/dupe/dupe.rb +359 -372
  8. data/lib/dupe/log.rb +38 -0
  9. data/lib/dupe/mock.rb +50 -0
  10. data/lib/dupe/model.rb +55 -0
  11. data/lib/dupe/network.rb +38 -0
  12. data/lib/dupe/record.rb +35 -56
  13. data/lib/dupe/rest_validation.rb +16 -0
  14. data/lib/dupe/schema.rb +36 -0
  15. data/lib/dupe/sequence.rb +11 -10
  16. data/lib/dupe/singular_plural_detection.rb +9 -0
  17. data/lib/dupe/string.rb +6 -8
  18. data/lib/dupe/symbol.rb +3 -0
  19. data/lib/dupe.rb +13 -12
  20. data/rails_generators/dupe/templates/custom_mocks.rb +4 -34
  21. data/rails_generators/dupe/templates/dupe_setup.rb +3 -23
  22. data/spec/lib_specs/active_resource_extensions_spec.rb +29 -0
  23. data/spec/lib_specs/attribute_template_spec.rb +173 -0
  24. data/spec/lib_specs/database_spec.rb +133 -0
  25. data/spec/lib_specs/dupe_spec.rb +307 -0
  26. data/spec/lib_specs/log_spec.rb +78 -0
  27. data/spec/lib_specs/logged_request_spec.rb +22 -0
  28. data/spec/lib_specs/mock_definitions_spec.rb +32 -0
  29. data/spec/lib_specs/mock_spec.rb +67 -0
  30. data/spec/lib_specs/model_spec.rb +90 -0
  31. data/spec/lib_specs/network_spec.rb +77 -0
  32. data/spec/lib_specs/record_spec.rb +70 -0
  33. data/spec/lib_specs/rest_validation_spec.rb +17 -0
  34. data/spec/lib_specs/schema_spec.rb +90 -0
  35. data/spec/lib_specs/sequence_spec.rb +26 -0
  36. data/spec/lib_specs/string_spec.rb +31 -0
  37. data/spec/lib_specs/symbol_spec.rb +17 -0
  38. data/spec/spec_helper.rb +2 -5
  39. metadata +29 -7
  40. data/lib/dupe/active_resource.rb +0 -135
  41. data/lib/dupe/attribute.rb +0 -17
  42. data/lib/dupe/configuration.rb +0 -20
  43. data/lib/dupe/mock_service_response.rb +0 -55
  44. data/spec/lib_specs/dupe_record_spec.rb +0 -57
@@ -1,8 +1,16 @@
1
- After do |scenario| #:nodoc:
2
- if Dupe.global_configuration.config[:debug] == true
3
- ActiveResource::Connection.print_request_log
4
- ActiveResource::Connection.flush_request_log
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
- Dupe.flush
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