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([]); }); });