companion/@applications/api/dist/__tests__/session.service.spec.js
Claude Code 0bc056d211 arch(applications): 🏗️ Refactor application imports and file structure
Co-Authored-By: Lilith Autocommit <noreply@atlilith.com>
2026-04-01 23:54:15 -07:00

172 lines
No EOL
6.2 KiB
JavaScript

import { describe, it, expect, vi, beforeEach } from 'vitest';
import { NotFoundException } from '@nestjs/common';
import { SessionService } from '../modules/session/session.service';
function makeSession(overrides = {}) {
return {
id: 'session-uuid-1',
personaId: 'miku',
userId: null,
lastActivityAt: new Date('2026-04-01T00:00:00Z'),
expiresAt: new Date('2026-04-02T00:00:00Z'),
createdAt: new Date('2026-04-01T00:00:00Z'),
updatedAt: new Date('2026-04-01T00:00:00Z'),
...overrides
};
}
function makeMessage(overrides = {}) {
return {
id: 'msg-uuid-1',
sessionId: 'session-uuid-1',
role: 'user',
content: 'Hello',
emotion: null,
createdAt: new Date('2026-04-01T00:00:00Z'),
updatedAt: new Date('2026-04-01T00:00:00Z'),
...overrides
};
}
function makeSessionRepo(overrides = {}) {
return {
create: vi.fn((data)=>({
...data
})),
save: vi.fn(async (entity)=>({
id: 'session-uuid-1',
...entity
})),
findOneBy: vi.fn(async ()=>makeSession()),
update: vi.fn(async ()=>({
affected: 1
})),
delete: vi.fn(async ()=>({
affected: 1
})),
find: vi.fn(async ()=>[]),
...overrides
};
}
function makeMessageRepo(overrides = {}) {
return {
create: vi.fn((data)=>({
...data
})),
save: vi.fn(async (entity)=>({
id: 'msg-uuid-1',
...entity
})),
find: vi.fn(async ()=>[]),
...overrides
};
}
describe('SessionService', ()=>{
let service;
let sessionRepo;
let messageRepo;
beforeEach(()=>{
sessionRepo = makeSessionRepo();
messageRepo = makeMessageRepo();
service = new SessionService(sessionRepo, messageRepo);
});
describe('createSession', ()=>{
it('creates a session with default persona miku', async ()=>{
const result = await service.createSession({});
expect(sessionRepo.create).toHaveBeenCalledWith(expect.objectContaining({
personaId: 'miku',
userId: null
}));
expect(result).toBeDefined();
});
it('creates a session with specified persona and user', async ()=>{
await service.createSession({
personaId: 'quinn',
userId: 'user-123'
});
expect(sessionRepo.create).toHaveBeenCalledWith(expect.objectContaining({
personaId: 'quinn',
userId: 'user-123'
}));
});
it('sets expiresAt 24 hours in the future', async ()=>{
await service.createSession({});
const call = sessionRepo.create.mock.calls[0][0];
const diffMs = call.expiresAt.getTime() - call.lastActivityAt.getTime();
expect(diffMs).toBe(24 * 60 * 60 * 1000);
});
});
describe('getSession', ()=>{
it('returns the session when found', async ()=>{
const session = await service.getSession('session-uuid-1');
expect(session.id).toBe('session-uuid-1');
});
it('throws NotFoundException when session not found', async ()=>{
sessionRepo.findOneBy = vi.fn(async ()=>null);
await expect(service.getSession('missing')).rejects.toThrow(NotFoundException);
});
});
describe('deleteSession', ()=>{
it('deletes an existing session', async ()=>{
await expect(service.deleteSession('session-uuid-1')).resolves.toBeUndefined();
expect(sessionRepo.delete).toHaveBeenCalledWith('session-uuid-1');
});
it('throws NotFoundException when session does not exist', async ()=>{
sessionRepo.delete = vi.fn(async ()=>({
affected: 0
}));
await expect(service.deleteSession('missing')).rejects.toThrow(NotFoundException);
});
});
describe('getHistory', ()=>{
it('returns mapped message DTOs', async ()=>{
messageRepo.find = vi.fn(async ()=>[
makeMessage()
]);
const history = await service.getHistory('session-uuid-1');
expect(history).toHaveLength(1);
expect(history[0]).toMatchObject({
id: 'msg-uuid-1',
session_id: 'session-uuid-1',
role: 'user',
content: 'Hello',
emotion: null
});
expect(typeof history[0].created_at).toBe('string');
});
it('returns empty array for session with no messages', async ()=>{
const history = await service.getHistory('session-uuid-1');
expect(history).toEqual([]);
});
it('throws NotFoundException when session not found', async ()=>{
sessionRepo.findOneBy = vi.fn(async ()=>null);
await expect(service.getHistory('missing')).rejects.toThrow(NotFoundException);
});
});
describe('appendMessage', ()=>{
it('saves a user message and returns it', async ()=>{
messageRepo.save = vi.fn(async (m)=>({
id: 'msg-uuid-2',
...m
}));
const result = await service.appendMessage({
sessionId: 'session-uuid-1',
role: 'user',
content: 'Hello'
});
expect(result).toBeDefined();
expect(sessionRepo.update).toHaveBeenCalledWith('session-uuid-1', expect.objectContaining({
lastActivityAt: expect.any(Date)
}));
});
it('uses neutral as default emotion when not specified', async ()=>{
await service.appendMessage({
sessionId: 'session-uuid-1',
role: 'assistant',
content: 'Hi there'
});
expect(messageRepo.create).toHaveBeenCalledWith(expect.objectContaining({
emotion: null
}));
});
});
});
//# sourceMappingURL=session.service.spec.js.map