368 lines
12 KiB
TypeScript
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 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(); |