Skip to content

Commit c8f44fb

Browse files
committed
refactor context and events tests with shared helpers
1 parent b9846ff commit c8f44fb

3 files changed

Lines changed: 96 additions & 116 deletions

File tree

vibes/capability_context_test.go

Lines changed: 19 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,9 @@ import (
77
)
88

99
func TestContextCapabilityResolver(t *testing.T) {
10-
engine := MustNewEngine(Config{})
11-
script, err := engine.Compile(`def run()
10+
script := compileScriptDefault(t, `def run()
1211
ctx.user.id
1312
end`)
14-
if err != nil {
15-
t.Fatalf("compile failed: %v", err)
16-
}
1713

1814
type ctxKey string
1915
resolver := func(ctx context.Context) (Value, error) {
@@ -30,25 +26,18 @@ end`)
3026
ctx := context.WithValue(context.Background(), ctxKey("user_id"), "player-1")
3127
ctx = context.WithValue(ctx, ctxKey("role"), "coach")
3228

33-
result, err := script.Call(ctx, "run", nil, CallOptions{
34-
Capabilities: []CapabilityAdapter{MustNewContextCapability("ctx", resolver)},
35-
})
36-
if err != nil {
37-
t.Fatalf("call failed: %v", err)
38-
}
29+
result := callScript(t, ctx, script, "run", nil, callOptionsWithCapabilities(
30+
MustNewContextCapability("ctx", resolver),
31+
))
3932
if result.Kind() != KindString || result.String() != "player-1" {
4033
t.Fatalf("unexpected result: %#v", result)
4134
}
4235
}
4336

4437
func TestContextCapabilityRejectsCallableValue(t *testing.T) {
45-
engine := MustNewEngine(Config{})
46-
script, err := engine.Compile(`def run()
38+
script := compileScriptDefault(t, `def run()
4739
ctx.user.id
4840
end`)
49-
if err != nil {
50-
t.Fatalf("compile failed: %v", err)
51-
}
5241

5342
resolver := func(ctx context.Context) (Value, error) {
5443
return NewObject(map[string]Value{
@@ -61,65 +50,42 @@ end`)
6150
}), nil
6251
}
6352

64-
_, err = script.Call(context.Background(), "run", nil, CallOptions{
65-
Capabilities: []CapabilityAdapter{MustNewContextCapability("ctx", resolver)},
66-
})
67-
if err == nil {
68-
t.Fatalf("expected callable context data error")
69-
}
70-
if got := err.Error(); !strings.Contains(got, "ctx capability value must be data-only") {
71-
t.Fatalf("unexpected error: %s", got)
72-
}
53+
err := callScriptErr(t, context.Background(), script, "run", nil, callOptionsWithCapabilities(
54+
MustNewContextCapability("ctx", resolver),
55+
))
56+
requireErrorContains(t, err, "ctx capability value must be data-only")
7357
}
7458

7559
func TestContextCapabilityRejectsNonObjectValue(t *testing.T) {
76-
engine := MustNewEngine(Config{})
77-
script, err := engine.Compile(`def run()
60+
script := compileScriptDefault(t, `def run()
7861
1
7962
end`)
80-
if err != nil {
81-
t.Fatalf("compile failed: %v", err)
82-
}
8363

8464
resolver := func(ctx context.Context) (Value, error) {
8565
return NewString("invalid"), nil
8666
}
8767

88-
_, err = script.Call(context.Background(), "run", nil, CallOptions{
89-
Capabilities: []CapabilityAdapter{MustNewContextCapability("ctx", resolver)},
90-
})
91-
if err == nil {
92-
t.Fatalf("expected resolver shape error")
93-
}
94-
if got := err.Error(); !strings.Contains(got, "ctx capability resolver must return hash/object") {
95-
t.Fatalf("unexpected error: %s", got)
96-
}
68+
err := callScriptErr(t, context.Background(), script, "run", nil, callOptionsWithCapabilities(
69+
MustNewContextCapability("ctx", resolver),
70+
))
71+
requireErrorContains(t, err, "ctx capability resolver must return hash/object")
9772
}
9873

9974
func TestContextCapabilityRejectsCyclicValue(t *testing.T) {
100-
engine := MustNewEngine(Config{})
101-
script, err := engine.Compile(`def run()
75+
script := compileScriptDefault(t, `def run()
10276
ctx
10377
end`)
104-
if err != nil {
105-
t.Fatalf("compile failed: %v", err)
106-
}
10778

10879
resolver := func(context.Context) (Value, error) {
10980
cyclic := map[string]Value{}
11081
cyclic["self"] = NewHash(cyclic)
11182
return NewHash(cyclic), nil
11283
}
11384

114-
_, err = script.Call(context.Background(), "run", nil, CallOptions{
115-
Capabilities: []CapabilityAdapter{MustNewContextCapability("ctx", resolver)},
116-
})
117-
if err == nil {
118-
t.Fatalf("expected cyclic value error")
119-
}
120-
if got := err.Error(); !strings.Contains(got, "ctx capability value must not contain cyclic references") {
121-
t.Fatalf("unexpected error: %s", got)
122-
}
85+
err := callScriptErr(t, context.Background(), script, "run", nil, callOptionsWithCapabilities(
86+
MustNewContextCapability("ctx", resolver),
87+
))
88+
requireErrorContains(t, err, "ctx capability value must not contain cyclic references")
12389
}
12490

12591
func TestNewContextCapabilityRejectsInvalidArguments(t *testing.T) {

vibes/capability_events_test.go

Lines changed: 23 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -24,22 +24,15 @@ func (s *eventsCapabilityStub) Publish(ctx context.Context, req EventPublishRequ
2424

2525
func TestEventsCapabilityPublish(t *testing.T) {
2626
stub := &eventsCapabilityStub{publishResult: NewBool(true)}
27-
engine := MustNewEngine(Config{})
28-
script, err := engine.Compile(`def run()
27+
script := compileScriptDefault(t, `def run()
2928
events.publish("players_totals", { id: "p-1", total: "55.00 USD" }, trace: "abc")
3029
end`)
31-
if err != nil {
32-
t.Fatalf("compile failed: %v", err)
33-
}
3430

3531
type ctxKey string
3632
ctx := context.WithValue(context.Background(), ctxKey("request_id"), "req-1")
37-
result, err := script.Call(ctx, "run", nil, CallOptions{
38-
Capabilities: []CapabilityAdapter{MustNewEventsCapability("events", stub)},
39-
})
40-
if err != nil {
41-
t.Fatalf("call failed: %v", err)
42-
}
33+
result := callScript(t, ctx, script, "run", nil, callOptionsWithCapabilities(
34+
MustNewEventsCapability("events", stub),
35+
))
4336
if result.Kind() != KindBool || !result.Bool() {
4437
t.Fatalf("unexpected result: %#v", result)
4538
}
@@ -63,48 +56,30 @@ end`)
6356

6457
func TestEventsCapabilityRejectsCallablePayload(t *testing.T) {
6558
stub := &eventsCapabilityStub{}
66-
engine := MustNewEngine(Config{})
67-
script, err := engine.Compile(`def helper(value)
59+
script := compileScriptDefault(t, `def helper(value)
6860
value
6961
end
7062
7163
def run()
7264
events.publish("topic", { callback: helper })
7365
end`)
74-
if err != nil {
75-
t.Fatalf("compile failed: %v", err)
76-
}
7766

78-
_, err = script.Call(context.Background(), "run", nil, CallOptions{
79-
Capabilities: []CapabilityAdapter{MustNewEventsCapability("events", stub)},
80-
})
81-
if err == nil {
82-
t.Fatalf("expected callable payload error")
83-
}
84-
if got := err.Error(); !strings.Contains(got, "events.publish payload must be data-only") {
85-
t.Fatalf("unexpected error: %s", got)
86-
}
67+
err := callScriptErr(t, context.Background(), script, "run", nil, callOptionsWithCapabilities(
68+
MustNewEventsCapability("events", stub),
69+
))
70+
requireErrorContains(t, err, "events.publish payload must be data-only")
8771
}
8872

8973
func TestEventsCapabilityRejectsNonHashPayload(t *testing.T) {
9074
stub := &eventsCapabilityStub{}
91-
engine := MustNewEngine(Config{})
92-
script, err := engine.Compile(`def run()
75+
script := compileScriptDefault(t, `def run()
9376
events.publish("topic", 42)
9477
end`)
95-
if err != nil {
96-
t.Fatalf("compile failed: %v", err)
97-
}
9878

99-
_, err = script.Call(context.Background(), "run", nil, CallOptions{
100-
Capabilities: []CapabilityAdapter{MustNewEventsCapability("events", stub)},
101-
})
102-
if err == nil {
103-
t.Fatalf("expected non-hash payload error")
104-
}
105-
if got := err.Error(); !strings.Contains(got, "events.publish payload expected hash, got int") {
106-
t.Fatalf("unexpected error: %s", got)
107-
}
79+
err := callScriptErr(t, context.Background(), script, "run", nil, callOptionsWithCapabilities(
80+
MustNewEventsCapability("events", stub),
81+
))
82+
requireErrorContains(t, err, "events.publish payload expected hash, got int")
10883
}
10984

11085
func TestEventsCapabilityRejectsCallableReturn(t *testing.T) {
@@ -115,23 +90,14 @@ func TestEventsCapabilityRejectsCallableReturn(t *testing.T) {
11590
}),
11691
}),
11792
}
118-
engine := MustNewEngine(Config{})
119-
script, err := engine.Compile(`def run()
93+
script := compileScriptDefault(t, `def run()
12094
events.publish("topic", { id: "p-1" })
12195
end`)
122-
if err != nil {
123-
t.Fatalf("compile failed: %v", err)
124-
}
12596

126-
_, err = script.Call(context.Background(), "run", nil, CallOptions{
127-
Capabilities: []CapabilityAdapter{MustNewEventsCapability("events", stub)},
128-
})
129-
if err == nil {
130-
t.Fatalf("expected return contract error")
131-
}
132-
if got := err.Error(); !strings.Contains(got, "events.publish return value must be data-only") {
133-
t.Fatalf("unexpected error: %s", got)
134-
}
97+
err := callScriptErr(t, context.Background(), script, "run", nil, callOptionsWithCapabilities(
98+
MustNewEventsCapability("events", stub),
99+
))
100+
requireErrorContains(t, err, "events.publish return value must be data-only")
135101
}
136102

137103
func TestEventsCapabilityReturnsAreClonedFromHostState(t *testing.T) {
@@ -142,20 +108,14 @@ func TestEventsCapabilityReturnsAreClonedFromHostState(t *testing.T) {
142108
}),
143109
}),
144110
}
145-
engine := MustNewEngine(Config{})
146-
script, err := engine.Compile(`def run()
111+
script := compileScriptDefault(t, `def run()
147112
event = events.publish("topic", { id: "p-1" })
148113
event[:meta][:trace] = "script"
149114
end`)
150-
if err != nil {
151-
t.Fatalf("compile failed: %v", err)
152-
}
153115

154-
if _, err := script.Call(context.Background(), "run", nil, CallOptions{
155-
Capabilities: []CapabilityAdapter{MustNewEventsCapability("events", stub)},
156-
}); err != nil {
157-
t.Fatalf("call failed: %v", err)
158-
}
116+
callScript(t, context.Background(), script, "run", nil, callOptionsWithCapabilities(
117+
MustNewEventsCapability("events", stub),
118+
))
159119

160120
trace := stub.publishResult.Hash()["meta"].Hash()["trace"]
161121
if trace.Kind() != KindString || trace.String() != "host" {
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
package vibes
2+
3+
import (
4+
"context"
5+
"strings"
6+
"testing"
7+
)
8+
9+
func compileScriptWithConfig(t testing.TB, cfg Config, source string) *Script {
10+
t.Helper()
11+
engine := MustNewEngine(cfg)
12+
script, err := engine.Compile(source)
13+
if err != nil {
14+
t.Fatalf("compile failed: %v", err)
15+
}
16+
return script
17+
}
18+
19+
func compileScriptDefault(t testing.TB, source string) *Script {
20+
t.Helper()
21+
return compileScriptWithConfig(t, Config{}, source)
22+
}
23+
24+
func callScript(t testing.TB, ctx context.Context, script *Script, fn string, args []Value, opts CallOptions) Value {
25+
t.Helper()
26+
result, err := script.Call(ctx, fn, args, opts)
27+
if err != nil {
28+
t.Fatalf("call failed: %v", err)
29+
}
30+
return result
31+
}
32+
33+
func callScriptErr(t testing.TB, ctx context.Context, script *Script, fn string, args []Value, opts CallOptions) error {
34+
t.Helper()
35+
_, err := script.Call(ctx, fn, args, opts)
36+
if err == nil {
37+
t.Fatalf("expected call to fail")
38+
}
39+
return err
40+
}
41+
42+
func requireErrorContains(t testing.TB, err error, want string) {
43+
t.Helper()
44+
if err == nil {
45+
t.Fatalf("expected error containing %q, got nil", want)
46+
}
47+
if got := err.Error(); !strings.Contains(got, want) {
48+
t.Fatalf("unexpected error: %s", got)
49+
}
50+
}
51+
52+
func callOptionsWithCapabilities(capabilities ...CapabilityAdapter) CallOptions {
53+
return CallOptions{Capabilities: capabilities}
54+
}

0 commit comments

Comments
 (0)