Files
bunq/test/test.payments.ts

368 lines
12 KiB
TypeScript

import { expect, tap } from '@git.zone/tstest/tapbundle';
import * as bunq from '../ts/index.js';
let testBunqAccount: bunq.BunqAccount;
let sandboxApiKey: string;
let primaryAccount: bunq.BunqMonetaryAccount;
let secondaryAccount: bunq.BunqMonetaryAccount;
tap.test('should create test setup with multiple accounts', async () => {
// Create sandbox user
const tempAccount = new bunq.BunqAccount({
apiKey: '',
deviceName: 'bunq-payment-test',
environment: 'SANDBOX',
});
sandboxApiKey = await tempAccount.createSandboxUser();
console.log('Generated sandbox API key for payment tests');
// Initialize bunq account
testBunqAccount = new bunq.BunqAccount({
apiKey: sandboxApiKey,
deviceName: 'bunq-payment-test',
environment: 'SANDBOX',
});
await testBunqAccount.init();
// Get accounts
const { accounts } = await testBunqAccount.getAccounts();
primaryAccount = accounts[0];
// Create a second account for testing transfers
try {
const newAccount = await bunq.BunqMonetaryAccount.create(testBunqAccount, {
currency: 'EUR',
description: 'Test Secondary Account',
dailyLimit: '100.00',
overdraftLimit: '0.00'
});
// Refresh accounts list
const { accounts: updatedAccounts } = await testBunqAccount.getAccounts();
secondaryAccount = updatedAccounts.find(acc => acc.id === newAccount.id) || primaryAccount;
} catch (error) {
console.log('Could not create secondary account, using primary for tests');
secondaryAccount = primaryAccount;
}
expect(primaryAccount).toBeInstanceOf(bunq.BunqMonetaryAccount);
console.log(`Primary account: ${primaryAccount.description} (${primaryAccount.balance.value} ${primaryAccount.balance.currency})`);
});
tap.test('should create and execute a payment draft', async () => {
const draft = new bunq.BunqDraftPayment(testBunqAccount, primaryAccount);
// Create a draft payment
const draftId = await draft.create({
numberOfRequiredAccepts: 1,
entries: [{
amount: {
currency: 'EUR',
value: '5.00'
},
counterparty_alias: {
type: 'IBAN',
value: 'NL91ABNA0417164300',
name: 'Draft Test Recipient'
},
description: 'Test draft payment entry'
}]
});
expect(draftId).toBeTypeofNumber();
console.log(`Created draft payment with ID: ${draftId}`);
// List drafts
const drafts = await bunq.BunqDraftPayment.list(testBunqAccount, primaryAccount.id);
expect(drafts).toBeArray();
expect(drafts.length).toBeGreaterThan(0);
const createdDraft = drafts.find((d: any) => d.DraftPayment?.id === draftId);
expect(createdDraft).toBeDefined();
// Verify we can get the draft details
const draftDetails = await draft.get();
expect(draftDetails).toBeDefined();
expect(draftDetails.id).toEqual(draftId);
expect(draftDetails.entries).toBeArray();
expect(draftDetails.entries.length).toEqual(1);
console.log(`Draft payment verified - status: ${draftDetails.status || 'unknown'}`);
// Note: Draft payment update/cancel operations are limited in sandbox
// The API only accepts certain status transitions and field updates
});
tap.test('should test payment builder with various options', async () => {
// Test different payment builder configurations
// 1. Simple IBAN payment
const simplePayment = bunq.BunqPayment.builder(testBunqAccount, primaryAccount)
.amount('1.00', 'EUR')
.toIban('NL91ABNA0417164300', 'Simple Test')
.description('Simple payment test');
expect(simplePayment).toBeDefined();
// 2. Payment with custom request ID
const customIdPayment = bunq.BunqPayment.builder(testBunqAccount, primaryAccount)
.amount('2.50', 'EUR')
.toIban('NL91ABNA0417164300', 'Custom ID Test')
.description('Payment with custom request ID')
.customRequestId('test-request-123');
expect(customIdPayment).toBeDefined();
// 3. Payment to email
const emailPayment = bunq.BunqPayment.builder(testBunqAccount, primaryAccount)
.amount('3.00', 'EUR')
.toEmail('test@example.com', 'Email Test')
.description('Payment to email');
expect(emailPayment).toBeDefined();
// 4. Payment to phone number
const phonePayment = bunq.BunqPayment.builder(testBunqAccount, primaryAccount)
.amount('4.00', 'EUR')
.toPhoneNumber('+31612345678', 'Phone Test')
.description('Payment to phone');
expect(phonePayment).toBeDefined();
console.log('All payment builder variations created successfully');
});
tap.test('should test batch payments', async () => {
const paymentBatch = new bunq.BunqPaymentBatch(testBunqAccount);
// Create a batch payment
const batchPayments = [
{
amount: {
currency: 'EUR',
value: '1.00'
},
counterparty_alias: {
type: 'IBAN',
value: 'NL91ABNA0417164300',
name: 'Batch Recipient 1'
},
description: 'Batch payment 1'
},
{
amount: {
currency: 'EUR',
value: '2.00'
},
counterparty_alias: {
type: 'IBAN',
value: 'NL91ABNA0417164300',
name: 'Batch Recipient 2'
},
description: 'Batch payment 2'
}
];
try {
const batchId = await paymentBatch.create(primaryAccount, batchPayments);
expect(batchId).toBeTypeofNumber();
console.log(`Created batch payment with ID: ${batchId}`);
// Get batch details
const batchDetails = await paymentBatch.get(primaryAccount, batchId);
expect(batchDetails).toBeDefined();
expect(batchDetails.payments).toBeArray();
expect(batchDetails.payments.length).toEqual(2);
console.log(`Batch contains ${batchDetails.payments.length} payments`);
} catch (error) {
console.log('Batch payment creation failed (may not be supported in sandbox):', error.message);
}
});
tap.test('should test scheduled payments', async () => {
const schedulePayment = new bunq.BunqSchedulePayment(testBunqAccount);
// Create a scheduled payment for tomorrow
const tomorrow = new Date();
tomorrow.setDate(tomorrow.getDate() + 1);
try {
const scheduleId = await schedulePayment.create(primaryAccount, {
payment: {
amount: {
currency: 'EUR',
value: '10.00'
},
counterparty_alias: {
type: 'IBAN',
value: 'NL91ABNA0417164300',
name: 'Scheduled Recipient'
},
description: 'Scheduled payment test'
},
schedule: {
time_start: tomorrow.toISOString(),
time_end: tomorrow.toISOString(),
recurrence_unit: 'ONCE',
recurrence_size: 1
}
});
expect(scheduleId).toBeTypeofNumber();
console.log(`Created scheduled payment with ID: ${scheduleId}`);
// List scheduled payments
const schedules = await schedulePayment.list(primaryAccount);
expect(schedules).toBeArray();
// Cancel the scheduled payment
await schedulePayment.delete(primaryAccount, scheduleId);
console.log('Scheduled payment cancelled successfully');
} catch (error) {
console.log('Scheduled payment creation failed (may not be supported in sandbox):', error.message);
}
});
tap.test('should test payment requests', async () => {
const paymentRequest = new bunq.BunqRequestInquiry(testBunqAccount, primaryAccount);
// Create a payment request
try {
const requestId = await paymentRequest.create({
amountInquired: {
currency: 'EUR',
value: '15.00'
},
counterpartyAlias: {
type: 'EMAIL',
value: 'requester@example.com',
name: 'Request Sender'
},
description: 'Payment request test',
allowBunqme: true
});
expect(requestId).toBeTypeofNumber();
console.log(`Created payment request with ID: ${requestId}`);
// List requests
const requests = await bunq.BunqRequestInquiry.list(testBunqAccount, primaryAccount.id);
expect(requests).toBeArray();
// Cancel the request
await paymentRequest.update(requestId, {
status: 'CANCELLED'
});
console.log('Payment request cancelled successfully');
} catch (error) {
console.log('Payment request creation failed:', error.message);
}
});
tap.test('should test payment response (accepting a request)', async () => {
const paymentResponse = new bunq.BunqRequestResponse(testBunqAccount, primaryAccount);
// First create a request to respond to
const paymentRequest = new bunq.BunqRequestInquiry(testBunqAccount, primaryAccount);
try {
// Create a self-request (from same account) for testing
const requestId = await paymentRequest.create({
amountInquired: {
currency: 'EUR',
value: '5.00'
},
counterpartyAlias: {
type: 'IBAN',
value: primaryAccount.iban,
name: primaryAccount.displayName
},
description: 'Self request for testing response'
});
console.log(`Created self-request with ID: ${requestId}`);
// Accept the request
const responseId = await paymentResponse.accept(requestId);
expect(responseId).toBeTypeofNumber();
console.log(`Accepted request with response ID: ${responseId}`);
} catch (error) {
console.log('Payment response test failed:', error.message);
}
});
tap.test('should test transaction filtering and pagination', async () => {
try {
// Get transactions with filters
const recentTransactions = await primaryAccount.getTransactions({
count: 5,
older_id: undefined,
newer_id: undefined
});
expect(recentTransactions).toBeArray();
expect(recentTransactions.length).toBeLessThanOrEqual(5);
console.log(`Retrieved ${recentTransactions.length} recent transactions`);
// Test transaction details
if (recentTransactions.length > 0) {
const firstTx = recentTransactions[0];
expect(firstTx.id).toBeTypeofNumber();
expect(firstTx.created).toBeTypeofString();
expect(firstTx.amount).toHaveProperty('value');
expect(firstTx.amount).toHaveProperty('currency');
expect(firstTx.description).toBeTypeofString();
expect(firstTx.type).toBeTypeofString();
// Check transaction type
expect(firstTx.type).toBeOneOf([
'IDEAL',
'BUNQ',
'MASTERCARD',
'MAESTRO',
'SAVINGS',
'INTEREST',
'REQUEST',
'SOFORT',
'EBA_SCT'
]);
console.log(`First transaction: ${firstTx.type} - ${firstTx.amount.value} ${firstTx.amount.currency}`);
}
} catch (error) {
if (error.message && error.message.includes('Insufficient authentication')) {
console.log('Transaction filtering test skipped - insufficient permissions in sandbox');
// At least verify that the error is handled properly
expect(error).toBeInstanceOf(Error);
} else {
throw error;
}
}
});
tap.test('should test payment with attachments', async () => {
// Create a payment with attachment placeholder
const paymentWithAttachment = bunq.BunqPayment.builder(testBunqAccount, primaryAccount)
.amount('2.00', 'EUR')
.toIban('NL91ABNA0417164300', 'Attachment Test')
.description('Payment with attachment test');
// Note: Actual attachment upload would require:
// 1. Upload attachment using BunqAttachment.upload()
// 2. Get attachment ID
// 3. Include attachment_id in payment
expect(paymentWithAttachment).toBeDefined();
console.log('Payment with attachment builder created (attachment upload not tested in sandbox)');
});
tap.test('should cleanup test resources', async () => {
await testBunqAccount.stop();
console.log('Payment test cleanup completed');
});
export default tap.start();