Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Adding unit tests for start - Covering goals, defaultCharacters, relationships, evaulators, posts, database, messages #367

Open
wants to merge 13 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 35 additions & 0 deletions packages/core/README-TESTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# Core Package Tests

This package contains a test suite for evaluating functionalities using **Jest**.

## Prerequisites

1. **pnpm**: Ensure you have `pnpm` installed. If not, you can install it globally using:
```bash
npm install -g pnpm
```

2. **Environment Variables - NOT REQUIRED** : Set up a `.env` file in the project root (eliza) with the necessary environment variables. Copy .env.example file and add required variables.

## Setup

1. Navigate to the `packages/core` directory:
```bash
cd packages/core
```

2. Install dependencies:
```bash
pnpm install
```

## Running Tests

Run all tests using:
```bash
pnpm test
```

The test results will be displayed in the terminal.

---
1 change: 0 additions & 1 deletion packages/core/jest.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ export default {
testEnvironment: "node",
rootDir: "./src",
testMatch: ["**/*.test.ts"],
setupFilesAfterEnv: ["<rootDir>/test_resources/testSetup.ts"],
testTimeout: 120000,
globals: {
__DEV__: true,
Expand Down
2 changes: 1 addition & 1 deletion packages/core/src/embedding.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { EmbeddingModel, FlagEmbedding } from "fastembed";
import { FlagEmbedding } from "fastembed";
import path from "path";
import { fileURLToPath } from "url";
import { models } from "./models.ts";
Expand Down
239 changes: 239 additions & 0 deletions packages/core/src/tests/database.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,239 @@
/* eslint-disable no-dupe-class-members */
import { DatabaseAdapter } from '../database.ts'; // Adjust the import based on your project structure
import { Memory, Actor, Account, Goal, GoalStatus, Participant, Relationship, UUID } from '../types'; // Adjust based on your types location

class MockDatabaseAdapter extends DatabaseAdapter {
getMemoryById(_id: UUID): Promise<Memory | null> {
throw new Error('Method not implemented.');
}
log(_params: { body: { [key: string]: unknown; }; userId: UUID; roomId: UUID; type: string; }): Promise<void> {
throw new Error('Method not implemented.');
}
getActorDetails(_params: { roomId: UUID; }): Promise<Actor[]> {
throw new Error('Method not implemented.');
}
searchMemoriesByEmbedding(_embedding: number[], _params: { match_threshold?: number; count?: number; roomId?: UUID; agentId?: UUID; unique?: boolean; tableName: string; }): Promise<Memory[]> {
throw new Error('Method not implemented.');
}
createMemory(_memory: Memory, _tableName: string, _unique?: boolean): Promise<void> {
throw new Error('Method not implemented.');
}
removeMemory(_memoryId: UUID, _tableName: string): Promise<void> {
throw new Error('Method not implemented.');
}
removeAllMemories(_roomId: UUID, _tableName: string): Promise<void> {
throw new Error('Method not implemented.');
}
countMemories(_roomId: UUID, _unique?: boolean, _tableName?: string): Promise<number> {
throw new Error('Method not implemented.');
}
getGoals(_params: { roomId: UUID; userId?: UUID | null; onlyInProgress?: boolean; count?: number; }): Promise<Goal[]> {
throw new Error('Method not implemented.');
}
updateGoal(_goal: Goal): Promise<void> {
throw new Error('Method not implemented.');
}
createGoal(_goal: Goal): Promise<void> {
throw new Error('Method not implemented.');
}
removeGoal(_goalId: UUID): Promise<void> {
throw new Error('Method not implemented.');
}
removeAllGoals(_roomId: UUID): Promise<void> {
throw new Error('Method not implemented.');
}
getRoom(_roomId: UUID): Promise<UUID | null> {
throw new Error('Method not implemented.');
}
createRoom(_roomId?: UUID): Promise<UUID> {
throw new Error('Method not implemented.');
}
removeRoom(_roomId: UUID): Promise<void> {
throw new Error('Method not implemented.');
}
getRoomsForParticipant(_userId: UUID): Promise<UUID[]> {
throw new Error('Method not implemented.');
}
getRoomsForParticipants(_userIds: UUID[]): Promise<UUID[]> {
throw new Error('Method not implemented.');
}
addParticipant(_userId: UUID, _roomId: UUID): Promise<boolean> {
throw new Error('Method not implemented.');
}
removeParticipant(_userId: UUID, _roomId: UUID): Promise<boolean> {
throw new Error('Method not implemented.');
}
getParticipantsForAccount(userId: UUID): Promise<Participant[]>;
getParticipantsForAccount(userId: UUID): Promise<Participant[]>;
getParticipantsForAccount(_userId: unknown): Promise<import("../types").Participant[]> {
throw new Error('Method not implemented.');
}
getParticipantsForRoom(_roomId: UUID): Promise<UUID[]> {
throw new Error('Method not implemented.');
}
getParticipantUserState(_roomId: UUID, _userId: UUID): Promise<'FOLLOWED' | 'MUTED' | null> {
throw new Error('Method not implemented.');
}
setParticipantUserState(_roomId: UUID, _userId: UUID, _state: 'FOLLOWED' | 'MUTED' | null): Promise<void> {
throw new Error('Method not implemented.');
}
createRelationship(_params: { userA: UUID; userB: UUID; }): Promise<boolean> {
throw new Error('Method not implemented.');
}
getRelationship(_params: { userA: UUID; userB: UUID; }): Promise<Relationship | null> {
throw new Error('Method not implemented.');
}
getRelationships(_params: { userId: UUID; }): Promise<Relationship[]> {
throw new Error('Method not implemented.');
}
db: any = {};

// Mock method for getting memories by room IDs
async getMemoriesByRoomIds(params: { roomIds: `${string}-${string}-${string}-${string}-${string}`[]; agentId?: `${string}-${string}-${string}-${string}-${string}`; tableName: string }): Promise<Memory[]> {
return [{
id: 'memory-id' as UUID,
content: 'Test Memory',
roomId: params.roomIds[0],
userId: 'user-id' as UUID,
agentId: params.agentId ?? 'agent-id' as UUID
}] as unknown as Memory[];
}

// Mock method for getting cached embeddings
async getCachedEmbeddings(_params: { query_table_name: string; query_threshold: number; query_input: string; query_field_name: string; query_field_sub_name: string; query_match_count: number }): Promise<any[]> {
return [{
embedding: [0.1, 0.2, 0.3],
levenshtein_distance: 0.4
}];
}

// Mock method for searching memories
async searchMemories(params: { tableName: string; roomId: `${string}-${string}-${string}-${string}-${string}`; embedding: number[]; match_threshold: number; match_count: number; unique: boolean }): Promise<Memory[]> {
return [{
id: 'memory-id' as UUID,
content: 'Test Memory',
roomId: params.roomId,
userId: 'user-id' as UUID,
agentId: 'agent-id' as UUID
}] as unknown as Memory[];
}

// Mock method for getting account by ID
async getAccountById(userId: UUID): Promise<Account | null> {
return { id: userId, username: 'testuser', name: 'Test Account' } as Account;
}

// Other methods stay the same...
async createAccount(_account: Account): Promise<boolean> {
return true;
}

async getMemories(params: { roomId: UUID; count?: number; unique?: boolean; tableName: string }): Promise<Memory[]> {
return [{
id: 'memory-id' as UUID,
content: 'Test Memory',
roomId: params.roomId,
userId: 'user-id' as UUID,
agentId: 'agent-id' as UUID
}] as unknown as Memory[];
}

async getActors(_params: { roomId: UUID }): Promise<Actor[]> {
return [{
id: 'actor-id' as UUID,
name: 'Test Actor',
username: 'testactor',
roomId: 'room-id' as UUID // Ensure roomId is provided
}] as unknown as Actor[];
}

async updateGoalStatus(_params: { goalId: UUID, status: GoalStatus }): Promise<void> {
return Promise.resolve();
}

async getGoalById(goalId: UUID): Promise<Goal | null> {
return {
id: goalId,
status: GoalStatus.IN_PROGRESS,
roomId: 'room-id' as UUID,
userId: 'user-id' as UUID,
name: 'Test Goal',
objectives: []
} as Goal;
}
}

// Now, let’s fix the test suite.

describe('DatabaseAdapter Tests', () => {
let adapter: MockDatabaseAdapter;
const roomId = 'room-id' as UUID;

beforeEach(() => {
adapter = new MockDatabaseAdapter();
});

it('should return memories by room ID', async () => {
const memories = await adapter.getMemoriesByRoomIds({
roomIds: ['room-id' as `${string}-${string}-${string}-${string}-${string}`],
tableName: 'test_table'
});
expect(memories).toHaveLength(1);
expect(memories[0].roomId).toBe('room-id');
});

it('should return cached embeddings', async () => {
const embeddings = await adapter.getCachedEmbeddings({
query_table_name: 'test_table',
query_threshold: 0.5,
query_input: 'test query',
query_field_name: 'field',
query_field_sub_name: 'subfield',
query_match_count: 5
});
expect(embeddings).toHaveLength(1);
expect(embeddings[0].embedding).toEqual([0.1, 0.2, 0.3]);
});

it('should search memories based on embedding', async () => {
const memories = await adapter.searchMemories({
tableName: 'test_table',
roomId: 'room-id' as `${string}-${string}-${string}-${string}-${string}`,
embedding: [0.1, 0.2, 0.3],
match_threshold: 0.5,
match_count: 3,
unique: true
});
expect(memories).toHaveLength(1);
expect(memories[0].roomId).toBe('room-id');
});

it('should get an account by user ID', async () => {
const account = await adapter.getAccountById('test-user-id' as UUID);
expect(account).not.toBeNull();
expect(account.username).toBe('testuser');
});

it('should create a new account', async () => {
const newAccount: Account = { id: 'new-user-id' as UUID, username: 'newuser', name: 'New Account' };
const result = await adapter.createAccount(newAccount);
expect(result).toBe(true);
});

it('should update the goal status', async () => {
const goalId = 'goal-id' as UUID;
await expect(adapter.updateGoalStatus({ goalId, status: GoalStatus.IN_PROGRESS })).resolves.toBeUndefined();
});

it('should return actors by room ID', async () => {
const actors = await adapter.getActors({ roomId });
expect(actors).toHaveLength(1);
});

it('should get a goal by ID', async () => {
const goalId = 'goal-id' as UUID;
const goal = await adapter.getGoalById(goalId);
expect(goal).not.toBeNull();
expect(goal?.status).toBe(GoalStatus.IN_PROGRESS);
});
});
48 changes: 48 additions & 0 deletions packages/core/src/tests/defaultCharacters.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import { defaultCharacter } from '../defaultCharacter';
import { ModelProviderName } from '../types';

describe('defaultCharacter', () => {
it('should have the correct name', () => {
expect(defaultCharacter.name).toBe('Eliza');
});

it('should have an empty plugins array', () => {
expect(defaultCharacter.plugins).toEqual([]);
});

it('should have an empty clients array', () => {
expect(defaultCharacter.clients).toEqual([]);
});

it('should have the correct modelProvider', () => {
expect(defaultCharacter.modelProvider).toBe(ModelProviderName.OPENAI);
});

it('should have the correct voice model', () => {
expect(defaultCharacter.settings.voice.model).toBe('en_US-hfc_female-medium');
});

it('should have a system description', () => {
expect(defaultCharacter.system).toBe('Roleplay and generate interesting on behalf of Eliza.');
});

it('should have a bio array with at least one entry', () => {
expect(defaultCharacter.bio.length).toBeGreaterThan(0);
});

it('should have a lore array with at least one entry', () => {
expect(defaultCharacter.lore.length).toBeGreaterThan(0);
});

it('should have messageExamples array with at least one example', () => {
expect(defaultCharacter.messageExamples.length).toBeGreaterThan(0);
});

it('should have a topics array with at least one broad topic', () => {
expect(defaultCharacter.topics).toContain('metaphysics');
});

it('should have style settings with "all" array', () => {
expect(defaultCharacter.style.all.length).toBeGreaterThan(0);
});
});
Loading
Loading