665 lines
24 KiB
Dart
665 lines
24 KiB
Dart
// test/widget/manual_screen_test.dart
|
|
// ignore_for_file: prefer_const_constructors
|
|
//
|
|
// Widget tests untuk ManualScreen — halaman panduan perintah suara.
|
|
// Jalankan: flutter test test/widget/manual_screen_test.dart
|
|
|
|
// ignore_for_file: avoid_print
|
|
|
|
import 'package:flutter/material.dart';
|
|
import 'package:flutter_test/flutter_test.dart';
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// Stubs — mereplikasi VoiceCommandKey dan ManualScreen tanpa plugin
|
|
// ---------------------------------------------------------------------------
|
|
|
|
enum VoiceCommandKey {
|
|
openWalkguide,
|
|
startWalkguide,
|
|
stopWalkguide,
|
|
callGuardian,
|
|
openNotification,
|
|
readAllNotif,
|
|
openSos,
|
|
sendSos,
|
|
whereAmI,
|
|
openActivity,
|
|
openNavigation,
|
|
openSettings,
|
|
repeatLast,
|
|
stopTts,
|
|
}
|
|
|
|
class VoiceCommandEntry {
|
|
final VoiceCommandKey key;
|
|
final String phrase;
|
|
final String description;
|
|
final String category;
|
|
final bool enabled;
|
|
|
|
const VoiceCommandEntry({
|
|
required this.key,
|
|
required this.phrase,
|
|
required this.description,
|
|
required this.category,
|
|
this.enabled = true,
|
|
});
|
|
}
|
|
|
|
/// Data perintah suara default (sama seperti di backend)
|
|
const List<VoiceCommandEntry> _defaultCommands = [
|
|
VoiceCommandEntry(
|
|
key: VoiceCommandKey.openWalkguide,
|
|
phrase: 'Open Walkguide',
|
|
description: 'Membuka layar WalkGuide',
|
|
category: 'Navigasi',
|
|
),
|
|
VoiceCommandEntry(
|
|
key: VoiceCommandKey.startWalkguide,
|
|
phrase: 'Start Walkguide',
|
|
description: 'Memulai sesi navigasi WalkGuide',
|
|
category: 'Navigasi',
|
|
),
|
|
VoiceCommandEntry(
|
|
key: VoiceCommandKey.stopWalkguide,
|
|
phrase: 'Stop Walkguide',
|
|
description: 'Menghentikan sesi navigasi',
|
|
category: 'Navigasi',
|
|
),
|
|
VoiceCommandEntry(
|
|
key: VoiceCommandKey.callGuardian,
|
|
phrase: 'Call Guardian',
|
|
description: 'Menelepon Guardian',
|
|
category: 'Komunikasi',
|
|
),
|
|
VoiceCommandEntry(
|
|
key: VoiceCommandKey.openNotification,
|
|
phrase: 'Open Notifications',
|
|
description: 'Membuka layar notifikasi',
|
|
category: 'Navigasi',
|
|
),
|
|
VoiceCommandEntry(
|
|
key: VoiceCommandKey.readAllNotif,
|
|
phrase: 'Read All My Notifications',
|
|
description: 'TTS membacakan semua notifikasi',
|
|
category: 'Aksesibilitas',
|
|
),
|
|
VoiceCommandEntry(
|
|
key: VoiceCommandKey.openSos,
|
|
phrase: 'Open SOS',
|
|
description: 'Membuka layar SOS',
|
|
category: 'Darurat',
|
|
),
|
|
VoiceCommandEntry(
|
|
key: VoiceCommandKey.sendSos,
|
|
phrase: 'Send SOS',
|
|
description: 'Mengirim sinyal darurat',
|
|
category: 'Darurat',
|
|
),
|
|
VoiceCommandEntry(
|
|
key: VoiceCommandKey.whereAmI,
|
|
phrase: 'Where Am I',
|
|
description: 'TTS membacakan lokasi saat ini',
|
|
category: 'Lokasi',
|
|
),
|
|
VoiceCommandEntry(
|
|
key: VoiceCommandKey.openActivity,
|
|
phrase: 'Open Activity Log',
|
|
description: 'Membuka log aktivitas',
|
|
category: 'Navigasi',
|
|
),
|
|
VoiceCommandEntry(
|
|
key: VoiceCommandKey.openNavigation,
|
|
phrase: 'Open Navigation',
|
|
description: 'Membuka layar navigasi',
|
|
category: 'Navigasi',
|
|
),
|
|
VoiceCommandEntry(
|
|
key: VoiceCommandKey.openSettings,
|
|
phrase: 'Open Settings',
|
|
description: 'Membuka halaman pengaturan',
|
|
category: 'Navigasi',
|
|
),
|
|
VoiceCommandEntry(
|
|
key: VoiceCommandKey.repeatLast,
|
|
phrase: 'Repeat',
|
|
description: 'Mengulangi TTS terakhir',
|
|
category: 'Aksesibilitas',
|
|
),
|
|
VoiceCommandEntry(
|
|
key: VoiceCommandKey.stopTts,
|
|
phrase: 'Stop',
|
|
description: 'Menghentikan TTS',
|
|
category: 'Aksesibilitas',
|
|
),
|
|
];
|
|
|
|
/// Stub ManualScreen yang lebih kaya dari versi asli untuk keperluan testing
|
|
class _StubManualScreen extends StatefulWidget {
|
|
final List<VoiceCommandEntry> commands;
|
|
final bool showSearch;
|
|
|
|
const _StubManualScreen({
|
|
this.commands = _defaultCommands,
|
|
this.showSearch = false,
|
|
});
|
|
|
|
@override
|
|
State<_StubManualScreen> createState() => _StubManualScreenState();
|
|
}
|
|
|
|
class _StubManualScreenState extends State<_StubManualScreen> {
|
|
String _searchQuery = '';
|
|
String? _selectedCategory;
|
|
|
|
List<VoiceCommandEntry> get _filteredCommands {
|
|
return widget.commands.where((cmd) {
|
|
final matchesSearch = _searchQuery.isEmpty ||
|
|
cmd.phrase.toLowerCase().contains(_searchQuery.toLowerCase()) ||
|
|
cmd.description.toLowerCase().contains(_searchQuery.toLowerCase());
|
|
final matchesCategory =
|
|
_selectedCategory == null || cmd.category == _selectedCategory;
|
|
return matchesSearch && matchesCategory;
|
|
}).toList();
|
|
}
|
|
|
|
Set<String> get _categories => widget.commands.map((c) => c.category).toSet();
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return Scaffold(
|
|
appBar: AppBar(
|
|
title: const Text('Panduan Suara'),
|
|
actions: [
|
|
IconButton(
|
|
key: const Key('info_button'),
|
|
icon: const Icon(Icons.info_outline),
|
|
onPressed: () {
|
|
showDialog(
|
|
context: context,
|
|
builder: (_) => AlertDialog(
|
|
key: const Key('info_dialog'),
|
|
title: const Text('Cara Penggunaan'),
|
|
content: const Text(
|
|
'Ucapkan perintah suara yang tertera untuk mengontrol aplikasi. '
|
|
'Pastikan mikrofon aktif.',
|
|
),
|
|
actions: [
|
|
TextButton(
|
|
key: const Key('info_close_button'),
|
|
onPressed: () => Navigator.of(context).pop(),
|
|
child: const Text('Tutup'),
|
|
),
|
|
],
|
|
),
|
|
);
|
|
},
|
|
),
|
|
],
|
|
),
|
|
body: Column(
|
|
children: [
|
|
// Header instruksi
|
|
Container(
|
|
key: const Key('header_banner'),
|
|
width: double.infinity,
|
|
padding: const EdgeInsets.all(12),
|
|
color: Colors.blue.shade50,
|
|
child: const Row(
|
|
children: [
|
|
Icon(Icons.mic, color: Colors.blue),
|
|
SizedBox(width: 8),
|
|
Expanded(
|
|
child: Text(
|
|
key: Key('header_text'),
|
|
'Ucapkan salah satu perintah di bawah ini untuk mengontrol WalkGuide',
|
|
style: TextStyle(color: Colors.blue),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
|
|
// Search bar (opsional)
|
|
if (widget.showSearch)
|
|
Padding(
|
|
padding: const EdgeInsets.all(12),
|
|
child: TextField(
|
|
key: const Key('search_field'),
|
|
decoration: const InputDecoration(
|
|
hintText: 'Cari perintah...',
|
|
prefixIcon: Icon(Icons.search),
|
|
border: OutlineInputBorder(),
|
|
),
|
|
onChanged: (value) => setState(() => _searchQuery = value),
|
|
),
|
|
),
|
|
|
|
// Filter kategori
|
|
if (_categories.length > 1)
|
|
SizedBox(
|
|
height: 44,
|
|
child: ListView(
|
|
key: const Key('category_filter'),
|
|
scrollDirection: Axis.horizontal,
|
|
padding: const EdgeInsets.symmetric(horizontal: 12),
|
|
children: [
|
|
Padding(
|
|
padding: const EdgeInsets.only(right: 8),
|
|
child: FilterChip(
|
|
key: const Key('filter_all'),
|
|
label: const Text('Semua'),
|
|
selected: _selectedCategory == null,
|
|
onSelected: (_) =>
|
|
setState(() => _selectedCategory = null),
|
|
),
|
|
),
|
|
..._categories.map((cat) => Padding(
|
|
padding: const EdgeInsets.only(right: 8),
|
|
child: FilterChip(
|
|
key: Key('filter_$cat'),
|
|
label: Text(cat),
|
|
selected: _selectedCategory == cat,
|
|
onSelected: (_) =>
|
|
setState(() => _selectedCategory = cat),
|
|
),
|
|
)),
|
|
],
|
|
),
|
|
),
|
|
|
|
// Jumlah perintah
|
|
Padding(
|
|
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 4),
|
|
child: Align(
|
|
alignment: Alignment.centerLeft,
|
|
child: Text(
|
|
key: const Key('command_count'),
|
|
'${_filteredCommands.length} perintah tersedia',
|
|
style: TextStyle(color: Colors.grey.shade600, fontSize: 13),
|
|
),
|
|
),
|
|
),
|
|
|
|
// Daftar perintah
|
|
Expanded(
|
|
child: _filteredCommands.isEmpty
|
|
? Center(
|
|
child: Column(
|
|
mainAxisSize: MainAxisSize.min,
|
|
children: const [
|
|
Icon(Icons.search_off,
|
|
size: 48,
|
|
color: Colors.grey,
|
|
key: Key('no_result_icon')),
|
|
SizedBox(height: 8),
|
|
Text(
|
|
key: Key('no_result_text'),
|
|
'Tidak ada perintah yang cocok',
|
|
style: TextStyle(color: Colors.grey),
|
|
),
|
|
],
|
|
),
|
|
)
|
|
: ListView.separated(
|
|
key: const Key('command_list'),
|
|
padding:
|
|
const EdgeInsets.symmetric(horizontal: 12, vertical: 4),
|
|
itemCount: _filteredCommands.length,
|
|
separatorBuilder: (_, __) => const Divider(height: 1),
|
|
itemBuilder: (context, index) {
|
|
final cmd = _filteredCommands[index];
|
|
return ListTile(
|
|
key: Key('cmd_tile_${cmd.key.name}'),
|
|
leading: CircleAvatar(
|
|
backgroundColor: Colors.blue.shade100,
|
|
child: const Icon(Icons.record_voice_over,
|
|
color: Colors.blue),
|
|
),
|
|
title: Text(
|
|
key: Key('cmd_phrase_${cmd.key.name}'),
|
|
'"${cmd.phrase}"',
|
|
style: const TextStyle(fontWeight: FontWeight.bold),
|
|
),
|
|
subtitle: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
Text(
|
|
key: Key('cmd_desc_${cmd.key.name}'),
|
|
cmd.description,
|
|
style: TextStyle(
|
|
fontSize: 12, color: Colors.grey.shade700),
|
|
),
|
|
Container(
|
|
margin: const EdgeInsets.only(top: 4),
|
|
padding: const EdgeInsets.symmetric(
|
|
horizontal: 8, vertical: 2),
|
|
decoration: BoxDecoration(
|
|
color: Colors.grey.shade200,
|
|
borderRadius: BorderRadius.circular(10),
|
|
),
|
|
child: Text(
|
|
key: Key('cmd_category_${cmd.key.name}'),
|
|
cmd.category,
|
|
style: const TextStyle(fontSize: 11),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
trailing: cmd.enabled
|
|
? null
|
|
: const Icon(Icons.block,
|
|
color: Colors.grey,
|
|
size: 16,
|
|
key: Key('disabled_icon')),
|
|
isThreeLine: true,
|
|
);
|
|
},
|
|
),
|
|
),
|
|
],
|
|
),
|
|
);
|
|
}
|
|
}
|
|
|
|
Widget makeTestable(Widget child) => MaterialApp(home: child);
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// Tests
|
|
// ---------------------------------------------------------------------------
|
|
|
|
void main() {
|
|
group('ManualScreen Widget Tests', () {
|
|
// ── Rendering awal ─────────────────────────────────────────────────────
|
|
|
|
group('Rendering awal', () {
|
|
testWidgets('menampilkan AppBar dengan judul Panduan Suara',
|
|
(tester) async {
|
|
await tester.pumpWidget(makeTestable(const _StubManualScreen()));
|
|
expect(find.text('Panduan Suara'), findsOneWidget);
|
|
});
|
|
|
|
testWidgets('menampilkan header banner instruksi', (tester) async {
|
|
await tester.pumpWidget(makeTestable(const _StubManualScreen()));
|
|
expect(find.byKey(const Key('header_banner')), findsOneWidget);
|
|
expect(find.byKey(const Key('header_text')), findsOneWidget);
|
|
});
|
|
|
|
testWidgets('menampilkan daftar semua perintah default', (tester) async {
|
|
await tester.pumpWidget(makeTestable(const _StubManualScreen()));
|
|
expect(find.byKey(const Key('command_list')), findsOneWidget);
|
|
});
|
|
|
|
testWidgets('menampilkan jumlah perintah yang benar (14)',
|
|
(tester) async {
|
|
await tester.pumpWidget(makeTestable(const _StubManualScreen()));
|
|
expect(find.text('14 perintah tersedia'), findsOneWidget);
|
|
});
|
|
|
|
testWidgets('menampilkan tombol info di AppBar', (tester) async {
|
|
await tester.pumpWidget(makeTestable(const _StubManualScreen()));
|
|
expect(find.byKey(const Key('info_button')), findsOneWidget);
|
|
});
|
|
|
|
testWidgets('menampilkan filter kategori', (tester) async {
|
|
await tester.pumpWidget(makeTestable(const _StubManualScreen()));
|
|
expect(find.byKey(const Key('category_filter')), findsOneWidget);
|
|
});
|
|
|
|
testWidgets('filter Semua tersedia', (tester) async {
|
|
await tester.pumpWidget(makeTestable(const _StubManualScreen()));
|
|
expect(find.byKey(const Key('filter_all')), findsOneWidget);
|
|
});
|
|
});
|
|
|
|
// ── Konten perintah ───────────────────────────────────────────────────
|
|
|
|
group('Konten perintah suara', () {
|
|
testWidgets('menampilkan tile untuk perintah Open Walkguide',
|
|
(tester) async {
|
|
await tester.pumpWidget(makeTestable(const _StubManualScreen()));
|
|
await tester.scrollUntilVisible(
|
|
find.byKey(const Key('cmd_tile_openWalkguide')),
|
|
200,
|
|
);
|
|
expect(find.byKey(const Key('cmd_tile_openWalkguide')), findsOneWidget);
|
|
});
|
|
|
|
testWidgets('menampilkan phrase perintah dalam tanda kutip',
|
|
(tester) async {
|
|
await tester.pumpWidget(makeTestable(const _StubManualScreen()));
|
|
expect(find.text('"Open Walkguide"'), findsOneWidget);
|
|
});
|
|
|
|
testWidgets('menampilkan deskripsi perintah', (tester) async {
|
|
await tester.pumpWidget(makeTestable(const _StubManualScreen()));
|
|
expect(find.text('Membuka layar WalkGuide'), findsOneWidget);
|
|
});
|
|
|
|
testWidgets('menampilkan kategori perintah', (tester) async {
|
|
await tester.pumpWidget(makeTestable(const _StubManualScreen()));
|
|
expect(find.byKey(const Key('cmd_category_openWalkguide')),
|
|
findsOneWidget);
|
|
expect(find.text('Navigasi'), findsAtLeastNWidgets(1));
|
|
});
|
|
|
|
testWidgets('menampilkan perintah Call Guardian', (tester) async {
|
|
await tester.pumpWidget(makeTestable(const _StubManualScreen()));
|
|
expect(find.text('"Call Guardian"'), findsOneWidget);
|
|
});
|
|
|
|
testWidgets('menampilkan perintah Send SOS', (tester) async {
|
|
await tester.pumpWidget(makeTestable(const _StubManualScreen()));
|
|
await tester.scrollUntilVisible(find.text('"Send SOS"'), 200);
|
|
expect(find.text('"Send SOS"'), findsOneWidget);
|
|
});
|
|
|
|
testWidgets('menampilkan perintah Where Am I', (tester) async {
|
|
await tester.pumpWidget(makeTestable(const _StubManualScreen()));
|
|
await tester.scrollUntilVisible(find.text('"Where Am I"'), 200);
|
|
expect(find.text('"Where Am I"'), findsOneWidget);
|
|
});
|
|
|
|
testWidgets('menampilkan kategori Darurat untuk Send SOS',
|
|
(tester) async {
|
|
await tester.pumpWidget(makeTestable(const _StubManualScreen()));
|
|
await tester.scrollUntilVisible(
|
|
find.byKey(const Key('cmd_category_sendSos')), 200);
|
|
expect(find.byKey(const Key('cmd_category_sendSos')), findsOneWidget);
|
|
});
|
|
});
|
|
|
|
// ── Dialog info ───────────────────────────────────────────────────────
|
|
|
|
group('Dialog info penggunaan', () {
|
|
testWidgets('tap info button membuka dialog', (tester) async {
|
|
await tester.pumpWidget(makeTestable(const _StubManualScreen()));
|
|
|
|
await tester.tap(find.byKey(const Key('info_button')));
|
|
await tester.pumpAndSettle();
|
|
|
|
expect(find.byKey(const Key('info_dialog')), findsOneWidget);
|
|
expect(find.text('Cara Penggunaan'), findsOneWidget);
|
|
});
|
|
|
|
testWidgets('dialog berisi teks instruksi', (tester) async {
|
|
await tester.pumpWidget(makeTestable(const _StubManualScreen()));
|
|
|
|
await tester.tap(find.byKey(const Key('info_button')));
|
|
await tester.pumpAndSettle();
|
|
|
|
expect(find.textContaining('mikrofon'), findsOneWidget);
|
|
});
|
|
|
|
testWidgets('tombol Tutup menutup dialog', (tester) async {
|
|
await tester.pumpWidget(makeTestable(const _StubManualScreen()));
|
|
|
|
await tester.tap(find.byKey(const Key('info_button')));
|
|
await tester.pumpAndSettle();
|
|
|
|
expect(find.byKey(const Key('info_dialog')), findsOneWidget);
|
|
|
|
await tester.tap(find.byKey(const Key('info_close_button')));
|
|
await tester.pumpAndSettle();
|
|
|
|
expect(find.byKey(const Key('info_dialog')), findsNothing);
|
|
});
|
|
});
|
|
|
|
// ── Filter kategori ───────────────────────────────────────────────────
|
|
|
|
group('Filter kategori', () {
|
|
testWidgets('tap filter Darurat menampilkan hanya perintah darurat',
|
|
(tester) async {
|
|
await tester.pumpWidget(makeTestable(const _StubManualScreen()));
|
|
|
|
await tester.tap(find.byKey(const Key('filter_Darurat')));
|
|
await tester.pump();
|
|
|
|
// Hanya Open SOS dan Send SOS
|
|
expect(find.byKey(const Key('command_count')), findsOneWidget);
|
|
expect(find.text('2 perintah tersedia'), findsOneWidget);
|
|
});
|
|
|
|
testWidgets('tap filter Komunikasi menampilkan hanya Call Guardian',
|
|
(tester) async {
|
|
await tester.pumpWidget(makeTestable(const _StubManualScreen()));
|
|
|
|
await tester.tap(find.byKey(const Key('filter_Komunikasi')));
|
|
await tester.pump();
|
|
|
|
expect(find.text('1 perintah tersedia'), findsOneWidget);
|
|
});
|
|
|
|
testWidgets('tap filter Semua menampilkan kembali semua perintah',
|
|
(tester) async {
|
|
await tester.pumpWidget(makeTestable(const _StubManualScreen()));
|
|
|
|
await tester.tap(find.byKey(const Key('filter_Darurat')));
|
|
await tester.pump();
|
|
|
|
await tester.tap(find.byKey(const Key('filter_all')));
|
|
await tester.pump();
|
|
|
|
expect(find.text('14 perintah tersedia'), findsOneWidget);
|
|
});
|
|
|
|
testWidgets('tap filter Aksesibilitas menampilkan 3 perintah',
|
|
(tester) async {
|
|
await tester.pumpWidget(makeTestable(const _StubManualScreen()));
|
|
|
|
await tester.tap(find.byKey(const Key('filter_Aksesibilitas')));
|
|
await tester.pump();
|
|
|
|
expect(find.text('3 perintah tersedia'), findsOneWidget);
|
|
});
|
|
});
|
|
|
|
// ── Search ────────────────────────────────────────────────────────────
|
|
|
|
group('Pencarian perintah (showSearch=true)', () {
|
|
testWidgets('menampilkan search field saat showSearch=true',
|
|
(tester) async {
|
|
await tester.pumpWidget(
|
|
makeTestable(const _StubManualScreen(showSearch: true)),
|
|
);
|
|
expect(find.byKey(const Key('search_field')), findsOneWidget);
|
|
});
|
|
|
|
testWidgets('tidak menampilkan search field secara default',
|
|
(tester) async {
|
|
await tester.pumpWidget(makeTestable(const _StubManualScreen()));
|
|
expect(find.byKey(const Key('search_field')), findsNothing);
|
|
});
|
|
|
|
testWidgets('search "SOS" memfilter perintah SOS', (tester) async {
|
|
await tester.pumpWidget(
|
|
makeTestable(const _StubManualScreen(showSearch: true)),
|
|
);
|
|
|
|
await tester.enterText(find.byKey(const Key('search_field')), 'SOS');
|
|
await tester.pump();
|
|
|
|
expect(find.text('2 perintah tersedia'), findsOneWidget);
|
|
});
|
|
|
|
testWidgets('search tanpa hasil menampilkan empty state', (tester) async {
|
|
await tester.pumpWidget(
|
|
makeTestable(const _StubManualScreen(showSearch: true)),
|
|
);
|
|
|
|
await tester.enterText(
|
|
find.byKey(const Key('search_field')), 'xyz tidak ada');
|
|
await tester.pump();
|
|
|
|
expect(find.byKey(const Key('no_result_text')), findsOneWidget);
|
|
});
|
|
|
|
testWidgets('search "guardian" menemukan Call Guardian', (tester) async {
|
|
await tester.pumpWidget(
|
|
makeTestable(const _StubManualScreen(showSearch: true)),
|
|
);
|
|
|
|
await tester.enterText(
|
|
find.byKey(const Key('search_field')), 'guardian');
|
|
await tester.pump();
|
|
|
|
expect(find.text('"Call Guardian"'), findsOneWidget);
|
|
});
|
|
});
|
|
|
|
// ── Perintah disabled ─────────────────────────────────────────────────
|
|
|
|
group('Perintah disabled', () {
|
|
testWidgets('perintah disabled menampilkan icon block', (tester) async {
|
|
final disabledCommands = [
|
|
const VoiceCommandEntry(
|
|
key: VoiceCommandKey.callGuardian,
|
|
phrase: 'Call Guardian',
|
|
description: 'Test disabled',
|
|
category: 'Komunikasi',
|
|
enabled: false,
|
|
),
|
|
];
|
|
await tester.pumpWidget(makeTestable(
|
|
_StubManualScreen(commands: disabledCommands),
|
|
));
|
|
|
|
expect(find.byKey(const Key('disabled_icon')), findsOneWidget);
|
|
});
|
|
|
|
testWidgets('perintah enabled tidak menampilkan icon block',
|
|
(tester) async {
|
|
await tester.pumpWidget(makeTestable(const _StubManualScreen()));
|
|
expect(find.byKey(const Key('disabled_icon')), findsNothing);
|
|
});
|
|
});
|
|
|
|
// ── Layout responsif ──────────────────────────────────────────────────
|
|
|
|
group('Responsif', () {
|
|
testWidgets('tidak overflow pada layar 360x640', (tester) async {
|
|
tester.view.physicalSize = const Size(360, 640);
|
|
tester.view.devicePixelRatio = 1.0;
|
|
addTearDown(tester.view.resetPhysicalSize);
|
|
|
|
await tester.pumpWidget(makeTestable(const _StubManualScreen()));
|
|
|
|
expect(tester.takeException(), isNull);
|
|
});
|
|
|
|
testWidgets('tidak overflow pada layar 428x926 (iPhone 14 Pro Max)',
|
|
(tester) async {
|
|
tester.view.physicalSize = const Size(428, 926);
|
|
tester.view.devicePixelRatio = 1.0;
|
|
addTearDown(tester.view.resetPhysicalSize);
|
|
|
|
await tester.pumpWidget(makeTestable(const _StubManualScreen()));
|
|
|
|
expect(tester.takeException(), isNull);
|
|
});
|
|
});
|
|
});
|
|
}
|