initial commit
This commit is contained in:
163
internal/runtime/runtime_test.go
Normal file
163
internal/runtime/runtime_test.go
Normal file
@@ -0,0 +1,163 @@
|
||||
package runtime
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"os"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/fastschema/qjs"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"reichard.io/poiesis/internal/functions"
|
||||
)
|
||||
|
||||
type TestArgs struct {
|
||||
Field1 string `json:"field1"`
|
||||
}
|
||||
|
||||
func (t TestArgs) Validate() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func TestExecuteTypeScript(t *testing.T) {
|
||||
// Create Buffers
|
||||
var stdout, stderr bytes.Buffer
|
||||
|
||||
// Create Runtime
|
||||
rt, err := New(context.Background(), WithStderr(&stderr), WithStdout(&stdout))
|
||||
assert.NoError(t, err, "Expected no error")
|
||||
|
||||
// Create TypeScript Code
|
||||
tsCode := `interface Person {
|
||||
name: string;
|
||||
age: number;
|
||||
email: string;
|
||||
}
|
||||
|
||||
function greet(person: Person): string {
|
||||
return "Hello, " + person.name + "! You are " + person.age + " years old.";
|
||||
}
|
||||
|
||||
const user: Person = {
|
||||
name: "Alice",
|
||||
age: 30,
|
||||
email: "alice@example.com",
|
||||
};
|
||||
|
||||
console.log(greet(user));
|
||||
console.log("Email: " + user.email);
|
||||
|
||||
function calculateSum(a: number, b: number): number {
|
||||
return a + b;
|
||||
}
|
||||
|
||||
console.log("Sum of 5 and 10 is: " + calculateSum(5, 10));
|
||||
`
|
||||
|
||||
// Create Temp File
|
||||
tmpFile, err := os.CreateTemp("", "*.ts")
|
||||
assert.NoError(t, err, "Failed to create temp file")
|
||||
t.Cleanup(func() {
|
||||
_ = os.Remove(tmpFile.Name())
|
||||
})
|
||||
|
||||
// Write Code to File
|
||||
_, err = tmpFile.WriteString(tsCode)
|
||||
assert.NoError(t, err, "Failed to write to temp file")
|
||||
err = tmpFile.Close()
|
||||
assert.NoError(t, err, "Failed to close temp file")
|
||||
|
||||
// Run File
|
||||
err = rt.RunFile(tmpFile.Name())
|
||||
|
||||
// Verify Execution
|
||||
assert.NoError(t, err, "Expected no error")
|
||||
assert.Empty(t, stderr.String(), "Expected no error output")
|
||||
|
||||
// Verify Output
|
||||
output := stdout.String()
|
||||
assert.Contains(t, output, "Hello, Alice!", "Should greet Alice")
|
||||
assert.Contains(t, output, "You are 30 years old", "Should show age")
|
||||
assert.Contains(t, output, "Email: alice@example.com", "Should show email")
|
||||
assert.Contains(t, output, "Sum of 5 and 10 is: 15", "Should calculate sum correctly")
|
||||
|
||||
// Verify Line Count
|
||||
lines := strings.Split(strings.TrimSpace(output), "\n")
|
||||
assert.GreaterOrEqual(t, len(lines), 3, "Should have at least 3 output lines")
|
||||
}
|
||||
|
||||
func TestAsyncFunctionResolution(t *testing.T) {
|
||||
// Register Async Function
|
||||
functions.RegisterAsyncFunction("resolveTest", func(_ context.Context, args TestArgs) (string, error) {
|
||||
return "test-result", nil
|
||||
})
|
||||
|
||||
// Create Runtime
|
||||
r, err := New(context.Background())
|
||||
require.NoError(t, err)
|
||||
|
||||
// Execute Async Function - Must be awaited in async context
|
||||
result, err := r.ctx.Eval("test.js", qjs.Code(`async function run() { return await resolveTest("hello"); }; run()`))
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, result)
|
||||
defer result.Free()
|
||||
|
||||
// Verify Result
|
||||
assert.Equal(t, "test-result", result.String())
|
||||
}
|
||||
|
||||
func TestAsyncFunctionRejection(t *testing.T) {
|
||||
// Register Async Function that Returns Error
|
||||
functions.RegisterAsyncFunction("rejectTest", func(_ context.Context, args TestArgs) (string, error) {
|
||||
return "", assert.AnError
|
||||
})
|
||||
|
||||
// Create Runtime
|
||||
r, err := New(context.Background())
|
||||
require.NoError(t, err)
|
||||
|
||||
// Execute Async Function - Rejected Promises Throw When Awaited
|
||||
_, err = r.ctx.Eval("test.js", qjs.Code(`async function run() { return await rejectTest("hello"); }; run()`))
|
||||
assert.Error(t, err)
|
||||
}
|
||||
|
||||
func TestNonPromise(t *testing.T) {
|
||||
// Register Sync Function
|
||||
functions.RegisterFunction("nonPromiseTest", func(_ context.Context, args TestArgs) (string, error) {
|
||||
return "sync-result", nil
|
||||
})
|
||||
|
||||
// Create Runtime
|
||||
r, err := New(context.Background())
|
||||
assert.NoError(t, err)
|
||||
|
||||
// Execute Sync Function
|
||||
result, err := r.ctx.Eval("test.js", qjs.Code(`nonPromiseTest("hello")`))
|
||||
assert.NoError(t, err)
|
||||
defer result.Free()
|
||||
|
||||
// Verify Result
|
||||
assert.Equal(t, "sync-result", result.String())
|
||||
}
|
||||
|
||||
func TestGetTypeDeclarations(t *testing.T) {
|
||||
// Register Function
|
||||
functions.RegisterFunction("testFunc", func(_ context.Context, args TestArgs) (string, error) {
|
||||
return "result", nil
|
||||
})
|
||||
|
||||
// Create Runtime
|
||||
r, err := New(context.Background())
|
||||
require.NoError(t, err)
|
||||
|
||||
// Get Type Declarations
|
||||
decls := r.GetTypeDeclarations()
|
||||
|
||||
// Verify Declarations
|
||||
assert.Contains(t, decls, "interface TestArgs")
|
||||
assert.Contains(t, decls, "declare function testFunc")
|
||||
assert.Contains(t, decls, "field1: string")
|
||||
}
|
||||
Reference in New Issue
Block a user