-
-
Notifications
You must be signed in to change notification settings - Fork 178
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: aggregated provider state endpoint
# Provider States - Aggregated view by provider Allowed methods: `GET` Path: `/pacts/provider/{provider}/provider-states` This resource returns a aggregated de-duplicated list of all provider states for a given provider. Provider states are collected from the latest pact on the main branch for any dependant consumers. Example response ```json { "providerStates": [ { "name": "an error occurs retrieving an alligator" }, { "name": "there is an alligator named Mary" }, { "name": "there is not an alligator named Mary" } ] } ```
- Loading branch information
Showing
12 changed files
with
335 additions
and
5 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
19 changes: 19 additions & 0 deletions
19
lib/pact_broker/api/decorators/provider_states_decorator.rb
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
require "pact_broker/api/decorators/base_decorator" | ||
|
||
module PactBroker | ||
module Api | ||
module Decorators | ||
class ProviderStateDecorator < BaseDecorator | ||
camelize_property_names | ||
|
||
property :name | ||
property :params | ||
|
||
end | ||
|
||
class ProviderStatesDecorator < BaseDecorator | ||
collection :providerStates, getter: -> (context) { context[:represented].sort_by(&:name) }, :extend => PactBroker::Api::Decorators::ProviderStateDecorator | ||
end | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
require "pact_broker/api/resources/base_resource" | ||
require "pact_broker/api/decorators/provider_states_decorator" | ||
|
||
module PactBroker | ||
module Api | ||
module Resources | ||
class ProviderStates < BaseResource | ||
def content_types_provided | ||
[["application/hal+json", :to_json]] | ||
end | ||
|
||
def allowed_methods | ||
["GET", "OPTIONS"] | ||
end | ||
|
||
def resource_exists? | ||
!!provider | ||
end | ||
|
||
def to_json | ||
decorator_class(:provider_states_decorator).new(provider_states).to_json(decorator_options) | ||
end | ||
|
||
def policy_name | ||
:'pacts::pacts' | ||
end | ||
|
||
private | ||
|
||
# attr_reader :provider_states | ||
|
||
def provider_states | ||
@provider_states ||= provider_state_service.list_provider_states(provider) | ||
end | ||
end | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
# Provider States - Aggregated view by provider | ||
|
||
Allowed methods: `GET` | ||
|
||
Path: `/pacts/provider/{provider}/provider-states` | ||
|
||
This resource returns a aggregated de-duplicated list of all provider states for a given provider. | ||
|
||
Provider states are collected from the latest pact on the main branch for any dependant consumers. | ||
|
||
Example response | ||
|
||
```json | ||
{ | ||
"providerStates": [ | ||
{ | ||
"name": "an error occurs retrieving an alligator" | ||
}, | ||
{ | ||
"name": "there is an alligator named Mary" | ||
}, | ||
{ | ||
"name": "there is not an alligator named Mary" | ||
} | ||
] | ||
} | ||
``` | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
require "pact_broker/services" | ||
require "pact_broker/pacts/selectors" | ||
require "pact_broker/pacts/pact_publication" | ||
require "pact_broker/repositories" | ||
|
||
|
||
module PactBroker | ||
module Pacts | ||
class ProviderStateService | ||
# extend self | ||
extend PactBroker::Services | ||
extend PactBroker::Repositories::Scopes | ||
|
||
def self.list_provider_states(provider) | ||
query = scope_for(PactPublication).eager_for_domain_with_content.for_provider_and_consumer_version_selector(provider, PactBroker::Pacts::Selector.latest_for_main_branch) | ||
query.all.flat_map do | pact_publication | | ||
pact_publication.to_domain.content_object.provider_states | ||
end | ||
end | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
RSpec.describe "listing the provider states" do | ||
before do | ||
td.create_consumer("Foo", main_branch: "main") | ||
.publish_pact(consumer_name: "Foo", provider_name: "Bar", consumer_version_number: "1", branch: "main", json_content: pact_content_1.to_json) | ||
.publish_pact(consumer_name: "Foo", provider_name: "Bar", consumer_version_number: "2", branch: "not-main") | ||
.create_consumer("Waffle", main_branch: "main") | ||
.publish_pact(consumer_name: "Waffle", provider_name: "Bar", consumer_version_number: "1", branch: "main", json_content: pact_content_2.to_json) | ||
end | ||
|
||
let(:rack_headers) { { "HTTP_ACCEPT" => "application/hal+json" } } | ||
|
||
let(:pact_content_1) do | ||
{ | ||
interactions: [ | ||
{ | ||
providerState: "state 2" | ||
}, | ||
{ | ||
providerState: "state 1" | ||
} | ||
] | ||
} | ||
end | ||
|
||
let(:pact_content_2) do | ||
{ | ||
interactions: [ | ||
{ | ||
providerStates: [ { name: "state 3" }, { name: "state 4" } ] | ||
}, | ||
{ | ||
providerStates: [ { name: "state 5" } ] | ||
} | ||
] | ||
} | ||
end | ||
|
||
let(:path) { "/pacts/provider/Bar/provider-states" } | ||
|
||
subject { get(path, nil, rack_headers).tap { |it| puts it.body } } | ||
|
||
it { is_expected.to be_a_hal_json_success_response } | ||
|
||
end |
98 changes: 98 additions & 0 deletions
98
spec/lib/pact_broker/api/resources/provider_states_spec.rb
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,98 @@ | ||
require "pact_broker/api/resources/provider_states" | ||
require "pact_broker/application_context" | ||
require "pact_broker/pacts/provider_state_service" | ||
|
||
module PactBroker | ||
module Api | ||
module Resources | ||
describe ProviderStates do | ||
before do | ||
allow(PactBroker::Pacticipants::Service).to receive(:find_pacticipant_by_name).and_return(provider) | ||
allow(PactBroker::Pacts::ProviderStateService).to receive(:list_provider_states).and_return(provider_states) | ||
end | ||
|
||
let(:provider) { double("Example API") } | ||
let(:path) { "/pacts/provider/Example%20API/provider-states" } | ||
let(:json) { | ||
{ "providerStates": | ||
[ | ||
{"name":"an error occurs retrieving an alligator"}, | ||
{"name":"there is an alligator named Mary"}, | ||
{"name":"there is not an alligator named Mary"} | ||
]}.to_json | ||
} | ||
|
||
let(:provider_states) do | ||
[ | ||
PactBroker::Pacts::ProviderState.new(name: "there is an alligator named Mary", params: nil), | ||
PactBroker::Pacts::ProviderState.new(name: "there is not an alligator named Mary", params: nil), | ||
PactBroker::Pacts::ProviderState.new(name: "an error occurs retrieving an alligator", params: nil) | ||
] | ||
end | ||
|
||
describe "GET - provider states where they exist" do | ||
subject { get path; last_response } | ||
|
||
it "attempts to find the ProviderStates" do | ||
expect(PactBroker::Pacts::ProviderStateService).to receive(:list_provider_states) | ||
subject | ||
end | ||
|
||
it "returns a 200 response status" do | ||
expect(subject.status).to eq 200 | ||
end | ||
|
||
it "returns the correct JSON body" do | ||
expect(subject.body).to eq json | ||
end | ||
|
||
it "returns the correct content type" do | ||
expect(subject.headers["Content-Type"]).to include("application/hal+json") | ||
end | ||
end | ||
describe "GET - provider states where do not exist" do | ||
let(:provider_states) do | ||
[] | ||
end | ||
let(:json) { | ||
{ "providerStates": | ||
[]}.to_json | ||
} | ||
|
||
subject { get path; last_response } | ||
|
||
it "returns a 200 response status" do | ||
expect(subject.status).to eq 200 | ||
end | ||
|
||
it "returns the correct JSON body" do | ||
expect(subject.body).to eq json | ||
end | ||
|
||
it "returns the correct content type" do | ||
expect(subject.headers["Content-Type"]).to include("application/hal+json") | ||
end | ||
end | ||
describe "GET - where provider does not exist" do | ||
|
||
let(:provider) { nil } | ||
let(:json) { {"error":"No provider with name 'Example API' found"}.to_json } | ||
|
||
subject { get path; last_response } | ||
|
||
it "returns a 404 response status" do | ||
expect(subject.status).to eq 404 | ||
end | ||
|
||
it "returns the correct JSON error body" do | ||
expect(subject.body).to eq json | ||
end | ||
|
||
it "returns the correct content type" do | ||
expect(subject.headers["Content-Type"]).to include("application/hal+json") | ||
end | ||
end | ||
end | ||
end | ||
end | ||
end |
Oops, something went wrong.