github.com/turbot/steampipe@v1.7.0-rc.0.0.20240517123944-7cef272d4458/ui/dashboard/src/components/dashboards/common/index.test.ts (about) 1 import "../../../test/matchMedia"; 2 import { 3 adjustMinValue, 4 adjustMaxValue, 5 buildNodesAndEdges, 6 foldNodesAndEdges, 7 themeColors, 8 } from "./index"; 9 import { Edge, Node } from "./types"; 10 import { Graph } from "graphlib"; 11 12 describe("common.adjustMinValue", () => { 13 test("5", () => { 14 expect(adjustMinValue(5)).toEqual(0); 15 }); 16 17 test("-8", () => { 18 expect(adjustMinValue(-8)).toEqual(-9); 19 }); 20 21 test("-13", () => { 22 expect(adjustMinValue(-13)).toEqual(-14); 23 }); 24 25 test("-20", () => { 26 expect(adjustMinValue(-20)).toEqual(-25); 27 }); 28 29 test("-26", () => { 30 expect(adjustMinValue(-26)).toEqual(-30); 31 }); 32 33 test("-35", () => { 34 expect(adjustMinValue(-35)).toEqual(-40); 35 }); 36 37 test("-50", () => { 38 expect(adjustMinValue(-50)).toEqual(-60); 39 }); 40 41 test("-52", () => { 42 expect(adjustMinValue(-52)).toEqual(-60); 43 }); 44 45 test("-180", () => { 46 expect(adjustMinValue(-180)).toEqual(-190); 47 }); 48 49 test("-210", () => { 50 expect(adjustMinValue(-200)).toEqual(-250); 51 }); 52 53 test("-250", () => { 54 expect(adjustMinValue(-250)).toEqual(-300); 55 }); 56 57 test("-362", () => { 58 expect(adjustMinValue(-362)).toEqual(-400); 59 }); 60 61 test("-1000", () => { 62 expect(adjustMinValue(-1000)).toEqual(-1100); 63 }); 64 65 test("-2363", () => { 66 expect(adjustMinValue(-2363)).toEqual(-2400); 67 }); 68 69 test("-7001", () => { 70 expect(adjustMinValue(-7001)).toEqual(-7100); 71 }); 72 73 test("-10000", () => { 74 expect(adjustMinValue(-10000)).toEqual(-11000); 75 }); 76 77 test("-26526", () => { 78 expect(adjustMinValue(-26526)).toEqual(-27000); 79 }); 80 }); 81 82 describe("common.adjustMaxValue", () => { 83 test("-5", () => { 84 expect(adjustMaxValue(-5)).toEqual(0); 85 }); 86 87 test("8", () => { 88 expect(adjustMaxValue(8)).toEqual(9); 89 }); 90 91 test("13", () => { 92 expect(adjustMaxValue(13)).toEqual(14); 93 }); 94 95 test("20", () => { 96 expect(adjustMaxValue(20)).toEqual(25); 97 }); 98 99 test("26", () => { 100 expect(adjustMaxValue(26)).toEqual(30); 101 }); 102 103 test("35", () => { 104 expect(adjustMaxValue(35)).toEqual(40); 105 }); 106 107 test("50", () => { 108 expect(adjustMaxValue(50)).toEqual(60); 109 }); 110 111 test("52", () => { 112 expect(adjustMaxValue(52)).toEqual(60); 113 }); 114 115 test("180", () => { 116 expect(adjustMaxValue(180)).toEqual(190); 117 }); 118 119 test("210", () => { 120 expect(adjustMaxValue(210)).toEqual(250); 121 }); 122 123 test("250", () => { 124 expect(adjustMaxValue(250)).toEqual(300); 125 }); 126 127 test("362", () => { 128 expect(adjustMaxValue(362)).toEqual(400); 129 }); 130 131 test("1000", () => { 132 expect(adjustMaxValue(1000)).toEqual(1100); 133 }); 134 135 test("2363", () => { 136 expect(adjustMaxValue(2363)).toEqual(2400); 137 }); 138 139 test("7001", () => { 140 expect(adjustMaxValue(7001)).toEqual(7100); 141 }); 142 143 test("10000", () => { 144 expect(adjustMaxValue(10000)).toEqual(11000); 145 }); 146 147 test("26526", () => { 148 expect(adjustMaxValue(26526)).toEqual(27000); 149 }); 150 }); 151 152 describe("common.buildNodesAndEdges", () => { 153 test("single node", () => { 154 const rawData = { 155 columns: [{ name: "id", data_type: "TEXT" }], 156 rows: [{ id: "node" }], 157 }; 158 const node = { 159 id: "node", 160 title: null, 161 category: null, 162 depth: null, 163 row_data: { id: "node" }, 164 href: null, 165 symbol: null, 166 isFolded: false, 167 }; 168 const nodesAndEdges = buildNodesAndEdges({}, rawData); 169 delete nodesAndEdges.graph; 170 expect(nodesAndEdges).toEqual({ 171 categories: {}, 172 edgeMap: {}, 173 edges: [], 174 metadata: { contains_duplicate_edges: false, has_multiple_roots: false }, 175 next_color_index: 0, 176 nodeCategoryMap: {}, 177 nodeMap: { [node.id]: node }, 178 nodes: [node], 179 root_nodes: { 180 node, 181 }, 182 }); 183 }); 184 185 test("single node with depth", () => { 186 const rawData = { 187 columns: [ 188 { name: "id", data_type: "TEXT" }, 189 { name: "depth", data_type: "INT4" }, 190 ], 191 rows: [{ id: "node", depth: 0 }], 192 }; 193 const node = { 194 id: "node", 195 title: null, 196 category: null, 197 depth: 0, 198 row_data: { id: "node", depth: 0 }, 199 href: null, 200 symbol: null, 201 isFolded: false, 202 }; 203 const nodesAndEdges = buildNodesAndEdges({}, rawData); 204 delete nodesAndEdges.graph; 205 expect(nodesAndEdges).toEqual({ 206 categories: {}, 207 edgeMap: {}, 208 edges: [], 209 metadata: { contains_duplicate_edges: false, has_multiple_roots: false }, 210 next_color_index: 0, 211 nodeCategoryMap: {}, 212 nodeMap: { [node.id]: node }, 213 nodes: [node], 214 root_nodes: { 215 node, 216 }, 217 }); 218 }); 219 220 test("single node with category", () => { 221 const rawData = { 222 columns: [ 223 { name: "id", data_type: "TEXT" }, 224 { name: "category", data_type: "TEXT" }, 225 ], 226 rows: [{ id: "node", category: "c1" }], 227 }; 228 const node = { 229 id: "node", 230 title: null, 231 category: "c1", 232 depth: null, 233 row_data: rawData.rows[0], 234 href: null, 235 symbol: null, 236 isFolded: false, 237 }; 238 const nodesAndEdges = buildNodesAndEdges({}, rawData); 239 delete nodesAndEdges.graph; 240 expect(nodesAndEdges).toEqual({ 241 categories: { 242 c1: { 243 color: themeColors[0], 244 }, 245 }, 246 edgeMap: {}, 247 edges: [], 248 metadata: { contains_duplicate_edges: false, has_multiple_roots: false }, 249 next_color_index: 1, 250 nodeCategoryMap: { c1: { [node.id]: node } }, 251 nodeMap: { [node.id]: node }, 252 nodes: [node], 253 root_nodes: { 254 node, 255 }, 256 }); 257 }); 258 259 test("single node with from_id", () => { 260 const rawData = { 261 columns: [ 262 { name: "id", data_type: "TEXT" }, 263 { name: "from_id", data_type: "TEXT" }, 264 ], 265 rows: [{ id: "node", from_id: "from_node" }], 266 }; 267 const nodesAndEdges = buildNodesAndEdges({}, rawData); 268 delete nodesAndEdges.graph; 269 const sourceNode = { 270 id: "from_node", 271 title: null, 272 category: null, 273 depth: null, 274 row_data: null, 275 href: null, 276 symbol: null, 277 isFolded: false, 278 }; 279 const targetNode = { 280 id: "node", 281 title: null, 282 category: null, 283 depth: null, 284 row_data: { id: "node", from_id: "from_node" }, 285 href: null, 286 symbol: null, 287 isFolded: false, 288 }; 289 const edge = { 290 id: "from_node_node", 291 from_id: "from_node", 292 to_id: "node", 293 title: null, 294 category: null, 295 row_data: null, 296 isFolded: false, 297 }; 298 expect(nodesAndEdges).toEqual({ 299 categories: {}, 300 edgeMap: { [edge.id]: edge }, 301 edges: [edge], 302 metadata: { contains_duplicate_edges: false, has_multiple_roots: false }, 303 next_color_index: 0, 304 nodeCategoryMap: {}, 305 nodeMap: { [targetNode.id]: targetNode, [sourceNode.id]: sourceNode }, 306 nodes: [targetNode, sourceNode], 307 root_nodes: { 308 [sourceNode.id]: sourceNode, 309 }, 310 }); 311 }); 312 313 test("single node with to_id", () => { 314 const rawData = { 315 columns: [ 316 { name: "id", data_type: "TEXT" }, 317 { name: "to_id", data_type: "TEXT" }, 318 ], 319 rows: [{ id: "node", to_id: "to_node" }], 320 }; 321 const sourceNode = { 322 id: "node", 323 title: null, 324 category: null, 325 depth: null, 326 row_data: { id: "node", to_id: "to_node" }, 327 href: null, 328 symbol: null, 329 isFolded: false, 330 }; 331 const targetNode = { 332 id: "to_node", 333 title: null, 334 category: null, 335 depth: null, 336 row_data: null, 337 href: null, 338 symbol: null, 339 isFolded: false, 340 }; 341 const edge = { 342 id: "node_to_node", 343 from_id: "node", 344 to_id: "to_node", 345 title: null, 346 category: null, 347 row_data: null, 348 isFolded: false, 349 }; 350 const nodesAndEdges = buildNodesAndEdges({}, rawData); 351 delete nodesAndEdges.graph; 352 expect(nodesAndEdges).toEqual({ 353 categories: {}, 354 edgeMap: { [edge.id]: edge }, 355 edges: [edge], 356 metadata: { contains_duplicate_edges: false, has_multiple_roots: false }, 357 next_color_index: 0, 358 nodeCategoryMap: {}, 359 nodeMap: { [sourceNode.id]: sourceNode, [targetNode.id]: targetNode }, 360 nodes: [sourceNode, targetNode], 361 root_nodes: { 362 node: sourceNode, 363 }, 364 }); 365 }); 366 367 test("single node with from_id and to_id", () => { 368 const rawData = { 369 columns: [ 370 { name: "id", data_type: "TEXT" }, 371 { name: "from_id", data_type: "TEXT" }, 372 { name: "to_id", data_type: "TEXT" }, 373 ], 374 rows: [{ id: "node", from_id: "from_node", to_id: "to_node" }], 375 }; 376 const edge = { 377 id: "from_node_to_node", 378 from_id: "from_node", 379 to_id: "to_node", 380 title: null, 381 category: null, 382 row_data: null, 383 isFolded: false, 384 }; 385 const node = { 386 id: "node", 387 title: null, 388 category: null, 389 depth: null, 390 row_data: { id: "node", from_id: "from_node", to_id: "to_node" }, 391 href: null, 392 symbol: null, 393 isFolded: false, 394 }; 395 const sourceNode = { 396 id: "from_node", 397 title: null, 398 category: null, 399 depth: null, 400 row_data: null, 401 href: null, 402 symbol: null, 403 isFolded: false, 404 }; 405 const targetNode = { 406 id: "to_node", 407 title: null, 408 category: null, 409 depth: null, 410 row_data: null, 411 href: null, 412 symbol: null, 413 isFolded: false, 414 }; 415 const nodesAndEdges = buildNodesAndEdges({}, rawData); 416 delete nodesAndEdges.graph; 417 expect(nodesAndEdges).toEqual({ 418 categories: {}, 419 edgeMap: { [edge.id]: edge }, 420 edges: [edge], 421 metadata: { contains_duplicate_edges: false, has_multiple_roots: true }, 422 next_color_index: 0, 423 nodeCategoryMap: {}, 424 nodeMap: { 425 [node.id]: node, 426 [sourceNode.id]: sourceNode, 427 [targetNode.id]: targetNode, 428 }, 429 nodes: [node, sourceNode, targetNode], 430 root_nodes: { 431 node, 432 from_node: sourceNode, 433 }, 434 }); 435 }); 436 437 test("two nodes with separate edge declaration", () => { 438 const rawData = { 439 columns: [ 440 { name: "id", data_type: "TEXT" }, 441 { name: "from_id", data_type: "TEXT" }, 442 { name: "to_id", data_type: "TEXT" }, 443 { name: "depth", data_type: "INT4" }, 444 ], 445 rows: [ 446 { id: "from_node", depth: 0 }, 447 { id: "to_node", depth: 1 }, 448 { from_id: "from_node", to_id: "to_node" }, 449 ], 450 }; 451 const edge = { 452 id: "from_node_to_node", 453 from_id: "from_node", 454 to_id: "to_node", 455 title: null, 456 category: null, 457 row_data: { from_id: "from_node", to_id: "to_node" }, 458 isFolded: false, 459 }; 460 const sourceNode = { 461 id: "from_node", 462 title: null, 463 category: null, 464 depth: 0, 465 row_data: { id: "from_node", depth: 0 }, 466 href: null, 467 symbol: null, 468 isFolded: false, 469 }; 470 const targetNode = { 471 id: "to_node", 472 title: null, 473 category: null, 474 depth: 1, 475 row_data: { id: "to_node", depth: 1 }, 476 href: null, 477 symbol: null, 478 isFolded: false, 479 }; 480 const nodesAndEdges = buildNodesAndEdges({}, rawData); 481 delete nodesAndEdges.graph; 482 expect(nodesAndEdges).toEqual({ 483 categories: {}, 484 edgeMap: { [edge.id]: edge }, 485 edges: [edge], 486 metadata: { contains_duplicate_edges: false, has_multiple_roots: false }, 487 next_color_index: 0, 488 nodeCategoryMap: {}, 489 nodeMap: { [sourceNode.id]: sourceNode, [targetNode.id]: targetNode }, 490 nodes: [sourceNode, targetNode], 491 root_nodes: { 492 from_node: sourceNode, 493 }, 494 }); 495 }); 496 497 test("two nodes with separate edge declaration and title set on explicit node rows", () => { 498 const rawData = { 499 columns: [ 500 { name: "id", data_type: "TEXT" }, 501 { name: "from_id", data_type: "TEXT" }, 502 { name: "to_id", data_type: "TEXT" }, 503 { name: "depth", data_type: "INT4" }, 504 ], 505 rows: [ 506 { from_id: "from_node", to_id: "to_node" }, 507 { id: "from_node", depth: 0, title: "from_node" }, 508 { id: "to_node", depth: 1, title: "to_node" }, 509 ], 510 }; 511 const edge = { 512 id: "from_node_to_node", 513 from_id: "from_node", 514 to_id: "to_node", 515 title: null, 516 category: null, 517 row_data: { from_id: "from_node", to_id: "to_node" }, 518 isFolded: false, 519 }; 520 const sourceNode = { 521 id: "from_node", 522 title: "from_node", 523 category: null, 524 depth: 0, 525 row_data: { id: "from_node", depth: 0, title: "from_node" }, 526 href: null, 527 symbol: null, 528 isFolded: false, 529 }; 530 const targetNode = { 531 id: "to_node", 532 title: "to_node", 533 category: null, 534 depth: 1, 535 row_data: { id: "to_node", depth: 1, title: "to_node" }, 536 href: null, 537 symbol: null, 538 isFolded: false, 539 }; 540 const nodesAndEdges = buildNodesAndEdges({}, rawData); 541 delete nodesAndEdges.graph; 542 expect(nodesAndEdges).toEqual({ 543 categories: {}, 544 edgeMap: { [edge.id]: edge }, 545 edges: [edge], 546 metadata: { contains_duplicate_edges: false, has_multiple_roots: false }, 547 next_color_index: 0, 548 nodeCategoryMap: {}, 549 nodeMap: { [sourceNode.id]: sourceNode, [targetNode.id]: targetNode }, 550 nodes: [sourceNode, targetNode], 551 root_nodes: { 552 from_node: sourceNode, 553 }, 554 }); 555 }); 556 557 test("two nodes with separate edge declaration including properties", () => { 558 const rawData = { 559 columns: [ 560 { name: "id", data_type: "TEXT" }, 561 { name: "from_id", data_type: "TEXT" }, 562 { name: "to_id", data_type: "TEXT" }, 563 { name: "title", data_type: "TEXT" }, 564 { name: "properties", data_type: "jsonb" }, 565 ], 566 rows: [ 567 { id: "from_node", title: "From Node", properties: { foo: "bar" } }, 568 { id: "to_node", title: "To Node", properties: { bar: "foo" } }, 569 { 570 from_id: "from_node", 571 to_id: "to_node", 572 title: "The Edge", 573 properties: { foobar: "barfoo" }, 574 }, 575 ], 576 }; 577 const edge = { 578 id: "from_node_to_node", 579 from_id: "from_node", 580 to_id: "to_node", 581 title: "The Edge", 582 category: null, 583 row_data: { 584 from_id: "from_node", 585 to_id: "to_node", 586 title: "The Edge", 587 properties: { foobar: "barfoo" }, 588 }, 589 isFolded: false, 590 }; 591 const sourceNode = { 592 id: "from_node", 593 title: "From Node", 594 category: null, 595 depth: null, 596 row_data: { 597 id: "from_node", 598 title: "From Node", 599 properties: { foo: "bar" }, 600 }, 601 href: null, 602 symbol: null, 603 isFolded: false, 604 }; 605 const targetNode = { 606 id: "to_node", 607 title: "To Node", 608 category: null, 609 depth: null, 610 row_data: { 611 id: "to_node", 612 title: "To Node", 613 properties: { bar: "foo" }, 614 }, 615 href: null, 616 symbol: null, 617 isFolded: false, 618 }; 619 const nodesAndEdges = buildNodesAndEdges({}, rawData); 620 delete nodesAndEdges.graph; 621 expect(nodesAndEdges).toEqual({ 622 categories: {}, 623 edgeMap: { [edge.id]: edge }, 624 edges: [edge], 625 metadata: { contains_duplicate_edges: false, has_multiple_roots: false }, 626 next_color_index: 0, 627 nodeCategoryMap: {}, 628 nodeMap: { [sourceNode.id]: sourceNode, [targetNode.id]: targetNode }, 629 nodes: [sourceNode, targetNode], 630 root_nodes: { 631 from_node: sourceNode, 632 }, 633 }); 634 }); 635 636 // test("single node with title", () => { 637 // const rawData = { 638 // columns: [ 639 // { name: "id", data_type: "TEXT" }, 640 // { name: "title", data_type: "TEXT" }, 641 // ], 642 // rows: [{ id: "a_node", title: "A Node Title" }], 643 // }; 644 // expect(buildNodesAndEdges(rawData)).toEqual({ 645 // categories: {}, 646 // edges: [], 647 // metadata: { contains_duplicate_edges: false, has_multiple_roots: false }, 648 // next_color_index: 0, 649 // nodes: [ 650 // { category: null, depth: null, id: "a_node", title: "A Node Title" }, 651 // ], 652 // root_nodes: { 653 // a_node: { 654 // category: null, 655 // depth: null, 656 // id: "a_node", 657 // title: "A Node Title", 658 // }, 659 // }, 660 // }); 661 // }); 662 // 663 // test("single node with category", () => { 664 // const rawData = { 665 // columns: [ 666 // { name: "id", data_type: "TEXT" }, 667 // { name: "category", data_type: "TEXT" }, 668 // ], 669 // rows: [{ id: "a_node", category: "a_category" }], 670 // }; 671 // expect(buildNodesAndEdges(rawData)).toEqual({ 672 // categories: {}, 673 // edges: [], 674 // metadata: { contains_duplicate_edges: false, has_multiple_roots: false }, 675 // next_color_index: 0, 676 // nodes: [ 677 // { category: "a_category", depth: null, id: "a_node", title: null }, 678 // ], 679 // root_nodes: { 680 // a_node: { 681 // category: "a_category", 682 // depth: null, 683 // id: "a_node", 684 // title: null, 685 // }, 686 // }, 687 // }); 688 // }); 689 }); 690 691 const createNode = ({ id, category }): Node => { 692 return { 693 id, 694 category, 695 depth: null, 696 href: null, 697 isFolded: false, 698 row_data: null, 699 symbol: null, 700 title: null, 701 }; 702 }; 703 704 const createEdge = ({ id, from_id, to_id }): Edge => { 705 return { 706 id, 707 from_id, 708 to_id, 709 category: null, 710 row_data: null, 711 title: null, 712 isFolded: false, 713 }; 714 }; 715 716 describe("common.foldNodesAndEdges", () => { 717 test("Basic fold", () => { 718 const graph = new Graph({ directed: true }); 719 graph.setNode("c1-1"); 720 graph.setNode("c2-1"); 721 graph.setNode("c2-2"); 722 graph.setNode("c2-3"); 723 graph.setEdge("c1-1", "c2-1"); 724 graph.setEdge("c1-1", "c2-2"); 725 graph.setEdge("c1-1", "c2-3"); 726 const node_c1_1 = createNode({ 727 id: "c1-1", 728 category: "c1", 729 }); 730 const node_c2_1 = createNode({ 731 id: "c2-1", 732 category: "c2", 733 }); 734 const node_c2_2 = createNode({ 735 id: "c2-2", 736 category: "c2", 737 }); 738 const node_c2_3 = createNode({ 739 id: "c2-3", 740 category: "c2", 741 }); 742 const edge_c1_1_c2_1 = createEdge({ 743 id: "c1-1_c2-1", 744 from_id: "c1-1", 745 to_id: "c2-1", 746 }); 747 const edge_c1_1_c2_2 = createEdge({ 748 id: "c1-1_c2-2", 749 from_id: "c1-1", 750 to_id: "c2-2", 751 }); 752 const edge_c1_1_c2_3 = createEdge({ 753 id: "c1-1_c2-3", 754 from_id: "c1-1", 755 to_id: "c2-3", 756 }); 757 const category_1 = { id: "c1" }; 758 const category_2 = { id: "c2", fold: { threshold: 2 } }; 759 const nodesAndEdgesInput = { 760 graph, 761 nodeCategoryMap: { 762 c1: { 763 [node_c1_1.id]: node_c1_1, 764 }, 765 c2: { 766 [node_c2_1.id]: node_c2_1, 767 [node_c2_2.id]: node_c2_2, 768 [node_c2_3.id]: node_c2_3, 769 }, 770 }, 771 nodeMap: { 772 [node_c1_1.id]: node_c1_1, 773 [node_c2_1.id]: node_c2_1, 774 [node_c2_2.id]: node_c2_2, 775 [node_c2_3.id]: node_c2_3, 776 }, 777 nodes: [node_c1_1, node_c2_1, node_c2_2, node_c2_3], 778 edgeMap: { 779 [edge_c1_1_c2_1.id]: edge_c1_1_c2_1, 780 [edge_c1_1_c2_2.id]: edge_c1_1_c2_2, 781 [edge_c1_1_c2_3.id]: edge_c1_1_c2_3, 782 }, 783 edges: [edge_c1_1_c2_1, edge_c1_1_c2_2, edge_c1_1_c2_3], 784 root_nodes: { [node_c1_1.id]: node_c1_1 }, 785 categories: { [category_1.id]: category_1, [category_2.id]: category_2 }, 786 }; 787 // @ts-ignore 788 const nodesAndEdges = foldNodesAndEdges(nodesAndEdgesInput); 789 delete nodesAndEdges.graph; 790 const foldedNode = { 791 id: "fold-c2-1", 792 category: "c2", 793 depth: null, 794 href: null, 795 icon: undefined, 796 isFolded: true, 797 foldedNodes: [ 798 { id: node_c2_1.id, title: node_c2_1.title }, 799 { id: node_c2_2.id, title: node_c2_2.title }, 800 { id: node_c2_3.id, title: node_c2_3.title }, 801 ], 802 row_data: null, 803 symbol: null, 804 title: null, 805 }; 806 expect(nodesAndEdges).toEqual({ 807 nodeCategoryMap: { 808 c1: { 809 [node_c1_1.id]: node_c1_1, 810 }, 811 c2: { 812 [foldedNode.id]: foldedNode, 813 }, 814 }, 815 nodeMap: { 816 [node_c1_1.id]: node_c1_1, 817 [foldedNode.id]: foldedNode, 818 }, 819 nodes: [node_c1_1, foldedNode], 820 edgeMap: { 821 "c1-1_fold-c2-1": { 822 id: "c1-1_fold-c2-1", 823 from_id: "c1-1", 824 to_id: "fold-c2-1", 825 category: null, 826 title: null, 827 isFolded: true, 828 row_data: null, 829 }, 830 }, 831 edges: [ 832 { 833 id: "c1-1_fold-c2-1", 834 from_id: "c1-1", 835 to_id: "fold-c2-1", 836 category: null, 837 title: null, 838 isFolded: true, 839 row_data: null, 840 }, 841 ], 842 root_nodes: { [node_c1_1.id]: node_c1_1 }, 843 categories: { [category_1.id]: category_1, [category_2.id]: category_2 }, 844 }); 845 }); 846 847 test("Middle fold", () => { 848 const graph = new Graph({ directed: true }); 849 graph.setNode("c1-1"); 850 graph.setNode("c2-1"); 851 graph.setNode("c2-2"); 852 graph.setNode("c2-3"); 853 graph.setNode("c3-1"); 854 graph.setEdge("c1-1", "c2-1"); 855 graph.setEdge("c1-1", "c2-2"); 856 graph.setEdge("c1-1", "c2-3"); 857 graph.setEdge("c3-1", "c2-1"); 858 graph.setEdge("c3-1", "c2-2"); 859 graph.setEdge("c3-1", "c2-3"); 860 const node_c1_1 = createNode({ 861 id: "c1-1", 862 category: "c1", 863 }); 864 const node_c2_1 = createNode({ 865 id: "c2-1", 866 category: "c2", 867 }); 868 const node_c2_2 = createNode({ 869 id: "c2-2", 870 category: "c2", 871 }); 872 const node_c2_3 = createNode({ 873 id: "c2-3", 874 category: "c2", 875 }); 876 const node_c3_1 = createNode({ 877 id: "c3-1", 878 category: "c3", 879 }); 880 const edge_c1_1_c2_1 = createEdge({ 881 id: "c1-1_c2-1", 882 from_id: "c1-1", 883 to_id: "c2-1", 884 }); 885 const edge_c1_1_c2_2 = createEdge({ 886 id: "c1-1_c2-2", 887 from_id: "c1-1", 888 to_id: "c2-2", 889 }); 890 const edge_c1_1_c2_3 = createEdge({ 891 id: "c1-1_c2-3", 892 from_id: "c1-1", 893 to_id: "c2-3", 894 }); 895 const edge_c3_1_c2_1 = createEdge({ 896 id: "c3-1_c2-1", 897 from_id: "c3-1", 898 to_id: "c2-1", 899 }); 900 const edge_c3_1_c2_2 = createEdge({ 901 id: "c3-1_c2-2", 902 from_id: "c3-1", 903 to_id: "c2-2", 904 }); 905 const edge_c3_1_c2_3 = createEdge({ 906 id: "c3-1_c2-3", 907 from_id: "c3-1", 908 to_id: "c2-3", 909 }); 910 const category_1 = { id: "c1" }; 911 const category_2 = { id: "c2", fold: { threshold: 2 } }; 912 const category_3 = { id: "c3" }; 913 const nodesAndEdgesInput = { 914 graph, 915 nodeCategoryMap: { 916 c1: { 917 [node_c1_1.id]: node_c1_1, 918 }, 919 c2: { 920 [node_c2_1.id]: node_c2_1, 921 [node_c2_2.id]: node_c2_2, 922 [node_c2_3.id]: node_c2_3, 923 }, 924 c3: { 925 [node_c3_1.id]: node_c3_1, 926 }, 927 }, 928 nodeMap: { 929 [node_c1_1.id]: node_c1_1, 930 [node_c2_1.id]: node_c2_1, 931 [node_c2_2.id]: node_c2_2, 932 [node_c2_3.id]: node_c2_3, 933 [node_c3_1.id]: node_c3_1, 934 }, 935 nodes: [node_c1_1, node_c2_1, node_c2_2, node_c2_3, node_c3_1], 936 edgeMap: { 937 [edge_c1_1_c2_1.id]: edge_c1_1_c2_1, 938 [edge_c1_1_c2_2.id]: edge_c1_1_c2_2, 939 [edge_c1_1_c2_3.id]: edge_c1_1_c2_3, 940 [edge_c3_1_c2_1.id]: edge_c3_1_c2_1, 941 [edge_c3_1_c2_2.id]: edge_c3_1_c2_2, 942 [edge_c3_1_c2_3.id]: edge_c3_1_c2_3, 943 }, 944 edges: [ 945 edge_c1_1_c2_1, 946 edge_c1_1_c2_2, 947 edge_c1_1_c2_3, 948 edge_c3_1_c2_1, 949 edge_c3_1_c2_2, 950 edge_c3_1_c2_3, 951 ], 952 root_nodes: { [node_c1_1.id]: node_c1_1, [node_c3_1.id]: node_c3_1 }, 953 categories: { 954 [category_1.id]: category_1, 955 [category_2.id]: category_2, 956 [category_3.id]: category_3, 957 }, 958 }; 959 // @ts-ignore 960 const nodesAndEdges = foldNodesAndEdges(nodesAndEdgesInput); 961 delete nodesAndEdges.graph; 962 const foldedNode = { 963 id: "fold-c2-1", 964 category: "c2", 965 depth: null, 966 href: null, 967 icon: undefined, 968 isFolded: true, 969 foldedNodes: [ 970 { id: node_c2_1.id, title: node_c2_1.title }, 971 { id: node_c2_2.id, title: node_c2_2.title }, 972 { id: node_c2_3.id, title: node_c2_3.title }, 973 ], 974 row_data: null, 975 symbol: null, 976 title: null, 977 }; 978 expect(nodesAndEdges).toEqual({ 979 nodeCategoryMap: { 980 c1: { 981 [node_c1_1.id]: node_c1_1, 982 }, 983 c2: { 984 [foldedNode.id]: foldedNode, 985 }, 986 c3: { 987 [node_c3_1.id]: node_c3_1, 988 }, 989 }, 990 nodeMap: { 991 [node_c1_1.id]: node_c1_1, 992 [node_c3_1.id]: node_c3_1, 993 [foldedNode.id]: foldedNode, 994 }, 995 nodes: [node_c1_1, node_c3_1, foldedNode], 996 edgeMap: { 997 "c1-1_fold-c2-1": { 998 id: "c1-1_fold-c2-1", 999 from_id: "c1-1", 1000 to_id: "fold-c2-1", 1001 category: null, 1002 title: null, 1003 isFolded: true, 1004 row_data: null, 1005 }, 1006 "c3-1_fold-c2-1": { 1007 id: "c3-1_fold-c2-1", 1008 from_id: "c3-1", 1009 to_id: "fold-c2-1", 1010 category: null, 1011 title: null, 1012 isFolded: true, 1013 row_data: null, 1014 }, 1015 }, 1016 edges: [ 1017 { 1018 id: "c1-1_fold-c2-1", 1019 from_id: "c1-1", 1020 to_id: "fold-c2-1", 1021 category: null, 1022 title: null, 1023 isFolded: true, 1024 row_data: null, 1025 }, 1026 { 1027 id: "c3-1_fold-c2-1", 1028 from_id: "c3-1", 1029 to_id: "fold-c2-1", 1030 category: null, 1031 title: null, 1032 isFolded: true, 1033 row_data: null, 1034 }, 1035 ], 1036 root_nodes: { [node_c1_1.id]: node_c1_1, [node_c3_1.id]: node_c3_1 }, 1037 categories: { 1038 [category_1.id]: category_1, 1039 [category_2.id]: category_2, 1040 [category_3.id]: category_3, 1041 }, 1042 }); 1043 }); 1044 1045 test("3-way fold", () => { 1046 const graph = new Graph({ directed: true }); 1047 graph.setNode("c1-1"); 1048 graph.setNode("c2-1"); 1049 graph.setNode("c2-2"); 1050 graph.setNode("c2-3"); 1051 graph.setNode("c3-1"); 1052 graph.setNode("c4-1"); 1053 graph.setEdge("c1-1", "c2-1"); 1054 graph.setEdge("c1-1", "c2-2"); 1055 graph.setEdge("c1-1", "c2-3"); 1056 graph.setEdge("c3-1", "c2-1"); 1057 graph.setEdge("c3-1", "c2-2"); 1058 graph.setEdge("c3-1", "c2-3"); 1059 graph.setEdge("c4-1", "c2-1"); 1060 graph.setEdge("c4-1", "c2-2"); 1061 graph.setEdge("c4-1", "c2-3"); 1062 const node_c1_1 = createNode({ 1063 id: "c1-1", 1064 category: "c1", 1065 }); 1066 const node_c2_1 = createNode({ 1067 id: "c2-1", 1068 category: "c2", 1069 }); 1070 const node_c2_2 = createNode({ 1071 id: "c2-2", 1072 category: "c2", 1073 }); 1074 const node_c2_3 = createNode({ 1075 id: "c2-3", 1076 category: "c2", 1077 }); 1078 const node_c3_1 = createNode({ 1079 id: "c3-1", 1080 category: "c3", 1081 }); 1082 const node_c4_1 = createNode({ 1083 id: "c4-1", 1084 category: "c4", 1085 }); 1086 const edge_c1_1_c2_1 = createEdge({ 1087 id: "c1-1_c2-1", 1088 from_id: "c1-1", 1089 to_id: "c2-1", 1090 }); 1091 const edge_c1_1_c2_2 = createEdge({ 1092 id: "c1-1_c2-2", 1093 from_id: "c1-1", 1094 to_id: "c2-2", 1095 }); 1096 const edge_c1_1_c2_3 = createEdge({ 1097 id: "c1-1_c2-3", 1098 from_id: "c1-1", 1099 to_id: "c2-3", 1100 }); 1101 const edge_c3_1_c2_1 = createEdge({ 1102 id: "c3-1_c2-1", 1103 from_id: "c3-1", 1104 to_id: "c2-1", 1105 }); 1106 const edge_c3_1_c2_2 = createEdge({ 1107 id: "c3-1_c2-2", 1108 from_id: "c3-1", 1109 to_id: "c2-2", 1110 }); 1111 const edge_c3_1_c2_3 = createEdge({ 1112 id: "c3-1_c2-3", 1113 from_id: "c3-1", 1114 to_id: "c2-3", 1115 }); 1116 const edge_c4_1_c2_1 = createEdge({ 1117 id: "c4-1_c2-1", 1118 from_id: "c4-1", 1119 to_id: "c2-1", 1120 }); 1121 const edge_c4_1_c2_2 = createEdge({ 1122 id: "c4-1_c2-2", 1123 from_id: "c4-1", 1124 to_id: "c2-2", 1125 }); 1126 const edge_c4_1_c2_3 = createEdge({ 1127 id: "c4-1_c2-3", 1128 from_id: "c4-1", 1129 to_id: "c2-3", 1130 }); 1131 const category_1 = { id: "c1" }; 1132 const category_2 = { id: "c2", fold: { threshold: 2 } }; 1133 const category_3 = { id: "c3" }; 1134 const category_4 = { id: "c4" }; 1135 const nodesAndEdgesInput = { 1136 graph, 1137 nodeCategoryMap: { 1138 c1: { 1139 [node_c1_1.id]: node_c1_1, 1140 }, 1141 c2: { 1142 [node_c2_1.id]: node_c2_1, 1143 [node_c2_2.id]: node_c2_2, 1144 [node_c2_3.id]: node_c2_3, 1145 }, 1146 c3: { 1147 [node_c3_1.id]: node_c3_1, 1148 }, 1149 c4: { 1150 [node_c4_1.id]: node_c4_1, 1151 }, 1152 }, 1153 edgeMap: { 1154 [edge_c1_1_c2_1.id]: edge_c1_1_c2_1, 1155 [edge_c1_1_c2_2.id]: edge_c1_1_c2_2, 1156 [edge_c1_1_c2_3.id]: edge_c1_1_c2_3, 1157 [edge_c3_1_c2_1.id]: edge_c3_1_c2_1, 1158 [edge_c3_1_c2_2.id]: edge_c3_1_c2_2, 1159 [edge_c3_1_c2_3.id]: edge_c3_1_c2_3, 1160 [edge_c4_1_c2_1.id]: edge_c4_1_c2_1, 1161 [edge_c4_1_c2_2.id]: edge_c4_1_c2_2, 1162 [edge_c4_1_c2_3.id]: edge_c4_1_c2_3, 1163 }, 1164 edges: [ 1165 edge_c1_1_c2_1, 1166 edge_c1_1_c2_2, 1167 edge_c1_1_c2_3, 1168 edge_c3_1_c2_1, 1169 edge_c3_1_c2_2, 1170 edge_c3_1_c2_3, 1171 edge_c4_1_c2_1, 1172 edge_c4_1_c2_2, 1173 edge_c4_1_c2_3, 1174 ], 1175 nodeMap: { 1176 [node_c1_1.id]: node_c1_1, 1177 [node_c2_1.id]: node_c2_1, 1178 [node_c2_2.id]: node_c2_2, 1179 [node_c2_3.id]: node_c2_3, 1180 [node_c3_1.id]: node_c3_1, 1181 [node_c4_1.id]: node_c4_1, 1182 }, 1183 nodes: [node_c1_1, node_c2_1, node_c2_2, node_c2_3, node_c3_1, node_c4_1], 1184 root_nodes: { 1185 [node_c1_1.id]: node_c1_1, 1186 [node_c3_1.id]: node_c3_1, 1187 [node_c4_1.id]: node_c4_1, 1188 }, 1189 categories: { 1190 [category_1.id]: category_1, 1191 [category_2.id]: category_2, 1192 [category_3.id]: category_3, 1193 [category_4.id]: category_4, 1194 }, 1195 }; 1196 // @ts-ignore 1197 const nodesAndEdges = foldNodesAndEdges(nodesAndEdgesInput); 1198 delete nodesAndEdges.graph; 1199 const foldedNode = { 1200 id: "fold-c2-1", 1201 category: "c2", 1202 depth: null, 1203 href: null, 1204 icon: undefined, 1205 isFolded: true, 1206 foldedNodes: [ 1207 { id: node_c2_1.id, title: node_c2_1.title }, 1208 { id: node_c2_2.id, title: node_c2_2.title }, 1209 { id: node_c2_3.id, title: node_c2_3.title }, 1210 ], 1211 row_data: null, 1212 symbol: null, 1213 title: null, 1214 }; 1215 expect(nodesAndEdges).toEqual({ 1216 nodeCategoryMap: { 1217 c1: { 1218 [node_c1_1.id]: node_c1_1, 1219 }, 1220 c2: { 1221 [foldedNode.id]: foldedNode, 1222 }, 1223 c3: { 1224 [node_c3_1.id]: node_c3_1, 1225 }, 1226 c4: { 1227 [node_c4_1.id]: node_c4_1, 1228 }, 1229 }, 1230 nodeMap: { 1231 [node_c1_1.id]: node_c1_1, 1232 [node_c3_1.id]: node_c3_1, 1233 [node_c4_1.id]: node_c4_1, 1234 [foldedNode.id]: foldedNode, 1235 }, 1236 nodes: [node_c1_1, node_c3_1, node_c4_1, foldedNode], 1237 edgeMap: { 1238 "c1-1_fold-c2-1": { 1239 id: "c1-1_fold-c2-1", 1240 from_id: "c1-1", 1241 to_id: "fold-c2-1", 1242 category: null, 1243 title: null, 1244 isFolded: true, 1245 row_data: null, 1246 }, 1247 "c3-1_fold-c2-1": { 1248 id: "c3-1_fold-c2-1", 1249 from_id: "c3-1", 1250 to_id: "fold-c2-1", 1251 category: null, 1252 title: null, 1253 isFolded: true, 1254 row_data: null, 1255 }, 1256 "c4-1_fold-c2-1": { 1257 id: "c4-1_fold-c2-1", 1258 from_id: "c4-1", 1259 to_id: "fold-c2-1", 1260 category: null, 1261 title: null, 1262 isFolded: true, 1263 row_data: null, 1264 }, 1265 }, 1266 edges: [ 1267 { 1268 id: "c1-1_fold-c2-1", 1269 from_id: "c1-1", 1270 to_id: "fold-c2-1", 1271 category: null, 1272 title: null, 1273 isFolded: true, 1274 row_data: null, 1275 }, 1276 { 1277 id: "c3-1_fold-c2-1", 1278 from_id: "c3-1", 1279 to_id: "fold-c2-1", 1280 category: null, 1281 title: null, 1282 isFolded: true, 1283 row_data: null, 1284 }, 1285 { 1286 id: "c4-1_fold-c2-1", 1287 from_id: "c4-1", 1288 to_id: "fold-c2-1", 1289 category: null, 1290 title: null, 1291 isFolded: true, 1292 row_data: null, 1293 }, 1294 ], 1295 root_nodes: { 1296 [node_c1_1.id]: node_c1_1, 1297 [node_c3_1.id]: node_c3_1, 1298 [node_c4_1.id]: node_c4_1, 1299 }, 1300 categories: { 1301 [category_1.id]: category_1, 1302 [category_2.id]: category_2, 1303 [category_3.id]: category_3, 1304 [category_4.id]: category_4, 1305 }, 1306 }); 1307 }); 1308 1309 test("Multiple inheritance", () => { 1310 const graph = new Graph({ directed: true }); 1311 graph.setNode("c1-1"); 1312 graph.setNode("c2-1"); 1313 graph.setNode("c2-2"); 1314 graph.setNode("c2-3"); 1315 graph.setNode("c3-1"); 1316 graph.setEdge("c1-1", "c2-1"); 1317 graph.setEdge("c1-1", "c2-2"); 1318 graph.setEdge("c1-1", "c2-3"); 1319 graph.setEdge("c3-1", "c2-3"); 1320 const node_c1_1 = createNode({ 1321 id: "c1-1", 1322 category: "c1", 1323 }); 1324 const node_c2_1 = createNode({ 1325 id: "c2-1", 1326 category: "c2", 1327 }); 1328 const node_c2_2 = createNode({ 1329 id: "c2-2", 1330 category: "c2", 1331 }); 1332 const node_c2_3 = createNode({ 1333 id: "c2-3", 1334 category: "c2", 1335 }); 1336 const node_c3_1 = createNode({ 1337 id: "c3-1", 1338 category: "c3", 1339 }); 1340 const edge_c1_1_c2_1 = createEdge({ 1341 id: "c1-1_c2-1", 1342 from_id: "c1-1", 1343 to_id: "c2-1", 1344 }); 1345 const edge_c1_1_c2_2 = createEdge({ 1346 id: "c1-1_c2-2", 1347 from_id: "c1-1", 1348 to_id: "c2-2", 1349 }); 1350 const edge_c1_1_c2_3 = createEdge({ 1351 id: "c1-1_c2-3", 1352 from_id: "c1-1", 1353 to_id: "c2-3", 1354 }); 1355 const edge_c3_1_c2_3 = createEdge({ 1356 id: "c3-1_c2-3", 1357 from_id: "c3-1", 1358 to_id: "c2-3", 1359 }); 1360 const category_1 = {}; 1361 const category_2 = { fold: { threshold: 2 } }; 1362 const category_3 = {}; 1363 const nodesAndEdgesInput = { 1364 graph, 1365 edgeMap: { 1366 [edge_c1_1_c2_1.id]: edge_c1_1_c2_1, 1367 [edge_c1_1_c2_2.id]: edge_c1_1_c2_2, 1368 [edge_c1_1_c2_3.id]: edge_c1_1_c2_3, 1369 [edge_c3_1_c2_3.id]: edge_c3_1_c2_3, 1370 }, 1371 edges: [edge_c1_1_c2_1, edge_c1_1_c2_2, edge_c1_1_c2_3, edge_c3_1_c2_3], 1372 nodeCategoryMap: { 1373 c1: { 1374 [node_c1_1.id]: node_c1_1, 1375 }, 1376 c2: { 1377 [node_c2_1.id]: node_c2_1, 1378 [node_c2_2.id]: node_c2_2, 1379 [node_c2_3.id]: node_c2_3, 1380 }, 1381 c3: { 1382 [node_c3_1.id]: node_c3_1, 1383 }, 1384 }, 1385 nodeMap: { 1386 [node_c1_1.id]: node_c1_1, 1387 [node_c2_1.id]: node_c2_1, 1388 [node_c2_2.id]: node_c2_2, 1389 [node_c2_3.id]: node_c2_3, 1390 [node_c3_1.id]: node_c3_1, 1391 }, 1392 nodes: [node_c1_1, node_c2_1, node_c2_2, node_c2_3, node_c3_1], 1393 root_nodes: { [node_c1_1.id]: node_c1_1, [node_c3_1.id]: node_c3_1 }, 1394 categories: { c1: category_1, c2: category_2, c3: category_3 }, 1395 }; 1396 // @ts-ignore 1397 const nodesAndEdges = foldNodesAndEdges(nodesAndEdgesInput); 1398 delete nodesAndEdges.graph; 1399 const foldedNode = { 1400 id: "fold-c2-1", 1401 category: "c2", 1402 depth: null, 1403 href: null, 1404 icon: undefined, 1405 isFolded: true, 1406 foldedNodes: [ 1407 { id: node_c2_1.id, title: node_c2_1.title }, 1408 { id: node_c2_2.id, title: node_c2_2.title }, 1409 ], 1410 row_data: null, 1411 symbol: null, 1412 title: null, 1413 }; 1414 expect(nodesAndEdges).toEqual({ 1415 nodeCategoryMap: { 1416 c1: { 1417 [node_c1_1.id]: node_c1_1, 1418 }, 1419 c2: { 1420 [node_c2_3.id]: node_c2_3, 1421 [foldedNode.id]: foldedNode, 1422 }, 1423 c3: { 1424 [node_c3_1.id]: node_c3_1, 1425 }, 1426 }, 1427 nodeMap: { 1428 [node_c1_1.id]: node_c1_1, 1429 [node_c2_3.id]: node_c2_3, 1430 [node_c3_1.id]: node_c3_1, 1431 [foldedNode.id]: foldedNode, 1432 }, 1433 nodes: [node_c1_1, node_c2_3, node_c3_1, foldedNode], 1434 edgeMap: { 1435 [edge_c1_1_c2_3.id]: edge_c1_1_c2_3, 1436 [edge_c3_1_c2_3.id]: edge_c3_1_c2_3, 1437 "c1-1_fold-c2-1": { 1438 id: "c1-1_fold-c2-1", 1439 from_id: "c1-1", 1440 to_id: "fold-c2-1", 1441 category: null, 1442 title: null, 1443 isFolded: true, 1444 row_data: null, 1445 }, 1446 }, 1447 edges: [ 1448 edge_c1_1_c2_3, 1449 edge_c3_1_c2_3, 1450 { 1451 id: "c1-1_fold-c2-1", 1452 from_id: "c1-1", 1453 to_id: "fold-c2-1", 1454 category: null, 1455 title: null, 1456 isFolded: true, 1457 row_data: null, 1458 }, 1459 ], 1460 root_nodes: { [node_c1_1.id]: node_c1_1, [node_c3_1.id]: node_c3_1 }, 1461 categories: { c1: category_1, c2: category_2, c3: category_3 }, 1462 }); 1463 }); 1464 1465 test("Edge direction is included in fold group decision, so this does not collapse", () => { 1466 const graph = new Graph({ directed: true }); 1467 graph.setNode("c1-1"); 1468 graph.setNode("c2-1"); 1469 graph.setNode("c2-2"); 1470 graph.setNode("c3-1"); 1471 graph.setEdge("c1-1", "c2-1"); 1472 graph.setEdge("c1-1", "c2-2"); 1473 graph.setEdge("c3-1", "c2-1"); 1474 graph.setEdge("c2-2", "c3-1"); 1475 const node_c1_1 = createNode({ 1476 id: "c1-1", 1477 category: "c1", 1478 }); 1479 const node_c2_1 = createNode({ 1480 id: "c2-1", 1481 category: "c2", 1482 }); 1483 const node_c2_2 = createNode({ 1484 id: "c2-2", 1485 category: "c2", 1486 }); 1487 const node_c3_1 = createNode({ 1488 id: "c3-1", 1489 category: "c3", 1490 }); 1491 const edge_c1_1_c2_1 = createEdge({ 1492 id: "c1-1_c2-1", 1493 from_id: "c1-1", 1494 to_id: "c2-1", 1495 }); 1496 const edge_c1_1_c2_2 = createEdge({ 1497 id: "c1-1_c2-2", 1498 from_id: "c1-1", 1499 to_id: "c2-2", 1500 }); 1501 const edge_c3_1_c2_1 = createEdge({ 1502 id: "c3-1_c2-1", 1503 from_id: "c3-1", 1504 to_id: "c2-1", 1505 }); 1506 const edge_c2_2_c3_1 = createEdge({ 1507 id: "c2-2_c3-1", 1508 from_id: "c2-2", 1509 to_id: "c3-1", 1510 }); 1511 const category_1 = { id: "c1" }; 1512 const category_2 = { id: "c2", fold: { threshold: 2 } }; 1513 const category_3 = { id: "c3" }; 1514 const nodesAndEdgesInput = { 1515 graph, 1516 nodeCategoryMap: { 1517 c1: { 1518 [node_c1_1.id]: node_c1_1, 1519 }, 1520 c2: { 1521 [node_c2_1.id]: node_c2_1, 1522 [node_c2_2.id]: node_c2_2, 1523 }, 1524 c3: { 1525 [node_c3_1.id]: node_c3_1, 1526 }, 1527 }, 1528 nodeMap: { 1529 [node_c1_1.id]: node_c1_1, 1530 [node_c2_1.id]: node_c2_1, 1531 [node_c2_2.id]: node_c2_2, 1532 [node_c3_1.id]: node_c3_1, 1533 }, 1534 nodes: [node_c1_1, node_c2_1, node_c2_2, node_c3_1], 1535 edgeMap: { 1536 [edge_c1_1_c2_1.id]: edge_c1_1_c2_1, 1537 [edge_c1_1_c2_2.id]: edge_c1_1_c2_2, 1538 [edge_c3_1_c2_1.id]: edge_c3_1_c2_1, 1539 [edge_c2_2_c3_1.id]: edge_c2_2_c3_1, 1540 }, 1541 edges: [edge_c1_1_c2_1, edge_c1_1_c2_2, edge_c3_1_c2_1, edge_c2_2_c3_1], 1542 root_nodes: { [node_c1_1.id]: node_c1_1 }, 1543 categories: { 1544 [category_1.id]: category_1, 1545 [category_2.id]: category_2, 1546 [category_3.id]: category_3, 1547 }, 1548 }; 1549 // @ts-ignore 1550 const nodesAndEdges = foldNodesAndEdges(nodesAndEdgesInput); 1551 delete nodesAndEdges.graph; 1552 delete nodesAndEdgesInput.graph; 1553 expect(nodesAndEdges).toEqual(nodesAndEdgesInput); 1554 }); 1555 1556 test("All edges are included in fold group decision", () => { 1557 const graph = new Graph({ directed: true }); 1558 graph.setNode("c1-1"); 1559 graph.setNode("c2-1"); 1560 graph.setNode("c2-2"); 1561 graph.setNode("c2-3"); 1562 graph.setNode("c3-1"); 1563 graph.setNode("c4-1"); 1564 graph.setEdge("c1-1", "c2-1"); 1565 graph.setEdge("c1-1", "c2-2"); 1566 graph.setEdge("c1-1", "c2-3"); 1567 graph.setEdge("c3-1", "c2-1"); 1568 graph.setEdge("c3-1", "c2-2"); 1569 graph.setEdge("c3-1", "c2-3"); 1570 graph.setEdge("c4-1", "c2-3"); 1571 const node_c1_1 = createNode({ 1572 id: "c1-1", 1573 category: "c1", 1574 }); 1575 const node_c2_1 = createNode({ 1576 id: "c2-1", 1577 category: "c2", 1578 }); 1579 const node_c2_2 = createNode({ 1580 id: "c2-2", 1581 category: "c2", 1582 }); 1583 const node_c2_3 = createNode({ 1584 id: "c2-3", 1585 category: "c2", 1586 }); 1587 const node_c3_1 = createNode({ 1588 id: "c3-1", 1589 category: "c3", 1590 }); 1591 const node_c4_1 = createNode({ 1592 id: "c4-1", 1593 category: "c4", 1594 }); 1595 const edge_c1_1_c2_1 = createEdge({ 1596 id: "c1-1_c2-1", 1597 from_id: "c1-1", 1598 to_id: "c2-1", 1599 }); 1600 const edge_c1_1_c2_2 = createEdge({ 1601 id: "c1-1_c2-2", 1602 from_id: "c1-1", 1603 to_id: "c2-2", 1604 }); 1605 const edge_c1_1_c2_3 = createEdge({ 1606 id: "c1-1_c2-3", 1607 from_id: "c1-1", 1608 to_id: "c2-3", 1609 }); 1610 const edge_c3_1_c2_1 = createEdge({ 1611 id: "c3-1_c2-1", 1612 from_id: "c3-1", 1613 to_id: "c2-1", 1614 }); 1615 const edge_c3_1_c2_2 = createEdge({ 1616 id: "c3-1_c2-2", 1617 from_id: "c3-1", 1618 to_id: "c2-2", 1619 }); 1620 const edge_c3_1_c2_3 = createEdge({ 1621 id: "c3-1_c2-3", 1622 from_id: "c3-1", 1623 to_id: "c2-3", 1624 }); 1625 const edge_c4_1_c2_3 = createEdge({ 1626 id: "c4-1_c2-3", 1627 from_id: "c4-1", 1628 to_id: "c2-3", 1629 }); 1630 const category_1 = { id: "c1" }; 1631 const category_2 = { id: "c2", fold: { threshold: 2 } }; 1632 const category_3 = { id: "c3" }; 1633 const category_4 = { id: "c4" }; 1634 const nodesAndEdgesInput = { 1635 graph, 1636 nodeCategoryMap: { 1637 c1: { 1638 [node_c1_1.id]: node_c1_1, 1639 }, 1640 c2: { 1641 [node_c2_1.id]: node_c2_1, 1642 [node_c2_2.id]: node_c2_2, 1643 [node_c2_3.id]: node_c2_3, 1644 }, 1645 c3: { 1646 [node_c3_1.id]: node_c3_1, 1647 }, 1648 c4: { 1649 [node_c4_1.id]: node_c4_1, 1650 }, 1651 }, 1652 nodeMap: { 1653 [node_c1_1.id]: node_c1_1, 1654 [node_c2_1.id]: node_c2_1, 1655 [node_c2_2.id]: node_c2_2, 1656 [node_c2_3.id]: node_c2_3, 1657 [node_c3_1.id]: node_c3_1, 1658 [node_c4_1.id]: node_c4_1, 1659 }, 1660 nodes: [node_c1_1, node_c2_1, node_c2_2, node_c2_3, node_c3_1, node_c4_1], 1661 edgeMap: { 1662 [edge_c1_1_c2_1.id]: edge_c1_1_c2_1, 1663 [edge_c1_1_c2_2.id]: edge_c1_1_c2_2, 1664 [edge_c1_1_c2_3.id]: edge_c1_1_c2_3, 1665 [edge_c3_1_c2_1.id]: edge_c3_1_c2_1, 1666 [edge_c3_1_c2_2.id]: edge_c3_1_c2_2, 1667 [edge_c3_1_c2_3.id]: edge_c3_1_c2_3, 1668 [edge_c4_1_c2_3.id]: edge_c4_1_c2_3, 1669 }, 1670 edges: [ 1671 edge_c1_1_c2_1, 1672 edge_c1_1_c2_2, 1673 edge_c1_1_c2_3, 1674 edge_c3_1_c2_1, 1675 edge_c3_1_c2_2, 1676 edge_c3_1_c2_3, 1677 edge_c4_1_c2_3, 1678 ], 1679 root_nodes: { 1680 [node_c1_1.id]: node_c1_1, 1681 [node_c3_1.id]: node_c3_1, 1682 [node_c4_1.id]: node_c4_1, 1683 }, 1684 categories: { 1685 [category_1.id]: category_1, 1686 [category_2.id]: category_2, 1687 [category_3.id]: category_3, 1688 [category_4.id]: category_4, 1689 }, 1690 }; 1691 // @ts-ignore 1692 const nodesAndEdges = foldNodesAndEdges(nodesAndEdgesInput); 1693 delete nodesAndEdges.graph; 1694 const foldedNode = { 1695 id: "fold-c2-1", 1696 category: "c2", 1697 depth: null, 1698 href: null, 1699 icon: undefined, 1700 isFolded: true, 1701 foldedNodes: [ 1702 { id: node_c2_1.id, title: node_c2_1.title }, 1703 { id: node_c2_2.id, title: node_c2_2.title }, 1704 ], 1705 row_data: null, 1706 symbol: null, 1707 title: null, 1708 }; 1709 expect(nodesAndEdges).toEqual({ 1710 nodeCategoryMap: { 1711 c1: { 1712 [node_c1_1.id]: node_c1_1, 1713 }, 1714 c2: { 1715 [node_c2_3.id]: node_c2_3, 1716 [foldedNode.id]: foldedNode, 1717 }, 1718 c3: { 1719 [node_c3_1.id]: node_c3_1, 1720 }, 1721 c4: { 1722 [node_c4_1.id]: node_c4_1, 1723 }, 1724 }, 1725 nodeMap: { 1726 [node_c1_1.id]: node_c1_1, 1727 [node_c2_3.id]: node_c2_3, 1728 [node_c3_1.id]: node_c3_1, 1729 [node_c4_1.id]: node_c4_1, 1730 [foldedNode.id]: foldedNode, 1731 }, 1732 nodes: [node_c1_1, node_c2_3, node_c3_1, node_c4_1, foldedNode], 1733 edgeMap: { 1734 [edge_c1_1_c2_3.id]: edge_c1_1_c2_3, 1735 [edge_c3_1_c2_3.id]: edge_c3_1_c2_3, 1736 [edge_c4_1_c2_3.id]: edge_c4_1_c2_3, 1737 "c1-1_fold-c2-1": { 1738 id: "c1-1_fold-c2-1", 1739 from_id: "c1-1", 1740 to_id: "fold-c2-1", 1741 category: null, 1742 title: null, 1743 isFolded: true, 1744 row_data: null, 1745 }, 1746 "c3-1_fold-c2-1": { 1747 id: "c3-1_fold-c2-1", 1748 from_id: "c3-1", 1749 to_id: "fold-c2-1", 1750 category: null, 1751 title: null, 1752 isFolded: true, 1753 row_data: null, 1754 }, 1755 }, 1756 edges: [ 1757 edge_c1_1_c2_3, 1758 edge_c3_1_c2_3, 1759 edge_c4_1_c2_3, 1760 { 1761 id: "c1-1_fold-c2-1", 1762 from_id: "c1-1", 1763 to_id: "fold-c2-1", 1764 category: null, 1765 title: null, 1766 isFolded: true, 1767 row_data: null, 1768 }, 1769 { 1770 id: "c3-1_fold-c2-1", 1771 from_id: "c3-1", 1772 to_id: "fold-c2-1", 1773 category: null, 1774 title: null, 1775 isFolded: true, 1776 row_data: null, 1777 }, 1778 ], 1779 root_nodes: { 1780 [node_c1_1.id]: node_c1_1, 1781 [node_c3_1.id]: node_c3_1, 1782 [node_c4_1.id]: node_c4_1, 1783 }, 1784 categories: { 1785 [category_1.id]: category_1, 1786 [category_2.id]: category_2, 1787 [category_3.id]: category_3, 1788 [category_4.id]: category_4, 1789 }, 1790 }); 1791 }); 1792 });