diff --git a/Makefile b/Makefile index 8c218899b..586d5f675 100755 --- a/Makefile +++ b/Makefile @@ -7,7 +7,7 @@ TEST?=./... ci:: docker deps clean bin test pact goveralls docker: - echo "--- 🛠 Starting docker" + @echo "--- 🛠 Starting docker" docker-compose up -d bin: @@ -15,14 +15,14 @@ bin: gox -os="windows" -arch="386" -output="build/pact-go_{{.OS}}_{{.Arch}}" gox -os="linux" -arch="386" -output="build/pact-go_{{.OS}}_{{.Arch}}" gox -os="linux" -arch="amd64" -output="build/pact-go_{{.OS}}_{{.Arch}}" - echo "==> Results:" + @echo "==> Results:" ls -hl build/ clean: rm -rf build output dist deps: - echo "--- 🐿 Fetching build dependencies " + @echo "--- 🐿 Fetching build dependencies " go get github.com/axw/gocov/gocov go get github.com/mattn/goveralls go get golang.org/x/tools/cmd/cover @@ -39,18 +39,18 @@ install: fi pact: install docker - echo "--- 🔨 Running Pact examples " - go test -tags=consumer -count=1 -v github.com/pact-foundation/pact-go/examples/./... -run TestExample - go test -tags=provider -count=1 -v github.com/pact-foundation/pact-go/examples/./... -run TestExample + @echo "--- 🔨 Running Pact examples " + go test -tags=consumer -count=1 github.com/pact-foundation/pact-go/examples/... -run TestExample + go test -tags=provider -count=1 github.com/pact-foundation/pact-go/examples/... -run TestExample release: echo "--- 🚀 Releasing it" "$(CURDIR)/scripts/release.sh" test: deps - echo "--- ✅ Running tests" + @echo "--- ✅ Running tests" @if [ -f coverage.txt ]; then rm coverage.txt; fi; - echo "mode: count" > coverage.txt + @echo "mode: count" > coverage.txt @for d in $$(go list ./... | grep -v vendor | grep -v examples); \ do \ go test -race -coverprofile=profile.out -covermode=atomic $$d; \ diff --git a/types/consumer_version_selector.go b/types/consumer_version_selector.go new file mode 100644 index 000000000..f10e56908 --- /dev/null +++ b/types/consumer_version_selector.go @@ -0,0 +1,21 @@ +package types + +import "fmt" + +// ConsumerVersionSelector are the way we specify which pacticipants and +// versions we want to use when configuring verifications +// See https://docs.pact.io/selectors for more +type ConsumerVersionSelector struct { + Pacticipant string `json:"pacticipant"` + Version string `json:"version"` + Latest bool `json:"latest"` + All bool `json:"all"` +} + +func (c *ConsumerVersionSelector) Validate() error { + if c.Pacticipant == "" { + return fmt.Errorf("must provide a Pacticpant") + } + + return nil +} diff --git a/types/consumer_version_selector_test.go b/types/consumer_version_selector_test.go new file mode 100644 index 000000000..954f0a513 --- /dev/null +++ b/types/consumer_version_selector_test.go @@ -0,0 +1,28 @@ +package types + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestConsumerVersionSelectorValidate(t *testing.T) { + tests := []struct { + name string + selector ConsumerVersionSelector + err bool + }{ + {name: "no pacticipant", selector: ConsumerVersionSelector{}, err: true}, + {name: "pacticipant only", selector: ConsumerVersionSelector{Pacticipant: "foo"}, err: false}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + err := tt.selector.Validate() + if tt.err { + assert.Error(t, err) + } else { + assert.NoError(t, err) + } + }) + } +} diff --git a/types/publish_request_test.go b/types/publish_request_test.go index eacb8f07b..6d5f84145 100644 --- a/types/publish_request_test.go +++ b/types/publish_request_test.go @@ -9,7 +9,7 @@ import ( func TestPublishRequest_Validate(t *testing.T) { dir, _ := os.Getwd() - testFile := fmt.Sprintf(filepath.Join(dir, "publish_test.go")) + testFile := fmt.Sprint(filepath.Join(dir, "publish_test.go")) p := PublishRequest{} err := p.Validate() diff --git a/types/verify_request.go b/types/verify_request.go index ff80fcb39..63dc64ba1 100644 --- a/types/verify_request.go +++ b/types/verify_request.go @@ -2,6 +2,7 @@ package types import ( "crypto/tls" + "encoding/json" "errors" "fmt" "log" @@ -23,7 +24,10 @@ type VerifyRequest struct { // Pact Broker URL for broker-based verification BrokerURL string - // ConsumerVersionSelectors []ConsumerVersionSelector + // Selectors are the way we specify which pacticipants and + // versions we want to use when configuring verifications + // See https://docs.pact.io/selectors for more + ConsumerVersionSelectors []ConsumerVersionSelector // Retrieve the latest pacts with this consumer version tag Tags []string @@ -111,6 +115,7 @@ type VerifyRequest struct { // and should not be used outside of this library. func (v *VerifyRequest) Validate() error { v.Args = []string{} + var err error if len(v.PactURLs) != 0 { v.Args = append(v.Args, v.PactURLs...) @@ -120,6 +125,20 @@ func (v *VerifyRequest) Validate() error { return fmt.Errorf("One of 'PactURLs' or 'BrokerURL' must be specified") } + if len(v.ConsumerVersionSelectors) != 0 { + for _, selector := range v.ConsumerVersionSelectors { + if err = selector.Validate(); err != nil { + return fmt.Errorf("invalid consumer version selector specified: %v", err) + } + body, err := json.Marshal(selector) + if err != nil { + return fmt.Errorf("invalid consumer version selector specified: %v", err) + } + + v.Args = append(v.Args, "--consumer-version-selector", string(body)) + } + } + if len(v.CustomProviderHeaders) != 0 { for _, header := range v.CustomProviderHeaders { v.Args = append(v.Args, "--custom-provider-header", header) diff --git a/types/verify_request_test.go b/types/verify_request_test.go index 7b3311061..54764a01e 100644 --- a/types/verify_request_test.go +++ b/types/verify_request_test.go @@ -1,71 +1,107 @@ package types import ( + "github.com/stretchr/testify/assert" "testing" ) -func TestVerifyRequest_ValidRequest(t *testing.T) { - r := VerifyRequest{ - BrokerURL: "http://localhost:1234", - PactURLs: []string{"http://localhost:1234/path/to/pact"}, - BrokerUsername: "abcd", - BrokerPassword: "1234", - ProviderBaseURL: "http://localhost:8080", - ProviderStatesSetupURL: "http://localhost:8080/setup", - ProviderVersion: "1.0.0", - PublishVerificationResults: true, - Verbose: true, - CustomProviderHeaders: []string{ - "header: value", - }, - } +func TestVerifyRequestValidate(t *testing.T) { - err := r.Validate() + t.Run("local validation", func(t *testing.T) { + tests := []struct { + name string + request VerifyRequest + err bool + }{ + {name: "valid parameters", request: VerifyRequest{ + BrokerURL: "http://localhost:1234", + PactURLs: []string{"http://localhost:1234/path/to/pact"}, + BrokerUsername: "abcd", + BrokerPassword: "1234", + ProviderBaseURL: "http://localhost:8080", + ProviderStatesSetupURL: "http://localhost:8080/setup", + ProviderVersion: "1.0.0", + PublishVerificationResults: true, + Verbose: true, + CustomProviderHeaders: []string{ + "header: value", + }, + }, err: false}, + {name: "no base URL provided", request: VerifyRequest{ + PactURLs: []string{"http://localhost:1234/path/to/pact"}, + }, err: true}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + err := tt.request.Validate() + if tt.err { + assert.Error(t, err) + } else { + assert.NoError(t, err) + } + }) + } - if err != nil { - t.Fatal("want nil, got err: ", err) - } -} - -func TestVerifyRequest_NoBaseURL(t *testing.T) { - r := VerifyRequest{ - PactURLs: []string{"http://localhost:1234/path/to/pact"}, - } - - err := r.Validate() - - if err == nil { - t.Fatal("want err, got nil") - } -} - -func TestVerifyRequest_BrokerUsernameWithoutPassword(t *testing.T) { - r := VerifyRequest{ - PactURLs: []string{"http://localhost:1234/path/to/pact"}, - ProviderBaseURL: "http://localhost:8080", - BrokerURL: "http://localhost:1234", - ProviderVersion: "1.0.0.", - BrokerPassword: "1234", - } - - err := r.Validate() - - if err == nil { - t.Fatal("want error, got nil") - } -} + }) -func TestVerifyRequest_BrokerURLWithoutVersion(t *testing.T) { - r := VerifyRequest{ - PactURLs: []string{"http://localhost:1234/path/to/pact"}, - ProviderBaseURL: "http://localhost:8080", - BrokerURL: "http://localhost:1234", - BrokerPassword: "1234", - } + t.Run("broker integration", func(t *testing.T) { + tests := []struct { + name string + request VerifyRequest + err bool + }{ + {name: "url without version", request: VerifyRequest{ + PactURLs: []string{"http://localhost:1234/path/to/pact"}, + ProviderBaseURL: "http://localhost:8080", + BrokerURL: "http://localhost:1234", + }, err: true}, + {name: "password without username", request: VerifyRequest{ + PactURLs: []string{"http://localhost:1234/path/to/pact"}, + ProviderBaseURL: "http://localhost:8080", + BrokerURL: "http://localhost:1234", + ProviderVersion: "1.0.0", + BrokerPassword: "1234", + }, err: true}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + err := tt.request.Validate() + if tt.err { + assert.Error(t, err) + } else { + assert.NoError(t, err) + } + }) + } - err := r.Validate() + }) - if err == nil { - t.Fatal("want error, got nil") - } + t.Run("consumer version selectors", func(t *testing.T) { + tests := []struct { + name string + request VerifyRequest + err bool + }{ + {name: "no pacticipant", request: VerifyRequest{ + PactURLs: []string{"http://localhost:1234/path/to/pact"}, + ProviderBaseURL: "http://localhost:8080", + ConsumerVersionSelectors: []ConsumerVersionSelector{ConsumerVersionSelector{}}, + }, err: true}, + {name: "pacticipant only", request: VerifyRequest{ + PactURLs: []string{"http://localhost:1234/path/to/pact"}, + ProviderBaseURL: "http://localhost:8080", + ConsumerVersionSelectors: []ConsumerVersionSelector{ConsumerVersionSelector{Pacticipant: "foo"}}, + }, err: false}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + err := tt.request.Validate() + if tt.err { + assert.Error(t, err) + } else { + assert.NoError(t, err) + } + }) + } + }) }