97 lines
3.3 KiB
JavaScript
97 lines
3.3 KiB
JavaScript
const test = require('node:test');
|
|
const assert = require('node:assert/strict');
|
|
const fs = require('node:fs');
|
|
const os = require('node:os');
|
|
const path = require('node:path');
|
|
|
|
const dbPath = path.join(os.tmpdir(), `bill-tracker-bank-sync-test-${process.pid}.sqlite`);
|
|
process.env.DB_PATH = dbPath;
|
|
|
|
const { getDb, closeDb } = require('../db/database');
|
|
const { encryptSecret } = require('../services/encryptionService');
|
|
const { syncDataSource } = require('../services/bankSyncService');
|
|
|
|
function createUser(db, suffix) {
|
|
return db.prepare(`
|
|
INSERT INTO users (username, password_hash, role, active, email, created_at, updated_at)
|
|
VALUES (?, 'x', 'user', 1, ?, datetime('now'), datetime('now'))
|
|
`).run(`bank-sync-${suffix}`, `bank-sync-${suffix}@local`).lastInsertRowid;
|
|
}
|
|
|
|
function createSource(db, userId) {
|
|
return db.prepare(`
|
|
INSERT INTO data_sources (user_id, type, provider, name, status, encrypted_secret)
|
|
VALUES (?, 'provider_sync', 'simplefin', 'SimpleFIN', 'active', ?)
|
|
`).run(userId, encryptSecret('https://user:pass@example.com/simplefin')).lastInsertRowid;
|
|
}
|
|
|
|
function createAccount(db, userId, dataSourceId, providerAccountId, monitored) {
|
|
return db.prepare(`
|
|
INSERT INTO financial_accounts
|
|
(user_id, data_source_id, provider_account_id, name, currency, monitored)
|
|
VALUES (?, ?, ?, ?, 'USD', ?)
|
|
`).run(userId, dataSourceId, providerAccountId, providerAccountId, monitored ? 1 : 0).lastInsertRowid;
|
|
}
|
|
|
|
test.after(() => {
|
|
closeDb();
|
|
for (const suffix of ['', '-wal', '-shm']) {
|
|
fs.rmSync(`${dbPath}${suffix}`, { force: true });
|
|
}
|
|
});
|
|
|
|
test('SimpleFIN sync skips storing transactions for unmonitored accounts', async () => {
|
|
const db = getDb();
|
|
const userId = createUser(db, 'skip-unmonitored');
|
|
const dataSourceId = createSource(db, userId);
|
|
const mutedAccountId = createAccount(db, userId, dataSourceId, 'muted-account', false);
|
|
|
|
const originalFetch = global.fetch;
|
|
global.fetch = async () => ({
|
|
ok: true,
|
|
status: 200,
|
|
json: async () => ({
|
|
accounts: [
|
|
{
|
|
id: 'muted-account',
|
|
name: 'Muted Account',
|
|
currency: 'USD',
|
|
balance: '100.00',
|
|
transactions: [
|
|
{ id: 'muted-tx-1', amount: '-12.34', posted: 1772323200, description: 'Muted charge' },
|
|
],
|
|
},
|
|
{
|
|
id: 'tracked-account',
|
|
name: 'Tracked Account',
|
|
currency: 'USD',
|
|
balance: '200.00',
|
|
transactions: [
|
|
{ id: 'tracked-tx-1', amount: '-56.78', posted: 1772323200, description: 'Tracked charge' },
|
|
],
|
|
},
|
|
],
|
|
}),
|
|
});
|
|
|
|
try {
|
|
const result = await syncDataSource(db, userId, dataSourceId);
|
|
assert.equal(result.transactionsNew, 1);
|
|
} finally {
|
|
global.fetch = originalFetch;
|
|
}
|
|
|
|
const mutedTransactions = db.prepare('SELECT COUNT(*) AS count FROM transactions WHERE account_id = ?').get(mutedAccountId).count;
|
|
assert.equal(mutedTransactions, 0);
|
|
|
|
const trackedAccount = db.prepare(`
|
|
SELECT id, monitored
|
|
FROM financial_accounts
|
|
WHERE user_id = ? AND data_source_id = ? AND provider_account_id = 'tracked-account'
|
|
`).get(userId, dataSourceId);
|
|
assert.equal(trackedAccount.monitored, 1);
|
|
|
|
const trackedTransactions = db.prepare('SELECT COUNT(*) AS count FROM transactions WHERE account_id = ?').get(trackedAccount.id).count;
|
|
assert.equal(trackedTransactions, 1);
|
|
});
|