frindlymap/test_ux/shots_test.dart

160 lines
7.3 KiB
Dart
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

// 화면 점검용 캡처 (일반 시험이 아니다). 폰 크기(360×800)로 주요 화면을 그려 test_ux/shots/*.png 로 남긴다.
// flutter test test_ux/shots_test.dart --update-goldens
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:friendly_map/modules/app/app.dart';
import 'package:friendly_map/modules/core/core.dart';
import 'package:friendly_map/modules/platform/platform.dart';
import 'package:friendly_map/modules/storage/storage.dart';
import 'package:friendly_map/modules/transport/transport.dart';
import 'package:friendly_map/modules/ui/src/screens/chat_room_screen.dart';
import 'package:friendly_map/modules/ui/src/screens/contact_import_screen.dart';
import 'package:friendly_map/modules/ui/src/screens/group_detail_screen.dart';
import 'package:friendly_map/modules/ui/src/screens/person_screen.dart';
import 'package:friendly_map/modules/ui/src/screens/requests_screen.dart';
import 'package:friendly_map/modules/ui/src/screens/settings_screen.dart';
import 'package:friendly_map/modules/ui/ui.dart';
import '../test/support/app_device.dart';
import '../test/support/fake_cipher.dart';
import '../test/support/storage_contract.dart' show FakeProbe;
import '../test/widget_test.dart' show FakeBootstrap;
class _Contacts implements ContactsProvider {
@override
Future<bool> requestPermission() async => true;
@override
Future<List<DeviceContact>> all() async => const [
DeviceContact(id: '1', name: '김민수', phones: ['010-3333-4444'], labels: ['가족']),
DeviceContact(id: '2', name: '이영희', phones: ['010-5555-6666'], labels: ['고등학교 동창']),
DeviceContact(id: '3', name: '박철수', phones: ['010-7777-8888'], labels: ['회사']),
DeviceContact(id: '4', name: '최지은', phones: ['010-1212-3434']),
DeviceContact(id: '5', name: '정우성', phones: ['02-555-1234']),
];
}
Future<void> _font(String family, String path) async {
final bytes = File(path).readAsBytesSync();
await (FontLoader(family)..addFont(Future.value(ByteData.view(Uint8List.fromList(bytes).buffer)))).load();
}
void main() {
late AppDevice me, minsu;
late FriendlyApp app;
setUpAll(() async {
await _font('Roboto', 'build/ux/kr.ttf');
await _font('MaterialIcons', '/sdks/flutter/bin/cache/artifacts/material_fonts/MaterialIcons-Regular.otf');
});
Future<void> seed(WidgetTester tester) async {
await tester.runAsync(() async {
final hub = MemoryHub();
me = await AppDevice.create(hub, '010-1111-2222', '+821011112222', '이미영', contacts: _Contacts());
minsu = await AppDevice.create(hub, '010-3333-4444', '+821033334444', '김민수');
app = me.app;
await app.friends.add(minsu.phone, minsu.name);
await AppDevice.settleAll();
await minsu.app.friends.accept(me.phone);
await AppDevice.settleAll();
for (final (p, n) in [('+821055556666', '이영희'), ('+821077778888', '박철수'), ('+821012123434', '최지은')]) {
await app.friends.add(p, n);
}
final people = {for (final p in await app.friends.people()) p.name: p.id};
await app.relate.into(people['이영희']!, 'school.high');
final hb = (await app.groups.add('한빛전자', CardKinds.company, parent: CardKinds.company))!;
final team = (await app.groups.add('결제팀', CardKinds.company, parent: hb.id))!;
await app.relate.into(people['박철수']!, team.id);
await app.relate.into(people['김민수']!, team.id);
final room = (await app.chats.openDirect(people['김민수']!, CardKinds.personal))!;
await app.chats.send(room.id, '안녕하세요, 내일 회의 몇 시죠?');
await app.work.assign(room.id, '결제 API 정리', assigneeId: people['김민수'], due: DateTime(2026, 10, 30));
await app.work.urgent(room.id, '결제 서버가 멈췄어요');
// 김민수가 새 폰으로 다시 연결을 청함
final again = await AppDevice.create(hub, '010-3333-4444', '+821033334444', '김민수 새폰');
await again.app.friends.add(me.phone, '이미영');
await AppDevice.settleAll();
});
}
Future<void> open(WidgetTester tester) async {
tester.view.physicalSize = const Size(1080, 2400);
tester.view.devicePixelRatio = 3;
addTearDown(tester.view.reset);
await seed(tester);
await tester.pumpWidget(FriendlyMapApp(bootstrap: FakeBootstrap(keys: true, app: app)));
await tester.pumpAndSettle();
}
Future<void> shot(WidgetTester tester, String name) async {
await tester.runAsync(() => Future<void>.delayed(const Duration(milliseconds: 30)));
await tester.pumpAndSettle();
await expectLater(find.byType(MaterialApp), matchesGoldenFile('shots/$name.png'));
}
Future<void> push(WidgetTester tester, Widget page) async {
tester.state<NavigatorState>(find.byType(Navigator).first).push(MaterialPageRoute<void>(builder: (_) => page));
await tester.pumpAndSettle();
}
Future<void> tab(WidgetTester tester, String label) async {
await tester.tap(find.descendant(of: find.byType(NavigationBar), matching: find.text(label)));
await tester.pumpAndSettle();
}
testWidgets('처음 시작', (tester) async {
tester.view.physicalSize = const Size(1080, 2400);
tester.view.devicePixelRatio = 3;
addTearDown(tester.view.reset);
final fresh = FriendlyApp(AppDeps(storage: Storage.memory(), transport: MemoryTransport('+82100', MemoryHub()), cipher: FakeCipher('K'), identity: FakeIdentity('K'), probe: FakeProbe(10)));
await tester.pumpWidget(FriendlyMapApp(bootstrap: FakeBootstrap(app: fresh)));
await tester.pumpAndSettle();
await shot(tester, '00_onboarding');
});
testWidgets('아래 메뉴 다섯 칸', (tester) async {
await open(tester);
await shot(tester, '01_chats');
await tab(tester, '관계');
await shot(tester, '02_relations');
await tab(tester, '업무');
await shot(tester, '03_tasks');
await tab(tester, '명함');
await shot(tester, '04_cards');
await tab(tester, '나');
await shot(tester, '05_me');
});
testWidgets('요청 · 그룹 · 설정', (tester) async {
await open(tester);
await push(tester, const RequestsScreen());
await shot(tester, '10_requests');
await push(tester, const GroupDetailScreen(groupId: CardKinds.school));
await shot(tester, '11_group_school');
await push(tester, const GroupDetailScreen(groupId: CardKinds.company));
await shot(tester, '12_group_company');
await push(tester, const SettingsScreen());
await shot(tester, '13_settings');
});
testWidgets('주소록 · 사람 · 대화', (tester) async {
await open(tester);
await push(tester, const ContactImportScreen());
await shot(tester, '20_contacts');
final people = {for (final p in (await tester.runAsync(() => app.friends.people()))!) p.name: p.id};
await push(tester, PersonScreen(personId: people['김민수']!));
await shot(tester, '21_person');
await tester.tap(find.text('관계'));
await tester.pumpAndSettle();
await shot(tester, '22_relate');
await tester.tapAt(const Offset(10, 10));
await tester.pumpAndSettle();
final rooms = (await tester.runAsync(() => app.chats.summaries()))!;
await push(tester, ChatRoomScreen(roomId: rooms.first.room.id));
await shot(tester, '23_chat_room');
});
}