102 lines
3.2 KiB
JavaScript
Executable File
102 lines
3.2 KiB
JavaScript
Executable File
#!/usr/bin/env -S node --no-warnings --loader ts-node/esm
|
|
import { test, sinon, } from 'tstest';
|
|
import { createMachine, interpret, } from 'xstate';
|
|
test('sinon.clock.tick', async (t) => {
|
|
const sandbox = sinon.createSandbox({
|
|
useFakeTimers: true,
|
|
});
|
|
let resolved = false;
|
|
new Promise(resolve => setTimeout(resolve, 10))
|
|
.then(() => { resolved = true; return resolved; })
|
|
.catch(e => t.fail(e));
|
|
t.equal(resolved, false, 'should not resolved initialy');
|
|
await sandbox.clock.tickAsync(9);
|
|
t.equal(resolved, false, 'should not resolved after tick(9)');
|
|
await sandbox.clock.tickAsync(100);
|
|
t.equal(resolved, true, 'should be resolved after tick(100)');
|
|
sandbox.restore();
|
|
});
|
|
/**
|
|
* XState - Invoking Services
|
|
* @see https://xstate.js.org/docs/guides/communication.html#invoking-promises
|
|
*
|
|
* If the state where the invoked promise is active is exited before the promise settles,
|
|
* the result of the promise is discarded.
|
|
*/
|
|
test('state exit before the invoked promise settle', async (t) => {
|
|
const sandbox = sinon.createSandbox({
|
|
useFakeTimers: true,
|
|
});
|
|
const sleep = (milliseconds = 0) => new Promise(resolve => setTimeout(resolve, milliseconds));
|
|
const config = {
|
|
id: 'test',
|
|
initial: 'start',
|
|
states: {
|
|
rejected: {},
|
|
resolved: {},
|
|
start: {
|
|
invoke: {
|
|
onDone: 'resolved',
|
|
onError: 'rejected',
|
|
src: async () => {
|
|
// console.info('before sleep')
|
|
await sleep(10);
|
|
// console.info('after sleep')
|
|
},
|
|
},
|
|
on: {
|
|
STOP: 'stop',
|
|
},
|
|
},
|
|
stop: {},
|
|
},
|
|
};
|
|
const machine = createMachine(config);
|
|
/**
|
|
* Wait Promise to settle
|
|
*/
|
|
const service1 = interpret(machine);
|
|
service1
|
|
.onTransition(state => {
|
|
stateList.push([
|
|
state.event.type,
|
|
String(state.value),
|
|
]);
|
|
});
|
|
const stateList = [];
|
|
service1.start();
|
|
await sandbox.clock.tickAsync(100);
|
|
service1.send('STOP');
|
|
await sandbox.clock.tickAsync(100);
|
|
const PROMISE_STATE_LIST = [
|
|
['xstate.init', 'start'],
|
|
['done.invoke.test.start:invocation[0]', 'resolved'],
|
|
['STOP', 'resolved'],
|
|
];
|
|
t.same(stateList, PROMISE_STATE_LIST, 'should wait the promise resolved');
|
|
service1.stop();
|
|
/**
|
|
* STOP before promise settle
|
|
*/
|
|
const service2 = interpret(machine);
|
|
service2
|
|
.onTransition(state => {
|
|
stateList.push([
|
|
state.event.type,
|
|
String(state.value),
|
|
]);
|
|
});
|
|
stateList.length = 0;
|
|
service2.start();
|
|
await sandbox.clock.tickAsync(1);
|
|
service2.send('STOP');
|
|
await sandbox.clock.tickAsync(100);
|
|
const STOP_STATE_LIST = [
|
|
['xstate.init', 'start'],
|
|
['STOP', 'stop'],
|
|
];
|
|
t.same(stateList, STOP_STATE_LIST, 'should skip the promise resolved');
|
|
service2.stop();
|
|
sandbox.restore();
|
|
});
|
|
//# sourceMappingURL=xstate-behavior.spec.js.map
|