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] }) }) })