From 6d4b03f73fb53c203cf6620a74c175eb1b617c8d Mon Sep 17 00:00:00 2001 From: TOL Date: Thu, 2 Feb 2023 08:20:39 +0900 Subject: [PATCH] =?UTF-8?q?state=3Dopen=E3=81=AEMR=E3=81=AB=E7=B5=9E?= =?UTF-8?q?=E3=82=8B=E3=80=81LocalDateTime=20->=20OffsetDateTime=E3=81=AB?= =?UTF-8?q?=E3=83=AA=E3=83=95=E3=82=A1=E3=82=AF=E3=82=BF=20(#16)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dto/GitLabMergeRequestApiResponseDto.java | 10 +- .../github/tttol/mrls/form/MrDetailForm.java | 6 +- .../mrls/service/MergeRequestService.java | 108 +++--- src/main/resources/application.yml | 2 +- .../resources/templates/fragment/footer.html | 2 +- .../mrls/controller/MrListControllerTest.java | 19 +- .../mrls/service/MergeRequestServiceTest.java | 360 +++++++++--------- 7 files changed, 250 insertions(+), 257 deletions(-) diff --git a/src/main/java/io/github/tttol/mrls/dto/GitLabMergeRequestApiResponseDto.java b/src/main/java/io/github/tttol/mrls/dto/GitLabMergeRequestApiResponseDto.java index e245f51..6ad6d3b 100644 --- a/src/main/java/io/github/tttol/mrls/dto/GitLabMergeRequestApiResponseDto.java +++ b/src/main/java/io/github/tttol/mrls/dto/GitLabMergeRequestApiResponseDto.java @@ -8,7 +8,7 @@ import lombok.NoArgsConstructor; import org.springframework.format.annotation.DateTimeFormat; -import java.time.LocalDateTime; +import java.time.OffsetDateTime; import java.util.List; @Data @@ -30,22 +30,22 @@ public class GitLabMergeRequestApiResponseDto { String state; @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) - LocalDateTime createdAt; + OffsetDateTime createdAt; @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) - LocalDateTime updatedAt; + OffsetDateTime updatedAt; String mergedBy; String mergeUser; @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) - LocalDateTime mergedAt; + OffsetDateTime mergedAt; String closedBy; @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) - LocalDateTime closedAt; + OffsetDateTime closedAt; String targetBranch; diff --git a/src/main/java/io/github/tttol/mrls/form/MrDetailForm.java b/src/main/java/io/github/tttol/mrls/form/MrDetailForm.java index 8310e34..512b9db 100644 --- a/src/main/java/io/github/tttol/mrls/form/MrDetailForm.java +++ b/src/main/java/io/github/tttol/mrls/form/MrDetailForm.java @@ -1,7 +1,7 @@ package io.github.tttol.mrls.form; -import java.time.LocalDateTime; +import java.time.OffsetDateTime; -public record MrDetailForm(String title, String webUrl, UserForm author, LocalDateTime createdAt, - LocalDateTime updatedAt) { +public record MrDetailForm(String title, String webUrl, UserForm author, OffsetDateTime createdAt, + OffsetDateTime updatedAt) { } diff --git a/src/main/java/io/github/tttol/mrls/service/MergeRequestService.java b/src/main/java/io/github/tttol/mrls/service/MergeRequestService.java index a8ec3ca..6264155 100644 --- a/src/main/java/io/github/tttol/mrls/service/MergeRequestService.java +++ b/src/main/java/io/github/tttol/mrls/service/MergeRequestService.java @@ -5,75 +5,69 @@ import io.github.tttol.mrls.form.MrDetailForm; import io.github.tttol.mrls.form.MrInfoForm; import io.github.tttol.mrls.form.UserForm; -import java.time.LocalDateTime; -import java.time.ZoneId; -import java.time.ZonedDateTime; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +import java.time.ZoneOffset; import java.util.Comparator; import java.util.List; import java.util.Objects; import java.util.Optional; import java.util.stream.Collectors; -import lombok.RequiredArgsConstructor; -import org.springframework.stereotype.Service; @Service @RequiredArgsConstructor public class MergeRequestService { - private final GitLabApiExecutor gitLabApiExecutor; + private final GitLabApiExecutor gitLabApiExecutor; - public List get(String accessToken) { - var mergeRequestInfoDtos = executeGitLabApi(accessToken); - return mergeRequestInfoDtos.stream() - .collect(Collectors.groupingBy( - e -> Objects.isNull(e.getAssignee()) ? - e.getAuthor().getId() : e.getAssignee().getId() - ) - ) - .values().stream().map(this::generateForm) - .sorted(Comparator.comparing(e -> e.assignee().id())) - .toList(); - } + public List get(final String accessToken) { + final var mergeRequestInfoDtos = executeGitLabApi(accessToken); + return mergeRequestInfoDtos.stream() + .collect(Collectors.groupingBy( + e -> Objects.isNull(e.getAssignee()) ? + e.getAuthor().getId() : e.getAssignee().getId() + ) + ) + .values().stream().map(this::generateForm) + .sorted(Comparator.comparing(e -> e.assignee().id())) + .toList(); + } - private List executeGitLabApi(String accessToken) { - return gitLabApiExecutor.getMergeRequests(accessToken); - } + private List executeGitLabApi(final String accessToken) { + return gitLabApiExecutor.getMergeRequests(accessToken); + } - private MrInfoForm generateForm(List responseDtos) { - var responseDto = responseDtos.stream().findAny().orElseThrow(); - var assigneeForm = Optional.ofNullable(responseDto.getAssignee()) - .map(assignee -> new UserForm( - assignee.getId(), - assignee.getUsername(), - assignee.getName(), - assignee.getState(), - assignee.getAvatarUrl(), - assignee.getWebUrl() - ) - ).orElse(UserForm.empty()); - var linkForms = responseDtos.stream().map(e -> - new MrDetailForm( - e.getTitle(), - e.getWebUrl(), - Optional.ofNullable(e.getAuthor()) + private MrInfoForm generateForm(final List responseDtos) { + final var responseDto = responseDtos.stream().findAny().orElseThrow(); + final var assigneeForm = Optional.ofNullable(responseDto.getAssignee()) .map(assignee -> new UserForm( - assignee.getId(), - assignee.getUsername(), - assignee.getName(), - assignee.getState(), - assignee.getAvatarUrl(), - assignee.getWebUrl() - ) - ) - .orElse(UserForm.empty()), - toJst(e.getCreatedAt()), - toJst(e.getUpdatedAt()) - )).toList(); - return new MrInfoForm(assigneeForm, linkForms, linkForms.size()); - } - - private LocalDateTime toJst(LocalDateTime utc) { - return ZonedDateTime.of(utc, ZoneId.of("UTC")) - .withZoneSameInstant(ZoneId.of("Asia/Tokyo")).toLocalDateTime(); - } + assignee.getId(), + assignee.getUsername(), + assignee.getName(), + assignee.getState(), + assignee.getAvatarUrl(), + assignee.getWebUrl() + ) + ).orElse(UserForm.empty()); + final var linkForms = responseDtos.stream().map(e -> + new MrDetailForm( + e.getTitle(), + e.getWebUrl(), + Optional.ofNullable(e.getAuthor()) + .map(assignee -> new UserForm( + assignee.getId(), + assignee.getUsername(), + assignee.getName(), + assignee.getState(), + assignee.getAvatarUrl(), + assignee.getWebUrl() + ) + ) + .orElse(UserForm.empty()), + e.getCreatedAt().withOffsetSameInstant(ZoneOffset.of("+09:00")), + e.getUpdatedAt().withOffsetSameInstant(ZoneOffset.of("+09:00")) + )).toList(); + return new MrInfoForm(assigneeForm, linkForms, linkForms.size()); + } } diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index 181d36c..c507b62 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -5,7 +5,7 @@ app: id: ${GITLAB_PROJECT_ID} accessToken: ${GITLAB_ACCESS_TOKEN} api: - endpoint: https://${app.gitlab.host}/api/v4/projects/${app.gitlab.project.id}/merge_requests + endpoint: https://${app.gitlab.host}/api/v4/projects/${app.gitlab.project.id}/merge_requests?state=opened logging: level: root: INFO diff --git a/src/main/resources/templates/fragment/footer.html b/src/main/resources/templates/fragment/footer.html index b01f2c4..785da28 100644 --- a/src/main/resources/templates/fragment/footer.html +++ b/src/main/resources/templates/fragment/footer.html @@ -3,7 +3,7 @@ diff --git a/src/test/java/io/github/tttol/mrls/controller/MrListControllerTest.java b/src/test/java/io/github/tttol/mrls/controller/MrListControllerTest.java index 48cd31b..017a1ea 100644 --- a/src/test/java/io/github/tttol/mrls/controller/MrListControllerTest.java +++ b/src/test/java/io/github/tttol/mrls/controller/MrListControllerTest.java @@ -12,7 +12,8 @@ import org.springframework.test.web.servlet.setup.MockMvcBuilders; import org.springframework.web.context.WebApplicationContext; -import java.time.LocalDateTime; +import java.time.OffsetDateTime; +import java.time.ZoneOffset; import java.util.List; import static org.mockito.ArgumentMatchers.anyString; @@ -36,13 +37,13 @@ public class MrListControllerTest { public void init() { mockMvc = MockMvcBuilders.webAppContextSetup(this.webApplicationContext).build(); - var assignee = UserDto.builder() + final var assignee = UserDto.builder() .id(1) .username("assignee_username1") .name("assignee_name1") .state("active") .build(); - var mergeRequestInfoDtos = List.of( + final var mergeRequestInfoDtos = List.of( GitLabMergeRequestApiResponseDto.builder() .assignee(assignee) .author(UserDto.builder() @@ -53,8 +54,8 @@ public void init() { .build()) .webUrl("url1") .title("title1") - .createdAt(LocalDateTime.of(1970, 1, 1, 0, 0, 0)) - .updatedAt(LocalDateTime.of(2000, 1, 1, 0, 0, 0)) + .createdAt(OffsetDateTime.of(1970, 1, 1, 0, 0, 0, 0, ZoneOffset.UTC)) + .updatedAt(OffsetDateTime.of(1970, 1, 1, 0, 0, 0, 0, ZoneOffset.UTC)) .build(), GitLabMergeRequestApiResponseDto.builder() .assignee(assignee) @@ -66,8 +67,8 @@ public void init() { .build()) .webUrl("url2") .title("title2") - .createdAt(LocalDateTime.of(1970, 1, 1, 0, 0, 0)) - .updatedAt(LocalDateTime.of(2000, 1, 1, 0, 0, 0)) + .createdAt(OffsetDateTime.of(1970, 1, 1, 0, 0, 0, 0, ZoneOffset.UTC)) + .updatedAt(OffsetDateTime.of(1970, 1, 1, 0, 0, 0, 0, ZoneOffset.UTC)) .build(), GitLabMergeRequestApiResponseDto.builder() .assignee(assignee) @@ -79,8 +80,8 @@ public void init() { .build()) .webUrl("url3") .title("title3") - .createdAt(LocalDateTime.of(1970, 1, 1, 0, 0, 0)) - .updatedAt(LocalDateTime.of(2000, 1, 1, 0, 0, 0)) + .createdAt(OffsetDateTime.of(1970, 1, 1, 0, 0, 0, 0, ZoneOffset.UTC)) + .updatedAt(OffsetDateTime.of(1970, 1, 1, 0, 0, 0, 0, ZoneOffset.UTC)) .build() ); doReturn(mergeRequestInfoDtos).when(gitLabApiExecutor).getMergeRequests(anyString()); diff --git a/src/test/java/io/github/tttol/mrls/service/MergeRequestServiceTest.java b/src/test/java/io/github/tttol/mrls/service/MergeRequestServiceTest.java index cdb76a4..755609a 100644 --- a/src/test/java/io/github/tttol/mrls/service/MergeRequestServiceTest.java +++ b/src/test/java/io/github/tttol/mrls/service/MergeRequestServiceTest.java @@ -1,201 +1,199 @@ package io.github.tttol.mrls.service; -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.ArgumentMatchers.anyString; -import static org.mockito.Mockito.doReturn; - import io.github.tttol.mrls.dto.GitLabMergeRequestApiResponseDto; import io.github.tttol.mrls.dto.UserDto; import io.github.tttol.mrls.external.GitLabApiExecutor; import io.github.tttol.mrls.form.MrDetailForm; import io.github.tttol.mrls.form.MrInfoForm; import io.github.tttol.mrls.form.UserForm; -import java.time.LocalDateTime; -import java.util.List; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Nested; -import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.*; import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.MockitoAnnotations; +import java.time.OffsetDateTime; +import java.time.ZoneOffset; +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.Mockito.doReturn; + public class MergeRequestServiceTest { - private AutoCloseable closeable; - - @BeforeEach - void setUp() { - closeable = MockitoAnnotations.openMocks(this); - } - - @AfterEach - void close() throws Exception { - closeable.close(); - } - - @InjectMocks - private MergeRequestService mergeRequestService; - - @Mock - private GitLabApiExecutor gitLabApiExecutor; - - @Nested - class Get { - - @Test - @DisplayName("GitLabからMRを取得しdto->formの変換ができること") - void formTest() { - var assignee = UserDto.builder() - .id(1) - .username("assignee_username1") - .name("assignee_name1") - .state("active") - .build(); - var mergeRequestInfoDtos = List.of( - GitLabMergeRequestApiResponseDto.builder() - .assignee(assignee) - .author(UserDto.builder() - .id(11) - .username("author_username11") - .name("author_name11") - .state("active") - .build()) - .webUrl("url1") - .title("title1") - .createdAt(LocalDateTime.of(1970, 1, 1, 0, 0, 0)) - .updatedAt(LocalDateTime.of(2000, 1, 1, 0, 0, 0)) - .build(), - GitLabMergeRequestApiResponseDto.builder() - .assignee(assignee) - .author(UserDto.builder() - .id(11) - .username("author_username12") - .name("author_name12") - .state("active") - .build()) - .webUrl("url2") - .title("title2") - .createdAt(LocalDateTime.of(1970, 1, 1, 0, 0, 0)) - .updatedAt(LocalDateTime.of(2000, 1, 1, 0, 0, 0)) - .build(), - GitLabMergeRequestApiResponseDto.builder() - .assignee(assignee) - .author(UserDto.builder() - .id(13) - .username("author_username13") - .name("author_name13") - .state("active") - .build()) - .webUrl("url3") - .title("title3") - .createdAt(LocalDateTime.of(1970, 1, 1, 0, 0, 0)) - .updatedAt(LocalDateTime.of(2000, 1, 1, 0, 0, 0)) - .build() - ); - doReturn(mergeRequestInfoDtos).when(gitLabApiExecutor).getMergeRequests(anyString()); - var expected = List.of(new MrInfoForm( - new UserForm(1, "assignee_username1", "assignee_name1", "active", null, null), - List.of( - new MrDetailForm( - "title1", - "url1", - new UserForm( - 11, - "author_username11", - "author_name11", - "active", - null, - null - ), - LocalDateTime.of(1970, 1, 1, 9, 0, 0), - LocalDateTime.of(2000, 1, 1, 9, 0, 0) - ), - new MrDetailForm( - "title2", - "url2", - new UserForm( - 11, - "author_username12", - "author_name12", - "active", - null, - null - ), - LocalDateTime.of(1970, 1, 1, 9, 0, 0), - LocalDateTime.of(2000, 1, 1, 9, 0, 0) - ), - new MrDetailForm( - "title3", - "url3", - new UserForm( - 13, - "author_username13", - "author_name13", - "active", - null, - null - ), - LocalDateTime.of(1970, 1, 1, 9, 0, 0), - LocalDateTime.of(2000, 1, 1, 9, 0, 0) - - ) - ), - 3 - )); - - var actual = mergeRequestService.get(anyString()); - - assertThat(actual).usingRecursiveComparison().isEqualTo(expected); - } + private AutoCloseable closeable; - @Test - @DisplayName("MRのAssigneeが未指定の場合") - void noAssigneeTest() { - var mergeRequestInfoDtos = List.of( - GitLabMergeRequestApiResponseDto.builder() - .assignee(null) - .author(UserDto.builder() - .id(11) - .username("author_username11") - .name("author_name11") - .state("active") - .build()) - .webUrl("url1") - .title("title1") - .createdAt(LocalDateTime.of(1970, 1, 1, 0, 0, 0)) - .updatedAt(LocalDateTime.of(2000, 1, 1, 0, 0, 0)) - .build() - ); - doReturn(mergeRequestInfoDtos).when(gitLabApiExecutor).getMergeRequests(anyString()); - var expected = List.of(new MrInfoForm( - UserForm.empty(), - List.of( - new MrDetailForm( - "title1", - "url1", - new UserForm(11, "author_username11", "author_name11", "active", null, null), - LocalDateTime.of(1970, 1, 1, 9, 0, 0), - LocalDateTime.of(2000, 1, 1, 9, 0, 0) - ) - ), - 1 - )); - - var actual = mergeRequestService.get(anyString()); - - assertThat(actual).usingRecursiveComparison().isEqualTo(expected); + @BeforeEach + void setUp() { + closeable = MockitoAnnotations.openMocks(this); } - @Test - @DisplayName("MR0件の場合") - void noMrTest() { - doReturn(List.of()).when(gitLabApiExecutor).getMergeRequests(anyString()); - var expected = List.of(); - var actual = mergeRequestService.get(anyString()); + @AfterEach + void close() throws Exception { + closeable.close(); + } - assertThat(actual).usingRecursiveComparison().isEqualTo(expected); + @InjectMocks + private MergeRequestService mergeRequestService; + + @Mock + private GitLabApiExecutor gitLabApiExecutor; + + @Nested + class Get { + + @Test + @DisplayName("GitLabからMRを取得しdto->formの変換ができること") + void formTest() { + final var assignee = UserDto.builder() + .id(1) + .username("assignee_username1") + .name("assignee_name1") + .state("active") + .build(); + final var mergeRequestInfoDtos = List.of( + GitLabMergeRequestApiResponseDto.builder() + .assignee(assignee) + .author(UserDto.builder() + .id(11) + .username("author_username11") + .name("author_name11") + .state("active") + .build()) + .webUrl("url1") + .title("title1") + .createdAt(OffsetDateTime.of(1970, 1, 1, 0, 0, 0, 0, ZoneOffset.of("+09:00"))) + .updatedAt(OffsetDateTime.of(2000, 1, 1, 0, 0, 0, 0, ZoneOffset.of("+09:00"))) + .build(), + GitLabMergeRequestApiResponseDto.builder() + .assignee(assignee) + .author(UserDto.builder() + .id(11) + .username("author_username12") + .name("author_name12") + .state("active") + .build()) + .webUrl("url2") + .title("title2") + .createdAt(OffsetDateTime.of(1970, 1, 1, 0, 0, 0, 0, ZoneOffset.of("+09:00"))) + .updatedAt(OffsetDateTime.of(2000, 1, 1, 0, 0, 0, 0, ZoneOffset.of("+09:00"))) + .build(), + GitLabMergeRequestApiResponseDto.builder() + .assignee(assignee) + .author(UserDto.builder() + .id(13) + .username("author_username13") + .name("author_name13") + .state("active") + .build()) + .webUrl("url3") + .title("title3") + .createdAt(OffsetDateTime.of(1970, 1, 1, 0, 0, 0, 0, ZoneOffset.of("+09:00"))) + .updatedAt(OffsetDateTime.of(2000, 1, 1, 0, 0, 0, 0, ZoneOffset.of("+09:00"))) + .build() + ); + doReturn(mergeRequestInfoDtos).when(gitLabApiExecutor).getMergeRequests(anyString()); + final var expected = List.of(new MrInfoForm( + new UserForm(1, "assignee_username1", "assignee_name1", "active", null, null), + List.of( + new MrDetailForm( + "title1", + "url1", + new UserForm( + 11, + "author_username11", + "author_name11", + "active", + null, + null + ), + OffsetDateTime.of(1970, 1, 1, 0, 0, 0, 0, ZoneOffset.of("+09:00")), + OffsetDateTime.of(2000, 1, 1, 0, 0, 0, 0, ZoneOffset.of("+09:00")) + ), + new MrDetailForm( + "title2", + "url2", + new UserForm( + 11, + "author_username12", + "author_name12", + "active", + null, + null + ), + OffsetDateTime.of(1970, 1, 1, 0, 0, 0, 0, ZoneOffset.of("+09:00")), + OffsetDateTime.of(2000, 1, 1, 0, 0, 0, 0, ZoneOffset.of("+09:00")) + ), + new MrDetailForm( + "title3", + "url3", + new UserForm( + 13, + "author_username13", + "author_name13", + "active", + null, + null + ), + OffsetDateTime.of(1970, 1, 1, 0, 0, 0, 0, ZoneOffset.of("+09:00")), + OffsetDateTime.of(2000, 1, 1, 0, 0, 0, 0, ZoneOffset.of("+09:00")) + + ) + ), + 3 + )); + + final var actual = mergeRequestService.get(anyString()); + + assertThat(actual).usingRecursiveComparison().isEqualTo(expected); + } + + @Test + @DisplayName("MRのAssigneeが未指定の場合") + void noAssigneeTest() { + final var mergeRequestInfoDtos = List.of( + GitLabMergeRequestApiResponseDto.builder() + .assignee(null) + .author(UserDto.builder() + .id(11) + .username("author_username11") + .name("author_name11") + .state("active") + .build()) + .webUrl("url1") + .title("title1") + .createdAt(OffsetDateTime.of(1970, 1, 1, 9, 0, 0, 0, ZoneOffset.of("+09:00"))) + .updatedAt(OffsetDateTime.of(2000, 1, 1, 9, 0, 0, 0, ZoneOffset.of("+09:00"))) + .build() + ); + doReturn(mergeRequestInfoDtos).when(gitLabApiExecutor).getMergeRequests(anyString()); + final var expected = List.of(new MrInfoForm( + UserForm.empty(), + List.of( + new MrDetailForm( + "title1", + "url1", + new UserForm(11, "author_username11", "author_name11", "active", null, null), + OffsetDateTime.of(1970, 1, 1, 9, 0, 0, 0, ZoneOffset.of("+09:00")), + OffsetDateTime.of(2000, 1, 1, 9, 0, 0, 0, ZoneOffset.of("+09:00")) + ) + ), + 1 + )); + + final var actual = mergeRequestService.get(anyString()); + + assertThat(actual).usingRecursiveComparison().isEqualTo(expected); + } + + @Test + @DisplayName("MR0件の場合") + void noMrTest() { + doReturn(List.of()).when(gitLabApiExecutor).getMergeRequests(anyString()); + final var expected = List.of(); + final var actual = mergeRequestService.get(anyString()); + + assertThat(actual).usingRecursiveComparison().isEqualTo(expected); + } } - } }