119 lines
5.2 KiB
Dart
119 lines
5.2 KiB
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/transport/transport.dart';
|
||
import 'package:friendly_map/modules/work/work.dart';
|
||
|
||
import 'support/app_device.dart';
|
||
|
||
class FakeInstant implements InstantNotifier {
|
||
final shown = <String>[];
|
||
@override
|
||
Future<void> showNow(String title, String text) async => shown.add('$title|$text');
|
||
}
|
||
|
||
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();
|
||
}
|
||
|
||
Future<void> shareCompany(AppDevice from, AppDevice to) async {
|
||
final peer = (await from.app.deps.storage.people.byPhone(to.phone))!;
|
||
final company = (await from.app.cards.mine()).firstWhere((c) => c.kind == CardKinds.company);
|
||
await from.app.cards.shareWith(peer.id, [company.id]);
|
||
await AppDevice.settleAll();
|
||
}
|
||
|
||
void main() {
|
||
late AppDevice a, b, c;
|
||
late FakeInstant bAlerts;
|
||
|
||
setUp(() async {
|
||
final hub = MemoryHub();
|
||
bAlerts = FakeInstant();
|
||
a = await AppDevice.create(hub, '010-1111-2222', '+821011112222', '팀장');
|
||
b = await AppDevice.create(hub, '010-2222-3333', '+821022223333', '김민수', instant: bAlerts);
|
||
c = await AppDevice.create(hub, '010-3333-4444', '+821033334444', '이영희');
|
||
await befriend(a, b);
|
||
await befriend(a, c);
|
||
});
|
||
|
||
Future<String> team(List<AppDevice> members) async {
|
||
final hb = (await a.app.groups.add('한빛전자', CardKinds.company, parent: CardKinds.company))!;
|
||
final t = (await a.app.groups.add('결제팀', CardKinds.company, parent: hb.id))!;
|
||
final ids = [for (final m in members) (await a.app.deps.storage.people.byPhone(m.phone))!.id];
|
||
await a.app.groups.addMembers(t.id, ids);
|
||
return t.id;
|
||
}
|
||
|
||
test('팀 대화방: 회사 명함을 공유하지 않은 사람이 있으면 알려 주고, 모두 공유하면 방이 생긴다', () async {
|
||
final t = await team([b, c]);
|
||
await shareCompany(a, b);
|
||
final r1 = await a.app.work.teamRoom(t);
|
||
expect(r1.room, isNull);
|
||
expect(r1.missing.map((p) => p.name), ['이영희']);
|
||
await shareCompany(a, c);
|
||
final r2 = await a.app.work.teamRoom(t);
|
||
expect(r2.room!.title, '회사 › 한빛전자 › 결제팀');
|
||
expect(r2.room!.contextKind, CardKinds.company);
|
||
expect((await a.app.work.teamRoom(t)).room!.id, r2.room!.id, reason: '두 번째부터는 같은 방');
|
||
expect(await a.app.work.groupOfRoom(r2.room!.id), t);
|
||
});
|
||
|
||
test('업무를 맡기면 내 목록에 들어가고, 받는 쪽 목록에도 "내 업무"로 들어간다', () async {
|
||
final t = await team([b, c]);
|
||
await shareCompany(a, b);
|
||
await shareCompany(a, c);
|
||
final room = (await a.app.work.teamRoom(t)).room!;
|
||
await AppDevice.settleAll();
|
||
final bId = (await a.app.deps.storage.people.byPhone(b.phone))!.id;
|
||
final task = (await a.app.work.assign(room.id, '결제 API 정리', assigneeId: bId, due: DateTime(2026, 10, 30)))!;
|
||
expect(task.assigneeName, '김민수');
|
||
expect((await a.app.work.tasks(roomId: room.id)).single.title, '결제 API 정리');
|
||
await AppDevice.settleAll();
|
||
|
||
final mine = await b.app.work.tasks(onlyMine: true);
|
||
expect(mine.single.title, '결제 API 정리');
|
||
expect(mine.single.due, DateTime(2026, 10, 30));
|
||
final cTasks = await c.app.work.tasks();
|
||
expect(cTasks.single.assigneeName, '김민수');
|
||
expect(cTasks.single.mine, isFalse);
|
||
|
||
await b.app.work.setDone(mine.single.id, true);
|
||
expect(await b.app.work.tasks(onlyMine: true), isEmpty);
|
||
expect((await b.app.work.tasks(includeDone: true)).single.done, isTrue);
|
||
});
|
||
|
||
test('긴급 호출은 받는 쪽에서 바로 알림이 뜨고, 보통 대화는 뜨지 않는다', () async {
|
||
await shareCompany(a, b);
|
||
final bOfA = (await a.app.deps.storage.people.byPhone(b.phone))!;
|
||
final room = (await a.app.chats.openDirect(bOfA.id, CardKinds.company))!;
|
||
await a.app.chats.send(room.id, '보통 대화');
|
||
await a.app.work.urgent(room.id, '서버가 멈췄어요');
|
||
await AppDevice.settleAll();
|
||
expect(bAlerts.shown, ['🚨 긴급 호출 · 팀장|서버가 멈췄어요']);
|
||
expect(await a.app.work.tasks(), isEmpty);
|
||
});
|
||
|
||
test('지난 대화를 업무로 정리하기 (같은 대화는 한 번만)', () async {
|
||
final bOfA = (await a.app.deps.storage.people.byPhone(b.phone))!;
|
||
final room = (await a.app.chats.openDirect(bOfA.id, CardKinds.personal))!;
|
||
final m = (await a.app.chats.send(room.id, '금요일까지 견적서 보내 주세요'))!;
|
||
final t = (await a.app.work.fromMessage(m.id, assigneeId: Task.me))!;
|
||
expect(t.title, '금요일까지 견적서 보내 주세요');
|
||
expect(t.mine, isTrue);
|
||
expect(await a.app.work.fromMessage(m.id), isNull);
|
||
expect(WorkService.noteOf('🚨 긴급 호출: x'), isA<UrgentNote>());
|
||
});
|
||
|
||
test('닫힌 잠긴 그룹은 팀 대화방을 만들 수 없다', () async {
|
||
final t = await team([b]);
|
||
await a.app.groups.setPin(CardKinds.company, '1234');
|
||
a.app.groups.lockAll();
|
||
expect((await a.app.work.teamRoom(t)).closed, isTrue);
|
||
});
|
||
}
|