import * as bdd from 'intern!bdd'; import { map } from 'lodash'; import { flatten } from '../../un-flatten-tree'; import * as expect from 'intern/chai!expect'; import Node from './Node'; bdd.describe('flatten', () => { bdd.it('should convert an empty array to an empty array', function () { expect(flatten([], () => [])).to.eql([]); }); bdd.it('should convert tree to list', () => { const tree = [ {l: 1, i: [ {l: 5} ]}, {l: 2, i: [ {l: 6, i: []} ]}, {l: 3, i: [ {l: 7, i: [ {l: 8, i: null}, {l: 9, i: [ {l: 11, i: []} ]}, {l: 10, i: []} ]} ]}, {l: 4, i: undefined} ]; const list = [ {l: 1, i: [ {l: 5} ]}, {l: 5}, {l: 2, i: [ {l: 6, i: []} ]}, {l: 6, i: []}, {l: 3, i: [ {l: 7, i: [ {l: 8, i: null}, {l: 9, i: [ {l: 11, i: []} ]}, {l: 10, i: []} ]} ]}, {l: 7, i: [ {l: 8, i: null}, {l: 9, i: [ {l: 11, i: []} ]}, {l: 10, i: []} ]}, {l: 8, i: null}, {l: 9, i: [ {l: 11, i: []} ]}, {l: 11, i: []}, {l: 10, i: []}, {l: 4, i: undefined} ]; expect(flatten(tree, node => node.i as any)).to.eql(list); }); bdd.it('should convert tree to list of nodes with parent ids', () => { const tree = [ {id: 1, items: []}, {id: 2, items: [ {id: 4, items: [ {id: 5, items: [ {id: 7, items: []} ]}, {id: 6, items: []} ]} ]}, {id: 3, items: [ {id: 8, items: []} ]} ]; const list = [ {id: 1, pid: null}, {id: 2, pid: null}, {id: 4, pid: 2}, {id: 5, pid: 4}, {id: 7, pid: 5}, {id: 6, pid: 4}, {id: 3, pid: null}, {id: 8, pid: 3} ]; expect( flatten( tree, (node) => node.items, (node, parentNode) => ({ id: node.id, pid: parentNode !== undefined ? parentNode.id : null }) ) ).to.eql(list); }); bdd.it('should convert tree of node objects to list of node names', () => { const tree = [new Node('A',[ new Node('B'), new Node('C', [ new Node('D') ]), new Node('E', [ new Node('F', [ new Node('G'), new Node('H') ]) ]) ])]; const list = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H']; expect( flatten( tree, node => node.getChildren(), node => node.getName() ) ).to.eql(list); }); bdd.it('should convert tree to list with generated parent ids', () => { const tree = [ {name: 'A', items: [ {name: 'A'}, {name: 'B'}, {name: 'C'} ]}, {name: 'B', items: [ {name: 'A', items: []} ]} ]; const list = [ {name: 'A', id: 1, pid: undefined}, {name: 'A', id: 2, pid: 1}, {name: 'B', id: 3, pid: 1}, {name: 'C', id: 4, pid: 1}, {name: 'B', id: 5, pid: undefined}, {name: 'A', id: 6, pid: 5} ]; let cnt = 1; expect( flatten( tree, node => node.items as any, (node, parentNode, nodeId, parentId) => ({ name: node.name, id: nodeId, pid: parentId }), () => cnt++ ) ).to.eql(list); }); bdd.it('should convert array-like object tree to list', () => { const tree = { 0: {name: 'A', items: { 0: {name: 'B'}, 1: {name: 'C'}, 2: {name: 'D'}, length: 3 }}, 1: {name: 'E', items: { 0: {name: 'F', items: { length: 0 }}, length: 1 }}, length: 2 }; const list = [ {name: 'A'}, {name: 'B'}, {name: 'C'}, {name: 'D'}, {name: 'E'}, {name: 'F'} ]; expect( flatten( tree, node => node.items as any, node => ({ name: node.name }) ) ).to.eql(list); }); // test case taken from here - http://stackoverflow.com/q/23919887/4134913 bdd.it('should convert tree to list of "routes"', function () { const tree = { f: { t: '100', f: { i: ['150'], b: ['300'], f: { k: 100 } }, 'l': ['255'] }, 'c': { 's': { 't': ['100'] }, 't': '100' } }; const list = ['ft', 'ffi', 'ffb', 'fffk', 'fl', 'cst', 'ct']; const walk = t => map(t, (v, k) => ({ name: k, items: (typeof v !== 'object' || v instanceof Array) ? [] : walk(v) })); const getChildNodes = node => node.items.map(item => ({ name: node.name + item.name, items: item.items })); expect( flatten(walk(tree), getChildNodes) .filter(node => (node as any).items.length === 0) .map(node => (node as any).name) ).to.eql(list); }); bdd.it('should convert deeply nested tree to list', () => { const tree = {id: 0, items: []}; const list = [0]; let treeHead = tree; for (let i = 1; i <= 100000; i++) { treeHead.items.push({id: i, items: []}); treeHead = treeHead.items[0]; list.push(i); } expect( flatten( [tree], node => node.items, node => node.id ) ).to.eql(list); }); });