pact 1.1.0.rc2 → 1.1.0.rc3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (136) hide show
  1. data/.gitignore +0 -1
  2. data/CHANGELOG.md +46 -1
  3. data/Gemfile.lock +6 -4
  4. data/README.md +40 -186
  5. data/Rakefile +1 -1
  6. data/documentation/README.md +10 -0
  7. data/documentation/best-practices.md +33 -0
  8. data/documentation/configuration.md +166 -0
  9. data/documentation/diff_formatter_embedded.png +0 -0
  10. data/documentation/diff_formatter_list.png +0 -0
  11. data/documentation/diff_formatter_unix.png +0 -0
  12. data/documentation/faq.md +36 -6
  13. data/documentation/provider-states.md +173 -0
  14. data/documentation/raq.md +4 -4
  15. data/documentation/terminology.md +2 -2
  16. data/example/animal-service/Gemfile.lock +6 -9
  17. data/example/animal-service/Rakefile +2 -0
  18. data/example/animal-service/db/animal_db.sqlite3 +0 -0
  19. data/example/animal-service/lib/animal_service/animal_repository.rb +1 -5
  20. data/example/animal-service/lib/animal_service/api.rb +1 -1
  21. data/example/animal-service/spec/service_consumers/pact_helper.rb +7 -10
  22. data/example/animal-service/spec/service_consumers/provider_states_for_zoo_app.rb +5 -1
  23. data/example/zoo-app/Gemfile.lock +6 -9
  24. data/example/zoo-app/Rakefile +5 -0
  25. data/example/zoo-app/doc/markdown/README.md +3 -0
  26. data/example/zoo-app/doc/markdown/Zoo App - Animal Service.md +75 -0
  27. data/example/zoo-app/lib/zoo_app/animal_service_client.rb +2 -2
  28. data/example/zoo-app/spec/pacts/zoo_app-animal_service.json +1 -1
  29. data/example/zoo-app/spec/service_providers/animal_service_client_spec.rb +29 -34
  30. data/example/zoo-app/spec/service_providers/pact_helper.rb +4 -0
  31. data/lib/pact/configuration.rb +49 -1
  32. data/lib/pact/consumer/configuration.rb +4 -172
  33. data/lib/pact/consumer/configuration/configuration_extensions.rb +15 -0
  34. data/lib/pact/consumer/configuration/dsl.rb +12 -0
  35. data/lib/pact/consumer/configuration/mock_service.rb +89 -0
  36. data/lib/pact/consumer/configuration/service_consumer.rb +51 -0
  37. data/lib/pact/consumer/configuration/service_provider.rb +40 -0
  38. data/lib/pact/consumer/mock_service/interaction_mismatch.rb +3 -3
  39. data/lib/pact/consumer/mock_service/interaction_post.rb +2 -2
  40. data/lib/pact/consumer/mock_service/interaction_replay.rb +3 -4
  41. data/lib/pact/consumer/mock_service/verification_get.rb +32 -13
  42. data/lib/pact/consumer/rspec.rb +2 -4
  43. data/lib/pact/consumer/spec_hooks.rb +3 -1
  44. data/lib/pact/consumer_contract/consumer_contract.rb +1 -1
  45. data/lib/pact/consumer_contract/interaction.rb +1 -1
  46. data/lib/pact/doc/doc_file.rb +40 -0
  47. data/lib/pact/doc/generate.rb +11 -0
  48. data/lib/pact/doc/generator.rb +81 -0
  49. data/lib/pact/doc/interaction_view_model.rb +113 -0
  50. data/lib/pact/doc/markdown/generator.rb +26 -0
  51. data/lib/pact/doc/markdown/index_renderer.rb +41 -0
  52. data/lib/pact/doc/markdown/interaction.erb +14 -0
  53. data/lib/pact/doc/markdown/interaction_renderer.rb +38 -0
  54. data/lib/pact/doc/markdown/interactions_renderer.rb +56 -0
  55. data/lib/pact/doc/sort_interactions.rb +17 -0
  56. data/lib/pact/matchers/actual_type.rb +16 -0
  57. data/lib/pact/matchers/base_difference.rb +37 -0
  58. data/lib/pact/matchers/differ.rb +150 -0
  59. data/lib/pact/matchers/difference.rb +5 -30
  60. data/lib/pact/matchers/difference_indicator.rb +26 -0
  61. data/lib/pact/matchers/embedded_diff_formatter.rb +62 -0
  62. data/lib/pact/matchers/expected_type.rb +35 -0
  63. data/lib/pact/matchers/index_not_found.rb +3 -12
  64. data/lib/pact/matchers/{diff_decorator.rb → list_diff_formatter.rb} +28 -11
  65. data/lib/pact/matchers/matchers.rb +35 -39
  66. data/lib/pact/matchers/no_diff_indicator.rb +18 -0
  67. data/lib/pact/matchers/regexp_difference.rb +13 -0
  68. data/lib/pact/matchers/type_difference.rb +16 -0
  69. data/lib/pact/matchers/unexpected_index.rb +3 -13
  70. data/lib/pact/matchers/unexpected_key.rb +3 -12
  71. data/lib/pact/matchers/{plus_minus_diff_decorator.rb → unix_diff_formatter.rb} +22 -7
  72. data/lib/pact/provider/configuration.rb +5 -178
  73. data/lib/pact/provider/configuration/configuration_extension.rb +58 -0
  74. data/lib/pact/provider/configuration/dsl.rb +13 -0
  75. data/lib/pact/provider/configuration/pact_verification.rb +46 -0
  76. data/lib/pact/provider/configuration/service_provider_config.rb +16 -0
  77. data/lib/pact/provider/configuration/service_provider_dsl.rb +54 -0
  78. data/lib/pact/provider/matchers.rb +21 -13
  79. data/lib/pact/provider/matchers/messages.rb +43 -0
  80. data/lib/pact/provider/pact_spec_runner.rb +8 -0
  81. data/lib/pact/provider/rspec.rb +1 -1
  82. data/lib/pact/provider/rspec/formatter.rb +9 -7
  83. data/lib/pact/{consumer_contract → shared}/active_support_support.rb +4 -0
  84. data/lib/pact/shared/jruby_support.rb +18 -0
  85. data/lib/pact/shared/key_not_found.rb +3 -16
  86. data/lib/pact/shared/request.rb +5 -5
  87. data/lib/pact/term.rb +2 -2
  88. data/lib/pact/version.rb +1 -1
  89. data/pact.gemspec +2 -2
  90. data/spec/integration/pact/provider_configuration_spec.rb +2 -1
  91. data/spec/lib/pact/configuration_spec.rb +73 -0
  92. data/spec/lib/pact/consumer/mock_service/interaction_mismatch_spec.rb +21 -3
  93. data/spec/lib/pact/consumer/mock_service/verification_get_spec.rb +134 -0
  94. data/spec/lib/pact/consumer/request_spec.rb +1 -1
  95. data/spec/lib/pact/consumer_contract/active_support_support_spec.rb +1 -1
  96. data/spec/lib/pact/doc/generator_spec.rb +69 -0
  97. data/spec/lib/pact/doc/interaction_view_model_spec.rb +112 -0
  98. data/spec/lib/pact/doc/markdown/index_renderer_spec.rb +29 -0
  99. data/spec/lib/pact/doc/markdown/interactions_renderer_spec.rb +29 -0
  100. data/spec/lib/pact/matchers/differ_spec.rb +214 -0
  101. data/spec/lib/pact/matchers/difference_spec.rb +2 -12
  102. data/spec/lib/pact/matchers/embedded_diff_formatter_spec.rb +77 -0
  103. data/spec/lib/pact/matchers/index_not_found_spec.rb +21 -0
  104. data/spec/lib/pact/matchers/list_diff_formatter_spec.rb +114 -0
  105. data/spec/lib/pact/matchers/matchers_spec.rb +38 -22
  106. data/spec/lib/pact/matchers/regexp_difference_spec.rb +20 -0
  107. data/spec/lib/pact/matchers/type_difference_spec.rb +34 -0
  108. data/spec/lib/pact/matchers/unexpected_index_spec.rb +20 -0
  109. data/spec/lib/pact/matchers/unexpected_key_spec.rb +20 -0
  110. data/spec/lib/pact/matchers/{plus_minus_diff_decorator_spec.rb → unix_diff_formatter_spec.rb} +35 -6
  111. data/spec/lib/pact/provider/configuration/configuration_extension_spec.rb +30 -0
  112. data/spec/lib/pact/provider/configuration/pact_verification_spec.rb +43 -0
  113. data/spec/lib/pact/provider/configuration/service_provider_config_spec.rb +21 -0
  114. data/spec/lib/pact/provider/configuration/service_provider_dsl_spec.rb +92 -0
  115. data/spec/lib/pact/provider/configuration_spec.rb +7 -150
  116. data/spec/lib/pact/provider/matchers/messages_spec.rb +104 -0
  117. data/spec/lib/pact/provider/rspec/formatter_spec.rb +56 -0
  118. data/spec/lib/pact/shared/key_not_found_spec.rb +20 -0
  119. data/spec/lib/pact/shared/request_spec.rb +28 -0
  120. data/spec/spec_helper.rb +3 -0
  121. data/spec/standalone/consumer_fail_test.rb +54 -0
  122. data/spec/standalone/consumer_pass_test.rb +50 -0
  123. data/spec/support/generated_index.md +4 -0
  124. data/spec/support/generated_markdown.md +55 -0
  125. data/spec/support/interaction_view_model.json +63 -0
  126. data/spec/support/markdown_pact.json +48 -0
  127. data/spec/support/pact_helper.rb +2 -1
  128. data/spec/support/spec_support.rb +7 -0
  129. data/spec/support/test_app_fail.json +11 -2
  130. data/tasks/pact-test.rake +9 -0
  131. metadata +113 -20
  132. data/example/animal-service/db/animals_db.sqlite3 +0 -0
  133. data/lib/pact/consumer/rspec/full_example_description.rb +0 -28
  134. data/lib/pact/matchers/nested_json_diff_decorator.rb +0 -53
  135. data/spec/lib/pact/matchers/diff_decorator_spec.rb +0 -80
  136. data/spec/lib/pact/matchers/nested_json_diff_decorator_spec.rb +0 -48
@@ -5,21 +5,11 @@ module Pact
5
5
  module Matchers
6
6
  describe Difference do
7
7
 
8
- describe "#to_hash" do
9
-
10
- context "when a regexp is expected" do
11
-
12
- subject { Difference.new(/ap/, 'pear').to_hash }
13
-
14
- it "indicates that the actual was indended 'to match'" do
15
- expect(subject).to eq({:EXPECTED_TO_MATCH => "/ap/", :ACTUAL => "pear"})
16
- end
17
-
18
- end
8
+ describe "#as_json" do
19
9
 
20
10
  context "when something other than a regexp is expected" do
21
11
 
22
- subject { Difference.new("apple", 'pear').to_hash }
12
+ subject { Difference.new("apple", 'pear').as_json }
23
13
 
24
14
  it "indicates that the actual was intended 'to eq'" do
25
15
  expect(subject).to eq({:EXPECTED => "apple", :ACTUAL => "pear"})
@@ -0,0 +1,77 @@
1
+ require 'spec_helper'
2
+ require 'pact/matchers/embedded_diff_formatter'
3
+ require 'pact/matchers/type_difference'
4
+ require 'pact/matchers/expected_type'
5
+ require 'pact/matchers/actual_type'
6
+
7
+ module Pact
8
+ module Matchers
9
+ describe EmbeddedDiffFormatter do
10
+
11
+ let(:diff) do
12
+ {
13
+ :something => TypeDifference.new(ExpectedType.new("Fred"), ActualType.new(1))
14
+ }
15
+ end
16
+
17
+ subject { EmbeddedDiffFormatter.call(diff, options) }
18
+
19
+ let(:options) { { colour: colour }}
20
+ let(:expected_coloured) { '"' + ::Term::ANSIColor.red("expected_type") + '":'}
21
+ let(:actual_coloured) { '"' + ::Term::ANSIColor.green("actual_type") + '":'}
22
+
23
+ describe ".call" do
24
+
25
+ let(:colour) { true }
26
+
27
+ context "when color_enabled is true" do
28
+ it "returns nicely formatted json" do
29
+ expect(subject.split("\n").size).to eq 6
30
+ end
31
+
32
+ it "returns a string displaying the diff in colour" do
33
+ expect(subject).to include expected_coloured
34
+ expect(subject).to include actual_coloured
35
+ end
36
+ end
37
+
38
+ context "when color_enabled is false" do
39
+
40
+ let(:colour) { false }
41
+
42
+ it "returns nicely formatted json" do
43
+ expect(subject.split("\n").size).to eq 6
44
+ end
45
+
46
+ it "returns a string displaying the diff without colour" do
47
+ expect(subject).to_not include expected_coloured
48
+ expect(subject).to_not include actual_coloured
49
+ end
50
+ end
51
+
52
+ context "when no options are specified" do
53
+ subject { EmbeddedDiffFormatter.call(diff) }
54
+
55
+ context "when Pact.configuration.color_enabled is true" do
56
+ it "returns a string displaying the diff in colour" do
57
+ expect(Pact.configuration).to receive(:color_enabled).and_return(true)
58
+ expect(subject).to include expected_coloured
59
+ expect(subject).to include actual_coloured
60
+ end
61
+ end
62
+
63
+ context "when Pact.configuration.color_enabled is false" do
64
+ it "returns a string displaying the diff without colour" do
65
+ expect(Pact.configuration).to receive(:color_enabled).and_return(false)
66
+ expect(subject).to_not include expected_coloured
67
+ expect(subject).to_not include actual_coloured
68
+ end
69
+ end
70
+
71
+ end
72
+ end
73
+
74
+ end
75
+
76
+ end
77
+ end
@@ -0,0 +1,21 @@
1
+ require 'spec_helper'
2
+ require 'pact/matchers/index_not_found'
3
+
4
+ module Pact
5
+ describe IndexNotFound do
6
+
7
+ describe "#as_json" do
8
+ it "returns a string representation of the object" do
9
+ expect(subject.as_json).to eq subject.to_s
10
+ end
11
+ end
12
+
13
+ describe "#to_json" do
14
+ it "serialises the object to JSON" do
15
+ expect(subject.to_json).to eq "\"#{subject.to_s}\""
16
+ end
17
+ end
18
+
19
+ end
20
+
21
+ end
@@ -0,0 +1,114 @@
1
+ require 'spec_helper'
2
+ require 'pact/matchers/list_diff_formatter'
3
+ require 'pact/matchers/matchers'
4
+
5
+ module Pact
6
+ module Matchers
7
+ describe ListDiffFormatter do
8
+
9
+ describe ".call" do
10
+ subject{ ListDiffFormatter.call(diff, {}) }
11
+
12
+ context "when using class based matching" do
13
+ let(:diff) { {root: TypeDifference.new(ExpectedType.new("Fred"), ActualType.new(1)) } }
14
+ let(:expected_output) { <<-EOS
15
+ \tAt:
16
+ \t\t[:root]
17
+ \tExpected type:
18
+ \t\tString
19
+ \tActual type:
20
+ \t\tFixnum
21
+ EOS
22
+ }
23
+
24
+ it "shows the expected and actual classes" do
25
+ expect(subject + "\n").to eq(expected_output)
26
+ end
27
+
28
+ end
29
+
30
+ context "when there is an unmatched regexp" do
31
+ let(:diff) { {root: RegexpDifference.new(/fr.*ed/, "mary") } }
32
+ let(:expected_output) { <<-EOS
33
+ \tAt:
34
+ \t\t[:root]
35
+ \tExpected to match:
36
+ \t\t/fr.*ed/
37
+ \tActual:
38
+ \t\t"mary"
39
+ EOS
40
+ }
41
+ it "shows the expected regexp" do
42
+ expect(subject + "\n").to eq(expected_output)
43
+ end
44
+ end
45
+
46
+ context "when there is a mismatched value" do
47
+ let(:diff) { {root: {"blah" => { 1 => Difference.new("alphabet", "woozle")}}} }
48
+ let(:expected_output) { ""}
49
+
50
+ it "includes the expected value" do
51
+ expect(subject).to match(/Expected:.*"alphabet"/m)
52
+ end
53
+ it "includes the actual value" do
54
+ expect(subject).to match(/Actual:.*"woozle"/m)
55
+ end
56
+
57
+ it "includes the path" do
58
+ expect(subject).to include('[:root]["blah"][1]')
59
+ end
60
+ end
61
+
62
+ context "when there is a missing key" do
63
+ let(:expected_hash) { {"abc" => {"def" => [1,2]}}}
64
+ let(:diff) { {root: {"blah" => { 1 => Difference.new(expected_hash, Pact::KeyNotFound.new )}}} }
65
+ let(:expected_output) { ""}
66
+
67
+ it "includes the expected value" do
68
+ expect(subject).to match(/Missing key with value\:.*\{/m)
69
+ end
70
+
71
+ it "includes the path" do
72
+ expect(subject).to include('[:root]["blah"][1]')
73
+ end
74
+ end
75
+
76
+ context "when there is a missing index" do
77
+ let(:diff) { [NoDiffIndicator.new, Difference.new(1, IndexNotFound.new )]}
78
+ it "includes the expected value" do
79
+ expect(subject).to match(/Missing.*1/m)
80
+ end
81
+
82
+ it "includes the path" do
83
+ expect(subject).to include('[1]')
84
+ end
85
+ end
86
+
87
+ context "when there is an unexpected index" do
88
+ let(:diff) { [NoDiffIndicator.new, Difference.new(UnexpectedIndex.new, 2), Difference.new(UnexpectedIndex.new, "b")]}
89
+ it "includes the unexpected value" do
90
+ expect(subject).to include("Array contained unexpected item:")
91
+ end
92
+
93
+ it "includes the path" do
94
+ expect(subject).to include('[1]')
95
+ expect(subject).to include('[2]')
96
+ end
97
+ end
98
+
99
+ context "when there is an unexpected key" do
100
+ let(:diff) { {"blah" => Difference.new(UnexpectedKey.new, "b")}}
101
+ it "includes the unexpected key" do
102
+ expect(subject).to include("Hash contained unexpected key with value:")
103
+ end
104
+
105
+ it "includes the path" do
106
+ expect(subject).to include('["blah"]')
107
+ end
108
+ end
109
+
110
+ end
111
+
112
+ end
113
+ end
114
+ end
@@ -43,13 +43,13 @@ module Pact::Matchers
43
43
  describe "expecting a string matching a regexp and not finding key" do
44
44
  let(:expected) { {a: /b/} }
45
45
  let(:actual) { {} }
46
- let(:difference) { {:a=> Difference.new(/b/, Pact::KeyNotFound.new) } }
46
+ let(:difference) { {:a=> RegexpDifference.new(/b/, Pact::KeyNotFound.new) } }
47
47
  it "returns the diff" do
48
48
  expect(diff(expected, actual)).to eq difference
49
49
  end
50
50
  end
51
51
 
52
- describe 'structure_diff' do
52
+ describe 'type_diff' do
53
53
  let(:expected) {
54
54
  {a: 'a string', b: 1, c: nil, d: [{e: 'thing'}], f: {g: 10}, h: false}
55
55
  }
@@ -58,49 +58,48 @@ module Pact::Matchers
58
58
  let(:actual) { {a: 'another string', b: 2, c: nil, d: [{e: 'something'}], f: {g: 100}, h: true} }
59
59
  let(:difference) { {} }
60
60
  it "returns an empty hash" do
61
- expect(structure_diff(expected, actual)).to eq difference
61
+ expect(type_diff(expected, actual)).to eq difference
62
62
  end
63
63
  end
64
64
 
65
65
  context "when a key is not found" do
66
66
  let(:actual) { {a: 'blah'} }
67
67
  let(:expected) { {b: 'blah'} }
68
- let(:difference) { {:b=>Difference.new({:class=>String, :eg=>"blah"}, Pact::KeyNotFound.new)} }
68
+ let(:difference) { {:b=>TypeDifference.new(Pact::ExpectedType.new("blah"), Pact::KeyNotFound.new)} }
69
69
  it "returns the difference" do
70
- expect(structure_diff(expected, actual)).to eq difference
70
+ expect(type_diff(expected, actual)).to eq difference
71
71
  end
72
72
  end
73
73
 
74
74
  context "when a number is expected" do
75
75
  let(:expected) { {a: 1} }
76
- #let(:difference) { {a: {expected: 'Fixnum (eg. 1)', actual: 'String ("a string")'}} }
77
- let(:difference) { {a: Difference.new({:class => Fixnum, eg: 1 } , {:class => String, :value => 'a string'})} }
76
+ let(:difference) { {a: TypeDifference.new(Pact::ExpectedType.new(1) , Pact::ActualType.new('a string'))} }
78
77
 
79
78
  context "and a string is found" do
80
79
  let(:actual) { {a: 'a string'}}
81
80
  it "returns the diff" do
82
- expect(structure_diff(expected, actual)).to eq difference
81
+ expect(type_diff(expected, actual)).to eq difference
83
82
  end
84
83
  end
85
84
  context "and nil is found" do
86
85
  let(:actual) { {a: nil}}
87
- let(:difference ) { {a: Difference.new({:class => Fixnum, eg: 1}, nil) } }
86
+ let(:difference ) { {a: TypeDifference.new(Pact::ExpectedType.new(1), Pact::ActualType.new(nil)) } }
88
87
  it "returns the diff" do
89
- expect(structure_diff(expected, actual)).to eq difference
88
+ expect(type_diff(expected, actual)).to eq difference
90
89
  end
91
90
  end
92
91
  context "and a hash is found" do
93
92
  let(:actual) { {a: {b: 1}} }
94
- let(:difference) { {:a=>Difference.new({:class=>Fixnum, :eg=>1}, {:class=>Hash, :value=>{:b=>1}}) } }
93
+ let(:difference) { {:a=>TypeDifference.new(Pact::ExpectedType.new(1), Pact::ActualType.new({:b=>1})) } }
95
94
  it "returns the diff" do
96
- expect(structure_diff(expected, actual)).to eq difference
95
+ expect(type_diff(expected, actual)).to eq difference
97
96
  end
98
97
  end
99
98
  context "and an array is found" do
100
99
  let(:actual) { {a: [1] } }
101
- let(:difference) { {:a=>Difference.new({:class=>Fixnum, :eg=>1}, {:class=>Array, :value=>[1]} ) } }
100
+ let(:difference) { {:a=>TypeDifference.new(Pact::ExpectedType.new(1), Pact::ActualType.new([1]))}}
102
101
  it "returns the diff" do
103
- expect(structure_diff(expected, actual)).to eq difference
102
+ expect(type_diff(expected, actual)).to eq difference
104
103
  end
105
104
  end
106
105
  end
@@ -112,13 +111,12 @@ module Pact::Matchers
112
111
  let(:difference) { [
113
112
  Pact::Matchers::NO_DIFF_INDICATOR,
114
113
  {:name =>
115
- Difference.new( { :class=>String, :eg=>"Mary" },
116
- { :class=>Fixnum, :value=>1} )
114
+ TypeDifference.new(Pact::ExpectedType.new("Mary"), Pact::ActualType.new(1))
117
115
  }
118
116
  ]
119
117
  }
120
118
  it "returns the diff" do
121
- expect(structure_diff(expected, actual)).to eq difference
119
+ expect(type_diff(expected, actual)).to eq difference
122
120
  end
123
121
  end
124
122
  end
@@ -128,9 +126,9 @@ module Pact::Matchers
128
126
  let(:expected) { {a: nil} }
129
127
  context "and a string is found" do
130
128
  let(:actual) { {a: 'a string'} }
131
- let(:difference) { {:a=>Difference.new(nil, {:class=>String, :value=>"a string"}) } }
129
+ let(:difference) { {:a=>TypeDifference.new(Pact::ExpectedType.new(nil), Pact::ActualType.new("a string")) } }
132
130
  it "returns the diff" do
133
- expect(structure_diff(expected, actual)).to eq difference
131
+ expect(type_diff(expected, actual)).to eq difference
134
132
  end
135
133
  end
136
134
  end
@@ -139,12 +137,30 @@ module Pact::Matchers
139
137
  let(:expected) { {a: Pact::Term.new(:matcher => /p/, :generate => 'apple')} }
140
138
  context "and a non matching string is found" do
141
139
  let(:actual) { {a: 'banana'} }
142
- let(:difference) { {:a=>Pact::Matchers::Difference.new(/p/,"banana")} }
140
+ let(:difference) { {:a=>Pact::Matchers::RegexpDifference.new(/p/,"banana")} }
143
141
  it "returns the diff" do
144
- expect(structure_diff(expected, actual)).to eq difference
142
+ expect(type_diff(expected, actual)).to eq difference
145
143
  end
146
144
  end
147
145
  end
146
+
147
+ context "when unexpected keys are allowed" do
148
+ let(:expected) { { a: 'b' } }
149
+ let(:actual) { {a: 'c', d: 'e'} }
150
+ let(:difference) { {} }
151
+ it "returns the diff" do
152
+ expect(type_diff(expected, actual, allow_unexpected_keys: true)).to eq difference
153
+ end
154
+ end
155
+
156
+ context "when unexpected keys are not allowed" do
157
+ let(:expected) { { a: 'b' } }
158
+ let(:actual) { {a: 'c', d: 'e'} }
159
+ let(:difference) { {d: Difference.new(Pact::UnexpectedKey.new, 'e')} }
160
+ it "returns the diff" do
161
+ expect(type_diff(expected, actual, allow_unexpected_keys: false)).to eq difference
162
+ end
163
+ end
148
164
  end
149
165
 
150
166
  describe 'diffing' do
@@ -367,7 +383,7 @@ module Pact::Matchers
367
383
  context "a deep mismatch" do
368
384
  subject { {a: {b: { c: [1,2]}, d: { e: Pact::Term.new(matcher: /a/, generate: 'apple')}}, f: 1, g: {h: 99}} }
369
385
  let(:actual) { {a: {b: { c: [1,2]}, d: { e: 'food'}}, f: "thing"} }
370
- let(:difference) { {:a=>{:d=>{:e=> Difference.new(/a/, "food")}},
386
+ let(:difference) { {:a=>{:d=>{:e=> RegexpDifference.new(/a/, "food")}},
371
387
  :f=> Difference.new(1, "thing"),
372
388
  :g=>Difference.new({:h=>99}, Pact::KeyNotFound.new)} }
373
389
 
@@ -0,0 +1,20 @@
1
+ require 'spec_helper'
2
+ require 'pact/matchers/regexp_difference'
3
+
4
+ module Pact
5
+ module Matchers
6
+ describe RegexpDifference do
7
+
8
+ context "when a regexp is expected" do
9
+
10
+ subject { RegexpDifference.new(/ap/, 'pear').as_json }
11
+
12
+ it "indicates that the actual was indended 'to match'" do
13
+ expect(subject).to eq({:EXPECTED_TO_MATCH => "/ap/", :ACTUAL => "pear"})
14
+ end
15
+
16
+ end
17
+
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,34 @@
1
+ require 'spec_helper'
2
+ require 'pact/matchers/type_difference'
3
+
4
+ module Pact
5
+ module Matchers
6
+ describe TypeDifference do
7
+
8
+ describe "#as_json" do
9
+
10
+ let(:expected) { ExpectedType.new("Fred") }
11
+ let(:actual) { ActualType.new(1) }
12
+ subject { TypeDifference.new expected, actual }
13
+
14
+ context "when the actual is a KeyNotFound" do
15
+ let(:actual) { KeyNotFound.new }
16
+ let(:expected_hash) { {:EXPECTED_TYPE => "String", :ACTUAL => actual.to_s } }
17
+
18
+ it "use the key ACTUAL" do
19
+ expect(subject.as_json).to eq(expected_hash)
20
+ end
21
+ end
22
+
23
+ context "when the actual is an ActualType" do
24
+ let(:expected_hash) { {:EXPECTED_TYPE => "String", :ACTUAL_TYPE => "Fixnum" } }
25
+
26
+ it "uses the key ACTUAL_TYPE" do
27
+ expect(subject.as_json).to eq(expected_hash)
28
+ end
29
+ end
30
+
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,20 @@
1
+ require 'spec_helper'
2
+ require 'pact/matchers/unexpected_index'
3
+
4
+ module Pact
5
+ describe UnexpectedIndex do
6
+
7
+ describe "#as_json" do
8
+ it "returns a string representation of the object" do
9
+ expect(subject.as_json).to eq subject.to_s
10
+ end
11
+ end
12
+
13
+ describe "#to_json" do
14
+ it "serialises the object to JSON" do
15
+ expect(subject.to_json).to eq "\"#{subject.to_s}\""
16
+ end
17
+ end
18
+
19
+ end
20
+ end