mirror of
https://github.com/syumai/workers.git
synced 2025-03-10 17:29:11 +00:00
212 lines
5.9 KiB
Go
212 lines
5.9 KiB
Go
package queues
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"syscall/js"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/syumai/workers/internal/jsutil"
|
|
)
|
|
|
|
func validatingProducer(t *testing.T, validateFn func(message js.Value, options js.Value) error) *Producer {
|
|
sendFn := js.FuncOf(func(this js.Value, args []js.Value) interface{} {
|
|
sendArg := args[0] // this should be batch (in case of SendBatch) or a single message (in case of Send)
|
|
var options js.Value
|
|
if len(args) > 1 {
|
|
options = args[1]
|
|
}
|
|
return jsutil.NewPromise(js.FuncOf(func(this js.Value, args []js.Value) interface{} {
|
|
resolve := args[0]
|
|
go func() {
|
|
if err := validateFn(sendArg, options); err != nil {
|
|
// must be non-fatal to avoid a deadlock
|
|
t.Errorf("validation failed: %v", err)
|
|
}
|
|
resolve.Invoke(js.Undefined())
|
|
}()
|
|
return js.Undefined()
|
|
}))
|
|
})
|
|
|
|
queue := jsutil.NewObject()
|
|
queue.Set("send", sendFn)
|
|
queue.Set("sendBatch", sendFn)
|
|
|
|
return &Producer{queue: queue}
|
|
}
|
|
|
|
func TestSend(t *testing.T) {
|
|
t.Run("text content type", func(t *testing.T) {
|
|
validation := func(message js.Value, options js.Value) error {
|
|
if message.Type() != js.TypeString {
|
|
return errors.New("message body must be a string")
|
|
}
|
|
if message.String() != "hello" {
|
|
return errors.New("message body must be 'hello'")
|
|
}
|
|
if options.Get("contentType").String() != "text" {
|
|
return errors.New("content type must be text")
|
|
}
|
|
return nil
|
|
}
|
|
|
|
producer := validatingProducer(t, validation)
|
|
err := producer.Send("hello", WithContentType(QueueContentTypeText))
|
|
if err != nil {
|
|
t.Fatalf("Send failed: %v", err)
|
|
}
|
|
})
|
|
|
|
t.Run("json content type", func(t *testing.T) {
|
|
validation := func(message js.Value, options js.Value) error {
|
|
if message.Type() != js.TypeString {
|
|
return errors.New("message body must be a string")
|
|
}
|
|
if message.String() != "hello" {
|
|
return errors.New("message body must be 'hello'")
|
|
}
|
|
if options.Get("contentType").String() != "json" {
|
|
return errors.New("content type must be json")
|
|
}
|
|
return nil
|
|
}
|
|
|
|
producer := validatingProducer(t, validation)
|
|
err := producer.Send("hello", WithContentType(QueueContentTypeJSON))
|
|
if err != nil {
|
|
t.Fatalf("Send failed: %v", err)
|
|
}
|
|
})
|
|
}
|
|
|
|
func TestSend_ContentTypeOption(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
options []SendOption
|
|
expectedContentType string
|
|
expectedDelaySec int
|
|
wantErr bool
|
|
}{
|
|
{
|
|
name: "text",
|
|
options: []SendOption{WithContentType(QueueContentTypeText)},
|
|
expectedContentType: "text",
|
|
},
|
|
{
|
|
name: "json",
|
|
options: []SendOption{WithContentType(QueueContentTypeJSON)},
|
|
expectedContentType: "json",
|
|
},
|
|
{
|
|
name: "default",
|
|
options: nil,
|
|
expectedContentType: "json",
|
|
},
|
|
{
|
|
name: "v8",
|
|
options: []SendOption{WithContentType(QueueContentTypeV8)},
|
|
expectedContentType: "v8",
|
|
},
|
|
{
|
|
name: "bytes",
|
|
options: []SendOption{WithContentType(QueueContentTypeBytes)},
|
|
expectedContentType: "bytes",
|
|
},
|
|
|
|
{
|
|
name: "delay",
|
|
options: []SendOption{WithDelay(5 * time.Second)},
|
|
expectedDelaySec: 5,
|
|
expectedContentType: "json",
|
|
},
|
|
|
|
{
|
|
name: "invalid content type",
|
|
options: []SendOption{WithContentType("invalid")},
|
|
wantErr: true,
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
validation := func(message js.Value, options js.Value) error {
|
|
gotCT := options.Get("contentType").String()
|
|
if gotCT != string(tt.expectedContentType) {
|
|
return fmt.Errorf("expected content type %q, got %q", tt.expectedContentType, gotCT)
|
|
}
|
|
gotDelaySec := jsutil.MaybeInt(options.Get("delaySeconds"))
|
|
if gotDelaySec != tt.expectedDelaySec {
|
|
return fmt.Errorf("expected delay %d, got %d", tt.expectedDelaySec, gotDelaySec)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
producer := validatingProducer(t, validation)
|
|
err := producer.Send("hello", tt.options...)
|
|
if (err != nil) != tt.wantErr {
|
|
t.Fatalf("expected error: %t, got %v", tt.wantErr, err)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestSendBatch_Defaults(t *testing.T) {
|
|
validation := func(batch js.Value, options js.Value) error {
|
|
if batch.Type() != js.TypeObject {
|
|
return errors.New("message batch must be an object (array)")
|
|
}
|
|
if batch.Length() != 2 {
|
|
return fmt.Errorf("expected 2 messages, got %d", batch.Length())
|
|
}
|
|
first := batch.Index(0)
|
|
if first.Get("body").String() != "hello" {
|
|
return fmt.Errorf("first message body must be 'hello', was %s", first.Get("body"))
|
|
}
|
|
if first.Get("options").Get("contentType").String() != "json" {
|
|
return fmt.Errorf("first message content type must be json, was %s", first.Get("options").Get("contentType"))
|
|
}
|
|
|
|
second := batch.Index(1)
|
|
if second.Get("body").String() != "world" {
|
|
return fmt.Errorf("second message body must be 'world', was %s", second.Get("body"))
|
|
}
|
|
if second.Get("options").Get("contentType").String() != "text" {
|
|
return fmt.Errorf("second message content type must be text, was %s", second.Get("options").Get("contentType"))
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
var batch []*BatchMessage = []*BatchMessage{
|
|
NewBatchMessage("hello"),
|
|
NewBatchMessage("world", WithContentType(QueueContentTypeText)),
|
|
}
|
|
|
|
producer := validatingProducer(t, validation)
|
|
err := producer.SendBatch(batch)
|
|
if err != nil {
|
|
t.Fatalf("SendBatch failed: %v", err)
|
|
}
|
|
}
|
|
|
|
func TestSendBatch_Options(t *testing.T) {
|
|
validation := func(_ js.Value, options js.Value) error {
|
|
if options.Get("delaySeconds").Int() != 5 {
|
|
return fmt.Errorf("expected delay 5, got %d", options.Get("delaySeconds").Int())
|
|
}
|
|
return nil
|
|
}
|
|
|
|
var batch []*BatchMessage = []*BatchMessage{
|
|
NewBatchMessage("hello"),
|
|
}
|
|
|
|
producer := validatingProducer(t, validation)
|
|
err := producer.SendBatch(batch, WithBatchDelay(5*time.Second))
|
|
if err != nil {
|
|
t.Fatalf("SendBatch failed: %v", err)
|
|
}
|
|
}
|