278 lines
9.8 KiB
TypeScript
278 lines
9.8 KiB
TypeScript
import { expect, tap } from '@git.zone/tstest/tapbundle';
|
|
import * as plugins from '../ts/bunq.plugins.js';
|
|
import * as bunq from '../ts/index.js';
|
|
|
|
let testBunqAccount: bunq.BunqAccount;
|
|
let sandboxApiKey: string;
|
|
let primaryAccount: bunq.BunqMonetaryAccount;
|
|
|
|
tap.test('should setup statement test environment', async () => {
|
|
// Create sandbox user
|
|
const tempAccount = new bunq.BunqAccount({
|
|
apiKey: '',
|
|
deviceName: 'bunq-statement-test',
|
|
environment: 'SANDBOX',
|
|
});
|
|
|
|
sandboxApiKey = await tempAccount.createSandboxUser();
|
|
|
|
// Initialize bunq account
|
|
testBunqAccount = new bunq.BunqAccount({
|
|
apiKey: sandboxApiKey,
|
|
deviceName: 'bunq-statement-test',
|
|
environment: 'SANDBOX',
|
|
});
|
|
|
|
await testBunqAccount.init();
|
|
|
|
// Get primary account
|
|
const { accounts } = await testBunqAccount.getAccounts();
|
|
primaryAccount = accounts[0];
|
|
|
|
console.log('Statement test environment setup complete');
|
|
console.log(`Using account: ${primaryAccount.description}`);
|
|
});
|
|
|
|
tap.test('should create export builder with specific date range', async () => {
|
|
const fromDate = new Date('2024-01-01');
|
|
const toDate = new Date('2024-01-31');
|
|
|
|
const exportBuilder = primaryAccount.getAccountStatement({
|
|
from: fromDate,
|
|
to: toDate,
|
|
includeTransactionAttachments: true
|
|
});
|
|
|
|
expect(exportBuilder).toBeInstanceOf(bunq.ExportBuilder);
|
|
|
|
// The export builder should be properly configured
|
|
const privateOptions = (exportBuilder as any).options;
|
|
expect(privateOptions.dateStart).toEqual('01-01-2024');
|
|
expect(privateOptions.dateEnd).toEqual('31-01-2024');
|
|
expect(privateOptions.includeAttachment).toBeTrue();
|
|
});
|
|
|
|
tap.test('should create export builder with monthly index from 0', async () => {
|
|
// Test with 0-indexed month (0 = current month, 1 = last month, etc.)
|
|
const exportBuilder = primaryAccount.getAccountStatement({
|
|
monthlyIndexedFrom0: 2, // Two months ago
|
|
includeTransactionAttachments: false
|
|
});
|
|
|
|
expect(exportBuilder).toBeInstanceOf(bunq.ExportBuilder);
|
|
|
|
// The export builder should have dates for two months ago
|
|
const privateOptions = (exportBuilder as any).options;
|
|
const now = new Date();
|
|
const twoMonthsAgo = new Date(now.getFullYear(), now.getMonth() - 2, 1);
|
|
const expectedStart = `01-${String(twoMonthsAgo.getMonth() + 1).padStart(2, '0')}-${twoMonthsAgo.getFullYear()}`;
|
|
|
|
expect(privateOptions.dateStart).toEqual(expectedStart);
|
|
expect(privateOptions.includeAttachment).toBeFalse();
|
|
});
|
|
|
|
tap.test('should create export builder with monthly index from 1', async () => {
|
|
// Test with 1-indexed month (1 = last month, 2 = two months ago, etc.)
|
|
const exportBuilder = primaryAccount.getAccountStatement({
|
|
monthlyIndexedFrom1: 1, // Last month
|
|
includeTransactionAttachments: true
|
|
});
|
|
|
|
expect(exportBuilder).toBeInstanceOf(bunq.ExportBuilder);
|
|
|
|
// The export builder should have dates for last month
|
|
const privateOptions = (exportBuilder as any).options;
|
|
const now = new Date();
|
|
const lastMonth = new Date(now.getFullYear(), now.getMonth() - 1, 1);
|
|
const expectedStart = `01-${String(lastMonth.getMonth() + 1).padStart(2, '0')}-${lastMonth.getFullYear()}`;
|
|
|
|
expect(privateOptions.dateStart).toEqual(expectedStart);
|
|
expect(privateOptions.includeAttachment).toBeTrue();
|
|
});
|
|
|
|
tap.test('should default to last month when no date options provided', async () => {
|
|
const exportBuilder = primaryAccount.getAccountStatement({
|
|
includeTransactionAttachments: false
|
|
});
|
|
|
|
expect(exportBuilder).toBeInstanceOf(bunq.ExportBuilder);
|
|
|
|
// Should default to last month
|
|
const privateOptions = (exportBuilder as any).options;
|
|
const now = new Date();
|
|
const lastMonth = new Date(now.getFullYear(), now.getMonth() - 1, 1);
|
|
const expectedStart = `01-${String(lastMonth.getMonth() + 1).padStart(2, '0')}-${lastMonth.getFullYear()}`;
|
|
|
|
expect(privateOptions.dateStart).toEqual(expectedStart);
|
|
});
|
|
|
|
tap.test('should create and download PDF statement', async () => {
|
|
console.log('Creating PDF statement export...');
|
|
|
|
const exportBuilder = primaryAccount.getAccountStatement({
|
|
monthlyIndexedFrom1: 1,
|
|
includeTransactionAttachments: false
|
|
});
|
|
|
|
// Configure as PDF
|
|
exportBuilder.asPdf();
|
|
|
|
// Create the export
|
|
const bunqExport = await exportBuilder.create();
|
|
expect(bunqExport).toBeInstanceOf(bunq.BunqExport);
|
|
expect(bunqExport.id).toBeTypeofNumber();
|
|
console.log('Created PDF export with ID:', bunqExport.id);
|
|
|
|
// Wait for completion with status updates
|
|
console.log('Waiting for PDF export to complete...');
|
|
const maxWaitTime = 180000; // 3 minutes
|
|
const startTime = Date.now();
|
|
|
|
while (true) {
|
|
const status = await bunqExport.get();
|
|
console.log(`Export status: ${status.status}`);
|
|
|
|
if (status.status === 'COMPLETED') {
|
|
break;
|
|
}
|
|
|
|
if (status.status === 'FAILED') {
|
|
throw new Error('Export failed: ' + JSON.stringify(status));
|
|
}
|
|
|
|
if (Date.now() - startTime > maxWaitTime) {
|
|
throw new Error(`Export timed out after ${maxWaitTime/1000} seconds. Last status: ${status.status}`);
|
|
}
|
|
|
|
await new Promise(resolve => setTimeout(resolve, 5000)); // Wait 5 seconds
|
|
}
|
|
|
|
// Download to test directory
|
|
console.log('Downloading PDF statement...');
|
|
const testFilePath = '.nogit/teststatements/test-statement.pdf';
|
|
await bunqExport.saveToFile(testFilePath);
|
|
|
|
// Verify file exists and has content
|
|
const fileExists = await plugins.smartfile.fs.fileExists(testFilePath);
|
|
expect(fileExists).toBeTrue();
|
|
|
|
const fileStats = await plugins.smartfile.fs.stat(testFilePath);
|
|
console.log(`PDF Statement downloaded to: ${testFilePath} (${fileStats.size} bytes)`);
|
|
expect(fileStats.size).toBeGreaterThan(0);
|
|
});
|
|
|
|
tap.test('should create CSV statement with custom date range', async () => {
|
|
console.log('Creating CSV statement export...');
|
|
|
|
// Use last month's date range to ensure it's in the past
|
|
const now = new Date();
|
|
const startOfMonth = new Date(now.getFullYear(), now.getMonth() - 1, 1);
|
|
const endOfMonth = new Date(now.getFullYear(), now.getMonth(), 0);
|
|
|
|
const exportBuilder = primaryAccount.getAccountStatement({
|
|
from: startOfMonth,
|
|
to: endOfMonth,
|
|
includeTransactionAttachments: false
|
|
});
|
|
|
|
// Configure as CSV
|
|
const csvExport = await exportBuilder.asCsv().create();
|
|
console.log('Created CSV export with ID:', csvExport.id);
|
|
|
|
// Wait for completion
|
|
console.log('Waiting for CSV export to complete...');
|
|
await csvExport.waitForCompletion(60000);
|
|
|
|
// Download to test directory
|
|
console.log('Downloading CSV statement...');
|
|
const testFilePath = '.nogit/teststatements/test-statement.csv';
|
|
await csvExport.saveToFile(testFilePath);
|
|
|
|
// Verify file exists and has content
|
|
const fileExists = await plugins.smartfile.fs.fileExists(testFilePath);
|
|
expect(fileExists).toBeTrue();
|
|
|
|
const fileStats = await plugins.smartfile.fs.stat(testFilePath);
|
|
console.log(`CSV statement downloaded to: ${testFilePath} (${fileStats.size} bytes)`);
|
|
expect(fileStats.size).toBeGreaterThan(0);
|
|
});
|
|
|
|
tap.test('should create MT940 statement', async () => {
|
|
console.log('Creating MT940 statement export...');
|
|
|
|
const exportBuilder = primaryAccount.getAccountStatement({
|
|
monthlyIndexedFrom0: 1, // Last month
|
|
includeTransactionAttachments: false
|
|
});
|
|
|
|
// Configure as MT940
|
|
const mt940Export = await exportBuilder.asMt940().create();
|
|
console.log('Created MT940 export with ID:', mt940Export.id);
|
|
|
|
// Wait for completion
|
|
console.log('Waiting for MT940 export to complete...');
|
|
await mt940Export.waitForCompletion(60000);
|
|
|
|
// Download to test directory
|
|
console.log('Downloading MT940 statement...');
|
|
const testFilePath = '.nogit/teststatements/test-statement.txt';
|
|
await mt940Export.saveToFile(testFilePath);
|
|
|
|
// Verify file exists and has content
|
|
const fileExists = await plugins.smartfile.fs.fileExists(testFilePath);
|
|
expect(fileExists).toBeTrue();
|
|
|
|
const fileStats = await plugins.smartfile.fs.stat(testFilePath);
|
|
console.log(`MT940 statement downloaded to: ${testFilePath} (${fileStats.size} bytes)`);
|
|
expect(fileStats.size).toBeGreaterThan(0);
|
|
});
|
|
|
|
tap.test('should handle edge cases for date calculations', async () => {
|
|
// Mock the getAccountStatement method to test with a specific date
|
|
const originalMethod = primaryAccount.getAccountStatement;
|
|
|
|
// Override the method temporarily for this test
|
|
primaryAccount.getAccountStatement = function(optionsArg) {
|
|
const exportBuilder = new bunq.ExportBuilder(this.bunqAccountRef, this);
|
|
|
|
// Simulate January 2024 as "now"
|
|
const mockNow = new Date(2024, 0, 15); // January 15, 2024
|
|
const targetDate = new Date(mockNow.getFullYear(), mockNow.getMonth() - 1, 1);
|
|
const startDate = new Date(targetDate.getFullYear(), targetDate.getMonth(), 1);
|
|
const endDate = new Date(targetDate.getFullYear(), targetDate.getMonth() + 1, 0);
|
|
|
|
const formatDate = (date: Date): string => {
|
|
const year = date.getFullYear();
|
|
const month = String(date.getMonth() + 1).padStart(2, '0');
|
|
const day = String(date.getDate()).padStart(2, '0');
|
|
return `${day}-${month}-${year}`;
|
|
};
|
|
|
|
exportBuilder.dateRange(formatDate(startDate), formatDate(endDate));
|
|
exportBuilder.includeAttachments(optionsArg.includeTransactionAttachments);
|
|
|
|
return exportBuilder;
|
|
};
|
|
|
|
try {
|
|
const exportBuilder = primaryAccount.getAccountStatement({
|
|
monthlyIndexedFrom1: 1, // Last month (December 2023)
|
|
includeTransactionAttachments: false
|
|
});
|
|
|
|
const privateOptions = (exportBuilder as any).options;
|
|
expect(privateOptions.dateStart).toEqual('01-12-2023');
|
|
expect(privateOptions.dateEnd).toEqual('31-12-2023');
|
|
} finally {
|
|
// Restore original method
|
|
primaryAccount.getAccountStatement = originalMethod;
|
|
}
|
|
});
|
|
|
|
tap.test('should cleanup test environment', async () => {
|
|
await testBunqAccount.stop();
|
|
console.log('Test environment cleaned up');
|
|
});
|
|
|
|
export default tap.start();
|