Metaplex MCP Server
by aldrin-labs
import { describe, expect, it, jest, beforeEach } from '@jest/globals';
import { Connection as SolanaConnection } from '@solana/web3.js';
import { Program as AnchorProgram, Idl } from '@project-serum/anchor';
import { PublicKey, Program, Connection } from '../../types/mocks';
import { RecipeService } from '../recipe';
import type { MockedFunction } from '../../types/mocks';
describe('RecipeService', () => {
let recipeService: RecipeService;
let mockConnection: Connection;
let mockProgram: Program;
let mockFetch: MockedFunction<(address: PublicKey) => Promise<any>>;
beforeEach(() => {
mockConnection = new Connection('mock-endpoint');
mockProgram = new Program('MPL4o4wMzndgh8T1NVDxELQCj5UQfYTYEkabX3wNKtb');
mockFetch = mockProgram.account.recipeV1.fetch as MockedFunction<(address: PublicKey) => Promise<any>>;
recipeService = new RecipeService(
mockConnection as unknown as SolanaConnection,
mockProgram as unknown as AnchorProgram<Idl>
);
});
describe('analyzeRecipe', () => {
it('should analyze a valid recipe configuration', async () => {
const mockRecipeData = {
name: 'Test Recipe',
uri: 'https://test.uri',
max: { toNumber: () => 100 },
min: { toNumber: () => 1 },
amount: { toNumber: () => 10 },
feeAmountCapture: { toNumber: () => 1 },
feeAmountRelease: { toNumber: () => 1 },
solFeeAmountCapture: { toNumber: () => 0.1 },
solFeeAmountRelease: { toNumber: () => 0.1 },
path: 1,
count: { toNumber: () => 5 },
};
mockFetch.mockResolvedValue(mockRecipeData);
const result = await recipeService.analyzeRecipe('11111111111111111111111111111111');
expect(result.isValid).toBe(true);
expect(result.issues).toHaveLength(0);
expect(result.name).toBe('Test Recipe');
expect(result.max).toBe(100);
expect(result.min).toBe(1);
});
it('should detect invalid max/min configuration', async () => {
const mockRecipeData = {
name: 'Test Recipe',
uri: 'https://test.uri',
max: { toNumber: () => 1 }, // max <= min
min: { toNumber: () => 1 },
amount: { toNumber: () => 10 },
feeAmountCapture: { toNumber: () => 1 },
feeAmountRelease: { toNumber: () => 1 },
solFeeAmountCapture: { toNumber: () => 0.1 },
solFeeAmountRelease: { toNumber: () => 0.1 },
path: 1,
count: { toNumber: () => 5 },
};
mockFetch.mockResolvedValue(mockRecipeData);
const result = await recipeService.analyzeRecipe('11111111111111111111111111111111');
expect(result.isValid).toBe(false);
expect(result.issues).toContain('Max value must be greater than min value');
});
it('should detect invalid amount configuration', async () => {
const mockRecipeData = {
name: 'Test Recipe',
uri: 'https://test.uri',
max: { toNumber: () => 100 },
min: { toNumber: () => 1 },
amount: { toNumber: () => 0 }, // invalid amount
feeAmountCapture: { toNumber: () => 1 },
feeAmountRelease: { toNumber: () => 1 },
solFeeAmountCapture: { toNumber: () => 0.1 },
solFeeAmountRelease: { toNumber: () => 0.1 },
path: 1,
count: { toNumber: () => 5 },
};
mockFetch.mockResolvedValue(mockRecipeData);
const result = await recipeService.analyzeRecipe('11111111111111111111111111111111');
expect(result.isValid).toBe(false);
expect(result.issues).toContain('Amount must be greater than 0');
});
it('should handle recipe fetch errors', async () => {
mockFetch.mockRejectedValue(new Error('Recipe not found'));
const result = await recipeService.analyzeRecipe('11111111111111111111111111111111');
expect(result.isValid).toBe(false);
expect(result.issues).toContain('Failed to analyze recipe: Recipe not found');
});
});
});