frindlymap/test/work_service_test.dart

119 lines
5.2 KiB
Dart
Raw Permalink Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

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);
});
}