Isolate test persistence roots

This commit is contained in:
Haitao Pan 2026-03-23 22:57:24 +08:00
parent bf0d3def67
commit 5ea0a61aac
4 changed files with 52 additions and 16 deletions

View File

@ -3,9 +3,9 @@ import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:integration_test/integration_test.dart';
import 'package:path_provider/path_provider.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:xworkmate/app/app.dart';
import 'package:xworkmate/runtime/secure_config_store.dart';
void initializeIntegrationHarness() {
IntegrationTestWidgetsFlutterBinding.ensureInitialized();
@ -13,15 +13,16 @@ void initializeIntegrationHarness() {
Future<void> resetIntegrationPreferences() async {
SharedPreferences.setMockInitialValues(<String, Object>{});
try {
final supportDirectory = await getApplicationSupportDirectory();
final xworkmateDirectory = Directory('${supportDirectory.path}/xworkmate');
if (await xworkmateDirectory.exists()) {
await xworkmateDirectory.delete(recursive: true);
final isolatedRoot = await Directory.systemTemp.createTemp(
'xworkmate-integration-store-',
);
debugOverridePersistentSupportRoot(isolatedRoot.path);
addTearDown(() async {
debugOverridePersistentSupportRoot(null);
if (await isolatedRoot.exists()) {
await isolatedRoot.delete(recursive: true);
}
} catch (_) {
// Keep integration setup best-effort on runners without path support.
}
});
}
Future<void> pumpDesktopApp(

View File

@ -4,6 +4,15 @@ import 'dart:io';
import 'package:path_provider/path_provider.dart';
import 'package:yaml/yaml.dart';
String? _persistentSupportRootOverride;
void debugOverridePersistentSupportRoot(String? path) {
final trimmed = path?.trim() ?? '';
_persistentSupportRootOverride = trimmed.isEmpty
? null
: normalizeStoreDirectoryPath(trimmed);
}
enum PersistentStoreScope { settings, tasks, secrets, audit }
class PersistentWriteFailure {
@ -120,6 +129,10 @@ class StoreLayoutResolver {
}
Future<String?> _defaultSupportRootPath() async {
final override = _persistentSupportRootOverride;
if (override != null && override.isNotEmpty) {
return override;
}
try {
final supportDirectory = await getApplicationSupportDirectory();
return '${supportDirectory.path}/xworkmate';

View File

@ -12,6 +12,8 @@ import 'package:xworkmate/runtime/desktop_platform_service.dart';
import 'package:xworkmate/runtime/runtime_models.dart';
import 'package:xworkmate/runtime/secure_config_store.dart';
import '../test_support.dart';
class _FakeDesktopPlatformService implements DesktopPlatformService {
_FakeDesktopPlatformService()
: _state = DesktopIntegrationState.fromJson(const <String, dynamic>{
@ -104,8 +106,13 @@ class _FakeDesktopPlatformService implements DesktopPlatformService {
}
class _ThrowingSecureConfigStore extends SecureConfigStore {
_ThrowingSecureConfigStore()
: super(enableSecureStorage: false);
_ThrowingSecureConfigStore(String rootPath)
: super(
enableSecureStorage: false,
databasePathResolver: () async => '$rootPath/settings.sqlite3',
fallbackDirectoryPathResolver: () async => rootPath,
defaultSupportDirectoryPathResolver: () async => rootPath,
);
@override
Future<String?> loadGatewayToken({int? profileIndex}) async {
@ -233,7 +240,10 @@ void main() {
() async {
SharedPreferences.setMockInitialValues(<String, Object>{});
final service = _FakeDesktopPlatformService();
final controller = AppController(desktopPlatformService: service);
final controller = AppController(
store: createIsolatedTestStore(enableSecureStorage: false),
desktopPlatformService: service,
);
addTearDown(controller.dispose);
await _waitFor(() => !controller.initializing);
@ -272,9 +282,19 @@ void main() {
() async {
SharedPreferences.setMockInitialValues(<String, Object>{});
final server = await _FakeGatewayTestServer.start();
final controller = AppController(store: _ThrowingSecureConfigStore());
final tempDirectory = await Directory.systemTemp.createTemp(
'xworkmate-desktop-platform-tests-',
);
final controller = AppController(
store: _ThrowingSecureConfigStore(tempDirectory.path),
);
addTearDown(server.close);
addTearDown(controller.dispose);
addTearDown(() async {
if (await tempDirectory.exists()) {
await tempDirectory.delete(recursive: true);
}
});
await _waitFor(() => !controller.initializing);
@ -299,7 +319,7 @@ void main() {
Future<void> _waitFor(
bool Function() condition, {
Duration timeout = const Duration(seconds: 2),
Duration timeout = const Duration(seconds: 5),
}) async {
final stopwatch = Stopwatch()..start();
while (!condition()) {

View File

@ -8,12 +8,14 @@ import 'package:shared_preferences/shared_preferences.dart';
import 'package:xworkmate/app/app_controller.dart';
import 'package:xworkmate/models/app_models.dart';
import '../test_support.dart';
void main() {
test(
'AppController keeps tasks destination in focused destinations',
() async {
SharedPreferences.setMockInitialValues(<String, Object>{});
final controller = AppController();
final controller = AppController(store: createIsolatedTestStore());
addTearDown(controller.dispose);
await _waitFor(() => !controller.initializing);
@ -43,7 +45,7 @@ void main() {
test('AppController toggles focused navigation destinations', () async {
SharedPreferences.setMockInitialValues(<String, Object>{});
final controller = AppController();
final controller = AppController(store: createIsolatedTestStore());
addTearDown(controller.dispose);
await _waitFor(() => !controller.initializing);