Skip to content

Commit a7288d4

Browse files
committed
refactor: tidy up pact v2
1 parent 01ff94e commit a7288d4

File tree

3 files changed

+47
-40
lines changed

3 files changed

+47
-40
lines changed

v3/http.go

Lines changed: 1 addition & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,7 @@ package v3
99
// 3. Need to ensure only v2 or v3 matchers are added
1010

1111
import (
12-
"bytes"
1312
"crypto/tls"
14-
"encoding/json"
1513
"errors"
1614
"fmt"
1715
"log"
@@ -263,7 +261,7 @@ func (p *httpMockProvider) displayMismatches(mismatches []native.MismatchedReque
263261
}
264262
}
265263

266-
// WritePact should be called writes when all tests have been performed for a
264+
// WritePact should be called when all tests have been performed for a
267265
// given Consumer <-> Provider pair. It will write out the Pact to the
268266
// configured file. This is safe to call multiple times as the service is smart
269267
// enough to merge pacts and avoid duplicates.
@@ -286,19 +284,6 @@ var checkCliCompatibility = func() {
286284
}
287285
}
288286

289-
// Format a JSON document to make comparison easier.
290-
func formatJSONString(object string) string {
291-
var out bytes.Buffer
292-
json.Indent(&out, []byte(object), "", "\t")
293-
return string(out.Bytes())
294-
}
295-
296-
// Format a JSON document for creating Pact files.
297-
func formatJSONObject(object interface{}) string {
298-
out, _ := json.Marshal(object)
299-
return formatJSONString(string(out))
300-
}
301-
302287
// GetTLSConfigForTLSMockServer gets an http transport with
303288
// the certificates already trusted. Alternatively, simply set
304289
// trust level to insecure

v3/json_utils.go

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
package v3
2+
3+
import (
4+
"bytes"
5+
"encoding/json"
6+
)
7+
8+
// Format a JSON document to make comparison easier.
9+
func formatJSONString(object string) string {
10+
var out bytes.Buffer
11+
json.Indent(&out, []byte(object), "", "\t")
12+
return string(out.Bytes())
13+
}
14+
15+
// Format a JSON document for creating Pact files.
16+
func formatJSONObject(object interface{}) string {
17+
out, _ := json.Marshal(object)
18+
return formatJSONString(string(out))
19+
}

v3/pact_v2.go

Lines changed: 27 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ type pactFileV2 struct {
5151
// Raw incoming interactions from the consumer test
5252
interactions []*InteractionV2
5353

54-
// Interactions are the annotated set the request/response expectations, with matching rules and generators
54+
// Interactions are the annotated set the request/response expectations, with matching rules
5555
Interactions []pactInteractionV2 `json:"interactions"`
5656

5757
Metadata map[string]interface{} `json:"metadata"`
@@ -92,16 +92,16 @@ func (p *pactFileV2) generateV2PactFile() *pactFileV2 {
9292
var requestBodyMatchingRules, requestHeaderMatchingRules, requestQueryMatchingRules, responseBodyMatchingRules, responseHeaderMatchingRules rule
9393
var requestQuery map[string]interface{}
9494

95-
_, requestQuery, requestQueryMatchingRules, _ = buildPactPart("", interaction.Request.Query, make(map[string]interface{}), "$.query", make(rule), make(rule))
96-
_, serialisedInteraction.Request.Headers, requestHeaderMatchingRules, _ = buildPactPart("", interaction.Request.Headers, make(map[string]interface{}), "$.headers", make(rule), make(rule))
97-
_, serialisedInteraction.Request.Body, requestBodyMatchingRules, _ = buildPactPart("", interaction.Request.Body, make(map[string]interface{}), "$.body", make(rule), make(rule))
98-
_, serialisedInteraction.Response.Body, responseBodyMatchingRules, _ = buildPactPart("", interaction.Response.Body, make(map[string]interface{}), "$.body", make(rule), make(rule))
99-
_, serialisedInteraction.Response.Headers, responseHeaderMatchingRules, _ = buildPactPart("", interaction.Response.Headers, make(map[string]interface{}), "$.headers", make(rule), make(rule))
95+
requestQuery, requestQueryMatchingRules = buildPartV2(interaction.Request.Query, "$.query")
96+
serialisedInteraction.Request.Headers, requestHeaderMatchingRules = buildPartV2(interaction.Request.Headers, "$.headers")
97+
serialisedInteraction.Request.Body, requestBodyMatchingRules = buildPartV2(interaction.Request.Body, "$.body")
98+
serialisedInteraction.Response.Body, responseBodyMatchingRules = buildPartV2(interaction.Response.Body, "$.body")
99+
serialisedInteraction.Response.Headers, responseHeaderMatchingRules = buildPartV2(interaction.Response.Headers, "$.headers")
100100

101101
buildPactRequestQueryV2(requestQuery, interaction, &serialisedInteraction, p.Options)
102102
buildPactRequestPathV2(interaction, &serialisedInteraction)
103-
mergeRules(serialisedInteraction.Request.MatchingRules, requestHeaderMatchingRules)
104103
mergeRules(serialisedInteraction.Request.MatchingRules, requestQueryMatchingRules)
104+
mergeRules(serialisedInteraction.Request.MatchingRules, requestHeaderMatchingRules)
105105
mergeRules(serialisedInteraction.Request.MatchingRules, requestBodyMatchingRules)
106106
mergeRules(serialisedInteraction.Response.MatchingRules, responseBodyMatchingRules)
107107
mergeRules(serialisedInteraction.Response.MatchingRules, responseHeaderMatchingRules)
@@ -119,7 +119,7 @@ const startList = "["
119119
const endList = "]"
120120

121121
func recurseMapType(key string, value interface{}, body map[string]interface{}, path string,
122-
matchingRules rule, generators rule) (string, map[string]interface{}, rule, rule) {
122+
matchingRules rule) (string, map[string]interface{}, rule) {
123123
mapped := reflect.ValueOf(value)
124124
entry := make(map[string]interface{})
125125
path = path + buildPath(key, "")
@@ -132,16 +132,22 @@ func recurseMapType(key string, value interface{}, body map[string]interface{},
132132

133133
// Starting position
134134
if key == "" {
135-
_, body, matchingRules, generators = buildPactPart(k.String(), v.Interface(), copyMap(body), path, matchingRules, generators)
135+
_, body, matchingRules = buildPactPartV2(k.String(), v.Interface(), copyMap(body), path, matchingRules)
136136
} else {
137-
_, body[key], matchingRules, generators = buildPactPart(k.String(), v.Interface(), entry, path, matchingRules, generators)
137+
_, body[key], matchingRules = buildPactPartV2(k.String(), v.Interface(), entry, path, matchingRules)
138138
}
139139
}
140140

141-
return path, body, matchingRules, generators
141+
return path, body, matchingRules
142+
}
143+
144+
func buildPartV2(value interface{}, path string) (map[string]interface{}, rule) {
145+
_, o, matchingRules := buildPactPartV2("", value, make(object), path, make(rule))
146+
147+
return o, matchingRules
142148
}
143149

144-
// Recurse the Matcher tree and buildPactPart up an example body and set of matchers for
150+
// Recurse the Matcher tree and buildPactPartV2 up an example body and set of matchers for
145151
// the Pact file. Ideally this stays as a pure function, but probably might need
146152
// to store matchers externally.
147153
//
@@ -153,12 +159,10 @@ func recurseMapType(key string, value interface{}, body map[string]interface{},
153159
// - body => Current state of the body map to be built up (body will be the returned Pact body for serialisation)
154160
// - path => Path to the current key
155161
// - matchingRules => Current set of matching rules (matching rules will also be serialised into the Pact)
156-
// - generators => Current set of generators rules (generators rules will also be serialised into the Pact)
157162
//
158-
159-
// Returns path, body, matchingRules, generators
160-
func buildPactPart(key string, value interface{}, body map[string]interface{}, path string,
161-
matchingRules rule, generators rule) (string, map[string]interface{}, rule, rule) {
163+
// Returns path, body, matchingRules
164+
func buildPactPartV2(key string, value interface{}, body map[string]interface{}, path string,
165+
matchingRules rule) (string, map[string]interface{}, rule) {
162166
log.Println("[TRACE] generate pact => key:", key, ", body:", body, ", value:", value, ", path:", path)
163167

164168
switch t := value.(type) {
@@ -181,7 +185,7 @@ func buildPactPart(key string, value interface{}, body map[string]interface{}, p
181185
minArray := make([]interface{}, times)
182186

183187
builtPath := path + buildPath(key, allListItems)
184-
buildPactPart("0", t.GetValue(), arrayMap, builtPath, matchingRules, generators)
188+
buildPactPartV2("0", t.GetValue(), arrayMap, builtPath, matchingRules)
185189
log.Println("[TRACE] generate pact: ArrayMikeLikeMatcher/ArrayMaxLikeMatcher =>", builtPath)
186190
matchingRules[path+buildPath(key, "")] = m.MatchingRule()
187191

@@ -205,7 +209,7 @@ func buildPactPart(key string, value interface{}, body map[string]interface{}, p
205209
// This exists to server the v3.Match() interface
206210
case structTypeMatcher:
207211
log.Println("[TRACE] generate pact: StructTypeMatcher")
208-
_, body, matchingRules, generators = recurseMapType(key, t.GetValue().(StructMatcher), body, path, matchingRules, generators)
212+
_, body, matchingRules = recurseMapType(key, t.GetValue().(StructMatcher), body, path, matchingRules)
209213

210214
default:
211215
log.Fatalf("unexpected matcher (%s) for current specification format (2.0.0)", t.Type())
@@ -223,15 +227,15 @@ func buildPactPart(key string, value interface{}, body map[string]interface{}, p
223227
k := fmt.Sprintf("%d", i)
224228
builtPath := path + buildPath(key, fmt.Sprintf("%s%d%s", startList, i, endList))
225229
log.Println("[TRACE] generate pact: []interface{}: recursing into =>", builtPath)
226-
buildPactPart(k, el, arrayMap, builtPath, matchingRules, generators)
230+
buildPactPartV2(k, el, arrayMap, builtPath, matchingRules)
227231
arrayValues[i] = arrayMap[k]
228232
}
229233
body[key] = arrayValues
230234

231235
// Map -> Recurse keys (All objects start here!)
232236
case map[string]interface{}, MapMatcher, QueryMatcher:
233237
log.Println("[TRACE] generate pact: MapMatcher")
234-
_, body, matchingRules, generators = recurseMapType(key, t, body, path, matchingRules, generators)
238+
_, body, matchingRules = recurseMapType(key, t, body, path, matchingRules)
235239

236240
// Primitives (terminal cases)
237241
default:
@@ -241,7 +245,7 @@ func buildPactPart(key string, value interface{}, body map[string]interface{}, p
241245

242246
log.Printf("[TRACE] generate pact => returning body: %+v\n", body)
243247

244-
return path, body, matchingRules, generators
248+
return path, body, matchingRules
245249
}
246250

247251
// V2 query strings are stored as strings
@@ -256,9 +260,8 @@ func buildPactPart(key string, value interface{}, body map[string]interface{}, p
256260
// See https://stackoverflow.com/questions/6243051/how-to-pass-an-array-within-a-query-string
257261
// TODO: allow a specific generator to be provided?
258262
func buildPactRequestQueryV2(input map[string]interface{}, sourceInteraction *InteractionV2, destInteraction *pactInteractionV2, options PactSerialisationOptionsV2) {
259-
// matching rules already added
260-
261263
var parts []string
264+
262265
for k, v := range input {
263266
rt := reflect.TypeOf(v)
264267
switch rt.Kind() {

0 commit comments

Comments
 (0)