Skip to content

Commit

Permalink
Revert "Report first instance of mismatch for JSON matcher"
Browse files Browse the repository at this point in the history
  • Loading branch information
Onsi Fakhouri committed Mar 22, 2017
1 parent c5ef083 commit d7dc9ba
Show file tree
Hide file tree
Showing 2 changed files with 5 additions and 90 deletions.
77 changes: 5 additions & 72 deletions matchers/match_json_matcher.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,12 @@ import (
"encoding/json"
"fmt"
"reflect"
"strings"

"github.com/onsi/gomega/format"
)

type MatchJSONMatcher struct {
JSONToMatch interface{}
firstFailurePath []interface{}
JSONToMatch interface{}
}

func (matcher *MatchJSONMatcher) Match(actual interface{}) (success bool, err error) {
Expand All @@ -27,45 +25,18 @@ func (matcher *MatchJSONMatcher) Match(actual interface{}) (success bool, err er
// this is guarded by prettyPrint
json.Unmarshal([]byte(actualString), &aval)
json.Unmarshal([]byte(expectedString), &eval)
var equal bool
equal, matcher.firstFailurePath = deepEqual(aval, eval)
return equal, nil

return reflect.DeepEqual(aval, eval), nil
}

func (matcher *MatchJSONMatcher) FailureMessage(actual interface{}) (message string) {
actualString, expectedString, _ := matcher.prettyPrint(actual)
return formattedMessage(format.Message(actualString, "to match JSON of", expectedString), matcher.firstFailurePath)
return format.Message(actualString, "to match JSON of", expectedString)
}

func (matcher *MatchJSONMatcher) NegatedFailureMessage(actual interface{}) (message string) {
actualString, expectedString, _ := matcher.prettyPrint(actual)
return formattedMessage(format.Message(actualString, "not to match JSON of", expectedString), matcher.firstFailurePath)
}

func formattedMessage(comparisonMessage string, failurePath []interface{}) string {
var diffMessage string
if len(failurePath) == 0 {
diffMessage = ""
} else {
diffMessage = fmt.Sprintf("\n\nfirst mismatched key: %s", formattedFailurePath(failurePath))
}
return fmt.Sprintf("%s%s", comparisonMessage, diffMessage)
}

func formattedFailurePath(failurePath []interface{}) string {
formattedPaths := []string{}
for i := len(failurePath) - 1; i >= 0; i-- {
switch p := failurePath[i].(type) {
case int:
formattedPaths = append(formattedPaths, fmt.Sprintf(`[%d]`, p))
default:
if i != len(failurePath)-1 {
formattedPaths = append(formattedPaths, ".")
}
formattedPaths = append(formattedPaths, fmt.Sprintf(`"%s"`, p))
}
}
return strings.Join(formattedPaths, "")
return format.Message(actualString, "not to match JSON of", expectedString)
}

func (matcher *MatchJSONMatcher) prettyPrint(actual interface{}) (actualFormatted, expectedFormatted string, err error) {
Expand All @@ -91,41 +62,3 @@ func (matcher *MatchJSONMatcher) prettyPrint(actual interface{}) (actualFormatte

return abuf.String(), ebuf.String(), nil
}

func deepEqual(a interface{}, b interface{}) (bool, []interface{}) {
var errorPath []interface{}
if reflect.TypeOf(a) != reflect.TypeOf(b) {
return false, errorPath
}

switch a.(type) {
case []interface{}:
if len(a.([]interface{})) != len(b.([]interface{})) {
return false, errorPath
}

for i, v := range a.([]interface{}) {
elementEqual, keyPath := deepEqual(v, b.([]interface{})[i])
if !elementEqual {
return false, append(keyPath, i)
}
}
return true, errorPath

case map[string]interface{}:
if len(a.(map[string]interface{})) != len(b.(map[string]interface{})) {
return false, errorPath
}

for k, v := range a.(map[string]interface{}) {
elementEqual, keyPath := deepEqual(v, b.(map[string]interface{})[k])
if !elementEqual {
return false, append(keyPath, k)
}
}
return true, errorPath

default:
return a == b, errorPath
}
}
18 changes: 0 additions & 18 deletions matchers/match_json_matcher_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,24 +25,6 @@ var _ = Describe("MatchJSONMatcher", func() {
})
})

Context("when a key mismatch is found", func() {
It("reports the first found mismatch", func() {
subject := MatchJSONMatcher{JSONToMatch: `5`}
actual := `7`
subject.Match(actual)

failureMessage := subject.FailureMessage(`7`)
Ω(failureMessage).ToNot(ContainSubstring("first mismatched key"))

subject = MatchJSONMatcher{JSONToMatch: `{"a": 1, "b.g": {"c": 2, "1": ["hello", "see ya"]}}`}
actual = `{"a": 1, "b.g": {"c": 2, "1": ["hello", "goodbye"]}}`
subject.Match(actual)

failureMessage = subject.FailureMessage(actual)
Ω(failureMessage).To(ContainSubstring(`first mismatched key: "b.g"."1"[1]`))
})
})

Context("when the expected is not valid JSON", func() {
It("should error and explain why", func() {
success, err := (&MatchJSONMatcher{JSONToMatch: `{}`}).Match(`oops`)
Expand Down

0 comments on commit d7dc9ba

Please sign in to comment.