pact_broker 2.3.0 → 2.4.0

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 (47) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +8 -0
  3. data/README.md +3 -4
  4. data/db/migrations/37_create_labels_table.rb +11 -0
  5. data/lib/pact_broker/api.rb +4 -0
  6. data/lib/pact_broker/api/decorators/embedded_label_decorator.rb +20 -0
  7. data/lib/pact_broker/api/decorators/label_decorator.rb +32 -0
  8. data/lib/pact_broker/api/decorators/pact_collection_decorator.rb +1 -5
  9. data/lib/pact_broker/api/decorators/pact_versions_decorator.rb +0 -5
  10. data/lib/pact_broker/api/decorators/pacticipant_collection_decorator.rb +31 -2
  11. data/lib/pact_broker/api/decorators/pacticipant_decorator.rb +37 -8
  12. data/lib/pact_broker/api/pact_broker_urls.rb +12 -4
  13. data/lib/pact_broker/api/resources/label.rb +52 -0
  14. data/lib/pact_broker/api/resources/pacticipants.rb +1 -1
  15. data/lib/pact_broker/api/resources/pacticipants_for_label.rb +27 -0
  16. data/lib/pact_broker/api/resources/verifications.rb +1 -1
  17. data/lib/pact_broker/badges/service.rb +13 -3
  18. data/lib/pact_broker/configuration.rb +1 -1
  19. data/lib/pact_broker/domain.rb +1 -0
  20. data/lib/pact_broker/domain/label.rb +19 -0
  21. data/lib/pact_broker/domain/pacticipant.rb +12 -1
  22. data/lib/pact_broker/labels/repository.rb +32 -0
  23. data/lib/pact_broker/labels/service.rb +26 -0
  24. data/lib/pact_broker/pacticipants/repository.rb +8 -7
  25. data/lib/pact_broker/pacticipants/service.rb +4 -0
  26. data/lib/pact_broker/repositories.rb +5 -0
  27. data/lib/pact_broker/services.rb +5 -0
  28. data/lib/pact_broker/version.rb +1 -1
  29. data/spec/features/delete_label_spec.rb +28 -0
  30. data/spec/features/get_label_spec.rb +28 -0
  31. data/spec/features/get_pacticipants_by_label_spec.rb +27 -0
  32. data/spec/features/label_pacticipant_spec.rb +22 -0
  33. data/spec/lib/pact_broker/api/decorators/embedded_label_decorator_spec.rb +34 -0
  34. data/spec/lib/pact_broker/api/decorators/label_decorator_spec.rb +42 -0
  35. data/spec/lib/pact_broker/api/decorators/pacticipant_collection_decorator_spec.rb +34 -8
  36. data/spec/lib/pact_broker/api/decorators/pacticipant_decorator_spec.rb +41 -2
  37. data/spec/lib/pact_broker/api/decorators/tag_decorator_spec.rb +1 -1
  38. data/spec/lib/pact_broker/api/resources/verifications_spec.rb +2 -2
  39. data/spec/lib/pact_broker/badges/service_spec.rb +1 -1
  40. data/spec/lib/pact_broker/labels/repository_spec.rb +124 -0
  41. data/spec/lib/pact_broker/labels/service_spec.rb +28 -0
  42. data/spec/lib/pact_broker/pacticipants/repository_spec.rb +19 -0
  43. data/spec/support/test_data_builder.rb +6 -0
  44. data/tasks/database.rb +1 -1
  45. data/vendor/hal-browser/browser.html +1 -1
  46. data/vendor/hal-browser/js/hal/resource.js +1 -0
  47. metadata +26 -2
@@ -11,7 +11,7 @@ module PactBroker
11
11
 
12
12
  class Configuration
13
13
 
14
- SAVABLE_SETTING_NAMES = [:order_versions_by_date, :use_case_sensitive_resource_names]
14
+ SAVABLE_SETTING_NAMES = [:order_versions_by_date, :use_case_sensitive_resource_names, :enable_badge_resources, :shields_io_base_url]
15
15
 
16
16
  attr_accessor :log_dir, :database_connection, :auto_migrate_db, :use_hal_browser, :html_pact_renderer
17
17
  attr_accessor :validate_database_connection_config, :enable_diagnostic_endpoints, :version_parser
@@ -1,5 +1,6 @@
1
1
  require 'pact_broker/domain/pact'
2
2
  require 'pact_broker/domain/pacticipant'
3
3
  require 'pact_broker/domain/tag'
4
+ require 'pact_broker/domain/label'
4
5
  require 'pact_broker/domain/version'
5
6
  require 'pact_broker/domain/webhook'
@@ -0,0 +1,19 @@
1
+ require 'pact_broker/db'
2
+
3
+ module PactBroker
4
+ module Domain
5
+ class Label < Sequel::Model
6
+
7
+ unrestrict_primary_key
8
+
9
+ associate(:many_to_one, :pacticipant, :class => "PactBroker::Domain::Pacticipant", :key => :pacticipant_id, :primary_key => :id)
10
+
11
+ def <=> other
12
+ name <=> other.name
13
+ end
14
+
15
+ end
16
+
17
+ Label.plugin :timestamps, update_on_create: true
18
+ end
19
+ end
@@ -1,5 +1,6 @@
1
1
  require 'pact_broker/db'
2
2
  require 'pact_broker/messages'
3
+ require 'pact_broker/repositories/helpers'
3
4
 
4
5
  module PactBroker
5
6
 
@@ -12,8 +13,18 @@ module PactBroker
12
13
  set_primary_key :id
13
14
 
14
15
  one_to_many :versions, :order => :order, :reciprocal => :pacticipant
16
+ one_to_many :labels, :order => :name, :reciprocal => :pacticipant
15
17
  one_to_many :pacts
16
18
 
19
+ dataset_module do
20
+ include PactBroker::Repositories::Helpers
21
+
22
+ def label label_name
23
+ filter = name_like(Sequel[:labels][:name], label_name)
24
+ join(:labels, {pacticipant_id: :id}).where(filter)
25
+ end
26
+ end
27
+
17
28
  def latest_version
18
29
  versions.last
19
30
  end
@@ -29,6 +40,6 @@ module PactBroker
29
40
  end
30
41
  end
31
42
 
32
- Pacticipant.plugin :timestamps, :update_on_create=>true
43
+ Pacticipant.plugin :timestamps, update_on_create: true
33
44
  end
34
45
  end
@@ -0,0 +1,32 @@
1
+ require 'pact_broker/domain/label'
2
+ require 'pact_broker/repositories/helpers'
3
+
4
+ module PactBroker
5
+ module Labels
6
+ class Repository
7
+
8
+ include PactBroker::Repositories::Helpers
9
+
10
+ def create args
11
+ Domain::Label.new(name: args.fetch(:name), pacticipant: args.fetch(:pacticipant)).save
12
+ end
13
+
14
+ def find args
15
+ PactBroker::Domain::Label
16
+ .select(Sequel.qualify("labels", "name"), Sequel.qualify("labels", "pacticipant_id"), Sequel.qualify("labels", "created_at"), Sequel.qualify("labels", "updated_at"))
17
+ .join(:pacticipants, {id: :pacticipant_id})
18
+ .where(name_like(Sequel.qualify("labels", "name"), args.fetch(:label_name)))
19
+ .where(name_like(Sequel.qualify("pacticipants", "name"), args.fetch(:pacticipant_name)))
20
+ .single_record
21
+ end
22
+
23
+ def delete args
24
+ find(args).delete
25
+ end
26
+
27
+ def delete_by_pacticipant_id pacticipant_id
28
+ Sequel::Model.db[:labels].where(pacticipant_id: pacticipant_id).delete
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,26 @@
1
+ require 'pact_broker/repositories'
2
+
3
+ module PactBroker
4
+
5
+ module Labels
6
+ module Service
7
+
8
+ extend self
9
+
10
+ extend PactBroker::Repositories
11
+
12
+ def create args
13
+ pacticipant = pacticipant_repository.find_by_name_or_create args.fetch(:pacticipant_name)
14
+ label_repository.create pacticipant: pacticipant, name: args.fetch(:label_name)
15
+ end
16
+
17
+ def find args
18
+ label_repository.find args
19
+ end
20
+
21
+ def delete args
22
+ label_repository.delete args
23
+ end
24
+ end
25
+ end
26
+ end
@@ -17,12 +17,17 @@ module PactBroker
17
17
  end
18
18
 
19
19
  def find_all
20
- PactBroker::Domain::Pacticipant.order(:name).all
20
+ find
21
+ end
22
+
23
+ def find options = {}
24
+ query = PactBroker::Domain::Pacticipant.select_all_qualified
25
+ query = query.label(options[:label_name]) if options[:label_name]
26
+ query.order_ignore_case(Sequel[:pacticipants][:name]).all
21
27
  end
22
28
 
23
29
  def find_all_pacticipant_versions_in_reverse_order name
24
- PactBroker::Domain::Version
25
- .select(Sequel[:versions][:id], Sequel[:versions][:number], Sequel[:versions][:pacticipant_id], Sequel[:versions][:order], Sequel[:versions][:created_at], Sequel[:versions][:updated_at])
30
+ PactBroker::Domain::Version.select_all_qualified
26
31
  .join(:pacticipants, {id: :pacticipant_id})
27
32
  .where(name_like(:name, name))
28
33
  .reverse_order(:order)
@@ -43,10 +48,6 @@ module PactBroker
43
48
  def pacticipant_names
44
49
  PactBroker::Domain::Pacticipant.select(:name).order(:name).collect{ | pacticipant| pacticipant.name }
45
50
  end
46
-
47
- def find_latest_version name
48
-
49
- end
50
51
  end
51
52
  end
52
53
  end
@@ -41,6 +41,10 @@ module PactBroker
41
41
  pacticipant_repository.find_by_name(name)
42
42
  end
43
43
 
44
+ def self.find options
45
+ pacticipant_repository.find options
46
+ end
47
+
44
48
  def self.find_all_pacticipant_versions_in_reverse_order name
45
49
  pacticipant_repository.find_all_pacticipant_versions_in_reverse_order(name)
46
50
  end
@@ -22,6 +22,11 @@ module PactBroker
22
22
  Tags::Repository.new
23
23
  end
24
24
 
25
+ def label_repository
26
+ require 'pact_broker/labels/repository'
27
+ Labels::Repository.new
28
+ end
29
+
25
30
  def webhook_repository
26
31
  require 'pact_broker/webhooks/repository'
27
32
  Webhooks::Repository.new
@@ -17,6 +17,11 @@ module PactBroker
17
17
  Tags::Service
18
18
  end
19
19
 
20
+ def label_service
21
+ require 'pact_broker/labels/service'
22
+ Labels::Service
23
+ end
24
+
20
25
  def group_service
21
26
  require 'pact_broker/groups/service'
22
27
  Groups::Service
@@ -1,3 +1,3 @@
1
1
  module PactBroker
2
- VERSION = '2.3.0'
2
+ VERSION = '2.4.0'
3
3
  end
@@ -0,0 +1,28 @@
1
+ describe "Deleting a label" do
2
+
3
+ before do
4
+ TestDataBuilder.new
5
+ .create_pacticipant("foo")
6
+ .create_label("ios")
7
+ .create_label("consumer")
8
+ .create_pacticipant("bar")
9
+ .create_label("ios")
10
+ .create_label("consumer")
11
+ end
12
+
13
+ let(:path) { "/pacticipants/foo/labels/ios" }
14
+ let(:response_body_hash) { JSON.parse(subject.body, symbolize_names: true) }
15
+ let(:expected_response_body) { {name: 'ios'} }
16
+
17
+ subject { delete path; last_response }
18
+
19
+ context "when the label exists" do
20
+ it "returns a 204 No Content" do
21
+ expect(subject.status).to be 204
22
+ end
23
+
24
+ it "deletes the label" do
25
+ expect { subject }.to change { PactBroker::Domain::Label.count }.by(-1)
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,28 @@
1
+ describe "Get a label" do
2
+
3
+ before do
4
+ TestDataBuilder.new
5
+ .create_pacticipant("foo")
6
+ .create_label("ios")
7
+ .create_label("consumer")
8
+ .create_pacticipant("bar")
9
+ .create_label("ios")
10
+ .create_label("consumer")
11
+ end
12
+
13
+ let(:path) { "/pacticipants/foo/labels/ios" }
14
+ let(:response_body_hash) { JSON.parse(subject.body, symbolize_names: true) }
15
+ let(:expected_response_body) { {name: 'ios'} }
16
+
17
+ subject { get path; last_response }
18
+
19
+ context "when the label exists" do
20
+ it "returns a 200 OK" do
21
+ expect(subject).to be_a_hal_json_success_response
22
+ end
23
+
24
+ it "returns the label in the body" do
25
+ expect(response_body_hash).to include expected_response_body
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,27 @@
1
+ describe "Get pacticipants by label" do
2
+
3
+ let(:path) { "/pacticipants/label/ios" }
4
+ let(:response_body_hash) { JSON.parse(subject.body, symbolize_names: true) }
5
+ let(:expected_response_body) { {name: "Foo"} }
6
+
7
+ subject { get path; last_response }
8
+
9
+ context "when the pacts exist" do
10
+
11
+ before do
12
+ TestDataBuilder.new
13
+ .create_pacticipant("Foo")
14
+ .create_label("ios")
15
+ .create_pacticipant("Bar")
16
+ .create_label("android")
17
+ end
18
+
19
+ it "returns a 200 OK" do
20
+ expect(subject).to be_a_hal_json_success_response
21
+ end
22
+
23
+ it "returns a list of pacticipants" do
24
+ expect(response_body_hash[:_embedded][:pacticipants].first).to include expected_response_body
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,22 @@
1
+ describe "Labelling a pacticipant" do
2
+
3
+ let(:path) { "/pacticipants/foo/labels/ios" }
4
+ let(:response_body_hash) { JSON.parse(subject.body, symbolize_names: true) }
5
+ let(:expected_response_body) { {name: 'ios'} }
6
+
7
+ subject { put path, nil, {'CONTENT_TYPE' => 'application/json'}; last_response }
8
+
9
+ context "when the pacticipant exists" do
10
+ it "returns a 201 Created" do
11
+ expect(subject.status).to be 201
12
+ end
13
+
14
+ it "returns a json body" do
15
+ expect(subject.headers['Content-Type']).to eq "application/hal+json;charset=utf-8"
16
+ end
17
+
18
+ it "returns the label in the body" do
19
+ expect(response_body_hash).to include expected_response_body
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,34 @@
1
+ require 'pact_broker/api/decorators/embedded_label_decorator'
2
+
3
+ module PactBroker
4
+ module Api
5
+ module Decorators
6
+
7
+ describe LabelDecorator do
8
+
9
+ let(:label) do
10
+ TestDataBuilder.new
11
+ .create_consumer("Consumer")
12
+ .create_label("ios")
13
+ .and_return(:label)
14
+ end
15
+
16
+ let(:options) { { user_options: { base_url: 'http://example.org' } } }
17
+
18
+ subject { JSON.parse EmbeddedLabelDecorator.new(label).to_json(options), symbolize_names: true }
19
+
20
+ it "includes the label name" do
21
+ expect(subject[:name]).to eq "ios"
22
+ end
23
+
24
+ it "includes a link to itself" do
25
+ expect(subject[:_links][:self][:href]).to eq "http://example.org/pacticipants/Consumer/labels/ios"
26
+ end
27
+
28
+ it "includes the label name" do
29
+ expect(subject[:_links][:self][:name]).to eq "ios"
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,42 @@
1
+ require 'pact_broker/api/decorators/label_decorator'
2
+
3
+ module PactBroker
4
+ module Api
5
+ module Decorators
6
+
7
+ describe LabelDecorator do
8
+
9
+ let(:label) do
10
+ TestDataBuilder.new
11
+ .create_consumer("Consumer")
12
+ .create_label("ios")
13
+ .and_return(:label)
14
+ end
15
+
16
+ let(:options) { { user_options: { base_url: 'http://example.org' } } }
17
+
18
+ subject { JSON.parse LabelDecorator.new(label).to_json(options), symbolize_names: true }
19
+
20
+ it "includes the label name" do
21
+ expect(subject[:name]).to eq "ios"
22
+ end
23
+
24
+ it "includes a link to itself" do
25
+ expect(subject[:_links][:self][:href]).to eq "http://example.org/pacticipants/Consumer/labels/ios"
26
+ end
27
+
28
+ it "includes the label name" do
29
+ expect(subject[:_links][:self][:name]).to eq "ios"
30
+ end
31
+
32
+ it "includes a link to the pacticipant" do
33
+ expect(subject[:_links][:pacticipant][:href]).to eq "http://example.org/pacticipants/Consumer"
34
+ end
35
+
36
+ it "includes the pacticipant name" do
37
+ expect(subject[:_links][:pacticipant][:name]).to eq "Consumer"
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
@@ -3,18 +3,20 @@ require 'pact_broker/api/decorators/pacticipant_collection_decorator'
3
3
  require 'pact_broker/domain/pacticipant'
4
4
 
5
5
  module PactBroker
6
-
7
6
  module Api
8
-
9
7
  module Decorators
10
-
11
8
  describe PacticipantCollectionDecorator do
9
+ let(:options) { {user_options: {base_url: 'http://example.org'} } }
10
+ let(:pacticipants) { [] }
11
+ let(:json) { PacticipantCollectionDecorator.new(pacticipants).to_json(options) }
12
12
 
13
- subject { JSON.parse PacticipantCollectionDecorator.new(pacticipants).to_json, symbolize_names: true }
13
+ subject { JSON.parse json, symbolize_names: true }
14
14
 
15
- context "with no pacticipants" do
16
- let(:pacticipants) { [] }
15
+ it "includes a link to find pacticipants by label" do
16
+ expect(subject[:_links][:'pb:pacticipants-with-label'][:href]).to match %r{http://.*label/{label}}
17
+ end
17
18
 
19
+ context "with no pacticipants" do
18
20
  it "doesn't blow up" do
19
21
  subject
20
22
  end
@@ -25,11 +27,35 @@ module PactBroker
25
27
  let(:pacticipants) { [pacticipant] }
26
28
 
27
29
  it "displays a list of pacticipants" do
28
- expect(subject[:pacticipants]).to be_instance_of(Array)
29
- expect(subject[:pacticipants].size).to eq 1
30
+ expect(subject[:_embedded][:pacticipants]).to be_instance_of(Array)
31
+ expect(subject[:_embedded][:pacticipants].size).to eq 1
30
32
  end
31
33
  end
34
+ end
35
+
36
+ describe DeprecatedPacticipantCollectionDecorator do
37
+ let(:options) { {user_options: {base_url: 'http://example.org'} } }
38
+ let(:pacticipant) { PactBroker::Domain::Pacticipant.new(name: 'Name', created_at: DateTime.new, updated_at: DateTime.new)}
39
+ let(:pacticipants) { [pacticipant] }
40
+ let(:json) { DeprecatedPacticipantCollectionDecorator.new(pacticipants).to_json(options) }
41
+
42
+ subject { JSON.parse json, symbolize_names: true }
43
+
44
+ it "includes the pacticipants under the _embedded key" do
45
+ expect(subject[:_embedded][:pacticipants]).to be_instance_of(Array)
46
+ end
47
+
48
+ it "includes the pacticipants under the pacticipants key" do
49
+ expect(subject[:pacticipants]).to be_instance_of(Array)
50
+ end
51
+
52
+ it "includes a deprecation warning in the pacticipants links" do
53
+ expect(subject[:_links][:pacticipants].first[:name]).to include "DEPRECATED"
54
+ end
32
55
 
56
+ it "includes a deprecation warning in the non-embedded pacticipant title" do
57
+ expect(subject[:pacticipants].first[:title]).to include "DEPRECATED"
58
+ end
33
59
  end
34
60
  end
35
61
  end