Files
platforms/apps/user_app/test/ui/repair_speech_test.dart
czl231 3ef33b531d 已完成用户APP首期功能开发
交付用户端首期页面、配套接口、后台资源及测试文档。用户APP构建、静态分析和三个管理后台构建通过;完整测试仍有2项失败,后端模型注释检查未通过,详见交付记录。
2026-09-13 00:57:32 +08:00

166 lines
5.6 KiB
Dart
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// 功能描述:语音结果选区替换、重复中间结果、拒绝权限、离页取消与长度边界回归。
// 版本1.0.0。
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:user_app/data/services/repair_speech.dart';
import 'package:user_app/ui/features/tickets/repair_speech_button.dart';
class _Speech implements RepairSpeech {
bool available = true;
int cancels = 0, starts = 0;
Completer<bool>? pending;
late void Function(String) words, error;
late void Function() done;
@override
Future<bool> start({
required void Function(String) onWords,
required void Function(String) onError,
required void Function() onDone,
}) async {
starts++;
words = onWords;
error = onError;
done = onDone;
return pending?.future ?? available;
}
@override
Future<void> stop() async {
done();
}
@override
Future<void> cancel() async {
cancels++;
}
}
void main() {
testWidgets('权限弹窗不取消初始化,切后台立即取消', (tester) async {
final speech = _Speech()..pending = Completer<bool>();
final controller = TextEditingController(text: '保留');
await tester.pumpWidget(
MaterialApp(
home: Scaffold(
body: RepairSpeechButton(controller: controller, onBusy: (_) {}, speech: speech),
),
),
);
await tester.tap(find.text('语音输入'));
await tester.pump();
tester.binding.handleAppLifecycleStateChanged(AppLifecycleState.inactive);
await tester.pump();
expect(speech.cancels, 0);
tester.binding.handleAppLifecycleStateChanged(AppLifecycleState.paused);
await tester.pump();
expect(speech.cancels, 1);
speech.pending!.complete(true);
speech.words('迟到');
await tester.pump();
expect(controller.text, '保留');
tester.binding.handleAppLifecycleStateChanged(AppLifecycleState.resumed);
await tester.pumpWidget(const SizedBox());
controller.dispose();
});
testWidgets('选区替换和中间结果不重复追加,结束后可再次录入', (tester) async {
final speech = _Speech(), controller = TextEditingController(text: '前旧后');
controller.selection = const TextSelection(baseOffset: 1, extentOffset: 2);
final busy = <bool>[];
await tester.pumpWidget(
MaterialApp(
home: Scaffold(
body: RepairSpeechButton(controller: controller, onBusy: busy.add, speech: speech),
),
),
);
await tester.tap(find.text('语音输入'));
await tester.pump();
speech.words('阀门');
speech.words('阀门异响');
await tester.pump();
expect(controller.text, '前阀门异响后');
await tester.tap(find.text('结束识别'));
await tester.pump();
speech.words('迟到结果');
expect(controller.text, '前阀门异响后');
expect(busy.last, false);
await tester.tap(find.text('语音输入'));
await tester.pump();
speech.words('补充');
speech.done();
await tester.pump();
expect(controller.text, '前阀门异响补充后');
expect(speech.starts, 2);
await tester.pumpWidget(const SizedBox());
controller.dispose();
});
testWidgets('不可用和权限拒绝保留输入并解除忙碌', (tester) async {
final speech = _Speech()..available = false, controller = TextEditingController(text: '已有内容');
final busy = <bool>[];
await tester.pumpWidget(
MaterialApp(
home: Scaffold(
body: RepairSpeechButton(controller: controller, onBusy: busy.add, speech: speech),
),
),
);
await tester.tap(find.text('语音输入'));
await tester.pump();
expect(find.textContaining('无法使用语音识别'), findsOneWidget);
expect(controller.text, '已有内容');
expect(busy.last, false);
speech.available = true;
await tester.tap(find.text('语音输入'));
await tester.pump();
speech.error('error_permission');
await tester.pump();
expect(find.textContaining('未获得麦克风'), findsOneWidget);
expect(controller.text, '已有内容');
expect(busy.last, false);
await tester.pumpWidget(const SizedBox());
controller.dispose();
});
testWidgets('初始化中离页取消,迟到结果不改变文字', (tester) async {
final speech = _Speech()..pending = Completer<bool>(),
controller = TextEditingController(text: '保留');
await tester.pumpWidget(
MaterialApp(
home: Scaffold(
body: RepairSpeechButton(controller: controller, onBusy: (_) {}, speech: speech),
),
),
);
await tester.tap(find.text('语音输入'));
await tester.pump();
await tester.pumpWidget(const SizedBox());
speech.pending!.complete(true);
speech.words('迟到');
await tester.pump();
expect(speech.cancels, 1);
expect(controller.text, '保留');
expect(tester.takeException(), isNull);
controller.dispose();
});
testWidgets('识别遵守2000字符上限不截断表情字符', (tester) async {
final speech = _Speech(),
controller = TextEditingController(text: List.filled(1999, '').join());
await tester.pumpWidget(
MaterialApp(
home: Scaffold(
body: RepairSpeechButton(controller: controller, onBusy: (_) {}, speech: speech),
),
),
);
await tester.tap(find.text('语音输入'));
await tester.pump();
speech.words('😀多余');
speech.done();
await tester.pump();
expect(controller.text.characters.length, 2000);
expect(controller.text.endsWith('😀'), true);
await tester.pumpWidget(const SizedBox());
controller.dispose();
});
}