From 33c32c5311d6d7a0502649e523ad24d02a095c8b Mon Sep 17 00:00:00 2001 From: Marcus Fihlon Date: Wed, 29 Apr 2026 15:26:54 +0200 Subject: [PATCH] fix(komoot): map racebike activities to ride Signed-off-by: Marcus Fihlon --- .../fitpub/service/KomootImportService.java | 2 +- .../service/KomootImportServiceTest.java | 67 +++++++++++++++++++ 2 files changed, 68 insertions(+), 1 deletion(-) diff --git a/src/main/java/net/javahippie/fitpub/service/KomootImportService.java b/src/main/java/net/javahippie/fitpub/service/KomootImportService.java index 4030f95..cce0493 100644 --- a/src/main/java/net/javahippie/fitpub/service/KomootImportService.java +++ b/src/main/java/net/javahippie/fitpub/service/KomootImportService.java @@ -397,7 +397,7 @@ public class KomootImportService { case "hike" -> Activity.ActivityType.HIKE; case "walk" -> Activity.ActivityType.WALK; case "run", "trailrunning", "jogging" -> Activity.ActivityType.RUN; - case "touringbicycle", "road_bike", "bike", "bicycle", "gravel", "mtb", "mtb_easy", "mtb_advanced", "ebike" -> + case "touringbicycle", "road_bike", "racebike", "bike", "bicycle", "gravel", "mtb", "mtb_easy", "mtb_advanced", "ebike" -> Activity.ActivityType.RIDE; case "alpine_ski" -> Activity.ActivityType.ALPINE_SKI; case "backcountry_ski" -> Activity.ActivityType.BACKCOUNTRY_SKI; diff --git a/src/test/java/net/javahippie/fitpub/service/KomootImportServiceTest.java b/src/test/java/net/javahippie/fitpub/service/KomootImportServiceTest.java index 5cf85a5..1ea5a13 100644 --- a/src/test/java/net/javahippie/fitpub/service/KomootImportServiceTest.java +++ b/src/test/java/net/javahippie/fitpub/service/KomootImportServiceTest.java @@ -336,6 +336,73 @@ class KomootImportServiceTest { assertThat(response.getStatus()).isEqualTo("SKIPPED_ALREADY_IMPORTED"); } + @Test + @DisplayName("Should map Komoot cycling sport racebike to ride") + void shouldMapKomootRacebikeToRide() { + String authHeader = "Basic " + Base64.getEncoder() + .encodeToString("user@example.com:secret".getBytes(StandardCharsets.UTF_8)); + UUID userId = UUID.fromString("aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa"); + UUID importedActivityId = UUID.fromString("bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb"); + KomootImportService throttledService = spy(service); + doNothing().when(throttledService).pauseBetweenDetailAndGpxRequest(); + doNothing().when(throttledService).pauseAfterActivityImport(); + + when(komootImportRepository.findByUserIdAndKomootActivityId(userId, 2880957037L)).thenReturn(Optional.empty()); + + server.expect(once(), requestTo("https://www.komoot.com/api/v007/tours/2880957037?hl=en")) + .andExpect(method(HttpMethod.GET)) + .andExpect(header(HttpHeaders.AUTHORIZATION, authHeader)) + .andRespond(withSuccess(""" + { + "id": "2880957037", + "name": "Road Ride", + "description": "Komoot road cycling type", + "status": "private", + "sport": "racebike" + } + """, MediaType.APPLICATION_JSON)); + + server.expect(once(), requestTo("https://www.komoot.com/api/v007/tours/2880957037.gpx")) + .andExpect(method(HttpMethod.GET)) + .andExpect(header(HttpHeaders.AUTHORIZATION, authHeader)) + .andExpect(header(HttpHeaders.ACCEPT, "application/gpx+xml, application/xml, text/xml")) + .andRespond(withSuccess(""" + + + Road Ride + + """, MediaType.APPLICATION_XML)); + + Activity importedActivity = Activity.builder() + .id(importedActivityId) + .userId(userId) + .activityType(Activity.ActivityType.OTHER) + .title("GPX Title") + .description(null) + .visibility(Activity.Visibility.PRIVATE) + .sourceFileFormat("GPX") + .build(); + + when(activityFileService.processActivityFile(any(), any(), any(), any(), any())).thenReturn(importedActivity); + when(activityRepository.save(any(Activity.class))).thenAnswer(invocation -> invocation.getArgument(0)); + when(komootImportRepository.save(any(KomootImport.class))).thenAnswer(invocation -> invocation.getArgument(0)); + + KomootImportExecutionResponse response = throttledService.importActivity( + new KomootActivityImportRequest("user@example.com", "secret", "123456", 2880957037L), + userId + ); + + assertThat(response.getImportedActivityId()).isEqualTo(importedActivityId); + assertThat(response.getStatus()).isEqualTo("IMPORTED"); + assertThat(importedActivity.getActivityType()).isEqualTo(Activity.ActivityType.RIDE); + verify(komootImportRepository).save(any(KomootImport.class)); + + verify(throttledService).pauseBetweenDetailAndGpxRequest(); + verify(throttledService).pauseAfterActivityImport(); + verify(activityPostProcessingService).processActivityAsync(importedActivityId, userId); + server.verify(); + } + @Test @DisplayName("Should fall back to OTHER when Komoot sport cannot be mapped") void shouldFallbackToOtherForUnknownKomootSport() {