teth
Version:
Functional, reactive, pattern matching based, centralized state tree, open source JS library.
231 lines (228 loc) • 6.56 kB
JavaScript
/* Copyright 2017 Ronny Reichmann */
/* global test expect */
const { match, context } = require('./T') // { match, context, type }
const jsonic = require('jsonic')
test('matcher inline', () => {
const message = {say: 'Hello', to: 'Mr. Smith'}
const result = match(message)
.define({say: 'Hello'}, msg => {
expect(msg).toEqual(message)
return 111
})
.define({say: 'Hi'}, msg => {
expect(false).toBe(true)
return 222
})
.do()
expect(result).toBe(111)
})
test('matcher inline string', () => {
const message = 'say: Hello, to: Mr. Smith'
const result = match(message)
.define('say: Hello', msg => {
expect(msg).toEqual(jsonic(message))
return 333
})
.define('say: Hi', msg => {
expect(false).toBe(true)
return 444
})
.do()
expect(result).toBe(333)
})
test('matcher instance', () => {
const message = {say: 'Hello', to: 'Mr. Smith'}
const matcher = match()
matcher.define({say: 'Hello'}, msg => {
expect(msg).toEqual(message)
return 555
})
matcher.define({say: 'Hi'}, msg => {
expect(false).toBe(true)
return 666
})
expect(matcher.do(message)).toBe(555)
})
test('matcher instance with unknown', () => {
const message = {say: 'Hello', to: 'Mr. Smith'}
const matcher = match()
.define({say: 'Hello'}, msg => {
expect(msg).toEqual(message)
return 555
})
.define({say: 'Hi'}, msg => {
expect(false).toBe(true)
return 666
})
.unknown(msg => 111)
expect(matcher.do(message)).toBe(555)
expect(matcher.do({say: 'OneEleven!'})).toBe(111)
})
test('define and send', done => {
const message = {say: 'Hello', to: 'Mr. Smith'}
const { define, send } = context()
define({say: 'Hello'}, msg => {
expect(msg).toEqual(message)
return 777
})
define({say: 'Hi'}, msg => {
expect(false).toBe(true)
return 888
})
send(message).then(result => {
expect(result).toBe(777)
done()
})
// expect(send(message)).toBe(777)
})
test('define and context define', done => {
const rootMessage = {talk: 'Silently', to: 'Mr. Smith'}
const contextMessage = {talk: 'Loudly', to: 'Subcontext'}
const { define, send } = context()
define({talk: 'Silently'}, msg => {
expect(msg).toEqual(rootMessage)
return 999
})
const subctx = context()
subctx.define({to: 'Subcontext'}, msg => {
expect(msg).toEqual(contextMessage)
return 1111
})
send(rootMessage)
.then(result => {
expect(result).toBe(999)
return subctx.send(contextMessage)
})
.then(result => {
expect(result).toBe(1111)
done()
})
})
test('matcher error', () => {
expect(() => {
match({say: 'Hello', to: 'Mr. Smith'})
.define({say: 'Hi'}, msg => {
expect(false).toBe(true)
})
.do()
}).toThrow()
})
test('matcher unknown', () => {
const message = {say: 'Hello', to: 'Mr. Smith'}
match()
.define({say: 'Hi'}, msg => {
expect(false).toBe(true)
})
.unknown(msg => {
expect(msg).toEqual(message)
})
.do(message)
})
test('define and unknown', () => {
const message = {say: 'Ma shlomcha', to: 'Mar Cohen'}
const { define, send, unknown } = context()
define({say: 'Hello'}, msg => {
expect(false).toBe(true)
})
unknown(msg => {
expect(msg).toEqual(message)
})
send(message)
})
test('matcher doAll', () => {
const results = match()
.define('take: one', msg => msg.payload[2])
.define('take: one', msg => msg.payload[1])
.define('take: one', msg => msg.payload[0])
.doAll({take: 'one', payload: [111, 222, 333]})
expect(results).toEqual([ 333, 222, 111 ])
})
test('define and circular', done => {
const { define, circular } = context()
define('extract: any', msg => msg.list[4])
define('extract: any', msg => msg.list[3])
define('extract: any', msg => msg.list[2])
define('extract: any', msg => msg.list[1])
define('extract: any', msg => msg.list[0])
circular({extract: 'any', list: [10, 20, 30, 40, 50]})
.then(results => {
expect(results).toEqual([ 50, 40, 30, 20, 10 ])
done()
})
})
test('send error', done => {
const ctx = context()
ctx.define('what: ever', msg => false)
ctx.send({content: 'none'})
.then(() => {
expect(true).toBe(false)
done()
})
.catch(() => {
expect(true).toBe(true)
done()
})
})
test('circular error', done => {
const ctx = context()
ctx.define('what: ever', msg => false)
ctx.circular({content: 'none'})
.then(() => {
expect(true).toBe(false)
done()
})
.catch(() => {
expect(true).toBe(true)
done()
})
})
test('simple middlewares', done => {
const ctx = context()
const middleware = (inputMsg, next) => {
const payload = 111 + inputMsg.payload
return next(Object.assign({}, inputMsg, {payload})) + 5
}
const terminator = msg => msg.payload
ctx.define('check: mw', middleware, middleware, middleware, middleware, terminator)
ctx.send('check: mw, payload: 111')
.then(result => {
expect(result).toBe(575)
done()
})
})
test('argument multiplier middleware', () => {
const message = {check: 'middleware', payload: '!11'}
const ctx = context()
const middleware = (msg, next) => {
const result = next(msg, 'hi', 'there', 13)
result[result.length - 1] = result[result.length - 1] + '37'
return result
}
ctx.define('check: middleware', middleware, (msg, arg1, arg2, arg3) => {
return [msg.payload, arg1, arg2, arg3]
})
ctx.send(message)
.then(result => {
expect(result).toEqual([ '!11', 'hi', 'there', '1337' ])
})
})
test('create named contexts', () => {
const instanceA1 = context('instance-a')
const instanceA2 = context('instance-a')
expect(instanceA1).toBeDefined()
expect(instanceA2).toBeDefined()
expect(instanceA1).toBe(instanceA2)
})
// The usefulness of types needs to be discussed
// test('type', () => {
// const Adder = type(
// {var1: /\d+/, var2: /\d+/},
// initData => ({
// add: var3 => initData.var1 + initData.var2 + var3
// })
// )
// const inst = Adder({var1: 3, var2: 5})
// expect(inst.add(7)).toBe(15)
// expect(() => Adder({var3: 3, var4: 5})).toThrow()
// expect(() => Adder({var1: 'one', var2: 'two'})).toThrow()
// })