import 'package:flutter_test/flutter_test.dart'; import 'package:relationship_saver/app/state/local_data_state.dart'; import 'package:relationship_saver/features/ai_digest/application/anonymized_llm_context_builder.dart'; import 'package:relationship_saver/features/ai_digest/domain/ai_digest_models.dart'; import 'package:relationship_saver/features/dashboard/domain/dashboard_models.dart'; import 'package:relationship_saver/features/ideas/domain/idea_models.dart'; import 'package:relationship_saver/features/moments/domain/moment_models.dart'; import 'package:relationship_saver/features/people/domain/person_models.dart'; import 'package:relationship_saver/features/reminders/domain/reminder_models.dart'; import 'package:relationship_saver/features/share_intake/domain/share_models.dart'; void main() { test('builds pseudonymous payload without identifiable profile data', () { final LocalDataState state = LocalDataState( people: [ PersonProfile( id: 'p-1', name: 'Alice Secret', relationship: 'Sister', affinityScore: 85, nextMoment: DateTime(2026, 6, 1), tags: const ['coffee', 'books'], notes: 'Passport number and private address should stay local.', aliases: const ['Ally'], location: 'Zurich, Switzerland', lastInteractedAt: DateTime(2026, 5, 1), ), ], moments: const [], ideas: const [], reminders: const [], tasks: const [], sourceLinks: [ SourceProfileLink( id: 'sl-1', sourceApp: 'whatsapp', normalizedDisplayName: 'Alice Secret', profileId: 'p-1', firstSeenAt: DateTime(2026, 5, 1), lastSeenAt: DateTime(2026, 5, 1), sourceUserId: 'wa:alice', sourceThreadId: 'thread-secret', sourceFingerprint: 'whatsapp|u:wa:alice', ), ], sharedMessages: [ SharedMessageEntry( id: 'sm-1', profileId: 'p-1', payload: SharedPayload( sourceApp: 'whatsapp', payloadType: SharedPayloadType.text, rawText: 'Raw private chat text', createdAt: DateTime(2026, 5, 1), receivedAt: DateTime(2026, 5, 1), sharedMessageDateTime: DateTime.utc(2026, 2, 1, 10), platform: 'ios', sourceDisplayName: 'Alice Secret', sourceUserId: 'wa:alice', sourceThreadId: 'thread-secret', ), importedAt: DateTime(2026, 5, 1), resolvedAutomatically: true, ), ], personFacts: [ PersonFact( id: 'pf-1', personId: 'p-1', type: CapturedFactType.note, text: 'Secret medical detail', sourceKind: CaptureSourceKind.manual, createdAt: DateTime(2026, 5, 1), updatedAt: DateTime(2026, 5, 1), isSensitive: true, ), PersonFact( id: 'pf-2', personId: 'p-1', type: CapturedFactType.giftIdea, text: 'Alice wants ceramic espresso cups', label: 'Coffee gear', sourceKind: CaptureSourceKind.shareInbox, sharedMessageId: 'sm-1', createdAt: DateTime(2026, 5, 2), updatedAt: DateTime(2026, 5, 2), ), PersonFact( id: 'pf-3', personId: 'p-1', type: CapturedFactType.placeIdea, text: 'Unreviewed ramen place', sourceKind: CaptureSourceKind.shareSheet, createdAt: DateTime(2026, 5, 3), updatedAt: DateTime(2026, 5, 3), needsReview: true, ), ], aiSuggestionDrafts: [ AiSuggestionDraft( id: 'ai-1', personId: 'p-1', kind: AiSuggestionKind.eventIdea, title: 'Jazz concert downtown', details: 'Should not need to repeat the details.', suggestedAt: DateTime(2026, 5, 10), confidence: 0.8, status: AiSuggestionStatus.dismissed, sourceRunId: 'digest-old', ), ], ); final AnonymizedLlmDigestContext context = AnonymizedLlmContextBuilder( now: () => DateTime(2026, 5, 16), ).build(state); final String prompt = context.toPromptJson(); expect(context.tokenToPersonId, {'person_001': 'p-1'}); expect(prompt, contains('person_001')); expect(prompt, isNot(contains('Alice'))); expect(prompt, isNot(contains('Ally'))); expect(prompt, isNot(contains('Zurich'))); expect(prompt, isNot(contains('Passport'))); expect(prompt, isNot(contains('wa:alice'))); expect(prompt, isNot(contains('thread-secret'))); expect(prompt, isNot(contains('Raw private chat text'))); expect(prompt, isNot(contains('Secret medical detail'))); expect(prompt, contains('capturedFacts')); expect(prompt, contains('shared_message_datetime')); expect(prompt, contains('2026-02-01T10:00:00.000Z')); expect(prompt, contains('about 3 months ago')); expect(prompt, contains('ceramic espresso cups')); expect(prompt, contains('coffee gear')); expect(prompt, contains('this person wants ceramic espresso cups')); expect(prompt, isNot(contains('unreviewed ramen place'))); expect(prompt, contains('priorSuggestions')); expect(prompt, contains('jazz concert downtown')); expect(prompt, contains('dismissed')); expect(prompt, isNot(contains('Should not need to repeat the details.'))); }); }