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
@@ -1,180 +1,7 @@
1
- require 'pact/provider/pact_verification'
2
- require 'pact/shared/dsl'
1
+ require 'pact/provider/configuration/dsl'
2
+ require 'pact/provider/configuration/configuration_extension'
3
3
  require 'pact/provider/state/provider_state'
4
- require 'pact/provider/state/provider_state_configured_modules'
5
- require 'pact/matchers/plus_minus_diff_decorator'
6
- require 'pact/matchers/nested_json_diff_decorator'
7
4
 
8
- # TODO break this class up!
9
-
10
- module Pact
11
-
12
- module Provider
13
-
14
- module DSL
15
- def service_provider name, &block
16
- Configuration::ServiceProviderDSL.build(name, &block)
17
- end
18
- end
19
-
20
- Pact.send(:extend, Pact::Provider::DSL)
21
- Pact.send(:extend, Pact::Provider::State::DSL)
22
-
23
- module Configuration
24
-
25
- module ConfigurationExtension
26
-
27
- DIFF_FORMATTERS = {
28
- :nested_json => Pact::Matchers::NestedJsonDiffDecorator,
29
- :plus_and_minus => Pact::Matchers::PlusMinusDiffDecorator
30
- }
31
-
32
- def provider= provider
33
- @provider = provider
34
- end
35
-
36
- def provider
37
- if defined? @provider
38
- @provider
39
- else
40
- raise "Please configure your provider. See the Provider section in the README for examples."
41
- end
42
- end
43
-
44
- def add_pact_verification verification
45
- pact_verifications << verification
46
- end
47
-
48
- def pact_verifications
49
- @pact_verifications ||= []
50
- end
51
-
52
- def config_ru_path
53
- @config_ru_path ||= './config.ru'
54
- end
55
-
56
- def config_ru_path= config_ru_path
57
- @config_ru_path = config_ru_path
58
- end
59
-
60
- def color_enabled
61
- # Can't use ||= when the variable might be false, it will execute the expression if it's false
62
- defined?(@color_enabled) ? @color_enabled : true
63
- end
64
-
65
- def color_enabled= color_enabled
66
- @color_enabled = color_enabled
67
- end
68
-
69
- def diff_format= diff_format
70
- @diff_format = diff_format
71
- end
72
-
73
- def diff_format
74
- @diff_format ||= :nested_json
75
- end
76
-
77
- def diff_formatter_class
78
- DIFF_FORMATTERS.fetch(diff_format)
79
- end
80
-
81
- def include mod
82
- Pact::Provider::State::ProviderStateConfiguredModules.instance_eval do
83
- include mod
84
- end
85
- end
86
-
87
- end
88
-
89
- Pact::Configuration.send(:include, ConfigurationExtension)
90
-
91
- class ServiceProviderConfig
92
-
93
- def initialize &app_block
94
- @app_block = app_block
95
- end
96
-
97
- def app
98
- @app_block.call
99
- end
100
- end
101
-
102
- class PactVerification
103
- extend Pact::DSL
104
-
105
- attr_accessor :consumer_name, :pact_uri, :ref
106
-
107
- def initialize consumer_name, options = {}
108
- @consumer_name = consumer_name
109
- @ref = options.fetch(:ref, :head)
110
- @pact_uri = nil
111
- end
112
-
113
- dsl do
114
- def pact_uri pact_uri
115
- self.pact_uri = pact_uri
116
- end
117
- end
118
-
119
- def finalize
120
- validate
121
- create_pact_verification
122
- end
123
-
124
- private
125
-
126
- def create_pact_verification
127
- verification = Pact::Provider::PactVerification.new(consumer_name, pact_uri, ref)
128
- Pact.configuration.add_pact_verification verification
129
- end
130
-
131
- def validate
132
- raise "Please provide a pact_uri for the verification" unless pact_uri
133
- end
134
-
135
- end
136
-
137
- class ServiceProviderDSL
138
- extend Pact::DSL
139
-
140
- attr_accessor :name, :app_block
141
-
142
- CONFIG_RU_APP = lambda { Rack::Builder.parse_file(Pact.configuration.config_ru_path).first }
143
-
144
- def initialize name
145
- @name = name
146
- @app_block = CONFIG_RU_APP
147
- end
148
-
149
- dsl do
150
- def app &block
151
- self.app_block = block
152
- end
153
-
154
- def honours_pact_with consumer_name, options = {}, &block
155
- create_pact_verification consumer_name, options, &block
156
- end
157
- end
158
-
159
- def create_pact_verification consumer_name, options, &block
160
- PactVerification.build(consumer_name, options, &block)
161
- end
162
-
163
- def finalize
164
- validate
165
- create_service_provider
166
- end
167
-
168
- private
169
-
170
- def validate
171
- raise "Please provide a name for the Provider" unless name && !name.strip.empty?
172
- end
173
-
174
- def create_service_provider
175
- Pact.configuration.provider = ServiceProviderConfig.new(&@app_block)
176
- end
177
- end
178
- end
179
- end
180
- end
5
+ Pact.send(:extend, Pact::Provider::DSL)
6
+ Pact.send(:extend, Pact::Provider::State::DSL)
7
+ Pact::Configuration.send(:include, Pact::Provider::Configuration::ConfigurationExtension)
@@ -0,0 +1,58 @@
1
+ require 'pact/provider/state/provider_state'
2
+ require 'pact/provider/state/provider_state_configured_modules'
3
+
4
+ module Pact
5
+
6
+ module Provider
7
+
8
+ module Configuration
9
+
10
+ module ConfigurationExtension
11
+
12
+ def provider= provider
13
+ @provider = provider
14
+ end
15
+
16
+ def provider
17
+ if defined? @provider
18
+ @provider
19
+ else
20
+ raise "Please configure your provider. See the Provider section in the README for examples."
21
+ end
22
+ end
23
+
24
+ def add_pact_verification verification
25
+ pact_verifications << verification
26
+ end
27
+
28
+ def pact_verifications
29
+ @pact_verifications ||= []
30
+ end
31
+
32
+ def config_ru_path
33
+ @config_ru_path ||= './config.ru'
34
+ end
35
+
36
+ def config_ru_path= config_ru_path
37
+ @config_ru_path = config_ru_path
38
+ end
39
+
40
+ def color_enabled
41
+ # Can't use ||= when the variable might be false, it will execute the expression if it's false
42
+ defined?(@color_enabled) ? @color_enabled : true
43
+ end
44
+
45
+ def color_enabled= color_enabled
46
+ @color_enabled = color_enabled
47
+ end
48
+
49
+ def include mod
50
+ Pact::Provider::State::ProviderStateConfiguredModules.instance_eval do
51
+ include mod
52
+ end
53
+ end
54
+
55
+ end
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,13 @@
1
+ require 'pact/provider/configuration/service_provider_dsl'
2
+
3
+ module Pact
4
+
5
+ module Provider
6
+
7
+ module DSL
8
+ def service_provider name, &block
9
+ Configuration::ServiceProviderDSL.build(name, &block)
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,46 @@
1
+ require 'pact/provider/pact_verification'
2
+ require 'pact/shared/dsl'
3
+
4
+ module Pact
5
+ module Provider
6
+
7
+ module Configuration
8
+
9
+ class PactVerification
10
+
11
+ extend Pact::DSL
12
+
13
+ attr_accessor :consumer_name, :pact_uri, :ref
14
+
15
+ def initialize consumer_name, options = {}
16
+ @consumer_name = consumer_name
17
+ @ref = options.fetch(:ref, :head)
18
+ @pact_uri = nil
19
+ end
20
+
21
+ dsl do
22
+ def pact_uri pact_uri
23
+ self.pact_uri = pact_uri
24
+ end
25
+ end
26
+
27
+ def finalize
28
+ validate
29
+ create_pact_verification
30
+ end
31
+
32
+ private
33
+
34
+ def create_pact_verification
35
+ verification = Pact::Provider::PactVerification.new(consumer_name, pact_uri, ref)
36
+ Pact.configuration.add_pact_verification verification
37
+ end
38
+
39
+ def validate
40
+ raise "Please provide a pact_uri for the verification" unless pact_uri
41
+ end
42
+
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,16 @@
1
+ module Pact
2
+ module Provider
3
+ module Configuration
4
+ class ServiceProviderConfig
5
+
6
+ def initialize &app_block
7
+ @app_block = app_block
8
+ end
9
+
10
+ def app
11
+ @app_block.call
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,54 @@
1
+ require 'pact/provider/configuration/pact_verification'
2
+ require 'pact/provider/configuration/service_provider_config'
3
+
4
+ module Pact
5
+
6
+ module Provider
7
+
8
+ module Configuration
9
+
10
+ class ServiceProviderDSL
11
+
12
+ extend Pact::DSL
13
+
14
+ attr_accessor :name, :app_block
15
+
16
+ CONFIG_RU_APP = lambda { Rack::Builder.parse_file(Pact.configuration.config_ru_path).first }
17
+
18
+ def initialize name
19
+ @name = name
20
+ @app_block = CONFIG_RU_APP
21
+ end
22
+
23
+ dsl do
24
+ def app &block
25
+ self.app_block = block
26
+ end
27
+
28
+ def honours_pact_with consumer_name, options = {}, &block
29
+ create_pact_verification consumer_name, options, &block
30
+ end
31
+ end
32
+
33
+ def create_pact_verification consumer_name, options, &block
34
+ PactVerification.build(consumer_name, options, &block)
35
+ end
36
+
37
+ def finalize
38
+ validate
39
+ create_service_provider
40
+ end
41
+
42
+ private
43
+
44
+ def validate
45
+ raise "Please provide a name for the Provider" unless name && !name.strip.empty?
46
+ end
47
+
48
+ def create_service_provider
49
+ Pact.configuration.provider = ServiceProviderConfig.new(&@app_block)
50
+ end
51
+ end
52
+ end
53
+ end
54
+ end
@@ -1,25 +1,33 @@
1
- require 'pact/term'
2
- require 'awesome_print'
3
- require 'pact/matchers'
4
- require 'awesome_print'
5
1
  require 'rspec'
6
- require 'pact/matchers/nested_json_diff_decorator'
7
- require 'pact/matchers/diff_decorator'
2
+ require 'pact/matchers'
3
+ require 'pact/provider/matchers/messages'
8
4
 
9
5
  RSpec::Matchers.define :match_term do |expected|
6
+
7
+ include Pact::Matchers
8
+ include Pact::Matchers::Messages
9
+
10
+ match do |actual|
11
+ (@difference = diff(expected, actual)).empty?
12
+ end
13
+
14
+ failure_message_for_should do | actual |
15
+ match_term_failure_message @difference, ::RSpec.configuration.color_enabled
16
+ end
17
+
18
+ end
19
+
20
+ RSpec::Matchers.define :match_header do |header_name, expected|
21
+
10
22
  include Pact::Matchers
23
+ include Pact::Matchers::Messages
11
24
 
12
25
  match do |actual|
13
- if (difference = diff(expected, actual)).any?
14
- @diff_decorator = Pact.configuration.diff_formatter_class.new(difference)
15
- false
16
- else
17
- true
18
- end
26
+ diff(expected, actual).empty?
19
27
  end
20
28
 
21
29
  failure_message_for_should do | actual |
22
- @diff_decorator.to_s
30
+ match_header_failure_message header_name, expected, actual
23
31
  end
24
32
 
25
33
  end
@@ -0,0 +1,43 @@
1
+ require 'term/ansicolor'
2
+ require 'pact/term'
3
+
4
+ module Pact
5
+ module Matchers
6
+ module Messages
7
+
8
+ def match_term_failure_message diff, color_enabled
9
+ message = Pact.configuration.diff_formatter.call(diff)
10
+
11
+ if color_enabled
12
+ # RSpec wraps each line in the failure message with failure_color, turning it red.
13
+ # To ensure the lines in the diff that should be white, stay white, put an
14
+ # ANSI reset at the start of each line.
15
+ message.split("\n").collect{ |line| ::Term::ANSIColor.reset + line }.join("\n")
16
+ else
17
+ message
18
+ end
19
+
20
+ end
21
+
22
+ def match_header_failure_message header_name, expected, actual
23
+ "Expected header \"#{header_name}\" to #{expected_desc(expected)}, but was #{actual_desc(actual)}"
24
+ end
25
+
26
+ private
27
+
28
+ def expected_desc expected
29
+ case expected
30
+ when Pact::Term then "match #{expected.matcher.inspect}"
31
+ when NilClass then "be nil"
32
+ else
33
+ "match \"#{expected}\""
34
+ end
35
+ end
36
+
37
+ def actual_desc actual
38
+ actual.nil? ? 'nil' : '"' + actual + '"'
39
+ end
40
+
41
+ end
42
+ end
43
+ end