Files
OnBudget/test/core/database/migration_v8_test.dart
T
SandersandClaude Opus 4.8 76f301b758 Add native notification ingest and source-app allowlist
- Android NotificationListenerService plugin + queue store, MethodChannel
  bridge, and Flutter ingest worker / access controller
- source_apps allowlist (DAO, repo, settings + source_apps screen)
- schema v8 migration + decision_gate / dedup / draft_codec updates
- l10n strings and tests

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-28 00:08:18 +03:00

74 lines
2.7 KiB
Dart

import 'dart:io';
import 'package:drift/drift.dart' hide isNull, isNotNull;
import 'package:drift/native.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:new_budget/src/core/database/app_database.dart';
import 'package:new_budget/src/core/database/converters/enum_converters.dart';
import 'package:new_budget/src/features/notification_parsing/domain/enums.dart';
/// Тест миграции v7 → v8 (parse_rules.tx_type для gate-проверки
/// typeMatchesRule).
///
/// Поднимаем актуальную (v8) схему, «откатываем» до v7 (убираем tx_type,
/// ставим user_version = 7). Повторное открытие запускает onUpgrade(7 → 8),
/// который должен восстановить колонку.
void main() {
late File file;
setUp(() {
final dir = Directory.systemTemp.createTempSync('nb_migration_v8_test');
file = File('${dir.path}/test.sqlite');
});
tearDown(() {
if (file.existsSync()) file.deleteSync();
final parent = file.parent;
if (parent.existsSync()) parent.deleteSync(recursive: true);
});
test('onUpgrade 7 → 8 добавляет parse_rules.tx_type', () async {
const userId = 'user-1';
// 1. Актуальная схема (v8) + FK-цепочка.
final dbV8 = AppDatabase.forTesting(NativeDatabase(file));
await dbV8.usersDao
.insertUser(UsersTableCompanion.insert(id: userId, name: 'Тест'));
// 2. «Откатываем» до v7.
await dbV8.customStatement('ALTER TABLE parse_rules DROP COLUMN tx_type');
await dbV8.customStatement('PRAGMA user_version = 7');
await dbV8.close();
// 3. Повторное открытие → onUpgrade(7 → 8).
final dbMigrated = AppDatabase.forTesting(NativeDatabase(file));
addTearDown(dbMigrated.close);
// 4. Колонка снова доступна: правило с txType проходит round-trip,
// легаси-правило без txType читается с null.
await dbMigrated.parseRulesDao.insert(
ParseRulesTableCompanion.insert(
id: 'r-typed',
userId: userId,
kind: ParseRuleKind.merchantToCategory,
pattern: 'LENTA',
txType: const Value(TransactionType.expense),
),
);
await dbMigrated.parseRulesDao.insert(
ParseRulesTableCompanion.insert(
id: 'r-legacy',
userId: userId,
kind: ParseRuleKind.merchantToCategory,
pattern: 'OZON',
),
);
final typed = await dbMigrated.parseRulesDao.findById('r-typed');
expect(typed!.txType, TransactionType.expense);
final legacy = await dbMigrated.parseRulesDao.findById('r-legacy');
expect(legacy!.txType, isNull);
});
}