Skip to content

Instantly share code, notes, and snippets.

@artalar
Last active October 30, 2018 08:05
Show Gist options
  • Select an option

  • Save artalar/8dea5a6540e4d8b0cec90ab6df89f609 to your computer and use it in GitHub Desktop.

Select an option

Save artalar/8dea5a6540e4d8b0cec90ab6df89f609 to your computer and use it in GitHub Desktop.
stm-5.js
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