Fleet add gitrepo paths unit tests

Signed-off-by: Francesco Torchia <francesco.torchia@suse.com>
This commit is contained in:
Francesco Torchia 2025-06-12 16:15:17 +02:00
parent c8c40c55ff
commit 3c089c1f94
No known key found for this signature in database
GPG Key ID: E6D011B7415D4393
4 changed files with 379 additions and 2 deletions

View File

@ -35,7 +35,7 @@ function _cl(str: string) {
return trim;
}
function getRelevantPrefixes(paths: string[]): string[] {
export function getRelevantPrefixes(paths: string[]): string[] {
const prefixes: string[] = [];
getPrefixesRecursive(prefixes, paths, '', { name: '', children: pathArrayToTree(paths) });

View File

@ -0,0 +1,103 @@
import { getRelevantPrefixes } from '@shell/components/fleet/FleetGitRepoPaths.vue';
describe('fx: getRelevantPrefixes', () => {
it('should return an empty array for an empty input array', () => {
const paths: string[] = [];
expect(getRelevantPrefixes(paths)).toStrictEqual([]);
});
it('should return the single path if only one is provided', () => {
const paths: string[] = ['aaa'];
expect(getRelevantPrefixes(paths)).toStrictEqual(['aaa']);
});
it('should return only 2nd level prefixes', () => {
const paths: string[] = [
'folderA/aaa',
'folderA/subfolderB/bbb',
'folderC/ccc'
];
const res = getRelevantPrefixes(paths);
expect(res).toStrictEqual([
'folderC',
'folderA/subfolderB',
'folderA'
]);
});
it('should return common prefix between 2 paths with same prefix', () => {
const paths: string[] = [
'level1/level2',
'level1/level2/aaa'
];
const res = getRelevantPrefixes(paths);
expect(res).toStrictEqual([
'level1/level2'
]);
});
it('should return common prefix between 2 paths with same low level prefix', () => {
const paths: string[] = [
'aaa/bbb/ccc',
'aaa/bbb/eee/fff'
];
const res = getRelevantPrefixes(paths);
expect(res).toStrictEqual([
'aaa/bbb/eee',
'aaa/bbb'
]);
});
it('should return all original paths if they are leaves or satisfy the one-child condition', () => {
const paths: string[] = [
'aaa',
'bbb',
'ccc'
];
const res = getRelevantPrefixes(paths);
expect(res).toStrictEqual(['ccc', 'bbb', 'aaa']);
});
it('should handle multiple prefixes', () => {
const paths: string[] = [
'root/file1.txt',
'root/file2.txt',
'root/file3.txt'
];
const res = getRelevantPrefixes(paths);
expect(res).toStrictEqual([
'root'
]);
});
it('should add leaf nodes and single-child original paths, not grouping parents', () => {
const paths: string[] = [
'driven/kustomize/path1',
'driven/kustomize/path2',
'driven/kustomize',
'driven/simple',
'driven/helm'
];
const res = getRelevantPrefixes(paths);
expect(res).toStrictEqual([
'driven/kustomize',
'driven',
].sort((a, b) => b.localeCompare(a)));
});
});
describe.skip('test UI elements from YAML resource', () => {});

View File

@ -232,4 +232,6 @@ describe.each([
expect(pollingIntervalWebhookWarning.exists()).toBe(visible);
});
it.todo('test paths and subpaths');
});

View File

@ -1,4 +1,4 @@
import { decodeHtml, resourceNames } from '@shell/utils/string';
import { decodeHtml, resourceNames, pathArrayToTree } from '@shell/utils/string';
describe('fx: decodeHtml', () => {
it('should decode HTML values from escaped string into valid markup', () => {
@ -89,3 +89,275 @@ describe('fx: resourceNames', () => {
});
});
});
describe('fx: pathArrayToTree', () => {
interface TreeNode {
name: string;
children: TreeNode[];
}
function sortTree(nodes: TreeNode[]): void {
if (!nodes) return;
nodes.sort((a, b) => a.name.localeCompare(b.name));
nodes.forEach((node) => {
if (node.children && node.children.length > 0) {
sortTree(node.children);
}
});
}
it('should return an empty array for an empty input array', () => {
const paths: string[] = [];
expect(pathArrayToTree(paths)).toStrictEqual([]);
});
it('should convert simple single-level paths correctly', () => {
const paths: string[] = [
'file1.txt',
'folderA',
'itemB'
];
const expected: TreeNode[] = [
{ name: 'file1.txt', children: [] },
{ name: 'folderA', children: [] },
{ name: 'itemB', children: [] },
];
const actual = pathArrayToTree(paths);
sortTree(actual); // Sort the actual output for deterministic comparison
expect(actual).toStrictEqual(expected);
});
it('should convert two-level nested paths correctly', () => {
const paths: string[] = [
'folderA/file1.txt',
'folderC/file3.txt'
];
const expected: TreeNode[] = [
{
name: 'folderA',
children: [
{ name: 'file1.txt', children: [] },
]
},
{
name: 'folderC',
children: [
{ name: 'file3.txt', children: [] }
]
},
];
const actual = pathArrayToTree(paths);
sortTree(actual);
expect(actual).toStrictEqual(expected);
});
it('should handle deep nesting and common prefixes correctly', () => {
const paths: string[] = [
'root/level1/level2/file.doc',
'root/level1/another_file.txt',
'root/diff_level1/config.json'
];
const expected: TreeNode[] = [
{
name: 'root',
children: [
{
name: 'diff_level1',
children: [
{ name: 'config.json', children: [] }
]
},
{
name: 'level1',
children: [
{ name: 'another_file.txt', children: [] },
{
name: 'level2',
children: [
{ name: 'file.doc', children: [] }
]
}
]
}
]
}
];
const actual = pathArrayToTree(paths);
sortTree(actual);
expect(actual).toStrictEqual(expected);
});
it('should handle leading/trailing/multiple slashes by treating them as path segments', () => {
const paths: string[] = [
'/path/to/file.txt', // Starts with a slash
'path/to/another.txt/', // Ends with a slash (adds an empty segment)
'//root/item//subitem//', // Multiple slashes (adds empty segments)
'root/item/another_subitem'
];
const expected: TreeNode[] = [
{
name: '',
children: [
{
name: '',
children: [
{
name: 'root',
children: [
{
name: 'item',
children: [
{
name: '',
children: [
{
name: 'subitem',
children: [
{
name: '',
children: [
{
name: '',
children: [
],
},
],
},
],
},
],
},
],
},
],
},
],
},
{
name: 'path',
children: [
{
name: 'to',
children: [
{
name: 'file.txt',
children: [
],
},
],
},
],
},
],
},
{
name: 'path',
children: [
{
name: 'to',
children: [
{
name: 'another.txt',
children: [
{
name: '',
children: [
],
},
],
},
],
},
],
},
{
name: 'root',
children: [
{
name: 'item',
children: [
{
name: 'another_subitem',
children: [
],
},
],
},
],
},
];
const actual = pathArrayToTree(paths);
sortTree(actual);
expect(actual).toStrictEqual(expected);
});
it('should produce the same structure regardless of input order', () => {
const paths1: string[] = ['a/b', 'a/c'];
const paths2: string[] = ['a/c', 'a/b'];
const actual1 = pathArrayToTree(paths1);
sortTree(actual1);
const actual2 = pathArrayToTree(paths2);
sortTree(actual2);
expect(actual1).toStrictEqual(actual2);
});
it('should handle names with special characters (not slashes) correctly', () => {
const paths: string[] = [
'my-folder/file_name.1.txt',
'another folder/item with spaces'
];
const expected: TreeNode[] = [
{
name: 'another folder',
children: [
{ name: 'item with spaces', children: [] }
]
},
{
name: 'my-folder',
children: [
{ name: 'file_name.1.txt', children: [] }
]
}
];
const actual = pathArrayToTree(paths);
sortTree(actual);
expect(actual).toStrictEqual(expected);
});
it('should handle duplicate paths correctly, only adding unique structure', () => {
const paths: string[] = [
'folder/file.txt',
'folder/file.txt', // Duplicate
'other_folder/another_file.txt'
];
const expected: TreeNode[] = [
{
name: 'folder',
children: [
{ name: 'file.txt', children: [] }
]
},
{
name: 'other_folder',
children: [
{ name: 'another_file.txt', children: [] }
]
}
];
const actual = pathArrayToTree(paths);
sortTree(actual);
expect(actual).toStrictEqual(expected);
});
});