1
0
mirror of https://github.com/MontFerret/ferret.git synced 2025-03-19 21:28:32 +02:00
ferret/pkg/compiler/compiler_waitfor_event_test.go
Tim Voronov e6dd5689b4
Bugfix/e2e tests (#648)
* Fixed logger level

* Fixed WAITFOR EVENT parser

* Added tracing to Network Manager

* Updated logging

* Swtitched to value type of logger

* Added tracing

* Increased websocket maximum buffer size

* Ignore unimportant error message

* Added support of new CDP API for layouts

* Switched to value type of logger

* Added log level

* Fixed early context cancellation

* Updated example of 'click' action

* Switched to val for elements lookup

* Fixed unit tests

* Refactored 'eval' module

* Fixed SetStyle eval expression

* Fixed style deletion

* Updated logic of setting multiple styles
2021-09-02 11:09:48 -04:00

296 lines
5.9 KiB
Go

package compiler_test
import (
"context"
"github.com/MontFerret/ferret/pkg/compiler"
"github.com/MontFerret/ferret/pkg/runtime"
"github.com/MontFerret/ferret/pkg/runtime/core"
"github.com/MontFerret/ferret/pkg/runtime/events"
"github.com/MontFerret/ferret/pkg/runtime/values"
. "github.com/smartystreets/goconvey/convey"
"testing"
"time"
)
type MockedObservable struct {
*values.Object
subscribers map[string]chan events.Event
Args map[string][]*values.Object
}
func NewMockedObservable() *MockedObservable {
return &MockedObservable{
Object: values.NewObject(),
subscribers: map[string]chan events.Event{},
Args: map[string][]*values.Object{},
}
}
func (m *MockedObservable) Emit(eventName string, args core.Value, err error, timeout int64) {
ch := make(chan events.Event)
m.subscribers[eventName] = ch
go func() {
<-time.After(time.Millisecond * time.Duration(timeout))
ch <- events.Event{
Data: args,
Err: err,
}
}()
}
func (m *MockedObservable) Subscribe(_ context.Context, eventName string, opts *values.Object) <-chan events.Event {
calls, found := m.Args[eventName]
if !found {
calls = make([]*values.Object, 0, 10)
m.Args[eventName] = calls
}
m.Args[eventName] = append(calls, opts)
return m.subscribers[eventName]
}
func newCompilerWithObservable() *compiler.Compiler {
c := compiler.New()
err := c.Namespace("X").
RegisterFunctions(core.NewFunctionsFromMap(
map[string]core.Function{
"CREATE": func(ctx context.Context, args ...core.Value) (core.Value, error) {
return NewMockedObservable(), nil
},
"EMIT": func(ctx context.Context, args ...core.Value) (core.Value, error) {
if err := core.ValidateArgs(args, 2, 3); err != nil {
return values.None, err
}
observable := args[0].(*MockedObservable)
eventName := values.ToString(args[1])
timeout := values.NewInt(100)
if len(args) > 2 {
timeout = values.ToInt(args[2])
}
observable.Emit(eventName.String(), values.None, nil, int64(timeout))
return values.None, nil
},
"EMIT_WITH": func(ctx context.Context, args ...core.Value) (core.Value, error) {
if err := core.ValidateArgs(args, 3, 4); err != nil {
return values.None, err
}
observable := args[0].(*MockedObservable)
eventName := values.ToString(args[1])
timeout := values.NewInt(100)
if len(args) > 3 {
timeout = values.ToInt(args[3])
}
observable.Emit(eventName.String(), args[2], nil, int64(timeout))
return values.None, nil
},
"EVENT": func(ctx context.Context, args ...core.Value) (core.Value, error) {
return values.NewString("test"), nil
},
},
))
So(err, ShouldBeNil)
return c
}
func TestWaitforEventExpression(t *testing.T) {
Convey("WAITFOR EVENT parser", t, func() {
Convey("Should parse", func() {
c := newCompilerWithObservable()
_, err := c.Compile(`
LET obj = X::CREATE()
X::EMIT(obj, "test", 100)
WAITFOR EVENT "test" IN obj
RETURN NONE
`)
So(err, ShouldBeNil)
})
Convey("Should parse 2", func() {
c := newCompilerWithObservable()
_, err := c.Compile(`
LET obj = X::CREATE()
X::EMIT(obj, "test", 100)
WAITFOR EVENT "test" IN obj 1000
RETURN NONE
`)
So(err, ShouldBeNil)
})
Convey("Should parse 3", func() {
c := newCompilerWithObservable()
_, err := c.Compile(`
LET obj = X::CREATE()
X::EMIT(obj, "test", 100)
LET timeout = 1000
WAITFOR EVENT "test" IN obj timeout
RETURN NONE
`)
So(err, ShouldBeNil)
})
Convey("Should parse 4", func() {
c := newCompilerWithObservable()
_, err := c.Compile(`
LET obj = X::CREATE()
X::EMIT(obj, "test", 100)
LET timeout = 1000
WAITFOR EVENT "test" IN obj timeout
X::EMIT(obj, "test", 100)
RETURN NONE
`)
So(err, ShouldBeNil)
})
})
Convey("WAITFOR EVENT X IN Y runtime", t, func() {
Convey("Should wait for a given event", func() {
c := newCompilerWithObservable()
prog := c.MustCompile(`
LET obj = X::CREATE()
X::EMIT(obj, "test", 100)
WAITFOR EVENT "test" IN obj
RETURN NONE
`)
_, err := prog.Run(context.Background())
So(err, ShouldBeNil)
})
Convey("Should wait for a given event using variable", func() {
c := newCompilerWithObservable()
prog := c.MustCompile(`
LET obj = X::CREATE()
LET eventName = "test"
X::EMIT(obj, eventName, 100)
WAITFOR EVENT eventName IN obj
RETURN NONE
`)
_, err := prog.Run(context.Background())
So(err, ShouldBeNil)
})
Convey("Should wait for a given event using object", func() {
c := newCompilerWithObservable()
prog := c.MustCompile(`
LET obj = X::CREATE()
LET evt = {
name: "test"
}
X::EMIT(obj, evt.name, 100)
WAITFOR EVENT evt.name IN obj
RETURN NONE
`)
_, err := prog.Run(context.Background())
So(err, ShouldBeNil)
})
Convey("Should wait for a given event using param", func() {
c := newCompilerWithObservable()
prog := c.MustCompile(`
LET obj = X::CREATE()
X::EMIT(obj, @evt, 100)
WAITFOR EVENT @evt IN obj
RETURN NONE
`)
_, err := prog.Run(context.Background(), runtime.WithParam("evt", "test"))
So(err, ShouldBeNil)
})
Convey("Should use options", func() {
observable := NewMockedObservable()
c := newCompilerWithObservable()
c.Namespace("X").RegisterFunction("SINGLETONE", func(ctx context.Context, args ...core.Value) (core.Value, error) {
return observable, nil
})
prog := c.MustCompile(`
LET obj = X::SINGLETONE()
X::EMIT(obj, "test", 1000)
WAITFOR EVENT "test" IN obj OPTIONS { value: "foo" }
RETURN NONE
`)
_, err := prog.Run(context.Background())
So(err, ShouldBeNil)
options := observable.Args["test"][0]
So(options, ShouldNotBeNil)
So(options.MustGet("value").String(), ShouldEqual, "foo")
})
Convey("Should timeout", func() {
c := newCompilerWithObservable()
prog := c.MustCompile(`
LET obj = X::CREATE()
X::EMIT(obj, @evt, 6000)
WAITFOR EVENT @evt IN obj
RETURN NONE
`)
_, err := prog.Run(context.Background(), runtime.WithParam("evt", "test"))
So(err, ShouldNotBeNil)
})
})
}