promise-stream/test/test.js

150 lines
4.4 KiB
JavaScript

'use strict';
const assert = require('assert');
const PromiseStream = require('../promise-stream');
function cloneJSON(x) {
return JSON.parse(JSON.stringify(x));
}
function afterMicrotasks() {
return new Promise(function(resolve) {
setTimeout(resolve);
});
}
describe('PromiseStream', function() {
let stream;
it('should finish constructing the PromiseStream', function() {
stream = new PromiseStream;
});
it('should have an undefined initial value', function() {
assert.deepStrictEqual(stream.value, undefined);
});
const onceVal = [];
it('should allow setting a one-time callback', function() {
stream.once((v) => {
onceVal.push(v);
});
});
const listenVal = [];
let cancel;
it('should allow setting an ongoing callback', function() {
cancel = stream.listen((v) => {
listenVal.push(v);
});
});
it('should return a cancellation function', function() {
assert.strictEqual(typeof cancel, 'function');
});
const then0Val = [];
it('should provide access to the current promise', function() {
stream.promise.then((v) => v.value + 3).then((v) => {
then0Val.push(v);
});
});
const next0Val = [];
it('should provide access to the next promise', function() {
stream.next_promise.then((v) => v.value + 7).then((v) => {
next0Val.push(v);
});
});
it('should wait for the first update before running callbacks', async function() {
await afterMicrotasks();
assert.deepStrictEqual(onceVal, []);
assert.deepStrictEqual(listenVal, []);
assert.deepStrictEqual(then0Val, []);
assert.deepStrictEqual(next0Val, []);
});
let snapshot;
it('should allow updates', function() {
stream.update(10);
snapshot = cloneJSON({ onceVal, listenVal, then0Val, next0Val });
});
it('should hold callbacks in the microtask queue', function() {
assert.deepStrictEqual(snapshot.onceVal, []);
assert.deepStrictEqual(snapshot.listenVal, []);
assert.deepStrictEqual(snapshot.then0Val, []);
assert.deepStrictEqual(snapshot.next0Val, []);
});
it('should run callbacks after first update', async function() {
await afterMicrotasks();
assert.deepStrictEqual(onceVal, [10]);
assert.deepStrictEqual(listenVal, [10]);
assert.deepStrictEqual(then0Val, [13]);
assert.deepStrictEqual(next0Val, [17]);
});
const then1Val = [];
it('should provide access to current promise after update', async function() {
stream.promise.then((v) => v.value + 4).then((v) => {
then1Val.push(v);
});
assert.deepStrictEqual(then1Val, []);
await afterMicrotasks();
assert.deepStrictEqual(then1Val, [14]);
});
const next1Val = [];
it('should provide access to next promise after update', async function() {
stream.next_promise.then((v) => v.value + 8).then((v) => {
next1Val.push(v);
});
await afterMicrotasks();
assert.deepStrictEqual(next1Val, []);
});
it('should allow a second update', function() {
stream.update(20);
snapshot = cloneJSON({ onceVal, listenVal, then0Val, next0Val, then1Val, next1Val });
});
it('should hold callbacks in the microtask queue', function() {
assert.deepStrictEqual(snapshot.onceVal, [10]);
assert.deepStrictEqual(snapshot.listenVal, [10]);
assert.deepStrictEqual(snapshot.then0Val, [13]);
assert.deepStrictEqual(snapshot.next0Val, [17]);
assert.deepStrictEqual(snapshot.then1Val, [14]);
assert.deepStrictEqual(snapshot.next1Val, []);
});
it('should run callbacks after second update', async function() {
await afterMicrotasks();
assert.deepStrictEqual(onceVal, [10]);
assert.deepStrictEqual(listenVal, [10, 20]);
assert.deepStrictEqual(then0Val, [13]);
assert.deepStrictEqual(next0Val, [17]);
assert.deepStrictEqual(then1Val, [14]);
assert.deepStrictEqual(next1Val, [28]);
});
it('should allow listeners to be cancelled individually', async function() {
const listen2Val = [];
const cancel2 = stream.listen((v) => {
listen2Val.push(v);
});
cancel();
stream.update(30);
await afterMicrotasks();
cancel2();
assert.deepStrictEqual(listenVal, [10, 20]); /* not updated */
assert.deepStrictEqual(listen2Val, [20, 30]); /* updated w/ current and new value */
});
});