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 'support/app_device.dart'; class FakeContacts implements ContactsProvider { FakeContacts(this.list, {this.allow = true}); final List list; final bool allow; @override Future requestPermission() async => allow; @override Future> all() async => allow ? list : const []; } const book = [ DeviceContact(id: '1', name: '김민수', phones: ['02-555-1234', '010-3333-4444'], labels: ['가족']), DeviceContact(id: '2', name: '이영희', phones: ['010 5555 6666'], labels: ['고등학교 동창']), DeviceContact(id: '3', name: '박철수', phones: ['+82 10-7777-8888'], labels: ['고등학교 동창', '회사']), DeviceContact(id: '4', name: '번호없음', phones: ['1234']), DeviceContact(id: '5', name: '나 자신', phones: ['010-1111-2222']), DeviceContact(id: '6', name: 'Alice Kim', phones: ['010-9999-0000']), ]; void main() { late MemoryHub hub; late AppDevice me; setUp(() async { hub = MemoryHub(); me = await AppDevice.create(hub, '010-1111-2222', '+821011112222', '나', contacts: FakeContacts(book)); }); test('번호를 고를 때 휴대폰을 먼저, 읽을 수 없는 번호와 내 번호는 가져올 수 없다', () async { final all = await me.app.contacts.load(); ContactCandidate by(String name) => all.firstWhere((c) => c.name == name); expect(by('김민수').phone, '+821033334444'); expect(by('번호없음').importable, isFalse); expect(by('나 자신').isMe, isTrue); expect(by('나 자신').importable, isFalse); expect(by('Alice Kim').importable, isTrue); }); test('거르기: 이름·초성·번호·주소록 그룹·이미 있는 사람 빼기', () async { await me.app.friends.add('+821055556666', '이영희'); final all = await me.app.contacts.load(); List names(ContactFilter f) => ContactImportService.filter(all, f).map((c) => c.name).toList(); expect(names(const ContactFilter(query: '민수')), ['김민수']); expect(names(const ContactFilter(query: 'ㄱㅁㅅ')), ['김민수']); expect(names(const ContactFilter(query: 'alice')), ['Alice Kim']); expect(names(const ContactFilter(query: '7777')), ['박철수']); expect(names(const ContactFilter(query: '77')), isEmpty, reason: '번호는 세 자리 이상부터'); expect(names(const ContactFilter(label: '고등학교 동창')), ['박철수', '이영희']); expect(names(const ContactFilter(label: '고등학교 동창', hideKnown: true)), ['박철수']); expect(ContactImportService.labels(all), ['가족', '고등학교 동창', '회사']); }); test('한 명 가져오기: 인맥에 들어가고 고른 그룹에 들어간다, 친구 요청은 가지 않는다', () async { final all = await me.app.contacts.load(); final r = await me.app.contacts.import([all.firstWhere((c) => c.name == '김민수')], groupIds: {CardKinds.family}); expect(r.added, 1); expect(r.grouped, 1); expect(r.requested, 0); final p = (await me.app.deps.storage.people.byPhone('+821033334444'))!; expect(p.name, '김민수'); expect((await me.app.groups.members(CardKinds.family))!.map((x) => x.id), [p.id]); expect(await me.app.deps.storage.outbox.pending(), isEmpty); }); test('여러 명을 한꺼번에: 이미 있는 사람은 다시 만들지 않고, 못 가져오는 사람은 건너뛴다', () async { await me.app.friends.add('+821055556666', '이영희'); final before = (await me.app.deps.storage.people.all()).length; final all = await me.app.contacts.load(); final r = await me.app.contacts.import([...all, ...all], groupIds: {CardKinds.school, CardKinds.company}); expect(r.added, 3, reason: '김민수, 박철수, Alice Kim'); expect(r.existing, 1, reason: '이영희'); expect(r.skipped, 4, reason: '번호없음·나 자신 두 번씩'); expect(r.grouped, 8); expect((await me.app.deps.storage.people.all()).length, before + 3); expect((await me.app.groups.members(CardKinds.school))!.length, 4); }); test('친구 요청도 보내기를 켜면 가져오면서 인사를 보낸다', () async { final friend = await AppDevice.create(hub, '010-3333-4444', '+821033334444', '김민수'); final all = await me.app.contacts.load(); final r = await me.app.contacts.import([all.firstWhere((c) => c.name == '김민수')], sendRequest: true); expect(r.requested, 1); await AppDevice.settleAll(); final reqs = await friend.app.friends.requests(); expect(reqs.map((q) => q.id), ['+821011112222']); }); test('잠긴 그룹이 닫혀 있으면 가져와도 그 그룹에는 들어가지 않는다', () async { await me.app.groups.setPin(CardKinds.family, '1234'); me.app.groups.lockAll(); final all = await me.app.contacts.load(); final r = await me.app.contacts.import([all.firstWhere((c) => c.name == '김민수')], groupIds: {CardKinds.family}); expect(r.added, 1); expect(r.grouped, 0); }); test('주소록 권한이 없거나 주소록이 없는 기기면 빈 목록', () async { final no = await AppDevice.create(hub, '010-2222-3333', '+821022223333', '권한없음', contacts: FakeContacts(book, allow: false)); expect(await no.app.contacts.requestPermission(), isFalse); expect(await no.app.contacts.load(), isEmpty); final none = await AppDevice.create(hub, '010-4444-5555', '+821044445555', '주소록없음'); expect(none.app.contacts.available, isFalse); expect(await none.app.contacts.load(), isEmpty); }); test('번호 표준 형태 확인', () { expect(bestPhone(['02-555-1234']), '+8225551234'); expect(bestPhone(['없음']), isNull); expect(normalizePhone('010 5555 6666'), '+821055556666'); }); }