Skip to content

Commit e04c307

Browse files
committed
feat(utils): sort coverage tree alphabetically with folders before files
1 parent ef94d23 commit e04c307

File tree

3 files changed

+78
-2
lines changed

3 files changed

+78
-2
lines changed

packages/utils/src/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ export {
66
toSentenceCase,
77
toTitleCase,
88
} from './lib/case-conversions.js';
9+
export { filesCoverageToTree, type FileCoverage } from './lib/coverage-tree.js';
910
export { createRunnerFiles } from './lib/create-runner-files.js';
1011
export { comparePairs, matchArrayItemsByKey, type Diff } from './lib/diff.js';
1112
export { stringifyError } from './lib/errors.js';

packages/utils/src/lib/coverage-tree.ts

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,15 +36,16 @@ export function filesCoverageToTree(
3636
path: formatGitPath(file.path, gitRoot),
3737
}));
3838

39-
const tree = normalizedFiles.reduce<FileTree>(
39+
const filesTree = normalizedFiles.reduce<FileTree>(
4040
(acc, coverage) => {
4141
const { folders, file } = splitFilePath(coverage.path);
4242
return addNode(acc, folders, file, coverage);
4343
},
4444
{ name: '.', children: [] },
4545
);
4646

47-
const root = calculateTreeCoverage(tree);
47+
const coverageTree = calculateTreeCoverage(filesTree);
48+
const root = sortCoverageTree(coverageTree);
4849

4950
return {
5051
type: 'coverage',
@@ -151,3 +152,19 @@ function getNodeCoverageStats(
151152
cache.set(node, stats);
152153
return stats;
153154
}
155+
156+
function sortCoverageTree(root: CoverageTreeNode): CoverageTreeNode {
157+
if (!root.children?.length) {
158+
return root;
159+
}
160+
return {
161+
...root,
162+
children: root.children
163+
.map(sortCoverageTree)
164+
.toSorted(
165+
(a, b) =>
166+
Number(Boolean(b.children?.length)) -
167+
Number(Boolean(a.children?.length)) || a.name.localeCompare(b.name),
168+
),
169+
};
170+
}

packages/utils/src/lib/coverage-tree.unit.test.ts

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,4 +164,62 @@ describe('filesCoverageToTree', () => {
164164
expect.objectContaining({ title: 'Branch coverage' }),
165165
);
166166
});
167+
168+
it('should sort tree alphabetically with folders before files', () => {
169+
const mockCoverage: Omit<FileCoverage, 'path'> = {
170+
covered: 0,
171+
total: 0,
172+
missing: [],
173+
};
174+
const files: FileCoverage[] = [
175+
{
176+
...mockCoverage,
177+
path: path.join(process.cwd(), 'src', 'App.jsx'),
178+
},
179+
{
180+
...mockCoverage,
181+
path: path.join(process.cwd(), 'src', 'components', 'TodoList.jsx'),
182+
},
183+
{
184+
...mockCoverage,
185+
path: path.join(process.cwd(), 'src', 'hooks', 'useTodos.js'),
186+
},
187+
{
188+
...mockCoverage,
189+
path: path.join(process.cwd(), 'src', 'components', 'TodoFilter.jsx'),
190+
},
191+
{
192+
...mockCoverage,
193+
path: path.join(process.cwd(), 'src', 'components', 'CreateTodo.jsx'),
194+
},
195+
];
196+
197+
expect(filesCoverageToTree(files, process.cwd())).toEqual(
198+
expect.objectContaining({
199+
root: expect.objectContaining({
200+
name: '.',
201+
children: [
202+
expect.objectContaining({
203+
name: 'src',
204+
children: [
205+
expect.objectContaining({
206+
name: 'components',
207+
children: [
208+
expect.objectContaining({ name: 'CreateTodo.jsx' }),
209+
expect.objectContaining({ name: 'TodoFilter.jsx' }),
210+
expect.objectContaining({ name: 'TodoList.jsx' }),
211+
],
212+
}),
213+
expect.objectContaining({
214+
name: 'hooks',
215+
children: [expect.objectContaining({ name: 'useTodos.js' })],
216+
}),
217+
expect.objectContaining({ name: 'App.jsx' }),
218+
],
219+
}),
220+
],
221+
}),
222+
}),
223+
);
224+
});
167225
});

0 commit comments

Comments
 (0)