pact-support 1.9.0 → 1.15.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 (112) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +124 -0
  3. data/lib/pact/configuration.rb +7 -0
  4. data/lib/pact/consumer_contract/consumer_contract.rb +12 -1
  5. data/lib/pact/consumer_contract/http_consumer_contract_parser.rb +1 -1
  6. data/lib/pact/consumer_contract/interaction.rb +5 -1
  7. data/lib/pact/consumer_contract/interaction_v2_parser.rb +9 -1
  8. data/lib/pact/consumer_contract/interaction_v3_parser.rb +22 -3
  9. data/lib/pact/consumer_contract/pact_file.rb +32 -1
  10. data/lib/pact/matchers/matchers.rb +33 -13
  11. data/lib/pact/matching_rules/v3/merge.rb +4 -2
  12. data/lib/pact/shared/multipart_form_differ.rb +2 -0
  13. data/lib/pact/support/version.rb +1 -1
  14. data/lib/pact/term.rb +0 -1
  15. metadata +5 -228
  16. data/.gitignore +0 -32
  17. data/.rspec +0 -3
  18. data/.travis.yml +0 -29
  19. data/Appraisals +0 -7
  20. data/Gemfile +0 -4
  21. data/RELEASING.md +0 -5
  22. data/Rakefile +0 -4
  23. data/gemfiles/default.gemfile +0 -5
  24. data/gemfiles/ruby_under_22.gemfile +0 -8
  25. data/pact-support.gemspec +0 -39
  26. data/script/release.sh +0 -9
  27. data/script/update-pact-specification-v2 +0 -9
  28. data/spec/fixtures/interaction-with-matching-rules.json +0 -27
  29. data/spec/fixtures/multipart-form-diff.txt +0 -9
  30. data/spec/fixtures/not-a-pact.json +0 -3
  31. data/spec/fixtures/pact-http-v2.json +0 -36
  32. data/spec/fixtures/pact-http-v3.json +0 -36
  33. data/spec/integration/matching_rules_extract_and_merge_spec.rb +0 -127
  34. data/spec/lib/pact/array_like_spec.rb +0 -37
  35. data/spec/lib/pact/configuration_spec.rb +0 -61
  36. data/spec/lib/pact/consumer/request_spec.rb +0 -25
  37. data/spec/lib/pact/consumer_contract/active_support_support_spec.rb +0 -58
  38. data/spec/lib/pact/consumer_contract/consumer_contract_spec.rb +0 -142
  39. data/spec/lib/pact/consumer_contract/file_name_spec.rb +0 -24
  40. data/spec/lib/pact/consumer_contract/headers_spec.rb +0 -107
  41. data/spec/lib/pact/consumer_contract/http_consumer_contract_parser_spec.rb +0 -25
  42. data/spec/lib/pact/consumer_contract/interaction_parser_spec.rb +0 -62
  43. data/spec/lib/pact/consumer_contract/interaction_spec.rb +0 -121
  44. data/spec/lib/pact/consumer_contract/interaction_v2_parser_spec.rb +0 -54
  45. data/spec/lib/pact/consumer_contract/interaction_v3_parser_spec.rb +0 -48
  46. data/spec/lib/pact/consumer_contract/pact_file_spec.rb +0 -204
  47. data/spec/lib/pact/consumer_contract/query_hash_spec.rb +0 -154
  48. data/spec/lib/pact/consumer_contract/query_string_spec.rb +0 -131
  49. data/spec/lib/pact/consumer_contract/request_spec.rb +0 -486
  50. data/spec/lib/pact/consumer_contract/response_spec.rb +0 -82
  51. data/spec/lib/pact/helpers_spec.rb +0 -143
  52. data/spec/lib/pact/matchers/differ_spec.rb +0 -215
  53. data/spec/lib/pact/matchers/difference_spec.rb +0 -22
  54. data/spec/lib/pact/matchers/embedded_diff_formatter_spec.rb +0 -90
  55. data/spec/lib/pact/matchers/extract_diff_messages_spec.rb +0 -78
  56. data/spec/lib/pact/matchers/index_not_found_spec.rb +0 -21
  57. data/spec/lib/pact/matchers/list_diff_formatter_spec.rb +0 -121
  58. data/spec/lib/pact/matchers/matchers_array_like_spec.rb +0 -222
  59. data/spec/lib/pact/matchers/matchers_messages_hash_and_array_spec.rb +0 -146
  60. data/spec/lib/pact/matchers/matchers_messages_mismatched_value_spec.rb +0 -71
  61. data/spec/lib/pact/matchers/matchers_messages_regexp_spec.rb +0 -103
  62. data/spec/lib/pact/matchers/matchers_spec.rb +0 -521
  63. data/spec/lib/pact/matchers/multipart_form_diff_formatter_spec.rb +0 -36
  64. data/spec/lib/pact/matchers/no_diff_at_index_spec.rb +0 -15
  65. data/spec/lib/pact/matchers/regexp_difference_spec.rb +0 -20
  66. data/spec/lib/pact/matchers/type_difference_spec.rb +0 -36
  67. data/spec/lib/pact/matchers/unexpected_index_spec.rb +0 -20
  68. data/spec/lib/pact/matchers/unexpected_key_spec.rb +0 -20
  69. data/spec/lib/pact/matchers/unix_diff_formatter_spec.rb +0 -235
  70. data/spec/lib/pact/matching_rules/extract_spec.rb +0 -216
  71. data/spec/lib/pact/matching_rules/merge_spec.rb +0 -436
  72. data/spec/lib/pact/matching_rules/v3/extract_spec.rb +0 -238
  73. data/spec/lib/pact/matching_rules/v3/merge_spec.rb +0 -485
  74. data/spec/lib/pact/matching_rules_spec.rb +0 -82
  75. data/spec/lib/pact/reification_spec.rb +0 -172
  76. data/spec/lib/pact/shared/dsl_spec.rb +0 -100
  77. data/spec/lib/pact/shared/form_differ_spec.rb +0 -71
  78. data/spec/lib/pact/shared/json_differ_spec.rb +0 -36
  79. data/spec/lib/pact/shared/key_not_found_spec.rb +0 -20
  80. data/spec/lib/pact/shared/multipart_form_differ_spec.rb +0 -39
  81. data/spec/lib/pact/shared/request_spec.rb +0 -235
  82. data/spec/lib/pact/shared/text_differ_spec.rb +0 -54
  83. data/spec/lib/pact/something_like_spec.rb +0 -23
  84. data/spec/lib/pact/support_spec.rb +0 -9
  85. data/spec/lib/pact/symbolize_keys_spec.rb +0 -15
  86. data/spec/lib/pact/term_spec.rb +0 -89
  87. data/spec/pact_specification/compliance-2.0.rb +0 -66
  88. data/spec/spec_helper.rb +0 -18
  89. data/spec/support/a_consumer-a_producer.json +0 -32
  90. data/spec/support/a_consumer-a_provider.json +0 -32
  91. data/spec/support/active_support_if_configured.rb +0 -6
  92. data/spec/support/case-insensitive-response-header-matching.json +0 -21
  93. data/spec/support/consumer_contract_template.json +0 -24
  94. data/spec/support/dsl_spec_support.rb +0 -7
  95. data/spec/support/factories.rb +0 -87
  96. data/spec/support/generated_index.md +0 -4
  97. data/spec/support/generated_markdown.md +0 -55
  98. data/spec/support/interaction_view_model.json +0 -63
  99. data/spec/support/interaction_view_model_with_terms.json +0 -50
  100. data/spec/support/markdown_pact.json +0 -48
  101. data/spec/support/missing_provider_states_output.txt +0 -25
  102. data/spec/support/options.json +0 -21
  103. data/spec/support/ruby_version_helpers.rb +0 -23
  104. data/spec/support/shared_examples_for_request.rb +0 -132
  105. data/spec/support/spec_support.rb +0 -29
  106. data/spec/support/stubbing.json +0 -22
  107. data/spec/support/term.json +0 -48
  108. data/spec/support/test_app_fail.json +0 -61
  109. data/spec/support/test_app_pass.json +0 -38
  110. data/spec/support/test_app_with_right_content_type_differ.json +0 -23
  111. data/tasks/release.rake +0 -5
  112. data/tasks/spec.rake +0 -14
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 2184e9575553c8a69f05b2a7665f5c70948b06a8
4
- data.tar.gz: 896248de0a0c7c6d19d4ae7dfec15587929db2a8
2
+ SHA256:
3
+ metadata.gz: f2ee65cf7dfde0e38da424b8c462877550c73d8eb4a32d141979e3571dd5b68b
4
+ data.tar.gz: 156429a88a8fa6e2af7650a4ab82541a375e81a7d7613f8c1fc35d21a0f0c18f
5
5
  SHA512:
6
- metadata.gz: 890f78b04b7778391c0c2c7536c1ec153e080a48c4724f01be27ed77373e2fd472b8aed151e7420b4ccf9b4d453a6bb1907c1525c4295f8464eacccb1939684f
7
- data.tar.gz: 43688a515f9719b74666fb584fa9b80ed1b0d4951d64a0b75964710373bbd089bced0962201dfc627288e9e26d761d58628fedb9fa8dd3b15bc77914c48450d1
6
+ metadata.gz: 3d14e51c30179bae9db88aa6b9dfc4c6780a9fb5aafd446e5e7b0914ccc1421f9d508a19d744864756b4a6b3809cc1579f0d344a169b1837f28ef6705f4b0448
7
+ data.tar.gz: 1e072929086a22a1e8a6ed2bc07e6a4d46fed8f666f177971596249357c641d1fc976c2751f73c03324963b81227bc0afa9324db905308cc8aabb4914c9d9b0a
data/CHANGELOG.md CHANGED
@@ -1,3 +1,127 @@
1
+ <a name="v1.15.0"></a>
2
+ ### v1.15.0 (2020-04-30)
3
+
4
+
5
+ #### Bug Fixes
6
+
7
+ * follow first redirect when fetching remote pact artifacts. (#80) ([c1df6dd](/../../commit/c1df6dd))
8
+
9
+
10
+ <a name="v1.14.3"></a>
11
+ ### v1.14.3 (2020-04-06)
12
+
13
+
14
+ #### Bug Fixes
15
+
16
+ * do not blow up when there are no matchers ([ac70846](/../../commit/ac70846))
17
+
18
+
19
+ <a name="v1.14.2"></a>
20
+ ### v1.14.2 (2020-03-25)
21
+
22
+
23
+ #### Bug Fixes
24
+
25
+ * don't blow up when there is a term inside an each like ([a565a56](/../../commit/a565a56))
26
+
27
+
28
+ <a name="v1.14.1"></a>
29
+ ### v1.14.1 (2020-02-27)
30
+
31
+
32
+ #### Bug Fixes
33
+
34
+ * correctly parse matching rules for request paths ([cc15a72](/../../commit/cc15a72))
35
+
36
+
37
+ <a name="v1.14.0"></a>
38
+ ### v1.14.0 (2020-02-13)
39
+
40
+
41
+ #### Features
42
+
43
+ * use certificates from SSL_CERT_FILE and SSL_CERT_DIR environment variables in HTTP connections ([bf1333d](/../../commit/bf1333d))
44
+
45
+
46
+ <a name="v1.13.0"></a>
47
+ ### v1.13.0 (2020-01-24)
48
+
49
+
50
+ #### Features
51
+
52
+ * give each interaction an index when parsing the contract ([74e9568](/../../commit/74e9568))
53
+
54
+
55
+ <a name="v1.12.1"></a>
56
+ ### v1.12.1 (2020-01-22)
57
+
58
+
59
+ #### Bug Fixes
60
+
61
+ * add missing require for pact/configuration ([bc4bbb5](/../../commit/bc4bbb5))
62
+
63
+
64
+ <a name="v1.12.0"></a>
65
+ ### v1.12.0 (2019-09-26)
66
+
67
+
68
+ #### Features
69
+
70
+ * parse interaction _id from Pact Broker ([8d66a84](/../../commit/8d66a84))
71
+ * support marking an interaction as writable/not writable (#75) ([e1fc347](/../../commit/e1fc347))
72
+ * modernise gemspec ([c941d02](/../../commit/c941d02))
73
+
74
+
75
+ #### Bug Fixes
76
+
77
+ * add CHANGELOG to gem distribution ([35c9c48](/../../commit/35c9c48))
78
+
79
+
80
+ <a name="v1.11.0"></a>
81
+ ### v1.11.0 (2019-06-18)
82
+
83
+
84
+ #### Features
85
+
86
+ * allow Integers and Floats to be considered equivalent when using type based matching. ([d8a70a1](/../../commit/d8a70a1))
87
+
88
+
89
+ <a name="v1.10.3"></a>
90
+ ### v1.10.3 (2019-06-07)
91
+
92
+
93
+ #### Bug Fixes
94
+
95
+ * gracefully handle diff between an expected multipart form request and an actual application/json request ([8577d52](/../../commit/8577d52))
96
+
97
+
98
+ <a name="v1.10.2"></a>
99
+ ### v1.10.2 (2019-05-20)
100
+
101
+
102
+ #### Bug Fixes
103
+
104
+ * allow proxy env var to be used when fetching pacts ([ebce481](/../../commit/ebce481))
105
+
106
+
107
+ <a name="v1.10.1"></a>
108
+ ### v1.10.1 (2019-04-26)
109
+
110
+
111
+ #### Bug Fixes
112
+
113
+ * gracefully handle read only file system (eg RunKit) ([eeee528](/../../commit/eeee528))
114
+
115
+
116
+ <a name="v1.10.0"></a>
117
+ ### v1.10.0 (2019-03-15)
118
+
119
+
120
+ #### Bug Fixes
121
+
122
+ * don't try and fix producer keys for a nil string ([94245c7](/../../commit/94245c7))
123
+
124
+
1
125
  <a name="v1.9.0"></a>
2
126
  ### v1.9.0 (2019-02-22)
3
127
 
@@ -51,6 +51,7 @@ module Pact
51
51
  attr_accessor :error_stream
52
52
  attr_accessor :output_stream
53
53
  attr_accessor :pactfile_write_order
54
+ attr_accessor :treat_all_number_classes_as_equivalent # when using type based matching
54
55
 
55
56
  def self.default_configuration
56
57
  c = Configuration.new
@@ -61,6 +62,7 @@ module Pact
61
62
  c.output_stream = $stdout
62
63
  c.error_stream = $stderr
63
64
  c.pactfile_write_order = :chronological
65
+ c.treat_all_number_classes_as_equivalent = true
64
66
 
65
67
  c
66
68
  end
@@ -169,6 +171,11 @@ module Pact
169
171
  logger = ::Logger.new(log_path)
170
172
  logger.level = ::Logger::DEBUG
171
173
  logger
174
+ rescue Errno::EROFS
175
+ # So we can run on RunKit
176
+ logger = ::Logger.new($stdout)
177
+ logger.level = ::Logger::DEBUG
178
+ logger
172
179
  end
173
180
  end
174
181
 
@@ -59,7 +59,7 @@ module Pact
59
59
  end
60
60
 
61
61
  def self.maintain_backwards_compatiblity_with_producer_keys string
62
- string.gsub('"producer":', '"provider":').gsub('"producer_state":', '"provider_state":')
62
+ string.gsub('"producer":', '"provider":').gsub('"producer_state":', '"provider_state":') if string
63
63
  end
64
64
 
65
65
  def find_interaction criteria
@@ -82,5 +82,16 @@ module Pact
82
82
  end
83
83
  end
84
84
 
85
+ def writable_interactions
86
+ interactions.reject do |interaction|
87
+ # For the sake of backwards compatibility, only reject interactions where
88
+ # write_to_pact is explicitly set to false
89
+ interaction.respond_to?(:metadata) &&
90
+ !interaction.metadata.nil? &&
91
+ interaction.metadata.key?(:write_to_pact) &&
92
+ interaction.metadata[:write_to_pact] == false
93
+ end
94
+ end
95
+
85
96
  end
86
97
  end
@@ -13,7 +13,7 @@ module Pact
13
13
  Pact.configuration.error_stream.puts "WARN: This code only knows how to parse v3 pacts, attempting to parse v#{options[:pact_specification_version]} pact using v3 code."
14
14
  end
15
15
 
16
- interactions = hash[:interactions].collect { |hash| Interaction.from_hash(hash, options) }
16
+ interactions = hash[:interactions].each_with_index.collect { |hash, index| Interaction.from_hash({ index: index }.merge(hash), options) }
17
17
  ConsumerContract.new(
18
18
  :consumer => ServiceConsumer.from_hash(hash[:consumer]),
19
19
  :provider => ServiceProvider.from_hash(hash[:provider]),
@@ -5,7 +5,7 @@ module Pact
5
5
  class Interaction
6
6
  include ActiveSupportSupport
7
7
 
8
- attr_accessor :description, :request, :response, :provider_state, :provider_states
8
+ attr_accessor :description, :request, :response, :provider_state, :provider_states, :metadata, :_id, :index
9
9
 
10
10
  def initialize attributes = {}
11
11
  @description = attributes[:description]
@@ -13,6 +13,9 @@ module Pact
13
13
  @response = attributes[:response]
14
14
  @provider_state = attributes[:provider_state] || attributes[:providerState]
15
15
  @provider_states = attributes[:provider_states]
16
+ @metadata = attributes[:metadata]
17
+ @_id = attributes[:_id]
18
+ @index = attributes[:index]
16
19
  end
17
20
 
18
21
  def self.from_hash hash, options = {}
@@ -30,6 +33,7 @@ module Pact
30
33
 
31
34
  h[:request] = request.to_hash
32
35
  h[:response] = response.to_hash
36
+ h[:metadata] = metadata
33
37
  h
34
38
  end
35
39
 
@@ -14,7 +14,11 @@ module Pact
14
14
  request = parse_request(hash['request'], options)
15
15
  response = parse_response(hash['response'], options)
16
16
  provider_states = parse_provider_states(hash['providerState'] || hash['provider_state'])
17
- Interaction.new(symbolize_keys(hash).merge(request: request, response: response, provider_states: provider_states))
17
+ metadata = parse_metadata(hash['metadata'])
18
+ Interaction.new(symbolize_keys(hash).merge(request: request,
19
+ response: response,
20
+ provider_states: provider_states,
21
+ metadata: metadata))
18
22
  end
19
23
 
20
24
  def self.parse_request request_hash, options
@@ -30,5 +34,9 @@ module Pact
30
34
  def self.parse_provider_states provider_state_name
31
35
  provider_state_name ? [Pact::ProviderState.new(provider_state_name)] : []
32
36
  end
37
+
38
+ def self.parse_metadata metadata_hash
39
+ symbolize_keys(metadata_hash)
40
+ end
33
41
  end
34
42
  end
@@ -19,7 +19,12 @@ module Pact
19
19
  if provider_states && provider_states.size > 1
20
20
  Pact.configuration.error_stream.puts("WARN: Currently only 1 provider state is supported. Ignoring ")
21
21
  end
22
- Interaction.new(symbolize_keys(hash).merge(request: request, response: response, provider_states: provider_states, provider_state: provider_state))
22
+ metadata = parse_metadata(hash['metadata'])
23
+ Interaction.new(symbolize_keys(hash).merge(request: request,
24
+ response: response,
25
+ provider_states: provider_states,
26
+ provider_state: provider_state,
27
+ metadata: metadata))
23
28
  end
24
29
 
25
30
  def self.parse_request request_hash, options
@@ -42,14 +47,14 @@ module Pact
42
47
 
43
48
  def self.parse_request_with_non_string_body request_hash, request_matching_rules, options
44
49
  request_hash = request_hash.keys.each_with_object({}) do | key, new_hash |
45
- new_hash[key] = Pact::MatchingRules.merge(request_hash[key], request_matching_rules[key], options)
50
+ new_hash[key] = Pact::MatchingRules.merge(request_hash[key], look_up_matching_rules(key, request_matching_rules), options)
46
51
  end
47
52
  Pact::Request::Expected.from_hash(request_hash)
48
53
  end
49
54
 
50
55
  def self.parse_response_with_non_string_body response_hash, response_matching_rules, options
51
56
  response_hash = response_hash.keys.each_with_object({}) do | key, new_hash |
52
- new_hash[key] = Pact::MatchingRules.merge(response_hash[key], response_matching_rules[key], options)
57
+ new_hash[key] = Pact::MatchingRules.merge(response_hash[key], look_up_matching_rules(key, response_matching_rules), options)
53
58
  end
54
59
  Pact::Response.from_hash(response_hash)
55
60
  end
@@ -69,5 +74,19 @@ module Pact
69
74
  Pact::ProviderState.new(provider_state_hash['name'], provider_state_hash['params'])
70
75
  end
71
76
  end
77
+
78
+ def self.parse_metadata metadata_hash
79
+ symbolize_keys(metadata_hash)
80
+ end
81
+
82
+ def self.look_up_matching_rules(key, matching_rules)
83
+ # The matching rules for the path operate on the object itself and don't have sub paths
84
+ # Convert it into the format that Merge expects.
85
+ if key == 'path'
86
+ matching_rules[key] ? { '$.' => matching_rules[key] } : nil
87
+ else
88
+ matching_rules[key]
89
+ end
90
+ end
72
91
  end
73
92
  end
@@ -33,6 +33,8 @@ module Pact
33
33
  def save_pactfile_to_tmp pact, name
34
34
  ::FileUtils.mkdir_p Pact.configuration.tmp_dir
35
35
  ::File.open(Pact.configuration.tmp_dir + "/#{name}", "w") { |file| file << pact}
36
+ rescue Errno::EROFS => e
37
+ # do nothing, probably on RunKit
36
38
  end
37
39
 
38
40
  def render_pact(uri_string, options)
@@ -77,9 +79,38 @@ module Pact
77
79
 
78
80
  def get_remote(uri, options)
79
81
  request = Net::HTTP::Get.new(uri)
82
+ request = prepare_auth(request, options) if options[:username] || options[:token]
83
+
84
+ http = prepare_request(uri)
85
+ response = perform_http_request(http, request, options)
86
+
87
+ if response.is_a?(Net::HTTPRedirection)
88
+ uri = URI(response.header['location'])
89
+ req = Net::HTTP::Get.new(uri)
90
+ req = prepare_auth(req, options) if options[:username] || options[:token]
91
+
92
+ http = prepare_request(uri)
93
+ response = perform_http_request(http, req, options)
94
+ end
95
+ response
96
+ end
97
+
98
+ def prepare_auth(request, options)
80
99
  request.basic_auth(options[:username], options[:password]) if options[:username]
81
100
  request['Authorization'] = "Bearer #{options[:token]}" if options[:token]
82
- Net::HTTP.start(uri.host, uri.port, use_ssl: uri.scheme == 'https') do |http|
101
+ request
102
+ end
103
+
104
+ def prepare_request(uri)
105
+ http = Net::HTTP.new(uri.host, uri.port, :ENV)
106
+ http.use_ssl = (uri.scheme == 'https')
107
+ http.ca_file = ENV['SSL_CERT_FILE'] if ENV['SSL_CERT_FILE'] && ENV['SSL_CERT_FILE'] != ''
108
+ http.ca_path = ENV['SSL_CERT_DIR'] if ENV['SSL_CERT_DIR'] && ENV['SSL_CERT_DIR'] != ''
109
+ http
110
+ end
111
+
112
+ def perform_http_request(http, request, options)
113
+ http.start do |http|
83
114
  http.open_timeout = options[:open_timeout] || OPEN_TIMEOUT
84
115
  http.read_timeout = options[:read_timeout] || READ_TIMEOUT
85
116
  http.request(request)
@@ -1,3 +1,4 @@
1
+ require 'pact/configuration'
1
2
  require 'pact/term'
2
3
  require 'pact/something_like'
3
4
  require 'pact/array_like'
@@ -20,23 +21,30 @@ module Pact
20
21
  # maintain backwards compatibility
21
22
 
22
23
  module Matchers
23
-
24
24
  NO_DIFF_AT_INDEX = NoDiffAtIndex.new
25
- DEFAULT_OPTIONS = {allow_unexpected_keys: true, type: false}.freeze
26
25
  NO_DIFF = {}.freeze
26
+ NUMERIC_TYPES = %w[Integer Float Fixnum Bignum BigDecimal].freeze
27
+ DEFAULT_OPTIONS = {
28
+ allow_unexpected_keys: true,
29
+ type: false
30
+ }.freeze
27
31
 
28
32
  extend self
29
33
 
30
34
  def diff expected, actual, opts = {}
31
- calculate_diff(expected, actual, DEFAULT_OPTIONS.merge(opts))
35
+ calculate_diff(expected, actual, DEFAULT_OPTIONS.merge(configurable_options).merge(opts))
32
36
  end
33
37
 
34
38
  def type_diff expected, actual, opts = {}
35
- calculate_diff expected, actual, DEFAULT_OPTIONS.merge(opts).merge(type: true)
39
+ calculate_diff expected, actual, DEFAULT_OPTIONS.merge(configurable_options).merge(opts).merge(type: true)
36
40
  end
37
41
 
38
42
  private
39
43
 
44
+ def configurable_options
45
+ { treat_all_number_classes_as_equivalent: Pact.configuration.treat_all_number_classes_as_equivalent }
46
+ end
47
+
40
48
  def calculate_diff expected, actual, opts = {}
41
49
  options = DEFAULT_OPTIONS.merge(opts)
42
50
  case expected
@@ -112,7 +120,11 @@ module Pact
112
120
  def array_like_diff array_like, actual, options
113
121
  if actual.is_a? Array
114
122
  expected_size = [array_like.min, actual.size].max
115
- expected_array = expected_size.times.collect{ Pact::Term.unpack_regexps(array_like.contents) }
123
+ # I know changing this is going to break something, but I don't know what it is, as there's no
124
+ # test that fails when I make this change. I know the unpack regexps was there for a reason however.
125
+ # Guess we'll have to change it and see!
126
+ # expected_array = expected_size.times.collect{ Pact::Term.unpack_regexps(array_like.contents) }
127
+ expected_array = expected_size.times.collect{ array_like.contents }
116
128
  actual_array_diff expected_array, actual, options.merge(:type => true)
117
129
  else
118
130
  Difference.new array_like.generate, actual, type_difference_message(array_like.generate, actual)
@@ -156,22 +168,22 @@ module Pact
156
168
 
157
169
  def object_diff expected, actual, options
158
170
  if options[:type]
159
- type_difference expected, actual
171
+ type_difference expected, actual, options
160
172
  else
161
173
  exact_value_diff expected, actual, options
162
174
  end
163
175
  end
164
176
 
165
177
  def exact_value_diff expected, actual, options
166
- if expected != actual
167
- Difference.new expected, actual, value_difference_message(expected, actual, options)
168
- else
178
+ if expected == actual
169
179
  NO_DIFF
180
+ else
181
+ Difference.new expected, actual, value_difference_message(expected, actual, options)
170
182
  end
171
183
  end
172
184
 
173
- def type_difference expected, actual
174
- if types_match? expected, actual
185
+ def type_difference expected, actual, options
186
+ if types_match? expected, actual, options
175
187
  NO_DIFF
176
188
  else
177
189
  TypeDifference.new type_diff_expected_display(expected), type_diff_actual_display(actual), type_difference_message(expected, actual)
@@ -186,8 +198,16 @@ module Pact
186
198
  actual.is_a?(KeyNotFound) ? actual : ActualType.new(actual)
187
199
  end
188
200
 
189
- def types_match? expected, actual
190
- expected.class == actual.class || (is_boolean(expected) && is_boolean(actual))
201
+ # Make options optional to support existing monkey patches
202
+ def types_match? expected, actual, options = {}
203
+ expected.class == actual.class ||
204
+ (is_boolean(expected) && is_boolean(actual)) ||
205
+ (options.fetch(:treat_all_number_classes_as_equivalent, false) && is_number?(expected) && is_number?(actual))
206
+ end
207
+
208
+ def is_number? object
209
+ # deal with Fixnum and Integer without warnings by using string class names
210
+ NUMERIC_TYPES.include?(object.class.to_s)
191
211
  end
192
212
 
193
213
  def is_boolean object