UNPKG

permamind

Version:

An MCP server that provides an immortal memory layer for AI agents and clients

312 lines (311 loc) 12.2 kB
import { afterEach, beforeEach, describe, expect, it } from "vitest"; class AOLiteTestSuiteBuilderImpl { name; processDefinition; aoLiteService; configuration = {}; environment; setupFn; teardownFn; testCases = []; constructor(name, processDefinition, aoLiteService) { this.name = name; this.processDefinition = processDefinition; this.aoLiteService = aoLiteService; } addHandler(handlerName, testData) { const testCase = { assertions: [ { expected: true, id: `assert-${handlerName}-${Date.now()}`, message: `${handlerName} should return output`, target: "Output", type: "exists", }, ], description: `Automated test for ${handlerName} handler`, id: `test-${handlerName}-${Date.now()}`, messages: [ { action: handlerName, data: testData, id: `msg-${handlerName}-${Date.now()}`, tags: [{ name: "Action", value: handlerName }], }, ], name: `Test ${handlerName} Handler`, timeout: 10000, }; this.testCases.push(testCase); return this; } addTestCase(testCase) { this.testCases.push(testCase); return this; } async build() { describe(this.name, () => { beforeEach(async () => { this.environment = await this.aoLiteService.createTestEnvironment(this.processDefinition, this.configuration); if (this.setupFn) { await this.setupFn(this.environment); } }); afterEach(async () => { if (this.teardownFn && this.environment) { await this.teardownFn(this.environment); } }); for (const testCase of this.testCases) { it(testCase.name, async () => { if (!this.environment) { throw new Error("Test environment not initialized"); } const result = await this.aoLiteService.executeTestCase(testCase, this.environment); expect(result.status).toBe("passed"); expect(result.error).toBeUndefined(); // Validate all assertions passed for (const assertion of result.assertionResults) { expect(assertion.status).toBe("passed"); } // Validate all messages were sent successfully for (const message of result.messageResults) { expect(message.status).toBe("sent"); } }); } }); } withConfiguration(configuration) { this.configuration = { ...this.configuration, ...configuration }; return this; } withSetup(setup) { this.setupFn = setup; return this; } withTeardown(teardown) { this.teardownFn = teardown; return this; } } const service = (aoLiteService, aoMessageService, processService) => { return { createAOLiteEnvironment: async (processDefinition, configuration) => { const environment = await aoLiteService.createTestEnvironment(processDefinition, configuration); // Validate environment is properly initialized expect(environment.processId).toBe(processDefinition.id); expect(environment.processSource).toBe(processDefinition.compiledLua); expect(environment.isRunning).toBe(true); expect(environment.state).toBeDefined(); return environment; }, createTestSuite: (name, processDefinition, configuration) => { return new AOLiteTestSuiteBuilderImpl(name, processDefinition, aoLiteService).withConfiguration(configuration || {}); }, runAOLiteTest: async (testName, testCase, environment) => { describe(testName, () => { it(`should execute ${testCase.name}`, async () => { const result = await aoLiteService.executeTestCase(testCase, environment); expect(result.status).toBe("passed"); expect(result.error).toBeUndefined(); // Validate all assertions for (const assertion of result.assertionResults) { expect(assertion.status).toBe("passed"); if (assertion.message) { expect(assertion.actual).toBeDefined(); } } // Validate all messages for (const message of result.messageResults) { expect(message.status).toBe("sent"); expect(message.duration).toBeGreaterThan(0); } }); }); }, validateAOLiteCompatibility: async (processDefinition) => { try { // Check if the process definition is compatible with AOLite const hasHandlers = processDefinition.compiledLua.includes("Handlers.add"); const hasAOPatterns = processDefinition.compiledLua.includes("msg.") || processDefinition.compiledLua.includes("ao."); if (!hasHandlers) { console.warn("Process definition lacks handler patterns for AOLite testing"); return false; } if (!hasAOPatterns) { console.warn("Process definition lacks AO message patterns for AOLite testing"); return false; } // Try to create a test environment const environment = await aoLiteService.createTestEnvironment(processDefinition); // Validate the environment was created successfully return environment.isRunning && environment.state !== null; } catch (error) { console.error("AOLite compatibility validation failed:", error); return false; } }, }; }; // Helper functions for common AOLite test patterns export const AOLiteTestHelpers = { createBalanceTest: (target) => ({ assertions: [ { expected: "Balance", id: `assert-balance-${Date.now()}`, message: "Balance response should contain balance information", target: "Output", type: "contains", }, ], description: "Test balance query functionality", id: `balance-test-${Date.now()}`, messages: [ { action: "Balance", id: `msg-balance-${Date.now()}`, tags: target ? [ { name: "Action", value: "Balance" }, { name: "Target", value: target }, ] : [{ name: "Action", value: "Balance" }], }, ], name: "Balance Test", timeout: 10000, }), createCustomAssertion: (id, type, target, expected, message) => ({ expected, id, message, target, type, }), createEnvironmentConfig: (concurrent = false, timeout = 30000, verbose = false, coverage = true) => ({ concurrent, coverage, maxConcurrency: concurrent ? 4 : 1, retries: 3, timeout, verbose, }), createInfoTest: () => ({ assertions: [ { expected: true, id: `assert-info-${Date.now()}`, message: "Info should return process information", target: "Output", type: "exists", }, ], description: "Test process info functionality", id: `info-test-${Date.now()}`, messages: [ { action: "Info", id: `msg-info-${Date.now()}`, tags: [{ name: "Action", value: "Info" }], }, ], name: "Info Test", timeout: 10000, }), createTokenTest: (processId, action, data) => ({ assertions: [ { expected: true, id: `assert-${action}-${Date.now()}`, message: `${action} should return output`, target: "Output", type: "exists", }, ], description: `Test token ${action} functionality`, id: `token-test-${action}-${Date.now()}`, messages: [ { action, data, id: `msg-${action}-${Date.now()}`, tags: [{ name: "Action", value: action }], }, ], name: `Token ${action} Test`, timeout: 10000, }), createTransferTest: (recipient, quantity) => ({ assertions: [ { expected: "Success", id: `assert-transfer-${Date.now()}`, message: "Transfer should succeed", target: "Output", type: "contains", }, ], description: "Test token transfer functionality", id: `transfer-test-${Date.now()}`, messages: [ { action: "Transfer", id: `msg-transfer-${Date.now()}`, tags: [ { name: "Action", value: "Transfer" }, { name: "Recipient", value: recipient }, { name: "Quantity", value: quantity }, ], }, ], name: "Transfer Test", timeout: 10000, }), }; // Example usage patterns export const AOLiteTestExamples = { createBasicTokenTests: async (processDefinition, aoLiteService) => { const builder = new AOLiteTestSuiteBuilderImpl("Basic Token Tests", processDefinition, aoLiteService); return builder .withConfiguration(AOLiteTestHelpers.createEnvironmentConfig(false, 30000, true, true)) .addTestCase(AOLiteTestHelpers.createInfoTest()) .addTestCase(AOLiteTestHelpers.createBalanceTest()) .addTestCase(AOLiteTestHelpers.createTransferTest("test-recipient", "100")) .withSetup(async (environment) => { // Initialize test data environment.state = { ...environment.state, testData: { initialBalance: 1000, testAccount: "test-account", }, }; }) .withTeardown(async (environment) => { // Clean up test data environment.state = { ...environment.state, testData: null, }; }) .build(); }, createConcurrentTokenTests: async (processDefinition, aoLiteService) => { const builder = new AOLiteTestSuiteBuilderImpl("Concurrent Token Tests", processDefinition, aoLiteService); return builder .withConfiguration(AOLiteTestHelpers.createEnvironmentConfig(true, 60000, false, true)) .addTestCase(AOLiteTestHelpers.createBalanceTest("account-1")) .addTestCase(AOLiteTestHelpers.createBalanceTest("account-2")) .addTestCase(AOLiteTestHelpers.createBalanceTest("account-3")) .addTestCase(AOLiteTestHelpers.createTransferTest("account-1", "50")) .addTestCase(AOLiteTestHelpers.createTransferTest("account-2", "75")) .addTestCase(AOLiteTestHelpers.createTransferTest("account-3", "25")) .build(); }, }; export const createAOLiteVitestIntegration = (aoLiteService, aoMessageService, processService) => service(aoLiteService, aoMessageService, processService);