Skip to content

Commit

Permalink
chore: wrap snyk in guard to prevent PRs failing
Browse files Browse the repository at this point in the history
  • Loading branch information
mefellows committed Jul 5, 2020
1 parent 72e4f07 commit 142ed78
Show file tree
Hide file tree
Showing 5 changed files with 1,087 additions and 1,206 deletions.
12 changes: 10 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ TEST?=./...

.DEFAULT_GOAL := ci

ci:: docker deps clean bin test pact goveralls
ci:: docker deps snyk clean bin test pact goveralls

docker:
@echo "--- 🛠 Starting docker"
Expand All @@ -21,7 +21,7 @@ bin:
clean:
rm -rf build output dist

deps:
deps: snyk-install
@echo "--- 🐿 Fetching build dependencies "
go get github.com/axw/gocov/gocov
go get github.com/mattn/goveralls
Expand Down Expand Up @@ -69,4 +69,12 @@ testrace:
updatedeps:
go get -d -v -p 2 ./...

snyk-install:
npm i -g snyk

snyk:
@if [ "$$TRAVIS_PULL_REQUEST" != "false" ]; then\
snyk test; \
fi

.PHONY: install bin default dev test pact updatedeps clean release
147 changes: 14 additions & 133 deletions dsl/matcher.go
Original file line number Diff line number Diff line change
@@ -1,36 +1,5 @@
package dsl

// Matcher types supported by JVM:
//
// method description
// string, stringValue Match a string value (using string equality)
// number, numberValue Match a number value (using Number.equals)*
// booleanValue Match a boolean value (using equality)
// stringType Will match all Strings
// numberType Will match all numbers*
// integerType Will match all numbers that are integers (both ints and longs)*
// decimalType Will match all real numbers (floating point and decimal)*
// booleanType Will match all boolean values (true and false)
// stringMatcher Will match strings using the provided regular expression
// timestamp Will match string containing timestamps. If a timestamp format is not given, will match an ISO timestamp format
// date Will match string containing dates. If a date format is not given, will match an ISO date format
// time Will match string containing times. If a time format is not given, will match an ISO time format
// ipAddress Will match string containing IP4 formatted address.
// id Will match all numbers by type
// hexValue Will match all hexadecimal encoded strings
// uuid Will match strings containing UUIDs

// RULES I'd like to follow:
// 0. Allow the option of string bodies for simple things
// 1. Have all of the matchers deal with interfaces{} for their values (or a Matcher/Builder type interface)
// - Interfaces may turn out to be primitives like strings, ints etc. (valid JSON values I guess)
// 2. Make all matcher values serialise as map[string]interface{} to be able to easily convert to JSON,
// and allows simpler interspersing of builder logic
// - can we embed builders in maps??
// 3. Keep the matchers/builders simple, and orchestrate them from another class/func/place
// Candidates are:
// - Interaction
// - Some new DslBuilder thingo
import (
"encoding/json"
"fmt"
Expand All @@ -56,8 +25,7 @@ var timeExample = time.Date(2000, 2, 1, 12, 30, 0, 0, time.UTC)

type eachLike struct {
Contents interface{} `json:"contents"`
Min int `json:"min,omitempty"`
Max int `json:"max,omitempty"`
Min int `json:"min"`
}

func (m eachLike) GetValue() interface{} {
Expand All @@ -76,27 +44,6 @@ func (m eachLike) MarshalJSON() ([]byte, error) {
}{"Pact::ArrayLike", marshaler(m)})
}

func (m eachLike) Type() MatcherClass {
if m.Max != 0 {
return ArrayMaxLikeMatcher
}
return ArrayMinLikeMatcher
}

func (m eachLike) MatchingRule() matcherType {
matcher := matcherType{
"match": "type",
}

if m.Max != 0 {
matcher["max"] = m.Max
} else {
matcher["min"] = m.Min
}

return matcher
}

type like struct {
Contents interface{} `json:"contents"`
}
Expand All @@ -117,16 +64,6 @@ func (m like) MarshalJSON() ([]byte, error) {
}{"Pact::SomethingLike", marshaler(m)})
}

func (m like) Type() MatcherClass {
return LikeMatcher
}

func (m like) MatchingRule() matcherType {
return matcherType{
"match": "type",
}
}

type term struct {
Data termData `json:"data"`
}
Expand All @@ -147,17 +84,6 @@ func (m term) MarshalJSON() ([]byte, error) {
}{"Pact::Term", marshaler(m)})
}

func (m term) Type() MatcherClass {
return RegexMatcher
}

func (m term) MatchingRule() matcherType {
return matcherType{
"match": "regex",
"regex": m.Data.Matcher.Regex,
}
}

type termData struct {
Generate interface{} `json:"generate"`
Matcher termMatcher `json:"matcher"`
Expand All @@ -171,22 +97,10 @@ type termMatcher struct {

// EachLike specifies that a given element in a JSON body can be repeated
// "minRequired" times. Number needs to be 1 or greater
func EachLike(content interface{}, min int) Matcher {
return eachLike{
Contents: content,
Min: min,
}
}

var ArrayMinLike = EachLike

// ArrayMaxLike matches nested arrays in request bodies.
// Ensure that each item in the list matches the provided example and the list
// is no greater than the provided max.
func ArrayMaxLike(content interface{}, max int) Matcher {
func EachLike(content interface{}, minRequired int) Matcher {
return eachLike{
Contents: content,
Max: max,
Min: minRequired,
}
}

Expand Down Expand Up @@ -282,33 +196,12 @@ type Matcher interface {
// GetValue returns the raw generated value for the matcher
// without any of the matching detail context
GetValue() interface{}

Type() MatcherClass

// Generate the matching rule for this Matcher
MatchingRule() matcherType
}

// MatcherClass is used to differentiate the various matchers when serialising
type MatcherClass int

// Matcher Types
const (
// LikeMatcher is the ID for the Like Matcher
LikeMatcher MatcherClass = iota

// RegexMatcher is the ID for the Term Matcher
RegexMatcher

// ArrayMinLikeMatcher is the ID for the ArrayMinLike Matcher
ArrayMinLikeMatcher

// ArrayMaxLikeMatcher is the ID for the ArrayMaxLikeMatcher Matcher
ArrayMaxLikeMatcher
)

// S is the string primitive wrapper (alias) for the Matcher type,
// it allows plain strings to be matched
// To keep backwards compatible with previous versions
// we aren't using an alias here
type S string

func (s S) isMatcher() {}
Expand All @@ -319,19 +212,17 @@ func (s S) GetValue() interface{} {
return s
}

func (s S) Type() MatcherClass {
return LikeMatcher
}

func (s S) MatchingRule() matcherType {
return matcherType{
"match": "type",
}
}

// String is the longer named form of the string primitive wrapper,
// it allows plain strings to be matched
type String = S
type String string

func (s String) isMatcher() {}

// GetValue returns the raw generated value for the matcher
// without any of the matching detail context
func (s String) GetValue() interface{} {
return s
}

// StructMatcher matches a complex object structure, which may itself
// contain nested Matchers
Expand All @@ -345,16 +236,6 @@ func (m StructMatcher) GetValue() interface{} {
return nil
}

func (s StructMatcher) Type() MatcherClass {
return LikeMatcher
}

func (s StructMatcher) MatchingRule() matcherType {
return matcherType{
"match": "type",
}
}

// MapMatcher allows a map[string]string-like object
// to also contain complex matchers
type MapMatcher map[string]Matcher
Expand Down
47 changes: 11 additions & 36 deletions dsl/matcher_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -373,7 +373,7 @@ func TestMatcher_SugarMatchers(t *testing.T) {
testCase func(val interface{}) error
}
matchers := map[string]matcherTestCase{
"HexValue": {
"HexValue": matcherTestCase{
matcher: HexValue(),
testCase: func(v interface{}) (err error) {
if v.(string) != "3F" {
Expand All @@ -382,7 +382,7 @@ func TestMatcher_SugarMatchers(t *testing.T) {
return
},
},
"Identifier": {
"Identifier": matcherTestCase{
matcher: Identifier(),
testCase: func(v interface{}) (err error) {
_, valid := v.(float64) // JSON converts numbers to float64 in anonymous structs
Expand All @@ -392,7 +392,7 @@ func TestMatcher_SugarMatchers(t *testing.T) {
return
},
},
"Integer": {
"Integer": matcherTestCase{
matcher: Integer(),
testCase: func(v interface{}) (err error) {
_, valid := v.(float64) // JSON converts numbers to float64 in anonymous structs
Expand All @@ -402,7 +402,7 @@ func TestMatcher_SugarMatchers(t *testing.T) {
return
},
},
"IPAddress": {
"IPAddress": matcherTestCase{
matcher: IPAddress(),
testCase: func(v interface{}) (err error) {
if v.(string) != "127.0.0.1" {
Expand All @@ -411,7 +411,7 @@ func TestMatcher_SugarMatchers(t *testing.T) {
return
},
},
"IPv4Address": {
"IPv4Address": matcherTestCase{
matcher: IPv4Address(),
testCase: func(v interface{}) (err error) {
if v.(string) != "127.0.0.1" {
Expand All @@ -420,7 +420,7 @@ func TestMatcher_SugarMatchers(t *testing.T) {
return
},
},
"IPv6Address": {
"IPv6Address": matcherTestCase{
matcher: IPv6Address(),
testCase: func(v interface{}) (err error) {
if v.(string) != "::ffff:192.0.2.128" {
Expand All @@ -429,7 +429,7 @@ func TestMatcher_SugarMatchers(t *testing.T) {
return
},
},
"Decimal": {
"Decimal": matcherTestCase{
matcher: Decimal(),
testCase: func(v interface{}) (err error) {
_, valid := v.(float64)
Expand All @@ -439,7 +439,7 @@ func TestMatcher_SugarMatchers(t *testing.T) {
return
},
},
"Timestamp": {
"Timestamp": matcherTestCase{
matcher: Timestamp(),
testCase: func(v interface{}) (err error) {
_, valid := v.(string)
Expand All @@ -449,7 +449,7 @@ func TestMatcher_SugarMatchers(t *testing.T) {
return
},
},
"Date": {
"Date": matcherTestCase{
matcher: Date(),
testCase: func(v interface{}) (err error) {
_, valid := v.(string)
Expand All @@ -459,7 +459,7 @@ func TestMatcher_SugarMatchers(t *testing.T) {
return
},
},
"Time": {
"Time": matcherTestCase{
matcher: Time(),
testCase: func(v interface{}) (err error) {
_, valid := v.(string)
Expand All @@ -469,7 +469,7 @@ func TestMatcher_SugarMatchers(t *testing.T) {
return
},
},
"UUID": {
"UUID": matcherTestCase{
matcher: UUID(),
testCase: func(v interface{}) (err error) {
match, err := regexp.MatchString(uuid, v.(string))
Expand Down Expand Up @@ -973,28 +973,3 @@ func Test_pluckParams(t *testing.T) {
})
}
}

func TestMatcher_term(t *testing.T) {
matcher := map[string]interface{}{
"id": Like(127),
}

expectedBody := formatJSON(`{
"id": 127
}`)
expectedMatchingRules := matchingRuleType{
"$.body.id": map[string]interface{}{
"match": "type",
},
}

body := PactBodyBuilder(matcher)
result := formatJSONObject(body.Body)

if expectedBody != result {
t.Fatalf("got '%v' wanted '%v'", result, expectedBody)
}
if !reflect.DeepEqual(body.MatchingRules, expectedMatchingRules) {
t.Fatalf("got '%v' wanted '%v'", body.MatchingRules, expectedMatchingRules)
}
}
Loading

0 comments on commit 142ed78

Please sign in to comment.