Skip to content

Commit

Permalink
add tests
Browse files Browse the repository at this point in the history
  • Loading branch information
wtfsayo committed Feb 11, 2025
1 parent 3251fdc commit 4d2609a
Showing 1 changed file with 331 additions and 6 deletions.
337 changes: 331 additions & 6 deletions packages/plugin-sqlite/__tests__/sqlite-adapter.test.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
import type { UUID } from '@elizaos/core';
import type { Account, Actor, Character, UUID } from '@elizaos/core';
import { stringToUuid } from '@elizaos/core';
import type { Database } from 'better-sqlite3';
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
import { SqliteDatabaseAdapter } from '../src';
import { load } from '../src/sqlite_vec';
import type { Database } from 'better-sqlite3';

// Mock the logger
vi.mock('@elizaos/core', async () => {
const actual = await vi.importActual('@elizaos/core');
const actual = await vi.importActual<typeof import('@elizaos/core')>('@elizaos/core');
return {
...actual as any,
...actual,
logger: {
error: vi.fn()
}
Expand All @@ -20,9 +21,17 @@ vi.mock('../src/sqlite_vec', () => ({
load: vi.fn()
}));


interface MockDatabase {
prepare: ReturnType<typeof vi.fn>;
exec: ReturnType<typeof vi.fn>;
close: ReturnType<typeof vi.fn>;
}

describe('SqliteDatabaseAdapter', () => {
let adapter: SqliteDatabaseAdapter;
let mockDb: any;
let mockDb: MockDatabase;
const testUuid = stringToUuid('test-character-id');

beforeEach(() => {
// Create mock database methods
Expand All @@ -38,7 +47,7 @@ describe('SqliteDatabaseAdapter', () => {
};

// Initialize adapter with mock db
adapter = new SqliteDatabaseAdapter(mockDb as Database);
adapter = new SqliteDatabaseAdapter(mockDb as unknown as Database);
});

afterEach(() => {
Expand Down Expand Up @@ -168,4 +177,320 @@ describe('SqliteDatabaseAdapter', () => {
expect(mockDb.close).toHaveBeenCalled();
});
});

describe('createAccount', () => {
it('should create an account successfully', async () => {
const runMock = vi.fn();
mockDb.prepare.mockReturnValueOnce({
run: runMock
});

const account: Account = {
id: 'test-id' as UUID,
name: 'Test User',
username: 'testuser',
email: '[email protected]',
avatarUrl: 'https://example.com/avatar.png'
};

const result = await adapter.createAccount(account);

expect(mockDb.prepare).toHaveBeenCalledWith(
'INSERT INTO accounts (id, name, username, email, avatarUrl) VALUES (?, ?, ?, ?, ?)'
);
expect(runMock).toHaveBeenCalledWith(
account.id,
account.name,
account.username,
account.email,
account.avatarUrl
);
expect(result).toBe(true);
});

it('should handle errors when creating account', async () => {
mockDb.prepare.mockReturnValueOnce({
run: vi.fn().mockImplementationOnce(() => {
throw new Error('Database error');
})
});

const account: Account = {
id: 'test-id' as UUID,
name: 'Test User',
username: 'testuser',
email: '[email protected]',
avatarUrl: 'https://example.com/avatar.png'
};

const result = await adapter.createAccount(account);
expect(result).toBe(false);
});
});

describe('getActorDetails', () => {
it('should return actor details', async () => {
const mockActors: Actor[] = [
{ id: 'actor-1' as UUID, name: 'Actor 1', username: 'actor1' },
{ id: 'actor-2' as UUID, name: 'Actor 2', username: 'actor2' }
];

mockDb.prepare.mockReturnValueOnce({
all: vi.fn().mockReturnValueOnce(mockActors)
});

const result = await adapter.getActorDetails({ roomId: 'room-1' as UUID });

expect(mockDb.prepare).toHaveBeenCalledWith(expect.stringContaining('SELECT a.id, a.name, a.username'));
expect(result).toEqual(mockActors);
});

it('should filter out null actors', async () => {
mockDb.prepare.mockReturnValueOnce({
all: vi.fn().mockReturnValueOnce([null, { id: 'actor-1' as UUID, name: 'Actor 1', username: 'actor1' }, null])
});

const result = await adapter.getActorDetails({ roomId: 'room-1' as UUID });

expect(result).toHaveLength(1);
expect(result[0]).toEqual({ id: 'actor-1', name: 'Actor 1', username: 'actor1' });
});
});

describe('getMemoryById', () => {
it('should return memory when it exists', async () => {
const mockMemory = {
id: 'memory-1' as UUID,
content: JSON.stringify({ text: 'Test memory' })
};

mockDb.prepare.mockReturnValueOnce({
get: vi.fn().mockReturnValueOnce(mockMemory),
bind: vi.fn()
});

const result = await adapter.getMemoryById('memory-1' as UUID);

expect(mockDb.prepare).toHaveBeenCalledWith('SELECT * FROM memories WHERE id = ?');
expect(result).toEqual({
...mockMemory,
content: { text: 'Test memory' }
});
});

it('should return null when memory does not exist', async () => {
mockDb.prepare.mockReturnValueOnce({
get: vi.fn().mockReturnValueOnce(undefined),
bind: vi.fn()
});

const result = await adapter.getMemoryById('non-existent' as UUID);
expect(result).toBeNull();
});
});

describe('Character operations', () => {
const mockCharacter: Required<Pick<Character, 'id' | 'name' | 'bio' | 'lore' | 'messageExamples' | 'postExamples' | 'topics' | 'adjectives' | 'style'>> = {
id: testUuid,
name: 'Test Character',
bio: 'Test Bio',
lore: ['Test lore'],
messageExamples: [[]],
postExamples: ['Test post'],
topics: ['Test topic'],
adjectives: ['Test adjective'],
style: {
all: ['Test style'],
chat: ['Test chat style'],
post: ['Test post style']
}
};

it('should create a character', async () => {
const runMock = vi.fn();
mockDb.prepare.mockReturnValueOnce({
run: runMock
});

await adapter.createCharacter(mockCharacter);

expect(mockDb.prepare).toHaveBeenCalledWith(expect.stringContaining('INSERT INTO characters'));
expect(runMock).toHaveBeenCalledWith(
mockCharacter.id,
mockCharacter.name,
mockCharacter.bio,
JSON.stringify(mockCharacter)
);
});

it('should create a character with generated UUID', async () => {
const runMock = vi.fn();
mockDb.prepare.mockReturnValueOnce({
run: runMock
});

const characterWithoutId: Omit<typeof mockCharacter, 'id'> = {
name: mockCharacter.name,
bio: mockCharacter.bio,
lore: mockCharacter.lore,
messageExamples: mockCharacter.messageExamples,
postExamples: mockCharacter.postExamples,
topics: mockCharacter.topics,
adjectives: mockCharacter.adjectives,
style: mockCharacter.style
};

await adapter.createCharacter(characterWithoutId as Character);

expect(mockDb.prepare).toHaveBeenCalledWith(expect.stringContaining('INSERT INTO characters'));
expect(runMock).toHaveBeenCalledWith(
expect.any(String),
characterWithoutId.name,
characterWithoutId.bio,
expect.any(String)
);
});

it('should update a character', async () => {
const runMock = vi.fn();
mockDb.prepare.mockReturnValueOnce({
run: runMock
});

await adapter.updateCharacter(mockCharacter);

expect(mockDb.prepare).toHaveBeenCalledWith(expect.stringContaining('UPDATE characters'));
expect(runMock).toHaveBeenCalledWith(
mockCharacter.name,
mockCharacter.bio,
JSON.stringify(mockCharacter),
mockCharacter.id
);
});

it('should get a character', async () => {
mockDb.prepare.mockReturnValueOnce({
get: vi.fn().mockReturnValueOnce(mockCharacter)
});

const result = await adapter.getCharacter(mockCharacter.id);

expect(mockDb.prepare).toHaveBeenCalledWith('SELECT * FROM characters WHERE id = ?');
expect(result).toEqual(mockCharacter);
});

it('should return null when getting non-existent character', async () => {
mockDb.prepare.mockReturnValueOnce({
get: vi.fn().mockReturnValueOnce(null)
});

const result = await adapter.getCharacter(testUuid);

expect(mockDb.prepare).toHaveBeenCalledWith('SELECT * FROM characters WHERE id = ?');
expect(result).toBeNull();
});

it('should remove a character', async () => {
const runMock = vi.fn();
mockDb.prepare.mockReturnValueOnce({
run: runMock
});

await adapter.removeCharacter(mockCharacter.id);

expect(mockDb.prepare).toHaveBeenCalledWith('DELETE FROM characters WHERE id = ?');
expect(runMock).toHaveBeenCalledWith(mockCharacter.id);
});

it('should list all characters', async () => {
const mockCharacters = [mockCharacter];
mockDb.prepare.mockReturnValueOnce({
all: vi.fn().mockReturnValueOnce(mockCharacters)
});

const result = await adapter.listCharacters();

expect(mockDb.prepare).toHaveBeenCalledWith('SELECT * FROM characters');
expect(result).toEqual(mockCharacters);
});

it('should import a character', async () => {
const runMock = vi.fn();
mockDb.prepare.mockReturnValueOnce({
run: runMock
});

await adapter.importCharacter(mockCharacter);

expect(mockDb.prepare).toHaveBeenCalledWith(expect.stringContaining('INSERT INTO characters'));
expect(runMock).toHaveBeenCalledWith(
mockCharacter.id,
mockCharacter.name,
mockCharacter.bio,
JSON.stringify(mockCharacter)
);
});

it('should export a character', async () => {
mockDb.prepare.mockReturnValueOnce({
get: vi.fn().mockReturnValueOnce(mockCharacter)
});

const result = await adapter.exportCharacter(mockCharacter.id);

expect(mockDb.prepare).toHaveBeenCalledWith('SELECT * FROM characters WHERE id = ?');
expect(result).toEqual(mockCharacter);
});
});

describe('Cache operations', () => {
const mockParams = {
key: 'test-key',
agentId: 'agent-1' as UUID,
value: 'test-value'
};

it('should set cache value', async () => {
const runMock = vi.fn();
mockDb.prepare.mockReturnValueOnce({
run: runMock
});

const result = await adapter.setCache(mockParams);

expect(mockDb.prepare).toHaveBeenCalledWith(expect.stringContaining('INSERT OR REPLACE INTO cache'));
expect(runMock).toHaveBeenCalledWith(mockParams.key, mockParams.agentId, mockParams.value);
expect(result).toBe(true);
});

it('should get cache value', async () => {
mockDb.prepare.mockReturnValueOnce({
get: vi.fn().mockReturnValueOnce({ value: mockParams.value })
});

const result = await adapter.getCache({
key: mockParams.key,
agentId: mockParams.agentId
});

expect(mockDb.prepare).toHaveBeenCalledWith(expect.stringContaining('SELECT value FROM cache'));
expect(result).toBe(mockParams.value);
});

it('should delete cache value', async () => {
const runMock = vi.fn();
mockDb.prepare.mockReturnValueOnce({
run: runMock
});

const result = await adapter.deleteCache({
key: mockParams.key,
agentId: mockParams.agentId
});

expect(mockDb.prepare).toHaveBeenCalledWith('DELETE FROM cache WHERE key = ? AND agentId = ?');
expect(runMock).toHaveBeenCalledWith(mockParams.key, mockParams.agentId);
expect(result).toBe(true);
});
});
});

0 comments on commit 4d2609a

Please sign in to comment.