pact_broker 2.47.1 → 2.48.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (40) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +21 -0
  3. data/Dockerfile +0 -1
  4. data/README.md +1 -1
  5. data/lib/pact_broker/api/contracts/verifiable_pacts_json_query_schema.rb +11 -0
  6. data/lib/pact_broker/api/contracts/verifiable_pacts_query_schema.rb +1 -0
  7. data/lib/pact_broker/api/decorators/verifiable_pact_decorator.rb +4 -39
  8. data/lib/pact_broker/api/decorators/verifiable_pacts_query_decorator.rb +9 -2
  9. data/lib/pact_broker/api/decorators/version_decorator.rb +1 -1
  10. data/lib/pact_broker/api/resources/verification.rb +6 -1
  11. data/lib/pact_broker/pacts/build_verifiable_pact_notices.rb +35 -0
  12. data/lib/pact_broker/pacts/repository.rb +71 -17
  13. data/lib/pact_broker/pacts/selected_pact.rb +9 -18
  14. data/lib/pact_broker/pacts/selector.rb +66 -10
  15. data/lib/pact_broker/pacts/selectors.rb +44 -0
  16. data/lib/pact_broker/pacts/service.rb +2 -2
  17. data/lib/pact_broker/pacts/squash_pacts_for_verification.rb +4 -6
  18. data/lib/pact_broker/pacts/verifiable_pact.rb +3 -12
  19. data/lib/pact_broker/pacts/verifiable_pact_messages.rb +63 -11
  20. data/lib/pact_broker/test/test_data_builder.rb +6 -0
  21. data/lib/pact_broker/verifications/repository.rb +4 -0
  22. data/lib/pact_broker/verifications/service.rb +5 -0
  23. data/lib/pact_broker/version.rb +1 -1
  24. data/lib/pact_broker/webhooks/service.rb +4 -0
  25. data/spec/features/delete_verification_spec.rb +29 -0
  26. data/spec/lib/pact_broker/api/contracts/verifiable_pacts_json_query_schema_spec.rb +29 -0
  27. data/spec/lib/pact_broker/api/decorators/verifiable_pact_decorator_spec.rb +18 -40
  28. data/spec/lib/pact_broker/api/decorators/verifiable_pacts_query_decorator_spec.rb +20 -6
  29. data/spec/lib/pact_broker/api/decorators/version_decorator_spec.rb +4 -0
  30. data/spec/lib/pact_broker/api/resources/provider_pacts_for_verification_spec.rb +2 -2
  31. data/spec/lib/pact_broker/pacts/build_verifiable_pact_notices_spec.rb +76 -0
  32. data/spec/lib/pact_broker/pacts/repository_find_for_verification_fallback_spec.rb +73 -0
  33. data/spec/lib/pact_broker/pacts/repository_find_for_verification_spec.rb +10 -12
  34. data/spec/lib/pact_broker/pacts/selector_spec.rb +28 -0
  35. data/spec/lib/pact_broker/pacts/selectors_spec.rb +30 -0
  36. data/spec/lib/pact_broker/pacts/service_spec.rb +2 -2
  37. data/spec/lib/pact_broker/pacts/squash_pacts_for_verification_spec.rb +2 -5
  38. data/spec/lib/pact_broker/pacts/verifiable_pact_messages_spec.rb +32 -24
  39. data/spec/support/verification_job.rb +1 -0
  40. metadata +14 -2
@@ -5,53 +5,41 @@ module PactBroker
5
5
  module Decorators
6
6
  describe VerifiablePactDecorator do
7
7
  before do
8
- allow_any_instance_of(PactBroker::Api::PactBrokerUrls).to receive(:pact_version_url).and_return('/pact-version-url')
9
- allow_any_instance_of(PactBroker::Pacts::VerifiablePactMessages).to receive(:inclusion_reason).and_return("the inclusion reason")
10
- allow_any_instance_of(PactBroker::Pacts::VerifiablePactMessages).to receive(:pending_reason).and_return(pending_reason)
11
- allow_any_instance_of(PactBroker::Pacts::VerifiablePactMessages).to receive(:verification_success_true_published_false).and_return('verification_success_true_published_false')
12
- allow_any_instance_of(PactBroker::Pacts::VerifiablePactMessages).to receive(:verification_success_false_published_false).and_return('verification_success_false_published_false')
13
- allow_any_instance_of(PactBroker::Pacts::VerifiablePactMessages).to receive(:verification_success_true_published_true).and_return('verification_success_true_published_true')
14
- allow_any_instance_of(PactBroker::Pacts::VerifiablePactMessages).to receive(:verification_success_false_published_true).and_return('verification_success_false_published_true')
8
+ allow_any_instance_of(PactBroker::Api::PactBrokerUrls).to receive(:pact_version_url).and_return('http://pact')
9
+ allow(PactBroker::Pacts::BuildVerifiablePactNotices).to receive(:call).and_return(notices)
10
+ allow_any_instance_of(PactBroker::Pacts::VerifiablePactMessages).to receive(:pact_version_short_description).and_return('short desc')
15
11
  end
12
+
16
13
  let(:pending_reason) { "the pending reason" }
14
+ let(:notices) do
15
+ [
16
+ {
17
+ some: "notice"
18
+ }
19
+ ]
20
+ end
17
21
  let(:expected_hash) do
18
22
  {
23
+ "shortDescription" => "short desc",
19
24
  "verificationProperties" => {
20
25
  "pending" => true,
21
26
  "notices" => [
22
27
  {
23
- "when" => "before_verification",
24
- "text" => "the inclusion reason"
25
- },{
26
- "when" => "before_verification",
27
- "text" => pending_reason
28
- },{
29
- "when" => "after_verification:success_true_published_false",
30
- "text" => "verification_success_true_published_false"
31
- },{
32
- "when" => "after_verification:success_false_published_false",
33
- "text" => "verification_success_false_published_false"
34
- },{
35
- "when" => "after_verification:success_true_published_true",
36
- "text" => "verification_success_true_published_true"
37
- },{
38
- "when" => "after_verification:success_false_published_true",
39
- "text" => "verification_success_false_published_true"
28
+ "some" => "notice"
40
29
  }
41
30
  ]
42
31
  },
43
32
  "_links" => {
44
33
  "self" => {
45
- "href" => "/pact-version-url",
34
+ "href" => "http://pact",
46
35
  "name" => "name"
47
36
  }
48
37
  }
49
38
  }
50
39
  end
51
-
52
40
  let(:decorator) { VerifiablePactDecorator.new(pact) }
53
41
  let(:pact) do
54
- double('pact',
42
+ double('PactBroker::Pacts::VerifiablePact',
55
43
  pending: true,
56
44
  wip: wip,
57
45
  name: "name",
@@ -61,10 +49,10 @@ module PactBroker
61
49
  end
62
50
  let(:pending_provider_tags) { %w[dev] }
63
51
  let(:consumer_tags) { %w[dev] }
64
- let(:json) { decorator.to_json(options) }
65
52
  let(:options) { { user_options: { base_url: 'http://example.org', include_pending_status: include_pending_status } } }
66
53
  let(:include_pending_status) { true }
67
54
  let(:wip){ false }
55
+ let(:json) { decorator.to_json(options) }
68
56
 
69
57
  subject { JSON.parse(json) }
70
58
 
@@ -77,27 +65,17 @@ module PactBroker
77
65
  subject
78
66
  end
79
67
 
80
- it "creates the inclusion message" do
81
- expect(PactBroker::Pacts::VerifiablePactMessages).to receive(:new).with(pact, '/pact-version-url').and_call_original
68
+ it "creates the notices" do
69
+ allow(PactBroker::Pacts::BuildVerifiablePactNotices).to receive(:call).with(pact, 'http://pact', include_pending_status: include_pending_status)
82
70
  subject
83
71
  end
84
72
 
85
73
  context "when include_pending_status is false" do
86
74
  let(:include_pending_status) { false }
87
- let(:notices) { subject['verificationProperties']['notices'].collect{ | notice | notice['text'] } }
88
75
 
89
76
  it "does not include the pending flag" do
90
77
  expect(subject['verificationProperties']).to_not have_key('pending')
91
78
  end
92
-
93
- it "does not include the pending reason" do
94
- expect(subject['verificationProperties']).to_not have_key('pendingReason')
95
- expect(notices).to_not include(pending_reason)
96
- end
97
-
98
- it "does not include the pending notices" do
99
- expect(subject['verificationProperties']['notices'].size).to eq 1
100
- end
101
79
  end
102
80
 
103
81
  context "when wip is true" do
@@ -18,12 +18,16 @@ module PactBroker
18
18
  end
19
19
 
20
20
  let(:consumer_version_selectors) do
21
- [{"tag" => "dev", "ignored" => "foo", "latest" => true}]
21
+ [{ "tag" => "dev", "ignored" => "foo", "latest" => true }]
22
+ end
23
+
24
+ it "parses the consumer_version_selectors to a Selectors collection" do
25
+ expect(subject.consumer_version_selectors).to be_a(PactBroker::Pacts::Selectors)
22
26
  end
23
27
 
24
28
  context "when latest is not specified" do
25
29
  let(:consumer_version_selectors) do
26
- [{"tag" => "dev"}]
30
+ [{ "tag" => "dev" }]
27
31
  end
28
32
 
29
33
  it "defaults to nil" do
@@ -31,15 +35,25 @@ module PactBroker
31
35
  end
32
36
  end
33
37
 
38
+ context "with a fallback" do
39
+ let(:consumer_version_selectors) do
40
+ [{ "tag" => "feat-x", "fallbackTag" => "dev", "latest" => true }]
41
+ end
42
+
43
+ it "sets the fallback" do
44
+ expect(subject.consumer_version_selectors.first.fallback_tag).to eq "dev"
45
+ end
46
+ end
47
+
34
48
  it "parses the latest as a boolean" do
35
- expect(subject.consumer_version_selectors.first.latest).to be true
49
+ expect(subject.consumer_version_selectors.first).to eq PactBroker::Pacts::Selector.new(tag: "dev", latest: true)
36
50
  end
37
51
 
38
52
  context "when there are no consumer_version_selectors" do
39
53
  let(:params) { {} }
40
54
 
41
55
  it "returns an empty array" do
42
- expect(subject.consumer_version_selectors).to eq []
56
+ expect(subject.consumer_version_selectors).to eq PactBroker::Pacts::Selectors.new
43
57
  end
44
58
  end
45
59
 
@@ -61,7 +75,7 @@ module PactBroker
61
75
  end
62
76
 
63
77
  let(:consumer_version_selectors) do
64
- [{"tag" => "dev", "latest" => "true"}]
78
+ [{ "tag" => "dev", "latest" => "true" }]
65
79
  end
66
80
 
67
81
  it "parses the provider_version_tags" do
@@ -69,7 +83,7 @@ module PactBroker
69
83
  end
70
84
 
71
85
  it "parses a string 'latest' to a boolean" do
72
- expect(subject.consumer_version_selectors.first.latest).to be true
86
+ expect(subject.consumer_version_selectors.first).to eq PactBroker::Pacts::Selector.new(tag: "dev", latest: true)
73
87
  end
74
88
  end
75
89
 
@@ -42,6 +42,10 @@ module PactBroker
42
42
  expect(subject[:_links][:'pb:pacticipant']).to eq title: "Pacticipant", name: "Consumer", href: "http://example.org/pacticipants/Consumer"
43
43
  end
44
44
 
45
+ it "includes a link to get, create or delete a tag" do
46
+ expect(subject[:_links][:'pb:tag']).to include href: "http://example.org/pacticipants/Consumer/versions/1.2.3/tags/{tag}", templated: true
47
+ end
48
+
45
49
  it "includes a list of the tags" do
46
50
  expect(subject[:_embedded][:tags]).to be_instance_of(Array)
47
51
  expect(subject[:_embedded][:tags].first[:name]).to eq "prod"
@@ -31,7 +31,7 @@ module PactBroker
31
31
  expect(PactBroker::Pacts::Service).to receive(:find_for_verification).with(
32
32
  "Bar",
33
33
  ["master"],
34
- [OpenStruct.new(tag: "dev", latest: true)],
34
+ PactBroker::Pacts::Selectors.new([PactBroker::Pacts::Selector.latest_for_tag("dev")]),
35
35
  {
36
36
  include_wip_pacts_since: DateTime.parse('2018-01-01'),
37
37
  include_pending_status: true
@@ -77,7 +77,7 @@ module PactBroker
77
77
  expect(PactBroker::Pacts::Service).to receive(:find_for_verification).with(
78
78
  "Bar",
79
79
  ["master"],
80
- [OpenStruct.new(tag: "dev", latest: true)],
80
+ PactBroker::Pacts::Selectors.new([PactBroker::Pacts::Selector.latest_for_tag("dev")]),
81
81
  {
82
82
  include_wip_pacts_since: DateTime.parse('2018-01-01'),
83
83
  include_pending_status: true
@@ -0,0 +1,76 @@
1
+ require 'pact_broker/pacts/build_verifiable_pact_notices'
2
+
3
+ module PactBroker
4
+ module Pacts
5
+ describe BuildVerifiablePactNotices do
6
+ before do
7
+ allow(VerifiablePactMessages).to receive(:new).and_return(verifiable_pact_messages)
8
+ end
9
+
10
+ let(:verifiable_pact_messages) do
11
+ instance_double(VerifiablePactMessages,
12
+ inclusion_reason: 'the inclusion reason',
13
+ pending_reason: 'pending reason',
14
+ verification_success_true_published_false: 'verification_success_true_published_false',
15
+ verification_success_false_published_false: 'verification_success_false_published_false',
16
+ verification_success_true_published_true: 'verification_success_true_published_true',
17
+ verification_success_false_published_true: 'verification_success_false_published_true'
18
+ )
19
+ end
20
+
21
+ let(:options) { {} }
22
+ let(:pact_url) { 'http://pact' }
23
+ let(:verifiable_pact) { instance_double('PactBroker::Pacts::VerifiablePact') }
24
+
25
+ subject { BuildVerifiablePactNotices.call(verifiable_pact, pact_url, options) }
26
+
27
+
28
+ context "when include_pending_status is true" do
29
+ let(:expected_notices) do
30
+ [
31
+ {
32
+ :when => "before_verification",
33
+ :text => "the inclusion reason"
34
+ },{
35
+ :when => "before_verification",
36
+ :text => 'pending reason'
37
+ },{
38
+ :when => "after_verification:success_true_published_false",
39
+ :text => "verification_success_true_published_false"
40
+ },{
41
+ :when => "after_verification:success_false_published_false",
42
+ :text => "verification_success_false_published_false"
43
+ },{
44
+ :when => "after_verification:success_true_published_true",
45
+ :text => "verification_success_true_published_true"
46
+ },{
47
+ :when => "after_verification:success_false_published_true",
48
+ :text => "verification_success_false_published_true"
49
+ }
50
+ ]
51
+ end
52
+
53
+ let(:options) { { include_pending_status: true } }
54
+
55
+ it "it returns a list of notices with information about the pending status" do
56
+ expect(subject).to eq expected_notices
57
+ end
58
+ end
59
+
60
+ context "when include_pending_status is not true" do
61
+ let(:expected_notices) do
62
+ [
63
+ {
64
+ :when => "before_verification",
65
+ :text => "the inclusion reason"
66
+ }
67
+ ]
68
+ end
69
+
70
+ it "it returns a list of notices without information about the pending status" do
71
+ expect(subject).to eq expected_notices
72
+ end
73
+ end
74
+ end
75
+ end
76
+ end
@@ -0,0 +1,73 @@
1
+ require 'pact_broker/pacts/repository'
2
+
3
+ module PactBroker
4
+ module Pacts
5
+ describe Repository do
6
+ let(:td) { TestDataBuilder.new }
7
+
8
+ describe "#find_for_verification" do
9
+ def find_by_consumer_version_number(consumer_version_number)
10
+ subject.find{ |pact| pact.consumer_version_number == consumer_version_number }
11
+ end
12
+
13
+ def find_by_consumer_name_and_consumer_version_number(consumer_name, consumer_version_number)
14
+ subject.find{ |pact| pact.consumer_name == consumer_name && pact.consumer_version_number == consumer_version_number }
15
+ end
16
+
17
+ subject { Repository.new.find_for_verification("Bar", consumer_version_selectors) }
18
+
19
+ context "when there is a fallback tag specified" do
20
+ before do
21
+ td.create_pact_with_consumer_version_tag("Foo", "1", "master", "Bar")
22
+ .create_pact_with_consumer_version_tag("Foo", "2", "feat-x", "Bar")
23
+ end
24
+
25
+ let(:tag) { "feat-x" }
26
+ let(:fallback_tag) { "master" }
27
+ let(:selector) { Selector.new(tag: tag, fallback_tag: fallback_tag, latest: true) }
28
+ let(:consumer_version_selectors) { Selectors.new(selector) }
29
+
30
+ context "when a pact exists for the main tag" do
31
+ it "returns the pact with the main tag" do
32
+ expect(find_by_consumer_version_number("2")).to_not be nil
33
+ expect(find_by_consumer_version_number("2").selectors.first).to eq Selector.latest_for_tag(tag)
34
+ end
35
+
36
+ it "does not set the fallback_tag on the selector" do
37
+ expect(find_by_consumer_version_number("2").selectors.first.fallback_tag).to be nil
38
+ end
39
+ end
40
+
41
+ context "when a pact does not exist for the main tag and pact exists for the fallback tag" do
42
+ let(:tag) { "no-existy" }
43
+
44
+ it "returns the pact with the fallback tag" do
45
+ expect(find_by_consumer_version_number("1")).to_not be nil
46
+ end
47
+
48
+ it "sets the fallback_tag on the selector" do
49
+ expect(find_by_consumer_version_number("1").selectors.first.fallback_tag).to eq fallback_tag
50
+ end
51
+
52
+ it "sets the tag on the selector" do
53
+ expect(find_by_consumer_version_number("1").selectors.first.tag).to eq tag
54
+ end
55
+
56
+ it "sets the latest flag on the selector" do
57
+ expect(find_by_consumer_version_number("1").selectors.first.latest).to be true
58
+ end
59
+ end
60
+
61
+ context "when a pact does not exist for either tag or fallback_tag" do
62
+ let(:tag) { "no-existy" }
63
+ let(:fallback_tag) { "also-no-existy" }
64
+
65
+ it "returns an empty list" do
66
+ expect(subject).to be_empty
67
+ end
68
+ end
69
+ end
70
+ end
71
+ end
72
+ end
73
+ end
@@ -15,7 +15,6 @@ module PactBroker
15
15
  subject.find{ |pact| pact.consumer_name == consumer_name && pact.consumer_version_number == consumer_version_number }
16
16
  end
17
17
 
18
-
19
18
  subject { Repository.new.find_for_verification("Bar", consumer_version_selectors) }
20
19
 
21
20
  context "when there are no selectors" do
@@ -32,7 +31,7 @@ module PactBroker
32
31
  .create_pact
33
32
  end
34
33
 
35
- let(:consumer_version_selectors) { [] }
34
+ let(:consumer_version_selectors) { Selectors.new }
36
35
 
37
36
  it "returns the latest pact for each consumer" do
38
37
  expect(subject.size).to eq 2
@@ -57,10 +56,10 @@ module PactBroker
57
56
  .create_pact
58
57
  end
59
58
 
60
- let(:pact_selector_1) { double('selector', tag: 'dev', latest: true) }
61
- let(:pact_selector_2) { double('selector', tag: 'prod', latest: true) }
59
+ let(:pact_selector_1) { Selector.latest_for_tag('dev') }
60
+ let(:pact_selector_2) { Selector.latest_for_tag('prod') }
62
61
  let(:consumer_version_selectors) do
63
- [pact_selector_1, pact_selector_2]
62
+ Selectors.new(pact_selector_1, pact_selector_2)
64
63
  end
65
64
 
66
65
  it "returns the latest pact with the specified tags for each consumer" do
@@ -85,8 +84,8 @@ module PactBroker
85
84
  .create_pact
86
85
  end
87
86
 
88
- let(:consumer_version_selectors) { [pact_selector_1] }
89
- let(:pact_selector_1) { double('selector', tag: 'prod', latest: nil) }
87
+ let(:consumer_version_selectors) { Selectors.new(pact_selector_1) }
88
+ let(:pact_selector_1) { Selector.all_for_tag('prod') }
90
89
 
91
90
  subject { Repository.new.find_for_verification("Bar2", consumer_version_selectors) }
92
91
 
@@ -111,10 +110,9 @@ module PactBroker
111
110
  .create_consumer_version_tag("prod")
112
111
  end
113
112
 
114
- let(:consumer_version_selectors) { [pact_selector_1, pact_selector_2] }
115
- let(:pact_selector_1) { double('selector1', tag: 'prod', latest: nil) }
116
- let(:pact_selector_2) { double('selector2', tag: 'dev', latest: true) }
117
- let(:consumer_version_selectors) { [pact_selector_1, pact_selector_2] }
113
+ let(:pact_selector_1) { Selector.all_for_tag('prod') }
114
+ let(:pact_selector_2) { Selector.latest_for_tag('dev') }
115
+ let(:consumer_version_selectors) { Selectors.new(pact_selector_1, pact_selector_2) }
118
116
 
119
117
  it "returns a single selected pact with multiple selectors" do
120
118
  expect(subject.size).to eq 1
@@ -136,7 +134,7 @@ module PactBroker
136
134
  .create_pact
137
135
  end
138
136
 
139
- let(:consumer_version_selectors) { [] }
137
+ let(:consumer_version_selectors) { Selectors.new }
140
138
 
141
139
  it "returns the latest pact for each provider" do
142
140
  expect(find_by_consumer_version_number("foo-latest-dev-version")).to_not be nil
@@ -0,0 +1,28 @@
1
+ require 'pact_broker/pacts/selector'
2
+
3
+ module PactBroker
4
+ module Pacts
5
+ describe Selector do
6
+ describe "<=>" do
7
+ let(:overall_latest_1) { Selector.overall_latest }
8
+ let(:overall_latest_2) { Selector.overall_latest }
9
+ let(:latest_for_tag_prod) { Selector.latest_for_tag('prod') }
10
+ let(:latest_for_tag_dev) { Selector.latest_for_tag('dev') }
11
+ let(:all_prod) { Selector.all_for_tag('prod') }
12
+ let(:all_dev) { Selector.all_for_tag('dev') }
13
+
14
+ let(:unsorted_selectors) do
15
+ [all_prod, all_dev, latest_for_tag_prod, overall_latest_1, overall_latest_1, latest_for_tag_dev]
16
+ end
17
+
18
+ let(:expected_sorted_selectors) do
19
+ [overall_latest_1, overall_latest_1, latest_for_tag_dev, latest_for_tag_prod, all_dev, all_prod]
20
+ end
21
+
22
+ it "sorts the selectors" do
23
+ expect(unsorted_selectors.sort).to eq(expected_sorted_selectors)
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,30 @@
1
+ require 'pact_broker/pacts/selectors'
2
+ require 'pact_broker/pacts/selector'
3
+
4
+ module PactBroker
5
+ module Pacts
6
+ describe Selectors do
7
+ let(:selector_1) { Selector.overall_latest }
8
+ let(:selector_2) { Selector.latest_for_tag('dev') }
9
+ let(:selectors_1) { Selectors.new([selector_1]) }
10
+ let(:selectors_2) { Selectors.new([selector_2]) }
11
+ let(:selectors_array) { [selectors_1, selectors_2] }
12
+
13
+ describe "intialize" do
14
+ it "allows an array of Selector objects" do
15
+ expect(Selectors.new([selector_1, selector_2]).size).to eq 2
16
+ end
17
+
18
+ it "allows arguments of Selector objects" do
19
+ expect(Selectors.new(selector_1, selector_2).size).to eq 2
20
+ end
21
+ end
22
+
23
+ describe "+" do
24
+ it "returns an object of type Selector" do
25
+ expect(selectors_1 + selectors_2).to be_a(Selectors)
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end