import { describe, test, expect, beforeEach } from 'vitest'; import { Activities, StoreInMemory } from '../../src/storage'; describe('Activities', () => { let activities: Activities; beforeEach(async () => { activities = await Activities.from(); }); test('should add activity with auto-generated timestamp', async () => { const activity = { key: 'WalletName', entityId: 'wallet1', value: 'Test Wallet', }; await activities.add(activity); const storedActivity = activities.get('WalletName', 'wallet1'); expect(storedActivity).toBeDefined(); expect(storedActivity?.timestamp).toBeDefined(); expect(storedActivity?.value).toBe('Test Wallet'); }); test('should preserve provided timestamp', async () => { const timestamp = BigInt(1234567890000); const activity = { timestamp, key: 'WalletName', entityId: 'wallet1', value: 'Test Wallet', }; await activities.add(activity); const storedActivity = activities.get('WalletName', 'wallet1'); expect(storedActivity?.timestamp).toBe(timestamp); }); test('should update existing activity with newer timestamp', async () => { const oldTimestamp = BigInt(1000); const newTimestamp = BigInt(2000); await activities.add({ timestamp: oldTimestamp, key: 'WalletName', entityId: 'wallet1', value: 'Old Name', }); await activities.add({ timestamp: newTimestamp, key: 'WalletName', entityId: 'wallet1', value: 'New Name', }); const activity = activities.get('WalletName', 'wallet1'); expect(activity?.value).toBe('New Name'); expect(activity?.timestamp).toBe(newTimestamp); }); test('should honor first-seen policy', async () => { activities.registerPolicy('TransactionFirstSeen', (existing, newer) => { return existing || newer; }); const oldTimestamp = BigInt(1000); const newTimestamp = BigInt(2000); await activities.add({ timestamp: oldTimestamp, key: 'TransactionFirstSeen', entityId: 'tx1', value: 'First Value', }); await activities.add({ timestamp: newTimestamp, key: 'TransactionFirstSeen', entityId: 'tx1', value: 'Second Value', }); const activity = activities.get('TransactionFirstSeen', 'tx1'); expect(activity?.value).toBe('First Value'); expect(activity?.timestamp).toBe(oldTimestamp); }); test('should handle custom policy with comparison function', async () => { // Policy that keeps activity with highest value activities.registerPolicy('CustomType', (existing, newer) => { if (!existing) return newer; return existing.timestamp < newer.timestamp ? existing : newer; }); await activities.add({ timestamp: BigInt(1000), key: 'CustomType', entityId: 'custom1', value: 50, }); await activities.add({ timestamp: BigInt(2000), key: 'CustomType', entityId: 'custom1', value: 30, }); const activity = activities.get('CustomType', 'custom1'); expect(activity?.value).toBe(50); }); test('should process multiple activities in chronological order', async () => { const testActivities = [ { timestamp: BigInt(3000), key: 'WalletName', entityId: 'wallet1', value: 'Name 3', }, { timestamp: BigInt(1000), key: 'WalletName', entityId: 'wallet1', value: 'Name 1', }, { timestamp: BigInt(2000), key: 'WalletName', entityId: 'wallet1', value: 'Name 2', }, ]; for (const activity of testActivities) { await activities.add(activity); } const finalActivity = activities.get('WalletName', 'wallet1'); expect(finalActivity?.value).toBe('Name 3'); }); test('should handle multiple activity types independently', async () => { await activities.add({ timestamp: BigInt(1000), key: 'WalletName', entityId: 'wallet1', value: 'My Wallet', }); await activities.add({ timestamp: BigInt(2000), key: 'WalletDescription', entityId: 'wallet1', value: 'My Description', }); expect(activities.get('WalletName', 'wallet1')?.value).toBe('My Wallet'); expect(activities.get('WalletDescription', 'wallet1')?.value).toBe( 'My Description', ); }); test('should update snapshot immediately when activity is added', async () => { const activity = { timestamp: BigInt(1000), key: 'WalletName', entityId: 'wallet1', value: 'Test Wallet', }; await activities.add(activity); // Check snapshot without calling compileSnapshot const storedActivity = activities.get('WalletName', 'wallet1'); expect(storedActivity?.value).toBe('Test Wallet'); }); test('should handle missing timestamp gracefully', async () => { const activity = { key: 'WalletName', entityId: 'wallet1', value: 'Test Wallet', }; await activities.add(activity); const storedActivity = activities.get('WalletName', 'wallet1'); expect(storedActivity).toBeDefined(); expect(storedActivity?.timestamp).toBeDefined(); expect(typeof storedActivity?.timestamp).toBe('bigint'); }); /* test('should cleanup old activities from store when newer versions are added', async () => { // Add first activity await activities.add({ timestamp: BigInt(1000), type: 'WalletName', id: 'wallet1', value: 'Old Name', }); expect(Object.keys(await store.all()).length).toBe(1); // Add newer version - should trigger cleanup of old version await activities.add({ timestamp: BigInt(2000), type: 'WalletName', id: 'wallet1', value: 'New Name', }); // Should still be 1 as old activity was culled expect(Object.keys(await store.all()).length).toBe(1); // Add different type await activities.add({ timestamp: BigInt(1500), type: 'WalletDescription', id: 'wallet1', value: 'Description', }); // Should now have 2 activities expect(Object.keys(await store.all()).length).toBe(2); }); */ });