Skip to content

Commit be7ec59

Browse files
committed
refactor(be): migration extractor
1 parent 6b29795 commit be7ec59

2 files changed

Lines changed: 151 additions & 29 deletions

File tree

api/integration.go

Lines changed: 5 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -317,7 +317,7 @@ func GetTaskDefinition(
317317

318318
taskDefinition.Environment = string(envStr)
319319

320-
extractedTaskResults := ExtractAsAnyForTaskParams(taskValues, h, payload)
320+
extractedTaskResults := Extract(taskValues, h, payload)
321321
for k, v := range extractedTaskResults {
322322
taskDefinition.Params[k] = v
323323
}
@@ -366,38 +366,14 @@ func Extract(extractValues []db.IntegrationExtractValue, h http.Header, payload
366366
case db.IntegrationExtractBodyValue:
367367
switch extractValue.BodyDataType {
368368
case db.IntegrationBodyDataJSON:
369-
var extractedResult = fmt.Sprintf("%v", gojsonq.New().JSONString(string(payload)).Find(extractValue.Key))
370-
result[extractValue.Variable] = extractedResult
369+
val := gojsonq.New().JSONString(string(payload)).Find(extractValue.Key)
370+
if val != nil {
371+
result[extractValue.Variable] = fmt.Sprintf("%v", val)
372+
}
371373
case db.IntegrationBodyDataString:
372374
result[extractValue.Variable] = string(payload)
373375
}
374376
}
375377
}
376378
return
377379
}
378-
379-
func ExtractAsAnyForTaskParams(extractValues []db.IntegrationExtractValue, h http.Header, payload []byte) db.MapStringAnyField {
380-
// Create a result map that accepts any type
381-
result := make(db.MapStringAnyField)
382-
383-
for _, extractValue := range extractValues {
384-
switch extractValue.ValueSource {
385-
case db.IntegrationExtractHeaderValue:
386-
// Extract the header value
387-
result[extractValue.Variable] = h.Get(extractValue.Key)
388-
389-
case db.IntegrationExtractBodyValue:
390-
switch extractValue.BodyDataType {
391-
case db.IntegrationBodyDataJSON:
392-
// Query the JSON payload for the key using gojsonq
393-
rawValue := gojsonq.New().JSONString(string(payload)).Find(extractValue.Key)
394-
result[extractValue.Variable] = rawValue
395-
396-
case db.IntegrationBodyDataString:
397-
// Simply use the entire payload as a string
398-
result[extractValue.Variable] = string(payload)
399-
}
400-
}
401-
}
402-
return result
403-
}

api/integration_test.go

Lines changed: 146 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,154 @@ import (
99

1010
"net/http"
1111
"testing"
12+
13+
"github.com/stretchr/testify/require"
1214
)
1315

16+
func TestExtract_HeaderAndCaseInsensitive(t *testing.T) {
17+
h := http.Header{}
18+
h.Set("x-token", "abc123") // lower-case to verify case-insensitive get
19+
20+
values := []db.IntegrationExtractValue{
21+
{
22+
Name: "Token header",
23+
ValueSource: db.IntegrationExtractHeaderValue,
24+
Key: "X-Token", // different case
25+
Variable: "TOKEN",
26+
VariableType: db.IntegrationVariableEnvironment,
27+
},
28+
}
29+
30+
got := Extract(values, h, nil)
31+
32+
require.Equal(t, "abc123", got["TOKEN"], "TOKEN header value should match")
33+
}
34+
35+
func TestExtract_JSONBody_VariousTypesAndMissing(t *testing.T) {
36+
payload := []byte(`{
37+
"num": 42,
38+
"str": "hello",
39+
"bool": true,
40+
"nullv": null,
41+
"obj": {"k":"v"},
42+
"arr": [1,2,3],
43+
"nested": {"items":[{"c":123},{"c":"str"}]}
44+
}`)
45+
46+
values := []db.IntegrationExtractValue{
47+
{ // number coerced to string via fmt.Sprintf
48+
ValueSource: db.IntegrationExtractBodyValue,
49+
BodyDataType: db.IntegrationBodyDataJSON,
50+
Key: "num",
51+
Variable: "NUM",
52+
},
53+
{ // string stays same content
54+
ValueSource: db.IntegrationExtractBodyValue,
55+
BodyDataType: db.IntegrationBodyDataJSON,
56+
Key: "str",
57+
Variable: "STR",
58+
},
59+
{ // boolean -> "true"
60+
ValueSource: db.IntegrationExtractBodyValue,
61+
BodyDataType: db.IntegrationBodyDataJSON,
62+
Key: "bool",
63+
Variable: "BOOL",
64+
},
65+
{ // null should not be set (Find returns nil or we skip when nil)
66+
ValueSource: db.IntegrationExtractBodyValue,
67+
BodyDataType: db.IntegrationBodyDataJSON,
68+
Key: "nullv",
69+
Variable: "NULLV",
70+
},
71+
{ // array will be formatted with %v, expect Go-like format
72+
ValueSource: db.IntegrationExtractBodyValue,
73+
BodyDataType: db.IntegrationBodyDataJSON,
74+
Key: "arr",
75+
Variable: "ARR",
76+
},
77+
{ // object -> formatted map with %v
78+
ValueSource: db.IntegrationExtractBodyValue,
79+
BodyDataType: db.IntegrationBodyDataJSON,
80+
Key: "obj",
81+
Variable: "OBJ",
82+
},
83+
{ // missing key should not create an entry
84+
ValueSource: db.IntegrationExtractBodyValue,
85+
BodyDataType: db.IntegrationBodyDataJSON,
86+
Key: "missing",
87+
Variable: "MISSING",
88+
},
89+
{ // nested array index path
90+
ValueSource: db.IntegrationExtractBodyValue,
91+
BodyDataType: db.IntegrationBodyDataJSON,
92+
Key: "nested.items.[0].c",
93+
Variable: "NESTED_C",
94+
},
95+
{ // first element of arr
96+
ValueSource: db.IntegrationExtractBodyValue,
97+
BodyDataType: db.IntegrationBodyDataJSON,
98+
Key: "arr.[0]",
99+
Variable: "ARR0",
100+
},
101+
}
102+
103+
got := Extract(values, http.Header{}, payload)
104+
105+
// Basic scalar assertions
106+
assert.Equal(t, "42", got["NUM"], "NUM should equal stringified number")
107+
assert.Equal(t, "hello", got["STR"], "STR should match")
108+
assert.Equal(t, "true", got["BOOL"], "BOOL should be string 'true'")
109+
110+
// Indexed lookups
111+
assert.Equal(t, "123", got["NESTED_C"], "NESTED_C should equal nested.items[0].c")
112+
assert.Equal(t, "1", got["ARR0"], "ARR0 should equal arr[0]")
113+
114+
// Null should be absent
115+
assert.NotContains(t, got, "NULLV", "NULLV should not be present for null JSON value")
116+
117+
// Array/object string formats: we assert non-empty presence rather than exact formatting,
118+
// because %v formatting of gojsonq return types may vary across versions.
119+
assert.Contains(t, got, "ARR", "ARR key should be present")
120+
assert.NotEmpty(t, got["ARR"], "ARR value should be non-empty")
121+
assert.Contains(t, got, "OBJ", "OBJ key should be present")
122+
assert.NotEmpty(t, got["OBJ"], "OBJ value should be non-empty")
123+
124+
// Missing should not appear
125+
assert.NotContains(t, got, "MISSING", "MISSING should not be present for missing key")
126+
}
127+
128+
func TestExtract_BodyString_ReturnsFullPayload(t *testing.T) {
129+
payload := []byte("raw body data here")
130+
values := []db.IntegrationExtractValue{
131+
{
132+
ValueSource: db.IntegrationExtractBodyValue,
133+
BodyDataType: db.IntegrationBodyDataString,
134+
Variable: "BODY",
135+
Key: "ignored",
136+
},
137+
}
138+
got := Extract(values, http.Header{}, payload)
139+
if got["BODY"] != string(payload) {
140+
t.Fatalf("expected BODY to equal full payload; got %q", got["BODY"])
141+
}
142+
}
143+
144+
func TestExtract_MalformedJSON_SkipsSetting(t *testing.T) {
145+
payload := []byte("{not: valid json}")
146+
values := []db.IntegrationExtractValue{
147+
{
148+
ValueSource: db.IntegrationExtractBodyValue,
149+
BodyDataType: db.IntegrationBodyDataJSON,
150+
Variable: "BAD",
151+
Key: "a.b",
152+
},
153+
}
154+
got := Extract(values, http.Header{}, payload)
155+
if _, ok := got["BAD"]; ok {
156+
t.Fatalf("expected BAD to be absent for malformed JSON payload")
157+
}
158+
}
159+
14160
func TestIntegrationMatch(t *testing.T) {
15161
body := []byte("{\"hook_id\": 4856239453}")
16162
var header = make(http.Header)

0 commit comments

Comments
 (0)