Skip to content

Commit

Permalink
Merge pull request #365 from normand1/dn/token-provider-tests
Browse files Browse the repository at this point in the history
feat: [Issue-185] Token Provider Tests
  • Loading branch information
jkbrooks authored Nov 20, 2024
2 parents 95c3055 + 329db11 commit bea5567
Show file tree
Hide file tree
Showing 20 changed files with 380 additions and 86 deletions.
1 change: 1 addition & 0 deletions .nvmrc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
v23.1.0
7 changes: 5 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@
"docker:run": "bash ./scripts/docker.sh run",
"docker:bash": "bash ./scripts/docker.sh bash",
"docker:start": "bash ./scripts/docker.sh start",
"docker": "pnpm docker:build && pnpm docker:run && pnpm docker:bash"
"docker": "pnpm docker:build && pnpm docker:run && pnpm docker:bash",
"test": "pnpm --dir packages/core test"
},
"devDependencies": {
"concurrently": "^9.1.0",
Expand All @@ -27,7 +28,9 @@
"only-allow": "^1.2.1",
"prettier": "^3.3.3",
"typedoc": "^0.26.11",
"typescript": "5.6.3"
"typescript": "5.6.3",
"vite": "^5.4.11",
"vitest": "^2.1.5"
},
"pnpm": {
"overrides": {
Expand Down
4 changes: 4 additions & 0 deletions packages/core/.env.test
Original file line number Diff line number Diff line change
@@ -1,2 +1,6 @@
TEST_DATABASE_CLIENT=sqlite
NODE_ENV=test
MAIN_WALLET_ADDRESS=TEST_MAIN_WALLET_ADDRESS_VALUE
OPENAI_API_KEY=TEST_OPENAI_API_KEY_VALUE
RPC_URL=https://api.mainnet-beta.solana.com
WALLET_PUBLIC_KEY=2weMjPLLybRMMva1fM3U31goWWrCpF59CHWNhnCJ9Vyh
3 changes: 2 additions & 1 deletion packages/core/.gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
node_modules
dist
elizaConfig.yaml
custom_actions/
custom_actions/
cache/
25 changes: 0 additions & 25 deletions packages/core/jest.config.js

This file was deleted.

7 changes: 4 additions & 3 deletions packages/core/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@
"watch": "tsc --watch",
"dev": "tsup --format esm --dts --watch",
"build:docs": "cd docs && pnpm run build",
"test": "jest --runInBand",
"test:watch": "jest --runInBand --watch"
"test": "vitest run",
"test:watch": "vitest"
},
"author": "",
"license": "MIT",
Expand Down Expand Up @@ -48,7 +48,8 @@
"ts-node": "10.9.2",
"tslib": "2.8.0",
"tsup": "^8.3.5",
"typescript": "5.6.3"
"typescript": "5.6.3",
"@solana/web3.js": "1.95.4"
},
"dependencies": {
"@ai-sdk/anthropic": "^0.0.53",
Expand Down
9 changes: 5 additions & 4 deletions packages/core/src/runtime.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ import {
type Memory,
} from "./types.ts";
import { stringToUuid } from "./uuid.ts";
import { v4 as uuidv4 } from 'uuid';

/**
* Represents the runtime environment for an agent, handling message processing,
Expand Down Expand Up @@ -227,9 +228,9 @@ export class AgentRuntime implements IAgentRuntime {
this.databaseAdapter = opts.databaseAdapter;
// use the character id if it exists, otherwise use the agentId if it is passed in, otherwise use the character name
this.agentId =
opts.character.id ??
opts.agentId ??
stringToUuid(opts.character.name);
opts.character?.id ??
opts?.agentId ??
stringToUuid(opts.character?.name ?? uuidv4());

elizaLogger.success("Agent ID", this.agentId);

Expand Down Expand Up @@ -283,7 +284,7 @@ export class AgentRuntime implements IAgentRuntime {

this.token = opts.token;

[...(opts.character.plugins || []), ...(opts.plugins || [])].forEach(
[...(opts.character?.plugins || []), ...(opts.plugins || [])].forEach(
(plugin) => {
plugin.actions?.forEach((action) => {
this.registerAction(action);
Expand Down
12 changes: 12 additions & 0 deletions packages/core/src/test_resources/constants.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { type UUID } from "@ai16z/eliza/src/types.ts";

export const SERVER_URL = "http://localhost:7998";
export const SUPABASE_URL = "https://pronvzrzfwsptkojvudd.supabase.co";
export const SUPABASE_ANON_KEY =
"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6InByb252enJ6ZndzcHRrb2p2dWRkIiwicm9sZSI6ImFub24iLCJpYXQiOjE3MDY4NTYwNDcsImV4cCI6MjAyMjQzMjA0N30.I6_-XrqssUb2SWYg5DjsUqSodNS3_RPoET3-aPdqywM";
export const TEST_EMAIL = "testuser123@gmail.com";
export const TEST_PASSWORD = "testuser123@gmail.com";
export const TEST_EMAIL_2 = "testuser234@gmail.com";
export const TEST_PASSWORD_2 = "testuser234@gmail.com";

export const zeroUuid = "00000000-0000-0000-0000-000000000000" as UUID;
145 changes: 145 additions & 0 deletions packages/core/src/test_resources/createRuntime.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
import { SqliteDatabaseAdapter, loadVecExtensions } from "@ai16z/adapter-sqlite";
import { SqlJsDatabaseAdapter } from "@ai16z/adapter-sqljs";
import { SupabaseDatabaseAdapter } from "@ai16z/adapter-supabase";
import { DatabaseAdapter } from "../database.ts";
import { AgentRuntime } from "../runtime.ts";
import {
Action,
Evaluator,
ModelProviderName,
Provider,
} from "../types.ts";
import {
SUPABASE_ANON_KEY,
SUPABASE_URL,
TEST_EMAIL,
TEST_PASSWORD,
zeroUuid,
} from "./constants.ts";
import { User } from "./types.ts";
import { getEndpoint } from "../models.ts";

export async function createRuntime({
env,
conversationLength,
evaluators = [],
actions = [],
providers = [],
}: {
env?: Record<string, string> | NodeJS.ProcessEnv;
conversationLength?: number;
evaluators?: Evaluator[];
actions?: Action[];
providers?: Provider[];
}) {
let adapter: DatabaseAdapter;
let user: User;
let session: {
user: User;
};

switch (env?.TEST_DATABASE_CLIENT as string) {
case "sqljs":
{
const module = await import("sql.js");

const initSqlJs = module.default;

// SQLite adapter
const SQL = await initSqlJs({});
const db = new SQL.Database();

adapter = new SqlJsDatabaseAdapter(db);

// Load sqlite-vss
loadVecExtensions((adapter as SqlJsDatabaseAdapter).db);
// Create a test user and session
session = {
user: {
id: zeroUuid,
email: "test@example.com",
},
};
}
break;
case "supabase": {
const module = await import("@supabase/supabase-js");

const { createClient } = module;

const supabase = createClient(
env?.SUPABASE_URL ?? SUPABASE_URL,
env?.SUPABASE_SERVICE_API_KEY ?? SUPABASE_ANON_KEY
);

const { data } = await supabase.auth.signInWithPassword({
email: TEST_EMAIL!,
password: TEST_PASSWORD!,
});

user = data.user as User;
session = data.session as unknown as { user: User };

if (!session) {
const response = await supabase.auth.signUp({
email: TEST_EMAIL!,
password: TEST_PASSWORD!,
});

// Change the name of the user
const { error } = await supabase
.from("accounts")
.update({ name: "Test User" })
.eq("id", response.data.user?.id);

if (error) {
throw new Error(
"Create runtime error: " + JSON.stringify(error)
);
}

user = response.data.user as User;
session = response.data.session as unknown as { user: User };
}

adapter = new SupabaseDatabaseAdapter(
env?.SUPABASE_URL ?? SUPABASE_URL,
env?.SUPABASE_SERVICE_API_KEY ?? SUPABASE_ANON_KEY
);
}
case "sqlite":
default:
{
const module = await import("better-sqlite3");

const Database = module.default;

// SQLite adapter
adapter = new SqliteDatabaseAdapter(new Database(":memory:"));

// Load sqlite-vss
await loadVecExtensions((adapter as SqliteDatabaseAdapter).db);
// Create a test user and session
session = {
user: {
id: zeroUuid,
email: "test@example.com",
},
};
}
break;
}

const runtime = new AgentRuntime({
serverUrl: getEndpoint(ModelProviderName.OPENAI),
conversationLength,
token: env!.OPENAI_API_KEY!,
modelProvider: ModelProviderName.OPENAI,
actions: actions ?? [],
evaluators: evaluators ?? [],
providers: providers ?? [],
databaseAdapter: adapter,
});

return { user, session, runtime };
}
11 changes: 11 additions & 0 deletions packages/core/src/test_resources/testSetup.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import dotenv from "dotenv";
import path from "path";

// Load test environment variables
const envPath = path.resolve(__dirname, "../../.env.test");
console.log('Current directory:', __dirname);
console.log('Trying to load env from:', envPath);
const result = dotenv.config({ path: envPath });
if (result.error) {
console.error('Error loading .env.test:', result.error);
}
6 changes: 6 additions & 0 deletions packages/core/src/test_resources/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
export interface User {
id: string;
email?: string;
phone?: string;
role?: string;
}
26 changes: 26 additions & 0 deletions packages/core/src/tests/env.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { describe, it, expect } from 'vitest';
import fs from 'fs';
import path from 'path';

describe('Environment Setup', () => {
it('should verify .env.test file exists', () => {
const possiblePaths = [
path.join(process.cwd(), '.env.test'),
path.join(process.cwd(), 'packages/core/.env.test'),
path.join(__dirname, '../../.env.test'),
path.join(__dirname, '../.env.test'),
path.join(__dirname, '.env.test'),
];

console.log('Current working directory:', process.cwd());
console.log('__dirname:', __dirname);

const existingPaths = possiblePaths.filter(p => {
const exists = fs.existsSync(p);
console.log(`Path ${p} exists: ${exists}`);
return exists;
});

expect(existingPaths.length).toBeGreaterThan(0);
});
});
20 changes: 11 additions & 9 deletions packages/core/src/tests/goals.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,13 @@ import {
State,
} from "../types";

import { describe, test, expect, beforeEach, vi } from 'vitest';

// Mock the database adapter
export const mockDatabaseAdapter = {
getGoals: jest.fn(),
updateGoal: jest.fn(),
createGoal: jest.fn(),
getGoals: vi.fn(),
updateGoal: vi.fn(),
createGoal: vi.fn(),
};
const services = new Map<ServiceType, Service>();
// Mock the runtime
Expand Down Expand Up @@ -178,7 +180,7 @@ const sampleGoal: Goal = {

describe("getGoals", () => {
it("retrieves goals successfully", async () => {
(mockDatabaseAdapter.getGoals as jest.Mock).mockResolvedValue([
(mockDatabaseAdapter.getGoals).mockResolvedValue([
sampleGoal,
]);

Expand All @@ -197,7 +199,7 @@ describe("getGoals", () => {
});

it("handles failure to retrieve goals", async () => {
(mockDatabaseAdapter.getGoals as jest.Mock).mockRejectedValue(
(mockDatabaseAdapter.getGoals).mockRejectedValue(
new Error("Failed to retrieve goals")
);

Expand All @@ -223,7 +225,7 @@ describe("formatGoalsAsString", () => {

describe("updateGoal", () => {
it("updates a goal successfully", async () => {
(mockDatabaseAdapter.updateGoal as jest.Mock).mockResolvedValue(
(mockDatabaseAdapter.updateGoal).mockResolvedValue(
undefined
);

Expand All @@ -234,7 +236,7 @@ describe("updateGoal", () => {
});

it("handles failure to update a goal", async () => {
(mockDatabaseAdapter.updateGoal as jest.Mock).mockRejectedValue(
(mockDatabaseAdapter.updateGoal).mockRejectedValue(
new Error("Failed to update goal")
);

Expand All @@ -246,7 +248,7 @@ describe("updateGoal", () => {

describe("createGoal", () => {
it("creates a goal successfully", async () => {
(mockDatabaseAdapter.createGoal as jest.Mock).mockResolvedValue(
(mockDatabaseAdapter.createGoal).mockResolvedValue(
undefined
);

Expand All @@ -257,7 +259,7 @@ describe("createGoal", () => {
});

it("handles failure to create a goal", async () => {
(mockDatabaseAdapter.createGoal as jest.Mock).mockRejectedValue(
(mockDatabaseAdapter.createGoal).mockRejectedValue(
new Error("Failed to create goal")
);

Expand Down
Loading

0 comments on commit bea5567

Please sign in to comment.