chore(wip): consolidation intermédiaire multi-tickets (sprints Statistiques, UI, Bug resolution, Serveur-client)
Regroupe l'état de travail en cours réalisé dans un même worktree sur plusieurs tickets/sprints (#85, #136, #145, #155-160, #162-164), mélangeant des tickets QA et inProgress. Ne constitue pas une feature terminée : commit de sauvegarde avant triage/split par ticket en branches feature/* dédiées. Exclut les dossiers d'environnement de build locaux et le heap dump parasite (.gitignore mis à jour). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@ -48,6 +48,40 @@ void main() {
|
||||
]);
|
||||
});
|
||||
|
||||
test('create pack share stores a composite payload', () async {
|
||||
final useCase = CreateShareUseCase(
|
||||
users: users,
|
||||
shares: shares,
|
||||
clock: clock,
|
||||
ids: ids,
|
||||
);
|
||||
|
||||
final result = await useCase.execute(
|
||||
senderUserId: 'sender',
|
||||
shareKind: 'pack',
|
||||
packName: 'Pack été',
|
||||
resourceType: null,
|
||||
payloadJson: null,
|
||||
packItems: const [
|
||||
SharePackItemInput(
|
||||
resourceType: 'program',
|
||||
payloadJson: {'schemaVersion': 2, 'name': 'Programme'},
|
||||
),
|
||||
SharePackItemInput(
|
||||
resourceType: 'workoutTemplate',
|
||||
payloadJson: {'schemaVersion': 3, 'name': 'Séance'},
|
||||
),
|
||||
],
|
||||
recipientEmails: ['friend@example.com'],
|
||||
);
|
||||
|
||||
expect(result.share.kind, ShareKind.pack);
|
||||
expect(result.share.packName, 'Pack été');
|
||||
expect(result.share.resourceType, isNull);
|
||||
expect(result.share.payloadJson['items'], hasLength(2));
|
||||
expect(shares.recipients.single.recipientUserId, 'recipient-1');
|
||||
});
|
||||
|
||||
test(
|
||||
'accept creates a copied synced resource without touching source',
|
||||
() async {
|
||||
@ -75,7 +109,6 @@ void main() {
|
||||
resources.put(source);
|
||||
final useCase = AcceptShareUseCase(
|
||||
shares: shares,
|
||||
resources: resources,
|
||||
clock: clock,
|
||||
ids: ids,
|
||||
);
|
||||
@ -97,6 +130,54 @@ void main() {
|
||||
},
|
||||
);
|
||||
|
||||
test('accept pack creates all copied resources atomically', () async {
|
||||
final share = _share(
|
||||
id: 'share-1',
|
||||
kind: ShareKind.pack,
|
||||
resourceType: null,
|
||||
packName: 'Pack été',
|
||||
payloadJson: {
|
||||
'items': [
|
||||
{
|
||||
'resourceType': 'program',
|
||||
'payload': {'schemaVersion': 2, 'name': 'Programme'},
|
||||
},
|
||||
{
|
||||
'resourceType': 'workoutTemplate',
|
||||
'payload': {'schemaVersion': 3, 'name': 'Séance'},
|
||||
},
|
||||
],
|
||||
},
|
||||
);
|
||||
shares.putShare(share);
|
||||
shares.putRecipient(
|
||||
ShareRecipient(
|
||||
id: 'recipient-row-1',
|
||||
shareId: 'share-1',
|
||||
recipientUserId: 'recipient-1',
|
||||
),
|
||||
);
|
||||
final useCase = AcceptShareUseCase(shares: shares, clock: clock, ids: ids);
|
||||
|
||||
final result = await useCase.execute(
|
||||
shareId: 'share-1',
|
||||
recipientUserId: 'recipient-1',
|
||||
);
|
||||
|
||||
expect(result.createdResources.map((item) => item.resourceType), [
|
||||
SyncedResourceType.program,
|
||||
SyncedResourceType.workoutTemplate,
|
||||
]);
|
||||
expect(result.createdResources.map((item) => item.ownerUserId).toSet(), {
|
||||
'recipient-1',
|
||||
});
|
||||
expect(result.createdResources.map((item) => item.schemaVersion), [2, 3]);
|
||||
expect(
|
||||
shares.recipient('share-1', 'recipient-1')?.status,
|
||||
ShareRecipientStatus.accepted,
|
||||
);
|
||||
});
|
||||
|
||||
test('accept on already answered share fails', () async {
|
||||
shares.putShare(_share(id: 'share-1'));
|
||||
shares.putRecipient(
|
||||
@ -108,12 +189,7 @@ void main() {
|
||||
respondedAt: clock.now(),
|
||||
),
|
||||
);
|
||||
final useCase = AcceptShareUseCase(
|
||||
shares: shares,
|
||||
resources: resources,
|
||||
clock: clock,
|
||||
ids: ids,
|
||||
);
|
||||
final useCase = AcceptShareUseCase(shares: shares, clock: clock, ids: ids);
|
||||
|
||||
expect(
|
||||
() => useCase.execute(shareId: 'share-1', recipientUserId: 'recipient-1'),
|
||||
@ -130,12 +206,7 @@ void main() {
|
||||
recipientUserId: 'recipient-1',
|
||||
),
|
||||
);
|
||||
final useCase = AcceptShareUseCase(
|
||||
shares: shares,
|
||||
resources: resources,
|
||||
clock: clock,
|
||||
ids: ids,
|
||||
);
|
||||
final useCase = AcceptShareUseCase(shares: shares, clock: clock, ids: ids);
|
||||
|
||||
expect(
|
||||
() => useCase.execute(shareId: 'share-1', recipientUserId: 'recipient-1'),
|
||||
@ -224,7 +295,9 @@ UserAccount _user(String id, String email) {
|
||||
Share _share({
|
||||
required String id,
|
||||
String senderUserId = 'sender',
|
||||
SyncedResourceType resourceType = SyncedResourceType.program,
|
||||
ShareKind kind = ShareKind.single,
|
||||
SyncedResourceType? resourceType = SyncedResourceType.program,
|
||||
String? packName,
|
||||
Map<String, Object?> payloadJson = const {'schemaVersion': 1},
|
||||
DateTime? createdAt,
|
||||
DateTime? revokedAt,
|
||||
@ -232,7 +305,9 @@ Share _share({
|
||||
return Share(
|
||||
id: id,
|
||||
senderUserId: senderUserId,
|
||||
kind: kind,
|
||||
resourceType: resourceType,
|
||||
packName: packName,
|
||||
payloadJson: payloadJson,
|
||||
createdAt: createdAt ?? DateTime.utc(2026, 7, 19, 12),
|
||||
revokedAt: revokedAt,
|
||||
@ -376,6 +451,20 @@ final class _FakeShareRepository implements ShareRepository {
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<List<SyncedResource>> acceptShare({
|
||||
required String recipientId,
|
||||
required DateTime respondedAt,
|
||||
required List<SyncedResource> resources,
|
||||
}) async {
|
||||
await updateRecipientStatus(
|
||||
recipientId: recipientId,
|
||||
status: ShareRecipientStatus.accepted,
|
||||
respondedAt: respondedAt,
|
||||
);
|
||||
return resources;
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> revokeShare({
|
||||
required String shareId,
|
||||
@ -386,7 +475,9 @@ final class _FakeShareRepository implements ShareRepository {
|
||||
shares[index] = Share(
|
||||
id: share.id,
|
||||
senderUserId: share.senderUserId,
|
||||
kind: share.kind,
|
||||
resourceType: share.resourceType,
|
||||
packName: share.packName,
|
||||
payloadJson: share.payloadJson,
|
||||
createdAt: share.createdAt,
|
||||
revokedAt: revokedAt,
|
||||
|
||||
Reference in New Issue
Block a user