330 lines
15 KiB
Dart
330 lines
15 KiB
Dart
import 'package:flutter_test/flutter_test.dart';
|
|
import 'package:friendly_map/modules/app/app.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';
|
|
|
|
const pa = '+821011112222';
|
|
const pb = '+821022223333';
|
|
|
|
Future<(AppDevice, AppDevice)> pair({String? modeB}) async {
|
|
final hub = MemoryHub();
|
|
final a = await AppDevice.create(hub, '010-1111-2222', pa, '가');
|
|
final b = await AppDevice.create(hub, '010-2222-3333', pb, '나');
|
|
if (modeB != null) await b.app.settings.update(exchangeMode: modeB);
|
|
return (a, b);
|
|
}
|
|
|
|
Future<void> befriend(AppDevice a, AppDevice b) async {
|
|
await a.app.friends.add(b.phone, b.name);
|
|
await AppDevice.settleAll();
|
|
await b.app.friends.accept(a.phone);
|
|
await AppDevice.settleAll();
|
|
}
|
|
|
|
void main() {
|
|
group('처음 시작', () {
|
|
test('번호·이름을 정하면 종류별 기본 명함 5장이 생기고, 개인 명함만 새 친구에게 기본 공유', () async {
|
|
final (a, _) = await pair();
|
|
final cards = await a.app.cards.mine();
|
|
expect(cards.map((c) => c.kind).toList(), ['personal', 'company', 'school', 'group', 'family']);
|
|
expect(cards.where((c) => c.shareDefault).map((c) => c.kind).toList(), ['personal']);
|
|
expect(decodeFields(cards.first.fieldsJson)['name'], '가');
|
|
expect((await a.app.profile.me())!.phone, pa);
|
|
});
|
|
|
|
test('올바르지 않은 번호·이름은 거절', () async {
|
|
final (a, _) = await pair();
|
|
expect(await a.app.profile.setUp('abc', '가'), null);
|
|
expect(await a.app.profile.setUp('010-1111-2222', ' '), null);
|
|
});
|
|
});
|
|
|
|
group('친구 추가와 명함 교환', () {
|
|
test('요청 후 수락하면 서로 키를 알고, 개인 명함이 서로에게 간다', () async {
|
|
final (a, b) = await pair();
|
|
final added = await a.app.friends.add(pb, '나');
|
|
expect(added!.publicKey, null);
|
|
await AppDevice.settleAll();
|
|
final req = (await b.app.friends.requests()).single;
|
|
expect(req.phone, pa);
|
|
expect(req.name, '가');
|
|
await b.app.friends.accept(pa);
|
|
await AppDevice.settleAll();
|
|
final bOfA = (await a.app.friends.person(added.id))!;
|
|
expect(bOfA.publicKey, b.key);
|
|
final aOfB = (await b.app.friends.people()).single;
|
|
expect(aOfB.publicKey, a.key);
|
|
final got = await b.app.deps.storage.receivedCards.byPerson(aOfB.id);
|
|
expect(got.single.kind, 'personal');
|
|
expect(await b.app.friends.requests(), isEmpty);
|
|
final back = await a.app.deps.storage.receivedCards.byPerson(bOfA.id);
|
|
expect(back.single.kind, 'personal');
|
|
});
|
|
|
|
test('자동 수락 설정이면 요청 없이 바로 친구가 됨', () async {
|
|
final (a, b) = await pair(modeB: 'auto');
|
|
final added = await a.app.friends.add(pb, '나');
|
|
await AppDevice.settleAll();
|
|
expect(await b.app.friends.requests(), isEmpty);
|
|
expect((await b.app.friends.people()).single.phone, pa);
|
|
expect((await a.app.friends.person(added!.id))!.publicKey, b.key);
|
|
});
|
|
|
|
test('거절하면 친구가 되지 않음', () async {
|
|
final (a, b) = await pair();
|
|
await a.app.friends.add(pb, '나');
|
|
await AppDevice.settleAll();
|
|
await b.app.friends.decline(pa);
|
|
expect(await b.app.friends.requests(), isEmpty);
|
|
expect(await b.app.friends.people(), isEmpty);
|
|
});
|
|
|
|
test('QR 로 추가하면 키를 바로 알고, 내 QR 은 읽으면 같은 정보', () async {
|
|
final (a, b) = await pair();
|
|
final qr = (await b.app.friends.myQr())!.encode();
|
|
final p = await a.app.friends.addFromQr(qr);
|
|
expect(p!.phone, pb);
|
|
expect(p.publicKey, b.key);
|
|
expect(await a.app.friends.addFromQr('https://x.y'), null);
|
|
});
|
|
|
|
test('번호 확인: 형식 오류, 내 번호, 같은 번호·이름 변경 후보', () async {
|
|
final (a, b) = await pair();
|
|
expect((await a.app.friends.check('abc', '나')).error, isNotNull);
|
|
expect((await a.app.friends.check('010-1111-2222', '나')).error, '내 번호예요');
|
|
await a.app.friends.add(pb, '나');
|
|
final r = await a.app.friends.check('010 2222 3333', '나 아님');
|
|
expect(r.match!.kind, MatchKind.nameDiffers);
|
|
final c = await a.app.friends.check('010-9999-8888', '나');
|
|
expect(c.match!.kind, MatchKind.phoneDiffers);
|
|
final same = await a.app.friends.add(c.phone!, '나', samePersonId: c.match!.candidates.first.id);
|
|
expect(same!.phone, '+821099998888');
|
|
expect(await a.app.deps.storage.people.byPhone(pb), isNotNull); // 이전 번호로도 찾아짐
|
|
expect(b.phone, pb);
|
|
});
|
|
});
|
|
|
|
group('숨기기·근처 사람', () {
|
|
test('모든 정보 숨기기를 켜면 모르는 사람의 요청은 쌓이지 않고, 아는 사람은 그대로', () async {
|
|
final (a, b) = await pair();
|
|
await b.app.settings.setHideAll(true);
|
|
expect(await b.app.settings.hideAll(), true);
|
|
await a.app.friends.add(pb, '나');
|
|
await AppDevice.settleAll();
|
|
expect(await b.app.friends.requests(), isEmpty);
|
|
await b.app.settings.setHideAll(false);
|
|
await a.app.friends.add(pb, '나');
|
|
await AppDevice.settleAll();
|
|
expect((await b.app.friends.requests()).single.phone, pa);
|
|
});
|
|
|
|
test('근처에서 번호로만 추가한 사람은 답 인사가 오면 진짜 이름으로 바뀜', () async {
|
|
final (a, b) = await pair(modeB: 'auto');
|
|
final p = await a.app.friends.add(pb, pb); // 이름 대신 번호
|
|
expect(p!.name, pb);
|
|
await AppDevice.settleAll();
|
|
expect((await a.app.friends.person(p.id))!.name, '나');
|
|
});
|
|
});
|
|
|
|
group('수락 전에 정한 공유', () {
|
|
test('상대가 수락하기 전에 고른 회사 명함도 수락 뒤에 전달됨', () async {
|
|
final (a, b) = await pair();
|
|
final added = await a.app.friends.add(pb, '나');
|
|
final company = (await a.app.cards.mine()).firstWhere((c) => c.kind == 'company');
|
|
await a.app.cards.shareWith(added!.id, [company.id]); // 아직 키를 모름
|
|
await AppDevice.settleAll();
|
|
await b.app.friends.accept(pa);
|
|
await AppDevice.settleAll();
|
|
final aOfB = (await b.app.friends.people()).single;
|
|
final kinds = (await b.app.network.receivedCards(aOfB.id)).map((c) => c.kind).toSet();
|
|
expect(kinds, {'personal', 'company'});
|
|
});
|
|
});
|
|
|
|
group('근처 사람', () {
|
|
test('발견한 사람이 보이고, 번호로 추가하면 친구 목록에 들어가며 나 자신은 빠짐', () async {
|
|
final lan = FakeLan();
|
|
final hub = MemoryHub();
|
|
final a = await AppDevice.create(hub, '010-1111-2222', pa, '가', lan: lan);
|
|
await AppDevice.create(hub, '010-2222-3333', pb, '나');
|
|
lan.ctl.add(const LanPeer(phone: pa, host: '10.0.0.1', port: 1));
|
|
lan.ctl.add(const LanPeer(phone: pb, host: '10.0.0.2', port: 2));
|
|
final near = await a.app.friends.nearby();
|
|
expect(near.map((e) => e.phone).toList(), [pb]);
|
|
expect(near.single.known, null);
|
|
final p = await a.app.friends.addNearby(pb);
|
|
expect(p!.name, pb);
|
|
expect((await a.app.friends.nearby()).single.known!.id, p.id);
|
|
});
|
|
});
|
|
|
|
group('명함 공유', () {
|
|
test('회사 명함을 골라 공유하면 상대가 받고, 고치면 다시 보내기 전까지 상대 것은 그대로', () async {
|
|
final (a, b) = await pair();
|
|
await befriend(a, b);
|
|
final bOfA = (await a.app.friends.people()).single;
|
|
final company = (await a.app.cards.mine()).firstWhere((c) => c.kind == 'company');
|
|
await a.app.cards.edit(company.id, fields: {'name': '가', 'company': '한빛'});
|
|
expect(await a.app.cards.shareWith(bOfA.id, [company.id]), 1);
|
|
expect(await a.app.cards.shareWith(bOfA.id, [company.id]), 0); // 이미 공유 중
|
|
await AppDevice.settleAll();
|
|
final aOfB = (await b.app.friends.people()).single;
|
|
var got = (await b.app.deps.storage.receivedCards.byPerson(aOfB.id)).firstWhere((c) => c.kind == 'company');
|
|
expect(decodeFields(got.fieldsJson)['company'], '한빛');
|
|
|
|
await a.app.cards.edit(company.id, fields: {'name': '가', 'company': '새빛'});
|
|
await AppDevice.settleAll();
|
|
got = (await b.app.deps.storage.receivedCards.byPerson(aOfB.id)).firstWhere((c) => c.kind == 'company');
|
|
expect(decodeFields(got.fieldsJson)['company'], '한빛'); // 아직 그대로
|
|
final need = await a.app.cards.needingResend();
|
|
expect(need.single.targetId, company.id);
|
|
expect(await a.app.cards.resend(need.single.id), true);
|
|
await AppDevice.settleAll();
|
|
got = (await b.app.deps.storage.receivedCards.byPerson(aOfB.id)).firstWhere((c) => c.kind == 'company');
|
|
expect(decodeFields(got.fieldsJson)['company'], '새빛');
|
|
expect(await a.app.cards.needingResend(), isEmpty);
|
|
});
|
|
|
|
test('명함 만들기·순서 바꾸기·지우기', () async {
|
|
final (a, _) = await pair();
|
|
final tpls = await a.app.layout.templates();
|
|
final made = (await a.app.cards.createFromTemplate(tpls[1].id))!;
|
|
expect((await a.app.cards.mine()).length, 6);
|
|
await a.app.cards.move(made.id, 0);
|
|
expect((await a.app.cards.mine()).first.id, made.id);
|
|
await a.app.cards.delete(made.id);
|
|
expect((await a.app.cards.mine()).length, 5);
|
|
expect(await a.app.cards.createFromTemplate('없는틀'), null);
|
|
});
|
|
});
|
|
|
|
group('대화', () {
|
|
test('개인 대화는 바로 되고, 주고받는 대화가 양쪽에 남음', () async {
|
|
final (a, b) = await pair();
|
|
await befriend(a, b);
|
|
final bOfA = (await a.app.friends.people()).single;
|
|
final room = (await a.app.chats.openDirect(bOfA.id, 'personal'))!;
|
|
await a.app.chats.send(room.id, '안녕하세요');
|
|
await AppDevice.settleAll();
|
|
final aRooms = await b.app.chats.summaries();
|
|
expect(aRooms.single.last!.body, '안녕하세요');
|
|
await b.app.chats.send(aRooms.single.room.id, '반가워요');
|
|
await AppDevice.settleAll();
|
|
final mine = await a.app.chats.messages(room.id);
|
|
expect(mine.map((m) => m.body).toList(), ['안녕하세요', '반가워요']);
|
|
expect(mine.first.senderId, ChatService.me);
|
|
expect(await a.app.chats.openDirect(bOfA.id, 'personal'), isNotNull);
|
|
expect((await a.app.chats.summaries()).length, 1); // 같은 방을 다시 열어도 하나
|
|
});
|
|
|
|
test('회사 대화는 회사 명함을 공유해야 열리고, 받는 쪽도 명함을 받아야 보임', () async {
|
|
final (a, b) = await pair();
|
|
await befriend(a, b);
|
|
final bOfA = (await a.app.friends.people()).single;
|
|
expect(await a.app.chats.openDirect(bOfA.id, 'company'), null);
|
|
final company = (await a.app.cards.mine()).firstWhere((c) => c.kind == 'company');
|
|
await a.app.cards.shareWith(bOfA.id, [company.id]);
|
|
final room = (await a.app.chats.openDirect(bOfA.id, 'company'))!;
|
|
await a.app.chats.send(room.id, '업무 이야기');
|
|
await AppDevice.settleAll();
|
|
final rooms = await b.app.chats.summaries();
|
|
expect(rooms.single.room.contextKind, 'company');
|
|
expect(rooms.single.last!.body, '업무 이야기');
|
|
});
|
|
|
|
test('빈 메시지·없는 방은 보내지 않음', () async {
|
|
final (a, b) = await pair();
|
|
await befriend(a, b);
|
|
final bOfA = (await a.app.friends.people()).single;
|
|
final room = (await a.app.chats.openDirect(bOfA.id, 'personal'))!;
|
|
expect(await a.app.chats.send(room.id, ' '), null);
|
|
expect(await a.app.chats.send('없는방', '안녕'), null);
|
|
});
|
|
});
|
|
|
|
group('인맥', () {
|
|
test('같은 학교 명함을 주고받으면 동창으로 추측하고, 확정하면 추천에서 빠짐', () async {
|
|
final (a, b) = await pair();
|
|
await befriend(a, b);
|
|
final bOfA = (await a.app.friends.people()).single;
|
|
final aOfB = (await b.app.friends.people()).single;
|
|
for (final d in [a, b]) {
|
|
final school = (await d.app.cards.mine()).firstWhere((c) => c.kind == 'school');
|
|
await d.app.cards.edit(school.id, fields: {'name': d.name, 'school': '가람초', 'year': '2007'});
|
|
}
|
|
final aSchool = (await a.app.cards.mine()).firstWhere((c) => c.kind == 'school');
|
|
await a.app.cards.shareWith(bOfA.id, [aSchool.id]);
|
|
await AppDevice.settleAll();
|
|
final guesses = await b.app.network.guessesFor(aOfB.id);
|
|
expect(guesses.first.relation, '동창');
|
|
final sug = await b.app.network.suggestions();
|
|
expect(sug.single.person.id, aOfB.id);
|
|
await b.app.network.addLink(aOfB.id, guesses.first.relation, guesses.first.detail);
|
|
expect(await b.app.network.suggestions(), isEmpty);
|
|
final cl = await b.app.network.clusters('school');
|
|
expect(cl.single.people.single.id, aOfB.id);
|
|
expect((await b.app.network.links(aOfB.id)).single.confirmed, true);
|
|
final recv = await b.app.network.receivedCards(aOfB.id);
|
|
expect(recv.map((c) => c.kind).toSet(), {'personal', 'school'});
|
|
await b.app.network.deleteReceivedCard(recv.first.id);
|
|
expect((await b.app.network.receivedCards(aOfB.id)).length, 1);
|
|
});
|
|
|
|
test('가족 명함을 받으면 가족 목록에 나옴', () async {
|
|
final (a, b) = await pair();
|
|
await befriend(a, b);
|
|
final bOfA = (await a.app.friends.people()).single;
|
|
final fam = (await a.app.cards.mine()).firstWhere((c) => c.kind == 'family');
|
|
await a.app.cards.edit(fam.id, fields: {'name': '가', 'relation': '형'});
|
|
await a.app.cards.shareWith(bOfA.id, [fam.id]);
|
|
await AppDevice.settleAll();
|
|
final members = await b.app.network.family();
|
|
expect(members.single.relation, '형');
|
|
});
|
|
});
|
|
|
|
group('설정·배치', () {
|
|
test('설정은 범위 안으로 맞춰지고, 복구 조각 수는 필요한 수보다 작아지지 않음', () async {
|
|
final (a, _) = await pair();
|
|
var s = await a.app.settings.update(storageUsagePercent: 99, recoveryShares: 4, recoveryThreshold: 9);
|
|
expect(s.storageUsagePercent, 95);
|
|
expect(s.recoveryShares, 4);
|
|
expect(s.recoveryThreshold, 4);
|
|
s = await a.app.settings.update(recoveryShares: 2);
|
|
expect(s.recoveryThreshold, 2);
|
|
expect((await a.app.settings.load()).exchangeMode, 'request');
|
|
});
|
|
|
|
test('홈 구성·명함 틀 편집이 저장되고 변경 알림이 감', () async {
|
|
final (a, _) = await pair();
|
|
var n = 0;
|
|
a.app.changes.listen((_) => n++);
|
|
await a.app.layout.moveHome(0, 2);
|
|
await a.app.layout.removeHome('family');
|
|
expect((await a.app.layout.home()).any((e) => e.id == 'family'), false);
|
|
await a.app.layout.resetHome();
|
|
expect((await a.app.layout.home()).first.id, 'chats');
|
|
expect(n >= 3, true);
|
|
});
|
|
|
|
test('대화가 1MB 를 넘으면 별도 저장을 권하고 범위를 나눌 수 있음', () async {
|
|
final (a, b) = await pair();
|
|
await befriend(a, b);
|
|
final bOfA = (await a.app.friends.people()).single;
|
|
final room = (await a.app.chats.openDirect(bOfA.id, 'personal'))!;
|
|
for (var i = 0; i < 3; i++) {
|
|
await a.app.chats.send(room.id, 'x' * 400000);
|
|
}
|
|
expect((await a.app.settings.adviseRoom(room.id)).overText, true);
|
|
final span = (await a.app.settings.selectableSpan(room.id))!;
|
|
expect(await a.app.settings.archiveRange(room.id, span.$1, span.$1), 1);
|
|
expect((await a.app.settings.adviseRoom(room.id)).overText, false);
|
|
expect((await a.app.chats.messages(room.id)).length, 2);
|
|
});
|
|
});
|
|
}
|