127 lines
3.8 KiB
Dart
127 lines
3.8 KiB
Dart
import 'dart:async';
|
|
|
|
import 'package:ducafe_ui_core/ducafe_ui_core.dart';
|
|
import 'package:flutter/material.dart';
|
|
import 'package:flutter_test/flutter_test.dart';
|
|
import 'package:forui/forui.dart';
|
|
|
|
import 'package:pj_supermarket_cloud/common/index.dart';
|
|
|
|
void main() {
|
|
TestWidgetsFlutterBinding.ensureInitialized();
|
|
late int createTextureCount;
|
|
late int releaseTextureCount;
|
|
|
|
setUp(() {
|
|
createTextureCount = 0;
|
|
releaseTextureCount = 0;
|
|
TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger
|
|
.setMockMethodCallHandler(FaceDiscernPlugs.getChannel, (call) async {
|
|
if (call.method == 'createPreviewTexture') {
|
|
createTextureCount++;
|
|
return <String, Object>{
|
|
'textureId': 42,
|
|
'width': 1280,
|
|
'height': 720,
|
|
'rotation': 0,
|
|
'mirror': true,
|
|
};
|
|
}
|
|
if (call.method == 'releasePreviewTexture') {
|
|
releaseTextureCount++;
|
|
}
|
|
return null;
|
|
});
|
|
});
|
|
|
|
tearDown(() {
|
|
TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger
|
|
.setMockMethodCallHandler(FaceDiscernPlugs.getChannel, null);
|
|
});
|
|
|
|
testWidgets('面板销毁时取消事件监听、当前会话并释放预览纹理', (tester) async {
|
|
final eventController =
|
|
StreamController<FaceRecognitionSessionEvent>.broadcast();
|
|
addTearDown(eventController.close);
|
|
final resultCompleter = Completer<FaceStream>();
|
|
final service = _FakeFaceRecognitionSessionService('session-1');
|
|
final panelController = FaceRecognitionPanelController();
|
|
final handle = FaceRecognitionSessionHandle(
|
|
sessionId: 'session-1',
|
|
scene: FaceRecognitionScene.cashier,
|
|
events: eventController.stream,
|
|
result: resultCompleter.future,
|
|
);
|
|
|
|
await tester.pumpWidget(
|
|
_facePanelTestApp(
|
|
FaceRecognitionPanel(
|
|
service: service,
|
|
handle: handle,
|
|
controller: panelController,
|
|
onRecognized: (_) {},
|
|
timeout: const Duration(minutes: 1),
|
|
),
|
|
),
|
|
);
|
|
await tester.pump();
|
|
expect(createTextureCount, 1);
|
|
expect(eventController.hasListener, isTrue);
|
|
|
|
await tester.pumpWidget(_facePanelTestApp(const SizedBox.shrink()));
|
|
await tester.pump();
|
|
|
|
expect(eventController.hasListener, isFalse);
|
|
expect(service.cancelCount, 1);
|
|
expect(releaseTextureCount, 1);
|
|
await panelController.cancel();
|
|
expect(service.cancelCount, 1, reason: '销毁后的控制句柄不得继续操作旧会话');
|
|
expect(tester.takeException(), isNull);
|
|
});
|
|
}
|
|
|
|
/// 构建具备项目缩放和 ForUI 主题的人脸面板测试环境。
|
|
Widget _facePanelTestApp(Widget child) {
|
|
return ScreenUtilInit(
|
|
designSize: const Size(1920, 1080),
|
|
builder: (_, __) => MaterialApp(
|
|
home: FTheme(
|
|
data: FThemes.zinc.light,
|
|
child: Scaffold(body: Center(child: child)),
|
|
),
|
|
),
|
|
);
|
|
}
|
|
|
|
/// 测试专用人脸会话服务,只记录面板是否按所有权释放当前会话。
|
|
class _FakeFaceRecognitionSessionService extends FaceRecognitionSessionService {
|
|
/// 创建持有指定会话的测试服务。
|
|
_FakeFaceRecognitionSessionService(this.sessionId);
|
|
|
|
/// 当前测试服务拥有的会话 ID。
|
|
final String sessionId;
|
|
|
|
/// 面板销毁触发的取消次数。
|
|
int cancelCount = 0;
|
|
|
|
/// 当前测试会话是否仍归此服务所有。
|
|
bool active = true;
|
|
|
|
/// 仅声明与测试句柄一致的会话归属。
|
|
@override
|
|
bool owns(String? sessionId) => active && sessionId == this.sessionId;
|
|
|
|
/// 记录销毁时的取消动作并释放测试会话所有权。
|
|
@override
|
|
Future<void> cancel({String message = '已取消人脸识别'}) async {
|
|
cancelCount++;
|
|
active = false;
|
|
}
|
|
|
|
/// 结束路径与取消路径都释放测试会话所有权。
|
|
@override
|
|
Future<void> finish() async {
|
|
active = false;
|
|
}
|
|
}
|