pact 1.1.0 → 1.1.1
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG.md +31 -20
- data/Gemfile.lock +12 -12
- data/README.md +32 -16
- data/Rakefile +3 -3
- data/documentation/README.md +1 -0
- data/documentation/development-workflow.md +22 -0
- data/documentation/faq.md +8 -0
- data/documentation/provider-states.md +2 -0
- data/documentation/troubleshooting.md +4 -0
- data/documentation/verifying-pacts.md +97 -0
- data/lib/pact/app.rb +98 -4
- data/lib/pact/consumer/rspec.rb +3 -2
- data/lib/pact/doc/doc_file.rb +4 -4
- data/lib/pact/doc/generator.rb +3 -3
- data/lib/pact/doc/interaction_view_model.rb +1 -0
- data/lib/pact/doc/markdown/{interactions_renderer.rb → consumer_contract_renderer.rb} +1 -1
- data/lib/pact/doc/markdown/generator.rb +2 -2
- data/lib/pact/matchers/unix_diff_formatter.rb +1 -1
- data/lib/pact/project_root.rb +7 -0
- data/lib/pact/provider.rb +0 -1
- data/lib/pact/provider/context.rb +0 -0
- data/lib/pact/provider/matchers/messages.rb +15 -13
- data/lib/pact/provider/pact_spec_runner.rb +21 -22
- data/lib/pact/provider/rspec.rb +22 -15
- data/lib/pact/provider/rspec/custom_options_file +0 -0
- data/lib/pact/provider/{matchers.rb → rspec/matchers.rb} +2 -1
- data/lib/pact/rspec.rb +20 -0
- data/lib/pact/shared/request.rb +1 -1
- data/lib/pact/tasks/task_helper.rb +18 -15
- data/lib/pact/tasks/verification_task.rb +26 -32
- data/lib/pact/version.rb +1 -1
- data/lib/tasks/pact.rake +5 -11
- data/spec/integration/pact/consumer_configuration_spec.rb +3 -3
- data/spec/lib/pact/app_spec.rb +47 -0
- data/spec/lib/pact/consumer/app_manager_spec.rb +1 -1
- data/spec/lib/pact/consumer/mock_service/interaction_list_spec.rb +3 -3
- data/spec/lib/pact/consumer/mock_service/verification_get_spec.rb +10 -2
- data/spec/lib/pact/consumer/mock_service_interaction_expectation_spec.rb +2 -2
- data/spec/lib/pact/consumer_contract/consumer_contract_spec.rb +1 -1
- data/spec/lib/pact/consumer_contract/interaction_spec.rb +4 -4
- data/spec/lib/pact/consumer_contract/request_spec.rb +23 -23
- data/spec/lib/pact/doc/generator_spec.rb +4 -4
- data/spec/lib/pact/doc/markdown/{interactions_renderer_spec.rb → consumer_contract_renderer_spec.rb} +4 -4
- data/spec/lib/pact/matchers/unix_diff_formatter_spec.rb +8 -8
- data/spec/lib/pact/provider/configuration/configuration_extension_spec.rb +2 -2
- data/spec/lib/pact/provider/matchers/messages_spec.rb +17 -6
- data/spec/lib/pact/provider/rspec/formatter_spec.rb +3 -1
- data/spec/lib/pact/shared/dsl_spec.rb +1 -1
- data/spec/lib/pact/shared/request_spec.rb +8 -0
- data/spec/lib/pact/tasks/task_helper_spec.rb +39 -54
- data/spec/lib/pact/tasks/verification_task_spec.rb +75 -0
- data/spec/pact_specification/compliance-1.0.0.rb +47 -0
- data/spec/spec_helper.rb +2 -6
- data/spec/standalone/consumer_fail_test.rb +1 -0
- data/spec/standalone/consumer_pass_test.rb +1 -0
- data/spec/support/active_support_if_configured.rb +6 -0
- data/spec/support/pact_helper.rb +2 -1
- data/spec/support/shared_examples_for_request.rb +15 -4
- data/spec/support/spec_support.rb +3 -0
- data/spec/support/stubbing_using_allow.rb +1 -0
- data/spec/support/term.json +13 -1
- data/tasks/pact-test.rake +45 -26
- metadata +23 -13
- data/lib/pact/provider/client_project_pact_helper.rb +0 -4
- data/spec/lib/pact/provider/pact_spec_runner_spec.rb +0 -7
- data/spec/lib/pact/verification_task_spec.rb +0 -99
data/spec/lib/pact/doc/markdown/{interactions_renderer_spec.rb → consumer_contract_renderer_spec.rb}
RENAMED
@@ -1,12 +1,12 @@
|
|
1
1
|
require 'spec_helper'
|
2
|
-
require 'pact/doc/markdown/
|
2
|
+
require 'pact/doc/markdown/consumer_contract_renderer'
|
3
3
|
|
4
4
|
module Pact
|
5
5
|
module Doc
|
6
6
|
module Markdown
|
7
|
-
describe
|
7
|
+
describe ConsumerContractRenderer do
|
8
8
|
|
9
|
-
subject {
|
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(
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
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(
|
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(
|
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
|
102
|
+
context "when the expected is a regexp" do
|
92
103
|
|
93
|
-
let(:expected) {
|
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
|
-
|
22
|
+
|
23
|
+
let(:output_result) { Pact::SpecSupport.remove_ansicolor output.string }
|
22
24
|
|
23
25
|
before do
|
24
26
|
allow(PrintMissingProviderStates).to receive(:call)
|
@@ -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
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
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
|
-
|
24
|
-
|
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 "
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
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
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
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 "
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
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 "
|
69
|
-
|
70
|
-
|
71
|
-
|
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
|
-
|
75
|
-
|
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
|