diff --git a/packages/shared/src/dto.ts b/packages/shared/src/dto.ts index 56f3ff4..9872f16 100644 --- a/packages/shared/src/dto.ts +++ b/packages/shared/src/dto.ts @@ -86,6 +86,11 @@ export interface DriveTreeNode { export function sortDriveNodes(list: DriveTreeNode[]): DriveTreeNode[] { return [...list].sort((a, b) => { + if (a.modified_time !== b.modified_time) { + if (a.modified_time === null) return 1; + if (b.modified_time === null) return -1; + return b.modified_time - a.modified_time; + } if (a.is_folder !== b.is_folder) return a.is_folder ? -1 : 1; return a.name.localeCompare(b.name); }); diff --git a/packages/shared/test/dto.test.ts b/packages/shared/test/dto.test.ts new file mode 100644 index 0000000..e4c1eba --- /dev/null +++ b/packages/shared/test/dto.test.ts @@ -0,0 +1,50 @@ +import { describe, expect, it } from 'vitest'; +import { type DriveTreeNode, sortDriveNodes } from '../src/dto.js'; + +function driveNode(id: string, modifiedTime: number | null, isFolder = false): DriveTreeNode { + return { + id, + name: id, + mime_type: isFolder ? 'application/vnd.google-apps.folder' : 'text/plain', + is_folder: isFolder, + modified_time: modifiedTime, + children: isFolder ? [] : null, + }; +} + +describe('sortDriveNodes', () => { + it('sorts files and folders from newest to oldest', () => { + const nodes = [ + driveNode('old-folder', 100, true), + driveNode('new-file', 300), + driveNode('middle-file', 200), + ]; + + expect(sortDriveNodes(nodes).map((node) => node.id)).toEqual([ + 'new-file', + 'middle-file', + 'old-folder', + ]); + }); + + it('puts nodes without a modified time last', () => { + const nodes = [driveNode('unknown', null), driveNode('dated', 100)]; + + expect(sortDriveNodes(nodes).map((node) => node.id)).toEqual(['dated', 'unknown']); + }); + + it('uses folder and name tie-breakers without mutating the input', () => { + const nodes = [ + driveNode('z-file', 100), + driveNode('b-folder', 100, true), + driveNode('a-folder', 100, true), + ]; + + expect(sortDriveNodes(nodes).map((node) => node.id)).toEqual([ + 'a-folder', + 'b-folder', + 'z-file', + ]); + expect(nodes.map((node) => node.id)).toEqual(['z-file', 'b-folder', 'a-folder']); + }); +});