wip rename
This commit is contained in:
@@ -1 +0,0 @@
|
||||
package builtin
|
||||
@@ -1,4 +1,4 @@
|
||||
package builtin
|
||||
package functions
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
@@ -1,4 +1,4 @@
|
||||
package builtin
|
||||
package functions
|
||||
|
||||
import (
|
||||
"context"
|
||||
@@ -18,21 +18,21 @@ func (t TestArgs) Validate() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func TestAsyncBuiltin(t *testing.T) {
|
||||
RegisterAsyncBuiltin("testAsync", func(_ context.Context, args TestArgs) (string, error) {
|
||||
func TestAsyncFunction(t *testing.T) {
|
||||
RegisterAsyncFunction("testAsync", func(_ context.Context, args TestArgs) (string, error) {
|
||||
return "result: " + args.Field1, nil
|
||||
})
|
||||
|
||||
registryMutex.RLock()
|
||||
builtin, ok := builtinRegistry["testAsync"]
|
||||
fn, ok := functionRegistry["testAsync"]
|
||||
registryMutex.RUnlock()
|
||||
|
||||
require.True(t, ok, "testAsync should be registered")
|
||||
assert.Contains(t, builtin.Definition(), "Promise<string>", "definition should include Promise<string>")
|
||||
assert.Contains(t, fn.Definition(), "Promise<string>", "definition should include Promise<string>")
|
||||
}
|
||||
|
||||
func TestAsyncBuiltinResolution(t *testing.T) {
|
||||
RegisterAsyncBuiltin("resolveTest", func(_ context.Context, args TestArgs) (string, error) {
|
||||
func TestAsyncFunctionResolution(t *testing.T) {
|
||||
RegisterAsyncFunction("resolveTest", func(_ context.Context, args TestArgs) (string, error) {
|
||||
return "test-result", nil
|
||||
})
|
||||
|
||||
@@ -43,15 +43,15 @@ func TestAsyncBuiltinResolution(t *testing.T) {
|
||||
}()
|
||||
vm.SetCanBlock(true)
|
||||
|
||||
RegisterBuiltins(context.Background(), vm)
|
||||
RegisterFunctions(context.Background(), vm)
|
||||
|
||||
result, err := vm.Eval(`resolveTest("hello")`, quickjs.EvalGlobal)
|
||||
require.NoError(t, err)
|
||||
assert.NotNil(t, result)
|
||||
}
|
||||
|
||||
func TestAsyncBuiltinRejection(t *testing.T) {
|
||||
RegisterAsyncBuiltin("rejectTest", func(_ context.Context, args TestArgs) (string, error) {
|
||||
func TestAsyncFunctionRejection(t *testing.T) {
|
||||
RegisterAsyncFunction("rejectTest", func(_ context.Context, args TestArgs) (string, error) {
|
||||
return "", assert.AnError
|
||||
})
|
||||
|
||||
@@ -62,7 +62,7 @@ func TestAsyncBuiltinRejection(t *testing.T) {
|
||||
}()
|
||||
vm.SetCanBlock(true)
|
||||
|
||||
RegisterBuiltins(context.Background(), vm)
|
||||
RegisterFunctions(context.Background(), vm)
|
||||
|
||||
result, err := vm.Eval(`rejectTest({field1: "hello"})`, quickjs.EvalGlobal)
|
||||
require.NoError(t, err)
|
||||
@@ -70,7 +70,7 @@ func TestAsyncBuiltinRejection(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestNonPromise(t *testing.T) {
|
||||
RegisterBuiltin("nonPromiseTest", func(_ context.Context, args TestArgs) (string, error) {
|
||||
RegisterFunction("nonPromiseTest", func(_ context.Context, args TestArgs) (string, error) {
|
||||
return "sync-result", nil
|
||||
})
|
||||
|
||||
@@ -81,7 +81,7 @@ func TestNonPromise(t *testing.T) {
|
||||
}()
|
||||
vm.SetCanBlock(true)
|
||||
|
||||
RegisterBuiltins(context.Background(), vm)
|
||||
RegisterFunctions(context.Background(), vm)
|
||||
|
||||
result, err := vm.Eval(`nonPromiseTest({field1: "hello"})`, quickjs.EvalGlobal)
|
||||
require.NoError(t, err)
|
||||
@@ -1,4 +1,4 @@
|
||||
package builtin
|
||||
package functions
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
@@ -8,12 +8,12 @@ import (
|
||||
)
|
||||
|
||||
var (
|
||||
builtinRegistry = make(map[string]Builtin)
|
||||
registryMutex sync.RWMutex
|
||||
collector *typeCollector
|
||||
functionRegistry = make(map[string]Function)
|
||||
registryMutex sync.RWMutex
|
||||
collector *typeCollector
|
||||
)
|
||||
|
||||
func registerBuiltin[A Args, R any](name string, isAsync bool, fn Func[A, R]) {
|
||||
func registerFunction[A Args, R any](name string, isAsync bool, fn RawFunc[A, R]) {
|
||||
registryMutex.Lock()
|
||||
defer registryMutex.Unlock()
|
||||
|
||||
@@ -23,14 +23,14 @@ func registerBuiltin[A Args, R any](name string, isAsync bool, fn Func[A, R]) {
|
||||
|
||||
tType := reflect.TypeFor[A]()
|
||||
if tType.Kind() != reflect.Struct {
|
||||
panic(fmt.Sprintf("builtin %s: argument must be a struct type, got %v", name, tType))
|
||||
panic(fmt.Sprintf("function %s: argument must be a struct type, got %v", name, tType))
|
||||
}
|
||||
|
||||
fnType := reflect.TypeOf(fn)
|
||||
types := collector.collectTypes(tType, fnType)
|
||||
paramTypes := collector.getParamTypes()
|
||||
|
||||
builtinRegistry[name] = &builtinImpl[A, R]{
|
||||
functionRegistry[name] = &functionImpl[A, R]{
|
||||
name: name,
|
||||
fn: fn,
|
||||
types: types,
|
||||
@@ -38,7 +38,7 @@ func registerBuiltin[A Args, R any](name string, isAsync bool, fn Func[A, R]) {
|
||||
}
|
||||
}
|
||||
|
||||
func GetBuiltinsDeclarations() string {
|
||||
func GetFunctionDeclarations() string {
|
||||
registryMutex.RLock()
|
||||
defer registryMutex.RUnlock()
|
||||
|
||||
@@ -46,14 +46,14 @@ func GetBuiltinsDeclarations() string {
|
||||
var typeDefs []string
|
||||
var functionDecls []string
|
||||
|
||||
for _, builtin := range builtinRegistry {
|
||||
for _, t := range builtin.Types() {
|
||||
for _, fn := range functionRegistry {
|
||||
for _, t := range fn.Types() {
|
||||
if !typeDefinitions[t] {
|
||||
typeDefinitions[t] = true
|
||||
typeDefs = append(typeDefs, t)
|
||||
}
|
||||
}
|
||||
functionDecls = append(functionDecls, builtin.Definition())
|
||||
functionDecls = append(functionDecls, fn.Definition())
|
||||
}
|
||||
|
||||
result := strings.Join(typeDefs, "\n\n")
|
||||
@@ -65,14 +65,14 @@ func GetBuiltinsDeclarations() string {
|
||||
return result
|
||||
}
|
||||
|
||||
func RegisterBuiltin[T Args, R any](name string, fn Func[T, R]) {
|
||||
registerBuiltin(name, false, fn)
|
||||
func GetRegisteredFunctions() map[string]Function {
|
||||
return functionRegistry
|
||||
}
|
||||
|
||||
func RegisterAsyncBuiltin[T Args, R any](name string, fn Func[T, R]) {
|
||||
registerBuiltin(name, true, fn)
|
||||
func RegisterFunction[T Args, R any](name string, fn RawFunc[T, R]) {
|
||||
registerFunction(name, false, fn)
|
||||
}
|
||||
|
||||
func GetBuiltins() map[string]Builtin {
|
||||
return builtinRegistry
|
||||
func RegisterAsyncFunction[T Args, R any](name string, fn RawFunc[T, R]) {
|
||||
registerFunction(name, true, fn)
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package builtin
|
||||
package functions
|
||||
|
||||
import (
|
||||
"context"
|
||||
@@ -6,39 +6,39 @@ import (
|
||||
"reflect"
|
||||
)
|
||||
|
||||
type Builtin interface {
|
||||
type Function interface {
|
||||
Name() string
|
||||
Types() []string
|
||||
Definition() string
|
||||
WrapFn(context.Context) func(...any) (any, error)
|
||||
}
|
||||
|
||||
type Func[A Args, R any] func(ctx context.Context, args A) (R, error)
|
||||
type RawFunc[A Args, R any] func(context.Context, A) (R, error)
|
||||
|
||||
type Args interface {
|
||||
Validate() error
|
||||
}
|
||||
|
||||
type builtinImpl[A Args, R any] struct {
|
||||
type functionImpl[A Args, R any] struct {
|
||||
name string
|
||||
fn Func[A, R]
|
||||
fn RawFunc[A, R]
|
||||
definition string
|
||||
types []string
|
||||
}
|
||||
|
||||
func (b *builtinImpl[A, R]) Name() string {
|
||||
func (b *functionImpl[A, R]) Name() string {
|
||||
return b.name
|
||||
}
|
||||
|
||||
func (b *builtinImpl[A, R]) Types() []string {
|
||||
func (b *functionImpl[A, R]) Types() []string {
|
||||
return b.types
|
||||
}
|
||||
|
||||
func (b *builtinImpl[A, R]) Definition() string {
|
||||
func (b *functionImpl[A, R]) Definition() string {
|
||||
return b.definition
|
||||
}
|
||||
|
||||
func (b *builtinImpl[A, R]) WrapFn(ctx context.Context) func(...any) (any, error) {
|
||||
func (b *functionImpl[A, R]) WrapFn(ctx context.Context) func(...any) (any, error) {
|
||||
return func(allArgs ...any) (any, error) {
|
||||
// Populate Arguments
|
||||
var fnArgs A
|
||||
@@ -1,4 +1,4 @@
|
||||
package builtin
|
||||
package functions
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
@@ -1,4 +1,4 @@
|
||||
package builtin
|
||||
package functions
|
||||
|
||||
import (
|
||||
"context"
|
||||
@@ -18,11 +18,11 @@ func (t TestBasicArgs) Validate() error { return nil }
|
||||
|
||||
func TestBasicType(t *testing.T) {
|
||||
resetRegistry()
|
||||
RegisterBuiltin[TestBasicArgs, string]("basic", func(ctx context.Context, args TestBasicArgs) (string, error) {
|
||||
RegisterFunction[TestBasicArgs, string]("basic", func(ctx context.Context, args TestBasicArgs) (string, error) {
|
||||
return args.Name, nil
|
||||
})
|
||||
|
||||
defs := GetBuiltinsDeclarations()
|
||||
defs := GetFunctionDeclarations()
|
||||
assert.Contains(t, defs, "declare function basic(name: string, age: number): string;")
|
||||
assert.Contains(t, defs, "interface TestBasicArgs")
|
||||
}
|
||||
@@ -30,7 +30,7 @@ func TestBasicType(t *testing.T) {
|
||||
func resetRegistry() {
|
||||
registryLock.Lock()
|
||||
defer registryLock.Unlock()
|
||||
builtinRegistry = make(map[string]Builtin)
|
||||
functionRegistry = make(map[string]Function)
|
||||
}
|
||||
|
||||
var (
|
||||
@@ -47,11 +47,11 @@ func (t TestComplexArgs) Validate() error { return nil }
|
||||
|
||||
func TestComplexTypes(t *testing.T) {
|
||||
resetRegistry()
|
||||
RegisterBuiltin[TestComplexArgs, bool]("complex", func(ctx context.Context, args TestComplexArgs) (bool, error) {
|
||||
RegisterFunction[TestComplexArgs, bool]("complex", func(ctx context.Context, args TestComplexArgs) (bool, error) {
|
||||
return args.Flag, nil
|
||||
})
|
||||
|
||||
defs := GetBuiltinsDeclarations()
|
||||
defs := GetFunctionDeclarations()
|
||||
assert.Contains(t, defs, "declare function complex(items: number[], data: Record<string, any>, flag: boolean): boolean;")
|
||||
}
|
||||
|
||||
@@ -66,11 +66,11 @@ func (t TestNestedArgs) Validate() error { return nil }
|
||||
|
||||
func TestNestedStruct(t *testing.T) {
|
||||
resetRegistry()
|
||||
RegisterBuiltin[TestNestedArgs, string]("nested", func(ctx context.Context, args TestNestedArgs) (string, error) {
|
||||
RegisterFunction[TestNestedArgs, string]("nested", func(ctx context.Context, args TestNestedArgs) (string, error) {
|
||||
return args.User.FirstName, nil
|
||||
})
|
||||
|
||||
defs := GetBuiltinsDeclarations()
|
||||
defs := GetFunctionDeclarations()
|
||||
assert.Contains(t, defs, "declare function nested(user: {}): string;")
|
||||
}
|
||||
|
||||
@@ -84,11 +84,11 @@ func (t TestOptionalArgs) Validate() error { return nil }
|
||||
|
||||
func TestOptionalFields(t *testing.T) {
|
||||
resetRegistry()
|
||||
RegisterBuiltin[TestOptionalArgs, string]("optional", func(ctx context.Context, args TestOptionalArgs) (string, error) {
|
||||
RegisterFunction[TestOptionalArgs, string]("optional", func(ctx context.Context, args TestOptionalArgs) (string, error) {
|
||||
return args.Name, nil
|
||||
})
|
||||
|
||||
defs := GetBuiltinsDeclarations()
|
||||
defs := GetFunctionDeclarations()
|
||||
assert.Contains(t, defs, "declare function optional(name: string, age?: number | null, score?: number | null): string;")
|
||||
}
|
||||
|
||||
@@ -105,11 +105,11 @@ func (t TestResultArgs) Validate() error { return nil }
|
||||
|
||||
func TestResultStruct(t *testing.T) {
|
||||
resetRegistry()
|
||||
RegisterBuiltin[TestResultArgs, TestResult]("result", func(ctx context.Context, args TestResultArgs) (TestResult, error) {
|
||||
RegisterFunction[TestResultArgs, TestResult]("result", func(ctx context.Context, args TestResultArgs) (TestResult, error) {
|
||||
return TestResult{ID: 1}, nil
|
||||
})
|
||||
|
||||
defs := GetBuiltinsDeclarations()
|
||||
defs := GetFunctionDeclarations()
|
||||
assert.Contains(t, defs, "declare function result(input: string): TestResult;")
|
||||
assert.Contains(t, defs, "interface TestResult {id: number; data: number[]}")
|
||||
}
|
||||
@@ -126,11 +126,11 @@ type TestAsyncResult struct {
|
||||
|
||||
func TestAsyncPromise(t *testing.T) {
|
||||
resetRegistry()
|
||||
RegisterAsyncBuiltin[TestAsyncArgs, *TestAsyncStatus]("async", func(ctx context.Context, args TestAsyncArgs) (*TestAsyncStatus, error) {
|
||||
RegisterAsyncFunction[TestAsyncArgs, *TestAsyncStatus]("async", func(ctx context.Context, args TestAsyncArgs) (*TestAsyncStatus, error) {
|
||||
return &TestAsyncStatus{Code: 200}, nil
|
||||
})
|
||||
|
||||
defs := GetBuiltinsDeclarations()
|
||||
defs := GetFunctionDeclarations()
|
||||
assert.Contains(t, defs, "declare function async(url: string): Promise<TestAsyncStatus | null>;")
|
||||
assert.Contains(t, defs, "interface TestAsyncStatus")
|
||||
}
|
||||
@@ -151,11 +151,11 @@ func (t TestNestedPointerArgs) Validate() error { return nil }
|
||||
|
||||
func TestNestedPointerInResult(t *testing.T) {
|
||||
resetRegistry()
|
||||
RegisterBuiltin[TestNestedPointerArgs, *TestNestedPointerResult]("pointerResult", func(ctx context.Context, args TestNestedPointerArgs) (*TestNestedPointerResult, error) {
|
||||
RegisterFunction[TestNestedPointerArgs, *TestNestedPointerResult]("pointerResult", func(ctx context.Context, args TestNestedPointerArgs) (*TestNestedPointerResult, error) {
|
||||
return &TestNestedPointerResult{Value: "test"}, nil
|
||||
})
|
||||
|
||||
defs := GetBuiltinsDeclarations()
|
||||
defs := GetFunctionDeclarations()
|
||||
assert.Contains(t, defs, "declare function pointerResult(id: number): TestNestedPointerResult | null;")
|
||||
}
|
||||
|
||||
@@ -167,11 +167,11 @@ func (t TestUintArgs) Validate() error { return nil }
|
||||
|
||||
func TestUintType(t *testing.T) {
|
||||
resetRegistry()
|
||||
RegisterBuiltin[TestUintArgs, uint]("uint", func(ctx context.Context, args TestUintArgs) (uint, error) {
|
||||
RegisterFunction[TestUintArgs, uint]("uint", func(ctx context.Context, args TestUintArgs) (uint, error) {
|
||||
return args.Value, nil
|
||||
})
|
||||
|
||||
defs := GetBuiltinsDeclarations()
|
||||
defs := GetFunctionDeclarations()
|
||||
assert.Contains(t, defs, "declare function uint(value: number): number;")
|
||||
}
|
||||
|
||||
@@ -183,11 +183,11 @@ func (t TestFloatArgs) Validate() error { return nil }
|
||||
|
||||
func TestFloatType(t *testing.T) {
|
||||
resetRegistry()
|
||||
RegisterBuiltin[TestFloatArgs, float32]("float", func(ctx context.Context, args TestFloatArgs) (float32, error) {
|
||||
RegisterFunction[TestFloatArgs, float32]("float", func(ctx context.Context, args TestFloatArgs) (float32, error) {
|
||||
return float32(args.Amount), nil
|
||||
})
|
||||
|
||||
defs := GetBuiltinsDeclarations()
|
||||
defs := GetFunctionDeclarations()
|
||||
assert.Contains(t, defs, "declare function float(amount: number): number;")
|
||||
}
|
||||
|
||||
@@ -201,11 +201,11 @@ func (t TestPointerInArgs) Validate() error { return nil }
|
||||
|
||||
func TestNestedPointerStruct(t *testing.T) {
|
||||
resetRegistry()
|
||||
RegisterBuiltin[TestPointerInArgs, string]("nestedPointer", func(ctx context.Context, args TestPointerInArgs) (string, error) {
|
||||
RegisterFunction[TestPointerInArgs, string]("nestedPointer", func(ctx context.Context, args TestPointerInArgs) (string, error) {
|
||||
return "test", nil
|
||||
})
|
||||
|
||||
defs := GetBuiltinsDeclarations()
|
||||
defs := GetFunctionDeclarations()
|
||||
assert.Contains(t, defs, "declare function nestedPointer(user?: {} | null): string;")
|
||||
}
|
||||
|
||||
@@ -217,11 +217,11 @@ func (t TestErrorOnlyArgs) Validate() error { return nil }
|
||||
|
||||
func TestErrorOnlyReturn(t *testing.T) {
|
||||
resetRegistry()
|
||||
RegisterBuiltin[TestErrorOnlyArgs, struct{}]("errorOnly", func(ctx context.Context, args TestErrorOnlyArgs) (struct{}, error) {
|
||||
RegisterFunction[TestErrorOnlyArgs, struct{}]("errorOnly", func(ctx context.Context, args TestErrorOnlyArgs) (struct{}, error) {
|
||||
return struct{}{}, nil
|
||||
})
|
||||
|
||||
defs := GetBuiltinsDeclarations()
|
||||
defs := GetFunctionDeclarations()
|
||||
assert.Contains(t, defs, "declare function errorOnly(input: string): {};")
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@ import (
|
||||
|
||||
"github.com/evanw/esbuild/pkg/api"
|
||||
"modernc.org/quickjs"
|
||||
"reichard.io/poiesis/internal/builtin"
|
||||
"reichard.io/poiesis/internal/functions"
|
||||
)
|
||||
|
||||
type Runtime struct {
|
||||
@@ -59,7 +59,7 @@ func (r *Runtime) populateGlobals() error {
|
||||
}
|
||||
|
||||
// Register Custom Functions
|
||||
for name, builtin := range builtin.GetBuiltins() {
|
||||
for name, builtin := range functions.GetRegisteredFunctions() {
|
||||
// Register Main Function
|
||||
if err := r.vm.RegisterFunc(name, builtin.WrapFn(r.ctx), false); err != nil {
|
||||
return err
|
||||
|
||||
@@ -1,60 +0,0 @@
|
||||
package standard
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"testing"
|
||||
|
||||
"modernc.org/quickjs"
|
||||
|
||||
"reichard.io/poiesis/internal/builtin"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestFetchReturnsPromise(t *testing.T) {
|
||||
vm, err := quickjs.NewVM()
|
||||
require.NoError(t, err)
|
||||
defer func() {
|
||||
_ = vm.Close()
|
||||
}()
|
||||
vm.SetCanBlock(true)
|
||||
|
||||
builtin.RegisterBuiltins(context.Background(), vm)
|
||||
|
||||
result, err := vm.Eval(`fetch({input: "https://example.com"})`, quickjs.EvalGlobal)
|
||||
require.NoError(t, err)
|
||||
assert.NotNil(t, result)
|
||||
}
|
||||
|
||||
func TestFetchAsyncAwait(t *testing.T) {
|
||||
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
w.WriteHeader(http.StatusOK)
|
||||
_, _ = w.Write([]byte(`{"status":"ok"}`))
|
||||
}))
|
||||
defer server.Close()
|
||||
|
||||
vm, err := quickjs.NewVM()
|
||||
require.NoError(t, err)
|
||||
defer func() {
|
||||
_ = vm.Close()
|
||||
}()
|
||||
vm.SetCanBlock(true)
|
||||
|
||||
builtin.RegisterBuiltins(context.Background(), vm)
|
||||
|
||||
result, err := vm.Eval(`fetch({input: "`+server.URL+`"})`, quickjs.EvalGlobal)
|
||||
require.NoError(t, err)
|
||||
|
||||
if obj, ok := result.(*quickjs.Object); ok {
|
||||
var arr []any
|
||||
if err := obj.Into(&arr); err == nil && len(arr) > 0 {
|
||||
if response, ok := arr[0].(map[string]any); ok {
|
||||
assert.True(t, response["ok"].(bool))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package standard
|
||||
package stdlib
|
||||
|
||||
import (
|
||||
"context"
|
||||
@@ -8,9 +8,13 @@ import (
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"reichard.io/poiesis/internal/builtin"
|
||||
"reichard.io/poiesis/internal/functions"
|
||||
)
|
||||
|
||||
func init() {
|
||||
functions.RegisterAsyncFunction("fetch", Fetch)
|
||||
}
|
||||
|
||||
type FetchArgs struct {
|
||||
Input string `json:"input"`
|
||||
Init *RequestInit `json:"init,omitempty"`
|
||||
@@ -106,17 +110,3 @@ func Fetch(_ context.Context, args FetchArgs) (Response, error) {
|
||||
Headers: resultHeaders,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func Add(_ context.Context, args AddArgs) (int, error) {
|
||||
return args.A + args.B, nil
|
||||
}
|
||||
|
||||
func Greet(_ context.Context, args GreetArgs) (string, error) {
|
||||
return fmt.Sprintf("Hello, %s!", args.Name), nil
|
||||
}
|
||||
|
||||
func init() {
|
||||
builtin.RegisterAsyncBuiltin("fetch", Fetch)
|
||||
builtin.RegisterBuiltin("add", Add)
|
||||
builtin.RegisterBuiltin("greet", Greet)
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package standard
|
||||
package stdlib
|
||||
|
||||
import (
|
||||
"context"
|
||||
@@ -8,6 +8,8 @@ import (
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"modernc.org/quickjs"
|
||||
"reichard.io/poiesis/internal/functions"
|
||||
)
|
||||
|
||||
func TestFetch(t *testing.T) {
|
||||
@@ -97,24 +99,47 @@ func TestFetchDefaults(t *testing.T) {
|
||||
assert.True(t, result.OK)
|
||||
}
|
||||
|
||||
func TestAdd(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
result, err := Add(ctx, AddArgs{A: 5, B: 10})
|
||||
func TestFetchReturnsPromise(t *testing.T) {
|
||||
vm, err := quickjs.NewVM()
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, 15, result)
|
||||
defer func() {
|
||||
_ = vm.Close()
|
||||
}()
|
||||
vm.SetCanBlock(true)
|
||||
|
||||
result, err = Add(ctx, AddArgs{A: -3, B: 7})
|
||||
functions.RegisterBuiltins(context.Background(), vm)
|
||||
|
||||
result, err := vm.Eval(`fetch({input: "https://example.com"})`, quickjs.EvalGlobal)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, 4, result)
|
||||
assert.NotNil(t, result)
|
||||
}
|
||||
|
||||
func TestGreet(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
result, err := Greet(ctx, GreetArgs{Name: "World"})
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, "Hello, World!", result)
|
||||
func TestFetchAsyncAwait(t *testing.T) {
|
||||
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
w.WriteHeader(http.StatusOK)
|
||||
_, _ = w.Write([]byte(`{"status":"ok"}`))
|
||||
}))
|
||||
defer server.Close()
|
||||
|
||||
result, err = Greet(ctx, GreetArgs{Name: "Alice"})
|
||||
vm, err := quickjs.NewVM()
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, "Hello, Alice!", result)
|
||||
defer func() {
|
||||
_ = vm.Close()
|
||||
}()
|
||||
vm.SetCanBlock(true)
|
||||
|
||||
functions.RegisterBuiltins(context.Background(), vm)
|
||||
|
||||
result, err := vm.Eval(`fetch({input: "`+server.URL+`"})`, quickjs.EvalGlobal)
|
||||
require.NoError(t, err)
|
||||
|
||||
if obj, ok := result.(*quickjs.Object); ok {
|
||||
var arr []any
|
||||
if err := obj.Into(&arr); err == nil && len(arr) > 0 {
|
||||
if response, ok := arr[0].(map[string]any); ok {
|
||||
assert.True(t, response["ok"].(bool))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user