fix(watch): finalise correctif sync workoutHistory/exercise et distance live montre (#157)

This commit is contained in:
2026-07-29 11:22:17 +02:00
parent 6f913e4e8d
commit 30c6259748
28 changed files with 1658 additions and 248 deletions

View File

@ -2611,6 +2611,68 @@ void main() {
expect(inboxRepository.items.single.status, ShareInboxStatus.accepted);
});
test(
'ShareUseCases acceptShare imports all returned resources locally',
() async {
final remoteShareApi = _FakeRemoteShareApi()
..acceptResults = [
_remoteSharedProgramItem(),
_remoteSharedTemplateItem(),
];
final localChanges = _FakeLocalSyncChangeRepository();
final inboxRepository = _FakeShareInboxRepository()
..items.add(_shareInboxItem(status: ShareInboxStatus.pending));
await _shareUseCase(
remoteShareApi: remoteShareApi,
localChanges: localChanges,
inboxRepository: inboxRepository,
).acceptShare('share-1');
expect(localChanges.appliedItems.map((item) => item.resourceType), [
SyncResourceType.program,
SyncResourceType.workoutTemplate,
]);
expect(inboxRepository.items.single.status, ShareInboxStatus.accepted);
},
);
test(
'ShareUseCases acceptShare imports cached pack payload after remote ack',
() async {
final remoteShareApi = _FakeRemoteShareApi();
final templateRepository = _FakeWorkoutTemplateRepository();
final inboxRepository = _FakeShareInboxRepository()
..items.add(
_shareInboxItem(
status: ShareInboxStatus.pending,
resourceType: ShareResourceType.pack,
payloadJson: jsonEncode({
'name': 'Pack reprise',
'workouts': [
_sharedTemplatePayload(id: 'template-a', name: 'Séance A'),
_sharedTemplatePayload(id: 'template-b', name: 'Séance B'),
],
}),
),
);
await _shareUseCase(
remoteShareApi: remoteShareApi,
inboxRepository: inboxRepository,
templateRepository: templateRepository,
).acceptShare('share-1');
expect(remoteShareApi.acceptCalls, 1);
expect(templateRepository.templates, hasLength(2));
expect(
templateRepository.templates.map((template) => template.name),
containsAll(['Séance A', 'Séance B']),
);
expect(inboxRepository.items.single.status, ShareInboxStatus.accepted);
},
);
test(
'ShareUseCases acceptShare sans token importe une copie locale indépendante',
() async {
@ -4559,6 +4621,7 @@ ShareUseCases _shareUseCase({
final class _FakeRemoteShareApi implements RemoteShareApi {
Exception? exception;
RemoteSyncedItem? acceptResult;
List<RemoteSyncedItem>? acceptResults;
List<ShareInboxItem> inboxItems = const [];
var sendCalls = 0;
var acceptCalls = 0;
@ -4568,13 +4631,16 @@ final class _FakeRemoteShareApi implements RemoteShareApi {
Map<String, Object?>? lastPayload;
@override
Future<RemoteSyncedItem> acceptShare(String shareId, String token) async {
Future<List<RemoteSyncedItem>> acceptShare(
String shareId,
String token,
) async {
acceptCalls += 1;
final error = exception;
if (error != null) {
throw error;
}
return acceptResult ?? _remoteSharedProgramItem();
return acceptResults ?? [acceptResult ?? _remoteSharedProgramItem()];
}
@override
@ -4804,6 +4870,19 @@ RemoteSyncedItem _remoteSharedProgramItem() {
);
}
RemoteSyncedItem _remoteSharedTemplateItem() {
return RemoteSyncedItem(
resourceType: SyncResourceType.workoutTemplate,
clientId: 'shared-template-1',
serverId: 'server-template-1',
schemaVersion: 1,
clientUpdatedAt: DateTime.utc(2026, 7, 17, 12, 2),
serverUpdatedAt: DateTime.utc(2026, 7, 17, 12, 3),
deletedAt: null,
payload: const {'id': 'shared-template-1', 'name': 'Séance partagée'},
);
}
ExerciseUseCases _exerciseUseCase(
_FakeExerciseRepository repository, {
_FakeProgramRepository? programRepository,