test: cover account metadata reimport

This commit is contained in:
2026-08-20 08:46:49 +03:00
parent c6b79c1d35
commit 1b20b76704
4 changed files with 41 additions and 2 deletions

View File

@@ -1,5 +1,11 @@
# Changelog
## [Backend 0.7.3] - 2026-08-20
### Added
- Added a runnable database integration test for preserving account metadata during re-import.
## [Frontend 0.10.2 / Backend 0.7.2] - 2026-08-20
### Fixed

View File

@@ -1,6 +1,6 @@
{
"name": "@family-budget/backend",
"version": "0.7.2",
"version": "0.7.3",
"private": true,
"scripts": {
"dev": "tsx watch src/app.ts",
@@ -10,6 +10,7 @@
"migrate:prod": "node dist/db/migrate.js",
"test:analytics": "tsx src/services/analyticsSemantics.test.ts",
"test:analytics:db": "NODE_ENV=test tsx src/services/analytics.integration.test.ts",
"test:import:db": "NODE_ENV=test tsx src/services/import.integration.test.ts",
"test:llm": "tsx src/scripts/testLlm.ts"
},
"dependencies": {

View File

@@ -0,0 +1,31 @@
import assert from 'node:assert/strict';
import { pool } from '../db/pool';
import { importStatement } from './import';
const makeStatement = (sourceId: string) => ({
schemaVersion: '1.0', bank: 'TEST',
statement: { accountNumber: 'metadata-test', currency: 'RUB', openingBalance: 0, closingBalance: 100, exportedAt: '2026-08-20T12:00:00+03:00' },
transactions: [{ operationAt: '2026-08-20T10:00:00+03:00', amountSigned: 100, commission: 0, description: 'Пополнение', sourceId }],
});
async function run(): Promise<void> {
const client = await pool.connect();
try {
const db = { connect: async () => client };
await importStatement(makeStatement('first'), db);
const account = await client.query("UPDATE accounts SET account_type = 'savings', status = 'closed' WHERE bank = 'TEST' AND account_number = 'metadata-test' RETURNING id");
assert.equal(account.rows.length, 1);
await importStatement(makeStatement('second'), db);
const result = await client.query('SELECT account_type, status FROM accounts WHERE id = $1', [account.rows[0].id]);
assert.deepEqual(result.rows[0], { account_type: 'savings', status: 'closed' });
console.log('import metadata SQL: OK');
} finally {
await client.query('DELETE FROM transactions WHERE account_id IN (SELECT id FROM accounts WHERE bank = \'TEST\' AND account_number = \'metadata-test\')');
await client.query("DELETE FROM imports WHERE account_id IN (SELECT id FROM accounts WHERE bank = 'TEST' AND account_number = 'metadata-test')");
await client.query("DELETE FROM accounts WHERE bank = 'TEST' AND account_number = 'metadata-test'");
client.release();
await pool.end();
}
}
run();

View File

@@ -154,6 +154,7 @@ function validateSemantics(data: StatementFile): ValidationError | null {
export async function importStatement(
body: unknown,
db: Pick<typeof pool, 'connect'> = pool,
): Promise<ImportStatementResponse | ValidationError> {
const structErr = validateStructure(body);
if (structErr) return structErr;
@@ -162,7 +163,7 @@ export async function importStatement(
const semErr = validateSemantics(data);
if (semErr) return semErr;
const client = await pool.connect();
const client = await db.connect();
try {
await client.query('BEGIN');