recipe.test.ts•3.97 kB
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');
    });
  });
});