fix: isolate test thread workspaces

This commit is contained in:
Haitao Pan 2026-05-18 19:42:49 +08:00
parent 85297133c0
commit e264f3831a
4 changed files with 69 additions and 4 deletions

View File

@ -199,6 +199,12 @@ class AppController extends ChangeNotifier {
environmentOverrideInternal = environmentOverride == null
? null
: Map<String, String>.unmodifiable(environmentOverride);
if (environmentOverrideInternal != null) {
resolvedUserHomeDirectoryInternal =
resolveUserHomeDirectoryFromControllerEnvironmentInternal(
environmentOverrideInternal,
);
}
gatewayAcpClientInternal = GatewayAcpClient(
endpointResolver: resolveGatewayAcpEndpointInternal,
authorizationResolver: resolveGatewayAcpAuthorizationHeaderInternal,
@ -717,3 +723,22 @@ class AppController extends ChangeNotifier {
double get assistantSkillCount => skills.length.toDouble();
int get currentAssistantSkillCount => skills.length;
}
String resolveUserHomeDirectoryFromControllerEnvironmentInternal(
Map<String, String>? environment,
) {
if (environment == null) {
return resolveUserHomeDirectory();
}
final resolved = resolveUserHomeDirectory(environment: environment);
if (resolved.isNotEmpty) {
return resolved;
}
if (Platform.environment.containsKey('FLUTTER_TEST')) {
final suffix = DateTime.now().microsecondsSinceEpoch;
return Directory.systemTemp
.createTempSync('xworkmate-test-home-$suffix-')
.path;
}
return '';
}

View File

@ -457,8 +457,11 @@ extension AppControllerDesktopSettingsRuntime on AppController {
Future<void> initializeInternal() async {
try {
resolvedUserHomeDirectoryInternal =
await skillDirectoryAccessServiceInternal.resolveUserHomeDirectory();
resolvedUserHomeDirectoryInternal = environmentOverrideInternal == null
? await skillDirectoryAccessServiceInternal.resolveUserHomeDirectory()
: resolveUserHomeDirectoryFromControllerEnvironmentInternal(
environmentOverrideInternal,
);
await settingsControllerInternal.initialize();
final loadedAppUiState = await storeInternal.loadAppUiState();
final sanitizedAppUiState = sanitizeAppUiStateInternal(loadedAppUiState);

View File

@ -86,7 +86,9 @@ extension AssistantPageStateActionsInternal on AssistantPageStateInternal {
if (rawPrompt.isEmpty) {
return;
}
if (controller.hasAssistantPendingRun) {
if (controller.assistantSessionHasPendingRun(
controller.currentSessionKey,
)) {
await createNewThreadInternal();
}
final submittedSessionKey = controller.currentSessionKey;
@ -343,7 +345,16 @@ extension AssistantPageStateActionsInternal on AssistantPageStateInternal {
if (!mounted) {
return;
}
composerFocusNodeInternal.requestFocus();
void requestFocus() {
if (!mounted) {
return;
}
FocusScope.of(context).requestFocus(composerFocusNodeInternal);
composerFocusNodeInternal.requestFocus();
}
requestFocus();
WidgetsBinding.instance.addPostFrameCallback((_) => requestFocus());
}
Future<bool> runTaskSessionActionWithRetryInternal(

View File

@ -10,6 +10,32 @@ import 'package:xworkmate/runtime/go_task_service_client.dart';
import 'package:xworkmate/runtime/runtime_models.dart';
void main() {
test(
'empty environment override keeps thread workspaces out of real HOME',
() async {
final realHome = Platform.environment['HOME']?.trim() ?? '';
final controller = AppController(
environmentOverride: const <String, String>{},
);
addTearDown(controller.dispose);
await controller.sessionsController.switchSession('draft:test-task-a');
expect(controller.userHomeDirectory, isNot(isEmpty));
if (realHome.isNotEmpty) {
expect(controller.userHomeDirectory, isNot(realHome));
}
expect(
controller.localThreadWorkspacePathInternal('draft:test-task-a'),
isNot(contains('$realHome/.xworkmate/threads/draft-test-task-a')),
);
expect(
controller.localThreadWorkspaceDisplayPathInternal('draft:test-task-a'),
'\$HOME/.xworkmate/threads/draft-test-task-a',
);
},
);
test('does not expose gateway chat messages from another session', () async {
final controller = AppController(
environmentOverride: const <String, String>{},