xworkmate-app/test/features/mobile/mobile_assistant_page_test.dart
Cowork 3P fdda0b7d85 test,docs: fix all stale references to deleted multi-agent subsystem
Test fixes (6 files, -303 lines):
- Delete app_controller_acp_mount_resilience_test.dart (entirely about deleted types)
- Remove multi-agent test cases from gateway_acp_client_auth_test.dart
- Rename _manifestWithDesktopMultiAgentEnabled → _defaultDesktopManifest
  in assistant_execution_target_test, assistant_lower_pane_test,
  mobile_assistant_page_test

Docs fixes (6 files):
- Regenerate public-symbol-inventory.json/md via make docs-public-api
- Remove multi-agent sections from public-api/models-and-config.md,
  app-orchestration.md, runtime-contracts.md
- Fix xworkmate/ → xworkmate-app/ paths in cloud-session doc
- Remove multiAgent references from app-external-service-api-test-matrix.md
2026-06-04 06:31:45 +00:00

256 lines
8.0 KiB
Dart

import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:xworkmate/app/app_controller.dart';
import 'package:xworkmate/app/app_shell_desktop.dart';
import 'package:xworkmate/app/ui_feature_manifest.dart';
import 'package:xworkmate/app/workspace_page_registry.dart';
import 'package:xworkmate/features/mobile/mobile_assistant_page.dart';
import 'package:xworkmate/runtime/runtime_models.dart';
import 'package:xworkmate/theme/app_theme.dart';
void main() {
group('MobileAssistantPage', () {
testWidgets('mobile shell renders the mobile assistant surface', (
tester,
) async {
tester.view.devicePixelRatio = 1;
tester.view.physicalSize = const Size(430, 932);
addTearDown(tester.view.resetPhysicalSize);
addTearDown(tester.view.resetDevicePixelRatio);
final controller = AppController(
environmentOverride: const <String, String>{},
);
addTearDown(controller.dispose);
await tester.pumpWidget(
MaterialApp(
theme: AppTheme.light().copyWith(platform: TargetPlatform.iOS),
home: AppShell(controller: controller),
),
);
await tester.pumpAndSettle();
expect(find.byKey(const Key('mobile-assistant-page')), findsOneWidget);
expect(
find.byKey(const Key('assistant-conversation-shell')),
findsNothing,
);
expect(
find.byKey(const Key('assistant-workspace-resize-handle')),
findsNothing,
);
expect(
find.byKey(const Key('assistant-composer-resize-handle')),
findsNothing,
);
});
testWidgets('disconnected state shows a mobile Bridge connect CTA', (
tester,
) async {
final controller = AppController(
environmentOverride: const <String, String>{},
);
addTearDown(controller.dispose);
await tester.pumpWidget(_buildTestApp(controller: controller));
await tester.pumpAndSettle();
expect(find.text('先连接 Bridge'), findsWidgets);
expect(
find.byKey(const Key('mobile-assistant-connect-bridge-button')),
findsOneWidget,
);
});
testWidgets('provider sheet fails closed when capabilities are empty', (
tester,
) async {
final controller = AppController(
environmentOverride: const <String, String>{},
);
addTearDown(controller.dispose);
await tester.pumpWidget(_buildTestApp(controller: controller));
await tester.pumpAndSettle();
await tester.tap(
find.byKey(const Key('mobile-assistant-composer-add-button')),
);
await tester.pumpAndSettle();
await tester.tap(
find.byKey(const Key('mobile-assistant-provider-button')),
);
await tester.pumpAndSettle();
expect(
find.byKey(const Key('mobile-assistant-provider-empty-state')),
findsOneWidget,
);
expect(
find.byKey(const Key('mobile-assistant-provider-item-codex')),
findsNothing,
);
expect(
find.byKey(const Key('mobile-assistant-provider-item-openclaw')),
findsNothing,
);
});
testWidgets('provider sheet follows execution target capabilities', (
tester,
) async {
final controller = AppController(
environmentOverride: const <String, String>{},
uiFeatureManifest: _defaultDesktopManifest(),
initialBridgeProviderCatalog: const <SingleAgentProvider>[
SingleAgentProvider.codex,
],
initialGatewayProviderCatalog: <SingleAgentProvider>[
SingleAgentProvider.openclaw.copyWith(
supportedTargets: const <AssistantExecutionTarget>[
AssistantExecutionTarget.gateway,
],
),
],
initialAvailableExecutionTargets: const <AssistantExecutionTarget>[
AssistantExecutionTarget.agent,
AssistantExecutionTarget.gateway,
],
);
addTearDown(controller.dispose);
await tester.pumpWidget(
MaterialApp(
theme: AppTheme.light().copyWith(platform: TargetPlatform.iOS),
home: Scaffold(
body: Builder(
builder: (context) => Column(
children: [
TextButton(
key: const Key('show-agent-provider-sheet'),
onPressed: () {
showMobileAssistantProviderSheet(
context,
controller: controller,
target: AssistantExecutionTarget.agent,
selectedProvider: SingleAgentProvider.codex,
onSelected: (_) async {},
);
},
child: const Text('Agent providers'),
),
TextButton(
key: const Key('show-gateway-provider-sheet'),
onPressed: () {
showMobileAssistantProviderSheet(
context,
controller: controller,
target: AssistantExecutionTarget.gateway,
selectedProvider: SingleAgentProvider.openclaw,
onSelected: (_) async {},
);
},
child: const Text('Gateway providers'),
),
],
),
),
),
),
);
await tester.pumpAndSettle();
await tester.tap(find.byKey(const Key('show-agent-provider-sheet')));
await tester.pumpAndSettle();
expect(
find.byKey(const Key('mobile-assistant-provider-item-codex')),
findsOneWidget,
);
expect(
find.byKey(const Key('mobile-assistant-provider-item-openclaw')),
findsNothing,
);
await tester.tap(find.byKey(const Key('mobile-assistant-sheet-close')));
await tester.pumpAndSettle();
await tester.tap(find.byKey(const Key('show-gateway-provider-sheet')));
await tester.pumpAndSettle();
expect(
find.byKey(const Key('mobile-assistant-provider-item-openclaw')),
findsOneWidget,
);
expect(
find.byKey(const Key('mobile-assistant-provider-item-codex')),
findsNothing,
);
});
testWidgets('composer and submit stay visible with iPhone keyboard inset', (
tester,
) async {
tester.view.devicePixelRatio = 1;
tester.view.physicalSize = const Size(390, 844);
addTearDown(tester.view.resetPhysicalSize);
addTearDown(tester.view.resetDevicePixelRatio);
final controller = AppController(
environmentOverride: const <String, String>{},
);
addTearDown(controller.dispose);
await tester.pumpWidget(
_buildTestApp(
controller: controller,
viewInsets: const EdgeInsets.only(bottom: 312),
),
);
await tester.pumpAndSettle();
final inputRect = tester.getRect(
find.byKey(const Key('mobile-assistant-input')),
);
final sendRect = tester.getRect(
find.byKey(const Key('mobile-assistant-send-button')),
);
expect(inputRect.bottom, lessThanOrEqualTo(844));
expect(sendRect.bottom, lessThanOrEqualTo(844));
expect(sendRect.width, greaterThanOrEqualTo(32));
expect(sendRect.height, greaterThanOrEqualTo(32));
});
});
}
Widget _buildTestApp({
required AppController controller,
EdgeInsets viewInsets = EdgeInsets.zero,
}) {
final child = MobileAssistantDetailPage(
controller: controller,
onOpenDetail: (_) {},
onBack: () {},
mobileActions: const MobileWorkspaceActions(),
);
return MaterialApp(
theme: AppTheme.light().copyWith(platform: TargetPlatform.iOS),
home: MediaQuery(
data: MediaQueryData(size: const Size(430, 932), viewInsets: viewInsets),
child: Scaffold(body: child),
),
);
}
UiFeatureManifest _defaultDesktopManifest() {
return UiFeatureManifest.fromYamlString(
File(UiFeatureManifest.assetPath).readAsStringSync(),
);
}