Skip to content

Commit 9d4c285

Browse files
krisnyeclaude
andauthored
test(ecs): complex sort index sample — orderedChildOf with nested parent + FractionalIndex (#121)
* test(ecs): add complex sort index sample — orderedChildOf with nested parent + fractional index Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(test): use Entity.schema and FractionalIndex.schema in orderedChildOf component Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent 6805e80 commit 9d4c285

1 file changed

Lines changed: 77 additions & 0 deletions

File tree

packages/data/src/ecs/database/database.index.test.ts

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
import { describe, it, expect } from "vitest";
44
import { Database } from "./database.js";
5+
import { Entity } from "../entity/entity.js";
6+
import { FractionalIndex } from "../../schema/fractional-index/fractional-index.js";
57

68
// ============================================================================
79
// Catalogue pattern coverage — each describe corresponds to one of the 12
@@ -1472,3 +1474,78 @@ describe("registry maintenance", () => {
14721474
expect([...ext.indexes.byName.find({ name: "alice" })].sort()).toEqual([e1, e2].sort());
14731475
});
14741476
});
1477+
1478+
describe("complex sort index — orderedChildOf (nested parent + fractional-index order)", () => {
1479+
// orderedChildOf bundles the parent entity reference and the fractional-index
1480+
// sort key in a single object component. The index uses a computed slot map
1481+
// to extract the group key and a custom compare that drills into the nested
1482+
// object for the order field — matching the README pattern:
1483+
// key: (f) => f.parent, order: { by: ["foo"], compare: (a, b) => a.foo.order < b.foo.order ? -1 : 1 }
1484+
const plugin = () => Database.Plugin.create({
1485+
components: {
1486+
orderedChildOf: {
1487+
type: "object",
1488+
properties: {
1489+
parent: Entity.schema,
1490+
order: FractionalIndex.schema,
1491+
},
1492+
required: ["parent", "order"],
1493+
},
1494+
},
1495+
archetypes: { Child: ["orderedChildOf"] },
1496+
indexes: {
1497+
orderedChildrenOf: {
1498+
key: { parent: (c) => c.orderedChildOf!.parent },
1499+
components: ["orderedChildOf"],
1500+
order: {
1501+
by: ["orderedChildOf"],
1502+
compare: (
1503+
a: { orderedChildOf: { parent: number; order: string } },
1504+
b: { orderedChildOf: { parent: number; order: string } },
1505+
) => a.orderedChildOf.order < b.orderedChildOf.order ? -1 : 1,
1506+
},
1507+
},
1508+
},
1509+
transactions: {
1510+
add: (t, args: { parent: number; order: string }) =>
1511+
t.archetypes.Child.insert({ orderedChildOf: args }),
1512+
reorder: (t, args: { entity: number; parent: number; order: string }) =>
1513+
t.update(args.entity, { orderedChildOf: { parent: args.parent, order: args.order } }),
1514+
delete: (t, e: number) => t.delete(e),
1515+
},
1516+
});
1517+
1518+
it("returns children sorted by fractional index within the same parent", () => {
1519+
const db = Database.create(plugin());
1520+
const c = db.transactions.add({ parent: 1, order: "a2" });
1521+
const a = db.transactions.add({ parent: 1, order: "a0" });
1522+
const b = db.transactions.add({ parent: 1, order: "a1" });
1523+
expect(db.indexes.orderedChildrenOf.find({ parent: 1 })).toEqual([a, b, c]);
1524+
});
1525+
1526+
it("children of different parents are in independent buckets", () => {
1527+
const db = Database.create(plugin());
1528+
const child1 = db.transactions.add({ parent: 1, order: "a0" });
1529+
const child2 = db.transactions.add({ parent: 2, order: "a0" });
1530+
expect(db.indexes.orderedChildrenOf.find({ parent: 1 })).toEqual([child1]);
1531+
expect(db.indexes.orderedChildrenOf.find({ parent: 2 })).toEqual([child2]);
1532+
});
1533+
1534+
it("reordering an entity repositions it in the sorted result", () => {
1535+
const db = Database.create(plugin());
1536+
const a = db.transactions.add({ parent: 1, order: "a0" });
1537+
const b = db.transactions.add({ parent: 1, order: "a1" });
1538+
const c = db.transactions.add({ parent: 1, order: "a2" });
1539+
db.transactions.reorder({ entity: a, parent: 1, order: "a3" });
1540+
expect(db.indexes.orderedChildrenOf.find({ parent: 1 })).toEqual([b, c, a]);
1541+
});
1542+
1543+
it("delete removes the entity from its sorted bucket", () => {
1544+
const db = Database.create(plugin());
1545+
const a = db.transactions.add({ parent: 1, order: "a0" });
1546+
const b = db.transactions.add({ parent: 1, order: "a1" });
1547+
const c = db.transactions.add({ parent: 1, order: "a2" });
1548+
db.transactions.delete(b);
1549+
expect(db.indexes.orderedChildrenOf.find({ parent: 1 })).toEqual([a, c]);
1550+
});
1551+
});

0 commit comments

Comments
 (0)