pact-mock_service 0.0.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 (75) hide show
  1. checksums.yaml +15 -0
  2. data/.gitignore +29 -0
  3. data/.rspec +2 -0
  4. data/.travis.yml +8 -0
  5. data/CHANGELOG.md +4 -0
  6. data/Gemfile +8 -0
  7. data/Gemfile.lock +100 -0
  8. data/LICENSE.txt +22 -0
  9. data/README.md +314 -0
  10. data/Rakefile +6 -0
  11. data/bin/pact-mock-service +3 -0
  12. data/lib/pact/consumer/app_manager.rb +159 -0
  13. data/lib/pact/consumer/interactions_filter.rb +48 -0
  14. data/lib/pact/consumer/mock_service/app.rb +84 -0
  15. data/lib/pact/consumer/mock_service/interaction_delete.rb +33 -0
  16. data/lib/pact/consumer/mock_service/interaction_list.rb +76 -0
  17. data/lib/pact/consumer/mock_service/interaction_mismatch.rb +73 -0
  18. data/lib/pact/consumer/mock_service/interaction_post.rb +31 -0
  19. data/lib/pact/consumer/mock_service/interaction_replay.rb +139 -0
  20. data/lib/pact/consumer/mock_service/log_get.rb +28 -0
  21. data/lib/pact/consumer/mock_service/missing_interactions_get.rb +30 -0
  22. data/lib/pact/consumer/mock_service/mock_service_administration_endpoint.rb +31 -0
  23. data/lib/pact/consumer/mock_service/pact_post.rb +33 -0
  24. data/lib/pact/consumer/mock_service/rack_request_helper.rb +51 -0
  25. data/lib/pact/consumer/mock_service/verification_get.rb +68 -0
  26. data/lib/pact/consumer/mock_service.rb +2 -0
  27. data/lib/pact/consumer/mock_service_client.rb +65 -0
  28. data/lib/pact/consumer/mock_service_interaction_expectation.rb +37 -0
  29. data/lib/pact/consumer/request.rb +27 -0
  30. data/lib/pact/consumer/server.rb +90 -0
  31. data/lib/pact/consumer_contract/consumer_contract_writer.rb +84 -0
  32. data/lib/pact/mock_service/cli.rb +49 -0
  33. data/lib/pact/mock_service/version.rb +5 -0
  34. data/lib/pact/mock_service.rb +1 -0
  35. data/pact-mock-service.gemspec +41 -0
  36. data/spec/lib/pact/consumer/app_manager_spec.rb +42 -0
  37. data/spec/lib/pact/consumer/mock_service/app_spec.rb +52 -0
  38. data/spec/lib/pact/consumer/mock_service/interaction_list_spec.rb +78 -0
  39. data/spec/lib/pact/consumer/mock_service/interaction_mismatch_spec.rb +70 -0
  40. data/spec/lib/pact/consumer/mock_service/interaction_replay_spec.rb +12 -0
  41. data/spec/lib/pact/consumer/mock_service/rack_request_helper_spec.rb +88 -0
  42. data/spec/lib/pact/consumer/mock_service/verification_get_spec.rb +142 -0
  43. data/spec/lib/pact/consumer/mock_service_client_spec.rb +88 -0
  44. data/spec/lib/pact/consumer/mock_service_interaction_expectation_spec.rb +54 -0
  45. data/spec/lib/pact/consumer/service_consumer_spec.rb +11 -0
  46. data/spec/lib/pact/consumer_contract/consumer_contract_writer_spec.rb +111 -0
  47. data/spec/spec_helper.rb +16 -0
  48. data/spec/support/a_consumer-a_producer.json +32 -0
  49. data/spec/support/a_consumer-a_provider.json +32 -0
  50. data/spec/support/active_support_if_configured.rb +6 -0
  51. data/spec/support/app_for_config_ru.rb +4 -0
  52. data/spec/support/case-insensitive-response-header-matching.json +21 -0
  53. data/spec/support/case-insensitive-response-header-matching.rb +15 -0
  54. data/spec/support/consumer_contract_template.json +24 -0
  55. data/spec/support/dsl_spec_support.rb +7 -0
  56. data/spec/support/factories.rb +82 -0
  57. data/spec/support/generated_index.md +4 -0
  58. data/spec/support/generated_markdown.md +55 -0
  59. data/spec/support/interaction_view_model.json +63 -0
  60. data/spec/support/interaction_view_model_with_terms.json +50 -0
  61. data/spec/support/markdown_pact.json +48 -0
  62. data/spec/support/missing_provider_states_output.txt +25 -0
  63. data/spec/support/options.json +21 -0
  64. data/spec/support/options_app.rb +15 -0
  65. data/spec/support/pact_helper.rb +57 -0
  66. data/spec/support/shared_examples_for_request.rb +94 -0
  67. data/spec/support/spec_support.rb +20 -0
  68. data/spec/support/stubbing.json +22 -0
  69. data/spec/support/stubbing_using_allow.rb +29 -0
  70. data/spec/support/term.json +48 -0
  71. data/spec/support/test_app_fail.json +61 -0
  72. data/spec/support/test_app_pass.json +38 -0
  73. data/spec/support/test_app_with_right_content_type_differ.json +23 -0
  74. data/tasks/spec.rake +6 -0
  75. metadata +388 -0
@@ -0,0 +1,70 @@
1
+ require 'spec_helper'
2
+ require 'pact/consumer/mock_service/interaction_mismatch'
3
+
4
+ module Pact
5
+ module Consumer
6
+ describe InteractionMismatch do
7
+ let(:content_type) { 'some/content' }
8
+ let(:actual_request) { instance_double('Pact::Consumer::Request::Actual', :method_and_path => 'GET /path') }
9
+ let(:expected_request_1) { instance_double('Pact::Request::Expected', :content_type => content_type) }
10
+ let(:expected_request_2) { instance_double('Pact::Request::Expected', :content_type => content_type) }
11
+ let(:candidate_1) { instance_double('Pact::Interaction', request: expected_request_1, description_with_provider_state_quoted: "desc 1") }
12
+ let(:candidate_2) { instance_double('Pact::Interaction', request: expected_request_2, description_with_provider_state_quoted: "desc 2") }
13
+ let(:candidate_interactions) { [candidate_1, candidate_2] }
14
+ subject { InteractionMismatch.new(candidate_interactions, actual_request) }
15
+ let(:diff_1) { {body: 'diff'} }
16
+ let(:diff_2) { {} }
17
+
18
+ before do
19
+ allow(expected_request_1).to receive(:difference).with(actual_request).and_return(diff_1)
20
+ allow(expected_request_2).to receive(:difference).with(actual_request).and_return(diff_2)
21
+ end
22
+
23
+ describe "short_summary" do
24
+ it "includes the method and path" do
25
+ expect(subject.short_summary).to match /GET \/path \(.*\)/
26
+ end
27
+ context "when the body does not match" do
28
+ let(:diff_1) { {body: nil} }
29
+
30
+ it "returns a message indicating that the body does not match" do
31
+ expect(subject.short_summary).to include "(request body did not match)"
32
+ end
33
+ end
34
+ context "when the headers do not match" do
35
+ let(:diff_1) { {headers: nil} }
36
+ it "returns a message indicating that the body does not match" do
37
+ expect(subject.short_summary).to include "(request headers did not match)"
38
+ end
39
+ end
40
+ context "when the headers and body do not match" do
41
+ let(:diff_1) { {body: nil, headers: nil} }
42
+ let(:diff_2) { {body: nil, headers: nil} }
43
+ it "returns a message indicating that the headers and body do not match" do
44
+ expect(subject.short_summary).to include "(request body and headers did not match)"
45
+ end
46
+ end
47
+ end
48
+
49
+ describe "to_s" do
50
+ let(:expected_message) { "Diff with interaction: desc 1\ndiff 1\nDiff with interaction: desc 2\ndiff 2" }
51
+
52
+ let(:diff_formatter) { double("diff_formatter")}
53
+ before do
54
+ allow(Pact.configuration).to receive(:diff_formatter_for_content_type).with(content_type).and_return(diff_formatter)
55
+ allow(diff_formatter).to receive(:call).and_return("diff 1", "diff 2")
56
+ end
57
+
58
+ it "creates diff output using the configured diff_formatter" do
59
+ expect(diff_formatter).to receive(:call).with(diff_1, colour: false)
60
+ expect(diff_formatter).to receive(:call).with(diff_2, colour: false)
61
+ subject.to_s
62
+ end
63
+
64
+ it "includes a diff output in the string output" do
65
+ expect(subject.to_s).to eq expected_message
66
+ end
67
+ end
68
+ end
69
+ end
70
+ end
@@ -0,0 +1,12 @@
1
+ require 'spec_helper'
2
+ require 'pact/consumer/mock_service/interaction_replay'
3
+
4
+ module Pact
5
+ module Consumer
6
+
7
+ describe InteractionReplay do
8
+
9
+
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,88 @@
1
+ require 'spec_helper'
2
+ require 'pact/consumer/mock_service/rack_request_helper'
3
+
4
+ module Pact::Consumer
5
+
6
+ describe RackRequestHelper do
7
+ class TestSubject
8
+ include RackRequestHelper
9
+ end
10
+
11
+ let(:rack_env) {
12
+ {
13
+ "CONTENT_LENGTH" => "16",
14
+ "CONTENT_TYPE" => content_type,
15
+ "GATEWAY_INTERFACE" => "CGI/1.1",
16
+ "PATH_INFO" => "/donuts",
17
+ "QUERY_STRING" => "",
18
+ "REMOTE_ADDR" => "127.0.0.1",
19
+ "REMOTE_HOST" => "localhost",
20
+ "REQUEST_METHOD" => "POST",
21
+ "REQUEST_URI" => "http://localhost:4321/donuts",
22
+ "SCRIPT_NAME" => "",
23
+ "SERVER_NAME" => "localhost",
24
+ "SERVER_PORT" => "4321",
25
+ "SERVER_PROTOCOL" => "HTTP/1.1",
26
+ "SERVER_SOFTWARE" => "WEBrick/1.3.1 (Ruby/1.9.3/2013-02-22)",
27
+ "HTTP_ACCEPT" => "text/plain",
28
+ "HTTP_USER_AGENT" => "Ruby",
29
+ "HTTP_HOST" => "localhost:4321",
30
+ "HTTP_X_SOMETHING" => "1, 2",
31
+ "rack.version" => [1, 2 ],
32
+ "rack.input" => StringIO.new(body),
33
+ "rack.errors" => nil,
34
+ "rack.multithread" => true,
35
+ "rack.multiprocess" => false,
36
+ "rack.run_once" => false,
37
+ "rack.url_scheme" => "http",
38
+ "HTTP_VERSION" => "HTTP/1.1",
39
+ "REQUEST_PATH" => "/donuts"
40
+ }
41
+ }
42
+
43
+ let(:content_type) { "" }
44
+ let(:body) { '' }
45
+
46
+ subject { TestSubject.new }
47
+
48
+ let(:expected_request) {
49
+ {
50
+ :query => "",
51
+ :method => "post",
52
+ :body => expected_body,
53
+ :path => "/donuts",
54
+ :headers => {
55
+ "Content-Type" => content_type,
56
+ "Content-Length" => "16",
57
+ "Accept" => "text/plain",
58
+ "User-Agent" => "Ruby",
59
+ "Host" => "localhost:4321",
60
+ "Version" => "HTTP/1.1",
61
+ "X-Something" => "1, 2"
62
+ }
63
+ }
64
+ }
65
+
66
+ context "with a text body" do
67
+ let(:content_type) { "application/x-www-form-urlencoded" }
68
+ let(:body) { 'this is the body' }
69
+ let(:expected_body) { body }
70
+
71
+ it "extracts the body" do
72
+ expect(subject.request_as_hash_from(rack_env)).to eq expected_request
73
+ end
74
+ end
75
+
76
+ context "with a json body" do
77
+ let(:content_type) { "application/json" }
78
+ let(:body) { '{"a" : "body" }' }
79
+ let(:expected_body) { {"a" => "body"} }
80
+
81
+ it "extracts the body" do
82
+ expect(subject.request_as_hash_from(rack_env)).to eq expected_request
83
+ end
84
+ end
85
+
86
+
87
+ end
88
+ end
@@ -0,0 +1,142 @@
1
+ require 'spec_helper'
2
+ require 'pact/consumer/mock_service/verification_get'
3
+
4
+ module Pact
5
+ module Consumer
6
+ describe VerificationGet do
7
+
8
+ let(:interaction_list) { instance_double("Pact::Consumer::InteractionList")}
9
+ let(:logger) { double("Logger").as_null_object }
10
+ let(:log_description) { "/log/pact.log" }
11
+
12
+ subject { VerificationGet.new('VerificationGet', logger, interaction_list, log_description) }
13
+
14
+ describe "request_path" do
15
+ it "is /interactions/verification" do
16
+ expect(subject.request_path).to eq '/interactions/verification'
17
+ end
18
+ end
19
+
20
+ describe "request_method" do
21
+ it "is GET" do
22
+ expect(subject.request_method).to eq 'GET'
23
+ end
24
+ end
25
+
26
+ describe "#respond" do
27
+ let(:env) { {
28
+ "QUERY_STRING" => "example_description=a description"
29
+ } }
30
+
31
+ before do
32
+ allow(interaction_list).to receive(:all_matched?).and_return(all_matched)
33
+ end
34
+
35
+ let(:response) { subject.respond env }
36
+
37
+ context "when all interactions have been matched" do
38
+ let(:all_matched) { true }
39
+
40
+ it "returns a 200 status" do
41
+ expect(response.first).to eq 200
42
+ end
43
+
44
+ it "returns a Content-Type of text/plain" do
45
+ expect(response[1]).to eq 'Content-Type' => 'text/plain'
46
+ end
47
+
48
+ it "returns a nice message" do
49
+ expect(response.last).to eq ['Interactions matched']
50
+ end
51
+
52
+ it "logs the success" do
53
+ expect(logger).to receive(:info).with(/Verifying - interactions matched.*a description/)
54
+ response
55
+ end
56
+ end
57
+
58
+ context "when all interactions not been matched" do
59
+ let(:all_matched) { false }
60
+ let(:failure_message) { "this is a failure message"}
61
+
62
+ before do
63
+ allow_any_instance_of(VerificationGet::FailureMessage).to receive(:to_s).and_return(failure_message)
64
+ end
65
+
66
+ it "returns a 500 status" do
67
+ expect(response.first).to eq 500
68
+ end
69
+
70
+ it "returns a Content-Type of text/plain" do
71
+ expect(response[1]).to eq 'Content-Type' => 'text/plain'
72
+ end
73
+
74
+ it "returns a message" do
75
+ expect(response.last.first).to include "Actual interactions do not match"
76
+ expect(response.last.first).to include failure_message
77
+ expect(response.last.first).to include log_description
78
+ end
79
+
80
+ it "logs the failure message" do
81
+ expect(logger).to receive(:warn).with(/Verifying - actual interactions do not match/)
82
+ expect(logger).to receive(:warn).with(failure_message)
83
+ response
84
+ end
85
+
86
+ end
87
+
88
+ end
89
+
90
+ describe "FailureMessage" do
91
+ let(:missing_interactions_summaries) { ["Blah", "Thing"]}
92
+ let(:interaction_mismatches_summaries) { []}
93
+ let(:unexpected_requests_summaries) { []}
94
+ let(:interaction_list) { instance_double("Pact::Consumer::InteractionList") }
95
+ subject { VerificationGet::FailureMessage.new(interaction_list).to_s }
96
+
97
+ before do
98
+ allow(interaction_list).to receive(:missing_interactions_summaries).and_return(missing_interactions_summaries)
99
+ allow(interaction_list).to receive(:interaction_mismatches_summaries).and_return(interaction_mismatches_summaries)
100
+ allow(interaction_list).to receive(:unexpected_requests_summaries).and_return(unexpected_requests_summaries)
101
+ end
102
+
103
+ context "with only a missing interactions" do
104
+
105
+ let(:expected_string) { <<-EOS
106
+ Missing requests:
107
+ \tBlah
108
+ \tThing
109
+
110
+ EOS
111
+ }
112
+ it "only includes missing interactions" do
113
+ expect(subject).to eq expected_string
114
+ end
115
+ end
116
+
117
+ context "with missing, mismatches and unexpected interactions" do
118
+
119
+ let(:interaction_mismatches_summaries) { ["wiffle"]}
120
+ let(:unexpected_requests_summaries) { ["moose"]}
121
+
122
+ let(:expected_string) { <<-EOS
123
+ Incorrect requests:
124
+ \twiffle
125
+
126
+ Missing requests:
127
+ \tBlah
128
+ \tThing
129
+
130
+ Unexpected requests:
131
+ \tmoose
132
+
133
+ EOS
134
+ }
135
+ it "includes all the things" do
136
+ expect(subject).to eq expected_string
137
+ end
138
+ end
139
+ end
140
+ end
141
+ end
142
+ end
@@ -0,0 +1,88 @@
1
+ require 'spec_helper'
2
+ require 'pact/consumer/mock_service_client'
3
+
4
+ module Pact
5
+ module Consumer
6
+ describe MockServiceClient do
7
+
8
+ subject { MockServiceClient.new(4444) }
9
+
10
+ let(:administration_headers) { {'X-Pact-Mock-Service' => 'true'} }
11
+
12
+ describe "#add_expected_interaction" do
13
+ let(:interaction) { InteractionFactory.create }
14
+ let(:request_body) { MockServiceInteractionExpectation.new(interaction).to_json }
15
+
16
+ context "when successful" do
17
+ let!(:post_interaction) do
18
+ stub_request(:post, "localhost:4444/interactions").
19
+ with(body: request_body, headers: administration_headers.merge('Content-Type' => "application/json")).
20
+ to_return(status: 200)
21
+ end
22
+
23
+ it "sets up the expected interaction on the mock server" do
24
+ subject.add_expected_interaction interaction
25
+ expect(post_interaction).to have_been_made
26
+ end
27
+ end
28
+
29
+ end
30
+
31
+ describe "#verify" do
32
+
33
+ context "when all interactions are successfully verified" do
34
+
35
+ let!(:get_verification) do
36
+ stub_request(:get, "localhost:4444/interactions/verification?example_description=some%20example").
37
+ with(headers: administration_headers).
38
+ to_return(status: 200)
39
+ end
40
+
41
+ it "does not throw an error" do
42
+ subject.verify "some example"
43
+ expect(get_verification).to have_been_made
44
+ end
45
+ end
46
+ end
47
+
48
+ describe ".clear_interactions" do
49
+ let!(:delete_verifications) do
50
+ stub_request(:delete, "localhost:4444/interactions?example_description=some%20example").
51
+ with(headers: administration_headers).
52
+ to_return(status: 200)
53
+ end
54
+
55
+ it "deletes the interactions" do
56
+ MockServiceClient.clear_interactions 4444, "some example"
57
+ expect(delete_verifications).to have_been_made
58
+ end
59
+ end
60
+
61
+ describe "#write_pact" do
62
+ let(:consumer_contract_details) { {consumer: {name: 'Consumer'}, provider: {name: 'Provider'}, pactfile_write_mode: 'update'} }
63
+ let(:pact) { {a: 'pact'}.to_json }
64
+
65
+ let!(:post_pact) do
66
+ stub_request(:post, "localhost:4444/pact").
67
+ with(headers: administration_headers.merge('Content-Type' => "application/json"), body: consumer_contract_details).
68
+ to_return(status: 200, body: pact)
69
+ end
70
+
71
+ it "deletes the interactions" do
72
+ expect(subject.write_pact(consumer_contract_details)).to eq pact
73
+ expect(post_pact).to have_been_made
74
+ end
75
+
76
+ end
77
+
78
+ describe "#log" do
79
+ it "sends a log request to the mock server"
80
+ end
81
+
82
+ describe "#wait_for_interactions" do
83
+ it "waits until there are no missing interactions"
84
+ end
85
+ end
86
+ end
87
+ end
88
+
@@ -0,0 +1,54 @@
1
+ require 'spec_helper'
2
+ require 'pact/consumer/mock_service_interaction_expectation'
3
+
4
+ describe Pact::Consumer::MockServiceInteractionExpectation do
5
+ describe "as_json" do
6
+
7
+ let(:options ) { {} }
8
+ let(:request_as_json) { {a: 'request'} }
9
+ let(:request) { instance_double('Pact::Request::Expected', :as_json => request_as_json, :options => options)}
10
+ let(:response) { double('response') }
11
+ let(:generated_response ) { double('generated_response', :to_json => 'generated_response') }
12
+ let(:interaction) { instance_double('Pact::Interaction', :description => 'description', :request => request, :response => response, :provider_state => 'some state') }
13
+ subject { described_class.new(interaction)}
14
+ let(:expected_hash) { {:response => generated_response, :request => as_json_with_options, :description => '' } }
15
+
16
+ before do
17
+ allow(Pact::Reification).to receive(:from_term).with(response).and_return(generated_response)
18
+ end
19
+
20
+ it "includes the response" do
21
+ expect(subject.as_json[:response]).to eq response
22
+ end
23
+
24
+ it "includes the options in the request" do
25
+ expect(subject.as_json[:request]).to eq request_as_json
26
+ end
27
+
28
+ it "includes the provider state" do
29
+ expect(subject.as_json[:provider_state]).to eq 'some state'
30
+ end
31
+
32
+ it "includes the description" do
33
+ expect(subject.as_json[:description]).to eq 'description'
34
+ end
35
+
36
+ it "doesn't have any other keys" do
37
+ expect(subject.as_json.keys).to eq [:description, :provider_state, :request, :response]
38
+ end
39
+
40
+ context "without options" do
41
+ it "does not include the options key" do
42
+ expect(subject.as_json.key?(:options)).to be false
43
+ end
44
+ end
45
+
46
+ context "with options" do
47
+ let(:options) { {:opts => 'blah'} }
48
+ it "includes the options in the request hash" do
49
+ expect(subject.as_json[:request][:options]).to eq options
50
+ end
51
+ end
52
+ end
53
+
54
+ end
@@ -0,0 +1,11 @@
1
+ require 'spec_helper'
2
+
3
+ module Pact
4
+ describe ServiceConsumer do
5
+ describe "as_json" do
6
+ it "returns a hash representation of the object" do
7
+ expect(ServiceConsumer.new(:name => "Bob").as_json).to eq :name => "Bob"
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,111 @@
1
+ require 'spec_helper'
2
+ require 'pact/consumer_contract/consumer_contract_writer'
3
+
4
+ module Pact
5
+
6
+ describe ConsumerContractWriter do
7
+
8
+ let(:support_pact_file) { './spec/support/a_consumer-a_provider.json' }
9
+ let(:consumer_name) { 'a consumer' }
10
+ let(:provider_name) { 'a provider' }
11
+
12
+ before do
13
+ Pact.clear_configuration
14
+ allow(Pact.configuration).to receive(:pact_dir).and_return(File.expand_path(tmp_pact_dir))
15
+ FileUtils.rm_rf tmp_pact_dir
16
+ FileUtils.mkdir_p tmp_pact_dir
17
+ FileUtils.cp support_pact_file, "#{tmp_pact_dir}/a_consumer-a_provider.json"
18
+ end
19
+
20
+ let(:existing_interactions) { ConsumerContract.from_json(File.read(support_pact_file)).interactions }
21
+ let(:new_interactions) { [InteractionFactory.create] }
22
+ let(:tmp_pact_dir) {"./tmp/pacts"}
23
+ let(:logger) { double("logger").as_null_object }
24
+ let(:pactfile_write_mode) {:overwrite}
25
+ let(:consumer_contract_details) {
26
+ {
27
+ consumer: {name: consumer_name},
28
+ provider: {name: provider_name},
29
+ pactfile_write_mode: pactfile_write_mode,
30
+ interactions: new_interactions
31
+ }
32
+ }
33
+
34
+ let(:consumer_contract_writer) { ConsumerContractWriter.new(consumer_contract_details, logger) }
35
+
36
+ describe "consumer_contract" do
37
+
38
+ let(:subject) { consumer_contract_writer.consumer_contract }
39
+
40
+ context "when overwriting pact" do
41
+
42
+ it "it uses only the interactions from the current test run" do
43
+ expect(consumer_contract_writer.consumer_contract.interactions).to eq new_interactions
44
+ end
45
+
46
+ end
47
+
48
+ context "when updating pact" do
49
+
50
+ let(:pactfile_write_mode) {:update}
51
+
52
+ it "merges the interactions from the current test run with the interactions from the existing file" do
53
+ allow_any_instance_of(ConsumerContractWriter).to receive(:info_and_puts)
54
+ expect(consumer_contract_writer.consumer_contract.interactions).to eq existing_interactions + new_interactions
55
+ end
56
+
57
+ let(:line0) { /\*/ }
58
+ let(:line1) { /Updating existing file/ }
59
+ let(:line2) { /Only interactions defined in this test run will be updated/ }
60
+ let(:line3) { /As interactions are identified by description and provider state/ }
61
+
62
+ it "logs a description message" do
63
+ expect($stdout).to receive(:puts).with(line0).twice
64
+ expect($stdout).to receive(:puts).with(line1)
65
+ expect($stdout).to receive(:puts).with(line2)
66
+ expect($stdout).to receive(:puts).with(line3)
67
+ expect(logger).to receive(:info).with(line0).twice
68
+ expect(logger).to receive(:info).with(line1)
69
+ expect(logger).to receive(:info).with(line2)
70
+ expect(logger).to receive(:info).with(line3)
71
+ consumer_contract_writer.consumer_contract
72
+ end
73
+ end
74
+
75
+ context "when an error occurs deserializing the existing pactfile" do
76
+
77
+ let(:pactfile_write_mode) {:update}
78
+ let(:error) { RuntimeError.new('some error')}
79
+ let(:line1) { /Could not load existing consumer contract from .* due to some error/ }
80
+ let(:line2) {'Creating a new file.'}
81
+
82
+ before do
83
+ allow(ConsumerContract).to receive(:from_json).and_raise(error)
84
+ allow($stderr).to receive(:puts)
85
+ allow(logger).to receive(:puts)
86
+ end
87
+
88
+ it "logs the error" do
89
+ expect($stderr).to receive(:puts).with(line1)
90
+ expect($stderr).to receive(:puts).with(line2)
91
+ expect(logger).to receive(:warn).with(line1)
92
+ expect(logger).to receive(:warn).with(line2)
93
+ consumer_contract_writer.consumer_contract
94
+ end
95
+
96
+ it "uses the new interactions" do
97
+ expect(consumer_contract_writer.consumer_contract.interactions).to eq new_interactions
98
+ end
99
+ end
100
+ end
101
+
102
+ describe "write" do
103
+ it "writes the pact file" do
104
+ expect_any_instance_of(ConsumerContract).to receive(:update_pactfile)
105
+ consumer_contract_writer.write
106
+ end
107
+ end
108
+
109
+ end
110
+
111
+ end
@@ -0,0 +1,16 @@
1
+ require 'rspec'
2
+ require 'fakefs/spec_helpers'
3
+ require 'rspec'
4
+ require 'pact/support'
5
+ require 'webmock/rspec'
6
+ require 'support/factories'
7
+ require 'support/spec_support'
8
+
9
+ WebMock.disable_net_connect!(allow_localhost: true)
10
+
11
+ require './spec/support/active_support_if_configured'
12
+
13
+ RSpec.configure do | config |
14
+ config.include(FakeFS::SpecHelpers, :fakefs => true)
15
+ end
16
+
@@ -0,0 +1,32 @@
1
+ {
2
+ "producer": {
3
+ "name": "an old producer"
4
+ },
5
+ "consumer": {
6
+ "name": "a consumer"
7
+ },
8
+ "interactions": [
9
+ {
10
+ "description": "request one",
11
+ "request": {
12
+ "method": "get",
13
+ "path": "/path_one"
14
+ },
15
+ "response": {
16
+ },
17
+ "producer_state": "state one"
18
+ },
19
+ {
20
+ "description": "request two",
21
+ "request": {
22
+ "method": "get",
23
+ "path": "/path_two"
24
+ },
25
+ "response": {
26
+ }
27
+ }
28
+ ],
29
+ "metadata": {
30
+ "pactSpecificationVersion": "1.0"
31
+ }
32
+ }
@@ -0,0 +1,32 @@
1
+ {
2
+ "provider": {
3
+ "name": "a provider"
4
+ },
5
+ "consumer": {
6
+ "name": "a consumer"
7
+ },
8
+ "interactions": [
9
+ {
10
+ "description": "request one",
11
+ "request": {
12
+ "method": "get",
13
+ "path": "/path_one"
14
+ },
15
+ "response": {
16
+ },
17
+ "provider_state": "state one"
18
+ },
19
+ {
20
+ "description": "request two",
21
+ "request": {
22
+ "method": "get",
23
+ "path": "/path_two"
24
+ },
25
+ "response": {
26
+ }
27
+ }
28
+ ],
29
+ "metadata": {
30
+ "pactSpecificationVersion": "1.0"
31
+ }
32
+ }
@@ -0,0 +1,6 @@
1
+ if ENV['LOAD_ACTIVE_SUPPORT']
2
+ puts 'LOADING ACTIVE SUPPORT!!!! Hopefully it all still works'
3
+ require 'active_support/all'
4
+ require 'active_support'
5
+ require 'active_support/json'
6
+ end
@@ -0,0 +1,4 @@
1
+ class AppForConfigRu
2
+ def call env
3
+ end
4
+ end