import { describe, expect, it } from 'vitest'; import { strayIdsAfterCatchUp } from '../reindex'; describe('strayIdsAfterCatchUp', () => { it('removes locally-indexed ids absent from a complete (uncapped) fetch', () => { // Contacts/files have no date filter, so a catch-up query that comes back // under the cap IS the whole account - anything indexed but missing from // it was deleted. This is the only place a JMAP `destroyed` ever reaches // these two content types, since nothing in the renderer populates // reindex's `removed` field. const existing = new Set(['a', 'b', 'c']); expect(strayIdsAfterCatchUp(existing, ['a', 'c'], 2, 2_000)).toEqual(['b']); }); it('does nothing when the fetch is empty but so is the local index', () => { expect(strayIdsAfterCatchUp(new Set(), [], 0, 2_000)).toEqual([]); }); it('never removes anything when the query hit its cap - a truncated page is not the whole world', () => { // Exactly the case that would otherwise delete objects that are still // live: an account with >= cap contacts/files, where "missing from this // page" only means "not on this page", not "gone". const existing = new Set(['a', 'b', 'c']); expect(strayIdsAfterCatchUp(existing, ['a'], 2_000, 2_000)).toEqual([]); }); it('is a no-op when nothing is stray', () => { const existing = new Set(['a', 'b']); expect(strayIdsAfterCatchUp(existing, ['a', 'b', 'c'], 3, 2_000)).toEqual([]); }); });