import { Bind, BindTo, Do, Effect, Label, Noop, Pure, Seq, } from '../stdlib/effect' import { Throw, Try } from '../stdlib/exception' import { PutStringLn } from '../stdlib/stdio' import { DefineEffect, JsExpr, SetEvalEnvironment } from '../stdlib/sys' import { Test, AssertEqualsK, AssertEquals } from '../stdlib/test' interface MyEffect<_a extends number, _b extends string, _c extends unknown> extends Effect {} export type main = [ SetEvalEnvironment<'test.node'>, PutStringLn<'====================='>, PutStringLn<'=== Running tests ==='>, PutStringLn<'=====================\n\n'>, testDo, testSeq, testBind, testException, testFFI, PutStringLn<''> ] type testSeq = Do< [ PutStringLn<'Seq'>, Test< 'should run a sequence of effects and all results', [ BindTo<'result', Seq<[Pure<1>, Pure<2>, Pure<3>, Pure<4>]>>, Bind, AssertEqualsK<[1, 2, 3, 4]>> ] >, Test< 'should produce undefined for effects with no result', [ BindTo<'result', Seq<[Pure<1>, Noop, Pure<3>, Noop]>>, Bind, AssertEqualsK<[1, undefined, 3, undefined]>> ] > ] > type testDo = Do< [ PutStringLn<'Do'>, Test< 'should run a sequence of effects and return the last effect', [ BindTo<'result', Do<[Pure<1>, Pure<2>, Pure<3>, Pure<4>]>>, Bind, AssertEqualsK<4>> ] >, Test< 'should return undefined if last effect doesnt produce a result', [ BindTo<'result', Do<[Pure<1>, Noop, Pure<3>, Noop]>>, Bind, AssertEqualsK> ] > ] > type testBind = Do< [ PutStringLn<'Bind & BindTo'>, Test< 'should bind value to function and kind', [ Bind< Pure<[1, 2, 3]>, () => AssertEquals >, Bind, AssertEqualsK<[1, 2, 3]>> ] >, Test< 'should bind label correctly', [ BindTo<'value', Pure<{ a: 'b'; c: { d: 1 } }>>, Bind, AssertEqualsK<{ a: 'b'; c: { d: 1 } }>> ] >, Test< 'should bind only inside Do scope', [ Do< [ BindTo<'value', Pure<'some value'>>, Bind, AssertEqualsK<'some value'>> ] >, Bind, <_>() => Pure<'none'>>, AssertEqualsK<'none'>> ] >, Test< 'should bind only inside Bind scope', [ Bind< BindTo<'value', Pure<'some value'>>, <_>() => Bind, AssertEqualsK<'some value'>> >, Bind, <_>() => Pure<'none'>>, AssertEqualsK<'none'>> ] > ] > type testException = Do< [ PutStringLn<'Try/Throw'>, Test< 'should return the result of effect', [Bind, <_>() => Pure<0>>, AssertEqualsK<20>>] >, Test< 'should return the result of error handler', [ Bind< Try, Pure<20>]>, <_>() => Pure<0>>, AssertEqualsK<0> >, Bind< Try, Pure<20>]>, () => Pure>, AssertEqualsK<'wow'> > ] > ] > type testFFI = Do< [ PutStringLn<'FFI'>, Test< 'should return the result of js expression', [Bind, AssertEqualsK<28980>>] >, Test< 'should test custom effect', [ DefineEffect< 'MyEffect', `([a, b, c], ctx) => { return [ ctx.getTypeValue(a) * 2, ctx.getTypeValue(b) + '!', [...ctx.getTypeValue(c), 'wow'], ] }` >, Bind< MyEffect<4, 'hey', [1, 2]>, AssertEqualsK<[8, 'hey!', [1, 2, 'wow']]> > ] > ] >