UNPKG

basicprimitives

Version:

Basic Primitives Diagrams for JavaScript - data visualization components library that implements organizational chart and multi-parent dependency diagrams, contains implementations of JavaScript Controls and PDF rendering plugins.

514 lines (446 loc) 16.7 kB
import Family from './Family'; var items = [ { id: 1, name: "1" }, { id: 2, name: "2" }, { id: 3, name: "3" }, { id: 4, parents: [1, 2, 3], name: "4" }, { id: 5, parents: [1, 2, 3], name: "5" }, { id: 6, parents: [4], name: "6" }, { id: 7, parents: [4, 5], name: "7" }, { id: 8, parents: [5], name: "8" }, { id: 9, parents: [6], name: "9" }, { id: 10, parents: [7], name: "10" }, { id: 11, parents: [8], name: "11" } ]; function getFamily(items) { var family = Family(); for (var index = 0; index < items.length; index += 1) { var item = items[index]; family.add(item.parents, item.id, item); } return family; } test('loopTopo', () => { const family = getFamily(items); var topoSorted = []; family.loopTopo(this, function (itemid, item, position) { topoSorted.push(itemid); }); var expectedTopoSorted = ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11"]; expect(family.validate()).toBe(true); expect(topoSorted).toEqual(expectedTopoSorted); }); test('loopTopoReveresed', () => { const family = getFamily(items); var topoSorted = []; family.loopTopoReversed(this, function (itemid, item, position) { topoSorted.push(itemid); }); var expectedTopoSorted = ["9", "10", "11", "6", "7", "8", "4", "5", "1", "2", "3"]; expect(family.validate()).toBe(true); expect(topoSorted).toEqual(expectedTopoSorted); }); test('Function loopChildren for item 4 should return', () => { const family = getFamily(items); var levels = []; family.loopChildren(this, 4, function (itemid, item, level) { levels[level] = levels[level] || []; levels[level].push(itemid); }); var expected = [["6", "7"], ["9", "10"]]; expect(family.validate()).toBe(true); expect(levels).toEqual(expected); }); test('Function loopParents for item 11 should return following items', () => { const family = getFamily(items); var levels = []; family.loopParents(this, 11, function (itemid, item, level) { levels[level] = levels[level] || []; levels[level].push(itemid); }); var expected = [["8"], ["5"], ["1", "2", "3"]]; expect(family.validate()).toBe(true); expect(levels).toEqual(expected); }); test('Node 100 does not exists', () => { const family = getFamily(items); expect(family.node(100)).toBe(undefined); }); test('Item 6 has name 6', () => { const family = getFamily(items); expect(family.node(6).name).toBe("6"); }); test('Items 4 and 5 have common child', () => { const family = getFamily(items); expect(family.hasCommonChild([4, 5])).toBe(true); }); test('Items 2 and 3 have no common child, because they are not unique parents for exisiting shared child', () => { const family = getFamily(items); expect(!family.hasCommonChild([2, 3])).toBe(true); }); test('Items 10 and 11 have no common or any child', () => { const family = getFamily(items); expect(!family.hasCommonChild([10, 11])).toBe(true); }); test('Function loopLevels top aligned should return following items', () => { const family = getFamily(items); var bundleItem1 = { id: 12, name: "12" } family.bundleParents(4, [2, 3], bundleItem1.id, bundleItem1); var bundleItem2 = { id: 13, name: "13" } family.bundleChildren(5, [7, 8], bundleItem2.id, bundleItem2); var levels = []; family.loopLevels(this, true, function (itemid, item, level) { levels[level] = levels[level] || []; levels[level].push(itemid); }); var expected = [["1", "3", "2"], ["5", "12"], ["13", "4"], ["8", "6", "7"], ["11", "9", "10"]]; expect(family.validate()).toBe(true); expect(levels).toEqual(expected); }); test('Function loopLevels top aligned should return following items', () => { const family = getFamily([ { id: 1, name: "1" }, { id: 2, name: "2" }, { id: 3, name: "3", parents: [2] }, { id: 4, name: "4", parents: [1, 3] }, { id: 5, name: "5", parents: [4, 9] }, { id: 6, name: "6", parents: [5] }, { id: 7, name: "7", parents: [6, 8] }, { id: 8, name: "8", parents: [4] }, { id: 9, name: "9" } ]); var levels = []; family.loopLevels(this, true, function (itemid, item, level) { levels[level] = levels[level] || []; levels[level].push(itemid); }); var expectedLevels = [["2"], ["1", "3"], ["4", "9"], ["5", "8"], ["6"], ["7"]]; expect(family.validate()).toBe(true); expect(levels).toEqual(expectedLevels); }); test('Function loopLevels top aligned should return following items', () => { const family = getFamily([ { id: 1, name: "1" }, { id: 2, name: "2" }, { id: 3, name: "3", parents: [1] }, { id: 4, name: "4", parents: [1, 2] }, { id: 5, name: "5", parents: [2] }, { id: 6, name: "6", parents: [3] }, { id: 7, name: "7", parents: [5] }, { id: 8, name: "8", parents: [6] }, { id: 9, name: "9", parents: [7] }, { id: 10, name: "10", parents: [8] }, { id: 11, name: "11", parents: [10] }, { id: 12, name: "12", parents: [4] }, { id: 13, name: "13", parents: [11, 12] }, { id: 14, name: "14", parents: [12, 15] }, { id: 15, name: "15", parents: [9] }, { id: 16, name: "16", parents: [12] }, { id: 17, name: "17", parents: [16] }, { id: 18, name: "18", parents: [17] } ]); var levels = []; family.loopLevels(this, true, function (itemid, item, level) { levels[level] = levels[level] || []; levels[level].push(itemid); }); var expectedLevels = [["1", "2"], ["3", "4", "5"], ["6", "12", "7"], ["8", "16", "9"], ["10", "17", "15"], ["11", "18", "14"], ["13"]]; expect(family.validate()).toBe(true); expect(levels).toEqual(expectedLevels); }); test('Function loopLevels should return following items for cloned family', () => { const family = getFamily([ { id: 1, name: "1" }, { id: 2, name: "2" }, { id: 3, name: "3", parents: [1] }, { id: 4, name: "4", parents: [1, 2] }, { id: 5, name: "5", parents: [2] }, { id: 6, name: "6", parents: [3] }, { id: 7, name: "7", parents: [5] }, { id: 8, name: "8", parents: [6] }, { id: 9, name: "9", parents: [7] }, { id: 10, name: "10", parents: [8] }, { id: 11, name: "11", parents: [10] }, { id: 12, name: "12", parents: [4] }, { id: 13, name: "13", parents: [11, 12] }, { id: 14, name: "14", parents: [12, 15] }, { id: 15, name: "15", parents: [9] }, { id: 16, name: "16", parents: [12] }, { id: 17, name: "17", parents: [16] }, { id: 18, name: "18", parents: [17] } ]); var levels = []; const family3 = family.clone(); family3.loopLevels(this, false, function (itemid, item, level) { levels[level] = levels[level] || []; levels[level].push(itemid); }); var expected = [["1"], ["3", "2"], ["6", "5"], ["8", "7"], ["10", "9", "4"], ["11", "12", "15"], ["13", "16", "14"], ["17"], ["18"]]; expect(family3.validate()).toBe(true); expect(levels).toEqual(expected); }); test('loopTopo function', () => { const family = getFamily([ { id: "D", name: "D" }, { id: "C", name: "C", parents: ["D"] }, { id: "F", name: "F", parents: ["D"] }, { id: "B", name: "B", parents: ["C", "F"] }, { id: "E", name: "E", parents: ["C", "F"] }, { id: "A", name: "A", parents: ["B", "E"] } ]); var topoSorted = []; family.loopTopo(this, function (itemid, item, position) { topoSorted.push(itemid); }); var expectedTopoSorted = ["D", "C", "F", "B", "E", "A"]; expect(family.validate()).toBe(true); expect(topoSorted).toEqual(expectedTopoSorted); }); test('loopTopo function', () => { const family = getFamily([ { id: "A", name: "A" }, { id: "A2", name: "A2" }, { id: "C", name: "C", parents: ["B"] }, { id: "B", name: "B", parents: ["A"] }, { id: "C2", name: "C2", parents: ["B2"] }, { id: "B2", name: "B2", parents: ["A2"] }, { id: "G", name: "G", parents: ["B", "A", "B2", "A2"] } ]); var topoSorted = []; family.loopTopo(this, function (itemid, item, position) { topoSorted.push(itemid); }); var expectedTopoSorted = ["A", "A2", "B", "B2", "C", "C2", "G"]; expect(family.validate()).toBe(true); expect(topoSorted).toEqual(expectedTopoSorted); }); test('loopTopo function test for two disconnected families', () => { const family = getFamily([ { id: "A", name: "A" }, { id: "A2", name: "A2" }, { id: "C", name: "C", parents: ["B"] }, { id: "B", name: "B", parents: ["A"] }, { id: "C2", name: "C2", parents: ["B2"] }, { id: "B2", name: "B2", parents: ["A2"] } ]); var topoSorted = []; family.loopTopo(this, function (itemid, item, position) { topoSorted.push(itemid); }); var expectedTopoSorted = ["A", "A2", "B", "B2", "C", "C2"]; expect(family.validate()).toBe(true); expect(topoSorted).toEqual(expectedTopoSorted); }); test('adopt - Check adopted item', () => { function getLevels(family) { var levels = []; family.loopLevels(this, true, function (itemid, item, level) { var newItem = { id: itemid }; var children = []; family.loopChildren(this, itemid, function (itemid, item, levelIndex) { if (levelIndex > 0) { return family.BREAK; } children.push(itemid); }); if (children.length > 0) { newItem.children = children; } levels.push(newItem); }); return levels; } var items = [ { id: 1 }, { id: 2 }, { id: 3 }, { id: 4 }, { id: 5 }, { id: 6, parents: [2, 3, 4] }, { id: 7 }, { id: 8, parents: [1, 2, 3, 4, 5, 6, 7] } ]; var family = Family(); for (var index = 0; index < items.length; index += 1) { var item = items[index]; family.add(item.parents, item.id, item); } var result = []; family.adopt([1, 2, 3], 5); var levels = getLevels(family); var expectedResults = [{ "id": "1", "children": ["5", "8"] }, { "id": "3", "children": ["5", "6", "8"] }, { "id": "2", "children": ["5", "6", "8"] }, { "id": "4", "children": ["6", "8"] }, { "id": "5", "children": ["8"] }, { "id": "6", "children": ["8"] }, { "id": "7", "children": ["8"] }, { "id": "8" }]; expect(family.validate()).toBe(true); expect(levels).toEqual(expectedResults); }); function getLevels(family) { var levels = []; family.loopLevels(this, true, function (itemid, item, level) { var newItem = { id: itemid }; var children = []; family.loopChildren(this, itemid, function (itemid, item, levelIndex) { if (levelIndex > 0) { return family.BREAK; } children.push(itemid); }); if (children.length > 0) { newItem.children = children; } levels.push(newItem); }); return levels; } test('removeNode - Check item removal', () => { const family = getFamily([ { id: 1 }, { id: 2 }, { id: 3 }, { id: 4, parents: [1, 2, 3] }, { id: 5, parents: [1, 2, 3] }, { id: 6, parents: [4, 5] }, { id: 7, parents: [4, 5] }, { id: 8, parents: [4, 5] } ]); family.removeNode(4); var levels = getLevels(family); var expectedResults = [{ "id": "1", "children": ["5"] }, { "id": "3", "children": ["5"] }, { "id": "2", "children": ["5"] }, { "id": "5", "children": ["6", "7", "8"] }, { "id": "6" }, { "id": "7" }, { "id": "8" } ]; expect(family.validate()).toBe(true); expect(levels).toEqual(expectedResults); }); test('removeRelation - Check child/parent relation removal', () => { const family = getFamily([ { id: 1 }, { id: 2 }, { id: 3 }, { id: 4, parents: [1, 2, 3] }, { id: 5, parents: [1, 2, 3] }, { id: 6, parents: [4, 5] }, { id: 7, parents: [4, 5] }, { id: 8, parents: [4, 5] } ]); family.removeNode(4); family.removeRelation(5, 2); var levels = getLevels(family); var expectedResults = [{ "id": "1", "children": ["5"] }, { "id": "3", "children": ["5"] }, { "id": "2" }, { "id": "5", "children": ["6", "7", "8"] }, { "id": "6" }, { "id": "7" }, { "id": "8" } ]; expect(family.validate()).toBe(true); expect(levels).toEqual(expectedResults); }); test('removeRelation - Check parent/child relation removal resulting in new orphant item 6 creation', () => { const family = getFamily([ { id: 1 }, { id: 2 }, { id: 3 }, { id: 4, parents: [1, 2, 3] }, { id: 5, parents: [1, 2, 3] }, { id: 6, parents: [4, 5] }, { id: 7, parents: [4, 5] }, { id: 8, parents: [4, 5] } ]); family.removeNode(4); family.removeRelation(5, 2); family.removeRelation(5, 6); var levels = getLevels(family); var expectedResults = [{ "id": "1", "children": ["5"] }, { "id": "3", "children": ["5"] }, { "id": "2" }, { "id": "6" }, { "id": "5", "children": ["7", "8"] }, { "id": "7" }, { "id": "8" } ]; expect(family.validate()).toBe(true); expect(levels).toEqual(expectedResults); }); test('removeNode - Check orphant 1 removal', () => { const family = getFamily([ { id: 1 }, { id: 2 }, { id: 3 }, { id: 4, parents: [1, 2, 3] }, { id: 5, parents: [1, 2, 3] }, { id: 6, parents: [4, 5] }, { id: 7, parents: [4, 5] }, { id: 8, parents: [4, 5] } ]); family.removeNode(4); family.removeRelation(5, 2); family.removeRelation(5, 6); family.removeNode(1); var levels = getLevels(family); var expectedResults = [{ "id": "2" }, { "id": "3", "children": ["5"] }, { "id": "6" }, { "id": "5", "children": ["7", "8"] }, { "id": "7" }, { "id": "8" }]; expect(family.validate()).toBe(true); expect(levels).toEqual(expectedResults); }); test('findLargestRoot - Finds sub-tree having largest number of nodes', () => { const family = getFamily([ { id: 12 }, { id: 11, parents: [12] }, { id: 14 }, { id: 13, parents: [14] }, { id: 8 }, { id: 9, parents: [8] }, { id: 10, parents: [8] }, { id: 1 }, { id: 2, parents: [1, 13] }, { id: 3, parents: [1, 13] }, { id: 6, parents: [3] }, { id: 7, parents: [3] }, { id: 4, parents: [2, 11] }, { id: 5, parents: [2] } ]); var extractionFamily = family.clone(); var families = []; var grandParent; while ((grandParent = extractionFamily.findLargestRoot()) != null) { var members = []; extractionFamily.removeNode(grandParent); family.loopChildren(this, grandParent, function (itemid, item, levelIndex) { if (extractionFamily.node(itemid) != null) { members.push(itemid); extractionFamily.removeNode(itemid); } }); families.push({ root: grandParent, members: members }); }; var expected = [{ "root": "14", "members": ["13", "2", "3", "4", "5", "6", "7"] }, { "root": "8", "members": ["9", "10"] }, { "root": "12", "members": ["11"] }, { "root": "1", "members": [] } ]; expect(family.validate()).toBe(true); expect(families).toEqual(expected); }); const items2 = [ { id: 12 }, { id: 11, parents: [12] }, { id: 14 }, { id: 13, parents: [14] }, { id: 8 }, { id: 9, parents: [8] }, { id: 10, parents: [8] }, { id: 1 }, { id: 2, parents: [1, 13] }, { id: 3, parents: [1, 13] }, { id: 6, parents: [3] }, { id: 7, parents: [3] }, { id: 4, parents: [2, 11] }, { id: 5, parents: [2] } ]; test('loopRoots - Loop sub-trees by size from smallest to largest', () => { const family = getFamily(items2); var members = []; family.loopRoots(this, function (itemid, item) { members.push(itemid); }); var expected = ["8", "12", "1", "14"]; expect(family.validate()).toBe(true); expect(members).toEqual(expected); }); test('countParents - Item 2 has 2 parent nodes', () => { const family = getFamily(items2); expect(family.countParents(2)).toBe(2); }); test('countChildren - Item 12 has 1 child node', () => { const family = getFamily(items2); expect(family.countChildren(12)).toBe(1); }); test('countParents - Item 1 has no parents', () => { const family = getFamily(items2); expect(family.countParents(1)).toBe(0); }); test('countChildren - Item 9 has no children', () => { const family = getFamily(items2); expect(family.countChildren(9)).toBe(0); }); test('firstChild - Item 12 has first child 11', () => { const family = getFamily(items2); expect(family.firstChild(12)).toBe("11"); }); test('firstParent - Item 13 has first parent 14', () => { const family = getFamily(items2); expect(family.firstParent(13)).toBe("14"); });