Files
IKAR/test/voice_transcription_menu_test.dart
T

206 lines
7.2 KiB
Dart
Raw 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.
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:ikar/backend/modules/messages.dart';
import 'package:ikar/core/config/app_message_actions_style.dart';
import 'package:ikar/frontend/screens/chats/chat/view/message_row_widgets.dart';
import 'package:ikar/frontend/widgets/attachment/bubbles/voice_bubble.dart';
import 'package:ikar/frontend/widgets/message_actions_overlay.dart';
import 'package:ikar/frontend/widgets/message_bubble.dart';
import 'package:ikar/l10n/app_localizations.dart';
import 'package:ikar/models/attachment.dart';
import 'package:ikar/main.dart' show api;
import 'package:material_symbols_icons/symbols.dart';
const _label = 'Расшифровка голосового сообщения';
CachedMessage _message({bool voice = true, String status = 'sent'}) =>
CachedMessage(
id: '901',
accountId: 1,
chatId: 10,
senderId: 7,
time: DateTime(2026, 1, 1, 10).millisecondsSinceEpoch,
status: status,
text: voice ? null : 'Обычное сообщение',
attachments: voice
? const [AudioAttachment(audioId: 942, duration: 5000)]
: null,
);
Future<void> _pumpRow(
WidgetTester tester,
CachedMessage message, {
double scale = 1,
}) async {
final selected = ValueNotifier(<String>{});
addTearDown(selected.dispose);
await tester.pumpWidget(
MaterialApp(
locale: const Locale('ru'),
localizationsDelegates: AppLocalizations.localizationsDelegates,
supportedLocales: AppLocalizations.supportedLocales,
home: MediaQuery(
data: MediaQueryData(
size: const Size(800, 600),
textScaler: TextScaler.linear(scale),
),
child: Scaffold(
body: Padding(
padding: const EdgeInsets.all(24),
child: Align(
alignment: Alignment.topLeft,
child: SelectableMessageRow(
message: message,
isMe: false,
selectedIds: selected,
selectionAnim: const AlwaysStoppedAnimation(0),
isSelectionActive: () => false,
onToggleSelection: () {},
onEnterSelection: () {},
onStartTextSelection: (_) {},
onDragTextSelection: (_) {},
onDelete: () {},
isPinned: () => false,
child: MessageBubble(
message: message,
isMe: false,
myId: 1,
chatType: 'DIALOG',
),
),
),
),
),
),
),
);
await tester.pump();
}
Future<void> _tapBubble(WidgetTester tester, {bool voice = true}) async {
if (voice) {
final rect = tester.getRect(find.byType(VoiceMessageBubble));
await tester.tapAt(Offset(rect.right - 12, rect.bottom - 6));
} else {
await tester.tap(find.text('Обычное сообщение'));
}
await tester.pump(const Duration(milliseconds: 220));
await tester.pumpAndSettle();
}
void main() {
// Initialize the shared API outside the widget test's fake timer zone.
tearDownAll(api.dispose);
setUp(TranscriptionCache.clear);
tearDown(TranscriptionCache.clear);
testWidgets(
'tap on the voice bubble opens a large transcription row and shows text',
(tester) async {
TranscriptionCache.put(
'901',
TranscriptionResult(status: 1, text: 'Проверка расшифровки'),
);
await _pumpRow(tester, _message());
expect(find.text('Т'), findsNothing);
expect(find.text('Проверка расшифровки'), findsNothing);
await _tapBubble(tester);
final action = find.ancestor(
of: find.text(_label),
matching: find.byType(InkWell),
);
expect(find.text(_label), findsOneWidget);
expect(tester.getSize(action).height, greaterThanOrEqualTo(48));
await tester.tap(find.text(_label));
await tester.pumpAndSettle();
expect(find.text('Проверка расшифровки'), findsOneWidget);
await _tapBubble(tester);
await tester.tap(find.text('Скрыть расшифровку'));
await tester.pumpAndSettle();
expect(find.text('Проверка расшифровки'), findsNothing);
await tester.pumpWidget(const SizedBox());
},
);
testWidgets('text and uploading voice messages do not offer transcription', (
tester,
) async {
await _pumpRow(tester, _message(voice: false));
await _tapBubble(tester, voice: false);
expect(find.text(_label), findsNothing);
await tester.tapAt(const Offset(780, 570));
await tester.pumpAndSettle();
await _pumpRow(tester, _message(status: 'sending'));
await _tapBubble(tester);
expect(find.text(_label), findsNothing);
await tester.pumpWidget(const SizedBox());
});
testWidgets(
'recognition progress and completion push update the voice bubble',
(tester) async {
await _pumpRow(tester, _message());
TranscriptionCache.put(
'901',
TranscriptionResult(status: 0),
expanded: true,
);
await tester.pumpAndSettle();
expect(find.text('транскрибация...'), findsOneWidget);
TranscriptionCache.put(
'901',
TranscriptionResult(status: 1, text: 'Результат сервера'),
expanded: true,
);
await tester.pumpAndSettle();
expect(find.text('Результат сервера'), findsOneWidget);
expect(find.text('транскрибация...'), findsNothing);
await tester.pumpWidget(const SizedBox());
},
);
testWidgets('the full menu label fits with larger text', (tester) async {
final controller = MessageActionsController();
await tester.pumpWidget(
MaterialApp(
locale: const Locale('ru'),
localizationsDelegates: AppLocalizations.localizationsDelegates,
supportedLocales: AppLocalizations.supportedLocales,
builder: (context, child) => MediaQuery(
data: MediaQuery.of(
context,
).copyWith(textScaler: const TextScaler.linear(1.5)),
child: child!,
),
home: Scaffold(
body: Builder(
builder: (context) => TextButton(
onPressed: () => showMessageActions(
context: context,
originRect: const Rect.fromLTWH(24, 100, 240, 54),
tapPoint: const Offset(50, 120),
isMe: false,
messageText: null,
copyText: null,
controller: controller,
style: MessageActionsStyle.list,
interaction: MessageActionsInteraction.click,
onTranscribe: () {},
onDispose: controller.dispose,
),
child: const Text('open'),
),
),
),
),
);
await tester.tap(find.text('open'));
await tester.pumpAndSettle();
expect(find.text(_label), findsOneWidget);
expect(find.byIcon(Symbols.speech_to_text), findsOneWidget);
expect(tester.takeException(), isNull);
await tester.tapAt(const Offset(780, 570));
await tester.pumpAndSettle();
});
}