1414import org .junit .jupiter .api .BeforeEach ;
1515import org .junit .jupiter .api .Test ;
1616import org .mockito .ArgumentCaptor ;
17+ import org .mockito .InOrder ;
1718import org .mockito .Mockito ;
1819
1920import java .time .LocalDate ;
2425
2526import static org .hamcrest .MatcherAssert .assertThat ;
2627import static org .junit .jupiter .api .Assertions .*;
27- import static org .mockito .Mockito .when ;
28+ import static org .mockito .Mockito .* ;
2829
2930class HeimatControllerTest {
3031
@@ -355,10 +356,118 @@ void shouldGenerateLinkForDay() {
355356 final String urlForDay = heimatController .getUrlForDay (LocalDate .of (1999 , 4 , 2 ));
356357 assertThat (urlForDay , Matchers .is ("https://doubleslash.de/core/heimat/time/main/day/1999/4/2" ));
357358 }
358- // Save
359- // shouldSaveTimes
360- // shouldDeleteExistingTimesBeforeSavingWhenTimesAlreadyExist
361- // shouldContinueOnErrorAndReturnErrorsWhenErrorsOccurred
359+
360+ /* Save */
361+ @ Test
362+ void shouldSaveTimes () {
363+ // ARRANGE
364+ workItems .add (new Work (now .minusMinutes (13 ), now , workProject1 , "Notes 1" ));
365+ externalMappings .add (project1To1Mapping );
366+ final List <HeimatController .Mapping > tableRows = heimatController .getTableRows (now .toLocalDate (), workItems );
367+ final HeimatController .Mapping mapping = tableRows .get (0 );
368+
369+ // ACT
370+ final String userNote = "User entered note" ;
371+ final int userMinutes = 15 ;
372+ final List <HeimatController .HeimatErrors > errors = heimatController .saveDay (
373+ List .of (new HeimatController .UserMapping (mapping , true , userNote , userMinutes )), now .toLocalDate ());
374+
375+ // ASSERT
376+ ArgumentCaptor <HeimatTime > saveMappingsCaptor = ArgumentCaptor .forClass (HeimatTime .class );
377+ Mockito .verify (mockedHeimatAPI ).addMyTime (saveMappingsCaptor .capture ());
378+ assertAll ( //
379+ () -> assertThat (errors , Matchers .empty ()) //
380+ , () -> assertThat (saveMappingsCaptor .getValue ().taskId (),
381+ Matchers .is (project1To1Mapping .getExternalTaskId ())) //
382+ , () -> assertThat (saveMappingsCaptor .getValue ().note (), Matchers .is (userNote )) //
383+ , () -> assertThat (saveMappingsCaptor .getValue ().durationInMinutes (), Matchers .is (userMinutes )) //
384+ );
385+ }
386+
387+ @ Test
388+ void shouldNotSaveTimeWhenUserDoesNotWantToSync () {
389+ // ARRANGE
390+ workItems .add (new Work (now .minusMinutes (13 ), now , workProject1 , "Notes 1" ));
391+ externalMappings .add (project1To1Mapping );
392+ final List <HeimatController .Mapping > tableRows = heimatController .getTableRows (now .toLocalDate (), workItems );
393+ final HeimatController .Mapping mapping = tableRows .get (0 );
394+
395+ // ACT
396+ final String userNote = "User entered note" ;
397+ final int userMinutes = 15 ;
398+ final boolean shouldSync = false ;
399+ heimatController .saveDay (List .of (new HeimatController .UserMapping (mapping , shouldSync , userNote , userMinutes )),
400+ now .toLocalDate ());
401+
402+ // ASSERT
403+ Mockito .verify (mockedHeimatAPI , Mockito .never ()).addMyTime (any (HeimatTime .class ));
404+ }
405+
406+ @ Test
407+ void shouldDeleteExistingTimesBeforeSavingWhenTimesAlreadyExist () {
408+ // updating existing times is not supported. therefore, we delete existing and create new.
409+ // ARRANGE
410+ workItems .add (new Work (now .minusMinutes (13 ), now , workProject1 , "Notes 1" ));
411+ externalMappings .add (project1To1Mapping );
412+
413+ final HeimatTime existingTime1 = new HeimatTime (project1To1Mapping .getExternalTaskId (), now .toLocalDate (), null ,
414+ null , 60 , "Existing note 1" , 12 );
415+ final HeimatTime existingTime2 = new HeimatTime (project1To1Mapping .getExternalTaskId (), now .toLocalDate (), null ,
416+ null , 30 , "Existing note 2" , 13 );
417+ when (mockedHeimatAPI .getMyTimes (now .toLocalDate ())).thenReturn (Arrays .asList (existingTime1 , existingTime2 ));
418+
419+ final List <HeimatController .Mapping > tableRows = heimatController .getTableRows (now .toLocalDate (), workItems );
420+ final HeimatController .Mapping mapping = tableRows .get (0 );
421+
422+ // ACT
423+ final String userNote = "User entered note" ;
424+ final int userMinutes = 15 ;
425+ final List <HeimatController .HeimatErrors > errors = heimatController .saveDay (
426+ List .of (new HeimatController .UserMapping (mapping , true , userNote , userMinutes )), now .toLocalDate ());
427+
428+ // ASSERT
429+ InOrder inOrder = inOrder (mockedHeimatAPI );
430+ inOrder .verify (mockedHeimatAPI ).deleteMyTime (existingTime1 .id ());
431+ inOrder .verify (mockedHeimatAPI ).deleteMyTime (existingTime2 .id ());
432+
433+ ArgumentCaptor <HeimatTime > saveMappingsCaptor = ArgumentCaptor .forClass (HeimatTime .class );
434+ inOrder .verify (mockedHeimatAPI ).addMyTime (saveMappingsCaptor .capture ());
435+ assertAll ( //
436+ () -> assertThat (errors , Matchers .empty ()) //
437+ , () -> assertThat (saveMappingsCaptor .getValue ().taskId (),
438+ Matchers .is (project1To1Mapping .getExternalTaskId ())) //
439+ , () -> assertThat (saveMappingsCaptor .getValue ().note (), Matchers .is (userNote )) //
440+ , () -> assertThat (saveMappingsCaptor .getValue ().durationInMinutes (), Matchers .is (userMinutes )) //
441+ );
442+ }
443+
444+ @ Test
445+ void shouldReturnErrorsWhenErrorsOccurred () {
446+ // ARRANGE
447+ workItems .add (new Work (now .minusMinutes (13 ), now , workProject1 , "Notes 1" ));
448+ externalMappings .add (project1To1Mapping );
449+ final List <HeimatController .Mapping > tableRows = heimatController .getTableRows (now .toLocalDate (), workItems );
450+ final HeimatController .Mapping mapping = tableRows .get (0 );
451+ final String exceptionMessage = "SomethingDidNotWork" ;
452+ doThrow (new RuntimeException (exceptionMessage )).when (mockedHeimatAPI ).addMyTime (any (HeimatTime .class ));
453+
454+ // ACT
455+ final String userNote = "User entered note" ;
456+ final int userMinutes = 15 ;
457+ final HeimatController .UserMapping userMapping = new HeimatController .UserMapping (mapping , true , userNote ,
458+ userMinutes );
459+ final List <HeimatController .HeimatErrors > errors = heimatController .saveDay (List .of (userMapping ),
460+ now .toLocalDate ());
461+
462+ // ASSERT
463+ ArgumentCaptor <HeimatTime > saveMappingsCaptor = ArgumentCaptor .forClass (HeimatTime .class );
464+ Mockito .verify (mockedHeimatAPI ).addMyTime (saveMappingsCaptor .capture ());
465+ assertAll ( //
466+ () -> assertThat (errors , Matchers .hasSize (1 )) //
467+ , () -> assertThat (errors .get (0 ).errorMessage (), Matchers .containsString (exceptionMessage )) //
468+ , () -> assertThat (errors .get (0 ).mapping (), Matchers .is (userMapping )) //
469+ );
470+ }
362471 // shouldOnlyUpdateHeimatWhenSomethingHasChanged (not needed - user should decide)
363472
364473}
0 commit comments