Retry project loading when reusing agent URL

This commit is contained in:
sladro 2026-04-06 09:10:27 +08:00
parent 39ab30d715
commit 62908440e1
2 changed files with 59 additions and 5 deletions

View File

@ -68,11 +68,10 @@ class _ProjectListPageState extends ConsumerState<ProjectListPage> {
}
final current = ref.read(agentBaseUriProvider);
if (current == parsedUri) {
return;
if (current != parsedUri) {
ref.read(agentBaseUriProvider.notifier).state = parsedUri;
}
ref.read(agentBaseUriProvider.notifier).state = parsedUri;
ref.invalidate(sessionsProvider);
await _reloadProjects();
}

View File

@ -62,6 +62,30 @@ void main() {
expect(find.widgetWithText(FilledButton, 'Open terminal'), findsOneWidget);
});
testWidgets(
'reuses the same agent URL and retries project loading when Use is tapped',
(tester) async {
final projectRepository = _RecoveringProjectRepository();
await _pumpApp(
tester,
projectRepository: projectRepository,
sessionRepository: _FakeSessionRepository(),
);
expect(find.text('Could not load projects'), findsOneWidget);
expect(projectRepository.listProjectsCallCount, 1);
await tester.tap(find.widgetWithText(FilledButton, 'Use'));
await tester.pump();
await tester.pumpAndSettle();
expect(projectRepository.listProjectsCallCount, 2);
expect(find.text('Could not load projects'), findsNothing);
expect(find.text('codex-main'), findsOneWidget);
},
);
testWidgets('project card opens a terminal without an extra prompt', (
tester,
) async {
@ -275,7 +299,10 @@ void main() {
expect(find.byType(TextField), findsNothing);
expect(find.byKey(const Key('terminal_actions_sheet')), findsNothing);
expect(find.byKey(const Key('terminal_actions_button')), findsOneWidget);
expect(find.byKey(const Key('terminal_toggle_actions_button')), findsNothing);
expect(
find.byKey(const Key('terminal_toggle_actions_button')),
findsNothing,
);
await tester.tap(find.byKey(const Key('terminal_actions_button')));
await tester.pumpAndSettle();
@ -283,7 +310,10 @@ void main() {
expect(find.byKey(const Key('terminal_actions_sheet')), findsOneWidget);
expect(find.text('Reconnect'), findsOneWidget);
expect(find.text('Latest'), findsOneWidget);
expect(find.byKey(const Key('terminal_quick_key_ctrl_c')), findsOneWidget);
expect(
find.byKey(const Key('terminal_quick_key_ctrl_c')),
findsOneWidget,
);
expect(find.text('ssh prod'), findsNothing);
},
);
@ -1183,6 +1213,31 @@ class _FailingProjectRepository extends ProjectRepository {
}
}
class _RecoveringProjectRepository extends _FakeProjectRepository {
int listProjectsCallCount = 0;
@override
Future<List<Project>> listProjects() async {
listProjectsCallCount += 1;
if (listProjectsCallCount == 1) {
throw DioException.connectionError(
requestOptions: RequestOptions(
path: '/api/projects',
baseUrl: 'http://100.81.30.82:5067',
),
reason: 'No route to host',
error: const SocketException(
'Connection failed',
osError: OSError('No route to host', 65),
port: 5067,
),
);
}
return super.listProjects();
}
}
class _FakeAgentApiClient extends AgentApiClient {
_FakeAgentApiClient() : super(Uri.parse('http://100.81.30.82:5067'));