113 lines
4.4 KiB
Dart
113 lines
4.4 KiB
Dart
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>[
|
|
PersonProfile(
|
|
id: 'p-1',
|
|
name: 'Alice Secret',
|
|
relationship: 'Sister',
|
|
affinityScore: 85,
|
|
nextMoment: DateTime(2026, 6, 1),
|
|
tags: const <String>['coffee', 'books'],
|
|
notes: 'Passport number and private address should stay local.',
|
|
aliases: const <String>['Ally'],
|
|
location: 'Zurich, Switzerland',
|
|
lastInteractedAt: DateTime(2026, 5, 1),
|
|
),
|
|
],
|
|
moments: const <RelationshipMoment>[],
|
|
ideas: const <RelationshipIdea>[],
|
|
reminders: const <ReminderRule>[],
|
|
tasks: const <DashboardTask>[],
|
|
sourceLinks: <SourceProfileLink>[
|
|
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>[
|
|
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),
|
|
platform: 'ios',
|
|
sourceDisplayName: 'Alice Secret',
|
|
sourceUserId: 'wa:alice',
|
|
sourceThreadId: 'thread-secret',
|
|
),
|
|
importedAt: DateTime(2026, 5, 1),
|
|
resolvedAutomatically: true,
|
|
),
|
|
],
|
|
personFacts: <PersonFact>[
|
|
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,
|
|
),
|
|
],
|
|
aiSuggestionDrafts: <AiSuggestionDraft>[
|
|
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, <String, String>{'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('priorSuggestions'));
|
|
expect(prompt, contains('jazz concert downtown'));
|
|
expect(prompt, contains('dismissed'));
|
|
expect(prompt, isNot(contains('Should not need to repeat the details.')));
|
|
});
|
|
}
|