197 lines
4.6 KiB
TypeScript
197 lines
4.6 KiB
TypeScript
import { describe, expect, it } from 'vitest';
|
|
|
|
import { filterTree, mapTree, traverseTreeValues } from './tree';
|
|
|
|
describe('traverseTreeValues', () => {
|
|
interface Node {
|
|
children?: Node[];
|
|
name: string;
|
|
}
|
|
|
|
type NodeValue = string;
|
|
|
|
const sampleTree: Node[] = [
|
|
{
|
|
name: 'A',
|
|
children: [
|
|
{ name: 'B' },
|
|
{
|
|
name: 'C',
|
|
children: [{ name: 'D' }, { name: 'E' }],
|
|
},
|
|
],
|
|
},
|
|
{
|
|
name: 'F',
|
|
children: [
|
|
{ name: 'G' },
|
|
{
|
|
name: 'H',
|
|
children: [{ name: 'I' }],
|
|
},
|
|
],
|
|
},
|
|
];
|
|
|
|
it('traverses tree and returns all node values', () => {
|
|
const values = traverseTreeValues<Node, NodeValue>(
|
|
sampleTree,
|
|
(node) => node.name,
|
|
{
|
|
childProps: 'children',
|
|
},
|
|
);
|
|
expect(values).toEqual(['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I']);
|
|
});
|
|
|
|
it('handles empty tree', () => {
|
|
const values = traverseTreeValues<Node, NodeValue>([], (node) => node.name);
|
|
expect(values).toEqual([]);
|
|
});
|
|
|
|
it('handles tree with only root node', () => {
|
|
const rootNode = { name: 'A' };
|
|
const values = traverseTreeValues<Node, NodeValue>(
|
|
[rootNode],
|
|
(node) => node.name,
|
|
);
|
|
expect(values).toEqual(['A']);
|
|
});
|
|
|
|
it('handles tree with only leaf nodes', () => {
|
|
const leafNodes = [{ name: 'A' }, { name: 'B' }, { name: 'C' }];
|
|
const values = traverseTreeValues<Node, NodeValue>(
|
|
leafNodes,
|
|
(node) => node.name,
|
|
);
|
|
expect(values).toEqual(['A', 'B', 'C']);
|
|
});
|
|
});
|
|
|
|
describe('filterTree', () => {
|
|
const tree = [
|
|
{
|
|
id: 1,
|
|
children: [
|
|
{ id: 2 },
|
|
{ id: 3, children: [{ id: 4 }, { id: 5 }, { id: 6 }] },
|
|
{ id: 7 },
|
|
],
|
|
},
|
|
{ id: 8, children: [{ id: 9 }, { id: 10 }] },
|
|
{ id: 11 },
|
|
];
|
|
|
|
it('should return all nodes when condition is always true', () => {
|
|
const result = filterTree(tree, () => true, { childProps: 'children' });
|
|
expect(result).toEqual(tree);
|
|
});
|
|
|
|
it('should return only root nodes when condition is always false', () => {
|
|
const result = filterTree(tree, () => false);
|
|
expect(result).toEqual([]);
|
|
});
|
|
|
|
it('should return nodes with even id values', () => {
|
|
const result = filterTree(tree, (node) => node.id % 2 === 0);
|
|
expect(result).toEqual([{ id: 8, children: [{ id: 10 }] }]);
|
|
});
|
|
|
|
it('should return nodes with odd id values and their ancestors', () => {
|
|
const result = filterTree(tree, (node) => node.id % 2 === 1);
|
|
expect(result).toEqual([
|
|
{
|
|
id: 1,
|
|
children: [{ id: 3, children: [{ id: 5 }] }, { id: 7 }],
|
|
},
|
|
{ id: 11 },
|
|
]);
|
|
});
|
|
|
|
it('should return nodes with "leaf" in their name', () => {
|
|
const tree = [
|
|
{
|
|
name: 'root',
|
|
children: [
|
|
{ name: 'leaf 1' },
|
|
{
|
|
name: 'branch',
|
|
children: [{ name: 'leaf 2' }, { name: 'leaf 3' }],
|
|
},
|
|
{ name: 'leaf 4' },
|
|
],
|
|
},
|
|
];
|
|
const result = filterTree(
|
|
tree,
|
|
(node) => node.name.includes('leaf') || node.name === 'root',
|
|
);
|
|
expect(result).toEqual([
|
|
{
|
|
name: 'root',
|
|
children: [{ name: 'leaf 1' }, { name: 'leaf 4' }],
|
|
},
|
|
]);
|
|
});
|
|
});
|
|
|
|
describe('mapTree', () => {
|
|
it('map infinite depth tree using mapTree', () => {
|
|
const tree = [
|
|
{
|
|
id: 1,
|
|
name: 'node1',
|
|
children: [
|
|
{ id: 2, name: 'node2' },
|
|
{ id: 3, name: 'node3' },
|
|
{
|
|
id: 4,
|
|
name: 'node4',
|
|
children: [
|
|
{
|
|
id: 5,
|
|
name: 'node5',
|
|
children: [
|
|
{ id: 6, name: 'node6' },
|
|
{ id: 7, name: 'node7' },
|
|
],
|
|
},
|
|
{ id: 8, name: 'node8' },
|
|
],
|
|
},
|
|
],
|
|
},
|
|
];
|
|
const newTree = mapTree(tree, (node) => ({
|
|
...node,
|
|
name: `${node.name}-new`,
|
|
}));
|
|
|
|
expect(newTree).toEqual([
|
|
{
|
|
id: 1,
|
|
name: 'node1-new',
|
|
children: [
|
|
{ id: 2, name: 'node2-new' },
|
|
{ id: 3, name: 'node3-new' },
|
|
{
|
|
id: 4,
|
|
name: 'node4-new',
|
|
children: [
|
|
{
|
|
id: 5,
|
|
name: 'node5-new',
|
|
children: [
|
|
{ id: 6, name: 'node6-new' },
|
|
{ id: 7, name: 'node7-new' },
|
|
],
|
|
},
|
|
{ id: 8, name: 'node8-new' },
|
|
],
|
|
},
|
|
],
|
|
},
|
|
]);
|
|
});
|
|
});
|