Add tests
ssured opened this issue · comments
Sjoerd de Jong commented
const {
pipe,
interval,
take,
filter,
map,
forEach
} = require("callbag-basics");
const toRx = require("callbag-to-rxjs");
const {
autorun,
observable,
reaction,
configure,
runInAction
} = require("mobx");
const { fromStream, fromResource } = require("mobx-utils");
configure({
enforceActions: true
});
const delay = ms => new Promise(r => setTimeout(r, ms));
describe("callbag support for mobx", () => {
let status;
beforeEach(async () => {
status = "initial";
});
const pullableAsyncSource = (ms = 5) => {
let i = 0,
timeout;
return (start, sink) => {
if (start !== 0) return;
status = "started";
sink(0, t => {
if (t === 1) {
timeout = setTimeout(() => {
sink(1, i++);
}, ms);
} else if (t === 2) {
status = "stopped";
clearTimeout(timeout);
}
});
};
};
it("subscribes to observables", async () => {
const value = fromStream(
pipe(interval(10), take(5), filter(x => x !== 0), map(x => x * 10), toRx),
0
);
const values = [];
const dispose = autorun(() => values.push(value.current));
await delay(500);
dispose();
values; //?
expect(values).toEqual([0, 10, 20, 30, 40]);
});
it("callbag tracks unsubscribe", async () => {
const values = [];
pipe(pullableAsyncSource(), take(5), forEach(value => values.push(value)));
expect(status).toEqual("started");
await delay(100);
expect(status).toEqual("stopped");
pipe(pullableAsyncSource(), take(5), forEach(value => values.push(value)));
expect(status).toEqual("started");
await delay(100);
expect(status).toEqual("stopped");
values; //?
expect(values).toEqual([0, 1, 2, 3, 4, 0, 1, 2, 3, 4]);
});
it("callbag tracks unsubscribe - mobx", async () => {
const fromCallbag = (source, initialValue = undefined) => {
let talkback;
return fromResource(
sink => {
source(0, (t, d) => {
if (t === 0) talkback = d;
if (t === 1) sink(d);
if (t === 1 || t === 0) talkback(1);
});
},
() => talkback(2),
initialValue
);
};
const value = fromCallbag(pullableAsyncSource(20), -1);
// lazy initialization
expect(status).toEqual("initial");
const values = [];
// starts when observed
let runs = 0; // track number of runs for fixing timing issues in the test
let dispose = autorun(() => {
runs++;
values.push(value.current());
});
expect(status).toEqual("started");
await delay(70);
expect(status).toEqual("started");
// stops when not listened to
dispose();
expect(status).toEqual("stopped");
const expectedResult1 = [-1, 0, 1, 2].slice(0, runs);
runs; //?
expectedResult1; //?
expect(values).toEqual(expectedResult1);
// restarts when observed
dispose = autorun(() => {
runs++;
values.push(value.current());
});
expect(status).toEqual("started");
await delay(70);
expect(status).toEqual("started");
dispose();
expect(status).toEqual("stopped");
const lastResult1 = expectedResult1.slice(-1)[0]; //?
const expectedResult2 = expectedResult1
.concat(
Array(runs)
.fill()
.map((_, i) => i + lastResult1)
)
.slice(0, runs);
runs; //?
expectedResult2; //?
expect(values).toEqual(expectedResult2);
});
it("callbag tracks unsubscribe - mobx", async () => {
const value = observable({ a: "A" });
let status = "initial";
const asCallbag = (expression, fireImmediately = true) => {
let disposer;
return (start, sink) => {
if (start !== 0) return;
status = "started";
sink(0, t => {
if (t === 2) {
status = "stopped";
disposer();
}
});
disposer = reaction(expression, value => sink(1, value), {
fireImmediately
});
};
};
const values = [];
const valueBag = asCallbag(() => value.a);
// connecting callbag
expect(status).toEqual("initial");
pipe(valueBag, take(3), forEach(value => values.push(value)));
expect(values).toEqual(["A"]);
expect(status).toEqual("started");
// updates are tracked
runInAction(() => {
value.a = "B";
});
expect(values).toEqual(["A", "B"]);
// only three updates are listened to, because of take
expect(status).toEqual("started");
runInAction(() => {
value.a = "C";
});
expect(values).toEqual(["A", "B", "C"]);
expect(status).toEqual("stopped");
// further changes are not handled
runInAction(() => {
value.a = "D";
});
expect(values).toEqual(["A", "B", "C"]);
});
});