feat(vault): pick a notebook vault folder on first run
Some checks failed
CI / Windows build (push) Has been cancelled
Some checks failed
CI / Windows build (push) Has been cancelled
Phase 0 of the file-based storage plan (docs/plans/ 2026-06-24-file-based-storage.md). Foundation only — no editor or DB change yet. - VaultService (SharedPreferences): stores the vault root path, vaultRootValid() = path set AND directory exists. - VaultSetupScreen: first-run folder picker (file_picker, Windows). - main.dart gates HomeScreen behind a valid vault, re-prompting if the saved folder is gone. - Settings: a Vault section to change the folder. Editors still use SQLite; later phases move annotations into per-file sidecars under the vault. analyze clean, tests green.
This commit is contained in:
81
test/vault_service_test.dart
Normal file
81
test/vault_service_test.dart
Normal file
@@ -0,0 +1,81 @@
|
||||
// Proves the Phase-0 vault root recording: the path persists through
|
||||
// SharedPreferences, vaultRootValid() is true ONLY when a path is set AND its
|
||||
// directory exists, and clearVaultRoot() forgets it. Uses a real temp dir for
|
||||
// existence checks and a mock SharedPreferences for persistence.
|
||||
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
|
||||
import 'package:badnote/services/vault_service.dart';
|
||||
|
||||
void main() {
|
||||
TestWidgetsFlutterBinding.ensureInitialized();
|
||||
|
||||
late Directory tempDir;
|
||||
|
||||
setUp(() async {
|
||||
SharedPreferences.setMockInitialValues({});
|
||||
tempDir = await Directory.systemTemp.createTemp('vault_service_test');
|
||||
});
|
||||
|
||||
tearDown(() async {
|
||||
if (await tempDir.exists()) {
|
||||
await tempDir.delete(recursive: true);
|
||||
}
|
||||
});
|
||||
|
||||
Future<VaultService> makeService() async {
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
return VaultService.forTest(prefs);
|
||||
}
|
||||
|
||||
test('starts with no vault root and is invalid', () async {
|
||||
final vault = await makeService();
|
||||
expect(vault.vaultRoot, isNull);
|
||||
expect(await vault.vaultRootValid(), isFalse);
|
||||
});
|
||||
|
||||
test('setVaultRoot persists the path', () async {
|
||||
final vault = await makeService();
|
||||
await vault.setVaultRoot(tempDir.path);
|
||||
expect(vault.vaultRoot, tempDir.path);
|
||||
|
||||
// Re-read through a fresh service over the SAME prefs store: persisted.
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
expect(prefs.getString(VaultService.vaultRootKey), tempDir.path);
|
||||
final reopened = VaultService.forTest(prefs);
|
||||
expect(reopened.vaultRoot, tempDir.path);
|
||||
});
|
||||
|
||||
test('vaultRootValid is true only when set AND the dir exists', () async {
|
||||
final vault = await makeService();
|
||||
|
||||
// Set to an existing dir → valid.
|
||||
await vault.setVaultRoot(tempDir.path);
|
||||
expect(await vault.vaultRootValid(), isTrue);
|
||||
|
||||
// Point at a path that does not exist → invalid (folder went missing).
|
||||
final missing = '${tempDir.path}${Platform.pathSeparator}gone';
|
||||
await vault.setVaultRoot(missing);
|
||||
expect(vault.vaultRoot, missing);
|
||||
expect(await vault.vaultRootValid(), isFalse);
|
||||
});
|
||||
|
||||
test('clearVaultRoot forgets the path and becomes invalid', () async {
|
||||
final vault = await makeService();
|
||||
await vault.setVaultRoot(tempDir.path);
|
||||
expect(await vault.vaultRootValid(), isTrue);
|
||||
|
||||
await vault.clearVaultRoot();
|
||||
expect(vault.vaultRoot, isNull);
|
||||
expect(await vault.vaultRootValid(), isFalse);
|
||||
});
|
||||
|
||||
test('empty stored path is treated as invalid', () async {
|
||||
final vault = await makeService();
|
||||
await vault.setVaultRoot('');
|
||||
expect(await vault.vaultRootValid(), isFalse);
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user