SkateSpots/src/lib/eventMerge.test.ts

55 lines
2 KiB
TypeScript

import { describe, expect, it } from 'vitest';
import type { NostrEvent } from '@nostrify/nostrify';
import { eventMergeKey, eventReplaces, mergeEvents } from './eventMerge';
function ev(partial: Partial<NostrEvent> & { id: string }): NostrEvent {
return {
pubkey: 'a'.repeat(64),
created_at: 100,
kind: 1,
tags: [],
content: '',
sig: '0'.repeat(128),
...partial,
} as NostrEvent;
}
describe('eventMerge', () => {
it('keys addressable, replaceable and regular events correctly', () => {
expect(eventMergeKey(ev({ id: '1', kind: 30818, tags: [['d', 'spot']] }))).toBe(
`${'a'.repeat(64)}:30818:spot`,
);
expect(eventMergeKey(ev({ id: '2', kind: 0 }))).toBe(`${'a'.repeat(64)}:0`);
expect(eventMergeKey(ev({ id: '3', kind: 1 }))).toBe('3');
});
it('keeps the newest addressable version regardless of input order', () => {
const old = ev({ id: 'b', kind: 30818, tags: [['d', 'spot']], created_at: 100 });
const fresh = ev({ id: 'a', kind: 30818, tags: [['d', 'spot']], created_at: 101 });
expect(mergeEvents([old, fresh])).toEqual([fresh]);
expect(mergeEvents([fresh, old])).toEqual([fresh]);
});
it('uses event id as a deterministic tie-breaker', () => {
const first = ev({ id: 'aaa', kind: 30000, tags: [['d', 'x']], created_at: 100 });
const second = ev({ id: 'zzz', kind: 30000, tags: [['d', 'x']], created_at: 100 });
expect(eventReplaces(first, second)).toBe(true);
expect(mergeEvents([first, second])).toEqual([second]);
expect(mergeEvents([second, first])).toEqual([second]);
});
it('keeps distinct regular events and deduplicates by id', () => {
const a = ev({ id: 'a' });
const b = ev({ id: 'b' });
expect(mergeEvents([a, b, a])).toHaveLength(2);
});
it('drops local tombstones', () => {
const a = ev({ id: 'a', kind: 30818, tags: [['d', 'spot']] });
const b = ev({ id: 'b', kind: 30818, tags: [['d', 'other']] });
expect(mergeEvents([a, b], { isDeleted: (event) => event.id === 'a' })).toEqual([b]);
});
});