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/groups/groups.dart'; import 'package:friendly_map/modules/kinship/kinship.dart'; import 'package:friendly_map/modules/storage/storage.dart'; import 'package:friendly_map/modules/transport/transport.dart'; import 'package:friendly_map/modules/visibility/visibility.dart'; import 'support/app_device.dart'; void main() { late AppDevice me; late RelateService relate; var n = 0; setUp(() async { me = await AppDevice.create(MemoryHub(), '010-1111-2222', '+821011112222', '나'); relate = me.app.relate; await me.app.kin.setMe(gender: Gender.male, birthYear: 1990); }); Future person(String name) async => (await me.app.friends.add('+8210${(5000 + n++).toString().padLeft(4, '0')}0000', name))!; Future> membersOf(String groupId) async => [for (final p in (await me.app.groups.members(groupId))!) p.name]; Future> linksOf(Person p) => me.app.network.links(p.id); group('가족', () { test('아버지는 가족 그룹, 아버지의 아버지는 친가, 촌수와 호칭이 맞는다', () async { final dad = await person('아빠'); final r = (await relate.asFamily(dad.id, link: KinLink.parent, gender: Gender.male))!; expect(r.groupId, CardKinds.family); expect(r.relation!.title, '아버지'); expect(r.relation!.chon, 1); final gp = await person('할배'); final r2 = (await relate.asFamily(gp.id, link: KinLink.parent, to: dad.id, gender: Gender.male))!; expect(r2.groupId, 'family.paternal'); expect(r2.groupPath, '가족 › 친가'); expect(r2.relation!.title, contains('할아버지')); expect(r2.relation!.chon, 2); expect(await membersOf('family.paternal'), ['할배']); final links = await linksOf(dad); expect(links.map((l) => '${l.relation}:${l.detail}'), ['가족:아버지']); }); test('어머니의 형제(부모를 몰라도)는 외가 외삼촌 3촌, 이름 모를 부모가 생긴다', () async { final mom = await person('엄마'); await relate.asFamily(mom.id, link: KinLink.parent, gender: Gender.female); final uncle = await person('외삼촌'); final r = (await relate.asFamily(uncle.id, link: KinLink.sibling, to: mom.id, gender: Gender.male))!; expect(r.groupId, 'family.maternal'); expect(r.relation!.title, '외삼촌'); expect(r.relation!.chon, 3); final g = await me.app.kin.graph(); final shared = g.parentsOf(mom.id); expect(shared, g.parentsOf(uncle.id)); expect((await me.app.friends.person(shared.single))!.name, RelateService.placeholderParent); }); test('아내는 가족, 아내의 아버지는 처가·시가 장인', () async { final wife = await person('아내'); expect((await relate.asFamily(wife.id, link: KinLink.spouse, gender: Gender.female))!.groupId, CardKinds.family); final fil = await person('장인어른'); final r = (await relate.asFamily(fil.id, link: KinLink.parent, to: wife.id, gender: Gender.male))!; expect(r.groupId, 'family.inlaw'); expect(r.relation!.title, '장인'); }); test('촌수를 모르면 친척 모음에, 나중에 이으면 모음에서 빠진다', () async { final x = await person('먼 친척'); final r = (await relate.asFamily(x.id))!; expect(r.groupId, Group.unknownRelatives); expect(await membersOf(Group.unknownRelatives), ['먼 친척']); expect((await linksOf(x)).single.detail, '촌수 모름'); await relate.asFamily(x.id, link: KinLink.child, gender: Gender.female); expect(await membersOf(Group.unknownRelatives), isEmpty); expect((await linksOf(x)).single.detail, '딸'); }); test('가계도에 이을 수 없으면 null (부모가 이미 둘)', () async { await relate.asFamily((await person('부1')).id, link: KinLink.parent, gender: Gender.male); await relate.asFamily((await person('부2')).id, link: KinLink.parent, gender: Gender.female); expect(await relate.asFamily((await person('부3')).id, link: KinLink.parent), isNull); }); test('쪽을 모르면(부모 성별 모름) 가족 그룹에 둔다', () async { final p = await person('부모'); await relate.asFamily(p.id, link: KinLink.parent); final gp = await person('조부모'); expect((await relate.asFamily(gp.id, link: KinLink.parent, to: p.id))!.groupId, CardKinds.family); }); }); group('학교 · 회사 · 모임', () { test('고등학교에 넣으면 동문 연결 고리가 생기고, 공개 범위가 동문으로 적용된다', () async { final a = await person('이영희'); final r = (await relate.into(a.id, 'school.high'))!; expect(r.groupPath, '학교 › 고등학교'); expect((await linksOf(a)).map((l) => '${l.relation}:${l.detail}'), ['동문:학교 › 고등학교']); expect(VAudience.ofRelation((await linksOf(a)).single.relation), VAudience.school); expect(await relate.placesOf(a.id), ['학교 › 고등학교']); }); test('회사 › 한빛전자 › 결제팀에 넣으면 직장 동료, 빼면 연결 고리도 지운다', () async { final hb = (await me.app.groups.add('한빛전자', CardKinds.company, parent: CardKinds.company))!; final team = (await me.app.groups.add('결제팀', CardKinds.company, parent: hb.id))!; final b = await person('박철수'); await relate.into(b.id, team.id); await relate.into(b.id, hb.id); expect((await linksOf(b)).single.detail, '회사 › 한빛전자', reason: '같은 종류는 연결 고리 하나만, 마지막 근거로'); await relate.leave(b.id, team.id); expect(await linksOf(b), isNotEmpty, reason: '한빛전자에 아직 있다'); await relate.leave(b.id, hb.id); expect(await linksOf(b), isEmpty); }); test('닫힌 잠긴 그룹에는 넣을 수 없다', () async { await me.app.groups.setPin(CardKinds.group, '1234'); me.app.groups.lockAll(); expect(await relate.into((await person('누구')).id, CardKinds.group), isNull); }); }); }