Skip to content

Commit 1658825

Browse files
authored
fix(suite): Add hyphen support for context keys (#1277)
1 parent 3a95e32 commit 1658825

File tree

3 files changed

+139
-5
lines changed

3 files changed

+139
-5
lines changed

README.md

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -403,10 +403,12 @@ Here are a few cases in which suites could be useful:
403403

404404
#### Using Context in Endpoints
405405
Once values are stored in the context, they can be referenced in subsequent endpoints:
406-
- In the URL: `https://api.example.com/users/[CONTEXT].userId`
407-
- In headers: `Authorization: Bearer [CONTEXT].authToken`
408-
- In the body: `{"user_id": "[CONTEXT].userId"}`
409-
- In conditions: `[BODY].server_ip == [CONTEXT].serverIp`
406+
- In the URL: `https://api.example.com/users/[CONTEXT].user_id`
407+
- In headers: `Authorization: Bearer [CONTEXT].auth_token`
408+
- In the body: `{"user_id": "[CONTEXT].user_id"}`
409+
- In conditions: `[BODY].server_ip == [CONTEXT].server_ip`
410+
411+
Note that context/store keys are limited to A-Z, a-z, 0-9, underscores (`_`), and hyphens (`-`).
410412

411413
#### Example Suite Configuration
412414
```yaml

config/endpoint/endpoint.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -391,7 +391,7 @@ func replaceContextPlaceholders(input string, ctx *gontext.Gontext) (string, err
391391
return input, nil
392392
}
393393
var contextErrors []string
394-
contextRegex := regexp.MustCompile(`\[CONTEXT\]\.[\w\.]+`)
394+
contextRegex := regexp.MustCompile(`\[CONTEXT\]\.[\w\.\-]+`)
395395
result := contextRegex.ReplaceAllStringFunc(input, func(match string) string {
396396
// Extract the path after [CONTEXT].
397397
path := strings.TrimPrefix(match, "[CONTEXT].")

config/endpoint/endpoint_test.go

Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1227,6 +1227,138 @@ func TestEndpoint_preprocessWithContext(t *testing.T) {
12271227
expectedErrorCount: 1,
12281228
expectedErrorContains: []string{"path 'response.missing.path' not found"},
12291229
},
1230+
{
1231+
name: "hyphen_support_in_simple_keys",
1232+
endpoint: &Endpoint{
1233+
URL: "https://api.example.com/users/[CONTEXT].user-id",
1234+
Body: `{"api-key": "[CONTEXT].api-key", "user-name": "[CONTEXT].user-name"}`,
1235+
},
1236+
context: map[string]interface{}{
1237+
"user-id": "user-12345",
1238+
"api-key": "key-abcdef",
1239+
"user-name": "john-doe",
1240+
},
1241+
expectedURL: "https://api.example.com/users/user-12345",
1242+
expectedBody: `{"api-key": "key-abcdef", "user-name": "john-doe"}`,
1243+
expectedErrorCount: 0,
1244+
},
1245+
{
1246+
name: "hyphen_support_in_headers",
1247+
endpoint: &Endpoint{
1248+
URL: "https://api.example.com",
1249+
Body: "",
1250+
Headers: map[string]string{
1251+
"X-API-Key": "[CONTEXT].api-key",
1252+
"X-User-ID": "[CONTEXT].user-id",
1253+
"Content-Type": "[CONTEXT].content-type",
1254+
},
1255+
},
1256+
context: map[string]interface{}{
1257+
"api-key": "secret-key-123",
1258+
"user-id": "user-456",
1259+
"content-type": "application-json",
1260+
},
1261+
expectedURL: "https://api.example.com",
1262+
expectedBody: "",
1263+
expectedHeaders: map[string]string{
1264+
"X-API-Key": "secret-key-123",
1265+
"X-User-ID": "user-456",
1266+
"Content-Type": "application-json",
1267+
},
1268+
expectedErrorCount: 0,
1269+
},
1270+
{
1271+
name: "mixed_hyphens_underscores_and_dots",
1272+
endpoint: &Endpoint{
1273+
URL: "https://api.example.com/[CONTEXT].service-name/[CONTEXT].user_data.user-id",
1274+
Body: `{"tenant-id": "[CONTEXT].tenant_config.tenant-id"}`,
1275+
},
1276+
context: map[string]interface{}{
1277+
"service-name": "auth-service",
1278+
"user_data": map[string]interface{}{
1279+
"user-id": "user-789",
1280+
},
1281+
"tenant_config": map[string]interface{}{
1282+
"tenant-id": "tenant-abc-123",
1283+
},
1284+
},
1285+
expectedURL: "https://api.example.com/auth-service/user-789",
1286+
expectedBody: `{"tenant-id": "tenant-abc-123"}`,
1287+
expectedErrorCount: 0,
1288+
},
1289+
{
1290+
name: "hyphen_in_nested_paths",
1291+
endpoint: &Endpoint{
1292+
URL: "https://api.example.com/users/[CONTEXT].auth-response.user-data.profile-id",
1293+
Body: "",
1294+
},
1295+
context: map[string]interface{}{
1296+
"auth-response": map[string]interface{}{
1297+
"user-data": map[string]interface{}{
1298+
"profile-id": "profile-xyz-789",
1299+
},
1300+
},
1301+
},
1302+
expectedURL: "https://api.example.com/users/profile-xyz-789",
1303+
expectedBody: "",
1304+
expectedErrorCount: 0,
1305+
},
1306+
{
1307+
name: "missing_hyphenated_context_key",
1308+
endpoint: &Endpoint{
1309+
URL: "https://api.example.com/users/[CONTEXT].missing-user-id",
1310+
Body: `{"api-key": "[CONTEXT].missing-api-key"}`,
1311+
},
1312+
context: map[string]interface{}{
1313+
"user-id": "valid-user", // different key
1314+
},
1315+
expectedURL: "https://api.example.com/users/[CONTEXT].missing-user-id",
1316+
expectedBody: `{"api-key": "[CONTEXT].missing-api-key"}`,
1317+
expectedErrorCount: 2,
1318+
expectedErrorContains: []string{"path 'missing-user-id' not found", "path 'missing-api-key' not found"},
1319+
},
1320+
{
1321+
name: "multiple_hyphens_in_single_key",
1322+
endpoint: &Endpoint{
1323+
URL: "https://api.example.com/[CONTEXT].multi-hyphen-key-name",
1324+
Body: "",
1325+
},
1326+
context: map[string]interface{}{
1327+
"multi-hyphen-key-name": "value-with-multiple-hyphens",
1328+
},
1329+
expectedURL: "https://api.example.com/value-with-multiple-hyphens",
1330+
expectedBody: "",
1331+
expectedErrorCount: 0,
1332+
},
1333+
{
1334+
name: "hyphens_with_numeric_values",
1335+
endpoint: &Endpoint{
1336+
URL: "https://api.example.com/limit/[CONTEXT].max-items",
1337+
Body: `{"timeout-ms": [CONTEXT].timeout-ms, "retry-count": [CONTEXT].retry-count}`,
1338+
},
1339+
context: map[string]interface{}{
1340+
"max-items": 100,
1341+
"timeout-ms": 5000,
1342+
"retry-count": 3,
1343+
},
1344+
expectedURL: "https://api.example.com/limit/100",
1345+
expectedBody: `{"timeout-ms": 5000, "retry-count": 3}`,
1346+
expectedErrorCount: 0,
1347+
},
1348+
{
1349+
name: "hyphens_with_boolean_values",
1350+
endpoint: &Endpoint{
1351+
URL: "https://api.example.com",
1352+
Body: `{"enable-feature": [CONTEXT].enable-feature, "disable-cache": [CONTEXT].disable-cache}`,
1353+
},
1354+
context: map[string]interface{}{
1355+
"enable-feature": true,
1356+
"disable-cache": false,
1357+
},
1358+
expectedURL: "https://api.example.com",
1359+
expectedBody: `{"enable-feature": true, "disable-cache": false}`,
1360+
expectedErrorCount: 0,
1361+
},
12301362
}
12311363

12321364
for _, tt := range tests {

0 commit comments

Comments
 (0)