이클립스 사전 경고 연출 · 브리핑 출처·게시시각 · PASSPORT 역사적 사건 Stamp

This commit is contained in:
Sn-Kinos
2026-10-08 15:43:12 +09:00
parent 62b9637db9
commit 586039da0a
26 changed files with 1223 additions and 1013 deletions
+105 -24
View File
@@ -48,20 +48,34 @@ class _Backend extends Backend {
class _PersonalHistory extends SamplePlanetRepository {
final scopes = <bool>[];
@override
Future<PlanetHistoryPage> history({String? cursor, bool personal = false}) async {
Future<PlanetHistoryPage> history({
String? cursor,
bool personal = false,
}) async {
scopes.add(personal);
return PlanetHistoryPage(items: [PlanetHistoryEntry(
id: 'one', kind: personal ? PlanetHistoryKind.zap : PlanetHistoryKind.evolution,
occurredAt: DateTime.utc(2026, 9, 22), fromStage: personal ? null : 1,
toStage: personal ? null : 2, amount: personal ? 37 : null,
)], nextCursor: personal ? null : 'older');
return PlanetHistoryPage(
items: [
PlanetHistoryEntry(
id: 'one',
kind: personal ? PlanetHistoryKind.zap : PlanetHistoryKind.evolution,
occurredAt: DateTime.utc(2026, 9, 22),
fromStage: personal ? null : 1,
toStage: personal ? null : 2,
amount: personal ? 37 : null,
),
],
nextCursor: personal ? null : 'older',
);
}
}
class _History extends SamplePlanetRepository {
final cursors = <String?>[];
@override
Future<PlanetHistoryPage> history({String? cursor, bool personal = false}) async {
Future<PlanetHistoryPage> history({
String? cursor,
bool personal = false,
}) async {
cursors.add(cursor);
if (cursors.length == 2) throw StateError('private details');
return PlanetHistoryPage(
@@ -83,9 +97,11 @@ class _History extends SamplePlanetRepository {
void main() {
testWidgets('내 활동 전환은 이전 목록과 커서를 지우고 실제 성장량을 표시한다', (tester) async {
final repository = _PersonalHistory();
await tester.pumpWidget(MaterialApp(home: PlanetHistoryScreen(
repository: repository, fandomName: '팬덤',
)));
await tester.pumpWidget(
MaterialApp(
home: PlanetHistoryScreen(repository: repository, fandomName: '팬덤'),
),
);
await tester.pumpAndSettle();
await tester.tap(find.text('내 활동'));
await tester.pumpAndSettle();
@@ -101,10 +117,15 @@ void main() {
const repository = SamplePlanetRepository();
final states = StreamController<PlanetVisualState>.broadcast();
addTearDown(states.close);
await tester.pumpWidget(MaterialApp(home: PlanetDetailScreen(
repository: repository, eclipse: const NoEclipseRepository(),
watchPlanet: (_) => states.stream,
)));
await tester.pumpWidget(
MaterialApp(
home: PlanetDetailScreen(
repository: repository,
eclipse: const NoEclipseRepository(),
watchPlanet: (_) => states.stream,
),
),
);
await tester.pumpAndSettle();
states.add(const PlanetVisualState(stage: 1));
await tester.pumpAndSettle();
@@ -114,7 +135,12 @@ void main() {
await tester.pump(const Duration(seconds: 4));
await tester.tap(find.text('PASSPORT 기록 보기'));
await tester.pumpAndSettle();
expect(tester.widget<PlanetHistoryScreen>(find.byType(PlanetHistoryScreen)).repository, same(repository));
expect(
tester
.widget<PlanetHistoryScreen>(find.byType(PlanetHistoryScreen))
.repository,
same(repository),
);
await tester.pumpWidget(const SizedBox());
});
@@ -131,26 +157,54 @@ void main() {
'nextCursor': null,
};
await expectLater(repository.history(), throwsStateError);
backend.response = {'items': [{'id': 'zap', 'kind': 'zap',
'occurredAt': '2026-09-22T00:00:00Z', 'amount': 37, 'participationConfirmed': true}], 'nextCursor': null};
backend.response = {
'items': [
{
'id': 'zap',
'kind': 'zap',
'occurredAt': '2026-09-22T00:00:00Z',
'amount': 37,
'participationConfirmed': true,
},
],
'nextCursor': null,
};
final personal = await repository.history(personal: true);
expect(backend.payload, {'fandomId': 'target', 'scope': 'personal'});
expect(personal.items.single.amount, 37);
expect(personal.items.single.participationConfirmed, isFalse);
// PASSPORT Stamp 는 내 기록에서만 받는다(FX §5.2 · §7.2).
backend.response = {'items': [
{'id': 'e', 'kind': 'eclipse_success', 'occurredAt': '2026-09-23T00:00:00Z'},
{'id': 'v', 'kind': 'emblem_evolution', 'occurredAt': '2026-09-22T00:00:00Z', 'toStage': 3},
{'id': 'f', 'kind': 'badge_founder100', 'occurredAt': '2026-09-21T00:00:00Z', 'memberNo': 7},
], 'nextCursor': null};
backend.response = {
'items': [
{
'id': 'e',
'kind': 'eclipse_success',
'occurredAt': '2026-09-23T00:00:00Z',
},
{
'id': 'v',
'kind': 'emblem_evolution',
'occurredAt': '2026-09-22T00:00:00Z',
'toStage': 3,
},
{
'id': 'f',
'kind': 'badge_founder100',
'occurredAt': '2026-09-21T00:00:00Z',
'memberNo': 7,
},
],
'nextCursor': null,
};
final stamps = await repository.history(personal: true);
expect(stamps.items.map((i) => i.kind), [
PlanetHistoryKind.eclipseSuccess, PlanetHistoryKind.emblemEvolution, PlanetHistoryKind.founderBadge,
PlanetHistoryKind.eclipseSuccess,
PlanetHistoryKind.emblemEvolution,
PlanetHistoryKind.founderBadge,
]);
expect(stamps.items[1].toStage, 3);
expect(stamps.items[2].memberNo, 7);
await expectLater(repository.history(), throwsStateError);
});
testWidgets('행성 상세에서 같은 저장소의 팬덤 역사를 연다', (tester) async {
@@ -211,4 +265,31 @@ void main() {
expect(find.text('아직 기록된 팬덤 역사가 없습니다.'), findsOneWidget);
expect(find.text('다시 시도'), findsNothing);
});
test('UX·FX §7.2 — 진화 · Eclipse 성공 · 기념 Badge 만 역사적 사건', () {
expect(PlanetHistoryKind.values.where((k) => k.isHistoric).toSet(), {
PlanetHistoryKind.evolution,
PlanetHistoryKind.eclipseSuccess,
PlanetHistoryKind.emblemEvolution,
PlanetHistoryKind.founderBadge,
});
});
testWidgets('역사적 사건 줄에만 「역사적 사건」 표지가 붙는다', (tester) async {
await tester.pumpWidget(
MaterialApp(
home: PlanetHistoryScreen(
repository: _PersonalHistory(),
fandomName: '팬덤',
),
),
);
await tester.pumpAndSettle();
expect(find.text('Stage 1 → 2 진화'), findsOneWidget);
expect(find.text('역사적 사건'), findsOneWidget);
await tester.tap(find.text('내 활동'));
await tester.pumpAndSettle();
expect(find.text('ZAP 기여'), findsOneWidget);
expect(find.text('역사적 사건'), findsNothing);
});
}