pact 1.1.0 → 1.1.1

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 (66) hide show
  1. data/CHANGELOG.md +31 -20
  2. data/Gemfile.lock +12 -12
  3. data/README.md +32 -16
  4. data/Rakefile +3 -3
  5. data/documentation/README.md +1 -0
  6. data/documentation/development-workflow.md +22 -0
  7. data/documentation/faq.md +8 -0
  8. data/documentation/provider-states.md +2 -0
  9. data/documentation/troubleshooting.md +4 -0
  10. data/documentation/verifying-pacts.md +97 -0
  11. data/lib/pact/app.rb +98 -4
  12. data/lib/pact/consumer/rspec.rb +3 -2
  13. data/lib/pact/doc/doc_file.rb +4 -4
  14. data/lib/pact/doc/generator.rb +3 -3
  15. data/lib/pact/doc/interaction_view_model.rb +1 -0
  16. data/lib/pact/doc/markdown/{interactions_renderer.rb → consumer_contract_renderer.rb} +1 -1
  17. data/lib/pact/doc/markdown/generator.rb +2 -2
  18. data/lib/pact/matchers/unix_diff_formatter.rb +1 -1
  19. data/lib/pact/project_root.rb +7 -0
  20. data/lib/pact/provider.rb +0 -1
  21. data/lib/pact/provider/context.rb +0 -0
  22. data/lib/pact/provider/matchers/messages.rb +15 -13
  23. data/lib/pact/provider/pact_spec_runner.rb +21 -22
  24. data/lib/pact/provider/rspec.rb +22 -15
  25. data/lib/pact/provider/rspec/custom_options_file +0 -0
  26. data/lib/pact/provider/{matchers.rb → rspec/matchers.rb} +2 -1
  27. data/lib/pact/rspec.rb +20 -0
  28. data/lib/pact/shared/request.rb +1 -1
  29. data/lib/pact/tasks/task_helper.rb +18 -15
  30. data/lib/pact/tasks/verification_task.rb +26 -32
  31. data/lib/pact/version.rb +1 -1
  32. data/lib/tasks/pact.rake +5 -11
  33. data/spec/integration/pact/consumer_configuration_spec.rb +3 -3
  34. data/spec/lib/pact/app_spec.rb +47 -0
  35. data/spec/lib/pact/consumer/app_manager_spec.rb +1 -1
  36. data/spec/lib/pact/consumer/mock_service/interaction_list_spec.rb +3 -3
  37. data/spec/lib/pact/consumer/mock_service/verification_get_spec.rb +10 -2
  38. data/spec/lib/pact/consumer/mock_service_interaction_expectation_spec.rb +2 -2
  39. data/spec/lib/pact/consumer_contract/consumer_contract_spec.rb +1 -1
  40. data/spec/lib/pact/consumer_contract/interaction_spec.rb +4 -4
  41. data/spec/lib/pact/consumer_contract/request_spec.rb +23 -23
  42. data/spec/lib/pact/doc/generator_spec.rb +4 -4
  43. data/spec/lib/pact/doc/markdown/{interactions_renderer_spec.rb → consumer_contract_renderer_spec.rb} +4 -4
  44. data/spec/lib/pact/matchers/unix_diff_formatter_spec.rb +8 -8
  45. data/spec/lib/pact/provider/configuration/configuration_extension_spec.rb +2 -2
  46. data/spec/lib/pact/provider/matchers/messages_spec.rb +17 -6
  47. data/spec/lib/pact/provider/rspec/formatter_spec.rb +3 -1
  48. data/spec/lib/pact/shared/dsl_spec.rb +1 -1
  49. data/spec/lib/pact/shared/request_spec.rb +8 -0
  50. data/spec/lib/pact/tasks/task_helper_spec.rb +39 -54
  51. data/spec/lib/pact/tasks/verification_task_spec.rb +75 -0
  52. data/spec/pact_specification/compliance-1.0.0.rb +47 -0
  53. data/spec/spec_helper.rb +2 -6
  54. data/spec/standalone/consumer_fail_test.rb +1 -0
  55. data/spec/standalone/consumer_pass_test.rb +1 -0
  56. data/spec/support/active_support_if_configured.rb +6 -0
  57. data/spec/support/pact_helper.rb +2 -1
  58. data/spec/support/shared_examples_for_request.rb +15 -4
  59. data/spec/support/spec_support.rb +3 -0
  60. data/spec/support/stubbing_using_allow.rb +1 -0
  61. data/spec/support/term.json +13 -1
  62. data/tasks/pact-test.rake +45 -26
  63. metadata +23 -13
  64. data/lib/pact/provider/client_project_pact_helper.rb +0 -4
  65. data/spec/lib/pact/provider/pact_spec_runner_spec.rb +0 -7
  66. data/spec/lib/pact/verification_task_spec.rb +0 -99
@@ -1,12 +1,12 @@
1
1
  require 'spec_helper'
2
- require 'pact/doc/markdown/interactions_renderer'
2
+ require 'pact/doc/markdown/consumer_contract_renderer'
3
3
 
4
4
  module Pact
5
5
  module Doc
6
6
  module Markdown
7
- describe InteractionsRenderer do
7
+ describe ConsumerContractRenderer do
8
8
 
9
- subject { InteractionsRenderer.new(consumer_contract) }
9
+ subject { ConsumerContractRenderer.new(consumer_contract) }
10
10
  let(:consumer_contract) { Pact::ConsumerContract.from_uri './spec/support/markdown_pact.json' }
11
11
 
12
12
  let(:expected_output) { File.read("./spec/support/generated_markdown.md") }
@@ -19,7 +19,7 @@ module Pact
19
19
 
20
20
  describe ".call" do
21
21
  it "renders an interaction" do
22
- expect(InteractionsRenderer.call consumer_contract).to eq(expected_output)
22
+ expect(ConsumerContractRenderer.call consumer_contract).to eq(expected_output)
23
23
  end
24
24
  end
25
25
 
@@ -54,7 +54,7 @@ EOF
54
54
  end
55
55
 
56
56
  it "generates the right number of lines, even with ActiveSupport loaded" do
57
- expect(line_count).to eq 10
57
+ expect(line_count).to eq 9
58
58
  end
59
59
 
60
60
  end
@@ -76,7 +76,7 @@ EOF
76
76
  end
77
77
 
78
78
  it "generates the right number of lines, even with ActiveSupport loaded" do
79
- expect(line_count).to eq 10
79
+ expect(line_count).to eq 9
80
80
  end
81
81
 
82
82
  end
@@ -98,7 +98,7 @@ EOF
98
98
  end
99
99
 
100
100
  it "generates the right number of lines, even with ActiveSupport loaded" do
101
- expect(line_count).to eq 6
101
+ expect(line_count).to eq 5
102
102
  end
103
103
 
104
104
  end
@@ -120,7 +120,7 @@ EOF
120
120
  end
121
121
 
122
122
  it "generates the right number of lines, even with ActiveSupport loaded" do
123
- expect(line_count).to eq 9
123
+ expect(line_count).to eq 8
124
124
  end
125
125
  end
126
126
 
@@ -140,7 +140,7 @@ EOF
140
140
  end
141
141
 
142
142
  it "generates the right number of lines, even with ActiveSupport loaded" do
143
- expect(line_count).to eq 9
143
+ expect(line_count).to eq 8
144
144
  end
145
145
 
146
146
  end
@@ -159,7 +159,7 @@ EOF
159
159
  end
160
160
 
161
161
  it "generates the right number of lines, even with ActiveSupport loaded" do
162
- expect(line_count).to eq 9
162
+ expect(line_count).to eq 8
163
163
  end
164
164
 
165
165
  end
@@ -185,7 +185,7 @@ EOF
185
185
  end
186
186
 
187
187
  it "generates the right number of lines, even with ActiveSupport loaded" do
188
- expect(line_count).to eq 9
188
+ expect(line_count).to eq 8
189
189
  end
190
190
 
191
191
  end
@@ -203,7 +203,7 @@ EOF
203
203
  end
204
204
 
205
205
  it "generates the right number of lines, even with ActiveSupport loaded" do
206
- expect(line_count).to eq 12
206
+ expect(line_count).to eq 11
207
207
  end
208
208
 
209
209
  end
@@ -14,12 +14,12 @@ module Pact
14
14
  describe "#color_enabled" do
15
15
 
16
16
  it "sets color_enabled to be true by default" do
17
- expect(subject.color_enabled).to be_true
17
+ expect(subject.color_enabled).to be true
18
18
  end
19
19
 
20
20
  it "allows configuration of colour_enabled" do
21
21
  subject.color_enabled = false
22
- expect(subject.color_enabled).to be_false
22
+ expect(subject.color_enabled).to be false
23
23
  end
24
24
 
25
25
  end
@@ -10,9 +10,11 @@ module Pact
10
10
  describe "#match_term_failure_message" do
11
11
 
12
12
  let(:message) { "line1\nline2"}
13
+ let(:output_message) { "Actual: actual\n\n#{message}"}
14
+ let(:output_message_with_resets) { "Actual: actual\n\n#{r}line1\n#{r}line2"}
13
15
  let(:r) { ::Term::ANSIColor.reset }
14
- let(:message_with_resets) { "#{r}line1\n#{r}line2"}
15
16
  let(:diff) { double("diff") }
17
+ let(:actual) { "actual" }
16
18
  let(:color_enabled) { true }
17
19
  let(:ansi_reset_at_start_of_line) { /^#{Regexp.escape ::Term::ANSIColor.reset}/ }
18
20
  let(:message_line_count) { message.split("\n").size }
@@ -21,7 +23,7 @@ module Pact
21
23
  allow(Pact.configuration.diff_formatter).to receive(:call).and_return(message)
22
24
  end
23
25
 
24
- subject { match_term_failure_message diff, color_enabled }
26
+ subject { match_term_failure_message diff, actual, color_enabled }
25
27
 
26
28
  it "creates a message using the configured diff_formatter" do
27
29
  expect(Pact.configuration.diff_formatter).to receive(:call).with(diff)
@@ -31,17 +33,26 @@ module Pact
31
33
  context "when color_enabled is true" do
32
34
 
33
35
  it "returns the message with ANSI reset at the start of each line" do
34
- expect(subject).to eq(message_with_resets)
36
+ expect(subject).to eq(output_message_with_resets)
35
37
  end
36
38
 
37
39
  end
38
40
 
41
+ context "when the actual is not a string" do
42
+
43
+ let(:actual) { {the: "actual"} }
44
+
45
+ it "includes the actual as json" do
46
+ expect(subject).to include(actual.to_json)
47
+ end
48
+ end
49
+
39
50
  context "when color_enabled is false" do
40
51
 
41
52
  let(:color_enabled) { false }
42
53
 
43
54
  it "returns the message unmodified" do
44
- expect(subject).to eq(message)
55
+ expect(subject).to eq(output_message)
45
56
  end
46
57
 
47
58
  end
@@ -88,9 +99,9 @@ module Pact
88
99
 
89
100
  end
90
101
 
91
- context "when the expected is a Pact::Term" do
102
+ context "when the expected is a regexp" do
92
103
 
93
- let(:expected) { Pact::Term.new(matcher: /hal/, generate: 'application/hal+json')}
104
+ let(:expected) { /hal/ }
94
105
  let(:expected_message) { "Expected header \"Content-Type\" to match /hal/, but was \"text/plain\"" }
95
106
 
96
107
  it "creates a message with the term's matcher" do
@@ -1,6 +1,7 @@
1
1
  require 'spec_helper'
2
2
  require 'pact/provider/rspec/formatter'
3
3
  require './spec/support/factories'
4
+ require './spec/support/spec_support'
4
5
 
5
6
  module Pact
6
7
  module Provider
@@ -18,7 +19,8 @@ module Pact
18
19
  let(:missing_provider_states) { 'missing_provider_states'}
19
20
 
20
21
  subject { Formatter.new output }
21
- let(:output_result) { output.string }
22
+
23
+ let(:output_result) { Pact::SpecSupport.remove_ansicolor output.string }
22
24
 
23
25
  before do
24
26
  allow(PrintMissingProviderStates).to receive(:call)
@@ -79,7 +79,7 @@ module Pact
79
79
  end
80
80
 
81
81
  it "calls finalize" do
82
- expect(@test.finalized).to be_true
82
+ expect(@test.finalized).to be true
83
83
  end
84
84
  end
85
85
  end
@@ -72,6 +72,14 @@ module Pact
72
72
  expect(subject).to eq("GET /something")
73
73
  end
74
74
  end
75
+
76
+ context "with a query" do
77
+ subject { TestRequest.new("get", "/something", {}, {} , "test=query").method_and_path }
78
+
79
+ it "includes the query" do
80
+ expect(subject).to eq("GET /something?test=query")
81
+ end
82
+ end
75
83
  end
76
84
 
77
85
  end
@@ -1,80 +1,65 @@
1
1
  require 'spec_helper'
2
2
  require 'pact/tasks/task_helper'
3
+ require 'rake/file_utils'
3
4
 
4
5
  module Pact
5
6
  describe TaskHelper do
6
- include TaskHelper
7
7
 
8
- let(:env_description) { "pact description set in ENV"}
9
- let(:env_provider_state) { "provider state set in ENV"}
10
- let(:env_criteria){ {:description=>/#{env_description}/, :provider_state=>/#{env_provider_state}/} }
11
- let(:default_description) { "default description"}
12
- let(:default_provider_state) { "default provider state"}
13
8
 
14
- shared_context "PACT_DESCRIPTION is defined" do
15
- before do
16
- ENV.stub(:[])
17
- ENV.stub(:[]).with("PACT_DESCRIPTION").and_return(env_description)
18
- end
19
- end
9
+ describe ".execute_pact_verify" do
10
+ let(:ruby_path) { "/path/to/ruby" }
11
+ let(:pact_uri) { "/pact/uri" }
12
+ let(:default_pact_helper_path) { "/pact/helper/path.rb" }
20
13
 
21
- shared_context 'PACT_PROVIDER_STATE is defined' do
22
14
  before do
23
- ENV.stub(:[])
24
- ENV.stub(:[]).with("PACT_PROVIDER_STATE").and_return(env_provider_state)
15
+ stub_const("FileUtils::RUBY", ruby_path)
16
+ allow(Pact::Provider::PactHelperLocater).to receive(:pact_helper_path).and_return(default_pact_helper_path)
25
17
  end
26
- end
27
-
28
- shared_context 'default description is defined' do
29
- let(:default_description) { "default description"}
30
- end
31
-
32
- let(:defaults) { {:description => default_description, :provider_state => default_provider_state} }
33
-
34
- describe "spec_criteria" do
35
18
 
36
- context "when ENV variables are defined" do
37
- before do
38
- ENV.stub(:fetch).with("PACT_DESCRIPTION", anything).and_return(env_description)
39
- ENV.stub(:fetch).with("PACT_PROVIDER_STATE", anything).and_return(env_provider_state)
40
- end
41
-
42
- context "when defaults are not passed in" do
43
- it "returns the env vars as regexes" do
44
- expect(spec_criteria).to eq(env_criteria)
45
- end
19
+ context "with no pact_helper or pact URI" do
20
+ let(:command) { "#{ruby_path} -S pact verify -h #{default_pact_helper_path}" }
21
+ it "executes the command" do
22
+ expect(TaskHelper).to receive(:execute_cmd).with(command)
23
+ TaskHelper.execute_pact_verify
46
24
  end
25
+ end
47
26
 
48
- context "when defaults are passed in" do
49
- it "returns the env vars as regexes" do
50
- expect(spec_criteria(defaults)).to eq(env_criteria)
51
- end
27
+ context "with a pact URI" do
28
+ let(:command) { "#{ruby_path} -S pact verify -h #{default_pact_helper_path} -p #{pact_uri}" }
29
+ it "executes the command" do
30
+ expect(TaskHelper).to receive(:execute_cmd).with(command)
31
+ TaskHelper.execute_pact_verify(pact_uri)
52
32
  end
53
33
  end
54
34
 
55
- context "when ENV variables are not defined" do
56
- context "when defaults are passed in" do
57
- it "returns the defaults as regexes" do
58
- expect(spec_criteria(defaults)).to eq({:description=>/#{default_description}/, :provider_state=>/#{default_provider_state}/})
59
- end
60
- end
61
- context "when defaults are not passed in" do
62
- it "returns an empty hash" do
63
- expect(spec_criteria).to eq({})
64
- end
35
+ context "with a pact URI and a pact_helper" do
36
+ let(:custom_pact_helper_path) { '/custom/pact_helper.rb' }
37
+ let(:command) { "#{ruby_path} -S pact verify -h #{custom_pact_helper_path} -p #{pact_uri}" }
38
+ it "executes the command" do
39
+ expect(TaskHelper).to receive(:execute_cmd).with(command)
40
+ TaskHelper.execute_pact_verify(pact_uri, custom_pact_helper_path)
65
41
  end
66
42
  end
67
43
 
68
- context "when provider state is an empty string" do
69
- before do
70
- ENV.stub(:fetch).with(anything, anything).and_return(nil)
71
- ENV.stub(:fetch).with("PACT_PROVIDER_STATE", anything).and_return('')
44
+ context "with a pact_helper with no .rb on the end" do
45
+ let(:custom_pact_helper_path) { '/custom/pact_helper' }
46
+ let(:command) { "#{ruby_path} -S pact verify -h #{custom_pact_helper_path}.rb -p #{pact_uri}" }
47
+ it "executes the command" do
48
+ expect(TaskHelper).to receive(:execute_cmd).with(command)
49
+ TaskHelper.execute_pact_verify(pact_uri, custom_pact_helper_path)
72
50
  end
51
+ end
73
52
 
74
- it "returns a nil provider state so that it matches a nil provider state on the interaction" do
75
- expect(spec_criteria[:provider_state]).to be_nil
53
+ context "with a pact URI and a nil pact_helper" do
54
+ let(:command) { "#{ruby_path} -S pact verify -h #{default_pact_helper_path} -p #{pact_uri}" }
55
+ it "executes the command" do
56
+ expect(TaskHelper).to receive(:execute_cmd).with(command)
57
+ TaskHelper.execute_pact_verify(pact_uri, nil)
76
58
  end
77
59
  end
60
+
78
61
  end
62
+
63
+
79
64
  end
80
65
  end
@@ -0,0 +1,75 @@
1
+ require 'spec_helper'
2
+ require 'pact/tasks/verification_task'
3
+
4
+ module Pact
5
+ describe VerificationTask do
6
+ before :all do
7
+ @pact_helper = '/custom/path/pact_helper .rb'
8
+ @pact_uri = 'http://example.org/pact.json'
9
+ @task_name = 'pact:verify:pact_rake_spec'
10
+ @task_name_with_explict_pact_helper = 'pact:verify:pact_rake_spec_with_explict_pact_helper'
11
+ @consumer = 'some-consumer'
12
+ @criteria = {:description => /wiffle/}
13
+
14
+ VerificationTask.new(:pact_rake_spec_with_explict_pact_helper) do | pact |
15
+ pact.uri @pact_uri, pact_helper: @pact_helper
16
+ end
17
+
18
+ VerificationTask.new(:pact_rake_spec) do | pact |
19
+ pact.uri @pact_uri
20
+ end
21
+ end
22
+
23
+ before do
24
+ allow(Pact::TaskHelper).to receive(:execute_pact_verify).and_return(0)
25
+ end
26
+
27
+ let(:exit_code) {0}
28
+
29
+
30
+ describe '.initialize' do
31
+ context 'with an explict pact_helper' do
32
+ it 'creates the tasks' do
33
+ Rake::Task.tasks.should include_task @task_name
34
+ end
35
+ end
36
+ context 'with no explict pact_helper' do
37
+ it 'creates the tasks' do
38
+ Rake::Task.tasks.should include_task @task_name_with_explict_pact_helper
39
+ end
40
+ end
41
+ end
42
+
43
+ describe 'execute' do
44
+
45
+ context "with no explicit pact_helper" do
46
+ it 'verifies the pacts using the TaskHelper' do
47
+ expect(Pact::TaskHelper).to receive(:execute_pact_verify).with(@pact_uri, nil)
48
+ Rake::Task[@task_name].execute
49
+ end
50
+ end
51
+
52
+ context "with an explict pact_helper" do
53
+ let(:verification_config) { [ uri: @pact_uri, pact_helper: @pact_helper] }
54
+ it 'verifies the pacts using the TaskHelper' do
55
+ expect(Pact::TaskHelper).to receive(:execute_pact_verify).with(@pact_uri, @pact_helper)
56
+ Rake::Task[@task_name_with_explict_pact_helper].execute
57
+ end
58
+ end
59
+
60
+ context 'when all specs pass' do
61
+
62
+ it 'does not raise an exception' do
63
+ Rake::Task[@task_name].execute
64
+ end
65
+ end
66
+
67
+ end
68
+ end
69
+ end
70
+
71
+ RSpec::Matchers.define :include_task do |expected|
72
+ match do |actual|
73
+ actual.any? { |task| task.name == expected }
74
+ end
75
+ end
@@ -0,0 +1,47 @@
1
+ require 'spec_helper'
2
+ require 'pact/consumer/request'
3
+ require 'pact/consumer_contract/request'
4
+
5
+ PACT_SPEC_DIR = "../pact-specification/testcases"
6
+ REQUEST_TEST_CASE_FOLDERS = Dir.glob("#{PACT_SPEC_DIR}/request/**")
7
+ REQUEST_TEST_CASE_FILES = Dir.glob("#{PACT_SPEC_DIR}/request/**/*.json")
8
+
9
+ TEST_DESCRIPTIONS = {true => "matches", false => "does not match"}
10
+
11
+ describe "Pact gem complicance with Pact Specification 1.0.0" do
12
+
13
+ directories = Dir.glob("#{PACT_SPEC_DIR}/*")
14
+
15
+ directories.each do | dir_name |
16
+
17
+ describe File.basename(dir_name) do
18
+
19
+ sub_directories = Dir.glob("#{dir_name}/*")
20
+
21
+ sub_directories.each do | sub_dir_name |
22
+
23
+ context File.basename(sub_dir_name) do
24
+ testcases = Dir.glob("#{sub_dir_name}/**/*.json")
25
+
26
+ testcases.each do | file_name |
27
+
28
+ context File.basename(file_name).chomp(".json") do
29
+
30
+ file_content = JSON.parse(File.read(file_name))
31
+ expected = Pact::Request::Expected.from_hash(file_content["expected"])
32
+ actual = Pact::Consumer::Request::Actual.from_hash(file_content["actual"])
33
+ expected_result = file_content.fetch("match")
34
+ comment = file_content["comment"]
35
+
36
+ it "#{TEST_DESCRIPTIONS[expected_result]} - #{comment}" do
37
+ expect(expected.matches?(actual)).to eq expected_result
38
+ end
39
+
40
+ end
41
+
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end