212 lines
5.3 KiB
JavaScript
212 lines
5.3 KiB
JavaScript
import {InputCell, ComputeCell, CallbackCell} from './react';
|
|
|
|
describe('React module', () => {
|
|
|
|
test('accepts input', () => {
|
|
const inputCell = new InputCell(10);
|
|
expect(inputCell.value).toEqual(10);
|
|
});
|
|
|
|
test('allows input cell value to be set', () => {
|
|
const inputCell = new InputCell(4);
|
|
inputCell.setValue(20);
|
|
expect(inputCell.value).toEqual(20);
|
|
});
|
|
|
|
test('allows setting compute cells', () => {
|
|
const inputCell = new InputCell(1);
|
|
const fn = inputCells => inputCells[0].value + 1;
|
|
const computeCell = new ComputeCell([inputCell], fn);
|
|
expect(computeCell.value).toEqual(2);
|
|
});
|
|
|
|
test('compute cell takes inputs in correct order', () => {
|
|
const inputCells = [
|
|
new InputCell(1),
|
|
new InputCell(2)
|
|
];
|
|
|
|
const computeCell = new ComputeCell(
|
|
inputCells,
|
|
inputs => inputs[0].value + inputs[1].value * 10
|
|
);
|
|
|
|
expect(computeCell.value).toEqual(21);
|
|
});
|
|
|
|
test('compute cells update value when inputs are changed', () => {
|
|
const inputCell = new InputCell(1);
|
|
const computeCell = new ComputeCell(
|
|
[inputCell],
|
|
inputs => inputs[0].value + 1
|
|
);
|
|
inputCell.setValue(3);
|
|
expect(computeCell.value).toEqual(4);
|
|
});
|
|
|
|
|
|
test('compute cells can depend on other compute cells', () => {
|
|
const inputCell = new InputCell(1);
|
|
const timesTwo = new ComputeCell(
|
|
[inputCell],
|
|
inputs => inputs[0].value * 2
|
|
);
|
|
|
|
const timesThirty = new ComputeCell(
|
|
[inputCell],
|
|
inputs => inputs[0].value * 30
|
|
);
|
|
|
|
const sum = new ComputeCell(
|
|
[timesTwo, timesThirty],
|
|
inputs => inputs[0].value + inputs[1].value
|
|
);
|
|
|
|
expect(sum.value).toEqual(32);
|
|
|
|
inputCell.setValue(3);
|
|
expect(sum.value).toEqual(96);
|
|
});
|
|
|
|
test('compute cells fire callbacks', () => {
|
|
const inputCell = new InputCell(1);
|
|
const output = new ComputeCell(
|
|
[inputCell],
|
|
inputs => inputs[0].value + 1
|
|
);
|
|
|
|
const callback = new CallbackCell(cell => cell.value);
|
|
output.addCallback(callback);
|
|
|
|
inputCell.setValue(3);
|
|
expect(callback.values).toEqual([4]);
|
|
});
|
|
|
|
test('callbacks fire only when output values change', () => {
|
|
const inputCell = new InputCell(1);
|
|
const output = new ComputeCell(
|
|
[inputCell],
|
|
inputs => inputs[0].value < 3 ? 111 : 222
|
|
);
|
|
|
|
const callback = new CallbackCell(cell => cell.value);
|
|
output.addCallback(callback);
|
|
|
|
inputCell.setValue(2);
|
|
expect(callback.values).toEqual([]);
|
|
|
|
inputCell.setValue(4);
|
|
expect(callback.values).toEqual([222]);
|
|
});
|
|
|
|
|
|
test('callbacks can be added and removed', () => {
|
|
const inputCell = new InputCell(1);
|
|
const output = new ComputeCell(
|
|
[inputCell],
|
|
inputs => inputs[0].value + 1
|
|
);
|
|
|
|
const callback1 = new CallbackCell(cell => cell.value);
|
|
const callback2 = new CallbackCell(cell => cell.value);
|
|
|
|
output.addCallback(callback1);
|
|
output.addCallback(callback2);
|
|
|
|
inputCell.setValue(31);
|
|
|
|
output.removeCallback(callback1);
|
|
|
|
const callback3 = new CallbackCell(cell => cell.value);
|
|
output.addCallback(callback3);
|
|
|
|
inputCell.setValue(41);
|
|
|
|
expect(callback1.values).toEqual([32]);
|
|
expect(callback2.values).toEqual([32, 42]);
|
|
expect(callback3.values).toEqual([42]);
|
|
});
|
|
|
|
test('removing a callback multiple times doesn\'t interfere with other callbacks', () => {
|
|
const inputCell = new InputCell(1);
|
|
const output = new ComputeCell(
|
|
[inputCell],
|
|
inputs => inputs[0].value + 1
|
|
);
|
|
|
|
const callback1 = new CallbackCell(cell => cell.value);
|
|
const callback2 = new CallbackCell(cell => cell.value);
|
|
|
|
output.addCallback(callback1);
|
|
output.addCallback(callback2);
|
|
|
|
output.removeCallback(callback1);
|
|
output.removeCallback(callback1);
|
|
output.removeCallback(callback1);
|
|
|
|
inputCell.setValue(2);
|
|
|
|
expect(callback1.values).toEqual([]);
|
|
expect(callback2.values).toEqual([3]);
|
|
});
|
|
|
|
test('callbacks should only be called once, even if multiple dependencies change', () => {
|
|
const inputCell = new InputCell(1);
|
|
const plusOne = new ComputeCell(
|
|
[inputCell],
|
|
inputs => inputs[0].value + 1
|
|
);
|
|
|
|
const minusOne1 = new ComputeCell(
|
|
[inputCell],
|
|
inputs => inputs[0].value - 1
|
|
);
|
|
|
|
const minusOne2 = new ComputeCell(
|
|
[minusOne1],
|
|
inputs => inputs[0].value - 1
|
|
);
|
|
|
|
const output = new ComputeCell(
|
|
[plusOne, minusOne2],
|
|
inputs => inputs[0].value * inputs[1].value
|
|
);
|
|
|
|
const callback1 = new CallbackCell(cell => cell.value);
|
|
output.addCallback(callback1);
|
|
|
|
inputCell.setValue(4);
|
|
|
|
expect(callback1.values).toEqual([10]);
|
|
});
|
|
|
|
test('callbacks should not be called if dependencies change but output value doesn\'t change', () => {
|
|
const inputCell = new InputCell(1);
|
|
const plusOne = new ComputeCell(
|
|
[inputCell],
|
|
inputs => inputs[0].value + 1
|
|
);
|
|
|
|
const minusOne = new ComputeCell(
|
|
[inputCell],
|
|
inputs => inputs[0].value - 1
|
|
);
|
|
|
|
const alwaysTwo = new ComputeCell(
|
|
[plusOne, minusOne],
|
|
inputs => inputs[0].value - inputs[1].value
|
|
);
|
|
|
|
|
|
const callback = new CallbackCell(cell => cell.value);
|
|
alwaysTwo.addCallback(callback);
|
|
|
|
inputCell.setValue(2);
|
|
inputCell.setValue(3);
|
|
inputCell.setValue(4);
|
|
inputCell.setValue(5);
|
|
|
|
expect(callback.values).toEqual([]);
|
|
});
|
|
});
|