Skip to content

Commit

Permalink
feat (chore): plugin-bootstrap: test config and test coverage (#3068)
Browse files Browse the repository at this point in the history
* Update fact.test.ts

* Update goal.test.ts

---------

Co-authored-by: Shakker Nerd <[email protected]>
  • Loading branch information
ai16z-demirix and shakkernerd authored Jan 31, 2025
1 parent 3c81965 commit e344805
Show file tree
Hide file tree
Showing 5 changed files with 481 additions and 1 deletion.
218 changes: 218 additions & 0 deletions packages/plugin-bootstrap/__tests__/actions/continue.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,218 @@
import { describe, expect, it, vi, beforeEach } from 'vitest';
import { continueAction } from '../../src/actions/continue';
import { composeContext, generateMessageResponse, generateTrueOrFalse, ModelClass } from '@elizaos/core';

vi.mock('@elizaos/core', () => ({
composeContext: vi.fn(),
generateMessageResponse: vi.fn(),
generateTrueOrFalse: vi.fn(),
elizaLogger: {
info: vi.fn(),
error: vi.fn(),
debug: vi.fn(),
log: vi.fn()
},
messageCompletionFooter: '\nResponse format:\n```\n{"content": {"text": string}}\n```',
booleanFooter: '\nResponse format: YES or NO',
ModelClass: {
SMALL: 'small',
LARGE: 'large'
}
}));

describe('continueAction', () => {
let mockRuntime;
let mockMessage;
let mockState;
let mockCallback;

beforeEach(() => {
mockRuntime = {
character: {
settings: {},
name: 'TestBot',
bio: 'A test bot',
lore: 'Test lore',
knowledge: 'Test knowledge',
templates: {
messageHandlerTemplate: 'Test template {{agentName}}'
}
},
messageManager: {
getLastMessageInRoom: vi.fn().mockResolvedValue({
userId: 'test-user',
content: { text: 'Hello' }
}),
getMemories: vi.fn().mockResolvedValue([{
userId: 'test-agent',
content: {
text: 'Previous bot message',
action: 'CONTINUE'
}
}])
},
composeState: vi.fn().mockResolvedValue({
agentId: 'test-agent',
roomId: 'test-room'
}),
updateRecentMessageState: vi.fn().mockImplementation(state => Promise.resolve({
...state,
recentMessagesData: [{
userId: 'test-agent',
content: {
text: 'Previous bot message',
action: 'CONTINUE'
}
}]
})),
agentId: 'test-agent',
databaseAdapter: {
log: vi.fn().mockResolvedValue(true)
}
};

mockMessage = {
id: 'test-message-1',
content: {
text: 'Hello, how are you' // No question mark to avoid early return
},
roomId: 'test-room',
userId: 'test-user',
createdAt: Date.now()
};

mockState = {
agentId: 'test-agent',
roomId: 'test-room',
recentMessagesData: [{
id: 'test-message-2',
userId: 'test-agent',
content: {
text: 'Previous bot message',
action: 'NONE',
inReplyTo: 'different-message-id' // Different ID to avoid early return
},
createdAt: Date.now() - 1000
}]
};

mockCallback = vi.fn();

// Reset all mocks
vi.clearAllMocks();
});

describe('validation', () => {
it('should validate successfully when conditions are met', async () => {
mockRuntime.messageManager.getMemories.mockResolvedValueOnce([{
userId: 'test-agent',
content: {
text: 'Previous bot message',
action: 'NONE'
}
}]);

const result = await continueAction.validate(mockRuntime, mockMessage);
expect(result).toBe(true);
});

it('should fail validation when too many continues in a row', async () => {
mockRuntime.messageManager.getMemories.mockResolvedValueOnce([
{
userId: 'test-agent',
content: {
text: 'Message 1',
action: 'CONTINUE'
}
},
{
userId: 'test-agent',
content: {
text: 'Message 2',
action: 'CONTINUE'
}
},
{
userId: 'test-agent',
content: {
text: 'Message 3',
action: 'CONTINUE'
}
}
]);

const result = await continueAction.validate(mockRuntime, mockMessage);
expect(result).toBe(false);
});
});

describe('action properties', () => {
it('should have correct action properties', () => {
expect(continueAction.name).toBe('CONTINUE');
expect(continueAction.description).toBeDefined();
expect(continueAction.examples).toBeDefined();
expect(Array.isArray(continueAction.examples)).toBe(true);
});

it('should have valid examples', () => {
continueAction.examples.forEach(example => {
expect(Array.isArray(example)).toBe(true);
example.forEach(interaction => {
expect(interaction).toHaveProperty('user');
expect(interaction).toHaveProperty('content');
});
});
});
});

describe('message generation', () => {
it('should generate continuation message', async () => {
const mockResponse = {
content: {
text: 'This is a continuation message',
action: 'CONTINUE',
inReplyTo: 'test-message-1'
}
};

const mockStateWithContext = {
...mockState,
actionExamples: [],
bio: mockRuntime.character.bio,
lore: mockRuntime.character.lore,
knowledge: mockRuntime.character.knowledge,
agentName: mockRuntime.character.name,
messageDirections: 'Test directions',
recentMessages: 'Test recent messages',
actions: 'Test actions',
providers: [],
attachments: []
};

mockRuntime.messageManager.getMemories.mockResolvedValueOnce([{
id: 'test-message-2',
userId: 'test-agent',
content: {
text: 'Previous bot message',
action: 'NONE',
inReplyTo: 'different-message-id'
},
createdAt: Date.now() - 1000
}]);

mockRuntime.updateRecentMessageState.mockResolvedValueOnce(mockStateWithContext);

vi.mocked(composeContext).mockReturnValue('mock-context');
vi.mocked(generateTrueOrFalse).mockResolvedValue(true);
vi.mocked(generateMessageResponse).mockResolvedValue(mockResponse);

await continueAction.handler(mockRuntime, mockMessage, mockStateWithContext, {}, mockCallback);

expect(composeContext).toHaveBeenCalled();
expect(generateTrueOrFalse).toHaveBeenCalled();
expect(generateMessageResponse).toHaveBeenCalled();
expect(mockCallback).toHaveBeenCalledWith(mockResponse);
expect(mockRuntime.databaseAdapter.log).toHaveBeenCalled();
});
});
});
113 changes: 113 additions & 0 deletions packages/plugin-bootstrap/__tests__/evaluators/fact.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
import { describe, expect, it, vi, beforeEach } from 'vitest';
import { factEvaluator } from '../../src/evaluators/fact';
import { composeContext, generateObjectArray, MemoryManager } from '@elizaos/core';

vi.mock('@elizaos/core', () => ({
composeContext: vi.fn(),
generateObjectArray: vi.fn(),
MemoryManager: vi.fn().mockImplementation((config: any) => ({
getMemoriesByEvaluator: vi.fn().mockResolvedValue([]),
addMemory: vi.fn().mockResolvedValue(true),
addEmbeddingToMemory: vi.fn().mockResolvedValue({
id: 'test-memory-id',
content: {
text: 'Test memory content'
}
}),
createMemory: vi.fn().mockResolvedValue({
id: 'test-memory-id',
content: {
text: 'Test memory content'
}
})
})),
ModelClass: {
SMALL: 'small'
}
}));

describe('factEvaluator', () => {
let mockRuntime;
let mockMessage;

beforeEach(() => {
mockRuntime = {
character: {
settings: {}
},
messageManager: {
countMemories: vi.fn().mockResolvedValue(5)
},
composeState: vi.fn().mockResolvedValue({
agentId: 'test-agent',
roomId: 'test-room'
}),
getConversationLength: vi.fn().mockReturnValue(10)
};

mockMessage = {
content: {
text: 'I live in New York and work as a software engineer.'
},
roomId: 'test-room'
};

// Reset all mocks
vi.clearAllMocks();
});

describe('validation', () => {
it('should validate successfully', async () => {
const result = await factEvaluator.validate(mockRuntime, mockMessage);
expect(result).toBe(true);
expect(mockRuntime.messageManager.countMemories).toHaveBeenCalledWith('test-room');
expect(mockRuntime.getConversationLength).toHaveBeenCalled();
});
});

describe('evaluator properties', () => {
it('should have correct evaluator properties', () => {
expect(factEvaluator.name).toBe('GET_FACTS');
expect(factEvaluator.similes).toContain('GET_CLAIMS');
expect(factEvaluator.description).toBeDefined();
expect(factEvaluator.description).toContain('Extract factual information');
expect(factEvaluator.examples).toBeDefined();
expect(Array.isArray(factEvaluator.examples)).toBe(true);
});

it('should have valid examples', () => {
factEvaluator.examples.forEach(example => {
expect(example).toBeDefined();
// will add more specific example validations based on the example structure
});
});
});

describe('fact extraction', () => {
it('should handle fact extraction', async () => {
const mockFacts = [
{
claim: 'User lives in New York',
type: 'fact',
in_bio: false,
already_known: false
},
{
claim: 'User works as a software engineer',
type: 'fact',
in_bio: false,
already_known: false
}
];

vi.mocked(composeContext).mockReturnValue('mock-context');
vi.mocked(generateObjectArray).mockResolvedValue(mockFacts);

const result = await factEvaluator.handler(mockRuntime, mockMessage);

expect(composeContext).toHaveBeenCalled();
expect(generateObjectArray).toHaveBeenCalled();
expect(result).toBeDefined();
});
});
});
Loading

0 comments on commit e344805

Please sign in to comment.