Files
OnBudget/test/core/database/migration_v6_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

90 lines
3.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';
/// Тест миграции v5 → v6 (habit-tracking).
///
/// Поднимаем актуальную (v6) схему на файле, затем «откатываем» её до v5,
/// удаляя новые колонки и проставляя user_version = 5. При повторном открытии
/// срабатывает `onUpgrade(5 → 6)`, который должен снова добавить колонки.
void main() {
late File file;
setUp(() {
final dir = Directory.systemTemp.createTempSync('nb_migration_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 5 → 6 добавляет obligation/impulse/habitTrackingEnabled',
() async {
const userId = 'user-1';
const accountId = 'account-1';
// 1. Создаём актуальную схему (v6) и наполняем FK-цепочку.
final dbV6 = AppDatabase.forTesting(NativeDatabase(file));
await dbV6.usersDao
.insertUser(UsersTableCompanion.insert(id: userId, name: 'Тест'));
await dbV6.accountsDao.insertAccount(
AccountsTableCompanion.insert(
id: accountId,
userId: userId,
name: 'Основной',
),
);
// 2. «Откатываем» схему до v5: убираем колонки v6 И артефакты v7/v8
// (иначе onUpgrade 5→8 попытается создать их повторно).
await dbV6.customStatement(
'ALTER TABLE transactions DROP COLUMN obligation');
await dbV6.customStatement('ALTER TABLE transactions DROP COLUMN impulse');
await dbV6.customStatement(
'ALTER TABLE settings DROP COLUMN habit_tracking_enabled');
await dbV6.customStatement(
'ALTER TABLE account_bindings DROP COLUMN is_default');
await dbV6.customStatement('DROP TABLE source_apps');
await dbV6.customStatement('ALTER TABLE parse_rules DROP COLUMN tx_type');
await dbV6.customStatement('PRAGMA user_version = 5');
await dbV6.close();
// 3. Повторное открытие запускает onUpgrade(5 → 6).
final dbMigrated = AppDatabase.forTesting(NativeDatabase(file));
addTearDown(dbMigrated.close);
// 4. Колонки снова доступны: запись с оценками проходит round-trip.
final repoRow = await dbMigrated.transactionsDao.findById('tx-1');
expect(repoRow, isNull);
await dbMigrated.transactionsDao.insertTransaction(
TransactionsTableCompanion.insert(
id: 'tx-1',
userId: userId,
accountId: accountId,
amount: 1000,
date: DateTime(2024, 6, 1),
obligation: const Value(SpendingObligation.required),
impulse: const Value(SpendingImpulse.impulsive),
),
);
final tx = await dbMigrated.transactionsDao.findById('tx-1');
expect(tx!.obligation, SpendingObligation.required);
expect(tx.impulse, SpendingImpulse.impulsive);
// settings.habitTrackingEnabled присутствует с дефолтом false.
await dbMigrated.settingsDao.upsertSettings(
SettingsTableCompanion.insert(userId: userId),
);
final settings = await dbMigrated.settingsDao.getSettingsByUser(userId);
expect(settings!.habitTrackingEnabled, isFalse);
});
}