import { describe, it, expect, vi } from 'vitest' import { createUniqueList, uniqueListUpdate, uniqueListGetElements, uniqueListById, } from '../UniqueList' interface Item { id: number name: string } describe('createUniqueList', () => { it('creates an empty list', () => { const list = createUniqueList() expect(list.elements).toEqual({}) expect(uniqueListGetElements(list)).toEqual([]) }) }) describe('uniqueListUpdate', () => { it('adds new elements', () => { const list = createUniqueList() const addCb = vi.fn() uniqueListUpdate(list, [{ id: 1, name: 'a' }, { id: 2, name: 'b' }], addCb) expect(addCb).toHaveBeenCalledTimes(2) expect(uniqueListGetElements(list)).toHaveLength(2) expect(uniqueListById(list, 1)).toEqual({ id: 1, name: 'a' }) expect(uniqueListById(list, 2)).toEqual({ id: 2, name: 'b' }) }) it('removes elements no longer present', () => { const list = createUniqueList() const removeCb = vi.fn() uniqueListUpdate(list, [{ id: 1, name: 'a' }, { id: 2, name: 'b' }]) uniqueListUpdate(list, [{ id: 1, name: 'a' }], undefined, removeCb) expect(removeCb).toHaveBeenCalledTimes(1) expect(removeCb).toHaveBeenCalledWith({ id: 2, name: 'b' }) expect(uniqueListGetElements(list)).toHaveLength(1) expect(uniqueListById(list, 2)).toBeUndefined() }) it('calls update callback for existing elements', () => { const list = createUniqueList() const updateCb = vi.fn() uniqueListUpdate(list, [{ id: 1, name: 'a' }]) uniqueListUpdate(list, [{ id: 1, name: 'updated' }], undefined, undefined, updateCb) expect(updateCb).toHaveBeenCalledTimes(1) expect(updateCb).toHaveBeenCalledWith({ id: 1, name: 'a' }, { id: 1, name: 'updated' }) }) it('handles all callbacks together', () => { const list = createUniqueList() const addCb = vi.fn() const removeCb = vi.fn() const updateCb = vi.fn() uniqueListUpdate(list, [{ id: 1, name: 'keep' }, { id: 2, name: 'remove' }]) uniqueListUpdate( list, [{ id: 1, name: 'kept' }, { id: 3, name: 'new' }], addCb, removeCb, updateCb, ) expect(addCb).toHaveBeenCalledTimes(1) expect(addCb).toHaveBeenCalledWith({ id: 3, name: 'new' }) expect(removeCb).toHaveBeenCalledTimes(1) expect(removeCb).toHaveBeenCalledWith({ id: 2, name: 'remove' }) expect(updateCb).toHaveBeenCalledTimes(1) expect(updateCb).toHaveBeenCalledWith({ id: 1, name: 'keep' }, { id: 1, name: 'kept' }) }) it('works with string IDs', () => { interface StringItem { id: string label: string } const list = createUniqueList() uniqueListUpdate(list, [{ id: 'abc', label: 'first' }]) expect(uniqueListById(list, 'abc')).toEqual({ id: 'abc', label: 'first' }) }) it('handles empty update', () => { const list = createUniqueList() uniqueListUpdate(list, [{ id: 1, name: 'a' }]) const removeCb = vi.fn() uniqueListUpdate(list, [], undefined, removeCb) expect(removeCb).toHaveBeenCalledTimes(1) expect(uniqueListGetElements(list)).toHaveLength(0) }) it('handles update with no callbacks', () => { const list = createUniqueList() uniqueListUpdate(list, [{ id: 1, name: 'a' }]) uniqueListUpdate(list, [{ id: 2, name: 'b' }]) expect(uniqueListGetElements(list)).toHaveLength(1) expect(uniqueListById(list, 2)).toEqual({ id: 2, name: 'b' }) }) }) describe('uniqueListGetElements', () => { it('returns all elements as array', () => { const list = createUniqueList() uniqueListUpdate(list, [{ id: 1, name: 'a' }, { id: 2, name: 'b' }]) const elements = uniqueListGetElements(list) expect(elements).toHaveLength(2) expect(elements.map(e => e.id).sort()).toEqual([1, 2]) }) }) describe('uniqueListById', () => { it('finds element by id', () => { const list = createUniqueList() uniqueListUpdate(list, [{ id: 42, name: 'target' }]) expect(uniqueListById(list, 42)?.name).toBe('target') }) it('returns undefined for missing id', () => { const list = createUniqueList() expect(uniqueListById(list, 999)).toBeUndefined() }) })