Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
43
src/lib/session-grouping.test.ts
Normal file
43
src/lib/session-grouping.test.ts
Normal file
@@ -0,0 +1,43 @@
|
||||
import { test } from "node:test"
|
||||
import assert from "node:assert/strict"
|
||||
import { groupByDirectory } from "./session-grouping.ts"
|
||||
|
||||
test("groupByDirectory: buckets items by directory, preserving item order within a bucket", () => {
|
||||
const items = [
|
||||
{ id: "1", directory: "/a" },
|
||||
{ id: "2", directory: "/b" },
|
||||
{ id: "3", directory: "/a" },
|
||||
]
|
||||
const groups = groupByDirectory(items)
|
||||
assert.equal(groups.length, 2)
|
||||
assert.equal(groups[0].directory, "/a")
|
||||
assert.deepEqual(groups[0].items.map((i) => i.id), ["1", "3"])
|
||||
assert.equal(groups[1].directory, "/b")
|
||||
assert.deepEqual(groups[1].items.map((i) => i.id), ["2"])
|
||||
})
|
||||
|
||||
test("groupByDirectory: orders groups by first-seen directory, not alphabetically", () => {
|
||||
const items = [
|
||||
{ id: "1", directory: "/z" },
|
||||
{ id: "2", directory: "/a" },
|
||||
]
|
||||
const groups = groupByDirectory(items)
|
||||
assert.deepEqual(
|
||||
groups.map((g) => g.directory),
|
||||
["/z", "/a"],
|
||||
)
|
||||
})
|
||||
|
||||
test("groupByDirectory: empty input returns no groups", () => {
|
||||
assert.deepEqual(groupByDirectory([]), [])
|
||||
})
|
||||
|
||||
test("groupByDirectory: single directory yields a single group with all items", () => {
|
||||
const items = [
|
||||
{ id: "1", directory: "/a" },
|
||||
{ id: "2", directory: "/a" },
|
||||
]
|
||||
const groups = groupByDirectory(items)
|
||||
assert.equal(groups.length, 1)
|
||||
assert.equal(groups[0].items.length, 2)
|
||||
})
|
||||
31
src/lib/session-grouping.ts
Normal file
31
src/lib/session-grouping.ts
Normal file
@@ -0,0 +1,31 @@
|
||||
// Pure helpers for grouping the session list by project directory.
|
||||
// No React Native imports — unit-testable with node --test.
|
||||
|
||||
/** A contiguous-by-directory bucket of items, in first-seen order. */
|
||||
export interface DirectoryGroup<T> {
|
||||
directory: string
|
||||
items: T[]
|
||||
}
|
||||
|
||||
/**
|
||||
* Groups items by their `directory` field, preserving both the original
|
||||
* item order within a group and the order in which each directory was
|
||||
* first encountered. Does not sort — callers decide presentation order.
|
||||
*/
|
||||
export function groupByDirectory<T extends { directory: string }>(items: T[]): DirectoryGroup<T>[] {
|
||||
const order: string[] = []
|
||||
const buckets = new Map<string, T[]>()
|
||||
|
||||
for (const item of items) {
|
||||
const dir = item.directory
|
||||
let bucket = buckets.get(dir)
|
||||
if (!bucket) {
|
||||
bucket = []
|
||||
buckets.set(dir, bucket)
|
||||
order.push(dir)
|
||||
}
|
||||
bucket.push(item)
|
||||
}
|
||||
|
||||
return order.map((directory) => ({ directory, items: buckets.get(directory) as T[] }))
|
||||
}
|
||||
Reference in New Issue
Block a user