diff --git a/packages/plugin-coinbase/__tests__/commerce.test.ts b/packages/plugin-coinbase/__tests__/commerce.test.ts new file mode 100644 index 0000000000..3556dc62ea --- /dev/null +++ b/packages/plugin-coinbase/__tests__/commerce.test.ts @@ -0,0 +1,116 @@ +import { describe, it, expect, vi, beforeEach } from 'vitest'; +import { coinbaseCommercePlugin, createCharge } from '../src/plugins/commerce'; +import { IAgentRuntime, Memory, State } from '@elizaos/core'; + +// Mock fetch +global.fetch = vi.fn(); + +// Mock runtime +const mockRuntime = { + getSetting: vi.fn().mockReturnValue('test-api-key'), + getProvider: vi.fn().mockReturnValue({ apiKey: 'test-api-key' }), + character: { + name: 'test-character' + } +}; + +describe('Coinbase Commerce Plugin', () => { + beforeEach(() => { + vi.clearAllMocks(); + }); + + describe('createCharge', () => { + it('should create a charge successfully', async () => { + const mockResponse = { + data: { + id: 'test-charge-id', + name: 'Test Charge', + description: 'Test Description', + pricing_type: 'fixed_price', + local_price: { + amount: '100', + currency: 'USD' + } + } + }; + + (global.fetch as any).mockResolvedValueOnce({ + ok: true, + json: () => Promise.resolve(mockResponse) + }); + + const params = { + name: 'Test Charge', + description: 'Test Description', + pricing_type: 'fixed_price', + local_price: { + amount: '100', + currency: 'USD' + } + }; + + const result = await createCharge('test-api-key', params); + expect(result).toEqual(mockResponse.data); + expect(global.fetch).toHaveBeenCalledWith( + 'https://api.commerce.coinbase.com/charges', + { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + 'X-CC-Api-Key': 'test-api-key' + }, + body: JSON.stringify(params) + } + ); + }); + + it('should handle errors when creating charge', async () => { + (global.fetch as any).mockResolvedValueOnce({ + ok: false, + statusText: 'Bad Request' + }); + + const params = { + name: 'Test Charge', + description: 'Test Description', + pricing_type: 'fixed_price', + local_price: { + amount: '100', + currency: 'USD' + } + }; + + await expect(createCharge('test-api-key', params)) + .rejects + .toThrow('Failed to create charge: Bad Request'); + }); + }); + + describe('coinbaseCommercePlugin', () => { + it('should have correct plugin properties', () => { + expect(coinbaseCommercePlugin.name).toBe('coinbaseCommerce'); + expect(coinbaseCommercePlugin.actions).toBeDefined(); + expect(Array.isArray(coinbaseCommercePlugin.actions)).toBe(true); + }); + + it('should validate plugin actions', async () => { + const mockMessage: Memory = { + id: '1', + user: 'test-user', + content: { text: 'test message' }, + timestamp: new Date(), + type: 'text' + }; + + const createChargeAction = coinbaseCommercePlugin.actions.find( + action => action.name === 'CREATE_CHARGE' + ); + + expect(createChargeAction).toBeDefined(); + if (createChargeAction) { + const result = await createChargeAction.validate(mockRuntime as any, mockMessage); + expect(result).toBe(true); + } + }); + }); +}); diff --git a/packages/plugin-coinbase/__tests__/utils.test.ts b/packages/plugin-coinbase/__tests__/utils.test.ts new file mode 100644 index 0000000000..fb5b36f019 --- /dev/null +++ b/packages/plugin-coinbase/__tests__/utils.test.ts @@ -0,0 +1,64 @@ +import { describe, it, expect, vi, beforeEach } from 'vitest'; +import { getWalletDetails } from '../src/utils'; +import { Coinbase, Wallet } from '@coinbase/coinbase-sdk'; + +vi.mock('@coinbase/coinbase-sdk'); + +// Mock the runtime +const mockRuntime = { + getSetting: vi.fn() + .mockReturnValueOnce('test-seed') // COINBASE_GENERATED_WALLET_HEX_SEED + .mockReturnValueOnce('test-wallet-id'), // COINBASE_GENERATED_WALLET_ID + getProvider: vi.fn().mockReturnValue({ apiKey: 'test-api-key' }), + character: { + name: 'test-character' + } +}; + +// Mock Wallet class +const mockWallet = { + getDefaultAddress: vi.fn().mockResolvedValue('0x123'), + getNetworkId: vi.fn().mockReturnValue('eth-mainnet'), + listBalances: vi.fn().mockResolvedValue([ + ['ETH', { toString: () => '1.0' }] + ]), + getTransactions: vi.fn().mockResolvedValue([]), + export: vi.fn().mockReturnValue({ + seed: 'test-seed', + walletId: 'test-wallet-id' + }) +}; + +describe('Utils', () => { + describe('getWalletDetails', () => { + beforeEach(() => { + vi.clearAllMocks(); + (Coinbase as any).networks = { + EthereumMainnet: 'eth-mainnet' + }; + (Wallet as any).import = vi.fn().mockResolvedValue(mockWallet); + }); + + it('should fetch wallet details successfully', async () => { + const result = await getWalletDetails(mockRuntime as any); + + expect(result).toEqual({ + balances: [{ asset: 'ETH', amount: '1.0' }], + transactions: [] + }); + + expect(Wallet.import).toHaveBeenCalledWith({ + seed: 'test-seed', + walletId: 'test-wallet-id' + }); + }); + + it('should handle errors when fetching wallet details', async () => { + (Wallet as any).import = vi.fn().mockRejectedValue(new Error('Unable to retrieve wallet details.')); + + await expect(getWalletDetails(mockRuntime as any)) + .rejects + .toThrow('Unable to retrieve wallet details.'); + }); + }); +}); diff --git a/packages/plugin-coinbase/package.json b/packages/plugin-coinbase/package.json index 73ff823b52..f7777a6d8a 100644 --- a/packages/plugin-coinbase/package.json +++ b/packages/plugin-coinbase/package.json @@ -28,11 +28,14 @@ }, "devDependencies": { "tsup": "8.3.5", - "@types/node": "^20.0.0" + "@types/node": "^20.0.0", + "vitest": "^1.0.0" }, "scripts": { "build": "tsup --format esm --dts", "dev": "tsup --format esm --dts --watch", - "lint": "eslint --fix --cache ." + "lint": "eslint --fix --cache .", + "test": "vitest run", + "test:watch": "vitest" } }