This repository has been archived on 2020-09-01. You can view files and clone it, but cannot push or open issues or pull requests.
reactimal/spec/container.spec.js

141 lines
3.1 KiB
JavaScript

import { container, hashableContainer, computed } from '../src/index.js';
import { dirtyMock, hashSet } from '../src/testUtil.js';
describe('A container', () => {
const containedSet = hashableContainer(hashSet);
const containedArray = hashableContainer(arr => arr.join('x'));
it('tracks properties', () => {
let i = 0;
const a = container({}, () => i++);
a.a = 1;
expect(a.a).toBe(a._.a);
a.b = false;
expect(a.b).toBe(a._.b);
});
it('notifies dependents of updates', () => {
let runCount = 0;
let currentValue = new Set();
const a = containedSet(new Set());
const b = computed(s => Array.from(s).reduce((i, acc) => i + acc, 0), [a]);
a.subscribe(val => {
runCount += 1;
expect(hashSet(a)).toEqual(hashSet(currentValue));
});
currentValue.add(1);
a.add(1);
expect(runCount).toEqual(1);
expect(b()).toEqual(1);
currentValue.add(2);
a.add(2);
expect(runCount).toEqual(2);
expect(b()).toEqual(3);
});
it('works for arrays', () => {
let runCount = 0;
let currentValue = [];
const a = containedArray([]);
a.subscribe(val => {
runCount += 1;
expect(a.join('x')).toEqual(currentValue.join('x'));
});
currentValue.push(1);
a.push(1);
expect(runCount).toEqual(1);
currentValue.push(2);
a.push(2);
expect(runCount).toEqual(2);
currentValue.push(3);
a._.push(3);
expect(runCount).toEqual(2);
});
it('._ returns the proxied element', () => {
let runCount = 0;
let currentValue = new Set();
const a = containedSet(new Set());
a.subscribe(val => {
runCount += 1;
expect(hashSet(a)).toEqual(hashSet(currentValue));
});
currentValue.add(1);
a.add(1);
expect(runCount).toEqual(1);
currentValue.add(2);
a.add(2);
expect(runCount).toEqual(2);
currentValue.add(3);
a._.add(3);
expect(runCount).toEqual(2);
});
it('flags all subscribers as dirty before propagating change', () => {
const a = containedSet(new Set());
const [dirtyA, dirtyB, checker] = dirtyMock(2);
a.subscribe(dirtyA.setDirty);
a.subscribe(dirtyB.setDirty);
a.add(1);
expect(checker()).toBe(true);
});
it('can be locked to delay change propagation', () => {
let aVal = 0;
const a = container([0], c => c[0]);
a.subscribe(val => {
aVal = val[0];
});
expect(aVal).toBe(0);
a[0] = 1;
expect(aVal).toBe(1);
a._lock();
a[0] = 2;
expect(aVal).toBe(1);
a[0] = 3;
expect(aVal).toBe(1);
a._unlock();
expect(aVal).toBe(3);
});
it('requires the same number of unlocks as locks to resume change propagation', () => {
let aVal = 0;
const a = container([0], c => c[0]);
a.subscribe(val => {
aVal = val[0];
});
expect(aVal).toBe(0);
a[0] = 1;
expect(aVal).toBe(1);
a._lock();
a._lock();
a[0] = 2;
expect(aVal).toBe(1);
a[0] = 3;
expect(aVal).toBe(1);
a._unlock();
expect(aVal).toBe(1);
a._unlock();
expect(aVal).toBe(3);
});
it('calls subscriptions in order', () => {
let order = '';
const a = containedSet(new Set());
a.subscribe(() => (order += 'a'));
a.subscribe(() => (order += 'b'));
a.subscribe(() => (order += 'c'));
a.add(1);
expect(order).toEqual('abc');
});
});