mirror of
https://github.com/gristlabs/grist-core.git
synced 2024-10-27 20:44:07 +00:00
126 lines
3.3 KiB
TypeScript
126 lines
3.3 KiB
TypeScript
|
import { assert } from 'chai';
|
||
|
import { Signal } from 'app/client/lib/Signal';
|
||
|
|
||
|
describe('Signal', function() {
|
||
|
it('computes new signal from other events', function() {
|
||
|
const started = Signal.create(null, false);
|
||
|
const hovered = Signal.create(null, false);
|
||
|
const hoverAndStarted = Signal.compute(null, on => on(started) && on(hovered));
|
||
|
|
||
|
let flag: any = 'not-called';
|
||
|
hoverAndStarted.listen(val => flag = val);
|
||
|
|
||
|
function start(emit: boolean, expected: boolean) {
|
||
|
started.emit(emit);
|
||
|
assert.equal(flag, expected);
|
||
|
flag = 'not-called';
|
||
|
}
|
||
|
|
||
|
function hover(emit: boolean, expected: boolean) {
|
||
|
hovered.emit(emit);
|
||
|
assert.equal(flag, expected);
|
||
|
flag = 'not-called';
|
||
|
}
|
||
|
|
||
|
start(true, false);
|
||
|
start(false, false);
|
||
|
start(true, false);
|
||
|
|
||
|
hover(true, true);
|
||
|
hover(false, false);
|
||
|
hover(true, true);
|
||
|
|
||
|
start(false, false);
|
||
|
});
|
||
|
|
||
|
it('works as flag', function() {
|
||
|
const started = Signal.create(null, false);
|
||
|
const hovered = Signal.create(null, false);
|
||
|
const andEvent = Signal.compute(null, on => on(started) && on(hovered)).distinct();
|
||
|
|
||
|
const notCalled = {};
|
||
|
let andCalled = notCalled;
|
||
|
andEvent.listen(val => andCalled = val);
|
||
|
|
||
|
function start(emit: boolean, expected: any) {
|
||
|
started.emit(emit);
|
||
|
assert.equal(andCalled, expected);
|
||
|
andCalled = notCalled;
|
||
|
}
|
||
|
|
||
|
start(true, notCalled);
|
||
|
start(false, notCalled);
|
||
|
start(true, notCalled);
|
||
|
|
||
|
function hover(emit: boolean, expected: any) {
|
||
|
hovered.emit(emit);
|
||
|
assert.equal(andCalled, expected);
|
||
|
andCalled = notCalled;
|
||
|
}
|
||
|
|
||
|
hover(true, true);
|
||
|
hover(false, false);
|
||
|
hover(true, true);
|
||
|
|
||
|
start(false, false);
|
||
|
});
|
||
|
|
||
|
it('supports basic compositions', function() {
|
||
|
const numbers = Signal.create(null, 0);
|
||
|
const even = numbers.filter(n => n % 2 === 0);
|
||
|
const odd = numbers.filter(n => n % 2 === 1);
|
||
|
|
||
|
let evenCount = 0;
|
||
|
let oddCount = 0;
|
||
|
even.listen(() => evenCount++);
|
||
|
odd.listen(() => oddCount++);
|
||
|
assert.equal(evenCount, 0);
|
||
|
assert.equal(oddCount, 0);
|
||
|
|
||
|
numbers.emit(2);
|
||
|
assert.equal(evenCount, 1);
|
||
|
assert.equal(oddCount, 0);
|
||
|
|
||
|
numbers.emit(3);
|
||
|
assert.equal(evenCount, 1);
|
||
|
assert.equal(oddCount, 1);
|
||
|
|
||
|
const distinct = numbers.distinct();
|
||
|
let distinctCount = 0;
|
||
|
distinct.listen(() => distinctCount++);
|
||
|
assert.equal(distinctCount, 0);
|
||
|
|
||
|
numbers.emit(3);
|
||
|
assert.equal(distinctCount, 0);
|
||
|
numbers.emit(3);
|
||
|
assert.equal(distinctCount, 0);
|
||
|
numbers.emit(4);
|
||
|
assert.equal(distinctCount, 1);
|
||
|
numbers.emit(4);
|
||
|
assert.equal(distinctCount, 1);
|
||
|
numbers.emit(5);
|
||
|
assert.equal(distinctCount, 2);
|
||
|
|
||
|
const trafficLight = Signal.create(null, false);
|
||
|
const onRoad = numbers.filter(n => !!trafficLight.state.get());
|
||
|
|
||
|
let onRoadCount = 0;
|
||
|
onRoad.listen(() => onRoadCount++);
|
||
|
assert.equal(onRoadCount, 0);
|
||
|
numbers.emit(5);
|
||
|
assert.equal(onRoadCount, 0);
|
||
|
trafficLight.emit(true);
|
||
|
assert.equal(onRoadCount, 0);
|
||
|
numbers.emit(6);
|
||
|
assert.equal(onRoadCount, 1);
|
||
|
});
|
||
|
|
||
|
it('detects cycles', function() {
|
||
|
const first = Signal.create(null, 0);
|
||
|
const second = Signal.create(null, 0);
|
||
|
first.listen(n => second.emit(n + 1));
|
||
|
second.listen(n => first.emit(n + 1));
|
||
|
assert.throws(() => first.emit(1));
|
||
|
});
|
||
|
});
|