Skip to content

Commit a524ecd

Browse files
mpywclaude
andcommitted
test: add unit tests for JS request/response objects and error patterns
- Add unit tests for Request (method, url, headers) and Response (status, statusText, ok, headers) - Add test for {"error": "..."} pattern in TransformError - Add test for infinite loop timeout (ErrJSTimeout) - Fix lint errors in config_test.go (os.Remove and tmpFile.Close error handling) - Fix sealed object tests to verify silent ignoring behavior instead of expecting errors Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
1 parent 8a51b21 commit a524ecd

5 files changed

Lines changed: 361 additions & 2 deletions

File tree

internal/config/config_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -435,7 +435,7 @@ func TestParseFile(t *testing.T) {
435435
// Create a temporary file
436436
tmpFile, err := os.CreateTemp("", "config-*.yaml")
437437
require.NoError(t, err)
438-
defer os.Remove(tmpFile.Name())
438+
defer func() { _ = os.Remove(tmpFile.Name()) }()
439439

440440
content := `
441441
queries:
@@ -447,7 +447,7 @@ queries:
447447
`
448448
_, err = tmpFile.WriteString(content)
449449
require.NoError(t, err)
450-
tmpFile.Close()
450+
require.NoError(t, tmpFile.Close())
451451

452452
cfg, err := ParseFile(tmpFile.Name())
453453
require.NoError(t, err)

internal/js/apply_test.go

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package js
22

33
import (
4+
"errors"
45
"testing"
56

67
"github.com/stretchr/testify/assert"
@@ -287,3 +288,21 @@ func TestApplyPostToAllRows(t *testing.T) {
287288
assert.Equal(t, int64(2), resultMap["total"])
288289
})
289290
}
291+
292+
func TestJSTimeout(t *testing.T) {
293+
t.Run("infinite loop times out", func(t *testing.T) {
294+
// This test verifies that infinite loops are interrupted
295+
// Note: JSTimeout is 5 seconds by default
296+
transformer, err := CompilePre(`while(true) {} return input`)
297+
require.NoError(t, err)
298+
299+
_, err = transformer.ApplyPre(
300+
map[string]any{},
301+
"SELECT 1",
302+
map[string]any{},
303+
nil,
304+
)
305+
require.Error(t, err)
306+
assert.True(t, errors.Is(err, ErrJSTimeout), "expected timeout error, got: %v", err)
307+
})
308+
}

internal/js/error_test.go

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,14 @@ func TestTransformError(t *testing.T) {
2121
assert.Equal(t, "validation error", err.Error())
2222
})
2323

24+
t.Run("object body with error key", func(t *testing.T) {
25+
err := &TransformError{
26+
Status: 400,
27+
Body: map[string]any{"error": "something went wrong", "code": "ERR001"},
28+
}
29+
assert.Equal(t, "something went wrong", err.Error())
30+
})
31+
2432
t.Run("object body without message", func(t *testing.T) {
2533
err := &TransformError{
2634
Status: 400,
@@ -147,3 +155,18 @@ func TestParseJSError_ThrownString(t *testing.T) {
147155
assert.Equal(t, "simple error message", transformErr.Body)
148156
})
149157
}
158+
159+
func TestParseJSError_ErrorKey(t *testing.T) {
160+
t.Run("body with error key", func(t *testing.T) {
161+
transformer, err := CompilePre(`throw { status: 400, body: { error: "something went wrong" } }`)
162+
require.NoError(t, err)
163+
164+
_, err = transformer.ApplyMock(nil, "", nil, nil)
165+
require.Error(t, err)
166+
167+
var transformErr *TransformError
168+
require.ErrorAs(t, err, &transformErr)
169+
assert.Equal(t, 400, transformErr.Status)
170+
assert.Equal(t, "something went wrong", transformErr.Error())
171+
})
172+
}

internal/js/request_test.go

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
package js
2+
3+
import (
4+
"net/http"
5+
"net/http/httptest"
6+
"testing"
7+
8+
"github.com/dop251/goja"
9+
"github.com/stretchr/testify/assert"
10+
"github.com/stretchr/testify/require"
11+
)
12+
13+
func TestRequest(t *testing.T) {
14+
req := httptest.NewRequest(http.MethodPost, "/test/path?foo=bar", nil)
15+
req.Header.Set("X-Custom", "value")
16+
req.Header.Set("Content-Type", "application/json")
17+
18+
r := NewRequest(req)
19+
20+
t.Run("Method", func(t *testing.T) {
21+
assert.Equal(t, "POST", r.Method())
22+
})
23+
24+
t.Run("URL", func(t *testing.T) {
25+
assert.Equal(t, "/test/path?foo=bar", r.URL())
26+
})
27+
28+
t.Run("Headers", func(t *testing.T) {
29+
h := r.Headers()
30+
require.NotNil(t, h)
31+
assert.Equal(t, "value", h.Get("X-Custom"))
32+
assert.Equal(t, "application/json", h.Get("Content-Type"))
33+
})
34+
}
35+
36+
func TestRequest_ToJSObject(t *testing.T) {
37+
req := httptest.NewRequest(http.MethodGet, "/api/users?id=123", nil)
38+
req.Header.Set("Authorization", "Bearer token")
39+
40+
r := NewRequest(req)
41+
vm := goja.New()
42+
obj := r.ToJSObject(vm)
43+
44+
err := vm.Set("request", obj)
45+
require.NoError(t, err)
46+
47+
t.Run("method property", func(t *testing.T) {
48+
result, err := vm.RunString(`request.method`)
49+
require.NoError(t, err)
50+
assert.Equal(t, "GET", result.String())
51+
})
52+
53+
t.Run("url property", func(t *testing.T) {
54+
result, err := vm.RunString(`request.url`)
55+
require.NoError(t, err)
56+
assert.Equal(t, "/api/users?id=123", result.String())
57+
})
58+
59+
t.Run("headers.get()", func(t *testing.T) {
60+
result, err := vm.RunString(`request.headers.get("Authorization")`)
61+
require.NoError(t, err)
62+
assert.Equal(t, "Bearer token", result.String())
63+
})
64+
65+
t.Run("headers.has()", func(t *testing.T) {
66+
result, err := vm.RunString(`request.headers.has("Authorization")`)
67+
require.NoError(t, err)
68+
assert.True(t, result.ToBoolean())
69+
70+
result, err = vm.RunString(`request.headers.has("X-Missing")`)
71+
require.NoError(t, err)
72+
assert.False(t, result.ToBoolean())
73+
})
74+
75+
t.Run("request is sealed - new property ignored", func(t *testing.T) {
76+
// Sealed objects silently ignore new property assignments in non-strict mode
77+
_, err := vm.RunString(`request.newProp = "test"`)
78+
require.NoError(t, err)
79+
80+
result, err := vm.RunString(`request.newProp`)
81+
require.NoError(t, err)
82+
assert.True(t, goja.IsUndefined(result)) // Property was not added
83+
})
84+
85+
t.Run("method is read-only - assignment ignored", func(t *testing.T) {
86+
// Read-only properties silently ignore assignments in non-strict mode
87+
_, err := vm.RunString(`request.method = "PUT"`)
88+
require.NoError(t, err)
89+
90+
result, err := vm.RunString(`request.method`)
91+
require.NoError(t, err)
92+
assert.Equal(t, "GET", result.String()) // Value unchanged
93+
})
94+
}

0 commit comments

Comments
 (0)