Last active
October 30, 2018 08:05
-
-
Save artalar/8dea5a6540e4d8b0cec90ab6df89f609 to your computer and use it in GitHub Desktop.
stm-5.js
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| const lib = require('../index'); | |
| // ------------------------------------ | |
| // -------------- HELPERS ------------- | |
| // ------------------------------------ | |
| const EFFECT_STATUS = { | |
| idle: 'IDLE', | |
| req: 'REQUEST', | |
| res: 'RESPONSE', | |
| err: 'ERROR', | |
| }; | |
| const createEffect = request => { | |
| const node = lib.createNode({ | |
| // `reset` - call when initiate | |
| reset: () => ({ status: EFFECT_STATUS.idle, payload: null, error: null }), | |
| req: payload => ({ status: EFFECT_STATUS.req, payload, error: null }), | |
| res: payload => ({ status: EFFECT_STATUS.res, payload, error: null }), | |
| err: error => ({ status: EFFECT_STATUS.err, payload: null, error }), | |
| }); | |
| const effect = async payload => { | |
| node.req(payload); | |
| try { | |
| const response = await request(payload); | |
| if (node.get().status !== EFFECT_STATUS.req) { | |
| /* concurrency */ return; | |
| } else { | |
| node.res(response); | |
| } | |
| } catch (error) { | |
| node.err(error); | |
| } | |
| }; | |
| // `toString` return unique node id with dynamic counter | |
| // it is mean you can use many times `({ [effect]: some1, [effect]: some2 })` | |
| // and `[effect]` properties will difference | |
| effect.toString = node.toString(); | |
| effect.on = predicate => mod => ({ | |
| [effect]: { | |
| if: predicate, | |
| mod, | |
| }, | |
| }); | |
| effect.onResponse = effect.on(({ status }) => status === EFFECT_STATUS.res); | |
| effect.onRequest = effect.on(({ status }) => status === EFFECT_STATUS.req); | |
| effect.onError = effect.on(({ status }) => status === EFFECT_STATUS.err); | |
| return effect; | |
| }; | |
| // ------------------------------------ | |
| // ------------- TESTS ---------------- | |
| // ------------------------------------ | |
| const api = { | |
| getUser() { | |
| return new Promise(r => setTimeout(r, 150, { name: 'Tom Sawyer', age: 12 })); | |
| }, | |
| }; | |
| describe('createNode', () => { | |
| it('individual subscribers by selectors', () => {}); | |
| it('computed subscribe calls one time', async () => { | |
| const getUser = createEffect(api.getUser); | |
| // you can use `Object.assign` instead spread | |
| // `reset` - call when initiate | |
| const userData = createNode({ | |
| firstName: { | |
| reset: () => '', | |
| ...getUser.onResponse(({ name }) => name.split(' ')[0]), | |
| }, | |
| lastName: { | |
| reset: () => '', | |
| ...getUser.onResponse(({ name }) => name.split(' ')[1]), | |
| }, | |
| age: { | |
| reset: () => NaN, | |
| ...getUser.onResponse(({ age }) => age), | |
| }, | |
| }); | |
| const { select } = userData.select; | |
| const userName = createNode({ | |
| reset: () => '', | |
| [[select.firstName, select.lastName, select.age]]: ([firstName, lastName, age]) => { | |
| const prefix = age > 18 ? 'Mr. ' : ''; | |
| return `${prefix}${firstName} ${lastName}`; | |
| }, | |
| }); | |
| const callback = jest.fn(); | |
| userName.watch(callback); | |
| getUser(); | |
| return new Promise(callback).then(() => new Promise(r => setTimeout(r))).then(() => { | |
| expect(callback.mock.calls.length).toBe(1); | |
| expect(userName.get()).toBe('Tom Sawyer'); | |
| }); | |
| }); | |
| }); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment