pact_broker 2.3.0 → 2.4.0

Sign up to get free protection for your applications and to get access to all the features.
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