Files
PotentialStorage/test/documents/units.test.ts
T
Claude e27541c46a
CI / Node 20 (push) Successful in 1m49s
CI / Node 22 (push) Successful in 1m52s
Add Prettier formatting and Gitea Actions CI (format, typecheck, test, build)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017Qxbkp4tA7G5SCWjzWuxmE
2026-10-23 07:29:38 +00:00

63 lines
2.5 KiB
TypeScript

import { describe, expect, it } from 'vitest'
import { createIdGenerator } from '../../src/documents/ulid.js'
import { matches } from '../../src/documents/filter.js'
import { applyPatch, resolveUpdate } from '../../src/documents/update.js'
describe('ulid', () => {
it('is strictly increasing within one millisecond and sorts by time', () => {
let t = 1_700_000_000_000
const gen = createIdGenerator(() => t)
const ids = Array.from({ length: 1000 }, () => gen())
expect([...ids].sort()).toEqual(ids)
expect(new Set(ids).size).toBe(1000)
t += 1
const later = gen()
expect(later > ids.at(-1)!).toBe(true)
expect(later.slice(0, 10) > ids[0]!.slice(0, 10)).toBe(true)
})
})
describe('filter semantics', () => {
it('requires one array element to satisfy all positive operators of a condition', () => {
expect(matches({ s: [1, 20] }, { s: { $gt: 5, $lt: 10 } })).toBe(false) // MongoDB would match
expect(matches({ s: [1, 7] }, { s: { $gt: 5, $lt: 10 } })).toBe(true)
expect(matches({ s: [1, 20] }, { $and: [{ s: { $gt: 5 } }, { s: { $lt: 10 } }] })).toBe(true)
})
it('traverses arrays of sub-documents on dot paths', () => {
expect(matches({ a: [{ b: 1 }, { b: 2 }] }, { 'a.b': 2 })).toBe(true)
expect(matches({ a: [{ b: 1 }] }, { 'a.0.b': 1 })).toBe(true)
expect(matches({ a: [{ b: 1 }] }, { 'a.b': { $exists: true } })).toBe(true)
expect(matches({ a: [] }, { 'a.b': { $exists: true } })).toBe(false)
})
it('treats null as matching missing', () => {
expect(matches({}, { x: null })).toBe(true)
expect(matches({ x: null }, { x: { $ne: null } })).toBe(false)
expect(matches({ x: 0 }, { x: { $ne: null } })).toBe(true)
})
it('rejects unknown operators', () => {
expect(() => matches({}, { x: { $regex: 'a' } })).toThrow(/Unknown operator/)
expect(() => matches({}, { $nor: [] } as never)).toThrow(/Unknown top-level/)
})
})
describe('update resolution', () => {
it('$pull by sub-document filter and by condition', () => {
const state = {
items: [
{ k: 1, v: 'a' },
{ k: 2, v: 'b' },
],
n: [1, 5, 9],
}
const patch = resolveUpdate(state, { $pull: { items: { k: 2 }, n: { $gte: 5 } } })
expect(applyPatch(state, patch)).toEqual({ items: [{ k: 1, v: 'a' }], n: [1] })
})
it('$unset of an array position nulls it', () => {
expect(applyPatch({ a: [1, 2] }, resolveUpdate({ a: [1, 2] }, { $unset: { 'a.0': true } }))).toEqual({ a: [null, 2] })
})
})