diff --git a/mobile-next/test/company/b273_client_cleanup_test.dart b/mobile-next/test/company/b273_client_cleanup_test.dart
new file mode 100644
index 0000000..f8dbcef
--- /dev/null
+++ b/mobile-next/test/company/b273_client_cleanup_test.dart
@@ -0,0 +1,105 @@
+import 'dart:io';
+
+import 'package:flutter_test/flutter_test.dart';
+import 'package:openim_common/openim_common.dart';
+import 'package:openim_common/src/res/lang/en_US.dart';
+import 'package:openim_common/src/res/lang/zh_CN.dart';
+
+void main() {
+ test('通话入口文案统一为语音通话,不改相册/拍摄视频能力文案', () {
+ expect(zh_CN['toolboxCall'], '语音通话');
+ expect(zh_CN['audioAndVideoCall'], '语音通话');
+ expect(zh_CN['callVoice'], '语音通话');
+ expect(zh_CN['invitedVoiceCallHint'], '邀请你语音通话');
+ expect(zh_CN['toolboxCamera'], '拍摄');
+ expect(zh_CN['video'], '视频');
+ expect(en_US['toolboxCall'], 'Voice Call');
+ expect(en_US['audioAndVideoCall'], 'Voice Call');
+ });
+
+ test('资料页通话按钮使用麦克风语义图标', () {
+ expect(ImageRes.callVoice, contains('ic_call_voice'));
+ });
+
+ test('历史位置消息解析失败时回退到标题和坐标,不抛异常', () {
+ final valid = LocationBubbleData.parse(
+ description:
+ '{"name":"公司门口","addr":"示范路 1 号","url":"https://example.com/map.png"}',
+ latitude: 31.23,
+ longitude: 121.47,
+ );
+ expect(valid.title, '公司门口');
+ expect(valid.address, '示范路 1 号');
+ expect(valid.thumbnailUrl, 'https://example.com/map.png');
+
+ final broken = LocationBubbleData.parse(
+ description: 'not-json',
+ latitude: 31.23001,
+ longitude: 121.47002,
+ );
+ expect(broken.title, '位置消息');
+ expect(broken.address, 'not-json');
+ expect(broken.thumbnailUrl, isNull);
+
+ final emptyJson = LocationBubbleData.parse(
+ description: '{}',
+ latitude: 1.5,
+ longitude: 2.5,
+ );
+ expect(emptyJson.title, '位置消息');
+ expect(emptyJson.address, '1.50000, 2.50000');
+ expect(emptyJson.thumbnailUrl, isNull);
+ });
+
+ test('Android 清单移除悬浮窗、定位和旧浮窗服务', () {
+ final xml =
+ File('android/app/src/main/AndroidManifest.xml').readAsStringSync();
+ expect(xml.contains('SYSTEM_ALERT_WINDOW'), isTrue);
+ expect(xml.contains('tools:node="remove"'), isTrue);
+ expect(
+ RegExp(r'')
+ .hasMatch(xml),
+ isFalse);
+ expect(
+ RegExp(r'')
+ .hasMatch(xml),
+ isFalse);
+ expect(
+ RegExp(r'')
+ .hasMatch(xml),
+ isFalse);
+ expect(
+ RegExp(r'')
+ .hasMatch(xml),
+ isFalse);
+ expect(xml.contains('flutter_openim_live_alert.services.CallService'),
+ isFalse);
+ expect(xml.contains('REQUEST_IGNORE_BATTERY_OPTIMIZATIONS'), isFalse);
+ });
+
+ test('IM 同步完成不再申请悬浮窗,来电不再检查 overlay', () {
+ final im =
+ File('lib/core/controller/im_controller.dart').readAsStringSync();
+ expect(im.contains('systemAlertWindow'), isFalse);
+ final live =
+ File('openim_live/lib/src/live_controller.dart').readAsStringSync();
+ expect(live.contains('checkSystemAlertWindow'), isFalse);
+ expect(live.contains('systemAlertWindow'), isFalse);
+ });
+
+ test('工具箱和选点发送链路已删除', () {
+ final toolbox = File('openim_common/lib/src/widgets/chat/chat_toolbox.dart')
+ .readAsStringSync();
+ expect(toolbox.contains('onTapLocation'), isFalse);
+ expect(toolbox.contains('toolboxLocation'), isFalse);
+ final chatLogic = File('lib/pages/chat/chat_logic.dart').readAsStringSync();
+ expect(chatLogic.contains('onTapLocation'), isFalse);
+ expect(chatLogic.contains('sendLocation'), isFalse);
+ expect(chatLogic.contains('createLocationMessage'), isFalse);
+ expect(chatLogic.contains('ChatWebViewMap'), isFalse);
+ expect(
+ File('openim_common/lib/src/widgets/chat/chat_webview_map.dart')
+ .existsSync(),
+ isFalse);
+ });
+}