frindlymap/test/family_gathering_test.dart

196 lines
8.8 KiB
Dart

import 'package:flutter_test/flutter_test.dart';
import 'package:friendly_map/modules/app/app.dart';
import 'package:friendly_map/modules/events/events.dart';
import 'package:friendly_map/modules/kinship/kinship.dart';
import 'package:friendly_map/modules/platform/platform.dart';
import 'package:friendly_map/modules/transport/transport.dart';
import 'support/app_device.dart';
class FakeLog implements CallLogProvider {
FakeLog(this.entries);
final List<CallLogEntry> entries;
@override
Future<List<CallLogEntry>> forNumber(String number, {int limit = 200}) async => entries;
}
class FakePhone implements PhoneActions {
final dialed = <String>[];
final texted = <String>[];
@override
Future<bool> dial(String number) async {
dialed.add(number);
return true;
}
@override
Future<bool> sms(String number) async {
texted.add(number);
return true;
}
}
class FakeNotifier implements Notifier {
List<ScheduledNotice> last = [];
@override
Future<void> replaceAll(List<ScheduledNotice> notices) async => last = notices;
}
void main() {
late AppDevice me;
late FakeNotifier notifier;
late FakePhone phone;
setUp(() async {
notifier = FakeNotifier();
phone = FakePhone();
me = await AppDevice.create(MemoryHub(), '010-1111-2222', '+821011112222', '나',
notifier: notifier,
phone: phone,
callLog: FakeLog([
CallLogEntry('+821033334444', DateTime(2026, 10, 1, 19, 10), 600, CallKind.outgoing),
CallLogEntry('+821033334444', DateTime(2026, 10, 9, 19, 30), 120, CallKind.incoming),
CallLogEntry('+821033334444', DateTime(2026, 10, 12, 9, 0), 0, CallKind.missed),
]));
});
group('촌수 알려주기', () {
test('번호 없는 친척도 가계도에 넣고, 나와 내 자식 눈으로 본 관계를 알려 준다', () async {
final k = me.app.kin;
await k.setMe(gender: Gender.male, birthYear: 1990);
final father = (await k.addRelative('아버지', gender: Gender.male, birthYear: 1960))!;
final uncle = (await k.addRelative('큰아버지', gender: Gender.male, birthYear: 1955))!;
final cousin = (await k.addRelative('사촌형', gender: Gender.male, birthYear: 1985))!;
final gf = (await k.addRelative('할아버지', gender: Gender.male, birthYear: 1930))!;
final son = (await k.addRelative('철수', gender: Gender.male, birthYear: 2020))!;
expect(await k.setParent('me', father.id), true);
expect(await k.setParent(father.id, gf.id), true);
expect(await k.setParent(uncle.id, gf.id), true);
expect(await k.setParent(cousin.id, uncle.id), true);
expect(await k.setParent(son.id, 'me'), true);
final r = await k.relationOf(cousin.id);
expect(r.title, '친사촌 형');
expect(r.chon, 4);
final views = await k.explain(cousin.id);
expect(views.map((v) => v.whose).toList(), ['나', '철수']);
expect(views[1].relation.title, '당숙');
expect(views[1].relation.chon, 5);
final list = await k.everyone();
final chons = list.map((e) => e.relation.chon ?? 99).toList();
expect(chons.first, 1); // 가까운 촌수가 맨 앞
expect(chons, [...chons]..sort());
});
test('잘못된 번호는 거절, 같은 번호는 한 번만', () async {
expect(await me.app.kin.addRelative('x', phone: '12'), isNull);
expect(await me.app.kin.addRelative(' '), isNull);
expect(await me.app.kin.addRelative('고모', phone: '010-5555-6666'), isNotNull);
expect(await me.app.kin.addRelative('고모2', phone: '01055556666'), isNull);
});
test('다시 열어도 가계도가 남아 있다', () async {
final f = (await me.app.kin.addRelative('엄마', gender: Gender.female))!;
await me.app.kin.setParent('me', f.id);
expect((await me.app.kin.relationOf(f.id)).title, '어머니');
expect(await me.app.kin.inTree(f.id), true);
await me.app.kin.exclude(f.id);
expect((await me.app.kin.relationOf(f.id)).related, false);
});
});
group('사람 정보와 통화', () {
test('통화 요약: 횟수·시간·자주 받는 시간대, 바로 전화·문자', () async {
final p = (await me.app.friends.add('+821033334444', '삼촌'))!;
final s = await me.app.calls.summary(p.id);
expect(s.total, 3);
expect(s.missed, 1);
expect(s.totalSeconds, 720);
expect(s.windows.first.fromHour, 19);
expect(await me.app.calls.call(p.id), true);
expect(await me.app.calls.sms(p.id), true);
expect(phone.dialed, ['+821033334444']);
expect(phone.texted, ['+821033334444']);
});
test('번호 없는 친척은 걸 수 없고 요약도 비어 있다', () async {
final r = (await me.app.kin.addRelative('먼 친척'))!;
expect(await me.app.calls.reachable(r.id), false);
expect(await me.app.calls.call(r.id), false);
expect((await me.app.calls.summary(r.id)).total, 0);
});
test('생일·돌아가신 날 기록, 주제·메모', () async {
final r = (await me.app.kin.addRelative('할머니'))!;
await me.app.facts.save(r.id, const PersonFacts(birthMonth: 5, birthDay: 3, topics: ['안부', '제사'], memo: '저녁에 편함'));
var f = await me.app.facts.get(r.id);
expect(f.hasBirthday, true);
expect(f.deceased, false);
expect(f.topics, ['안부', '제사']);
await me.app.facts.setDeceased(r.id, year: 2020, month: 2, day: 14);
f = await me.app.facts.get(r.id);
expect(f.deceased, true);
expect(f.deceasedText, '2020.2.14');
expect(f.topics, ['안부', '제사']); // 다른 값은 그대로
await me.app.facts.setDeceased(r.id); // 해제
expect((await me.app.facts.get(r.id)).deceased, false);
expect(() => me.app.facts.save(r.id, const PersonFacts(birthMonth: 2, birthDay: 30)), throwsArgumentError);
expect(() => me.app.facts.save(r.id, const PersonFacts(birthMonth: 2)), throwsArgumentError);
});
});
group('일정 알림', () {
test('기본은 하루 전과 당일, 설정에 적은 날짜대로 예약이 바뀐다', () async {
final r = (await me.app.kin.addRelative('엄마'))!;
final soon = DateTime.now().add(const Duration(days: 10));
await me.app.facts.save(r.id, PersonFacts(birthMonth: soon.month, birthDay: soon.day));
expect(await me.app.events.leadDays(), [1, 0]);
expect(await me.app.events.reschedule(), 2);
expect(notifier.last.length, 2);
expect(notifier.last.first.text, '내일 엄마 생일입니다');
await me.app.events.setLeadDays('1일 전, 2일 전, 7일 전');
expect(await me.app.events.leadDays(), [7, 2, 1]);
expect(notifier.last.map((n) => n.text).toList(),
['7일 뒤 엄마 생일입니다', '2일 뒤 엄마 생일입니다', '내일 엄마 생일입니다']);
});
test('돌아가신 분은 생일 대신 기일, 표시 설정', () async {
final r = (await me.app.kin.addRelative('할아버지'))!;
final soon = DateTime.now().add(const Duration(days: 3));
await me.app.facts.save(
r.id, PersonFacts(birthMonth: 1, birthDay: 1, deceasedYear: 2015, deceasedMonth: soon.month, deceasedDay: soon.day));
final list = await me.app.events.forPerson(r.id);
expect(list.length, 1);
expect(list.first.upcoming.event.kind, EventKind.memorial);
expect(list.first.text, '할아버지 기일');
expect(list.first.upcoming.years, soon.year - 2015);
expect((await me.app.events.soon(withinDays: 5)).length, 1);
expect(await me.app.events.showDeceased(), true);
await me.app.events.setShowDeceased(false);
expect(await me.app.events.showDeceased(), false);
});
test('음력 기일: 음력 날짜가 양력으로 바뀌어 알림이 잡힌다', () async {
final r = (await me.app.kin.addRelative('할아버지'))!;
final target = DateTime.now().add(const Duration(days: 20));
final l = solarToLunar(target)!;
await me.app.facts.setDeceased(r.id, year: 2015, month: l.month, day: l.day, lunar: true);
final list = await me.app.events.forPerson(r.id, withinDays: 40);
expect(list.length, 1);
final d = list.first.upcoming.date;
expect(DateTime(d.year, d.month, d.day).difference(DateTime(target.year, target.month, target.day)).inDays.abs() <= 1, true);
expect(list.first.text, '할아버지 기일(음력)');
expect((await me.app.facts.get(r.id)).deceasedText.startsWith('음력 2015.'), true);
expect(() => me.app.facts.save(r.id, const PersonFacts(birthMonth: 13, birthDay: 1, birthLunar: true)), throwsArgumentError);
});
test('알림 부품이 없으면 예약 0건', () async {
final bare = await AppDevice.create(MemoryHub(), '010-7777-8888', '+821077778888', '무');
expect(bare.app.events.canNotify, false);
expect(await bare.app.events.reschedule(), 0);
});
});
}