pact_broker 2.76.1 → 2.79.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (188) hide show
  1. checksums.yaml +4 -4
  2. data/.codeclimate.yml +12 -0
  3. data/.github/workflows/release_gem.yml +1 -0
  4. data/.github/workflows/test-ruby-3.yml +19 -0
  5. data/.github/workflows/test.yml +16 -7
  6. data/.gitignore +3 -1
  7. data/CHANGELOG.md +50 -0
  8. data/DEVELOPER_DOCUMENTATION.md +13 -0
  9. data/DEVELOPER_SETUP.md +62 -3
  10. data/Dockerfile +1 -0
  11. data/ISSUES.md +12 -4
  12. data/config.ru +2 -1
  13. data/db/ddl_statements/head_pact_tags.rb +24 -1
  14. data/db/ddl_statements/latest_tagged_pact_consumer_version_orders.rb +11 -0
  15. data/db/ddl_statements/latest_tagged_pact_publications.rb +6 -0
  16. data/db/ddl_statements/latest_verification_ids_for_consumer_version_tags.rb +13 -0
  17. data/db/migrations/20210117_add_branch_to_version.rb +9 -0
  18. data/db/migrations/20210202_add_created_at_to_head_pact_tags.rb +14 -0
  19. data/db/migrations/20210205_add_pacticipant_id_to_tag.rb +17 -0
  20. data/db/migrations/20210206_add_index_to_tags_and_versions.rb +27 -0
  21. data/db/migrations/20210207_optimise_latest_verification_ids_for_consumer_version_tags.rb +13 -0
  22. data/db/migrations/20210208_optimise_latest_tagged_pact_cv_orders.rb +13 -0
  23. data/db/migrations/20210210_create_environments_table.rb +16 -0
  24. data/docker-compose-dev-postgres.yml +9 -1
  25. data/docker-compose-issue-repro-with-pact-broker-docker-image.yml +16 -5
  26. data/lib/pact_broker/api.rb +7 -2
  27. data/lib/pact_broker/api/contracts/dry_validation_predicates.rb +8 -0
  28. data/lib/pact_broker/api/contracts/environment_schema.rb +49 -0
  29. data/lib/pact_broker/api/decorators/base_decorator.rb +11 -0
  30. data/lib/pact_broker/api/decorators/dashboard_decorator.rb +5 -1
  31. data/lib/pact_broker/api/decorators/environment_decorator.rb +30 -0
  32. data/lib/pact_broker/api/decorators/environments_decorator.rb +21 -0
  33. data/lib/pact_broker/api/decorators/matrix_decorator.rb +3 -1
  34. data/lib/pact_broker/api/decorators/verifiable_pacts_query_decorator.rb +2 -0
  35. data/lib/pact_broker/api/decorators/version_decorator.rb +15 -2
  36. data/lib/pact_broker/api/pact_broker_urls.rb +8 -0
  37. data/lib/pact_broker/api/resources/default_base_resource.rb +18 -0
  38. data/lib/pact_broker/api/resources/environment.rb +76 -0
  39. data/lib/pact_broker/api/resources/environments.rb +75 -0
  40. data/lib/pact_broker/api/resources/index.rb +20 -0
  41. data/lib/pact_broker/api/resources/latest_version.rb +27 -0
  42. data/lib/pact_broker/api/resources/provider_pacts_for_verification.rb +1 -0
  43. data/lib/pact_broker/api/resources/verifications.rb +5 -2
  44. data/lib/pact_broker/api/resources/version.rb +15 -9
  45. data/lib/pact_broker/api/resources/webhook_execution.rb +1 -1
  46. data/lib/pact_broker/app.rb +1 -1
  47. data/lib/pact_broker/certificates/certificate.rb +1 -1
  48. data/lib/pact_broker/config/setting.rb +1 -1
  49. data/lib/pact_broker/config/space_delimited_integer_list.rb +25 -0
  50. data/lib/pact_broker/configuration.rb +22 -1
  51. data/lib/pact_broker/db/data_migrations/helpers.rb +4 -0
  52. data/lib/pact_broker/db/data_migrations/set_extra_columns_for_tags.rb +29 -0
  53. data/lib/pact_broker/db/migrate_data.rb +1 -0
  54. data/lib/pact_broker/db/seed_example_data.rb +13 -13
  55. data/lib/pact_broker/deployments/environment.rb +15 -0
  56. data/lib/pact_broker/deployments/environment_service.rb +39 -0
  57. data/lib/pact_broker/doc/views/index/environment.markdown +37 -0
  58. data/lib/pact_broker/doc/views/index/environments.markdown +53 -0
  59. data/lib/pact_broker/doc/views/index/latest-pact-versions.markdown +1 -1
  60. data/lib/pact_broker/doc/views/index/pacticipant-version-tag.markdown +1 -0
  61. data/lib/pact_broker/doc/views/index/pacticipant-version.markdown +13 -0
  62. data/lib/pact_broker/domain/index_item.rb +18 -4
  63. data/lib/pact_broker/domain/pacticipant.rb +9 -5
  64. data/lib/pact_broker/domain/tag.rb +131 -71
  65. data/lib/pact_broker/domain/verification.rb +3 -2
  66. data/lib/pact_broker/domain/version.rb +58 -23
  67. data/lib/pact_broker/domain/webhook.rb +12 -9
  68. data/lib/pact_broker/hash_refinements.rb +4 -0
  69. data/lib/pact_broker/index/service.rb +55 -49
  70. data/lib/pact_broker/locale/en.yml +3 -1
  71. data/lib/pact_broker/matrix/quick_row.rb +8 -0
  72. data/lib/pact_broker/metrics/service.rb +1 -1
  73. data/lib/pact_broker/pacts/eager_loaders.rb +52 -0
  74. data/lib/pact_broker/pacts/latest_pact_publication_id_for_consumer_version.rb +18 -13
  75. data/lib/pact_broker/pacts/lazy_loaders.rb +14 -0
  76. data/lib/pact_broker/pacts/pact_publication.rb +38 -84
  77. data/lib/pact_broker/pacts/pact_publication_dataset_module.rb +297 -0
  78. data/lib/pact_broker/pacts/pact_version.rb +1 -2
  79. data/lib/pact_broker/pacts/pacts_for_verification_repository.rb +286 -0
  80. data/lib/pact_broker/pacts/repository.rb +5 -240
  81. data/lib/pact_broker/pacts/selected_pact.rb +4 -0
  82. data/lib/pact_broker/pacts/selector.rb +56 -1
  83. data/lib/pact_broker/pacts/selectors.rb +16 -0
  84. data/lib/pact_broker/pacts/service.rb +6 -8
  85. data/lib/pact_broker/pacts/squash_pacts_for_verification.rb +1 -4
  86. data/lib/pact_broker/pacts/verifiable_pact.rb +23 -2
  87. data/lib/pact_broker/pacts/verifiable_pact_messages.rb +56 -16
  88. data/lib/pact_broker/repositories/helpers.rb +4 -0
  89. data/lib/pact_broker/services.rb +9 -0
  90. data/lib/pact_broker/tags/eager_loaders.rb +47 -0
  91. data/lib/pact_broker/tags/repository.rb +3 -1
  92. data/lib/pact_broker/tags/service.rb +0 -3
  93. data/lib/pact_broker/tags/tag_with_latest_flag.rb +1 -0
  94. data/lib/pact_broker/test/http_test_data_builder.rb +86 -25
  95. data/lib/pact_broker/test/test_data_builder.rb +50 -3
  96. data/lib/pact_broker/ui/view_models/index_item.rb +19 -2
  97. data/lib/pact_broker/ui/view_models/matrix_line.rb +38 -2
  98. data/lib/pact_broker/ui/views/index/show-with-tags.haml +14 -6
  99. data/lib/pact_broker/ui/views/matrix/show.haml +12 -2
  100. data/lib/pact_broker/verifications/latest_verification_id_for_pact_version_and_provider_version.rb +7 -5
  101. data/lib/pact_broker/verifications/service.rb +2 -1
  102. data/lib/pact_broker/version.rb +1 -1
  103. data/lib/pact_broker/versions/eager_loaders.rb +71 -0
  104. data/lib/pact_broker/versions/lazy_loaders.rb +13 -0
  105. data/lib/pact_broker/versions/repository.rb +22 -2
  106. data/lib/pact_broker/versions/service.rb +5 -1
  107. data/lib/pact_broker/webhooks/execution.rb +3 -2
  108. data/lib/pact_broker/webhooks/latest_triggered_webhook.rb +2 -0
  109. data/lib/pact_broker/webhooks/pact_and_verification_parameters.rb +10 -3
  110. data/lib/pact_broker/webhooks/service.rb +8 -7
  111. data/lib/pact_broker/webhooks/trigger_service.rb +56 -23
  112. data/lib/pact_broker/webhooks/triggered_webhook.rb +14 -5
  113. data/lib/pact_broker/webhooks/webhook.rb +1 -1
  114. data/lib/pact_broker/webhooks/webhook_event.rb +1 -1
  115. data/lib/pact_broker/webhooks/webhook_execution_result.rb +6 -1
  116. data/lib/pact_broker/webhooks/webhook_request_logger.rb +7 -1
  117. data/lib/rack/pact_broker/set_base_url.rb +35 -5
  118. data/lib/sequel/plugins/upsert.rb +18 -4
  119. data/public/javascripts/clipboard.js +8 -2
  120. data/public/stylesheets/index.css +22 -1
  121. data/public/stylesheets/matrix.css +0 -21
  122. data/regression/can_i_deploy_spec.rb +5 -4
  123. data/regression/index_spec.rb +26 -0
  124. data/regression/regression_helper.rb +29 -3
  125. data/regression/script/clear.sh +3 -0
  126. data/regression/script/run.sh +3 -0
  127. data/script/demonstrate-version-branches.rb +33 -0
  128. data/script/pry.rb +2 -2
  129. data/script/reproduce-issue-starting-up.rb +13 -23
  130. data/script/reproduce-issue.rb +2 -1
  131. data/script/trigger-release.sh +1 -1
  132. data/script/webhook-server.ru +5 -5
  133. data/spec/features/create_environment_spec.rb +47 -0
  134. data/spec/features/create_tag_spec.rb +32 -0
  135. data/spec/features/create_version_spec.rb +70 -0
  136. data/spec/features/delete_environment_spec.rb +16 -0
  137. data/spec/features/end_deployment_spec.rb +29 -0
  138. data/spec/features/get_environment_spec.rb +19 -0
  139. data/spec/features/get_environments_spec.rb +20 -0
  140. data/spec/features/record_deployment_spec.rb +28 -0
  141. data/spec/features/update_environment_spec.rb +44 -0
  142. data/spec/fixtures/approvals/modifiable_resources.approved.json +6 -0
  143. data/spec/fixtures/dashboard.json +4 -2
  144. data/spec/lib/pact_broker/api/contracts/environment_schema_spec.rb +83 -0
  145. data/spec/lib/pact_broker/api/decorators/dashboard_decorator_spec.rb +4 -2
  146. data/spec/lib/pact_broker/api/decorators/matrix_decorator_spec.rb +11 -6
  147. data/spec/lib/pact_broker/api/decorators/verifiable_pacts_query_decorator_spec.rb +6 -0
  148. data/spec/lib/pact_broker/api/decorators/version_decorator_spec.rb +18 -0
  149. data/spec/lib/pact_broker/api/resources/default_base_resource_approval_spec.rb +1 -1
  150. data/spec/lib/pact_broker/api/resources/provider_pacts_for_verification_spec.rb +4 -0
  151. data/spec/lib/pact_broker/api/resources/verifications_spec.rb +2 -5
  152. data/spec/lib/pact_broker/api/resources/webhook_execution_result_spec.rb +56 -0
  153. data/spec/lib/pact_broker/api/resources/webhook_execution_spec.rb +3 -2
  154. data/spec/lib/pact_broker/config/space_delimited_integer_list_spec.rb +47 -0
  155. data/spec/lib/pact_broker/configuration_spec.rb +12 -0
  156. data/spec/lib/pact_broker/domain/tag_spec.rb +101 -27
  157. data/spec/lib/pact_broker/domain/version_spec.rb +103 -15
  158. data/spec/lib/pact_broker/domain/webhook_spec.rb +7 -7
  159. data/spec/lib/pact_broker/index/service_spec.rb +89 -15
  160. data/spec/lib/pact_broker/pacts/pact_publication_dataset_module_spec.rb +400 -0
  161. data/spec/lib/pact_broker/pacts/pact_publication_spec.rb +434 -14
  162. data/spec/lib/pact_broker/pacts/repository_find_for_verification_fallback_spec.rb +1 -1
  163. data/spec/lib/pact_broker/pacts/repository_find_for_verification_spec.rb +1 -1
  164. data/spec/lib/pact_broker/pacts/repository_find_wip_pact_versions_for_provider_branch_spec.rb +224 -0
  165. data/spec/lib/pact_broker/pacts/repository_find_wip_pact_versions_for_provider_spec.rb +20 -7
  166. data/spec/lib/pact_broker/pacts/selector_spec.rb +3 -2
  167. data/spec/lib/pact_broker/pacts/service_find_for_verification_spec.rb +2 -3
  168. data/spec/lib/pact_broker/pacts/service_spec.rb +9 -7
  169. data/spec/lib/pact_broker/pacts/verifiable_pact_messages_spec.rb +57 -10
  170. data/spec/lib/pact_broker/tags/repository_spec.rb +2 -0
  171. data/spec/lib/pact_broker/verifications/service_spec.rb +4 -1
  172. data/spec/lib/pact_broker/versions/repository_spec.rb +54 -0
  173. data/spec/lib/pact_broker/webhooks/render_spec.rb +6 -5
  174. data/spec/lib/pact_broker/webhooks/service_spec.rb +13 -9
  175. data/spec/lib/pact_broker/webhooks/trigger_service_spec.rb +60 -18
  176. data/spec/lib/pact_broker/webhooks/webhook_request_logger_spec.rb +8 -0
  177. data/spec/lib/rack/pact_broker/set_base_url_spec.rb +86 -0
  178. data/spec/lib/sequel/plugins/upsert_spec.rb +31 -3
  179. data/spec/service_consumers/hal_relation_proxy_app.rb +3 -1
  180. data/spec/service_consumers/provider_states_for_pact_broker_client.rb +16 -0
  181. data/spec/spec_helper.rb +17 -5
  182. data/spec/support/approvals.rb +24 -0
  183. data/spec/support/shared_examples_for_responses.rb +11 -0
  184. data/tasks/database.rb +1 -1
  185. data/tasks/db.rake +1 -0
  186. data/tasks/rspec.rake +1 -1
  187. metadata +68 -4
  188. data/docker-compose-issue-repro.yml +0 -22
@@ -0,0 +1,400 @@
1
+ require 'pact_broker/pacts/pact_publication'
2
+
3
+ module PactBroker
4
+ module Pacts
5
+ describe PactPublication do
6
+ describe "latest_by_consumer_branch" do
7
+ before do
8
+ td.set_now(Date.new(2020, 1, 1))
9
+ .create_consumer("Foo")
10
+ .create_provider("Bar")
11
+ .create_consumer_version("1", branch: "main")
12
+ .create_pact
13
+ .set_now(Date.new(2020, 1, 2))
14
+ .create_consumer_version("2", branch: "feat/x")
15
+ .create_pact
16
+ .set_now(Date.new(2020, 1, 3))
17
+ .create_consumer_version("3", branch: "main", comment: "latest")
18
+ .create_pact
19
+ .set_now(Date.new(2020, 1, 4))
20
+ .create_consumer_version("4", branch: "feat/x", comment: "latest")
21
+ .create_pact
22
+ .set_now(Date.new(2020, 1, 5))
23
+ .create_consumer("FooZ")
24
+ .create_consumer_version("6", branch: "main", comment: "latest, different consumer")
25
+ .create_pact
26
+ .set_now(Date.new(2020, 1, 6))
27
+ .create_consumer_version("7", comment: "No branch")
28
+ .create_pact
29
+ .set_now(Date.new(2020, 1, 7))
30
+ .create_consumer_version("8", branch: "main", comment: "No pact")
31
+ end
32
+
33
+ subject { PactPublication.latest_by_consumer_branch.all }
34
+
35
+ let(:foo) { PactBroker::Domain::Pacticipant.where(name: "Foo").single_record }
36
+ let(:bar) { PactBroker::Domain::Pacticipant.where(name: "Bar").single_record }
37
+ let(:foo_z) { PactBroker::Domain::Pacticipant.where(name: "FooZ").single_record }
38
+
39
+ it "returns the latest pact publications for each consumer/branch" do
40
+ expect(subject.size).to eq 3
41
+
42
+ expect(subject.find { |pp| pp.consumer_id == foo.id && pp[:branch] == "main" }.consumer_version.number).to eq "3"
43
+ expect(subject.find { |pp| pp.consumer_id == foo.id && pp[:branch] == "feat/x" }.consumer_version.number).to eq "4"
44
+ expect(subject.find { |pp| pp.consumer_id == foo_z.id && pp[:branch] == "main" }.consumer_version.number).to eq "6"
45
+ end
46
+
47
+ it "does not return extra columns" do
48
+ expect(subject.first.values.keys.sort).to eq (PactPublication.columns + [:branch]).sort
49
+ end
50
+
51
+ context "chained with created after" do
52
+ subject { PactPublication.created_after(DateTime.new(2020, 1, 3)).latest_by_consumer_branch.all }
53
+
54
+ its(:size) { is_expected.to eq 2 }
55
+
56
+ it "returns the right versions" do
57
+ expect(subject.find { |pp| pp.consumer_id == foo.id && pp[:branch] == "feat/x" }.consumer_version.number).to eq "4"
58
+ expect(subject.find { |pp| pp.consumer_id == foo_z.id && pp[:branch] == "main" }.consumer_version.number).to eq "6"
59
+ end
60
+ end
61
+ end
62
+
63
+ describe "latest_for_consumer_branch" do
64
+ before do
65
+ td.create_consumer("Foo")
66
+ .create_provider("Bar")
67
+ .create_consumer_version("1", branch: "main")
68
+ .create_pact
69
+ .create_consumer_version("2", branch: "main")
70
+ .create_pact
71
+ .create_consumer_version("3", branch: "feat-x")
72
+ .create_pact
73
+ .create_consumer("Foo2")
74
+ .create_provider("Bar2")
75
+ .create_consumer_version("10", branch: "main")
76
+ .create_pact
77
+ .create_consumer_version("11", branch: "main")
78
+ .create_pact
79
+ end
80
+
81
+ subject { PactPublication.latest_for_consumer_branch("main") }
82
+
83
+ it "returns the latest pacts for the branches with the specified name (for any consumer/provider)" do
84
+ all = subject.all.sort_by{ |pact_publication| pact_publication.consumer_version.order }
85
+ expect(all.size).to eq 2
86
+ expect(all.first.consumer.name).to eq "Foo"
87
+ expect(all.first.provider.name).to eq "Bar"
88
+ expect(all.first.consumer_version.number).to eq "2"
89
+
90
+ expect(all.last.consumer.name).to eq "Foo2"
91
+ expect(all.last.provider.name).to eq "Bar2"
92
+ expect(all.last.consumer_version.number).to eq "11"
93
+ end
94
+
95
+ it "does not return extra columns" do
96
+ expect(subject.first.values.keys.sort).to eq (PactPublication.columns + [:branch]).sort
97
+ end
98
+
99
+ context "when columns are already selected" do
100
+ subject { PactPublication.select(Sequel[:pact_publications][:id]).latest_for_consumer_branch("main") }
101
+
102
+ it "does not override them" do
103
+ expect(subject.all.first.values.keys).to eq [:id]
104
+ end
105
+ end
106
+
107
+ context "when chained" do
108
+ it "works" do
109
+ all = PactPublication.for_provider(td.find_pacticipant("Bar")).latest_for_consumer_branch("main").all
110
+ expect(all.first.provider.name).to eq "Bar"
111
+ end
112
+ end
113
+ end
114
+
115
+ describe "latest_by_consumer_tag" do
116
+ before do
117
+ td.create_consumer("Foo")
118
+ .create_provider("Bar")
119
+ .create_consumer_version("1", tag_names: ["main"])
120
+ .create_pact
121
+ .create_consumer_version("2", tag_names: ["feat/x"])
122
+ .create_pact
123
+ .create_consumer_version("3", tag_names: ["main"], comment: "latest")
124
+ .create_pact
125
+ .create_consumer_version("4", tag_names: ["feat/x"], comment: "latest")
126
+ .create_pact
127
+ .create_consumer("FooZ")
128
+ .create_consumer_version("6", tag_names: ["main"], comment: "Different consumer")
129
+ .create_pact
130
+ .create_consumer_version("7", comment: "No branch")
131
+ .create_pact
132
+ .create_consumer_version("8", tag_names: ["main"], comment: "No pact")
133
+ end
134
+
135
+ subject { PactPublication.latest_by_consumer_tag.all }
136
+
137
+ let(:foo) { PactBroker::Domain::Pacticipant.where(name: "Foo").single_record }
138
+ let(:bar) { PactBroker::Domain::Pacticipant.where(name: "Bar").single_record }
139
+ let(:foo_z) { PactBroker::Domain::Pacticipant.where(name: "FooZ").single_record }
140
+
141
+ it "returns the latest pact publications for each consumer/branch" do
142
+ expect(subject.size).to eq 3
143
+ hashes = subject.collect(&:values)
144
+
145
+ expect(subject.find { |pp| pp.consumer_id == foo.id && pp[:tag_name] == "main" }.consumer_version.number).to eq "3"
146
+ expect(subject.find { |pp| pp.consumer_id == foo.id && pp[:tag_name] == "feat/x" }.consumer_version.number).to eq "4"
147
+ expect(subject.find { |pp| pp.consumer_id == foo_z.id && pp[:tag_name] == "main" }.consumer_version.number).to eq "6"
148
+ end
149
+
150
+ it "does not return extra columns" do
151
+ expect(subject.first.values.keys.sort).to eq (PactPublication.columns + [:tag_name]).sort
152
+ end
153
+
154
+ context "when columns are already selected" do
155
+ subject { PactPublication.select(Sequel[:pact_publications][:id]).latest_by_consumer_tag }
156
+
157
+ it "does not override them" do
158
+ expect(subject.all.first.values.keys).to eq [:id]
159
+ end
160
+ end
161
+ end
162
+
163
+ describe "overall_latest" do
164
+ before do
165
+ td.create_consumer("Foo")
166
+ .create_provider("Bar")
167
+ .create_consumer_version("1", tag_names: ["main"])
168
+ .create_pact
169
+ .create_consumer_version("2", tag_names: ["main"])
170
+ .create_pact
171
+ .create_consumer_version("3", tag_names: ["feat/x"])
172
+ .create_pact
173
+ .create_consumer("Foo2")
174
+ .create_provider("Bar2")
175
+ .create_consumer_version("10", tag_names: ["main"])
176
+ .create_pact
177
+ .create_consumer_version("11", tag_names: ["main"])
178
+ .create_pact
179
+ end
180
+
181
+ subject { PactPublication.overall_latest }
182
+
183
+ it "returns the latest by consumer/provider" do
184
+ all = subject.all.sort_by{ | pact_publication | pact_publication.consumer_version.order }
185
+ expect(all.size).to eq 2
186
+ end
187
+
188
+ it "does not return extra columns" do
189
+ expect(subject.all.first.values.keys.sort).to eq PactPublication.columns.sort
190
+ end
191
+
192
+ context "when columns are already selected" do
193
+ subject { PactPublication.select(Sequel[:pact_publications][:id]).overall_latest }
194
+
195
+ it "does not override them" do
196
+ expect(subject.all.first.values.keys).to eq [:id]
197
+ end
198
+ end
199
+
200
+ context "when chained" do
201
+ it "works with a consumer" do
202
+ expect(PactPublication.for_consumer(td.find_pacticipant("Foo")).overall_latest.all.first.consumer.name).to eq "Foo"
203
+ end
204
+
205
+ it "works with a consumer and provider" do
206
+ td.create_pact_with_hierarchy("Foo", "666", "Nope")
207
+ all = PactPublication
208
+ .for_consumer(td.find_pacticipant("Foo"))
209
+ .for_provider(td.find_pacticipant("Bar"))
210
+ .overall_latest.all
211
+ expect(all.size).to eq 1
212
+ expect(all.first.consumer.name).to eq "Foo"
213
+ expect(all.first.provider.name).to eq "Bar"
214
+ end
215
+ end
216
+ end
217
+
218
+ describe "latest_for_consumer_tag" do
219
+ before do
220
+ td.create_consumer("Foo")
221
+ .create_provider("Bar")
222
+ .create_consumer_version("1", tag_names: ["main"])
223
+ .create_pact
224
+ .create_consumer_version("2", tag_names: ["main"])
225
+ .create_pact
226
+ .revise_pact
227
+ .create_consumer_version("3", tag_names: ["feat/x"])
228
+ .create_pact
229
+ .create_consumer("Foo2")
230
+ .create_provider("Bar2")
231
+ .create_consumer_version("10", tag_names: ["main"])
232
+ .create_pact
233
+ .create_consumer_version("11", tag_names: ["main"])
234
+ .create_pact
235
+ end
236
+
237
+ subject { PactPublication.latest_for_consumer_tag("main") }
238
+
239
+ it "returns the latest pacts for the tags with the specified name (for any consumer/provider)" do
240
+ all = subject.all.sort_by{ |pact_publication| pact_publication.consumer_version.order }
241
+ expect(all.size).to eq 2
242
+ expect(all.first.consumer.name).to eq "Foo"
243
+ expect(all.first.provider.name).to eq "Bar"
244
+ expect(all.first.consumer_version.number).to eq "2"
245
+
246
+ expect(all.last.consumer.name).to eq "Foo2"
247
+ expect(all.last.provider.name).to eq "Bar2"
248
+ expect(all.last.consumer_version.number).to eq "11"
249
+ end
250
+
251
+ it "does not return extra columns" do
252
+ expect(subject.all.first.values.keys.sort).to eq (PactPublication.columns + [:tag_name]).sort
253
+ end
254
+
255
+ context "when columns are already selected" do
256
+ subject { PactPublication.select(Sequel[:pact_publications][:id]).latest_for_consumer_tag("main") }
257
+
258
+ it "does not override them" do
259
+ expect(subject.all.first.values.keys).to eq [:id]
260
+ end
261
+ end
262
+
263
+ context "when chained" do
264
+ it "works" do
265
+ all = PactPublication.for_provider(td.find_pacticipant("Bar")).latest_for_consumer_tag("main").all
266
+ expect(all.first.provider.name).to eq "Bar"
267
+ end
268
+ end
269
+ end
270
+
271
+ describe "#successfully_verified_by_provider_branch" do
272
+ let(:bar) { td.find_pacticipant("Bar") }
273
+
274
+ subject { PactPublication.successfully_verified_by_provider_branch(bar.id, "main").all }
275
+
276
+ context "PactPublication" do
277
+ before do
278
+ td.create_pact_with_hierarchy("Foo", "1", "Bar")
279
+ .create_verification(provider_version: "2", branch: "main", success: false)
280
+ .create_pact_with_hierarchy("Foo", "2", "Bar")
281
+ .create_verification(provider_version: "2", branch: "main", success: true)
282
+ .create_pact_with_hierarchy("Foo", "3", "Bar")
283
+ .create_verification(provider_version: "3", branch: "not-main", success: true)
284
+ end
285
+
286
+ it "returns the pact publications that have been succesfully verified by the given provider id and branch" do
287
+ expect(subject.size).to eq 1
288
+ expect(subject.first.consumer_version.number).to eq "2"
289
+ end
290
+
291
+ it "does not return extra columns" do
292
+ expect(subject.first.values.keys.sort).to eq PactPublication.columns.sort
293
+ end
294
+ end
295
+
296
+
297
+ context "with chained scopes" do
298
+ subject { PactPublication.latest_by_consumer_branch.successfully_verified_by_provider_branch(bar.id, "provider-main").all }
299
+
300
+ context "when there are no latest branch pacts that have been successfully verified by the specified provider branch" do
301
+ before do
302
+ td.create_consumer("Foo")
303
+ .create_provider("Bar")
304
+ .create_consumer_version("1", branch: "main", comment: "not latest")
305
+ .create_pact
306
+ .create_verification(provider_version: "1", success: true, branch: "provider-main", comment: "successful but not latest")
307
+ .create_consumer_version("2", branch: "main", comment: "latest")
308
+ .create_pact
309
+ .create_verification(provider_version: "2", success: false, branch: "provider-main", comment: "latest but not successful")
310
+ .create_consumer_version("3", branch: "feat/x", comment: "latest")
311
+ .create_pact
312
+ .create_verification(provider_version: "3", success: true, branch: "not-provider-main", comment: "latest, successful, but wrong branch")
313
+ end
314
+
315
+ it { is_expected.to eq [] }
316
+ end
317
+
318
+ context "when there are latest branch pacts that have been successfully verified by the specified provider branch" do
319
+ before do
320
+ td.create_consumer("Foo")
321
+ .create_provider("Bar")
322
+ .create_consumer_version("1", branch: "main", comment: "not latest")
323
+ .create_pact
324
+ .create_verification(provider_version: "1", success: true, branch: "provider-main")
325
+ .create_consumer_version("2", branch: "main", comment: "latest")
326
+ .create_pact
327
+ .create_verification(provider_version: "1", success: true, branch: "provider-main")
328
+ .create_verification(provider_version: "2", success: true, branch: "provider-main", number: "2")
329
+ end
330
+
331
+ its(:size) { is_expected.to eq 1 }
332
+
333
+ it "returns them" do
334
+ expect(subject.first.consumer_version.number).to eq "2"
335
+ end
336
+ end
337
+
338
+ context "when there are latest tagged pacts that have been successfully verified by the specified provider branch" do
339
+ before do
340
+ td.create_consumer("Foo")
341
+ .create_provider("Bar")
342
+ .create_consumer_version("1", tag_names: ["main"], comment: "not latest")
343
+ .create_pact
344
+ .create_verification(provider_version: "1", success: true, tag_names: ["provider-main"])
345
+ .create_consumer_version("2", tag_names: ["main"], comment: "latest")
346
+ .create_pact
347
+ .create_verification(provider_version: "1", success: true, branch: "provider-main")
348
+ .create_verification(provider_version: "2", success: true, branch: "provider-main", number: "2")
349
+ end
350
+
351
+ subject { PactPublication.latest_by_consumer_tag.successfully_verified_by_provider_branch(bar.id, "provider-main").all }
352
+
353
+ its(:size) { is_expected.to eq 1 }
354
+
355
+ it "returns them" do
356
+ expect(subject.first.consumer_version.number).to eq "2"
357
+ end
358
+ end
359
+
360
+ context "subtracting Pact Publications" do
361
+ before do
362
+ td.create_consumer("Foo")
363
+ .create_provider("Bar")
364
+ .create_consumer_version("1", branch: "main", tag_names: ["main"], comment: "not latest")
365
+ .create_pact
366
+ .create_verification(provider_version: "1", success: true, branch: "provider-main")
367
+ .create_consumer_version("2", branch: "main", tag_names: ["main"], comment: "latest")
368
+ .create_pact
369
+ .create_verification(provider_version: "1", success: true, branch: "provider-main")
370
+ .create_verification(provider_version: "2", success: true, branch: "provider-main", number: "2")
371
+ .create_consumer_version("3", branch: "feat/x", tag_names: ["feat/x"], )
372
+ .create_pact
373
+ end
374
+
375
+ let(:bar) { td.find_pacticipant("Bar") }
376
+
377
+ it "with branches" do
378
+ potential = PactPublication.for_provider(bar).latest_by_consumer_branch
379
+ already_verified = potential.successfully_verified_by_provider_branch(bar.id, "provider-main")
380
+ not_verified = PactPublication.subtract(potential.all, already_verified.all)
381
+
382
+ expect(not_verified.size).to eq 1
383
+ expect(not_verified.first.consumer_version_number).to eq "3"
384
+ end
385
+
386
+ it "with tags" do
387
+ potential = PactPublication.for_provider(bar).latest_by_consumer_tag
388
+ already_verified = potential.successfully_verified_by_provider_branch(bar.id, "provider-main")
389
+ not_verified = PactPublication.subtract(potential.all, already_verified.all)
390
+
391
+ expect(not_verified.size).to eq 1
392
+ expect(not_verified.first.consumer_version_number).to eq "3"
393
+ end
394
+ end
395
+ end
396
+ end
397
+ end
398
+ end
399
+ end
400
+
@@ -86,6 +86,32 @@ module PactBroker
86
86
  end
87
87
  end
88
88
 
89
+ describe "latest_for_branch?" do
90
+ before do
91
+ td.create_consumer("Foo")
92
+ .create_provider("Bar")
93
+ .create_consumer_version("1", branch: "main")
94
+ .create_pact
95
+ .create_consumer_version("2", branch: "main")
96
+ .create_pact
97
+ .create_consumer_version("3", branch: "main")
98
+ end
99
+
100
+ subject { pact_publication.latest_for_branch? }
101
+
102
+ context "when there are no later pacts with the same branch" do
103
+ let(:pact_publication) { PactPublication.where(consumer_version: td.find_version("Foo", "2")).single_record }
104
+
105
+ it { is_expected.to be true }
106
+ end
107
+
108
+ context "when there are later pacts with the same branch" do
109
+ let(:pact_publication) { PactPublication.where(consumer_version: td.find_version("Foo", "1")).single_record }
110
+
111
+ it { is_expected.to be false }
112
+ end
113
+ end
114
+
89
115
  describe "#consumer_version_tags" do
90
116
  before do
91
117
  td.create_pact_with_hierarchy("Foo", "1.2.3", "Bar")
@@ -105,22 +131,22 @@ module PactBroker
105
131
  end
106
132
 
107
133
  describe "#head_tag_names" do
108
- before do
109
- td.create_pact_with_hierarchy("Foo", "1.2.3", "Bar")
110
- .create_consumer_version_tag("no")
111
- .create_consumer_version("3.4.5")
112
- .create_consumer_version_tag("yes")
113
- .create_pact
114
- .create_consumer_version("5.6.7")
115
- .create_consumer_version_tag("no")
116
- .create_consumer("Foo2")
117
- .create_consumer_version("3.4.5")
118
- .create_consumer_version_tag("yes", comment: "actually no, just here to make sure it selects the right one")
119
- end
120
134
 
121
135
  let(:pact_publication) { PactPublication.find(id: td.pact.id) }
122
136
 
123
137
  context "when the pact is the latest for a tag" do
138
+ before do
139
+ td.create_pact_with_hierarchy("Foo", "1.2.3", "Bar")
140
+ .create_consumer_version_tag("no")
141
+ .create_consumer_version("3.4.5")
142
+ .create_consumer_version_tag("yes")
143
+ .create_pact
144
+ .create_consumer_version("5.6.7")
145
+ .create_consumer_version_tag("no")
146
+ .create_consumer("Foo2")
147
+ .create_consumer_version("3.4.5")
148
+ .create_consumer_version_tag("yes", comment: "actually no, just here to make sure it selects the right one")
149
+ end
124
150
  it "returns the relevant tag names" do
125
151
  expect(pact_publication.head_tag_names).to eq ["yes"]
126
152
  expect(pact_publication.head_pact_tags.collect(&:name)).to eq ["yes"]
@@ -128,9 +154,403 @@ module PactBroker
128
154
  end
129
155
 
130
156
  context "when the pact is not the latest for a tag" do
157
+ before do
158
+ td.create_pact_with_hierarchy("Foo", "1", "Bar")
159
+ .create_consumer_version_tag("prod")
160
+ .create_pact_with_hierarchy("Foo", "2", "Bar")
161
+ .create_consumer_version_tag("prod")
162
+
163
+ end
164
+ let(:pact_publication) { PactPublication.where(consumer_version_id: PactBroker::Domain::Version.for("Foo", "1").id).single_record }
165
+
131
166
  it "returns the relevant tag names" do
132
- expect(pact_publication.head_tag_names).to eq ["yes"]
133
- expect(pact_publication.head_pact_tags.collect(&:name)).to eq ["yes"]
167
+ expect(pact_publication.head_tag_names).to eq []
168
+ end
169
+ end
170
+ end
171
+
172
+ describe "#head_pact_publications_for_tags" do
173
+ before do
174
+ td.create_pact_with_hierarchy("Foo", "1", "Bar")
175
+ .create_consumer_version_tag("main")
176
+ .create_consumer_version_tag("prod")
177
+ .create_pact_with_hierarchy("Foo", "2", "Bar")
178
+ .create_consumer_version_tag("main")
179
+ .create_pact_with_hierarchy("Foo2", "6", "Bar")
180
+ .create_consumer_version_tag("main")
181
+ end
182
+
183
+ let(:pact_publication) { td.find_pact_publication("Foo", "1", "Bar") }
184
+
185
+ context "lazy loading" do
186
+ it "sets the head_pact_publications_for_tags" do
187
+ expect(pact_publication.head_pact_publications_for_tags.first.consumer_version.number).to eq "2"
188
+ expect(pact_publication.head_pact_publications_for_tags.last.consumer_version.number).to eq "1"
189
+ end
190
+ end
191
+
192
+ context "eager loading" do
193
+ it "sets the head_pact_publications_for_tags" do
194
+ all = PactPublication.eager(:head_pact_publications_for_tags).order(:id).all
195
+ expect(all.first.associations[:head_pact_publications_for_tags].first.consumer_version.number).to eq "2"
196
+ expect(all.first.associations[:head_pact_publications_for_tags].last.consumer_version.number).to eq "1"
197
+ end
198
+ end
199
+ end
200
+
201
+ describe "created_after" do
202
+ before do
203
+ td.set_now(Date.new(2020, 1, 1))
204
+ .create_consumer("Foo")
205
+ .create_provider("Bar")
206
+ .create_consumer_version("1", branch: "main")
207
+ .create_pact
208
+ .set_now(Date.new(2020, 1, 3))
209
+ .create_consumer_version("2", branch: "feat/x")
210
+ .create_pact
211
+ end
212
+
213
+ subject { PactPublication.created_after(Date.new(2020, 1, 2)).all }
214
+
215
+ its(:size) { is_expected.to eq 1 }
216
+
217
+ it "returns the pact publications created after the specified date" do
218
+ expect(subject.first.consumer_version.number).to eq "2"
219
+ end
220
+ end
221
+
222
+ describe "latest_by_consumer_branch" do
223
+ before do
224
+ td.set_now(Date.new(2020, 1, 1))
225
+ .create_consumer("Foo")
226
+ .create_provider("Bar")
227
+ .create_consumer_version("1", branch: "main")
228
+ .create_pact
229
+ .set_now(Date.new(2020, 1, 2))
230
+ .create_consumer_version("2", branch: "feat/x")
231
+ .create_pact
232
+ .set_now(Date.new(2020, 1, 3))
233
+ .create_consumer_version("3", branch: "main", comment: "latest")
234
+ .create_pact
235
+ .set_now(Date.new(2020, 1, 4))
236
+ .create_consumer_version("4", branch: "feat/x", comment: "latest")
237
+ .create_pact
238
+ .set_now(Date.new(2020, 1, 5))
239
+ .create_consumer("FooZ")
240
+ .create_consumer_version("6", branch: "main", comment: "latest, different consumer")
241
+ .create_pact
242
+ .set_now(Date.new(2020, 1, 6))
243
+ .create_consumer_version("7", comment: "No branch")
244
+ .create_pact
245
+ .set_now(Date.new(2020, 1, 7))
246
+ .create_consumer_version("8", branch: "main", comment: "No pact")
247
+ end
248
+
249
+ subject { PactPublication.latest_by_consumer_branch.all }
250
+
251
+ let(:foo) { PactBroker::Domain::Pacticipant.where(name: "Foo").single_record }
252
+ let(:bar) { PactBroker::Domain::Pacticipant.where(name: "Bar").single_record }
253
+ let(:foo_z) { PactBroker::Domain::Pacticipant.where(name: "FooZ").single_record }
254
+
255
+ it "returns the latest pact publications for each consumer/branch" do
256
+ expect(subject.size).to eq 3
257
+ hashes = subject.collect(&:values)
258
+
259
+ expect(subject.find { |pp| pp.consumer_id == foo.id && pp[:branch] == "main" }.consumer_version.number).to eq "3"
260
+ expect(subject.find { |pp| pp.consumer_id == foo.id && pp[:branch] == "feat/x" }.consumer_version.number).to eq "4"
261
+ expect(subject.find { |pp| pp.consumer_id == foo_z.id && pp[:branch] == "main" }.consumer_version.number).to eq "6"
262
+ end
263
+
264
+ context "chained with created after" do
265
+ subject { PactPublication.created_after(DateTime.new(2020, 1, 3)).latest_by_consumer_branch.all }
266
+
267
+ its(:size) { is_expected.to eq 2 }
268
+
269
+ it "returns the right versions" do
270
+ expect(subject.find { |pp| pp.consumer_id == foo.id && pp[:branch] == "feat/x" }.consumer_version.number).to eq "4"
271
+ expect(subject.find { |pp| pp.consumer_id == foo_z.id && pp[:branch] == "main" }.consumer_version.number).to eq "6"
272
+ end
273
+ end
274
+ end
275
+
276
+ describe "latest_for_consumer_branch" do
277
+ before do
278
+ td.create_consumer("Foo")
279
+ .create_provider("Bar")
280
+ .create_consumer_version("1", branch: "main")
281
+ .create_pact
282
+ .create_consumer_version("2", branch: "main")
283
+ .create_pact
284
+ .create_consumer_version("3", branch: "feat-x")
285
+ .create_pact
286
+ .create_consumer("Foo2")
287
+ .create_provider("Bar2")
288
+ .create_consumer_version("10", branch: "main")
289
+ .create_pact
290
+ .create_consumer_version("11", branch: "main")
291
+ .create_pact
292
+ end
293
+
294
+ subject { PactPublication.latest_for_consumer_branch("main") }
295
+
296
+ it "returns the latest pacts for the branches with the specified name (for any consumer/provider)" do
297
+ all = subject.all.sort_by{ |pact_publication| pact_publication.consumer_version.order }
298
+ expect(all.size).to eq 2
299
+ expect(all.first.consumer.name).to eq "Foo"
300
+ expect(all.first.provider.name).to eq "Bar"
301
+ expect(all.first.consumer_version.number).to eq "2"
302
+
303
+ expect(all.last.consumer.name).to eq "Foo2"
304
+ expect(all.last.provider.name).to eq "Bar2"
305
+ expect(all.last.consumer_version.number).to eq "11"
306
+ end
307
+
308
+ context "when chained" do
309
+ it "works" do
310
+ all = PactPublication.for_provider(td.find_pacticipant("Bar")).latest_for_consumer_branch("main").all
311
+ expect(all.first.provider.name).to eq "Bar"
312
+ end
313
+ end
314
+ end
315
+
316
+ describe "latest_by_consumer_tag" do
317
+ before do
318
+ td.create_consumer("Foo")
319
+ .create_provider("Bar")
320
+ .create_consumer_version("1", tag_names: ["main"])
321
+ .create_pact
322
+ .create_consumer_version("2", tag_names: ["feat/x"])
323
+ .create_pact
324
+ .create_consumer_version("3", tag_names: ["main"], comment: "latest")
325
+ .create_pact
326
+ .create_consumer_version("4", tag_names: ["feat/x"], comment: "latest")
327
+ .create_pact
328
+ .create_consumer("FooZ")
329
+ .create_consumer_version("6", tag_names: ["main"], comment: "Different consumer")
330
+ .create_pact
331
+ .create_consumer_version("7", comment: "No branch")
332
+ .create_pact
333
+ .create_consumer_version("8", tag_names: ["main"], comment: "No pact")
334
+ end
335
+
336
+ subject { PactPublication.latest_by_consumer_tag.all }
337
+
338
+ let(:foo) { PactBroker::Domain::Pacticipant.where(name: "Foo").single_record }
339
+ let(:bar) { PactBroker::Domain::Pacticipant.where(name: "Bar").single_record }
340
+ let(:foo_z) { PactBroker::Domain::Pacticipant.where(name: "FooZ").single_record }
341
+
342
+ it "returns the latest pact publications for each consumer/branch" do
343
+ expect(subject.size).to eq 3
344
+ hashes = subject.collect(&:values)
345
+
346
+ expect(subject.find { |pp| pp.consumer_id == foo.id && pp[:tag_name] == "main" }.consumer_version.number).to eq "3"
347
+ expect(subject.find { |pp| pp.consumer_id == foo.id && pp[:tag_name] == "feat/x" }.consumer_version.number).to eq "4"
348
+ expect(subject.find { |pp| pp.consumer_id == foo_z.id && pp[:tag_name] == "main" }.consumer_version.number).to eq "6"
349
+ end
350
+ end
351
+
352
+ describe "overall_latest" do
353
+ before do
354
+ td.create_consumer("Foo")
355
+ .create_provider("Bar")
356
+ .create_consumer_version("1", tag_names: ["main"])
357
+ .create_pact
358
+ .create_consumer_version("2", tag_names: ["main"])
359
+ .create_pact
360
+ .create_consumer_version("3", tag_names: ["feat/x"])
361
+ .create_pact
362
+ .create_consumer("Foo2")
363
+ .create_provider("Bar2")
364
+ .create_consumer_version("10", tag_names: ["main"])
365
+ .create_pact
366
+ .create_consumer_version("11", tag_names: ["main"])
367
+ .create_pact
368
+ end
369
+
370
+ subject { PactPublication.overall_latest }
371
+
372
+ it "returns the latest by consumer/provider" do
373
+ all = subject.all.sort_by{ | pact_publication | pact_publication.consumer_version.order }
374
+ expect(all.size).to eq 2
375
+ end
376
+
377
+ context "when chained" do
378
+ it "works with a consumer" do
379
+ expect(PactPublication.for_consumer(td.find_pacticipant("Foo")).overall_latest.all.first.consumer.name).to eq "Foo"
380
+ end
381
+
382
+ it "works with a consumer and provider" do
383
+ td.create_pact_with_hierarchy("Foo", "666", "Nope")
384
+ all = PactPublication
385
+ .for_consumer(td.find_pacticipant("Foo"))
386
+ .for_provider(td.find_pacticipant("Bar"))
387
+ .overall_latest.all
388
+ expect(all.size).to eq 1
389
+ expect(all.first.consumer.name).to eq "Foo"
390
+ expect(all.first.provider.name).to eq "Bar"
391
+ end
392
+ end
393
+ end
394
+
395
+ describe "latest_for_consumer_tag" do
396
+ before do
397
+ td.create_consumer("Foo")
398
+ .create_provider("Bar")
399
+ .create_consumer_version("1", tag_names: ["main"])
400
+ .create_pact
401
+ .create_consumer_version("2", tag_names: ["main"])
402
+ .create_pact
403
+ .create_consumer_version("3", tag_names: ["feat/x"])
404
+ .create_pact
405
+ .create_consumer("Foo2")
406
+ .create_provider("Bar2")
407
+ .create_consumer_version("10", tag_names: ["main"])
408
+ .create_pact
409
+ .create_consumer_version("11", tag_names: ["main"])
410
+ .create_pact
411
+ end
412
+
413
+ subject { PactPublication.latest_for_consumer_tag("main") }
414
+
415
+ it "returns the latest pacts for the tags with the specified name (for any consumer/provider)" do
416
+ all = subject.all.sort_by{ |pact_publication| pact_publication.consumer_version.order }
417
+ expect(all.size).to eq 2
418
+ expect(all.first.consumer.name).to eq "Foo"
419
+ expect(all.first.provider.name).to eq "Bar"
420
+ expect(all.first.consumer_version.number).to eq "2"
421
+
422
+ expect(all.last.consumer.name).to eq "Foo2"
423
+ expect(all.last.provider.name).to eq "Bar2"
424
+ expect(all.last.consumer_version.number).to eq "11"
425
+ end
426
+
427
+ context "when chained" do
428
+ it "works" do
429
+ all = PactPublication.for_provider(td.find_pacticipant("Bar")).latest_for_consumer_tag("main").all
430
+ expect(all.first.provider.name).to eq "Bar"
431
+ end
432
+ end
433
+ end
434
+
435
+ describe "#successfully_verified_by_provider_branch" do
436
+ let(:bar) { td.find_pacticipant("Bar") }
437
+
438
+ subject { PactPublication.successfully_verified_by_provider_branch(bar.id, "main").all }
439
+
440
+ context "PactPublication" do
441
+ before do
442
+ td.create_pact_with_hierarchy("Foo", "1", "Bar")
443
+ .create_verification(provider_version: "2", branch: "main", success: false)
444
+ .create_pact_with_hierarchy("Foo", "2", "Bar")
445
+ .create_verification(provider_version: "2", branch: "main", success: true)
446
+ .create_pact_with_hierarchy("Foo", "3", "Bar")
447
+ .create_verification(provider_version: "3", branch: "not-main", success: true)
448
+ end
449
+
450
+ it "returns the pact publications that have been succesfully verified by the given provider id and branch" do
451
+ expect(subject.size).to eq 1
452
+ expect(subject.first.consumer_version.number).to eq "2"
453
+ end
454
+ end
455
+
456
+
457
+ context "with chained scopes" do
458
+ subject { PactPublication.latest_by_consumer_branch.successfully_verified_by_provider_branch(bar.id, "provider-main").all }
459
+
460
+ context "when there are no latest branch pacts that have been successfully verified by the specified provider branch" do
461
+ before do
462
+ td.create_consumer("Foo")
463
+ .create_provider("Bar")
464
+ .create_consumer_version("1", branch: "main", comment: "not latest")
465
+ .create_pact
466
+ .create_verification(provider_version: "1", success: true, branch: "provider-main", comment: "successful but not latest")
467
+ .create_consumer_version("2", branch: "main", comment: "latest")
468
+ .create_pact
469
+ .create_verification(provider_version: "2", success: false, branch: "provider-main", comment: "latest but not successful")
470
+ .create_consumer_version("3", branch: "feat/x", comment: "latest")
471
+ .create_pact
472
+ .create_verification(provider_version: "3", success: true, branch: "not-provider-main", comment: "latest, successful, but wrong branch")
473
+ end
474
+
475
+ it { is_expected.to eq [] }
476
+ end
477
+
478
+ context "when there are latest branch pacts that have been successfully verified by the specified provider branch" do
479
+ before do
480
+ td.create_consumer("Foo")
481
+ .create_provider("Bar")
482
+ .create_consumer_version("1", branch: "main", comment: "not latest")
483
+ .create_pact
484
+ .create_verification(provider_version: "1", success: true, branch: "provider-main")
485
+ .create_consumer_version("2", branch: "main", comment: "latest")
486
+ .create_pact
487
+ .create_verification(provider_version: "1", success: true, branch: "provider-main")
488
+ .create_verification(provider_version: "2", success: true, branch: "provider-main", number: "2")
489
+ end
490
+
491
+ its(:size) { is_expected.to eq 1 }
492
+
493
+ it "returns them" do
494
+ expect(subject.first.consumer_version.number).to eq "2"
495
+ end
496
+ end
497
+
498
+ context "when there are latest tagged pacts that have been successfully verified by the specified provider branch" do
499
+ before do
500
+ td.create_consumer("Foo")
501
+ .create_provider("Bar")
502
+ .create_consumer_version("1", tag_names: ["main"], comment: "not latest")
503
+ .create_pact
504
+ .create_verification(provider_version: "1", success: true, tag_names: ["provider-main"])
505
+ .create_consumer_version("2", tag_names: ["main"], comment: "latest")
506
+ .create_pact
507
+ .create_verification(provider_version: "1", success: true, branch: "provider-main")
508
+ .create_verification(provider_version: "2", success: true, branch: "provider-main", number: "2")
509
+ end
510
+
511
+ subject { PactPublication.latest_by_consumer_tag.successfully_verified_by_provider_branch(bar.id, "provider-main").all }
512
+
513
+ its(:size) { is_expected.to eq 1 }
514
+
515
+ it "returns them" do
516
+ expect(subject.first.consumer_version.number).to eq "2"
517
+ end
518
+ end
519
+
520
+ context "subtracting Pact Publications" do
521
+ before do
522
+ td.create_consumer("Foo")
523
+ .create_provider("Bar")
524
+ .create_consumer_version("1", branch: "main", tag_names: ["main"], comment: "not latest")
525
+ .create_pact
526
+ .create_verification(provider_version: "1", success: true, branch: "provider-main")
527
+ .create_consumer_version("2", branch: "main", tag_names: ["main"], comment: "latest")
528
+ .create_pact
529
+ .create_verification(provider_version: "1", success: true, branch: "provider-main")
530
+ .create_verification(provider_version: "2", success: true, branch: "provider-main", number: "2")
531
+ .create_consumer_version("3", branch: "feat/x", tag_names: ["feat/x"], )
532
+ .create_pact
533
+ end
534
+
535
+ let(:bar) { td.find_pacticipant("Bar") }
536
+
537
+ it "with branches" do
538
+ potential = PactPublication.for_provider(bar).latest_by_consumer_branch
539
+ already_verified = potential.successfully_verified_by_provider_branch(bar.id, "provider-main")
540
+ not_verified = potential.all - already_verified.all
541
+
542
+ expect(not_verified.size).to eq 1
543
+ expect(not_verified.first.consumer_version_number).to eq "3"
544
+ end
545
+
546
+ it "with tags" do
547
+ potential = PactPublication.for_provider(bar).latest_by_consumer_tag
548
+ already_verified = potential.successfully_verified_by_provider_branch(bar.id, "provider-main")
549
+ not_verified = potential.all - already_verified.all
550
+
551
+ expect(not_verified.size).to eq 1
552
+ expect(not_verified.first.consumer_version_number).to eq "3"
553
+ end
134
554
  end
135
555
  end
136
556
  end