230 lines
4.9 KiB
Go
230 lines
4.9 KiB
Go
package goja_bindings_test
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"os"
|
|
"seanime/internal/extension"
|
|
"seanime/internal/extension_repo"
|
|
"seanime/internal/util"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/dop251/goja"
|
|
"github.com/dop251/goja/parser"
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
func setupTestVM(t *testing.T) *goja.Runtime {
|
|
vm := goja.New()
|
|
vm.SetParserOptions(parser.WithDisableSourceMaps)
|
|
// Bind the shared bindings
|
|
extension_repo.ShareBinds(vm, util.NewLogger())
|
|
fm := extension_repo.FieldMapper{}
|
|
vm.SetFieldNameMapper(fm)
|
|
return vm
|
|
}
|
|
|
|
func divide(a, b float64) (float64, error) {
|
|
if b == 0 {
|
|
return 0, errors.New("division by zero")
|
|
}
|
|
return a / b, nil
|
|
}
|
|
|
|
func TestDivideFunction(t *testing.T) {
|
|
vm := goja.New()
|
|
vm.Set("divide", divide)
|
|
|
|
// Case 1: Successful division
|
|
result, err := vm.RunString("divide(10, 3);")
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, 3.3333333333333335, result.Export())
|
|
|
|
// Case 2: Division by zero should throw an exception
|
|
_, err = vm.RunString("divide(10, 0);")
|
|
assert.Error(t, err)
|
|
assert.Contains(t, err.Error(), "division by zero")
|
|
|
|
// Case 3: Handling error with try-catch in JS
|
|
result, err = vm.RunString(`
|
|
try {
|
|
divide(10, 0);
|
|
} catch (e) {
|
|
e.toString();
|
|
}
|
|
`)
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, "GoError: division by zero", result.Export())
|
|
}
|
|
|
|
func multipleReturns() (int, string, float64) {
|
|
return 42, "hello", 3.14
|
|
}
|
|
|
|
func TestMultipleReturns(t *testing.T) {
|
|
vm := goja.New()
|
|
vm.Set("multiReturn", multipleReturns)
|
|
|
|
v, err := vm.RunString("multiReturn();")
|
|
assert.NoError(t, err)
|
|
util.Spew(v.Export())
|
|
}
|
|
|
|
func TestUserConfig(t *testing.T) {
|
|
vm := setupTestVM(t)
|
|
defer vm.ClearInterrupt()
|
|
|
|
ext := &extension.Extension{
|
|
UserConfig: &extension.UserConfig{
|
|
Fields: []extension.ConfigField{
|
|
{
|
|
Name: "test",
|
|
},
|
|
{
|
|
Name: "test2",
|
|
Default: "Default value",
|
|
},
|
|
},
|
|
},
|
|
SavedUserConfig: &extension.SavedUserConfig{
|
|
Values: map[string]string{
|
|
"test": "Hello World!",
|
|
},
|
|
},
|
|
}
|
|
extension_repo.ShareBinds(vm, util.NewLogger())
|
|
extension_repo.BindUserConfig(vm, ext, util.NewLogger())
|
|
|
|
vm.RunString(`
|
|
const result = $getUserPreference("test");
|
|
console.log(result);
|
|
|
|
const result2 = $getUserPreference("test2");
|
|
console.log(result2);
|
|
`)
|
|
}
|
|
|
|
func TestByteSliceToUint8Array(t *testing.T) {
|
|
// Initialize a new Goja VM
|
|
vm := goja.New()
|
|
|
|
// Create a Go byte slice
|
|
data := []byte("hello")
|
|
|
|
// Set the byte slice in the Goja VM
|
|
vm.Set("data", data)
|
|
|
|
extension_repo.ShareBinds(vm, util.NewLogger())
|
|
|
|
// JavaScript code to verify the type and contents of 'data'
|
|
jsCode := `
|
|
console.log(typeof data, data);
|
|
|
|
const dataArrayBuffer = new ArrayBuffer(5);
|
|
const uint8Array = new Uint8Array(dataArrayBuffer);
|
|
uint8Array[0] = 104;
|
|
uint8Array[1] = 101;
|
|
uint8Array[2] = 108;
|
|
uint8Array[3] = 108;
|
|
uint8Array[4] = 111;
|
|
console.log(typeof uint8Array, uint8Array);
|
|
|
|
console.log("toString", $toString(uint8Array));
|
|
console.log("toString", uint8Array.toString());
|
|
|
|
|
|
true; // Return true if all checks pass
|
|
`
|
|
|
|
// Run the JavaScript code in the Goja VM
|
|
result, err := vm.RunString(jsCode)
|
|
if err != nil {
|
|
t.Fatalf("JavaScript error: %v", err)
|
|
}
|
|
|
|
// Assert that the result is true
|
|
assert.Equal(t, true, result.Export())
|
|
}
|
|
|
|
func TestGojaDocument(t *testing.T) {
|
|
vm := setupTestVM(t)
|
|
defer vm.ClearInterrupt()
|
|
|
|
tests := []struct {
|
|
entry string
|
|
}{
|
|
{entry: "./js/test/doc-example.ts"},
|
|
{entry: "./js/test/doc-example-2.ts"},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.entry, func(t *testing.T) {
|
|
fileB, err := os.ReadFile(tt.entry)
|
|
require.NoError(t, err)
|
|
|
|
now := time.Now()
|
|
|
|
source, err := extension_repo.JSVMTypescriptToJS(string(fileB))
|
|
require.NoError(t, err)
|
|
|
|
_, err = vm.RunString(source)
|
|
require.NoError(t, err)
|
|
|
|
_, err = vm.RunString(`function NewProvider() { return new Provider() }`)
|
|
require.NoError(t, err)
|
|
|
|
newProviderFunc, ok := goja.AssertFunction(vm.Get("NewProvider"))
|
|
require.True(t, ok)
|
|
|
|
classObjVal, err := newProviderFunc(goja.Undefined())
|
|
require.NoError(t, err)
|
|
|
|
classObj := classObjVal.ToObject(vm)
|
|
|
|
testFunc, ok := goja.AssertFunction(classObj.Get("test"))
|
|
require.True(t, ok)
|
|
|
|
ret, err := testFunc(classObj)
|
|
require.NoError(t, err)
|
|
|
|
promise := ret.Export().(*goja.Promise)
|
|
|
|
for promise.State() == goja.PromiseStatePending {
|
|
time.Sleep(10 * time.Millisecond)
|
|
}
|
|
|
|
if promise.State() == goja.PromiseStateFulfilled {
|
|
t.Logf("Fulfilled: %v", promise.Result())
|
|
} else {
|
|
t.Fatalf("Rejected: %v", promise.Result())
|
|
}
|
|
|
|
fmt.Println(time.Since(now).Seconds())
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestOptionalParams(t *testing.T) {
|
|
vm := setupTestVM(t)
|
|
defer vm.ClearInterrupt()
|
|
|
|
type Options struct {
|
|
Add int `json:"add"`
|
|
}
|
|
|
|
vm.Set("test", func(a int, opts Options) int {
|
|
fmt.Println("opts", opts)
|
|
return a + opts.Add
|
|
})
|
|
|
|
vm.RunString(`
|
|
const result = test(1);
|
|
console.log(result);
|
|
|
|
const result2 = test(1, { add: 10 });
|
|
console.log(result2);
|
|
`)
|
|
}
|