UNPKG

react-vir-tree

Version:
367 lines (259 loc) 11.4 kB
import deepFreeze from 'deep-freeze'; import {diff} from 'deep-diff'; import TreeStateModifiers from '../TreeStateModifiers'; import {Nodes} from '../../../testData/sampleTree'; import TreeState from '../TreeState'; describe('TreeStateModifiers', () => { const noop = () => {}; describe('editNodeAt', () => { test('should fail when invalid state is supplied', () => { expect(() => TreeStateModifiers.editNodeAt('state', 0, noop)).toThrowError( 'Expected a State instance but got string', ); expect(() => TreeStateModifiers.editNodeAt(1225, 0, noop)).toThrowError( 'Expected a State instance but got number', ); expect(() => TreeStateModifiers.editNodeAt([], 0, noop)).toThrowError('Expected a State instance but got object'); expect(() => TreeStateModifiers.editNodeAt({}, 0, noop)).toThrowError('Expected a State instance but got object'); expect(() => TreeStateModifiers.editNodeAt(true, 0, noop)).toThrowError( 'Expected a State instance but got boolean', ); expect(() => TreeStateModifiers.editNodeAt(() => {}, 0, noop)).toThrowError( 'Expected a State instance but got function', ); }); test('should fail with descriptive error when node at index does not exist', () => { expect(() => TreeStateModifiers.editNodeAt(TreeState.createFromTree(Nodes), 20, noop), ).toThrowErrorMatchingSnapshot(); }); describe('flattened tree', () => { test('should collapse a node in a root node', () => { const state = TreeState.createFromTree(Nodes); deepFreeze(state); const {flattenedTree} = TreeStateModifiers.editNodeAt(state, 0, n => ({ ...n, state: {...n.state, expanded: false}, })); expect(flattenedTree).toMatchSnapshot(); }); test('should collapse a node in a children node', () => { const state = TreeState.createFromTree(Nodes); deepFreeze(state); const {flattenedTree} = TreeStateModifiers.editNodeAt(state, 1, n => ({ ...n, state: {...n.state, expanded: false}, })); expect(flattenedTree).toMatchSnapshot(); }); test('should expand a node in a root node', () => { const state = TreeState.createFromTree(Nodes); deepFreeze(state); const {flattenedTree} = TreeStateModifiers.editNodeAt(state, 5, n => ({ ...n, state: {...n.state, expanded: true}, })); expect(flattenedTree).toMatchSnapshot(); }); test('should expand a node in a children node', () => { const state = TreeState.createFromTree(Nodes); deepFreeze(state); const {flattenedTree} = TreeStateModifiers.editNodeAt(state, 2, n => ({ ...n, state: {...n.state, expanded: true}, })); expect(flattenedTree).toMatchSnapshot(); }); test('should not change for updates that do not change state', () => { const state = TreeState.createFromTree(Nodes); deepFreeze(state); const {flattenedTree} = TreeStateModifiers.editNodeAt(state, 2, n => ({ ...n, name: 'node', })); expect(flattenedTree).toEqual(state.flattenedTree); }); test('should not change for updates that change state but not expansion', () => { const state = TreeState.createFromTree(Nodes); deepFreeze(state); const {flattenedTree} = TreeStateModifiers.editNodeAt(state, 2, n => ({ ...n, state: {...n.state, favorite: true}, })); expect(flattenedTree).toEqual(state.flattenedTree); const {flattenedTree: flattenedTree2} = TreeStateModifiers.editNodeAt(state, 0, n => ({ ...n, state: {...n.state, deletable: true}, })); expect(flattenedTree2).toEqual(state.flattenedTree); const {flattenedTree: flattenedTree3} = TreeStateModifiers.editNodeAt(state, 0, n => ({ ...n, state: {...n.state, randomKey: true}, })); expect(flattenedTree3).toEqual(state.flattenedTree); }); }); describe('tree', () => { test('should update a node in the root and keep the rest intact', () => { const state = TreeState.createFromTree(Nodes); deepFreeze(state); const updatedName = 'Edit node 1'; // Change 'Leaf 1' const {tree} = TreeStateModifiers.editNodeAt(state, 0, n => ({ ...n, name: updatedName, })); const changes = diff(state.tree, tree); expect(changes.length).toBe(1); expect(changes[0]).toMatchSnapshot(); }); test('should update a child node and keep the rest intact', () => { const state = TreeState.createFromTree(Nodes); deepFreeze(state); const updatedName = 'Edited node'; // Change 'Leaf 3' const {tree} = TreeStateModifiers.editNodeAt(state, 2, n => ({ ...n, name: updatedName, })); const changes = diff(state.tree, tree); expect(changes.length).toBe(1); expect(changes[0]).toMatchSnapshot(); }); test('should update a node state in the root and keep the rest intact', () => { const state = TreeState.createFromTree(Nodes); deepFreeze(state); // Expand 'Leaf 6' const {tree} = TreeStateModifiers.editNodeAt(state, 5, n => ({ ...n, state: {expanded: true}, })); const changes = diff(state.tree, tree); expect(changes).toMatchSnapshot(); }); test('should update a child node state and keep the rest intact', () => { const state = TreeState.createFromTree(Nodes); deepFreeze(state); // Collapse 'Leaf 2' const {tree} = TreeStateModifiers.editNodeAt(state, 1, n => ({ ...n, state: {...n.state, expanded: false}, })); const changes = diff(state.tree, tree); expect(changes.length).toBe(1); expect(changes[0]).toMatchSnapshot(); }); test('should create state for a child node and keep the rest intact', () => { const state = TreeState.createFromTree(Nodes); deepFreeze(state); // Favorite 'Leaf 5' const {tree} = TreeStateModifiers.editNodeAt(state, 4, n => ({ ...n, state: {...n.state, expanded: true}, })); const changes = diff(state.tree, tree); expect(changes.length).toBe(1); expect(changes[0]).toMatchSnapshot(); }); test('should delete state for a root node and keep the rest intact', () => { const state = TreeState.createFromTree(Nodes); deepFreeze(state); // Clear state for 'Leaf 6' const {tree} = TreeStateModifiers.editNodeAt(state, 5, n => { return Object.keys(n) .filter(k => k !== 'state') .reduce((node, k) => ({...node, [k]: n[k]}), {}); }); const changes = diff(state.tree, tree); expect(changes.length).toBe(1); expect(changes[0]).toMatchSnapshot(); }); test('should delete state for a child node and keep the rest intact', () => { const state = TreeState.createFromTree(Nodes); deepFreeze(state); // Clear state for 'Leaf 3' const {tree} = TreeStateModifiers.editNodeAt(state, 2, n => { return Object.keys(n) .filter(k => k !== 'state') .reduce((node, k) => ({...node, [k]: n[k]}), {}); }); const changes = diff(state.tree, tree); expect(changes.length).toBe(1); expect(changes[0]).toMatchSnapshot(); }); }); }); describe('deleteNodeAt', () => { test('should fail when invalid state is supplied', () => { expect(() => TreeStateModifiers.deleteNodeAt('state', 0)).toThrowError( 'Expected a State instance but got string', ); expect(() => TreeStateModifiers.deleteNodeAt(1225, 0)).toThrowError('Expected a State instance but got number'); expect(() => TreeStateModifiers.deleteNodeAt([], 0)).toThrowError('Expected a State instance but got object'); expect(() => TreeStateModifiers.deleteNodeAt({}, 0)).toThrowError('Expected a State instance but got object'); expect(() => TreeStateModifiers.deleteNodeAt(true, 0)).toThrowError('Expected a State instance but got boolean'); expect(() => TreeStateModifiers.deleteNodeAt(() => {}, 0)).toThrowError( 'Expected a State instance but got function', ); }); test('should fail with descriptive error when node at index does not exist', () => { expect(() => TreeStateModifiers.deleteNodeAt(TreeState.createFromTree(Nodes), 20)).toThrowErrorMatchingSnapshot(); }); describe('flattened tree', () => { test('should delete a root node with expanded children', () => { const state = TreeState.createFromTree(Nodes); deepFreeze(state); const {flattenedTree} = TreeStateModifiers.deleteNodeAt(state, 0); expect(flattenedTree).toMatchSnapshot(); }); test('should delete a root node without expanded children', () => { const state = TreeState.createFromTree(Nodes); deepFreeze(state); const {flattenedTree} = TreeStateModifiers.deleteNodeAt(state, 5); expect(flattenedTree).toMatchSnapshot(); }); test('should delete a child node with expanded children', () => { const state = TreeState.createFromTree(Nodes); deepFreeze(state); const {flattenedTree} = TreeStateModifiers.deleteNodeAt(state, 1); expect(flattenedTree).toMatchSnapshot(); }); test('should delete a child node without expanded children', () => { const state = TreeState.createFromTree(Nodes); deepFreeze(state); const {flattenedTree} = TreeStateModifiers.deleteNodeAt(state, 2); expect(flattenedTree).toMatchSnapshot(); }); }); describe('tree', () => { test('should delete a root node with expanded children', () => { const state = TreeState.createFromTree(Nodes); deepFreeze(state); const {tree} = TreeStateModifiers.deleteNodeAt(state, 0); const changes = diff(state.tree, tree); expect(changes).toMatchSnapshot(); }); test('should delete a root node without expanded children', () => { const state = TreeState.createFromTree(Nodes); deepFreeze(state); const {tree} = TreeStateModifiers.deleteNodeAt(state, 6); const changes = diff(state.tree, tree); expect(changes).toMatchSnapshot(); }); test('should delete a child node without expanded children', () => { const state = TreeState.createFromTree(Nodes); deepFreeze(state); const {tree} = TreeStateModifiers.deleteNodeAt(state, 2); const changes = diff(state.tree, tree); expect(changes).toMatchSnapshot(); }); test('should delete a child node with expanded children', () => { const state = TreeState.createFromTree(Nodes); deepFreeze(state); const {tree} = TreeStateModifiers.deleteNodeAt(state, 1); const changes = diff(state.tree, tree); expect(changes).toMatchSnapshot(); }); }); }); });