/** * Payment integration tests */ import { describe, it, expect } from 'vitest'; import { createTestClient, assertSuccessResponse } from '../setup'; import { testNon3DPaymentRequest, test3DSInitializeRequest } from '../fixtures/payment'; import { IyzicoResponseError } from '../../src/errors'; describe('Payment Integration Tests', () => { const client = createTestClient(); it('should create a non-3DS payment', async () => { const request = { ...testNon3DPaymentRequest, conversationId: `test-non3ds-${Date.now()}`, }; const response = await client.payment.createNon3DS(request); assertSuccessResponse(response); expect(response.paymentId).toBeTruthy(); expect(response.price).toBe(request.price); }); it('should get payment detail by paymentId', async () => { // First create a payment const paymentRequest = { ...testNon3DPaymentRequest, conversationId: `test-detail-${Date.now()}`, }; const paymentResponse = await client.payment.createNon3DS(paymentRequest); assertSuccessResponse(paymentResponse); if (!paymentResponse.paymentId) { throw new Error('Payment ID is required for detail test'); } // Then get payment detail const detailResponse = await client.payment.getDetail({ paymentId: paymentResponse.paymentId, locale: 'tr', }); assertSuccessResponse(detailResponse); expect(detailResponse.paymentId).toBe(paymentResponse.paymentId); }); it('should initialize 3DS payment', async () => { const request = { ...test3DSInitializeRequest, conversationId: `test-3ds-init-${Date.now()}`, }; const response = await client.payment.initialize3DS(request); assertSuccessResponse(response); expect(response.paymentId).toBeTruthy(); expect(response.htmlContent || response.threeDSHtmlContent).toBeTruthy(); }); it('should complete 3DS v1 payment', async () => { // First initialize a 3DS payment const initRequest = { ...test3DSInitializeRequest, conversationId: `test-3ds-v1-${Date.now()}`, }; const initResponse = await client.payment.initialize3DS(initRequest); assertSuccessResponse(initResponse); if (!initResponse.paymentId) { throw new Error('Payment ID is required for 3DS completion test'); } // In sandbox, 3DS completion will fail without actual 3DS flow // We expect an IyzicoResponseError to be thrown await expect( client.payment.complete3DS({ paymentId: initResponse.paymentId, locale: 'tr', conversationId: `test-3ds-v1-complete-${Date.now()}`, }) ).rejects.toThrow(IyzicoResponseError); }); it('should complete 3DS v2 payment', async () => { // First initialize a 3DS payment const initRequest = { ...test3DSInitializeRequest, conversationId: `test-3ds-v2-${Date.now()}`, }; const initResponse = await client.payment.initialize3DS(initRequest); assertSuccessResponse(initResponse); if (!initResponse.paymentId) { throw new Error('Payment ID is required for 3DS completion test'); } // In sandbox, 3DS completion will fail without actual 3DS flow // We expect an IyzicoResponseError to be thrown await expect( client.payment.complete3DSV2({ paymentId: initResponse.paymentId, locale: 'tr', conversationId: `test-3ds-v2-complete-${Date.now()}`, paidPrice: initRequest.paidPrice, basketId: initRequest.basketId!, currency: initRequest.currency || 'TRY', }) ).rejects.toThrow(IyzicoResponseError); }); describe('Edge Cases - Invalid Fields', () => { it('should handle missing required fields (price)', async () => { const request = { ...testNon3DPaymentRequest, conversationId: `test-missing-price-${Date.now()}`, price: undefined as any, }; await expect(client.payment.createNon3DS(request)).rejects.toThrow(IyzicoResponseError); }); it('should handle missing required fields (paidPrice)', async () => { const request = { ...testNon3DPaymentRequest, conversationId: `test-missing-paidprice-${Date.now()}`, paidPrice: undefined as any, }; await expect(client.payment.createNon3DS(request)).rejects.toThrow(IyzicoResponseError); }); it('should handle missing required fields (paymentCard)', async () => { const request = { ...testNon3DPaymentRequest, conversationId: `test-missing-card-${Date.now()}`, paymentCard: undefined as any, }; await expect(client.payment.createNon3DS(request)).rejects.toThrow(IyzicoResponseError); }); it('should handle missing required fields (buyer)', async () => { const request = { ...testNon3DPaymentRequest, conversationId: `test-missing-buyer-${Date.now()}`, buyer: undefined as any, }; await expect(client.payment.createNon3DS(request)).rejects.toThrow(IyzicoResponseError); }); it('should handle missing required fields (billingAddress)', async () => { const request = { ...testNon3DPaymentRequest, conversationId: `test-missing-billing-${Date.now()}`, billingAddress: undefined as any, }; await expect(client.payment.createNon3DS(request)).rejects.toThrow(IyzicoResponseError); }); it('should handle missing required fields (basketItems)', async () => { const request = { ...testNon3DPaymentRequest, conversationId: `test-missing-basket-${Date.now()}`, basketItems: undefined as any, }; await expect(client.payment.createNon3DS(request)).rejects.toThrow(IyzicoResponseError); }); it('should handle empty basketItems array', async () => { const request = { ...testNon3DPaymentRequest, conversationId: `test-empty-basket-${Date.now()}`, basketItems: [], }; await expect(client.payment.createNon3DS(request)).rejects.toThrow(IyzicoResponseError); }); it('should handle invalid card number (too short)', async () => { const request = { ...testNon3DPaymentRequest, conversationId: `test-invalid-card-short-${Date.now()}`, paymentCard: { ...testNon3DPaymentRequest.paymentCard, cardNumber: '1234', }, }; await expect(client.payment.createNon3DS(request)).rejects.toThrow(IyzicoResponseError); }); it('should handle invalid card number (non-numeric)', async () => { const request = { ...testNon3DPaymentRequest, conversationId: `test-invalid-card-nonnumeric-${Date.now()}`, paymentCard: { ...testNon3DPaymentRequest.paymentCard, cardNumber: 'ABCDEFGHIJKLMNOP', }, }; await expect(client.payment.createNon3DS(request)).rejects.toThrow(IyzicoResponseError); }); it('should handle invalid expiry month (invalid format)', async () => { const request = { ...testNon3DPaymentRequest, conversationId: `test-invalid-expmonth-${Date.now()}`, paymentCard: { ...testNon3DPaymentRequest.paymentCard, expireMonth: '13', }, }; await expect(client.payment.createNon3DS(request)).rejects.toThrow(IyzicoResponseError); }); it('should handle invalid expiry year (invalid format)', async () => { // Note: Sandbox doesn't validate past years, so we test invalid format instead const request = { ...testNon3DPaymentRequest, conversationId: `test-invalid-expyear-format-${Date.now()}`, paymentCard: { ...testNon3DPaymentRequest.paymentCard, expireYear: 'AB', // Invalid format - non-numeric }, }; await expect(client.payment.createNon3DS(request)).rejects.toThrow(IyzicoResponseError); }); it('should handle invalid CVV (too short)', async () => { const request = { ...testNon3DPaymentRequest, conversationId: `test-invalid-cvv-short-${Date.now()}`, paymentCard: { ...testNon3DPaymentRequest.paymentCard, cvc: '12', }, }; await expect(client.payment.createNon3DS(request)).rejects.toThrow(IyzicoResponseError); }); it('should handle invalid CVV (non-numeric)', async () => { const request = { ...testNon3DPaymentRequest, conversationId: `test-invalid-cvv-nonnumeric-${Date.now()}`, paymentCard: { ...testNon3DPaymentRequest.paymentCard, cvc: 'ABC', }, }; await expect(client.payment.createNon3DS(request)).rejects.toThrow(IyzicoResponseError); }); it('should handle negative price', async () => { const request = { ...testNon3DPaymentRequest, conversationId: `test-negative-price-${Date.now()}`, price: -100.0, paidPrice: -100.0, }; await expect(client.payment.createNon3DS(request)).rejects.toThrow(IyzicoResponseError); }); it('should handle zero price', async () => { const request = { ...testNon3DPaymentRequest, conversationId: `test-zero-price-${Date.now()}`, price: 0, paidPrice: 0, }; await expect(client.payment.createNon3DS(request)).rejects.toThrow(IyzicoResponseError); }); it('should handle invalid currency', async () => { const request = { ...testNon3DPaymentRequest, conversationId: `test-invalid-currency-${Date.now()}`, currency: 'INVALID' as any, }; await expect(client.payment.createNon3DS(request)).rejects.toThrow(IyzicoResponseError); }); it('should handle invalid installment value', async () => { const request = { ...testNon3DPaymentRequest, conversationId: `test-invalid-installment-${Date.now()}`, installment: 99 as any, }; await expect(client.payment.createNon3DS(request)).rejects.toThrow(IyzicoResponseError); }); it('should handle invalid email format', async () => { const request = { ...testNon3DPaymentRequest, conversationId: `test-invalid-email-${Date.now()}`, buyer: { ...testNon3DPaymentRequest.buyer, email: 'invalid-email-format', }, }; await expect(client.payment.createNon3DS(request)).rejects.toThrow(IyzicoResponseError); }); it('should handle basket item with negative price', async () => { const request = { ...testNon3DPaymentRequest, conversationId: `test-negative-basket-price-${Date.now()}`, basketItems: [ { ...testNon3DPaymentRequest.basketItems[0], price: -10.0, }, ], }; await expect(client.payment.createNon3DS(request)).rejects.toThrow(IyzicoResponseError); }); it('should handle missing callbackUrl for 3DS initialize', async () => { const request = { ...test3DSInitializeRequest, conversationId: `test-missing-callback-${Date.now()}`, callbackUrl: undefined as any, }; await expect(client.payment.initialize3DS(request)).rejects.toThrow(IyzicoResponseError); }); it('should handle invalid paymentId for getDetail', async () => { await expect( client.payment.getDetail({ paymentId: 'invalid-payment-id-12345', locale: 'tr', }) ).rejects.toThrow(IyzicoResponseError); }); it('should handle empty paymentId for getDetail', async () => { await expect( client.payment.getDetail({ paymentId: '', locale: 'tr', }) ).rejects.toThrow(IyzicoResponseError); }); it('should handle missing paymentId and paymentConversationId for getDetail', async () => { await expect( client.payment.getDetail({ locale: 'tr', }) ).rejects.toThrow(IyzicoResponseError); }); }); });