package expressions_test import ( "context" "github.com/MontFerret/ferret/pkg/runtime/core" "github.com/MontFerret/ferret/pkg/runtime/events" "github.com/MontFerret/ferret/pkg/runtime/expressions" "github.com/MontFerret/ferret/pkg/runtime/expressions/literals" "testing" "time" . "github.com/smartystreets/goconvey/convey" "github.com/MontFerret/ferret/pkg/runtime/values" ) 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 TestWaitForEventExpression(t *testing.T) { Convey("Should create a return expression", t, func() { variable, err := expressions.NewVariableExpression(core.NewSourceMap("test", 1, 10), "test") So(err, ShouldBeNil) sourceMap := core.NewSourceMap("test", 2, 10) expression, err := expressions.NewWaitForEventExpression( sourceMap, literals.NewStringLiteral("test"), variable, nil, nil, ) So(err, ShouldBeNil) So(expression, ShouldNotBeNil) }) Convey("Should wait for an event", t, func() { mock := NewMockedObservable() eventName := "foobar" variable, err := expressions.NewVariableExpression( core.NewSourceMap("test", 1, 10), "observable", ) So(err, ShouldBeNil) sourceMap := core.NewSourceMap("test", 2, 10) expression, err := expressions.NewWaitForEventExpression( sourceMap, literals.NewStringLiteral(eventName), variable, nil, nil, ) So(err, ShouldBeNil) scope, _ := core.NewRootScope() So(scope.SetVariable("observable", mock), ShouldBeNil) mock.Emit(eventName, values.None, nil, 100) _, err = expression.Exec(context.Background(), scope) So(err, ShouldBeNil) }) Convey("Should receive opts", t, func() { mock := NewMockedObservable() eventName := "foobar" variable, err := expressions.NewVariableExpression( core.NewSourceMap("test", 1, 10), "observable", ) So(err, ShouldBeNil) prop, err := literals.NewObjectPropertyAssignment( literals.NewStringLiteral("value"), literals.NewStringLiteral("bar"), ) So(err, ShouldBeNil) sourceMap := core.NewSourceMap("test", 2, 10) expression, err := expressions.NewWaitForEventExpression( sourceMap, literals.NewStringLiteral(eventName), variable, literals.NewObjectLiteralWith(prop), nil, ) So(err, ShouldBeNil) scope, _ := core.NewRootScope() So(scope.SetVariable("observable", mock), ShouldBeNil) mock.Emit(eventName, values.None, nil, 100) _, err = expression.Exec(context.Background(), scope) So(err, ShouldBeNil) opts := mock.Args[eventName][0] So(opts, ShouldNotBeNil) }) Convey("Should return event arg", t, func() { mock := NewMockedObservable() eventName := "foobar" variable, err := expressions.NewVariableExpression( core.NewSourceMap("test", 1, 10), "observable", ) So(err, ShouldBeNil) sourceMap := core.NewSourceMap("test", 2, 10) expression, err := expressions.NewWaitForEventExpression( sourceMap, literals.NewStringLiteral(eventName), variable, nil, nil, ) So(err, ShouldBeNil) scope, _ := core.NewRootScope() So(scope.SetVariable("observable", mock), ShouldBeNil) arg := values.NewString("foo") mock.Emit(eventName, arg, nil, 100) out, err := expression.Exec(context.Background(), scope) So(err, ShouldBeNil) So(out.String(), ShouldEqual, arg.String()) }) Convey("Should timeout", t, func() { mock := NewMockedObservable() eventName := "foobar" variable, err := expressions.NewVariableExpression( core.NewSourceMap("test", 1, 10), "observable", ) So(err, ShouldBeNil) sourceMap := core.NewSourceMap("test", 2, 10) expression, err := expressions.NewWaitForEventExpression( sourceMap, literals.NewStringLiteral(eventName), variable, nil, nil, ) So(err, ShouldBeNil) scope, _ := core.NewRootScope() So(scope.SetVariable("observable", mock), ShouldBeNil) _, err = expression.Exec(context.Background(), scope) So(err, ShouldNotBeNil) }) }