61 lines
3.4 KiB
TypeScript
61 lines
3.4 KiB
TypeScript
import { describe, expect, it } from 'vitest';
|
|
import {
|
|
completeProjectSession,
|
|
createProjectConversationState,
|
|
normalizeProjectConversationState,
|
|
patchProjectSessionMetadata,
|
|
removeProjectSessionMetadata,
|
|
upsertProjectSessionMetadata,
|
|
} from '../../shared/project-conversations';
|
|
|
|
describe('project conversation metadata', () => {
|
|
it('links multiple independent sessions to one contact and keeps them ordered by activity', () => {
|
|
let state = createProjectConversationState('2026-07-30T00:00:00.000Z');
|
|
state = upsertProjectSessionMetadata(state, 'ses-a', 'agent-a', '2026-07-30T00:01:00.000Z');
|
|
state = upsertProjectSessionMetadata(state, 'ses-b', 'agent-a', '2026-07-30T00:02:00.000Z');
|
|
expect(state.sessions.map((session) => session.sessionId)).toEqual(['ses-b', 'ses-a']);
|
|
expect(state.sessions.every((session) => session.agentId === 'agent-a')).toBe(true);
|
|
});
|
|
|
|
it('archives one session without touching its sibling', () => {
|
|
let state = createProjectConversationState();
|
|
state = upsertProjectSessionMetadata(state, 'ses-a', 'agent-a', '2026-07-30T00:01:00.000Z');
|
|
state = upsertProjectSessionMetadata(state, 'ses-b', 'agent-a', '2026-07-30T00:02:00.000Z');
|
|
state = patchProjectSessionMetadata(state, 'ses-a', { archivedAt: '2026-07-30T00:03:00.000Z' }, '2026-07-30T00:03:00.000Z');
|
|
expect(state.sessions.find((session) => session.sessionId === 'ses-a')?.archivedAt).toBe('2026-07-30T00:03:00.000Z');
|
|
expect(state.sessions.find((session) => session.sessionId === 'ses-b')?.archivedAt).toBeNull();
|
|
});
|
|
|
|
it('removes one session metadata record without touching its sibling', () => {
|
|
let state = createProjectConversationState();
|
|
state = upsertProjectSessionMetadata(state, 'ses-a', 'agent-a', '2026-07-30T00:01:00.000Z');
|
|
state = upsertProjectSessionMetadata(state, 'ses-b', 'agent-a', '2026-07-30T00:02:00.000Z');
|
|
state = removeProjectSessionMetadata(state, 'ses-a', '2026-07-30T00:03:00.000Z');
|
|
expect(state.sessions.map((session) => session.sessionId)).toEqual(['ses-b']);
|
|
expect(state.updatedAt).toBe('2026-07-30T00:03:00.000Z');
|
|
});
|
|
|
|
it('increments unread only for background completion and updates recent activity', () => {
|
|
let state = createProjectConversationState();
|
|
state = upsertProjectSessionMetadata(state, 'ses-a', 'agent-a', '2026-07-30T00:01:00.000Z');
|
|
state = completeProjectSession(state, 'ses-a', true, '2026-07-30T00:04:00.000Z');
|
|
expect(state.sessions[0]).toMatchObject({ unreadCount: 1, updatedAt: '2026-07-30T00:04:00.000Z' });
|
|
state = completeProjectSession(state, 'ses-a', false, '2026-07-30T00:05:00.000Z');
|
|
expect(state.sessions[0]).toMatchObject({ unreadCount: 1, updatedAt: '2026-07-30T00:05:00.000Z' });
|
|
});
|
|
|
|
it('normalizes malformed persisted records and deduplicates by stable session id', () => {
|
|
const normalized = normalizeProjectConversationState({
|
|
schemaVersion: 1,
|
|
updatedAt: '2026-07-30T00:00:00.000Z',
|
|
sessions: [
|
|
{ sessionId: 'ses-a', agentId: 'agent-a', unreadCount: 2, createdAt: '', updatedAt: '' },
|
|
{ sessionId: 'ses-a', agentId: 'agent-b', unreadCount: -3, createdAt: '2026-07-30T00:01:00.000Z', updatedAt: '2026-07-30T00:01:00.000Z' },
|
|
{ sessionId: '', agentId: 'agent-a' },
|
|
],
|
|
});
|
|
expect(normalized.sessions).toHaveLength(1);
|
|
expect(normalized.sessions[0]).toMatchObject({ sessionId: 'ses-a', agentId: 'agent-b', unreadCount: 0 });
|
|
});
|
|
});
|