package esm_test import ( "context" "errors" "strings" "testing" "git.fsdpf.net/go/jscriptx" ) // async 方法要能像同步方法一样用:Promise 由本库解包,不泄漏 goja 类型。 func TestAsync_自动解包(t *testing.T) { e := newEngine(t, "testdata/app/src") ctx := context.Background() obj, err := e.New(ctx, "Async/AsyncController") if err != nil { t.Fatal(err) } defer obj.Close() for _, c := range []struct{ fn, want string }{ {"Sync", "同步结果"}, {"Async", "异步结果"}, {"AwaitSomething", "await 的结果"}, } { got, err := obj.Call(ctx, c.fn) if err != nil { t.Errorf("%s 失败: %v", c.fn, err) continue } if got != c.want { t.Errorf("%s = %#v, want %q", c.fn, got, c.want) } } // CallInto 也要解包 var s string if err := obj.CallInto(ctx, "Async", &s); err != nil { t.Fatalf("CallInto 失败: %v", err) } if s != "异步结果" { t.Errorf("CallInto = %q", s) } } // async 方法抛异常(Promise reject)要变成正常的 Go error。 func TestAsync_reject转成错误(t *testing.T) { e := newEngine(t, "testdata/app/src") ctx := context.Background() obj, err := e.New(ctx, "Async/AsyncController") if err != nil { t.Fatal(err) } defer obj.Close() _, err = obj.Call(ctx, "Fails") if err == nil { t.Fatal("应该报错") } if !errors.Is(err, jscriptx.ErrPromiseRejected) { t.Errorf("want ErrPromiseRejected, got %v", err) } var jsErr *jscriptx.Error if errors.As(err, &jsErr) && !strings.Contains(jsErr.Msg, "异步失败") { t.Errorf("没带上 reject 的原因: %q", jsErr.Msg) } t.Logf("%v", err) } // goja 没有事件循环,等待真正的异步会让 Promise 永远 pending,要报清楚。 func TestAsync_永不完成的Promise(t *testing.T) { e := newEngine(t, "testdata/app/src") ctx := context.Background() obj, err := e.New(ctx, "Async/AsyncController") if err != nil { t.Fatal(err) } defer obj.Close() _, err = obj.Call(ctx, "Never") if !errors.Is(err, jscriptx.ErrPromisePending) { t.Fatalf("want ErrPromisePending, got %v", err) } var jsErr *jscriptx.Error errors.As(err, &jsErr) if !strings.Contains(jsErr.Msg, "事件循环") { t.Errorf("报错没解释原因: %q", jsErr.Msg) } t.Logf("%v", jsErr.Msg) }