From 20a0a11b9ec9c4e0811995533a96fdb5c39fd8ef Mon Sep 17 00:00:00 2001 From: AlexanderGarifullin Date: Sun, 15 Dec 2024 19:34:21 +0500 Subject: [PATCH 01/60] =?UTF-8?q?dev/codeforces/=20=D0=94=D0=BE=D0=B1?= =?UTF-8?q?=D0=B0=D0=B2=D0=B8=D0=BB=20RestClient?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/com/cf/cfteam/config/AppConfig.java | 12 ++++++++++++ src/main/resources/application.yml | 2 +- src/main/resources/codeforces.yml | 4 ++++ 3 files changed, 17 insertions(+), 1 deletion(-) create mode 100644 src/main/resources/codeforces.yml diff --git a/src/main/java/com/cf/cfteam/config/AppConfig.java b/src/main/java/com/cf/cfteam/config/AppConfig.java index 9f1750e..4c2d356 100644 --- a/src/main/java/com/cf/cfteam/config/AppConfig.java +++ b/src/main/java/com/cf/cfteam/config/AppConfig.java @@ -2,8 +2,11 @@ import com.cf.cfteam.services.security.MyUserDetailsService; import lombok.RequiredArgsConstructor; +import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.http.HttpHeaders; +import org.springframework.http.MediaType; import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.authentication.AuthenticationProvider; import org.springframework.security.authentication.dao.DaoAuthenticationProvider; @@ -11,6 +14,7 @@ import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.security.crypto.password.PasswordEncoder; +import org.springframework.web.client.RestClient; @Configuration @@ -41,4 +45,12 @@ public UserDetailsService userDetailsService() { public PasswordEncoder passwordEncoder() { return new BCryptPasswordEncoder(); } + + @Bean + public RestClient restClient(@Value("${codeforces.api.base.url}") String url) { + return RestClient.builder() + .baseUrl(url) + .defaultHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE) + .build(); + } } diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index 3f1b622..a581d4c 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -7,7 +7,7 @@ spring: password: ${POSTGRES_PASSWORD:123} driver-class-name: org.postgresql.Driver config: - import: jwt.yml + import: jwt.yml, codeforces.yml profiles: active: prod diff --git a/src/main/resources/codeforces.yml b/src/main/resources/codeforces.yml new file mode 100644 index 0000000..66b11ef --- /dev/null +++ b/src/main/resources/codeforces.yml @@ -0,0 +1,4 @@ +codeforces: + api: + base: + url: https://codeforces.com/api/ \ No newline at end of file From 43380cc9b4b44eef3ae6e89e241f5e9da9c669e6 Mon Sep 17 00:00:00 2001 From: AlexanderGarifullin Date: Sun, 15 Dec 2024 19:36:14 +0500 Subject: [PATCH 02/60] =?UTF-8?q?dev/codeforces/=20=D0=94=D0=BE=D0=B1?= =?UTF-8?q?=D0=B0=D0=B2=D0=B8=D0=BB=20=D1=88=D0=B0=D0=B1=D0=BB=D0=BE=D0=BD?= =?UTF-8?q?=20=D0=B4=D0=BB=D1=8F=20=D1=80=D0=B0=D0=B1=D0=BE=D1=82=D1=8B=20?= =?UTF-8?q?=D1=81=20Codeforces=20Api?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../codeforces/teams/CfTeamController.java | 50 +++++++++++++++++++ .../teams/CfTeamGroupController.java | 50 +++++++++++++++++++ .../codeforces/users/CfUserController.java | 50 +++++++++++++++++++ .../users/CfUserGroupController.java | 50 +++++++++++++++++++ .../{CfUsersTeam.java => CfTeam.java} | 4 +- ...UsersTeamsGroup.java => CfTeamsGroup.java} | 4 +- .../jpa/codeforces/CfUsersTeamRepository.java | 4 +- .../CfUsersTeamsGroupRepository.java | 4 +- .../codeforces/teams/CfTeamGroupService.java | 9 ++++ .../codeforces/teams/CfTeamService.java | 4 ++ .../codeforces/users/CfUserGroupService.java | 9 ++++ .../codeforces/users/CfUserService.java | 4 ++ .../codeforces/teams/CfTeamGroupPayload.java | 4 ++ .../codeforces/teams/CfTeamPayload.java | 4 ++ .../codeforces/users/CfUserGroupPayload.java | 4 ++ .../codeforces/users/CfUserPayload.java | 4 ++ 16 files changed, 250 insertions(+), 8 deletions(-) create mode 100644 src/main/java/com/cf/cfteam/controllers/codeforces/teams/CfTeamController.java create mode 100644 src/main/java/com/cf/cfteam/controllers/codeforces/teams/CfTeamGroupController.java create mode 100644 src/main/java/com/cf/cfteam/controllers/codeforces/users/CfUserController.java create mode 100644 src/main/java/com/cf/cfteam/controllers/codeforces/users/CfUserGroupController.java rename src/main/java/com/cf/cfteam/models/entities/codeforces/{CfUsersTeam.java => CfTeam.java} (93%) rename src/main/java/com/cf/cfteam/models/entities/codeforces/{CfUsersTeamsGroup.java => CfTeamsGroup.java} (91%) create mode 100644 src/main/java/com/cf/cfteam/services/codeforces/teams/CfTeamGroupService.java create mode 100644 src/main/java/com/cf/cfteam/services/codeforces/teams/CfTeamService.java create mode 100644 src/main/java/com/cf/cfteam/services/codeforces/users/CfUserGroupService.java create mode 100644 src/main/java/com/cf/cfteam/services/codeforces/users/CfUserService.java create mode 100644 src/main/java/com/cf/cfteam/transfer/payloads/codeforces/teams/CfTeamGroupPayload.java create mode 100644 src/main/java/com/cf/cfteam/transfer/payloads/codeforces/teams/CfTeamPayload.java create mode 100644 src/main/java/com/cf/cfteam/transfer/payloads/codeforces/users/CfUserGroupPayload.java create mode 100644 src/main/java/com/cf/cfteam/transfer/payloads/codeforces/users/CfUserPayload.java diff --git a/src/main/java/com/cf/cfteam/controllers/codeforces/teams/CfTeamController.java b/src/main/java/com/cf/cfteam/controllers/codeforces/teams/CfTeamController.java new file mode 100644 index 0000000..1ab10e7 --- /dev/null +++ b/src/main/java/com/cf/cfteam/controllers/codeforces/teams/CfTeamController.java @@ -0,0 +1,50 @@ +package com.cf.cfteam.controllers.codeforces.teams; + +import com.cf.cfteam.services.codeforces.teams.CfTeamService; +import com.cf.cfteam.transfer.payloads.codeforces.teams.CfTeamPayload; +import lombok.RequiredArgsConstructor; +import org.springframework.http.ResponseEntity; +import org.springframework.security.core.Authentication; +import org.springframework.web.bind.annotation.*; + +@RestController +@RequiredArgsConstructor +@RequestMapping("/cf/team") +public class CfTeamController { + + private final CfTeamService cfTeamService; + + @PostMapping + public ResponseEntity createCfTeam(@RequestBody CfTeamPayload cfTeamPayload, + Authentication authentication) { + return ResponseEntity.ok().build(); + } + + @GetMapping + public ResponseEntity getAllCfTeams() { + return ResponseEntity.ok().build(); + } + + @GetMapping("/{id}") + public ResponseEntity getCfTeamById(@PathVariable Long id) { + return ResponseEntity.ok().build(); + } + + @PutMapping("/{id}") + public ResponseEntity updateCfTeam(@PathVariable Long id, + @RequestBody CfTeamPayload cFTeamPayload, + Authentication authentication) { + return ResponseEntity.ok().build(); + } + + @DeleteMapping + public ResponseEntity deleteAllCfTeams(Authentication authentication) { + return ResponseEntity.ok().build(); + } + + @DeleteMapping("/{id}") + public ResponseEntity deleteCfTeamById(@PathVariable Long id, + Authentication authentication) { + return ResponseEntity.ok().build(); + } +} diff --git a/src/main/java/com/cf/cfteam/controllers/codeforces/teams/CfTeamGroupController.java b/src/main/java/com/cf/cfteam/controllers/codeforces/teams/CfTeamGroupController.java new file mode 100644 index 0000000..f55bc9c --- /dev/null +++ b/src/main/java/com/cf/cfteam/controllers/codeforces/teams/CfTeamGroupController.java @@ -0,0 +1,50 @@ +package com.cf.cfteam.controllers.codeforces.teams; + +import com.cf.cfteam.services.codeforces.teams.CfTeamGroupService; +import com.cf.cfteam.transfer.payloads.codeforces.teams.CfTeamGroupPayload; +import lombok.RequiredArgsConstructor; +import org.springframework.http.ResponseEntity; +import org.springframework.security.core.Authentication; +import org.springframework.web.bind.annotation.*; + +@RestController +@RequiredArgsConstructor +@RequestMapping("/cf/team/group") +public class CfTeamGroupController { + + private final CfTeamGroupService cfTeamGroupService; + + @PostMapping + public ResponseEntity createCfTeamGroup(@RequestBody CfTeamGroupPayload cfTeamGroupPayload, + Authentication authentication) { + return ResponseEntity.ok().build(); + } + + @GetMapping + public ResponseEntity getAllCfTeamGroups() { + return ResponseEntity.ok().build(); + } + + @GetMapping("/{id}") + public ResponseEntity getCfTeamGroupById(@PathVariable Long id) { + return ResponseEntity.ok().build(); + } + + @PutMapping("/{id}") + public ResponseEntity updateCfTeamGroup(@PathVariable Long id, + @RequestBody CfTeamGroupPayload cfTeamGroupPayload, + Authentication authentication) { + return ResponseEntity.ok().build(); + } + + @DeleteMapping + public ResponseEntity deleteAllCfTeamGroups(Authentication authentication) { + return ResponseEntity.ok().build(); + } + + @DeleteMapping("/{id}") + public ResponseEntity deleteCfTeamGroupById(@PathVariable Long id, + Authentication authentication) { + return ResponseEntity.ok().build(); + } +} diff --git a/src/main/java/com/cf/cfteam/controllers/codeforces/users/CfUserController.java b/src/main/java/com/cf/cfteam/controllers/codeforces/users/CfUserController.java new file mode 100644 index 0000000..be3d038 --- /dev/null +++ b/src/main/java/com/cf/cfteam/controllers/codeforces/users/CfUserController.java @@ -0,0 +1,50 @@ +package com.cf.cfteam.controllers.codeforces.users; + +import com.cf.cfteam.services.codeforces.users.CfUserService; +import com.cf.cfteam.transfer.payloads.codeforces.users.CfUserPayload; +import lombok.RequiredArgsConstructor; +import org.springframework.http.ResponseEntity; +import org.springframework.security.core.Authentication; +import org.springframework.web.bind.annotation.*; + +@RestController +@RequiredArgsConstructor +@RequestMapping("/cf/user") +public class CfUserController { + + private final CfUserService cfUserService; + + @PostMapping + public ResponseEntity createCfUser(@RequestBody CfUserPayload cfUserPayload, + Authentication authentication) { + return ResponseEntity.ok().build(); + } + + @GetMapping + public ResponseEntity getAllCfUsers() { + return ResponseEntity.ok().build(); + } + + @GetMapping("/{id}") + public ResponseEntity getCfUserById(@PathVariable Long id) { + return ResponseEntity.ok().build(); + } + + @PutMapping("/{id}") + public ResponseEntity updateCfUser(@PathVariable Long id, + @RequestBody CfUserPayload cfUserPayload, + Authentication authentication) { + return ResponseEntity.ok().build(); + } + + @DeleteMapping + public ResponseEntity deleteAllCfUsers(Authentication authentication) { + return ResponseEntity.ok().build(); + } + + @DeleteMapping("/{id}") + public ResponseEntity deleteCfUserById(@PathVariable Long id, + Authentication authentication) { + return ResponseEntity.ok().build(); + } +} diff --git a/src/main/java/com/cf/cfteam/controllers/codeforces/users/CfUserGroupController.java b/src/main/java/com/cf/cfteam/controllers/codeforces/users/CfUserGroupController.java new file mode 100644 index 0000000..aa99b84 --- /dev/null +++ b/src/main/java/com/cf/cfteam/controllers/codeforces/users/CfUserGroupController.java @@ -0,0 +1,50 @@ +package com.cf.cfteam.controllers.codeforces.users; + +import com.cf.cfteam.services.codeforces.users.CfUserGroupService; +import com.cf.cfteam.transfer.payloads.codeforces.users.CfUserGroupPayload; +import lombok.RequiredArgsConstructor; +import org.springframework.http.ResponseEntity; +import org.springframework.security.core.Authentication; +import org.springframework.web.bind.annotation.*; + +@RestController +@RequiredArgsConstructor +@RequestMapping("/cf/user/group") +public class CfUserGroupController { + + private final CfUserGroupService cfUserGroupService; + + @PostMapping + public ResponseEntity createCfUserGroup(@RequestBody CfUserGroupPayload cfUserGroupPayload, + Authentication authentication) { + return ResponseEntity.ok().build(); + } + + @GetMapping + public ResponseEntity getAllCfUserGroups() { + return ResponseEntity.ok().build(); + } + + @GetMapping("/{id}") + public ResponseEntity getCfUserGroupById(@PathVariable Long id) { + return ResponseEntity.ok().build(); + } + + @PutMapping("/{id}") + public ResponseEntity updateCfUserGroup(@PathVariable Long id, + @RequestBody CfUserGroupPayload cfUserGroupPayload, + Authentication authentication) { + return ResponseEntity.ok().build(); + } + + @DeleteMapping + public ResponseEntity deleteAllCfUserGroups(Authentication authentication) { + return ResponseEntity.ok().build(); + } + + @DeleteMapping("/{id}") + public ResponseEntity deleteCfUserGroupById(@PathVariable Long id, + Authentication authentication) { + return ResponseEntity.ok().build(); + } +} diff --git a/src/main/java/com/cf/cfteam/models/entities/codeforces/CfUsersTeam.java b/src/main/java/com/cf/cfteam/models/entities/codeforces/CfTeam.java similarity index 93% rename from src/main/java/com/cf/cfteam/models/entities/codeforces/CfUsersTeam.java rename to src/main/java/com/cf/cfteam/models/entities/codeforces/CfTeam.java index 321a9a3..301719a 100644 --- a/src/main/java/com/cf/cfteam/models/entities/codeforces/CfUsersTeam.java +++ b/src/main/java/com/cf/cfteam/models/entities/codeforces/CfTeam.java @@ -11,7 +11,7 @@ @EqualsAndHashCode(exclude = "group") @Entity @Table(name = "t_cf_teams", schema = "codeforces") -public class CfUsersTeam { +public class CfTeam { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @@ -34,5 +34,5 @@ public class CfUsersTeam { @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "c_group_id", nullable = false) - private CfUsersTeamsGroup group; + private CfTeamsGroup group; } diff --git a/src/main/java/com/cf/cfteam/models/entities/codeforces/CfUsersTeamsGroup.java b/src/main/java/com/cf/cfteam/models/entities/codeforces/CfTeamsGroup.java similarity index 91% rename from src/main/java/com/cf/cfteam/models/entities/codeforces/CfUsersTeamsGroup.java rename to src/main/java/com/cf/cfteam/models/entities/codeforces/CfTeamsGroup.java index 9f06d8c..0d73718 100644 --- a/src/main/java/com/cf/cfteam/models/entities/codeforces/CfUsersTeamsGroup.java +++ b/src/main/java/com/cf/cfteam/models/entities/codeforces/CfTeamsGroup.java @@ -14,7 +14,7 @@ @EqualsAndHashCode(exclude = {"user", "cfTeams"}) @Entity @Table(name = "t_cf_users_teams_groups", schema = "codeforces") -public class CfUsersTeamsGroup { +public class CfTeamsGroup { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @@ -31,5 +31,5 @@ public class CfUsersTeamsGroup { private User user; @OneToMany(mappedBy = "group", cascade = CascadeType.ALL, orphanRemoval = true) - private List cfTeams; + private List cfTeams; } diff --git a/src/main/java/com/cf/cfteam/repositories/jpa/codeforces/CfUsersTeamRepository.java b/src/main/java/com/cf/cfteam/repositories/jpa/codeforces/CfUsersTeamRepository.java index f48ccde..fe2d6d1 100644 --- a/src/main/java/com/cf/cfteam/repositories/jpa/codeforces/CfUsersTeamRepository.java +++ b/src/main/java/com/cf/cfteam/repositories/jpa/codeforces/CfUsersTeamRepository.java @@ -1,7 +1,7 @@ package com.cf.cfteam.repositories.jpa.codeforces; -import com.cf.cfteam.models.entities.codeforces.CfUsersTeam; +import com.cf.cfteam.models.entities.codeforces.CfTeam; import org.springframework.data.jpa.repository.JpaRepository; -public interface CfUsersTeamRepository extends JpaRepository { +public interface CfUsersTeamRepository extends JpaRepository { } diff --git a/src/main/java/com/cf/cfteam/repositories/jpa/codeforces/CfUsersTeamsGroupRepository.java b/src/main/java/com/cf/cfteam/repositories/jpa/codeforces/CfUsersTeamsGroupRepository.java index bade64b..440af72 100644 --- a/src/main/java/com/cf/cfteam/repositories/jpa/codeforces/CfUsersTeamsGroupRepository.java +++ b/src/main/java/com/cf/cfteam/repositories/jpa/codeforces/CfUsersTeamsGroupRepository.java @@ -1,7 +1,7 @@ package com.cf.cfteam.repositories.jpa.codeforces; -import com.cf.cfteam.models.entities.codeforces.CfUsersTeamsGroup; +import com.cf.cfteam.models.entities.codeforces.CfTeamsGroup; import org.springframework.data.jpa.repository.JpaRepository; -public interface CfUsersTeamsGroupRepository extends JpaRepository { +public interface CfUsersTeamsGroupRepository extends JpaRepository { } diff --git a/src/main/java/com/cf/cfteam/services/codeforces/teams/CfTeamGroupService.java b/src/main/java/com/cf/cfteam/services/codeforces/teams/CfTeamGroupService.java new file mode 100644 index 0000000..519b62f --- /dev/null +++ b/src/main/java/com/cf/cfteam/services/codeforces/teams/CfTeamGroupService.java @@ -0,0 +1,9 @@ +package com.cf.cfteam.services.codeforces.teams; + +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +@Service +@RequiredArgsConstructor +public class CfTeamGroupService { +} diff --git a/src/main/java/com/cf/cfteam/services/codeforces/teams/CfTeamService.java b/src/main/java/com/cf/cfteam/services/codeforces/teams/CfTeamService.java new file mode 100644 index 0000000..54a118a --- /dev/null +++ b/src/main/java/com/cf/cfteam/services/codeforces/teams/CfTeamService.java @@ -0,0 +1,4 @@ +package com.cf.cfteam.services.codeforces.teams; + +public class CfTeamService { +} diff --git a/src/main/java/com/cf/cfteam/services/codeforces/users/CfUserGroupService.java b/src/main/java/com/cf/cfteam/services/codeforces/users/CfUserGroupService.java new file mode 100644 index 0000000..0062c79 --- /dev/null +++ b/src/main/java/com/cf/cfteam/services/codeforces/users/CfUserGroupService.java @@ -0,0 +1,9 @@ +package com.cf.cfteam.services.codeforces.users; + +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +@Service +@RequiredArgsConstructor +public class CfUserGroupService { +} diff --git a/src/main/java/com/cf/cfteam/services/codeforces/users/CfUserService.java b/src/main/java/com/cf/cfteam/services/codeforces/users/CfUserService.java new file mode 100644 index 0000000..75d60ca --- /dev/null +++ b/src/main/java/com/cf/cfteam/services/codeforces/users/CfUserService.java @@ -0,0 +1,4 @@ +package com.cf.cfteam.services.codeforces.users; + +public class CfUserService { +} diff --git a/src/main/java/com/cf/cfteam/transfer/payloads/codeforces/teams/CfTeamGroupPayload.java b/src/main/java/com/cf/cfteam/transfer/payloads/codeforces/teams/CfTeamGroupPayload.java new file mode 100644 index 0000000..5e8c3aa --- /dev/null +++ b/src/main/java/com/cf/cfteam/transfer/payloads/codeforces/teams/CfTeamGroupPayload.java @@ -0,0 +1,4 @@ +package com.cf.cfteam.transfer.payloads.codeforces.teams; + +public class CfTeamGroupPayload { +} diff --git a/src/main/java/com/cf/cfteam/transfer/payloads/codeforces/teams/CfTeamPayload.java b/src/main/java/com/cf/cfteam/transfer/payloads/codeforces/teams/CfTeamPayload.java new file mode 100644 index 0000000..09c5734 --- /dev/null +++ b/src/main/java/com/cf/cfteam/transfer/payloads/codeforces/teams/CfTeamPayload.java @@ -0,0 +1,4 @@ +package com.cf.cfteam.transfer.payloads.codeforces.teams; + +public class CfTeamPayload { +} diff --git a/src/main/java/com/cf/cfteam/transfer/payloads/codeforces/users/CfUserGroupPayload.java b/src/main/java/com/cf/cfteam/transfer/payloads/codeforces/users/CfUserGroupPayload.java new file mode 100644 index 0000000..54bf5dc --- /dev/null +++ b/src/main/java/com/cf/cfteam/transfer/payloads/codeforces/users/CfUserGroupPayload.java @@ -0,0 +1,4 @@ +package com.cf.cfteam.transfer.payloads.codeforces.users; + +public class CfUserGroupPayload { +} diff --git a/src/main/java/com/cf/cfteam/transfer/payloads/codeforces/users/CfUserPayload.java b/src/main/java/com/cf/cfteam/transfer/payloads/codeforces/users/CfUserPayload.java new file mode 100644 index 0000000..66dec2f --- /dev/null +++ b/src/main/java/com/cf/cfteam/transfer/payloads/codeforces/users/CfUserPayload.java @@ -0,0 +1,4 @@ +package com.cf.cfteam.transfer.payloads.codeforces.users; + +public class CfUserPayload { +} From 3293399a9c97182fe640c3d45a48467b3dbcaae4 Mon Sep 17 00:00:00 2001 From: AlexanderGarifullin Date: Sun, 15 Dec 2024 19:38:33 +0500 Subject: [PATCH 03/60] =?UTF-8?q?dev/codeforces/=20=D0=A0=D0=B0=D0=B7?= =?UTF-8?q?=D0=B4=D0=B5=D0=BB=D0=B8=D0=BB=20Codeforces=20=D0=BF=D0=B0?= =?UTF-8?q?=D0=BA=D0=B5=D1=82=D1=8B=20=D1=80=D0=B5=D0=BF=D0=BE=D0=B7=D0=B8?= =?UTF-8?q?=D1=82=D0=BE=D1=80=D0=B8=D0=B5=D0=B2=20=D0=B8=20=D0=BC=D0=BE?= =?UTF-8?q?=D0=B4=D0=B5=D0=BB=D0=B5=D0=B9=20=D0=BD=D0=B0=20=D0=BF=D0=B0?= =?UTF-8?q?=D0=BA=D0=B5=D1=82=D1=8B=20teams=20=D0=B8=20users?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../cfteam/models/entities/codeforces/{ => teams}/CfTeam.java | 2 +- .../models/entities/codeforces/{ => teams}/CfTeamsGroup.java | 2 +- .../cfteam/models/entities/codeforces/{ => users}/CfUser.java | 2 +- .../models/entities/codeforces/{ => users}/CfUsersGroup.java | 2 +- .../jpa/codeforces/{ => teams}/CfUsersTeamRepository.java | 4 ++-- .../codeforces/{ => teams}/CfUsersTeamsGroupRepository.java | 4 ++-- .../jpa/codeforces/{ => users}/CfUserRepository.java | 4 ++-- .../jpa/codeforces/{ => users}/CfUsersGroupRepository.java | 4 ++-- 8 files changed, 12 insertions(+), 12 deletions(-) rename src/main/java/com/cf/cfteam/models/entities/codeforces/{ => teams}/CfTeam.java (93%) rename src/main/java/com/cf/cfteam/models/entities/codeforces/{ => teams}/CfTeamsGroup.java (93%) rename src/main/java/com/cf/cfteam/models/entities/codeforces/{ => users}/CfUser.java (91%) rename src/main/java/com/cf/cfteam/models/entities/codeforces/{ => users}/CfUsersGroup.java (93%) rename src/main/java/com/cf/cfteam/repositories/jpa/codeforces/{ => teams}/CfUsersTeamRepository.java (54%) rename src/main/java/com/cf/cfteam/repositories/jpa/codeforces/{ => teams}/CfUsersTeamsGroupRepository.java (55%) rename src/main/java/com/cf/cfteam/repositories/jpa/codeforces/{ => users}/CfUserRepository.java (53%) rename src/main/java/com/cf/cfteam/repositories/jpa/codeforces/{ => users}/CfUsersGroupRepository.java (54%) diff --git a/src/main/java/com/cf/cfteam/models/entities/codeforces/CfTeam.java b/src/main/java/com/cf/cfteam/models/entities/codeforces/teams/CfTeam.java similarity index 93% rename from src/main/java/com/cf/cfteam/models/entities/codeforces/CfTeam.java rename to src/main/java/com/cf/cfteam/models/entities/codeforces/teams/CfTeam.java index 301719a..515fe32 100644 --- a/src/main/java/com/cf/cfteam/models/entities/codeforces/CfTeam.java +++ b/src/main/java/com/cf/cfteam/models/entities/codeforces/teams/CfTeam.java @@ -1,4 +1,4 @@ -package com.cf.cfteam.models.entities.codeforces; +package com.cf.cfteam.models.entities.codeforces.teams; import jakarta.persistence.*; import lombok.*; diff --git a/src/main/java/com/cf/cfteam/models/entities/codeforces/CfTeamsGroup.java b/src/main/java/com/cf/cfteam/models/entities/codeforces/teams/CfTeamsGroup.java similarity index 93% rename from src/main/java/com/cf/cfteam/models/entities/codeforces/CfTeamsGroup.java rename to src/main/java/com/cf/cfteam/models/entities/codeforces/teams/CfTeamsGroup.java index 0d73718..316cb8f 100644 --- a/src/main/java/com/cf/cfteam/models/entities/codeforces/CfTeamsGroup.java +++ b/src/main/java/com/cf/cfteam/models/entities/codeforces/teams/CfTeamsGroup.java @@ -1,4 +1,4 @@ -package com.cf.cfteam.models.entities.codeforces; +package com.cf.cfteam.models.entities.codeforces.teams; import com.cf.cfteam.models.entities.security.User; import jakarta.persistence.*; diff --git a/src/main/java/com/cf/cfteam/models/entities/codeforces/CfUser.java b/src/main/java/com/cf/cfteam/models/entities/codeforces/users/CfUser.java similarity index 91% rename from src/main/java/com/cf/cfteam/models/entities/codeforces/CfUser.java rename to src/main/java/com/cf/cfteam/models/entities/codeforces/users/CfUser.java index 248a39c..d75e20c 100644 --- a/src/main/java/com/cf/cfteam/models/entities/codeforces/CfUser.java +++ b/src/main/java/com/cf/cfteam/models/entities/codeforces/users/CfUser.java @@ -1,4 +1,4 @@ -package com.cf.cfteam.models.entities.codeforces; +package com.cf.cfteam.models.entities.codeforces.users; import jakarta.persistence.*; import lombok.*; diff --git a/src/main/java/com/cf/cfteam/models/entities/codeforces/CfUsersGroup.java b/src/main/java/com/cf/cfteam/models/entities/codeforces/users/CfUsersGroup.java similarity index 93% rename from src/main/java/com/cf/cfteam/models/entities/codeforces/CfUsersGroup.java rename to src/main/java/com/cf/cfteam/models/entities/codeforces/users/CfUsersGroup.java index 7ae6f56..941baec 100644 --- a/src/main/java/com/cf/cfteam/models/entities/codeforces/CfUsersGroup.java +++ b/src/main/java/com/cf/cfteam/models/entities/codeforces/users/CfUsersGroup.java @@ -1,4 +1,4 @@ -package com.cf.cfteam.models.entities.codeforces; +package com.cf.cfteam.models.entities.codeforces.users; import com.cf.cfteam.models.entities.security.User; import jakarta.persistence.*; diff --git a/src/main/java/com/cf/cfteam/repositories/jpa/codeforces/CfUsersTeamRepository.java b/src/main/java/com/cf/cfteam/repositories/jpa/codeforces/teams/CfUsersTeamRepository.java similarity index 54% rename from src/main/java/com/cf/cfteam/repositories/jpa/codeforces/CfUsersTeamRepository.java rename to src/main/java/com/cf/cfteam/repositories/jpa/codeforces/teams/CfUsersTeamRepository.java index fe2d6d1..c6368f0 100644 --- a/src/main/java/com/cf/cfteam/repositories/jpa/codeforces/CfUsersTeamRepository.java +++ b/src/main/java/com/cf/cfteam/repositories/jpa/codeforces/teams/CfUsersTeamRepository.java @@ -1,6 +1,6 @@ -package com.cf.cfteam.repositories.jpa.codeforces; +package com.cf.cfteam.repositories.jpa.codeforces.teams; -import com.cf.cfteam.models.entities.codeforces.CfTeam; +import com.cf.cfteam.models.entities.codeforces.teams.CfTeam; import org.springframework.data.jpa.repository.JpaRepository; public interface CfUsersTeamRepository extends JpaRepository { diff --git a/src/main/java/com/cf/cfteam/repositories/jpa/codeforces/CfUsersTeamsGroupRepository.java b/src/main/java/com/cf/cfteam/repositories/jpa/codeforces/teams/CfUsersTeamsGroupRepository.java similarity index 55% rename from src/main/java/com/cf/cfteam/repositories/jpa/codeforces/CfUsersTeamsGroupRepository.java rename to src/main/java/com/cf/cfteam/repositories/jpa/codeforces/teams/CfUsersTeamsGroupRepository.java index 440af72..3cc5bbc 100644 --- a/src/main/java/com/cf/cfteam/repositories/jpa/codeforces/CfUsersTeamsGroupRepository.java +++ b/src/main/java/com/cf/cfteam/repositories/jpa/codeforces/teams/CfUsersTeamsGroupRepository.java @@ -1,6 +1,6 @@ -package com.cf.cfteam.repositories.jpa.codeforces; +package com.cf.cfteam.repositories.jpa.codeforces.teams; -import com.cf.cfteam.models.entities.codeforces.CfTeamsGroup; +import com.cf.cfteam.models.entities.codeforces.teams.CfTeamsGroup; import org.springframework.data.jpa.repository.JpaRepository; public interface CfUsersTeamsGroupRepository extends JpaRepository { diff --git a/src/main/java/com/cf/cfteam/repositories/jpa/codeforces/CfUserRepository.java b/src/main/java/com/cf/cfteam/repositories/jpa/codeforces/users/CfUserRepository.java similarity index 53% rename from src/main/java/com/cf/cfteam/repositories/jpa/codeforces/CfUserRepository.java rename to src/main/java/com/cf/cfteam/repositories/jpa/codeforces/users/CfUserRepository.java index f389a6a..93c8594 100644 --- a/src/main/java/com/cf/cfteam/repositories/jpa/codeforces/CfUserRepository.java +++ b/src/main/java/com/cf/cfteam/repositories/jpa/codeforces/users/CfUserRepository.java @@ -1,6 +1,6 @@ -package com.cf.cfteam.repositories.jpa.codeforces; +package com.cf.cfteam.repositories.jpa.codeforces.users; -import com.cf.cfteam.models.entities.codeforces.CfUser; +import com.cf.cfteam.models.entities.codeforces.users.CfUser; import org.springframework.data.jpa.repository.JpaRepository; public interface CfUserRepository extends JpaRepository { diff --git a/src/main/java/com/cf/cfteam/repositories/jpa/codeforces/CfUsersGroupRepository.java b/src/main/java/com/cf/cfteam/repositories/jpa/codeforces/users/CfUsersGroupRepository.java similarity index 54% rename from src/main/java/com/cf/cfteam/repositories/jpa/codeforces/CfUsersGroupRepository.java rename to src/main/java/com/cf/cfteam/repositories/jpa/codeforces/users/CfUsersGroupRepository.java index a112656..3f34fa2 100644 --- a/src/main/java/com/cf/cfteam/repositories/jpa/codeforces/CfUsersGroupRepository.java +++ b/src/main/java/com/cf/cfteam/repositories/jpa/codeforces/users/CfUsersGroupRepository.java @@ -1,6 +1,6 @@ -package com.cf.cfteam.repositories.jpa.codeforces; +package com.cf.cfteam.repositories.jpa.codeforces.users; -import com.cf.cfteam.models.entities.codeforces.CfUsersGroup; +import com.cf.cfteam.models.entities.codeforces.users.CfUsersGroup; import org.springframework.data.jpa.repository.JpaRepository; public interface CfUsersGroupRepository extends JpaRepository { From ccf6888dbecb170a31234041d669095b4f9bb218 Mon Sep 17 00:00:00 2001 From: AlexanderGarifullin Date: Sun, 15 Dec 2024 19:43:32 +0500 Subject: [PATCH 04/60] =?UTF-8?q?dev/codeforces/=20=D0=A1=D0=B4=D0=B5?= =?UTF-8?q?=D0=BB=D0=B0=D0=BB=20=D0=B1=D0=B8=D0=BD=D1=8B=20=D0=B8=D0=B7=20?= =?UTF-8?q?=D1=81=D0=B5=D1=80=D0=B2=D0=B8=D1=81=D0=BE=D0=B2=20CfTeamServic?= =?UTF-8?q?e=20=D0=B8=20CfUserService?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../cf/cfteam/services/codeforces/teams/CfTeamService.java | 5 +++++ .../cf/cfteam/services/codeforces/users/CfUserService.java | 5 +++++ 2 files changed, 10 insertions(+) diff --git a/src/main/java/com/cf/cfteam/services/codeforces/teams/CfTeamService.java b/src/main/java/com/cf/cfteam/services/codeforces/teams/CfTeamService.java index 54a118a..7e4fb4a 100644 --- a/src/main/java/com/cf/cfteam/services/codeforces/teams/CfTeamService.java +++ b/src/main/java/com/cf/cfteam/services/codeforces/teams/CfTeamService.java @@ -1,4 +1,9 @@ package com.cf.cfteam.services.codeforces.teams; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +@Service +@RequiredArgsConstructor public class CfTeamService { } diff --git a/src/main/java/com/cf/cfteam/services/codeforces/users/CfUserService.java b/src/main/java/com/cf/cfteam/services/codeforces/users/CfUserService.java index 75d60ca..1932082 100644 --- a/src/main/java/com/cf/cfteam/services/codeforces/users/CfUserService.java +++ b/src/main/java/com/cf/cfteam/services/codeforces/users/CfUserService.java @@ -1,4 +1,9 @@ package com.cf.cfteam.services.codeforces.users; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +@Service +@RequiredArgsConstructor public class CfUserService { } From ac43cd2205ee0fa20d770f288ba96eba70d8531b Mon Sep 17 00:00:00 2001 From: AlexanderGarifullin Date: Mon, 16 Dec 2024 14:03:21 +0500 Subject: [PATCH 05/60] =?UTF-8?q?dev/codeforces/=20=D0=A3=D0=B4=D0=B0?= =?UTF-8?q?=D0=BB=D0=B8=D0=BB=20=D0=BD=D0=B5=D0=B0=D0=BA=D1=82=D1=83=D0=B0?= =?UTF-8?q?=D0=BB=D1=8C=D0=BD=D1=8B=D0=B5=20=D1=84=D0=B0=D0=B9=D0=BB=D1=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../codeforces/teams/CfTeamController.java | 50 ------------------- .../teams/CfTeamGroupController.java | 50 ------------------- .../codeforces/users/CfUserController.java | 50 ------------------- .../users/CfUserGroupController.java | 50 ------------------- .../entities/codeforces/teams/CfTeam.java | 38 -------------- .../entities/codeforces/users/CfUser.java | 30 ----------- .../codeforces/users/CfUsersGroup.java | 35 ------------- .../teams/CfUsersTeamRepository.java | 7 --- .../teams/CfUsersTeamsGroupRepository.java | 7 --- .../codeforces/users/CfUserRepository.java | 7 --- .../users/CfUsersGroupRepository.java | 7 --- .../codeforces/teams/CfTeamGroupService.java | 9 ---- .../codeforces/teams/CfTeamService.java | 9 ---- .../codeforces/users/CfUserGroupService.java | 9 ---- .../codeforces/users/CfUserService.java | 9 ---- .../codeforces/teams/CfTeamGroupPayload.java | 4 -- .../codeforces/teams/CfTeamPayload.java | 4 -- .../codeforces/users/CfUserGroupPayload.java | 4 -- .../codeforces/users/CfUserPayload.java | 4 -- 19 files changed, 383 deletions(-) delete mode 100644 src/main/java/com/cf/cfteam/controllers/codeforces/teams/CfTeamController.java delete mode 100644 src/main/java/com/cf/cfteam/controllers/codeforces/teams/CfTeamGroupController.java delete mode 100644 src/main/java/com/cf/cfteam/controllers/codeforces/users/CfUserController.java delete mode 100644 src/main/java/com/cf/cfteam/controllers/codeforces/users/CfUserGroupController.java delete mode 100644 src/main/java/com/cf/cfteam/models/entities/codeforces/teams/CfTeam.java delete mode 100644 src/main/java/com/cf/cfteam/models/entities/codeforces/users/CfUser.java delete mode 100644 src/main/java/com/cf/cfteam/models/entities/codeforces/users/CfUsersGroup.java delete mode 100644 src/main/java/com/cf/cfteam/repositories/jpa/codeforces/teams/CfUsersTeamRepository.java delete mode 100644 src/main/java/com/cf/cfteam/repositories/jpa/codeforces/teams/CfUsersTeamsGroupRepository.java delete mode 100644 src/main/java/com/cf/cfteam/repositories/jpa/codeforces/users/CfUserRepository.java delete mode 100644 src/main/java/com/cf/cfteam/repositories/jpa/codeforces/users/CfUsersGroupRepository.java delete mode 100644 src/main/java/com/cf/cfteam/services/codeforces/teams/CfTeamGroupService.java delete mode 100644 src/main/java/com/cf/cfteam/services/codeforces/teams/CfTeamService.java delete mode 100644 src/main/java/com/cf/cfteam/services/codeforces/users/CfUserGroupService.java delete mode 100644 src/main/java/com/cf/cfteam/services/codeforces/users/CfUserService.java delete mode 100644 src/main/java/com/cf/cfteam/transfer/payloads/codeforces/teams/CfTeamGroupPayload.java delete mode 100644 src/main/java/com/cf/cfteam/transfer/payloads/codeforces/teams/CfTeamPayload.java delete mode 100644 src/main/java/com/cf/cfteam/transfer/payloads/codeforces/users/CfUserGroupPayload.java delete mode 100644 src/main/java/com/cf/cfteam/transfer/payloads/codeforces/users/CfUserPayload.java diff --git a/src/main/java/com/cf/cfteam/controllers/codeforces/teams/CfTeamController.java b/src/main/java/com/cf/cfteam/controllers/codeforces/teams/CfTeamController.java deleted file mode 100644 index 1ab10e7..0000000 --- a/src/main/java/com/cf/cfteam/controllers/codeforces/teams/CfTeamController.java +++ /dev/null @@ -1,50 +0,0 @@ -package com.cf.cfteam.controllers.codeforces.teams; - -import com.cf.cfteam.services.codeforces.teams.CfTeamService; -import com.cf.cfteam.transfer.payloads.codeforces.teams.CfTeamPayload; -import lombok.RequiredArgsConstructor; -import org.springframework.http.ResponseEntity; -import org.springframework.security.core.Authentication; -import org.springframework.web.bind.annotation.*; - -@RestController -@RequiredArgsConstructor -@RequestMapping("/cf/team") -public class CfTeamController { - - private final CfTeamService cfTeamService; - - @PostMapping - public ResponseEntity createCfTeam(@RequestBody CfTeamPayload cfTeamPayload, - Authentication authentication) { - return ResponseEntity.ok().build(); - } - - @GetMapping - public ResponseEntity getAllCfTeams() { - return ResponseEntity.ok().build(); - } - - @GetMapping("/{id}") - public ResponseEntity getCfTeamById(@PathVariable Long id) { - return ResponseEntity.ok().build(); - } - - @PutMapping("/{id}") - public ResponseEntity updateCfTeam(@PathVariable Long id, - @RequestBody CfTeamPayload cFTeamPayload, - Authentication authentication) { - return ResponseEntity.ok().build(); - } - - @DeleteMapping - public ResponseEntity deleteAllCfTeams(Authentication authentication) { - return ResponseEntity.ok().build(); - } - - @DeleteMapping("/{id}") - public ResponseEntity deleteCfTeamById(@PathVariable Long id, - Authentication authentication) { - return ResponseEntity.ok().build(); - } -} diff --git a/src/main/java/com/cf/cfteam/controllers/codeforces/teams/CfTeamGroupController.java b/src/main/java/com/cf/cfteam/controllers/codeforces/teams/CfTeamGroupController.java deleted file mode 100644 index f55bc9c..0000000 --- a/src/main/java/com/cf/cfteam/controllers/codeforces/teams/CfTeamGroupController.java +++ /dev/null @@ -1,50 +0,0 @@ -package com.cf.cfteam.controllers.codeforces.teams; - -import com.cf.cfteam.services.codeforces.teams.CfTeamGroupService; -import com.cf.cfteam.transfer.payloads.codeforces.teams.CfTeamGroupPayload; -import lombok.RequiredArgsConstructor; -import org.springframework.http.ResponseEntity; -import org.springframework.security.core.Authentication; -import org.springframework.web.bind.annotation.*; - -@RestController -@RequiredArgsConstructor -@RequestMapping("/cf/team/group") -public class CfTeamGroupController { - - private final CfTeamGroupService cfTeamGroupService; - - @PostMapping - public ResponseEntity createCfTeamGroup(@RequestBody CfTeamGroupPayload cfTeamGroupPayload, - Authentication authentication) { - return ResponseEntity.ok().build(); - } - - @GetMapping - public ResponseEntity getAllCfTeamGroups() { - return ResponseEntity.ok().build(); - } - - @GetMapping("/{id}") - public ResponseEntity getCfTeamGroupById(@PathVariable Long id) { - return ResponseEntity.ok().build(); - } - - @PutMapping("/{id}") - public ResponseEntity updateCfTeamGroup(@PathVariable Long id, - @RequestBody CfTeamGroupPayload cfTeamGroupPayload, - Authentication authentication) { - return ResponseEntity.ok().build(); - } - - @DeleteMapping - public ResponseEntity deleteAllCfTeamGroups(Authentication authentication) { - return ResponseEntity.ok().build(); - } - - @DeleteMapping("/{id}") - public ResponseEntity deleteCfTeamGroupById(@PathVariable Long id, - Authentication authentication) { - return ResponseEntity.ok().build(); - } -} diff --git a/src/main/java/com/cf/cfteam/controllers/codeforces/users/CfUserController.java b/src/main/java/com/cf/cfteam/controllers/codeforces/users/CfUserController.java deleted file mode 100644 index be3d038..0000000 --- a/src/main/java/com/cf/cfteam/controllers/codeforces/users/CfUserController.java +++ /dev/null @@ -1,50 +0,0 @@ -package com.cf.cfteam.controllers.codeforces.users; - -import com.cf.cfteam.services.codeforces.users.CfUserService; -import com.cf.cfteam.transfer.payloads.codeforces.users.CfUserPayload; -import lombok.RequiredArgsConstructor; -import org.springframework.http.ResponseEntity; -import org.springframework.security.core.Authentication; -import org.springframework.web.bind.annotation.*; - -@RestController -@RequiredArgsConstructor -@RequestMapping("/cf/user") -public class CfUserController { - - private final CfUserService cfUserService; - - @PostMapping - public ResponseEntity createCfUser(@RequestBody CfUserPayload cfUserPayload, - Authentication authentication) { - return ResponseEntity.ok().build(); - } - - @GetMapping - public ResponseEntity getAllCfUsers() { - return ResponseEntity.ok().build(); - } - - @GetMapping("/{id}") - public ResponseEntity getCfUserById(@PathVariable Long id) { - return ResponseEntity.ok().build(); - } - - @PutMapping("/{id}") - public ResponseEntity updateCfUser(@PathVariable Long id, - @RequestBody CfUserPayload cfUserPayload, - Authentication authentication) { - return ResponseEntity.ok().build(); - } - - @DeleteMapping - public ResponseEntity deleteAllCfUsers(Authentication authentication) { - return ResponseEntity.ok().build(); - } - - @DeleteMapping("/{id}") - public ResponseEntity deleteCfUserById(@PathVariable Long id, - Authentication authentication) { - return ResponseEntity.ok().build(); - } -} diff --git a/src/main/java/com/cf/cfteam/controllers/codeforces/users/CfUserGroupController.java b/src/main/java/com/cf/cfteam/controllers/codeforces/users/CfUserGroupController.java deleted file mode 100644 index aa99b84..0000000 --- a/src/main/java/com/cf/cfteam/controllers/codeforces/users/CfUserGroupController.java +++ /dev/null @@ -1,50 +0,0 @@ -package com.cf.cfteam.controllers.codeforces.users; - -import com.cf.cfteam.services.codeforces.users.CfUserGroupService; -import com.cf.cfteam.transfer.payloads.codeforces.users.CfUserGroupPayload; -import lombok.RequiredArgsConstructor; -import org.springframework.http.ResponseEntity; -import org.springframework.security.core.Authentication; -import org.springframework.web.bind.annotation.*; - -@RestController -@RequiredArgsConstructor -@RequestMapping("/cf/user/group") -public class CfUserGroupController { - - private final CfUserGroupService cfUserGroupService; - - @PostMapping - public ResponseEntity createCfUserGroup(@RequestBody CfUserGroupPayload cfUserGroupPayload, - Authentication authentication) { - return ResponseEntity.ok().build(); - } - - @GetMapping - public ResponseEntity getAllCfUserGroups() { - return ResponseEntity.ok().build(); - } - - @GetMapping("/{id}") - public ResponseEntity getCfUserGroupById(@PathVariable Long id) { - return ResponseEntity.ok().build(); - } - - @PutMapping("/{id}") - public ResponseEntity updateCfUserGroup(@PathVariable Long id, - @RequestBody CfUserGroupPayload cfUserGroupPayload, - Authentication authentication) { - return ResponseEntity.ok().build(); - } - - @DeleteMapping - public ResponseEntity deleteAllCfUserGroups(Authentication authentication) { - return ResponseEntity.ok().build(); - } - - @DeleteMapping("/{id}") - public ResponseEntity deleteCfUserGroupById(@PathVariable Long id, - Authentication authentication) { - return ResponseEntity.ok().build(); - } -} diff --git a/src/main/java/com/cf/cfteam/models/entities/codeforces/teams/CfTeam.java b/src/main/java/com/cf/cfteam/models/entities/codeforces/teams/CfTeam.java deleted file mode 100644 index 515fe32..0000000 --- a/src/main/java/com/cf/cfteam/models/entities/codeforces/teams/CfTeam.java +++ /dev/null @@ -1,38 +0,0 @@ -package com.cf.cfteam.models.entities.codeforces.teams; - -import jakarta.persistence.*; -import lombok.*; - -@Builder -@Setter -@Getter -@NoArgsConstructor -@AllArgsConstructor -@EqualsAndHashCode(exclude = "group") -@Entity -@Table(name = "t_cf_teams", schema = "codeforces") -public class CfTeam { - - @Id - @GeneratedValue(strategy = GenerationType.IDENTITY) - private Long id; - - @Column(name = "c_name", nullable = false) - private String name; - - @Column(name = "c_description", nullable = true) - private String description; - - @Column(name = "c_first_user_login", nullable = true) - private String firstUser; - - @Column(name = "c_second_user_login", nullable = true) - private String secondUser; - - @Column(name = "c_third_user_login", nullable = true) - private String thirdUser; - - @ManyToOne(fetch = FetchType.LAZY) - @JoinColumn(name = "c_group_id", nullable = false) - private CfTeamsGroup group; -} diff --git a/src/main/java/com/cf/cfteam/models/entities/codeforces/users/CfUser.java b/src/main/java/com/cf/cfteam/models/entities/codeforces/users/CfUser.java deleted file mode 100644 index d75e20c..0000000 --- a/src/main/java/com/cf/cfteam/models/entities/codeforces/users/CfUser.java +++ /dev/null @@ -1,30 +0,0 @@ -package com.cf.cfteam.models.entities.codeforces.users; - -import jakarta.persistence.*; -import lombok.*; - - -@Builder -@Setter -@Getter -@NoArgsConstructor -@AllArgsConstructor -@EqualsAndHashCode(exclude = "group") -@Entity -@Table(name = "cf_users", schema = "codeforces") -public class CfUser { - - @Id - @GeneratedValue(strategy = GenerationType.IDENTITY) - private Long id; - - @Column(name = "c_name", nullable = false) - private String name; - - @Column(name = "c_description", nullable = true) - private String description; - - @ManyToOne(fetch = FetchType.LAZY) - @JoinColumn(name = "c_group_id", nullable = false) - private CfUsersGroup group; -} diff --git a/src/main/java/com/cf/cfteam/models/entities/codeforces/users/CfUsersGroup.java b/src/main/java/com/cf/cfteam/models/entities/codeforces/users/CfUsersGroup.java deleted file mode 100644 index 941baec..0000000 --- a/src/main/java/com/cf/cfteam/models/entities/codeforces/users/CfUsersGroup.java +++ /dev/null @@ -1,35 +0,0 @@ -package com.cf.cfteam.models.entities.codeforces.users; - -import com.cf.cfteam.models.entities.security.User; -import jakarta.persistence.*; -import lombok.*; - -import java.util.List; - -@Builder -@Setter -@Getter -@NoArgsConstructor -@AllArgsConstructor -@EqualsAndHashCode(exclude = {"user", "cfUsers"}) -@Entity -@Table(name = "t_cf_users_groups", schema = "codeforces") -public class CfUsersGroup { - - @Id - @GeneratedValue(strategy = GenerationType.IDENTITY) - private Long id; - - @Column(name = "c_name", nullable = false) - private String name; - - @Column(name = "c_description", nullable = true) - private String description; - - @ManyToOne(fetch = FetchType.LAZY) - @JoinColumn(name = "c_user_id", nullable = false) - private User user; - - @OneToMany(mappedBy = "group", cascade = CascadeType.ALL, orphanRemoval = true) - private List cfUsers; -} diff --git a/src/main/java/com/cf/cfteam/repositories/jpa/codeforces/teams/CfUsersTeamRepository.java b/src/main/java/com/cf/cfteam/repositories/jpa/codeforces/teams/CfUsersTeamRepository.java deleted file mode 100644 index c6368f0..0000000 --- a/src/main/java/com/cf/cfteam/repositories/jpa/codeforces/teams/CfUsersTeamRepository.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.cf.cfteam.repositories.jpa.codeforces.teams; - -import com.cf.cfteam.models.entities.codeforces.teams.CfTeam; -import org.springframework.data.jpa.repository.JpaRepository; - -public interface CfUsersTeamRepository extends JpaRepository { -} diff --git a/src/main/java/com/cf/cfteam/repositories/jpa/codeforces/teams/CfUsersTeamsGroupRepository.java b/src/main/java/com/cf/cfteam/repositories/jpa/codeforces/teams/CfUsersTeamsGroupRepository.java deleted file mode 100644 index 3cc5bbc..0000000 --- a/src/main/java/com/cf/cfteam/repositories/jpa/codeforces/teams/CfUsersTeamsGroupRepository.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.cf.cfteam.repositories.jpa.codeforces.teams; - -import com.cf.cfteam.models.entities.codeforces.teams.CfTeamsGroup; -import org.springframework.data.jpa.repository.JpaRepository; - -public interface CfUsersTeamsGroupRepository extends JpaRepository { -} diff --git a/src/main/java/com/cf/cfteam/repositories/jpa/codeforces/users/CfUserRepository.java b/src/main/java/com/cf/cfteam/repositories/jpa/codeforces/users/CfUserRepository.java deleted file mode 100644 index 93c8594..0000000 --- a/src/main/java/com/cf/cfteam/repositories/jpa/codeforces/users/CfUserRepository.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.cf.cfteam.repositories.jpa.codeforces.users; - -import com.cf.cfteam.models.entities.codeforces.users.CfUser; -import org.springframework.data.jpa.repository.JpaRepository; - -public interface CfUserRepository extends JpaRepository { -} diff --git a/src/main/java/com/cf/cfteam/repositories/jpa/codeforces/users/CfUsersGroupRepository.java b/src/main/java/com/cf/cfteam/repositories/jpa/codeforces/users/CfUsersGroupRepository.java deleted file mode 100644 index 3f34fa2..0000000 --- a/src/main/java/com/cf/cfteam/repositories/jpa/codeforces/users/CfUsersGroupRepository.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.cf.cfteam.repositories.jpa.codeforces.users; - -import com.cf.cfteam.models.entities.codeforces.users.CfUsersGroup; -import org.springframework.data.jpa.repository.JpaRepository; - -public interface CfUsersGroupRepository extends JpaRepository { -} diff --git a/src/main/java/com/cf/cfteam/services/codeforces/teams/CfTeamGroupService.java b/src/main/java/com/cf/cfteam/services/codeforces/teams/CfTeamGroupService.java deleted file mode 100644 index 519b62f..0000000 --- a/src/main/java/com/cf/cfteam/services/codeforces/teams/CfTeamGroupService.java +++ /dev/null @@ -1,9 +0,0 @@ -package com.cf.cfteam.services.codeforces.teams; - -import lombok.RequiredArgsConstructor; -import org.springframework.stereotype.Service; - -@Service -@RequiredArgsConstructor -public class CfTeamGroupService { -} diff --git a/src/main/java/com/cf/cfteam/services/codeforces/teams/CfTeamService.java b/src/main/java/com/cf/cfteam/services/codeforces/teams/CfTeamService.java deleted file mode 100644 index 7e4fb4a..0000000 --- a/src/main/java/com/cf/cfteam/services/codeforces/teams/CfTeamService.java +++ /dev/null @@ -1,9 +0,0 @@ -package com.cf.cfteam.services.codeforces.teams; - -import lombok.RequiredArgsConstructor; -import org.springframework.stereotype.Service; - -@Service -@RequiredArgsConstructor -public class CfTeamService { -} diff --git a/src/main/java/com/cf/cfteam/services/codeforces/users/CfUserGroupService.java b/src/main/java/com/cf/cfteam/services/codeforces/users/CfUserGroupService.java deleted file mode 100644 index 0062c79..0000000 --- a/src/main/java/com/cf/cfteam/services/codeforces/users/CfUserGroupService.java +++ /dev/null @@ -1,9 +0,0 @@ -package com.cf.cfteam.services.codeforces.users; - -import lombok.RequiredArgsConstructor; -import org.springframework.stereotype.Service; - -@Service -@RequiredArgsConstructor -public class CfUserGroupService { -} diff --git a/src/main/java/com/cf/cfteam/services/codeforces/users/CfUserService.java b/src/main/java/com/cf/cfteam/services/codeforces/users/CfUserService.java deleted file mode 100644 index 1932082..0000000 --- a/src/main/java/com/cf/cfteam/services/codeforces/users/CfUserService.java +++ /dev/null @@ -1,9 +0,0 @@ -package com.cf.cfteam.services.codeforces.users; - -import lombok.RequiredArgsConstructor; -import org.springframework.stereotype.Service; - -@Service -@RequiredArgsConstructor -public class CfUserService { -} diff --git a/src/main/java/com/cf/cfteam/transfer/payloads/codeforces/teams/CfTeamGroupPayload.java b/src/main/java/com/cf/cfteam/transfer/payloads/codeforces/teams/CfTeamGroupPayload.java deleted file mode 100644 index 5e8c3aa..0000000 --- a/src/main/java/com/cf/cfteam/transfer/payloads/codeforces/teams/CfTeamGroupPayload.java +++ /dev/null @@ -1,4 +0,0 @@ -package com.cf.cfteam.transfer.payloads.codeforces.teams; - -public class CfTeamGroupPayload { -} diff --git a/src/main/java/com/cf/cfteam/transfer/payloads/codeforces/teams/CfTeamPayload.java b/src/main/java/com/cf/cfteam/transfer/payloads/codeforces/teams/CfTeamPayload.java deleted file mode 100644 index 09c5734..0000000 --- a/src/main/java/com/cf/cfteam/transfer/payloads/codeforces/teams/CfTeamPayload.java +++ /dev/null @@ -1,4 +0,0 @@ -package com.cf.cfteam.transfer.payloads.codeforces.teams; - -public class CfTeamPayload { -} diff --git a/src/main/java/com/cf/cfteam/transfer/payloads/codeforces/users/CfUserGroupPayload.java b/src/main/java/com/cf/cfteam/transfer/payloads/codeforces/users/CfUserGroupPayload.java deleted file mode 100644 index 54bf5dc..0000000 --- a/src/main/java/com/cf/cfteam/transfer/payloads/codeforces/users/CfUserGroupPayload.java +++ /dev/null @@ -1,4 +0,0 @@ -package com.cf.cfteam.transfer.payloads.codeforces.users; - -public class CfUserGroupPayload { -} diff --git a/src/main/java/com/cf/cfteam/transfer/payloads/codeforces/users/CfUserPayload.java b/src/main/java/com/cf/cfteam/transfer/payloads/codeforces/users/CfUserPayload.java deleted file mode 100644 index 66dec2f..0000000 --- a/src/main/java/com/cf/cfteam/transfer/payloads/codeforces/users/CfUserPayload.java +++ /dev/null @@ -1,4 +0,0 @@ -package com.cf.cfteam.transfer.payloads.codeforces.users; - -public class CfUserPayload { -} From 138aad3799120f3afd91c93ed8c6b96ff5d3036c Mon Sep 17 00:00:00 2001 From: AlexanderGarifullin Date: Mon, 16 Dec 2024 14:04:07 +0500 Subject: [PATCH 06/60] =?UTF-8?q?dev/codeforces/=20=D0=94=D0=BE=D0=B1?= =?UTF-8?q?=D0=B0=D0=B2=D0=B8=D0=BB=20=D0=BD=D0=BE=D0=B2=D1=8B=D0=B5=20?= =?UTF-8?q?=D0=BC=D0=BE=D0=B4=D0=B5=D0=BB=D0=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../{teams/CfTeamsGroup.java => Group.java} | 14 ++++--- .../models/entities/codeforces/Player.java | 32 +++++++++++++++ .../models/entities/codeforces/Team.java | 40 +++++++++++++++++++ 3 files changed, 80 insertions(+), 6 deletions(-) rename src/main/java/com/cf/cfteam/models/entities/codeforces/{teams/CfTeamsGroup.java => Group.java} (66%) create mode 100644 src/main/java/com/cf/cfteam/models/entities/codeforces/Player.java create mode 100644 src/main/java/com/cf/cfteam/models/entities/codeforces/Team.java diff --git a/src/main/java/com/cf/cfteam/models/entities/codeforces/teams/CfTeamsGroup.java b/src/main/java/com/cf/cfteam/models/entities/codeforces/Group.java similarity index 66% rename from src/main/java/com/cf/cfteam/models/entities/codeforces/teams/CfTeamsGroup.java rename to src/main/java/com/cf/cfteam/models/entities/codeforces/Group.java index 316cb8f..3e3bccb 100644 --- a/src/main/java/com/cf/cfteam/models/entities/codeforces/teams/CfTeamsGroup.java +++ b/src/main/java/com/cf/cfteam/models/entities/codeforces/Group.java @@ -1,6 +1,7 @@ -package com.cf.cfteam.models.entities.codeforces.teams; +package com.cf.cfteam.models.entities.codeforces; import com.cf.cfteam.models.entities.security.User; +import com.fasterxml.jackson.annotation.JsonIgnore; import jakarta.persistence.*; import lombok.*; @@ -11,10 +12,10 @@ @Getter @NoArgsConstructor @AllArgsConstructor -@EqualsAndHashCode(exclude = {"user", "cfTeams"}) +@EqualsAndHashCode(exclude = {"user", "teams"}) @Entity -@Table(name = "t_cf_users_teams_groups", schema = "codeforces") -public class CfTeamsGroup { +@Table(name = "t_groups", schema = "codeforces") +public class Group { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @@ -23,13 +24,14 @@ public class CfTeamsGroup { @Column(name = "c_name", nullable = false) private String name; - @Column(name = "c_description", nullable = true) + @Column(name = "c_description") private String description; + @JsonIgnore @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "c_user_id", nullable = false) private User user; @OneToMany(mappedBy = "group", cascade = CascadeType.ALL, orphanRemoval = true) - private List cfTeams; + private List teams; } diff --git a/src/main/java/com/cf/cfteam/models/entities/codeforces/Player.java b/src/main/java/com/cf/cfteam/models/entities/codeforces/Player.java new file mode 100644 index 0000000..aff9233 --- /dev/null +++ b/src/main/java/com/cf/cfteam/models/entities/codeforces/Player.java @@ -0,0 +1,32 @@ +package com.cf.cfteam.models.entities.codeforces; + +import jakarta.persistence.*; +import lombok.*; + +import java.util.ArrayList; +import java.util.List; + +@Builder +@Setter +@Getter +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(exclude = {"teams"}) +@Entity +@Table(name = "t_players", schema = "codeforces") +public class Player { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @Column(name = "c_login", nullable = false) + private String login; + + @ManyToMany(cascade = CascadeType.ALL) + @JoinTable(name = "t_team_player", + joinColumns = @JoinColumn(name="c_player_id", referencedColumnName="id"), + inverseJoinColumns = @JoinColumn(name="c_team_id", referencedColumnName="id")) + @Builder.Default + private List teams = new ArrayList<>(); +} diff --git a/src/main/java/com/cf/cfteam/models/entities/codeforces/Team.java b/src/main/java/com/cf/cfteam/models/entities/codeforces/Team.java new file mode 100644 index 0000000..cf7157c --- /dev/null +++ b/src/main/java/com/cf/cfteam/models/entities/codeforces/Team.java @@ -0,0 +1,40 @@ +package com.cf.cfteam.models.entities.codeforces; + +import com.cf.cfteam.models.entities.security.User; +import jakarta.persistence.*; +import lombok.*; + +import java.util.ArrayList; +import java.util.List; + +@Builder +@Setter +@Getter +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(exclude = {"group", "players"}) +@Entity +@Table(name = "t_teams", schema = "codeforces") +public class Team { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @Column(name = "c_name", nullable = false) + private String name; + + @Column(name = "c_description") + private String description; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "c_group_id", nullable = false) + private Group group; + + @ManyToMany(cascade = CascadeType.ALL) + @JoinTable(name = "t_team_player", + joinColumns = @JoinColumn(name="c_team_id", referencedColumnName="id"), + inverseJoinColumns = @JoinColumn(name="c_player_id", referencedColumnName="id")) + @Builder.Default + private List players = new ArrayList<>(); +} From eaa3de758aba8194485a2a58cf2265f70040f0cf Mon Sep 17 00:00:00 2001 From: AlexanderGarifullin Date: Mon, 16 Dec 2024 14:04:43 +0500 Subject: [PATCH 07/60] =?UTF-8?q?dev/codeforces/=20=D0=9E=D0=B1=D0=BD?= =?UTF-8?q?=D0=BE=D0=B2=D0=B8=D0=BB=20=D0=B1=D0=B0=D0=B7=D1=83=20=D0=B4?= =?UTF-8?q?=D0=B0=D0=BD=D0=BD=D1=8B=D1=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../changelog/16-12-24-set-new-cf-schema.sql | 45 +++++++++++++++++++ .../db/changelog/db.changelog-master.yaml | 7 ++- .../db/changelog/db.changelog-test.yaml | 6 ++- 3 files changed, 56 insertions(+), 2 deletions(-) create mode 100644 src/main/resources/db/changelog/16-12-24-set-new-cf-schema.sql diff --git a/src/main/resources/db/changelog/16-12-24-set-new-cf-schema.sql b/src/main/resources/db/changelog/16-12-24-set-new-cf-schema.sql new file mode 100644 index 0000000..62b04a7 --- /dev/null +++ b/src/main/resources/db/changelog/16-12-24-set-new-cf-schema.sql @@ -0,0 +1,45 @@ +--liquibase formatted sql + +--changeset alexandergarifullin:25 +ALTER TABLE codeforces.t_cf_users_teams_groups RENAME TO t_groups; + +--changeset alexandergarifullin:26 +DROP TABLE IF EXISTS codeforces.t_cf_teams CASCADE; + +--changeset alexandergarifullin:27 +DROP TABLE IF EXISTS codeforces.t_cf_users_groups CASCADE; + +--changeset alexandergarifullin:28 +DROP TABLE IF EXISTS codeforces.cf_users CASCADE; + +--changeset alexandergarifullin:29 +CREATE TABLE codeforces.t_players +( + id BIGSERIAL PRIMARY KEY, + c_login TEXT NOT NULL UNIQUE +); + +--changeset alexandergarifullin:31 +CREATE TABLE codeforces.t_teams +( + id BIGSERIAL PRIMARY KEY, + c_name TEXT NOT NULL, + c_description TEXT NULL, + c_group_id BIGINT NOT NULL, + CONSTRAINT fk_team_group FOREIGN KEY (c_group_id ) REFERENCES codeforces.t_groups (id) +); + +--changeset alexandergarifullin:32 +CREATE TABLE codeforces.t_team_player_match +( + id BIGSERIAL PRIMARY KEY, + c_description TEXT NOT NULL, + c_team_id BIGINT NOT NULL, + c_player_id BIGINT NOT NULL, + CONSTRAINT fk_match_team FOREIGN KEY (c_team_id) REFERENCES codeforces.t_teams (id), + CONSTRAINT fk_match_player FOREIGN KEY (c_player_id) REFERENCES codeforces.t_players (id) +); + + + + diff --git a/src/main/resources/db/changelog/db.changelog-master.yaml b/src/main/resources/db/changelog/db.changelog-master.yaml index e37ca76..b02ee85 100644 --- a/src/main/resources/db/changelog/db.changelog-master.yaml +++ b/src/main/resources/db/changelog/db.changelog-master.yaml @@ -10,4 +10,9 @@ databaseChangeLog: - include: file: db/changelog/set-ctime-default-values.sql - include: - file: db/changelog/remove-ctime.sql \ No newline at end of file + file: db/changelog/remove-ctime.sql + - include: + file: db/changelog/16-12-24-set-new-cf-schema.sql + - include: + file: db/changelog/16-12-24-2.sql + diff --git a/src/main/resources/db/changelog/db.changelog-test.yaml b/src/main/resources/db/changelog/db.changelog-test.yaml index d404583..e49b392 100644 --- a/src/main/resources/db/changelog/db.changelog-test.yaml +++ b/src/main/resources/db/changelog/db.changelog-test.yaml @@ -12,4 +12,8 @@ databaseChangeLog: - include: file: db/changelog/remove-ctime.sql - include: - file: db/changelog/init-security-changelog.sql \ No newline at end of file + file: db/changelog/init-security-changelog.sql + - include: + file: db/changelog/16-12-24-set-new-cf-schema.sql + - include: + file: db/changelog/16-12-24-2.sql \ No newline at end of file From 8ea2b38fc3b6a693d7068cec9424a50ea8c5f7db Mon Sep 17 00:00:00 2001 From: AlexanderGarifullin Date: Mon, 16 Dec 2024 14:05:07 +0500 Subject: [PATCH 08/60] =?UTF-8?q?dev/codeforces/=20=D0=9E=D0=B1=D0=BD?= =?UTF-8?q?=D0=BE=D0=B2=D0=B8=D0=BB=20=D0=B1=D0=B0=D0=B7=D1=83=20=D0=B4?= =?UTF-8?q?=D0=B0=D0=BD=D0=BD=D1=8B=D1=85=202?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/resources/db/changelog/16-12-24-2.sql | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 src/main/resources/db/changelog/16-12-24-2.sql diff --git a/src/main/resources/db/changelog/16-12-24-2.sql b/src/main/resources/db/changelog/16-12-24-2.sql new file mode 100644 index 0000000..89043f2 --- /dev/null +++ b/src/main/resources/db/changelog/16-12-24-2.sql @@ -0,0 +1,11 @@ +--liquibase formatted sql + +--changeset alexandergarifullin:33 +ALTER TABLE codeforces.t_team_player_match DROP COLUMN c_description; + +--changeset alexandergarifullin:34 +ALTER TABLE codeforces.t_team_player_match RENAME TO t_team_player; + +--changeset alexandergarifullin:35 +CREATE INDEX idx_players_c_login ON codeforces.t_players(c_login); + From 67c0d7a643817626613ab61d2082e83330bb2285 Mon Sep 17 00:00:00 2001 From: AlexanderGarifullin Date: Mon, 16 Dec 2024 14:05:29 +0500 Subject: [PATCH 09/60] =?UTF-8?q?dev/codeforces/=20=D0=A1=D0=B4=D0=B5?= =?UTF-8?q?=D0=BB=D0=B0=D0=BB=20=D1=80=D0=B5=D0=BF=D0=BE=D0=B7=D0=B8=D1=82?= =?UTF-8?q?=D0=BE=D1=80=D0=B8=D0=B8=20=D0=B4=D0=BB=D1=8F=20=D0=BD=D0=BE?= =?UTF-8?q?=D0=B2=D1=8B=D1=85=20=D0=BC=D0=BE=D0=B4=D0=B5=D0=BB=D0=B5=D0=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../repositories/jpa/codeforces/GroupRepository.java | 11 +++++++++++ .../repositories/jpa/codeforces/PlayerRepository.java | 7 +++++++ .../repositories/jpa/codeforces/TeamRepository.java | 7 +++++++ 3 files changed, 25 insertions(+) create mode 100644 src/main/java/com/cf/cfteam/repositories/jpa/codeforces/GroupRepository.java create mode 100644 src/main/java/com/cf/cfteam/repositories/jpa/codeforces/PlayerRepository.java create mode 100644 src/main/java/com/cf/cfteam/repositories/jpa/codeforces/TeamRepository.java diff --git a/src/main/java/com/cf/cfteam/repositories/jpa/codeforces/GroupRepository.java b/src/main/java/com/cf/cfteam/repositories/jpa/codeforces/GroupRepository.java new file mode 100644 index 0000000..94f7951 --- /dev/null +++ b/src/main/java/com/cf/cfteam/repositories/jpa/codeforces/GroupRepository.java @@ -0,0 +1,11 @@ +package com.cf.cfteam.repositories.jpa.codeforces; + +import com.cf.cfteam.models.entities.codeforces.Group; +import com.cf.cfteam.models.entities.security.User; +import org.springframework.data.jpa.repository.JpaRepository; + +import java.util.List; + +public interface GroupRepository extends JpaRepository { + List findByUser(User user); +} diff --git a/src/main/java/com/cf/cfteam/repositories/jpa/codeforces/PlayerRepository.java b/src/main/java/com/cf/cfteam/repositories/jpa/codeforces/PlayerRepository.java new file mode 100644 index 0000000..eec3610 --- /dev/null +++ b/src/main/java/com/cf/cfteam/repositories/jpa/codeforces/PlayerRepository.java @@ -0,0 +1,7 @@ +package com.cf.cfteam.repositories.jpa.codeforces; + +import com.cf.cfteam.models.entities.codeforces.Player; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface PlayerRepository extends JpaRepository { +} diff --git a/src/main/java/com/cf/cfteam/repositories/jpa/codeforces/TeamRepository.java b/src/main/java/com/cf/cfteam/repositories/jpa/codeforces/TeamRepository.java new file mode 100644 index 0000000..b194985 --- /dev/null +++ b/src/main/java/com/cf/cfteam/repositories/jpa/codeforces/TeamRepository.java @@ -0,0 +1,7 @@ +package com.cf.cfteam.repositories.jpa.codeforces; + +import com.cf.cfteam.models.entities.codeforces.Team; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface TeamRepository extends JpaRepository { +} From 01c0e02b93583a9e75048ba97e88a2d98fbc5759 Mon Sep 17 00:00:00 2001 From: AlexanderGarifullin Date: Mon, 16 Dec 2024 14:06:06 +0500 Subject: [PATCH 10/60] =?UTF-8?q?dev/codeforces/=20=D0=94=D0=BE=D0=B1?= =?UTF-8?q?=D0=B0=D0=B2=D0=B8=D0=BB=20payload=20=D0=B4=D0=BB=D1=8F=20?= =?UTF-8?q?=D0=BD=D0=BE=D0=B2=D1=8B=D1=85=20=D0=BC=D0=BE=D0=B4=D0=B5=D0=BB?= =?UTF-8?q?=D0=B5=D0=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../transfer/payloads/codeforces/GroupPayload.java | 10 ++++++++++ .../transfer/payloads/codeforces/PlayerPayload.java | 7 +++++++ .../transfer/payloads/codeforces/TeamPayload.java | 7 +++++++ 3 files changed, 24 insertions(+) create mode 100644 src/main/java/com/cf/cfteam/transfer/payloads/codeforces/GroupPayload.java create mode 100644 src/main/java/com/cf/cfteam/transfer/payloads/codeforces/PlayerPayload.java create mode 100644 src/main/java/com/cf/cfteam/transfer/payloads/codeforces/TeamPayload.java diff --git a/src/main/java/com/cf/cfteam/transfer/payloads/codeforces/GroupPayload.java b/src/main/java/com/cf/cfteam/transfer/payloads/codeforces/GroupPayload.java new file mode 100644 index 0000000..808eac8 --- /dev/null +++ b/src/main/java/com/cf/cfteam/transfer/payloads/codeforces/GroupPayload.java @@ -0,0 +1,10 @@ +package com.cf.cfteam.transfer.payloads.codeforces; + +import lombok.Builder; + +@Builder +public record GroupPayload( + String name, + String description +) { +} diff --git a/src/main/java/com/cf/cfteam/transfer/payloads/codeforces/PlayerPayload.java b/src/main/java/com/cf/cfteam/transfer/payloads/codeforces/PlayerPayload.java new file mode 100644 index 0000000..aec7e33 --- /dev/null +++ b/src/main/java/com/cf/cfteam/transfer/payloads/codeforces/PlayerPayload.java @@ -0,0 +1,7 @@ +package com.cf.cfteam.transfer.payloads.codeforces; + +import lombok.Builder; + +@Builder +public class PlayerPayload { +} diff --git a/src/main/java/com/cf/cfteam/transfer/payloads/codeforces/TeamPayload.java b/src/main/java/com/cf/cfteam/transfer/payloads/codeforces/TeamPayload.java new file mode 100644 index 0000000..db11fe6 --- /dev/null +++ b/src/main/java/com/cf/cfteam/transfer/payloads/codeforces/TeamPayload.java @@ -0,0 +1,7 @@ +package com.cf.cfteam.transfer.payloads.codeforces; + +import lombok.Builder; + +@Builder +public class TeamPayload { +} From a72be82dba52c4d8dfc3291daa0d8f979e161ea5 Mon Sep 17 00:00:00 2001 From: AlexanderGarifullin Date: Mon, 16 Dec 2024 14:06:24 +0500 Subject: [PATCH 11/60] =?UTF-8?q?dev/codeforces/=20=D0=94=D0=BE=D0=B1?= =?UTF-8?q?=D0=B0=D0=B2=D0=B8=D0=BB=20=D1=81=D0=B5=D1=80=D0=B2=D0=B8=D1=81?= =?UTF-8?q?=D1=8B=20=D0=B4=D0=BB=D1=8F=20=D0=BD=D0=BE=D0=B2=D1=8B=D1=85=20?= =?UTF-8?q?=D0=BC=D0=BE=D0=B4=D0=B5=D0=BB=D0=B5=D0=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../services/codeforces/GroupService.java | 63 +++++++++++++++++++ .../services/codeforces/PlayerService.java | 9 +++ .../services/codeforces/TeamService.java | 9 +++ 3 files changed, 81 insertions(+) create mode 100644 src/main/java/com/cf/cfteam/services/codeforces/GroupService.java create mode 100644 src/main/java/com/cf/cfteam/services/codeforces/PlayerService.java create mode 100644 src/main/java/com/cf/cfteam/services/codeforces/TeamService.java diff --git a/src/main/java/com/cf/cfteam/services/codeforces/GroupService.java b/src/main/java/com/cf/cfteam/services/codeforces/GroupService.java new file mode 100644 index 0000000..9b9f816 --- /dev/null +++ b/src/main/java/com/cf/cfteam/services/codeforces/GroupService.java @@ -0,0 +1,63 @@ +package com.cf.cfteam.services.codeforces; + +import com.cf.cfteam.exceptions.codeforces.GroupNotFoundException; +import com.cf.cfteam.exceptions.security.UserNotFoundException; +import com.cf.cfteam.mappers.codeforces.GroupMapper; +import com.cf.cfteam.models.entities.codeforces.Group; +import com.cf.cfteam.models.entities.security.User; +import com.cf.cfteam.repositories.jpa.codeforces.GroupRepository; +import com.cf.cfteam.repositories.jpa.security.UserRepository; +import com.cf.cfteam.transfer.payloads.codeforces.GroupPayload; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +import java.util.List; + +@Service +@RequiredArgsConstructor +public class GroupService { + + private final GroupRepository groupRepository; + private final UserRepository userRepository; + + public List getAllGroupsByUser(Long userId) { + User user = userRepository.findById(userId) + .orElseThrow(() -> new UserNotFoundException(userId)); + return groupRepository.findByUser(user); + } + + public Group getGroupById(Long groupId) { + return groupRepository.findById(groupId) + .orElseThrow(() -> new GroupNotFoundException(groupId)); + } + + public Group addGroupToUser(Long userId, GroupPayload groupPayload) { + User user = userRepository.findById(userId) + .orElseThrow(() -> new UserNotFoundException(userId)); + + Group group = GroupMapper.fromPayloadToEntity(groupPayload, user); + + return groupRepository.save(group); + } + + public Group updateGroup(Long groupId, GroupPayload groupPayload) { + Group group = groupRepository.findById(groupId) + .orElseThrow(() -> new GroupNotFoundException(groupId)); + + Group updatedGroup = GroupMapper.updateEntityFromPayload(group, groupPayload); + + return groupRepository.save(updatedGroup); + } + + + public void deleteGroup(Long groupId) { + groupRepository.deleteById(groupId); + } + + public void deleteAllGroupsByUser(Long userId) { + User user = userRepository.findById(userId) + .orElseThrow(() -> new UserNotFoundException(userId)); + List groups = groupRepository.findByUser(user); + groupRepository.deleteAll(groups); + } +} diff --git a/src/main/java/com/cf/cfteam/services/codeforces/PlayerService.java b/src/main/java/com/cf/cfteam/services/codeforces/PlayerService.java new file mode 100644 index 0000000..8899242 --- /dev/null +++ b/src/main/java/com/cf/cfteam/services/codeforces/PlayerService.java @@ -0,0 +1,9 @@ +package com.cf.cfteam.services.codeforces; + +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +@Service +@RequiredArgsConstructor +public class PlayerService { +} diff --git a/src/main/java/com/cf/cfteam/services/codeforces/TeamService.java b/src/main/java/com/cf/cfteam/services/codeforces/TeamService.java new file mode 100644 index 0000000..7a9f31f --- /dev/null +++ b/src/main/java/com/cf/cfteam/services/codeforces/TeamService.java @@ -0,0 +1,9 @@ +package com.cf.cfteam.services.codeforces; + +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +@Service +@RequiredArgsConstructor +public class TeamService { +} From 5c7ae6805d3dfbcb9d66fc809d9525ef622cc269 Mon Sep 17 00:00:00 2001 From: AlexanderGarifullin Date: Mon, 16 Dec 2024 14:06:43 +0500 Subject: [PATCH 12/60] =?UTF-8?q?dev/codeforces/=20=D0=94=D0=BE=D0=B1?= =?UTF-8?q?=D0=B0=D0=B2=D0=B8=D0=BB=20=D0=BA=D0=BE=D0=BD=D1=82=D1=80=D0=BE?= =?UTF-8?q?=D0=BB=D0=BB=D0=B5=D1=80=D1=8B=20=D0=B4=D0=BB=D1=8F=20=D0=BD?= =?UTF-8?q?=D0=BE=D0=B2=D1=8B=D1=85=20=D0=BC=D0=BE=D0=B4=D0=B5=D0=BB=D0=B5?= =?UTF-8?q?=D0=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../codeforces/GroupController.java | 57 +++++++++++++++++++ .../codeforces/PlayerController.java | 4 ++ .../codeforces/TeamController.java | 4 ++ 3 files changed, 65 insertions(+) create mode 100644 src/main/java/com/cf/cfteam/controllers/codeforces/GroupController.java create mode 100644 src/main/java/com/cf/cfteam/controllers/codeforces/PlayerController.java create mode 100644 src/main/java/com/cf/cfteam/controllers/codeforces/TeamController.java diff --git a/src/main/java/com/cf/cfteam/controllers/codeforces/GroupController.java b/src/main/java/com/cf/cfteam/controllers/codeforces/GroupController.java new file mode 100644 index 0000000..b9a33dd --- /dev/null +++ b/src/main/java/com/cf/cfteam/controllers/codeforces/GroupController.java @@ -0,0 +1,57 @@ +package com.cf.cfteam.controllers.codeforces; + +import com.cf.cfteam.models.entities.codeforces.Group; +import com.cf.cfteam.services.codeforces.GroupService; +import com.cf.cfteam.transfer.payloads.codeforces.GroupPayload; +import lombok.RequiredArgsConstructor; +import org.springframework.http.ResponseEntity; +import org.springframework.security.core.Authentication; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +@RestController +@RequiredArgsConstructor +@RequestMapping("api/cf/groups") +public class GroupController { + + private final GroupService groupService; + + @GetMapping("/user/{userId}") + public ResponseEntity> getAllGroupsByUser(@PathVariable Long userId, Authentication authentication) { + List groups = groupService.getAllGroupsByUser(userId); + return ResponseEntity.ok(groups); + } + + @GetMapping("/{groupId}") + public ResponseEntity getGroupById(@PathVariable Long groupId, Authentication authentication) { + Group group = groupService.getGroupById(groupId); + return ResponseEntity.ok(group); + } + + @PostMapping("/user/{userId}") + public ResponseEntity addGroupToUser(@PathVariable Long userId, @RequestBody GroupPayload groupPayload, + Authentication authentication) { + Group createdGroup = groupService.addGroupToUser(userId, groupPayload); + return ResponseEntity.ok(createdGroup); + } + + @PutMapping("/{groupId}") + public ResponseEntity updateGroup(@PathVariable Long groupId, @RequestBody GroupPayload groupPayload, + Authentication authentication) { + Group group = groupService.updateGroup(groupId, groupPayload); + return ResponseEntity.ok(group); + } + + @DeleteMapping("/{groupId}") + public ResponseEntity deleteGroup(@PathVariable Long groupId, Authentication authentication) { + groupService.deleteGroup(groupId); + return ResponseEntity.noContent().build(); + } + + @DeleteMapping("/user/{userId}") + public ResponseEntity deleteAllGroupsByUser(@PathVariable Long userId, Authentication authentication) { + groupService.deleteAllGroupsByUser(userId); + return ResponseEntity.noContent().build(); + } +} diff --git a/src/main/java/com/cf/cfteam/controllers/codeforces/PlayerController.java b/src/main/java/com/cf/cfteam/controllers/codeforces/PlayerController.java new file mode 100644 index 0000000..01812b3 --- /dev/null +++ b/src/main/java/com/cf/cfteam/controllers/codeforces/PlayerController.java @@ -0,0 +1,4 @@ +package com.cf.cfteam.controllers.codeforces; + +public class PlayerController { +} diff --git a/src/main/java/com/cf/cfteam/controllers/codeforces/TeamController.java b/src/main/java/com/cf/cfteam/controllers/codeforces/TeamController.java new file mode 100644 index 0000000..b9d9ac0 --- /dev/null +++ b/src/main/java/com/cf/cfteam/controllers/codeforces/TeamController.java @@ -0,0 +1,4 @@ +package com.cf.cfteam.controllers.codeforces; + +public class TeamController { +} From 10f844c7bce417faa9d80a8ec61b1017337f444d Mon Sep 17 00:00:00 2001 From: AlexanderGarifullin Date: Mon, 16 Dec 2024 14:09:01 +0500 Subject: [PATCH 13/60] =?UTF-8?q?dev/codeforces/=20=D0=94=D0=BE=D0=B1?= =?UTF-8?q?=D0=B0=D0=B2=D0=B8=D0=BB=20=D0=BC=D0=B0=D0=BF=D0=BF=D0=B5=D1=80?= =?UTF-8?q?=20=D0=B4=D0=BB=D1=8F=20Group?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../mappers/codeforces/GroupMapper.java | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 src/main/java/com/cf/cfteam/mappers/codeforces/GroupMapper.java diff --git a/src/main/java/com/cf/cfteam/mappers/codeforces/GroupMapper.java b/src/main/java/com/cf/cfteam/mappers/codeforces/GroupMapper.java new file mode 100644 index 0000000..43fbcf4 --- /dev/null +++ b/src/main/java/com/cf/cfteam/mappers/codeforces/GroupMapper.java @@ -0,0 +1,22 @@ +package com.cf.cfteam.mappers.codeforces; + +import com.cf.cfteam.models.entities.codeforces.Group; +import com.cf.cfteam.models.entities.security.User; +import com.cf.cfteam.transfer.payloads.codeforces.GroupPayload; + +public class GroupMapper { + + public static Group fromPayloadToEntity(GroupPayload payload, User user) { + return Group.builder() + .name(payload.name()) + .description(payload.description()) + .user(user) + .build(); + } + + public static Group updateEntityFromPayload(Group group, GroupPayload payload) { + group.setName(payload.name()); + group.setDescription(payload.description()); + return group; + } +} From 5b5a955b84b29d34e699503174caf4569e9e5567 Mon Sep 17 00:00:00 2001 From: AlexanderGarifullin Date: Mon, 16 Dec 2024 14:09:21 +0500 Subject: [PATCH 14/60] =?UTF-8?q?dev/codeforces/=20=D0=94=D0=BE=D0=B1?= =?UTF-8?q?=D0=B0=D0=B2=D0=B8=D0=BB=20=D0=B8=D1=81=D0=BA=D0=BB=D1=8E=D1=87?= =?UTF-8?q?=D0=B5=D0=BD=D0=B8=D1=8F=20=D0=B4=D0=BB=D1=8F=20Group?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../codeforces/GroupNotFoundException.java | 14 ++++++++++++++ .../exceptions/security/UserNotFoundException.java | 8 ++++++++ 2 files changed, 22 insertions(+) create mode 100644 src/main/java/com/cf/cfteam/exceptions/codeforces/GroupNotFoundException.java diff --git a/src/main/java/com/cf/cfteam/exceptions/codeforces/GroupNotFoundException.java b/src/main/java/com/cf/cfteam/exceptions/codeforces/GroupNotFoundException.java new file mode 100644 index 0000000..c8f6b0c --- /dev/null +++ b/src/main/java/com/cf/cfteam/exceptions/codeforces/GroupNotFoundException.java @@ -0,0 +1,14 @@ +package com.cf.cfteam.exceptions.codeforces; + +import lombok.Getter; + +@Getter +public class GroupNotFoundException extends RuntimeException { + + private final Long id; + + public GroupNotFoundException(Long id) { + super("id.not_found"); + this.id = id; + } +} diff --git a/src/main/java/com/cf/cfteam/exceptions/security/UserNotFoundException.java b/src/main/java/com/cf/cfteam/exceptions/security/UserNotFoundException.java index a7b6510..aad1e88 100644 --- a/src/main/java/com/cf/cfteam/exceptions/security/UserNotFoundException.java +++ b/src/main/java/com/cf/cfteam/exceptions/security/UserNotFoundException.java @@ -6,9 +6,17 @@ public class UserNotFoundException extends RuntimeException { private final String login; + private final Long id; public UserNotFoundException(String login) { super("login.not_found"); this.login = login; + this.id = null; + } + + public UserNotFoundException(Long id) { + super("id.not_found"); + this.id = id; + this.login = null; } } \ No newline at end of file From c34c3d499b8e2657986e179ab0e58ebe79123972 Mon Sep 17 00:00:00 2001 From: AlexanderGarifullin Date: Mon, 16 Dec 2024 14:24:36 +0500 Subject: [PATCH 15/60] =?UTF-8?q?dev/codeforces/=20=D0=94=D0=BE=D0=B1?= =?UTF-8?q?=D0=B0=D0=B2=D0=B8=D0=BB=20=D0=BF=D1=80=D0=B8=D0=B2=D0=B0=D1=82?= =?UTF-8?q?=D0=BD=D1=8B=D0=B9=20=D0=BA=D0=BE=D0=BD=D1=81=D1=82=D1=80=D1=83?= =?UTF-8?q?=D0=BA=D1=82=D0=BE=D1=80=20=D0=B4=D0=BB=D1=8F=20GroupMapper?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/cf/cfteam/mappers/codeforces/GroupMapper.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/main/java/com/cf/cfteam/mappers/codeforces/GroupMapper.java b/src/main/java/com/cf/cfteam/mappers/codeforces/GroupMapper.java index 43fbcf4..5a31bb4 100644 --- a/src/main/java/com/cf/cfteam/mappers/codeforces/GroupMapper.java +++ b/src/main/java/com/cf/cfteam/mappers/codeforces/GroupMapper.java @@ -19,4 +19,8 @@ public static Group updateEntityFromPayload(Group group, GroupPayload payload) { group.setDescription(payload.description()); return group; } + + private GroupMapper() { + throw new UnsupportedOperationException("Utility class"); + } } From 2abd0bc1320d5c9e6791917bae815cd789a1d353 Mon Sep 17 00:00:00 2001 From: AlexanderGarifullin Date: Mon, 16 Dec 2024 14:33:28 +0500 Subject: [PATCH 16/60] =?UTF-8?q?dev/codeforces/=20=D0=98=D1=81=D0=BF?= =?UTF-8?q?=D1=80=D0=B0=D0=B2=D0=B8=D0=BB=20=D0=BA=D0=BB=D0=B0=D1=81=D1=81?= =?UTF-8?q?=D1=8B=20=D0=BF=D0=BE=20checkStyle?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/cf/cfteam/mappers/codeforces/GroupMapper.java | 2 +- .../com/cf/cfteam/models/entities/codeforces/Player.java | 4 ++-- .../java/com/cf/cfteam/models/entities/codeforces/Team.java | 5 ++--- 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/src/main/java/com/cf/cfteam/mappers/codeforces/GroupMapper.java b/src/main/java/com/cf/cfteam/mappers/codeforces/GroupMapper.java index 5a31bb4..ed03813 100644 --- a/src/main/java/com/cf/cfteam/mappers/codeforces/GroupMapper.java +++ b/src/main/java/com/cf/cfteam/mappers/codeforces/GroupMapper.java @@ -4,7 +4,7 @@ import com.cf.cfteam.models.entities.security.User; import com.cf.cfteam.transfer.payloads.codeforces.GroupPayload; -public class GroupMapper { +public final class GroupMapper { public static Group fromPayloadToEntity(GroupPayload payload, User user) { return Group.builder() diff --git a/src/main/java/com/cf/cfteam/models/entities/codeforces/Player.java b/src/main/java/com/cf/cfteam/models/entities/codeforces/Player.java index aff9233..6ff866c 100644 --- a/src/main/java/com/cf/cfteam/models/entities/codeforces/Player.java +++ b/src/main/java/com/cf/cfteam/models/entities/codeforces/Player.java @@ -25,8 +25,8 @@ public class Player { @ManyToMany(cascade = CascadeType.ALL) @JoinTable(name = "t_team_player", - joinColumns = @JoinColumn(name="c_player_id", referencedColumnName="id"), - inverseJoinColumns = @JoinColumn(name="c_team_id", referencedColumnName="id")) + joinColumns = @JoinColumn(name = "c_player_id", referencedColumnName = "id"), + inverseJoinColumns = @JoinColumn(name = "c_team_id", referencedColumnName = "id")) @Builder.Default private List teams = new ArrayList<>(); } diff --git a/src/main/java/com/cf/cfteam/models/entities/codeforces/Team.java b/src/main/java/com/cf/cfteam/models/entities/codeforces/Team.java index cf7157c..ba3df97 100644 --- a/src/main/java/com/cf/cfteam/models/entities/codeforces/Team.java +++ b/src/main/java/com/cf/cfteam/models/entities/codeforces/Team.java @@ -1,6 +1,5 @@ package com.cf.cfteam.models.entities.codeforces; -import com.cf.cfteam.models.entities.security.User; import jakarta.persistence.*; import lombok.*; @@ -33,8 +32,8 @@ public class Team { @ManyToMany(cascade = CascadeType.ALL) @JoinTable(name = "t_team_player", - joinColumns = @JoinColumn(name="c_team_id", referencedColumnName="id"), - inverseJoinColumns = @JoinColumn(name="c_player_id", referencedColumnName="id")) + joinColumns = @JoinColumn(name = "c_team_id", referencedColumnName = "id"), + inverseJoinColumns = @JoinColumn(name = "c_player_id", referencedColumnName = "id")) @Builder.Default private List players = new ArrayList<>(); } From bc7190f5e8c607d9d9234331865f351093d2cd33 Mon Sep 17 00:00:00 2001 From: AlexanderGarifullin Date: Mon, 16 Dec 2024 14:53:10 +0500 Subject: [PATCH 17/60] =?UTF-8?q?dev/codeforces/=20=D0=94=D0=BE=D0=B1?= =?UTF-8?q?=D0=B0=D0=B2=D0=B8=D0=BB=20ControllerAdvice=20=D0=B4=D0=BB?= =?UTF-8?q?=D1=8F=20Codeforces=20Exceptions?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../CodeforcesExceptionHandler.java | 37 +++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 src/main/java/com/cf/cfteam/advicers/codeforces/CodeforcesExceptionHandler.java diff --git a/src/main/java/com/cf/cfteam/advicers/codeforces/CodeforcesExceptionHandler.java b/src/main/java/com/cf/cfteam/advicers/codeforces/CodeforcesExceptionHandler.java new file mode 100644 index 0000000..9a0e918 --- /dev/null +++ b/src/main/java/com/cf/cfteam/advicers/codeforces/CodeforcesExceptionHandler.java @@ -0,0 +1,37 @@ +package com.cf.cfteam.advicers.codeforces; + +import com.cf.cfteam.exceptions.codeforces.GroupNotFoundException; +import com.cf.cfteam.exceptions.security.UserNotFoundException; +import jakarta.validation.GroupDefinitionException; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.ControllerAdvice; +import org.springframework.web.bind.annotation.ExceptionHandler; + +import java.time.LocalDateTime; +import java.util.HashMap; +import java.util.Map; + +@ControllerAdvice +public class CodeforcesExceptionHandler { + private static final String ID = "id"; + + @ExceptionHandler(GroupNotFoundException.class) + public ResponseEntity handleUserNotFoundException(GroupNotFoundException ex) { + return buildErrorResponse(ex.getMessage(), HttpStatus.NOT_FOUND, Map.of(ID, ex.getId())); + } + + private ResponseEntity buildErrorResponse(String message, HttpStatus status, Map details) { + Map errorResponse = new HashMap<>(); + errorResponse.put("timestamp", LocalDateTime.now()); + errorResponse.put("status", status.value()); + errorResponse.put("error", status.getReasonPhrase()); + errorResponse.put("message", message); + + if (details != null) { + errorResponse.put("details", details); + } + + return new ResponseEntity<>(errorResponse, status); + } +} From 3458a091895eee3183b9d26a87629b7e458863a5 Mon Sep 17 00:00:00 2001 From: AlexanderGarifullin Date: Mon, 16 Dec 2024 14:53:54 +0500 Subject: [PATCH 18/60] =?UTF-8?q?dev/codeforces/=20=D0=A3=D0=B4=D0=B0?= =?UTF-8?q?=D0=BB=D0=B8=D0=BB=20=D0=BB=D0=B8=D1=88=D0=BD=D0=B8=D0=B5=20?= =?UTF-8?q?=D0=B8=D0=BC=D0=BF=D0=BE=D1=80=D1=82=D1=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../cfteam/advicers/codeforces/CodeforcesExceptionHandler.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/main/java/com/cf/cfteam/advicers/codeforces/CodeforcesExceptionHandler.java b/src/main/java/com/cf/cfteam/advicers/codeforces/CodeforcesExceptionHandler.java index 9a0e918..6f1319a 100644 --- a/src/main/java/com/cf/cfteam/advicers/codeforces/CodeforcesExceptionHandler.java +++ b/src/main/java/com/cf/cfteam/advicers/codeforces/CodeforcesExceptionHandler.java @@ -1,8 +1,6 @@ package com.cf.cfteam.advicers.codeforces; import com.cf.cfteam.exceptions.codeforces.GroupNotFoundException; -import com.cf.cfteam.exceptions.security.UserNotFoundException; -import jakarta.validation.GroupDefinitionException; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.ControllerAdvice; From 8d84a2f908c910ba9a541ccb430f6621f437a781 Mon Sep 17 00:00:00 2001 From: AlexanderGarifullin Date: Mon, 16 Dec 2024 15:03:28 +0500 Subject: [PATCH 19/60] =?UTF-8?q?dev/codeforces/=20=D0=9E=D1=82=D1=80?= =?UTF-8?q?=D0=B5=D1=84=D0=B0=D0=BA=D1=82=D0=BE=D1=80=D0=B8=D0=BB=20util?= =?UTF-8?q?=20=D0=BA=D0=BB=D0=B0=D1=81=D1=81=D1=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../CodeforcesExceptionHandler.java | 18 ++-------- .../security/SecurityExceptionHandler.java | 34 +++++-------------- .../services/codeforces/GroupService.java | 2 +- .../cf/cfteam/utils/ErrorResponseBuilder.java | 30 ++++++++++++++++ .../codeforces/GroupMapper.java | 2 +- 5 files changed, 42 insertions(+), 44 deletions(-) create mode 100644 src/main/java/com/cf/cfteam/utils/ErrorResponseBuilder.java rename src/main/java/com/cf/cfteam/{mappers => utils}/codeforces/GroupMapper.java (94%) diff --git a/src/main/java/com/cf/cfteam/advicers/codeforces/CodeforcesExceptionHandler.java b/src/main/java/com/cf/cfteam/advicers/codeforces/CodeforcesExceptionHandler.java index 6f1319a..99433e1 100644 --- a/src/main/java/com/cf/cfteam/advicers/codeforces/CodeforcesExceptionHandler.java +++ b/src/main/java/com/cf/cfteam/advicers/codeforces/CodeforcesExceptionHandler.java @@ -1,13 +1,12 @@ package com.cf.cfteam.advicers.codeforces; import com.cf.cfteam.exceptions.codeforces.GroupNotFoundException; +import com.cf.cfteam.utils.ErrorResponseBuilder; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.bind.annotation.ExceptionHandler; -import java.time.LocalDateTime; -import java.util.HashMap; import java.util.Map; @ControllerAdvice @@ -16,20 +15,7 @@ public class CodeforcesExceptionHandler { @ExceptionHandler(GroupNotFoundException.class) public ResponseEntity handleUserNotFoundException(GroupNotFoundException ex) { - return buildErrorResponse(ex.getMessage(), HttpStatus.NOT_FOUND, Map.of(ID, ex.getId())); + return ErrorResponseBuilder.buildErrorResponse(ex.getMessage(), HttpStatus.NOT_FOUND, Map.of(ID, ex.getId())); } - private ResponseEntity buildErrorResponse(String message, HttpStatus status, Map details) { - Map errorResponse = new HashMap<>(); - errorResponse.put("timestamp", LocalDateTime.now()); - errorResponse.put("status", status.value()); - errorResponse.put("error", status.getReasonPhrase()); - errorResponse.put("message", message); - - if (details != null) { - errorResponse.put("details", details); - } - - return new ResponseEntity<>(errorResponse, status); - } } diff --git a/src/main/java/com/cf/cfteam/advicers/security/SecurityExceptionHandler.java b/src/main/java/com/cf/cfteam/advicers/security/SecurityExceptionHandler.java index 256a2fc..87100eb 100644 --- a/src/main/java/com/cf/cfteam/advicers/security/SecurityExceptionHandler.java +++ b/src/main/java/com/cf/cfteam/advicers/security/SecurityExceptionHandler.java @@ -4,13 +4,12 @@ import com.cf.cfteam.exceptions.security.TokenRevokedException; import com.cf.cfteam.exceptions.security.UserAlreadyRegisterException; import com.cf.cfteam.exceptions.security.UserNotFoundException; +import com.cf.cfteam.utils.ErrorResponseBuilder; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.bind.annotation.ExceptionHandler; -import java.time.LocalDateTime; -import java.util.HashMap; import java.util.Map; @ControllerAdvice @@ -18,44 +17,27 @@ public class SecurityExceptionHandler { private static final String LOGIN = "login"; private static final String TOKEN = "token"; - private static final String UNEXPECTED_ERROR = "unexpected.error"; @ExceptionHandler(UserAlreadyRegisterException.class) public ResponseEntity handleUserAlreadyRegisterException(UserAlreadyRegisterException ex) { - return buildErrorResponse(ex.getMessage(), HttpStatus.CONFLICT, Map.of(LOGIN, ex.getLogin())); + return ErrorResponseBuilder.buildErrorResponse(ex.getMessage(), HttpStatus.CONFLICT, Map.of(LOGIN, + ex.getLogin())); } @ExceptionHandler(UserNotFoundException.class) public ResponseEntity handleUserNotFoundException(UserNotFoundException ex) { - return buildErrorResponse(ex.getMessage(), HttpStatus.NOT_FOUND, Map.of(LOGIN, ex.getLogin())); + return ErrorResponseBuilder.buildErrorResponse(ex.getMessage(), HttpStatus.NOT_FOUND, Map.of(LOGIN, + ex.getLogin())); } @ExceptionHandler(TokenRevokedException.class) public ResponseEntity handleTokenRevokedException(TokenRevokedException ex) { - return buildErrorResponse(ex.getMessage(), HttpStatus.UNAUTHORIZED, Map.of(TOKEN, ex.getToken())); + return ErrorResponseBuilder.buildErrorResponse(ex.getMessage(), HttpStatus.UNAUTHORIZED, Map.of(TOKEN, + ex.getToken())); } @ExceptionHandler(InvalidTwoFactorCodeException.class) public ResponseEntity handleInvalidTwoFactorCodeException(InvalidTwoFactorCodeException ex) { - return buildErrorResponse(ex.getMessage(), HttpStatus.BAD_REQUEST, null); - } - - @ExceptionHandler(Exception.class) - public ResponseEntity handleGenericException(Exception ex) { - return buildErrorResponse(UNEXPECTED_ERROR, HttpStatus.INTERNAL_SERVER_ERROR, null); - } - - private ResponseEntity buildErrorResponse(String message, HttpStatus status, Map details) { - Map errorResponse = new HashMap<>(); - errorResponse.put("timestamp", LocalDateTime.now()); - errorResponse.put("status", status.value()); - errorResponse.put("error", status.getReasonPhrase()); - errorResponse.put("message", message); - - if (details != null) { - errorResponse.put("details", details); - } - - return new ResponseEntity<>(errorResponse, status); + return ErrorResponseBuilder.buildErrorResponse(ex.getMessage(), HttpStatus.BAD_REQUEST, null); } } diff --git a/src/main/java/com/cf/cfteam/services/codeforces/GroupService.java b/src/main/java/com/cf/cfteam/services/codeforces/GroupService.java index 9b9f816..b033d84 100644 --- a/src/main/java/com/cf/cfteam/services/codeforces/GroupService.java +++ b/src/main/java/com/cf/cfteam/services/codeforces/GroupService.java @@ -2,7 +2,7 @@ import com.cf.cfteam.exceptions.codeforces.GroupNotFoundException; import com.cf.cfteam.exceptions.security.UserNotFoundException; -import com.cf.cfteam.mappers.codeforces.GroupMapper; +import com.cf.cfteam.utils.codeforces.GroupMapper; import com.cf.cfteam.models.entities.codeforces.Group; import com.cf.cfteam.models.entities.security.User; import com.cf.cfteam.repositories.jpa.codeforces.GroupRepository; diff --git a/src/main/java/com/cf/cfteam/utils/ErrorResponseBuilder.java b/src/main/java/com/cf/cfteam/utils/ErrorResponseBuilder.java new file mode 100644 index 0000000..920ecf0 --- /dev/null +++ b/src/main/java/com/cf/cfteam/utils/ErrorResponseBuilder.java @@ -0,0 +1,30 @@ +package com.cf.cfteam.utils; + +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; + +import java.time.LocalDateTime; +import java.util.HashMap; +import java.util.Map; + +public final class ErrorResponseBuilder { + + public static ResponseEntity buildErrorResponse(String message, HttpStatus status, + Map details) { + Map errorResponse = new HashMap<>(); + errorResponse.put("timestamp", LocalDateTime.now()); + errorResponse.put("status", status.value()); + errorResponse.put("error", status.getReasonPhrase()); + errorResponse.put("message", message); + + if (details != null) { + errorResponse.put("details", details); + } + + return new ResponseEntity<>(errorResponse, status); + } + + private ErrorResponseBuilder() { + throw new UnsupportedOperationException("Utility class"); + } +} \ No newline at end of file diff --git a/src/main/java/com/cf/cfteam/mappers/codeforces/GroupMapper.java b/src/main/java/com/cf/cfteam/utils/codeforces/GroupMapper.java similarity index 94% rename from src/main/java/com/cf/cfteam/mappers/codeforces/GroupMapper.java rename to src/main/java/com/cf/cfteam/utils/codeforces/GroupMapper.java index ed03813..b0e259f 100644 --- a/src/main/java/com/cf/cfteam/mappers/codeforces/GroupMapper.java +++ b/src/main/java/com/cf/cfteam/utils/codeforces/GroupMapper.java @@ -1,4 +1,4 @@ -package com.cf.cfteam.mappers.codeforces; +package com.cf.cfteam.utils.codeforces; import com.cf.cfteam.models.entities.codeforces.Group; import com.cf.cfteam.models.entities.security.User; From 582256d573a4c408d9faa2a3eaa32eba3a7bf879 Mon Sep 17 00:00:00 2001 From: AlexanderGarifullin Date: Mon, 16 Dec 2024 16:01:28 +0500 Subject: [PATCH 20/60] =?UTF-8?q?dev/codeforces/test=20=D0=94=D0=BE=D0=B1?= =?UTF-8?q?=D0=B0=D0=B2=D0=B8=D0=BB=20=D0=BC=D0=BE=D0=B4=D1=83=D0=BB=D1=8C?= =?UTF-8?q?=D0=BD=D1=8B=D0=B5=20=D1=82=D0=B5=D1=81=D1=82=D1=8B=20=D0=B4?= =?UTF-8?q?=D0=BB=D1=8F=20GroupService?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../services/codeforces/GroupServiceTest.java | 182 ++++++++++++++++++ 1 file changed, 182 insertions(+) create mode 100644 src/test/java/com/cf/cfteam/services/codeforces/GroupServiceTest.java diff --git a/src/test/java/com/cf/cfteam/services/codeforces/GroupServiceTest.java b/src/test/java/com/cf/cfteam/services/codeforces/GroupServiceTest.java new file mode 100644 index 0000000..6f52d4d --- /dev/null +++ b/src/test/java/com/cf/cfteam/services/codeforces/GroupServiceTest.java @@ -0,0 +1,182 @@ +package com.cf.cfteam.services.codeforces; + +import com.cf.cfteam.exceptions.codeforces.GroupNotFoundException; +import com.cf.cfteam.exceptions.security.UserAlreadyRegisterException; +import com.cf.cfteam.exceptions.security.UserNotFoundException; +import com.cf.cfteam.models.entities.codeforces.Group; +import com.cf.cfteam.models.entities.security.Role; +import com.cf.cfteam.models.entities.security.User; +import com.cf.cfteam.repositories.jpa.codeforces.GroupRepository; +import com.cf.cfteam.repositories.jpa.security.UserRepository; +import com.cf.cfteam.transfer.payloads.codeforces.GroupPayload; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.springframework.test.context.ActiveProfiles; + +import java.util.List; +import java.util.Optional; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.*; + +@ActiveProfiles("test") +class GroupServiceTest { + + @InjectMocks + private GroupService groupService; + + @Mock + private GroupRepository groupRepository; + + @Mock + private UserRepository userRepository; + + private User user; + private Group group; + private GroupPayload groupPayload; + + @BeforeEach + void setUp() { + MockitoAnnotations.openMocks(this); + + user = User.builder() + .name("User name") + .login("User login") + .hashedPassword("Password") + .role(Role.USER) + .build(); + + group = Group.builder() + .name("Test Group") + .description("Test description") + .user(user) + .build(); + + groupPayload = GroupPayload.builder() + .name("Test Group") + .description("Test description") + .build(); + } + + @Test + void getAllGroupsByUser_ShouldReturnGroups_WhenUserExists() { + when(userRepository.findById(1L)).thenReturn(Optional.of(user)); + when(groupRepository.findByUser(user)).thenReturn(List.of(group)); + + var groups = groupService.getAllGroupsByUser(1L); + + assertAll( + () -> assertThat(groups).hasSize(1), + () -> assertThat(groups).contains(group) + ); + } + + @Test + void getAllGroupsByUser_ShouldThrowUserNotFoundException_WhenUserDoesNotExist() { + when(userRepository.findById(1L)).thenReturn(Optional.empty()); + + assertThatThrownBy(() -> groupService.getAllGroupsByUser(1L)) + .isInstanceOf(UserNotFoundException.class) + .hasMessageContaining("id.not_found"); + } + + @Test + void getGroupById_ShouldReturnGroup_WhenGroupExists() { + when(groupRepository.findById(1L)).thenReturn(Optional.of(group)); + + var result = groupService.getGroupById(1L); + + assertThat(result).isEqualTo(group); + } + + @Test + void getGroupById_ShouldThrowGroupNotFoundException_WhenGroupDoesNotExist() { + when(groupRepository.findById(1L)).thenReturn(Optional.empty()); + + assertThatThrownBy(() -> groupService.getGroupById(1L)) + .isInstanceOf(GroupNotFoundException.class) + .hasMessageContaining("id.not_found"); + } + + @Test + void addGroupToUser_ShouldAddGroup_WhenUserExists() { + when(userRepository.findById(1L)).thenReturn(Optional.of(user)); + when(groupRepository.save(any(Group.class))).thenReturn(group); + + var result = groupService.addGroupToUser(1L, groupPayload); + + assertThat(result).isEqualTo(group); + verify(groupRepository, times(1)).save(any(Group.class)); + } + + @Test + void addGroupToUser_ShouldThrowUserNotFoundException_WhenUserDoesNotExist() { + when(userRepository.findById(1L)).thenReturn(Optional.empty()); + + assertThatThrownBy(() -> groupService.addGroupToUser(1L, groupPayload)) + .isInstanceOf(UserNotFoundException.class) + .hasMessageContaining("id.not_found"); + } + + @Test + void updateGroup_ShouldUpdateGroup_WhenGroupExists() { + when(groupRepository.findById(1L)).thenReturn(Optional.of(group)); + when(groupRepository.save(any(Group.class))).thenReturn(group); + + groupPayload = GroupPayload.builder() + .name("NEW Test Group") + .description("NEW Test description") + .build(); + + var result = groupService.updateGroup(1L, groupPayload); + + assertAll( + () -> assertThat(result.getDescription()).isEqualTo(groupPayload.description()), + () -> assertThat(result.getName()).isEqualTo(group.getName()) + ); + verify(groupRepository, times(1)).save(any(Group.class)); + } + + @Test + void updateGroup_ShouldThrowGroupNotFoundException_WhenGroupDoesNotExist() { + when(groupRepository.findById(1L)).thenReturn(Optional.empty()); + + assertThatThrownBy(() -> groupService.updateGroup(1L, groupPayload)) + .isInstanceOf(GroupNotFoundException.class) + .hasMessageContaining("id.not_found"); + } + + @Test + void deleteGroup_ShouldDeleteGroup_WhenGroupExists() { + when(groupRepository.findById(1L)).thenReturn(Optional.of(group)); + + groupService.deleteGroup(1L); + + verify(groupRepository, times(1)).deleteById(1L); + } + + @Test + void deleteAllGroupsByUser_ShouldDeleteAllGroups_WhenUserExists() { + when(userRepository.findById(1L)).thenReturn(Optional.of(user)); + when(groupRepository.findByUser(user)).thenReturn(List.of(group)); + + groupService.deleteAllGroupsByUser(1L); + + verify(groupRepository, times(1)).deleteAll(anyList()); + } + + @Test + void deleteAllGroupsByUser_ShouldThrowUserNotFoundException_WhenUserDoesNotExist() { + when(userRepository.findById(1L)).thenReturn(Optional.empty()); + + assertThatThrownBy(() -> groupService.deleteAllGroupsByUser(1L)) + .isInstanceOf(UserNotFoundException.class) + .hasMessageContaining("id.not_found"); + } +} \ No newline at end of file From d64ff32679dc214c32c2153428f3d14de9150b6b Mon Sep 17 00:00:00 2001 From: AlexanderGarifullin Date: Mon, 16 Dec 2024 16:08:14 +0500 Subject: [PATCH 21/60] =?UTF-8?q?dev/codeforces/test=20=D0=94=D0=BE=D0=B1?= =?UTF-8?q?=D0=B0=D0=B2=D0=B8=D0=BB=20=D0=BC=D0=BE=D0=B4=D1=83=D0=BB=D1=8C?= =?UTF-8?q?=D0=BD=D1=8B=D0=B5=20=D1=82=D0=B5=D1=81=D1=82=D1=8B=20=D0=B4?= =?UTF-8?q?=D0=BB=D1=8F=20GroupMapper?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../services/codeforces/GroupServiceTest.java | 1 - .../utils/codeforces/GroupMapperTest.java | 60 +++++++++++++++++++ 2 files changed, 60 insertions(+), 1 deletion(-) create mode 100644 src/test/java/com/cf/cfteam/utils/codeforces/GroupMapperTest.java diff --git a/src/test/java/com/cf/cfteam/services/codeforces/GroupServiceTest.java b/src/test/java/com/cf/cfteam/services/codeforces/GroupServiceTest.java index 6f52d4d..daf43a0 100644 --- a/src/test/java/com/cf/cfteam/services/codeforces/GroupServiceTest.java +++ b/src/test/java/com/cf/cfteam/services/codeforces/GroupServiceTest.java @@ -1,7 +1,6 @@ package com.cf.cfteam.services.codeforces; import com.cf.cfteam.exceptions.codeforces.GroupNotFoundException; -import com.cf.cfteam.exceptions.security.UserAlreadyRegisterException; import com.cf.cfteam.exceptions.security.UserNotFoundException; import com.cf.cfteam.models.entities.codeforces.Group; import com.cf.cfteam.models.entities.security.Role; diff --git a/src/test/java/com/cf/cfteam/utils/codeforces/GroupMapperTest.java b/src/test/java/com/cf/cfteam/utils/codeforces/GroupMapperTest.java new file mode 100644 index 0000000..ba8cbe2 --- /dev/null +++ b/src/test/java/com/cf/cfteam/utils/codeforces/GroupMapperTest.java @@ -0,0 +1,60 @@ +package com.cf.cfteam.utils.codeforces; + +import com.cf.cfteam.models.entities.codeforces.Group; +import com.cf.cfteam.models.entities.security.Role; +import com.cf.cfteam.models.entities.security.User; +import com.cf.cfteam.transfer.payloads.codeforces.GroupPayload; +import org.junit.jupiter.api.Test; +import org.springframework.test.context.ActiveProfiles; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.*; + +@ActiveProfiles("test") +class GroupMapperTest { + + @Test + void shouldMapPayloadToEntity() { + GroupPayload payload = GroupPayload.builder() + .name("GroupName") + .description("GroupDescription") + .build(); + User user = User.builder() + .name("User name") + .login("User login") + .hashedPassword("Password") + .role(Role.USER) + .build(); + + + Group group = GroupMapper.fromPayloadToEntity(payload, user); + + assertAll( + () -> assertThat(group).isNotNull(), + () -> assertThat(group.getName()).isEqualTo(payload.name()), + () -> assertThat(group.getDescription()).isEqualTo(payload.description()), + () -> assertThat(group.getUser()).isEqualTo(user) + ); + } + + @Test + void shouldUpdateEntityFromPayload() { + Group group = Group.builder() + .name("Test Group") + .description("Test description") + .build(); + + GroupPayload payload = GroupPayload.builder() + .name("NewName") + .description("NewDescription") + .build(); + + Group updatedGroup = GroupMapper.updateEntityFromPayload(group, payload); + + assertAll( + () -> assertThat(updatedGroup).isNotNull(), + () -> assertThat(updatedGroup.getName()).isEqualTo(payload.name()), + () -> assertThat(updatedGroup.getDescription()).isEqualTo(payload.description()) + ); + } +} \ No newline at end of file From dcae5c8f3379b75cdaf27c1a7924910932e3a53b Mon Sep 17 00:00:00 2001 From: AlexanderGarifullin Date: Mon, 16 Dec 2024 16:16:37 +0500 Subject: [PATCH 22/60] =?UTF-8?q?dev/codeforces/test=20=D0=9D=D0=B5=D0=BC?= =?UTF-8?q?=D0=BD=D0=BE=D0=B3=D0=BE=20=D0=BE=D1=82=D1=80=D0=B5=D1=84=D0=B0?= =?UTF-8?q?=D0=BA=D1=82=D0=BE=D1=80=D0=B8=D0=BB=20GroupServiceTest?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/cf/cfteam/services/codeforces/GroupServiceTest.java | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/test/java/com/cf/cfteam/services/codeforces/GroupServiceTest.java b/src/test/java/com/cf/cfteam/services/codeforces/GroupServiceTest.java index daf43a0..ada6193 100644 --- a/src/test/java/com/cf/cfteam/services/codeforces/GroupServiceTest.java +++ b/src/test/java/com/cf/cfteam/services/codeforces/GroupServiceTest.java @@ -70,10 +70,8 @@ void getAllGroupsByUser_ShouldReturnGroups_WhenUserExists() { var groups = groupService.getAllGroupsByUser(1L); - assertAll( - () -> assertThat(groups).hasSize(1), - () -> assertThat(groups).contains(group) - ); + assertThat(groups).hasSize(1) + .contains(group); } @Test From 061b7f882b28ed62bf80710ea5a85737c88f2dd3 Mon Sep 17 00:00:00 2001 From: AlexanderGarifullin Date: Mon, 16 Dec 2024 16:23:55 +0500 Subject: [PATCH 23/60] =?UTF-8?q?dev/codeforces/test=20=D0=94=D0=BE=D0=B1?= =?UTF-8?q?=D0=B0=D0=B2=D0=B8=D0=BB=20unit=20=D1=82=D0=B5=D1=81=D1=82?= =?UTF-8?q?=D1=8B=20=D0=B4=D0=BB=D1=8F=20GroupController?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../codeforces/GroupControllerTest.java | 112 ++++++++++++++++++ 1 file changed, 112 insertions(+) create mode 100644 src/test/java/com/cf/cfteam/controllers/codeforces/GroupControllerTest.java diff --git a/src/test/java/com/cf/cfteam/controllers/codeforces/GroupControllerTest.java b/src/test/java/com/cf/cfteam/controllers/codeforces/GroupControllerTest.java new file mode 100644 index 0000000..cbf1c47 --- /dev/null +++ b/src/test/java/com/cf/cfteam/controllers/codeforces/GroupControllerTest.java @@ -0,0 +1,112 @@ +package com.cf.cfteam.controllers.codeforces; + +import com.cf.cfteam.models.entities.codeforces.Group; +import com.cf.cfteam.services.codeforces.GroupService; +import com.cf.cfteam.transfer.payloads.codeforces.GroupPayload; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.springframework.test.context.ActiveProfiles; + +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertAll; +import static org.mockito.Mockito.*; + + +@ActiveProfiles("test") +class GroupControllerTest { + + @InjectMocks + private GroupController groupController; + + @Mock + private GroupService groupService; + + private GroupPayload groupPayload; + private Group group; + + @BeforeEach + void setUp() { + MockitoAnnotations.openMocks(this); + + group = Group.builder() + .name("Test Group") + .description("Test description") + .user(null) + .build(); + + groupPayload = GroupPayload.builder() + .name("Test Group") + .description("Test description") + .build(); + } + + @Test + void shouldReturnGroupsByUserId() { + when(groupService.getAllGroupsByUser(1L)).thenReturn(List.of(group)); + + List groups = groupController.getAllGroupsByUser(1L, null).getBody(); + + verify(groupService, times(1)).getAllGroupsByUser(1L); + + assertThat(groups) + .isNotNull() + .hasSize(1) + .contains(group); + } + + @Test + void shouldReturnGroupById() { + when(groupService.getGroupById(1L)).thenReturn(group); + + Group result = groupController.getGroupById(1L, null).getBody(); + + verify(groupService, times(1)).getGroupById(1L); + assertThat(result).isEqualTo(group); + } + + @Test + void shouldAddGroupToUser() { + when(groupService.addGroupToUser(1L, groupPayload)).thenReturn(group); + + + Group result = groupController.addGroupToUser(1L, groupPayload, null).getBody(); + + verify(groupService, times(1)).addGroupToUser(1L, groupPayload); + + assertThat(result).isEqualTo(group); + } + + @Test + void shouldUpdateGroup() { + when(groupService.updateGroup(1L, groupPayload)).thenReturn(group); + + Group result = groupController.updateGroup(1L, groupPayload, null).getBody(); + + verify(groupService, times(1)).updateGroup(1L, groupPayload); + assertAll( + () -> assertThat(result).isNotNull(), + () -> assertThat(result.getName()).isEqualTo(groupPayload.name()), + () -> assertThat(result.getDescription()).isEqualTo(groupPayload.description()) + ); + } + + @Test + void shouldDeleteGroup() { + groupController.deleteGroup(1L, null); + + verify(groupService, times(1)).deleteGroup(1L); + } + + @Test + void shouldDeleteAllGroupsByUser() { + groupController.deleteAllGroupsByUser(1L, null); + + verify(groupService, times(1)).deleteAllGroupsByUser(1L); + } +} + From 53227448c90ab9a9190d39bdbe30a772d1cad329 Mon Sep 17 00:00:00 2001 From: AlexanderGarifullin Date: Mon, 16 Dec 2024 17:45:40 +0500 Subject: [PATCH 24/60] =?UTF-8?q?dev/codeforces/test=20=D0=94=D0=BE=D0=B1?= =?UTF-8?q?=D0=B0=D0=B2=D0=B8=D0=BB=20lombock=20=D0=B4=D0=BB=D1=8F=20?= =?UTF-8?q?=D1=82=D0=B5=D1=81=D1=82=D0=BE=D0=B2=20=D0=B8=20=D0=B7=D0=B0?= =?UTF-8?q?=D0=BC=D0=B5=D0=B8=D0=BB=20throws=20=D0=BD=D0=B0=20@SneakyThrow?= =?UTF-8?q?s?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle | 2 ++ .../UserControllerIntegrationTest.java | 23 ++++++++++++------- 2 files changed, 17 insertions(+), 8 deletions(-) diff --git a/build.gradle b/build.gradle index 2251581..c993236 100644 --- a/build.gradle +++ b/build.gradle @@ -51,6 +51,8 @@ dependencies { testImplementation 'org.wiremock.integrations.testcontainers:wiremock-testcontainers-module:1.0-alpha-14' testImplementation 'org.testcontainers:postgresql:1.20.3' testImplementation 'org.liquibase:liquibase-core:4.29.2' + testImplementation 'org.projectlombok:lombok' + testAnnotationProcessor 'org.projectlombok:lombok' } tasks.named('test') { diff --git a/src/test/java/com/cf/cfteam/controllers/security/UserControllerIntegrationTest.java b/src/test/java/com/cf/cfteam/controllers/security/UserControllerIntegrationTest.java index 31db666..267bf57 100644 --- a/src/test/java/com/cf/cfteam/controllers/security/UserControllerIntegrationTest.java +++ b/src/test/java/com/cf/cfteam/controllers/security/UserControllerIntegrationTest.java @@ -8,6 +8,7 @@ import com.cf.cfteam.transfer.payloads.security.ChangePasswordPayload; import com.cf.cfteam.transfer.payloads.security.RegistrationPayload; import com.cf.cfteam.transfer.responses.security.JwtAuthenticationResponse; +import lombok.SneakyThrows; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.MediaType; @@ -32,7 +33,8 @@ public class UserControllerIntegrationTest extends BaseIntegrationTest { private TokenRepository tokenRepository; @Test - public void register_success() throws Exception { + @SneakyThrows + public void register_success() { RegistrationPayload payload = RegistrationPayload.builder() .login("register-login") .name("register-name") @@ -57,7 +59,8 @@ public void register_success() throws Exception { } @Test - public void register_shouldThrowUserAlreadyRegisterException_WhenUserAlreadyRegistered() throws Exception { + @SneakyThrows + public void register_shouldThrowUserAlreadyRegisterException_WhenUserAlreadyRegistered() { String login = "user"; String password = "password"; String name = "Test User"; @@ -82,7 +85,8 @@ public void register_shouldThrowUserAlreadyRegisterException_WhenUserAlreadyRegi } @Test - public void login_success() throws Exception { + @SneakyThrows + public void login_success() { RegistrationPayload payloadToRegister = RegistrationPayload.builder() .login("register-login") .name("register-name") @@ -130,7 +134,8 @@ public void login_success() throws Exception { } @Test - public void logout_success() throws Exception { + @SneakyThrows + public void logout_success() { RegistrationPayload payloadToRegister = RegistrationPayload.builder() .login("register-login") .name("register-name") @@ -157,7 +162,8 @@ public void logout_success() throws Exception { } @Test - public void changePassword_success() throws Exception { + @SneakyThrows + public void changePassword_success() { RegistrationPayload payloadToRegister = RegistrationPayload.builder() .login("register-login") .name("register-name") @@ -232,7 +238,8 @@ public void changePassword_success() throws Exception { } @Test - public void changePassword_shouldReturnBadRequest_WhenTwoFactorCodeInvalid() throws Exception { + @SneakyThrows + public void changePassword_shouldReturnBadRequest_WhenTwoFactorCodeInvalid() { RegistrationPayload payloadToRegister = RegistrationPayload.builder() .login("register-login") .name("register-name") @@ -262,8 +269,8 @@ public void changePassword_shouldReturnBadRequest_WhenTwoFactorCodeInvalid() thr deleteUserFromDb(user.get()); } - - private JwtAuthenticationResponse register(RegistrationPayload payload) throws Exception { + @SneakyThrows + private JwtAuthenticationResponse register(RegistrationPayload payload) { var response = mockMvc.perform(post(uri + "/register") .contentType(MediaType.APPLICATION_JSON) .content(objectMapper.writeValueAsString(payload))) From c58a76fbe11d3cbc8640d74eaad1c5d4a33a0ba6 Mon Sep 17 00:00:00 2001 From: AlexanderGarifullin Date: Mon, 16 Dec 2024 18:44:59 +0500 Subject: [PATCH 25/60] =?UTF-8?q?dev/codeforces/test=20=D0=9D=D0=B0=D0=BF?= =?UTF-8?q?=D0=B8=D1=81=D0=B0=D0=BB=20=D0=B8=D0=BD=D1=82=D0=B5=D0=B3=D1=80?= =?UTF-8?q?=D0=B0=D1=86=D0=B8=D0=BE=D0=BD=D0=BD=D1=8B=D0=B5=20=D1=82=D0=B5?= =?UTF-8?q?=D1=81=D1=82=D1=8B=20=D0=B4=D0=BB=D1=8F=20GroupController?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../security/SecurityExceptionHandler.java | 17 +- .../GroupControllerIntegrationTest.java | 336 ++++++++++++++++++ 2 files changed, 351 insertions(+), 2 deletions(-) create mode 100644 src/test/java/com/cf/cfteam/controllers/codeforces/GroupControllerIntegrationTest.java diff --git a/src/main/java/com/cf/cfteam/advicers/security/SecurityExceptionHandler.java b/src/main/java/com/cf/cfteam/advicers/security/SecurityExceptionHandler.java index 87100eb..2ac464a 100644 --- a/src/main/java/com/cf/cfteam/advicers/security/SecurityExceptionHandler.java +++ b/src/main/java/com/cf/cfteam/advicers/security/SecurityExceptionHandler.java @@ -10,6 +10,7 @@ import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.bind.annotation.ExceptionHandler; +import java.util.HashMap; import java.util.Map; @ControllerAdvice @@ -26,10 +27,22 @@ public ResponseEntity handleUserAlreadyRegisterException(UserAlreadyRegi @ExceptionHandler(UserNotFoundException.class) public ResponseEntity handleUserNotFoundException(UserNotFoundException ex) { - return ErrorResponseBuilder.buildErrorResponse(ex.getMessage(), HttpStatus.NOT_FOUND, Map.of(LOGIN, - ex.getLogin())); + Map details = new HashMap<>(); + if (ex.getLogin() != null) { + details.put("login", ex.getLogin()); + } + if (ex.getId() != null) { + details.put("id", ex.getId()); + } + + return ErrorResponseBuilder.buildErrorResponse( + ex.getMessage(), + HttpStatus.NOT_FOUND, + details + ); } + @ExceptionHandler(TokenRevokedException.class) public ResponseEntity handleTokenRevokedException(TokenRevokedException ex) { return ErrorResponseBuilder.buildErrorResponse(ex.getMessage(), HttpStatus.UNAUTHORIZED, Map.of(TOKEN, diff --git a/src/test/java/com/cf/cfteam/controllers/codeforces/GroupControllerIntegrationTest.java b/src/test/java/com/cf/cfteam/controllers/codeforces/GroupControllerIntegrationTest.java new file mode 100644 index 0000000..c4973f0 --- /dev/null +++ b/src/test/java/com/cf/cfteam/controllers/codeforces/GroupControllerIntegrationTest.java @@ -0,0 +1,336 @@ +package com.cf.cfteam.controllers.codeforces; + +import com.fasterxml.jackson.core.type.TypeReference; +import com.cf.cfteam.BaseIntegrationTest; +import com.cf.cfteam.models.entities.codeforces.Group; +import com.cf.cfteam.models.entities.security.Role; +import com.cf.cfteam.models.entities.security.User; +import com.cf.cfteam.repositories.jpa.codeforces.GroupRepository; +import com.cf.cfteam.repositories.jpa.security.UserRepository; +import com.cf.cfteam.transfer.payloads.codeforces.GroupPayload; +import lombok.SneakyThrows; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.MediaType; +import org.springframework.test.context.ActiveProfiles; + +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertAll; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; + +@ActiveProfiles("test") +public class GroupControllerIntegrationTest extends BaseIntegrationTest { + + private static final String URI = "/api/cf/groups"; + + private static final Long BAD_USER_ID = 9999L; + private static final Long BAD_GROUP_ID = 9999L; + + @Autowired + private GroupRepository groupRepository; + + @Autowired + private UserRepository userRepository; + + @Test + @SneakyThrows + public void getAllGroupsByUser_notEmpty_success() { + User user = createUser(); + user = userRepository.save(user); + + Group group = createGroup(user); + group = groupRepository.save(group); + + + var mvcResponse = mockMvc.perform(get(URI + "/user/" + user.getId()) + .header("Authorization", userBearerToken)) + .andExpectAll( + status().isOk(), + content().contentType(MediaType.APPLICATION_JSON)) + .andReturn() + .getResponse(); + + var groups = objectMapper.readValue( + mvcResponse.getContentAsString(), + new TypeReference>() { + } + ); + + assertThat(groups).hasSize(1) + .contains(group); + + deleteGroupFromDb(group); + deleteUserFromDb(user); + } + + @Test + @SneakyThrows + void getAllGroupsByUser_shouldThrowUserNotFound_whenUserNotFound() { + mockMvc.perform(get(URI + "/user/" + BAD_USER_ID) + .header("Authorization", userBearerToken)) + .andExpectAll( + status().isNotFound(), + content().contentType(MediaType.APPLICATION_JSON), + jsonPath("$.details.id").value(BAD_USER_ID), + jsonPath("$.message").value("id.not_found"), + jsonPath("$.error").value("Not Found"), + jsonPath("$.status").value(404) + ); + } + + @Test + @SneakyThrows + public void getGroupById_notEmpty() { + User user = createUser(); + user = userRepository.save(user); + + Group group = createGroup(user); + group = groupRepository.save(group); + + var mvcResponse = mockMvc.perform(get(URI + "/" + group.getId()) + .header("Authorization", userBearerToken)) + .andExpectAll( + status().isOk(), + content().contentType(MediaType.APPLICATION_JSON)) + .andReturn() + .getResponse(); + + var responseGroupe = objectMapper.readValue(mvcResponse.getContentAsString(), Group.class); + + assertThat(responseGroupe).isEqualTo(group); + + deleteGroupFromDb(group);; + } + + @Test + @SneakyThrows + void getGroupById_shouldThrowGroupNotFound_whenGroupNotFound() { + mockMvc.perform(get(URI + "/" + BAD_USER_ID) + .header("Authorization", userBearerToken)) + .andExpectAll( + status().isNotFound(), + content().contentType(MediaType.APPLICATION_JSON), + jsonPath("$.details.id").value(BAD_USER_ID), + jsonPath("$.message").value("id.not_found"), + jsonPath("$.error").value("Not Found"), + jsonPath("$.status").value(404) + ); + } + + @Test + @SneakyThrows + public void addGroupToUser_success() { + User user = createUser(); + user = userRepository.save(user); + + var payload = createGroupPayload(); + + var mvcResponse = mockMvc.perform(post(URI + "/user/" + user.getId()) + .header("Authorization", userBearerToken) + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(payload))) + .andExpectAll( + status().isOk(), + content().contentType(MediaType.APPLICATION_JSON)) + .andReturn() + .getResponse(); + + var responseGroupe = objectMapper.readValue(mvcResponse.getContentAsString(), Group.class); + var groupFromDb = groupRepository.findById(responseGroupe.getId()); + + assertAll( + () -> assertThat(groupFromDb).isPresent(), + () -> assertThat(groupFromDb.get()).isEqualTo(responseGroupe), + () -> assertThat(responseGroupe.getDescription()).isEqualTo(payload.description()), + () -> assertThat(responseGroupe.getName()).isEqualTo(payload.name()) + ); + + deleteGroupFromDb(groupFromDb.get()); + deleteUserFromDb(user); + } + + @Test + @SneakyThrows + void addGroupToUser_shouldThrowUserNotFound_whenUserNotFound() { + var payload = createGroupPayload(); + + mockMvc.perform(post(URI + "/user/" + BAD_USER_ID) + .header("Authorization", userBearerToken) + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(payload))) + .andExpectAll( + status().isNotFound(), + content().contentType(MediaType.APPLICATION_JSON), + jsonPath("$.details.id").value(BAD_USER_ID), + jsonPath("$.message").value("id.not_found"), + jsonPath("$.error").value("Not Found"), + jsonPath("$.status").value(404) + ); + } + + @Test + @SneakyThrows + public void updateGroup_success() { + User user = createUser(); + user = userRepository.save(user); + + var payload = createGroupPayload("new name", "new description"); + + Group group = createGroup(user); + group = groupRepository.save(group); + + + var mvcResponse = mockMvc.perform(put(URI + "/" + group.getId()) + .header("Authorization", userBearerToken) + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(payload))) + .andExpectAll( + status().isOk(), + content().contentType(MediaType.APPLICATION_JSON)) + .andReturn() + .getResponse(); + + + var responseGroupe = objectMapper.readValue(mvcResponse.getContentAsString(), Group.class); + var groupFromDb = groupRepository.findById(responseGroupe.getId()); + + assertAll( + () -> assertThat(groupFromDb).isPresent(), + () -> assertThat(groupFromDb.get().getDescription()).isEqualTo(payload.description()), + () -> assertThat(groupFromDb.get().getName()).isEqualTo(payload.name()) + ); + + deleteGroupFromDb(groupFromDb.get()); + deleteUserFromDb(user); + } + + @Test + @SneakyThrows + void updateGroup_shouldThrowGroupNotFound_whenGroupNotFound() { + var payload = createGroupPayload(); + + mockMvc.perform(put(URI + "/" + BAD_GROUP_ID) + .header("Authorization", userBearerToken) + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(payload))) + .andExpectAll( + status().isNotFound(), + content().contentType(MediaType.APPLICATION_JSON), + jsonPath("$.details.id").value(BAD_USER_ID), + jsonPath("$.message").value("id.not_found"), + jsonPath("$.error").value("Not Found"), + jsonPath("$.status").value(404) + ); + } + + @Test + @SneakyThrows + public void deleteGroup_success() { + User user = createUser(); + user = userRepository.save(user); + + Group group = createGroup(user); + group = groupRepository.save(group); + + mockMvc.perform(delete(URI + "/" + group.getId()) + .header("Authorization", userBearerToken)) + .andExpectAll( + status().isNoContent(), + content().string("") + ); + + var groupFromDb = groupRepository.findById(group.getId()); + + assertThat(groupFromDb).isNotPresent(); + + deleteUserFromDb(user); + } + + @Test + @SneakyThrows + public void deleteAllGroupsByUser_success() { + User user = createUser(); + user = userRepository.save(user); + + Group group1 = createGroup(user); + group1 = groupRepository.save(group1); + + Group group2 = createGroup(user); + group2 = groupRepository.save(group2); + + mockMvc.perform(delete(URI + "/user/" + user.getId()) + .header("Authorization", userBearerToken)) + .andExpectAll( + status().isNoContent(), + content().string("") + ); + + var groupFromDb1 = groupRepository.findById(group1.getId()); + var groupFromDb2 = groupRepository.findById(group2.getId()); + + assertAll( + () -> assertThat(groupFromDb1).isNotPresent(), + () -> assertThat(groupFromDb2).isNotPresent() + ); + + var mvcResponse = mockMvc.perform(get(URI + "/user/" + user.getId()) + .header("Authorization", userBearerToken)) + .andExpectAll( + status().isOk(), + content().contentType(MediaType.APPLICATION_JSON)) + .andReturn() + .getResponse(); + + var groups = objectMapper.readValue( + mvcResponse.getContentAsString(), + new TypeReference>() { + } + ); + + assertThat(groups).isEmpty(); + + deleteUserFromDb(user); + } + + private User createUser() { + return User.builder() + .name("User name") + .login("User login") + .hashedPassword("Password") + .role(Role.USER) + .build(); + } + + private Group createGroup(User user) { + return Group.builder() + .name("Test Group") + .description("Test description") + .user(user) + .build(); + } + + private GroupPayload createGroupPayload() { + return GroupPayload.builder() + .name("Test group") + .description("Test description") + .build(); + } + + private GroupPayload createGroupPayload(String name, String description) { + return GroupPayload.builder() + .name(name) + .description(description) + .build(); + } + + private void deleteUserFromDb(User user) { + userRepository.delete(user); + } + + private void deleteGroupFromDb(Group group) { + groupRepository.delete(group); + } +} From e06188a5ef280a766689d8cdfeb260787ca0d009 Mon Sep 17 00:00:00 2001 From: AlexanderGarifullin Date: Mon, 16 Dec 2024 18:52:36 +0500 Subject: [PATCH 26/60] =?UTF-8?q?dev/codeforces/test=20=D0=98=D1=81=D0=BF?= =?UTF-8?q?=D1=80=D0=B0=D0=B2=D0=B8=D0=BB=20=D0=B8=D0=BD=D1=82=D0=B5=D0=B3?= =?UTF-8?q?=D1=80=D0=B0=D1=86=D0=B8=D0=BE=D0=BD=D0=BD=D1=8B=D0=B5=20=D1=82?= =?UTF-8?q?=D0=B5=D1=81=D1=82=D1=8B=20=D0=B8=20=D0=BA=D0=BE=D0=B4=20=D0=BF?= =?UTF-8?q?=D0=BE=D0=B4=20checkStyle?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../cfteam/advicers/security/SecurityExceptionHandler.java | 6 +++--- .../codeforces/GroupControllerIntegrationTest.java | 3 ++- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/cf/cfteam/advicers/security/SecurityExceptionHandler.java b/src/main/java/com/cf/cfteam/advicers/security/SecurityExceptionHandler.java index 2ac464a..5cafe3d 100644 --- a/src/main/java/com/cf/cfteam/advicers/security/SecurityExceptionHandler.java +++ b/src/main/java/com/cf/cfteam/advicers/security/SecurityExceptionHandler.java @@ -18,6 +18,7 @@ public class SecurityExceptionHandler { private static final String LOGIN = "login"; private static final String TOKEN = "token"; + private static final String ID = "id"; @ExceptionHandler(UserAlreadyRegisterException.class) public ResponseEntity handleUserAlreadyRegisterException(UserAlreadyRegisterException ex) { @@ -29,10 +30,10 @@ public ResponseEntity handleUserAlreadyRegisterException(UserAlreadyRegi public ResponseEntity handleUserNotFoundException(UserNotFoundException ex) { Map details = new HashMap<>(); if (ex.getLogin() != null) { - details.put("login", ex.getLogin()); + details.put(LOGIN, ex.getLogin()); } if (ex.getId() != null) { - details.put("id", ex.getId()); + details.put(ID, ex.getId()); } return ErrorResponseBuilder.buildErrorResponse( @@ -42,7 +43,6 @@ public ResponseEntity handleUserNotFoundException(UserNotFoundException ); } - @ExceptionHandler(TokenRevokedException.class) public ResponseEntity handleTokenRevokedException(TokenRevokedException ex) { return ErrorResponseBuilder.buildErrorResponse(ex.getMessage(), HttpStatus.UNAUTHORIZED, Map.of(TOKEN, diff --git a/src/test/java/com/cf/cfteam/controllers/codeforces/GroupControllerIntegrationTest.java b/src/test/java/com/cf/cfteam/controllers/codeforces/GroupControllerIntegrationTest.java index c4973f0..79c62e9 100644 --- a/src/test/java/com/cf/cfteam/controllers/codeforces/GroupControllerIntegrationTest.java +++ b/src/test/java/com/cf/cfteam/controllers/codeforces/GroupControllerIntegrationTest.java @@ -102,7 +102,8 @@ public void getGroupById_notEmpty() { assertThat(responseGroupe).isEqualTo(group); - deleteGroupFromDb(group);; + deleteGroupFromDb(group); + deleteUserFromDb(user); } @Test From c116e7490c0b89a2f2e722237cd25b470e2b1893 Mon Sep 17 00:00:00 2001 From: AlexanderGarifullin Date: Tue, 17 Dec 2024 04:24:12 +0500 Subject: [PATCH 27/60] =?UTF-8?q?dev/codeforces/=20=D0=94=D0=BE=D0=B1?= =?UTF-8?q?=D0=B0=D0=B2=D0=B8=D0=BB=20Response=20=D0=BA=D0=BB=D0=B0=D1=81?= =?UTF-8?q?=D1=81=D1=8B=20=D0=B4=D0=BB=D1=8F=20=D0=BC=D0=BE=D0=B4=D0=B5?= =?UTF-8?q?=D0=BB=D0=B5=D0=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../responses/codeforces/PlayerResponse.java | 11 +++++++++++ .../responses/codeforces/TeamResponse.java | 15 +++++++++++++++ .../transfer/responses/security/UserResponse.java | 4 ++++ 3 files changed, 30 insertions(+) create mode 100644 src/main/java/com/cf/cfteam/transfer/responses/codeforces/PlayerResponse.java create mode 100644 src/main/java/com/cf/cfteam/transfer/responses/codeforces/TeamResponse.java create mode 100644 src/main/java/com/cf/cfteam/transfer/responses/security/UserResponse.java diff --git a/src/main/java/com/cf/cfteam/transfer/responses/codeforces/PlayerResponse.java b/src/main/java/com/cf/cfteam/transfer/responses/codeforces/PlayerResponse.java new file mode 100644 index 0000000..eae701a --- /dev/null +++ b/src/main/java/com/cf/cfteam/transfer/responses/codeforces/PlayerResponse.java @@ -0,0 +1,11 @@ +package com.cf.cfteam.transfer.responses.codeforces; + +import lombok.Builder; + +@Builder +public record PlayerResponse( + Long id, + String login, + Double rating +) { +} diff --git a/src/main/java/com/cf/cfteam/transfer/responses/codeforces/TeamResponse.java b/src/main/java/com/cf/cfteam/transfer/responses/codeforces/TeamResponse.java new file mode 100644 index 0000000..56b2f5b --- /dev/null +++ b/src/main/java/com/cf/cfteam/transfer/responses/codeforces/TeamResponse.java @@ -0,0 +1,15 @@ +package com.cf.cfteam.transfer.responses.codeforces; + +import lombok.Builder; + +import java.util.List; + +@Builder +public record TeamResponse( + Long id, + String name, + String description, + List players, + Double teamRating +) { +} diff --git a/src/main/java/com/cf/cfteam/transfer/responses/security/UserResponse.java b/src/main/java/com/cf/cfteam/transfer/responses/security/UserResponse.java new file mode 100644 index 0000000..98f122c --- /dev/null +++ b/src/main/java/com/cf/cfteam/transfer/responses/security/UserResponse.java @@ -0,0 +1,4 @@ +package com.cf.cfteam.transfer.responses.security; + +public class UserResponse { +} From 71934664e70af7b93598b365adac5568b7f00d05 Mon Sep 17 00:00:00 2001 From: AlexanderGarifullin Date: Tue, 17 Dec 2024 04:24:44 +0500 Subject: [PATCH 28/60] =?UTF-8?q?dev/codeforces/=20=D0=94=D0=BE=D0=B1?= =?UTF-8?q?=D0=B0=D0=B2=D0=B8=D0=BB=20=D0=BA=D1=8D=D1=88=D0=B8=D1=80=D0=BE?= =?UTF-8?q?=D0=B2=D0=B0=D0=BD=D0=B8=D0=B5=20=D0=B4=D0=BB=D1=8F=20=D0=B7?= =?UTF-8?q?=D0=B0=D0=BF=D1=80=D0=BE=D1=81=D0=B0=20=D0=BF=D0=BE=D0=BB=D1=83?= =?UTF-8?q?=D1=87=D0=B5=D0=BD=D0=B8=D1=8F=20=D1=80=D0=B5=D0=B9=D1=82=D0=B8?= =?UTF-8?q?=D0=BD=D0=B3=D0=B0=20=D0=BF=D0=BE=D0=BB=D1=8C=D0=B7=D0=BE=D0=B2?= =?UTF-8?q?=D0=B0=D1=82=D0=B5=D0=BB=D1=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle | 3 +++ .../java/com/cf/cfteam/config/AppConfig.java | 1 + .../com/cf/cfteam/config/CacheConfig.java | 27 +++++++++++++++++++ 3 files changed, 31 insertions(+) create mode 100644 src/main/java/com/cf/cfteam/config/CacheConfig.java diff --git a/build.gradle b/build.gradle index c993236..51def51 100644 --- a/build.gradle +++ b/build.gradle @@ -44,6 +44,9 @@ dependencies { implementation 'io.jsonwebtoken:jjwt-impl:0.12.6' implementation 'io.jsonwebtoken:jjwt-jackson:0.12.6' + // cache + implementation 'com.github.ben-manes.caffeine:caffeine:3.1.8' + // test testImplementation 'org.springframework.boot:spring-boot-starter-test' testImplementation 'org.testcontainers:junit-jupiter:1.20.1' diff --git a/src/main/java/com/cf/cfteam/config/AppConfig.java b/src/main/java/com/cf/cfteam/config/AppConfig.java index 4c2d356..c9f48a8 100644 --- a/src/main/java/com/cf/cfteam/config/AppConfig.java +++ b/src/main/java/com/cf/cfteam/config/AppConfig.java @@ -1,6 +1,7 @@ package com.cf.cfteam.config; import com.cf.cfteam.services.security.MyUserDetailsService; +import com.cf.cfteam.utils.codeforces.mappers.GroupMapper; import lombok.RequiredArgsConstructor; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; diff --git a/src/main/java/com/cf/cfteam/config/CacheConfig.java b/src/main/java/com/cf/cfteam/config/CacheConfig.java new file mode 100644 index 0000000..2e46488 --- /dev/null +++ b/src/main/java/com/cf/cfteam/config/CacheConfig.java @@ -0,0 +1,27 @@ +package com.cf.cfteam.config; + +import com.cf.cfteam.services.client.CodeforcesClient; +import com.github.benmanes.caffeine.cache.Cache; +import com.github.benmanes.caffeine.cache.CacheLoader; +import com.github.benmanes.caffeine.cache.Caffeine; +import com.github.benmanes.caffeine.cache.LoadingCache; +import lombok.RequiredArgsConstructor; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import java.util.concurrent.TimeUnit; + +@Configuration +@RequiredArgsConstructor +public class CacheConfig { + + private final CodeforcesClient codeforcesClient; + + @Bean + public LoadingCache ratingCache() { + return Caffeine.newBuilder() + .expireAfterWrite(1, TimeUnit.HOURS) + .maximumSize(1000) + .build(codeforcesClient::fetchRatingFromApi); + } +} From c6efd6605e85b1cbde3d96949435582ca1460233 Mon Sep 17 00:00:00 2001 From: AlexanderGarifullin Date: Tue, 17 Dec 2024 04:25:06 +0500 Subject: [PATCH 29/60] =?UTF-8?q?dev/codeforces/=20=D0=94=D0=BE=D0=B1?= =?UTF-8?q?=D0=B0=D0=B2=D0=B8=D0=BB=20=D0=BE=D1=88=D0=B8=D0=B1=D0=BA=D0=B8?= =?UTF-8?q?=20=D0=B4=D0=BB=D1=8F=20=D1=80=D0=B0=D0=B1=D0=BE=D1=82=D1=8B=20?= =?UTF-8?q?=D1=81=20API?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../exceptions/client/ClientErrorException.java | 11 +++++++++++ .../exceptions/client/ServerErrorException.java | 14 ++++++++++++++ src/main/resources/codeforces.yml | 4 +++- 3 files changed, 28 insertions(+), 1 deletion(-) create mode 100644 src/main/java/com/cf/cfteam/exceptions/client/ClientErrorException.java create mode 100644 src/main/java/com/cf/cfteam/exceptions/client/ServerErrorException.java diff --git a/src/main/java/com/cf/cfteam/exceptions/client/ClientErrorException.java b/src/main/java/com/cf/cfteam/exceptions/client/ClientErrorException.java new file mode 100644 index 0000000..7eb7c97 --- /dev/null +++ b/src/main/java/com/cf/cfteam/exceptions/client/ClientErrorException.java @@ -0,0 +1,11 @@ +package com.cf.cfteam.exceptions.client; + +public class ClientErrorException extends RuntimeException { + + private final String code; + + public ClientErrorException(String code) { + super("server.error"); + this.code = code; + } +} diff --git a/src/main/java/com/cf/cfteam/exceptions/client/ServerErrorException.java b/src/main/java/com/cf/cfteam/exceptions/client/ServerErrorException.java new file mode 100644 index 0000000..8ecc9c6 --- /dev/null +++ b/src/main/java/com/cf/cfteam/exceptions/client/ServerErrorException.java @@ -0,0 +1,14 @@ +package com.cf.cfteam.exceptions.client; + +import lombok.Getter; + +@Getter +public class ServerErrorException extends RuntimeException { + + private final String code; + + public ServerErrorException(String code) { + super("server.error"); + this.code = code; + } +} diff --git a/src/main/resources/codeforces.yml b/src/main/resources/codeforces.yml index 66b11ef..436380b 100644 --- a/src/main/resources/codeforces.yml +++ b/src/main/resources/codeforces.yml @@ -1,4 +1,6 @@ codeforces: api: base: - url: https://codeforces.com/api/ \ No newline at end of file + url: https://codeforces.com/api + player: + url: /user.info \ No newline at end of file From 1ea75214198e296cf6898299bffec51f2583e19c Mon Sep 17 00:00:00 2001 From: AlexanderGarifullin Date: Tue, 17 Dec 2024 04:25:46 +0500 Subject: [PATCH 30/60] =?UTF-8?q?dev/codeforces/=20=D0=9D=D0=B5=D0=BC?= =?UTF-8?q?=D0=BD=D0=BE=D0=B3=D0=BE=20=D0=B8=D0=B7=D0=BC=D0=B5=D0=BD=D0=B8?= =?UTF-8?q?=D0=BB=20=D0=BC=D0=BE=D0=B4=D0=B5=D0=BB=D0=B8=20=D0=B1=D0=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/cf/cfteam/models/entities/codeforces/Group.java | 1 - .../java/com/cf/cfteam/models/entities/codeforces/Player.java | 2 +- .../java/com/cf/cfteam/models/entities/codeforces/Team.java | 3 ++- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/cf/cfteam/models/entities/codeforces/Group.java b/src/main/java/com/cf/cfteam/models/entities/codeforces/Group.java index 3e3bccb..86b5ec2 100644 --- a/src/main/java/com/cf/cfteam/models/entities/codeforces/Group.java +++ b/src/main/java/com/cf/cfteam/models/entities/codeforces/Group.java @@ -27,7 +27,6 @@ public class Group { @Column(name = "c_description") private String description; - @JsonIgnore @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "c_user_id", nullable = false) private User user; diff --git a/src/main/java/com/cf/cfteam/models/entities/codeforces/Player.java b/src/main/java/com/cf/cfteam/models/entities/codeforces/Player.java index 6ff866c..677b177 100644 --- a/src/main/java/com/cf/cfteam/models/entities/codeforces/Player.java +++ b/src/main/java/com/cf/cfteam/models/entities/codeforces/Player.java @@ -24,7 +24,7 @@ public class Player { private String login; @ManyToMany(cascade = CascadeType.ALL) - @JoinTable(name = "t_team_player", + @JoinTable(name = "t_team_player", schema = "codeforces", joinColumns = @JoinColumn(name = "c_player_id", referencedColumnName = "id"), inverseJoinColumns = @JoinColumn(name = "c_team_id", referencedColumnName = "id")) @Builder.Default diff --git a/src/main/java/com/cf/cfteam/models/entities/codeforces/Team.java b/src/main/java/com/cf/cfteam/models/entities/codeforces/Team.java index ba3df97..3344bbb 100644 --- a/src/main/java/com/cf/cfteam/models/entities/codeforces/Team.java +++ b/src/main/java/com/cf/cfteam/models/entities/codeforces/Team.java @@ -1,5 +1,6 @@ package com.cf.cfteam.models.entities.codeforces; +import com.fasterxml.jackson.annotation.JsonIgnore; import jakarta.persistence.*; import lombok.*; @@ -31,7 +32,7 @@ public class Team { private Group group; @ManyToMany(cascade = CascadeType.ALL) - @JoinTable(name = "t_team_player", + @JoinTable(name = "t_team_player", schema = "codeforces", joinColumns = @JoinColumn(name = "c_team_id", referencedColumnName = "id"), inverseJoinColumns = @JoinColumn(name = "c_player_id", referencedColumnName = "id")) @Builder.Default From a2a81a27ec5eda3e3fad4a010bb20ddf690f692a Mon Sep 17 00:00:00 2001 From: AlexanderGarifullin Date: Tue, 17 Dec 2024 04:26:20 +0500 Subject: [PATCH 31/60] =?UTF-8?q?dev/codeforces/=20=D0=94=D0=BE=D0=B1?= =?UTF-8?q?=D0=B0=D0=B2=D0=B8=D0=BB=20=D0=BC=D0=B0=D0=BF=D0=BF=D0=B5=D1=80?= =?UTF-8?q?=D1=8B=20=D0=B4=D0=BB=D1=8F=20=D0=BF=D1=80=D0=B5=D0=B2=D1=80?= =?UTF-8?q?=D0=B0=D1=89=D0=B5=D0=BD=D0=B8=D1=8F=20=D0=BC=D0=BE=D0=B4=D0=B5?= =?UTF-8?q?=D0=BB=D0=B8=20=D0=B2=20response?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../cfteam/utils/codeforces/GroupMapper.java | 26 ---------- .../utils/codeforces/RatingCalculator.java | 40 ++++++++++++++ .../utils/codeforces/mappers/GroupMapper.java | 52 +++++++++++++++++++ .../codeforces/mappers/PlayerMapper.java | 24 +++++++++ .../utils/codeforces/mappers/TeamMapper.java | 39 ++++++++++++++ 5 files changed, 155 insertions(+), 26 deletions(-) delete mode 100644 src/main/java/com/cf/cfteam/utils/codeforces/GroupMapper.java create mode 100644 src/main/java/com/cf/cfteam/utils/codeforces/RatingCalculator.java create mode 100644 src/main/java/com/cf/cfteam/utils/codeforces/mappers/GroupMapper.java create mode 100644 src/main/java/com/cf/cfteam/utils/codeforces/mappers/PlayerMapper.java create mode 100644 src/main/java/com/cf/cfteam/utils/codeforces/mappers/TeamMapper.java diff --git a/src/main/java/com/cf/cfteam/utils/codeforces/GroupMapper.java b/src/main/java/com/cf/cfteam/utils/codeforces/GroupMapper.java deleted file mode 100644 index b0e259f..0000000 --- a/src/main/java/com/cf/cfteam/utils/codeforces/GroupMapper.java +++ /dev/null @@ -1,26 +0,0 @@ -package com.cf.cfteam.utils.codeforces; - -import com.cf.cfteam.models.entities.codeforces.Group; -import com.cf.cfteam.models.entities.security.User; -import com.cf.cfteam.transfer.payloads.codeforces.GroupPayload; - -public final class GroupMapper { - - public static Group fromPayloadToEntity(GroupPayload payload, User user) { - return Group.builder() - .name(payload.name()) - .description(payload.description()) - .user(user) - .build(); - } - - public static Group updateEntityFromPayload(Group group, GroupPayload payload) { - group.setName(payload.name()); - group.setDescription(payload.description()); - return group; - } - - private GroupMapper() { - throw new UnsupportedOperationException("Utility class"); - } -} diff --git a/src/main/java/com/cf/cfteam/utils/codeforces/RatingCalculator.java b/src/main/java/com/cf/cfteam/utils/codeforces/RatingCalculator.java new file mode 100644 index 0000000..52fc605 --- /dev/null +++ b/src/main/java/com/cf/cfteam/utils/codeforces/RatingCalculator.java @@ -0,0 +1,40 @@ +package com.cf.cfteam.utils.codeforces; + +import com.cf.cfteam.transfer.responses.codeforces.PlayerResponse; + +import java.util.List; + +public class RatingCalculator { + + public static double getWinProbability(double ra, double rb) { + return 1.0 / (1.0 + Math.pow(10.0, (rb - ra) / 400.0)); + } + + public static double aggregateRatings(List players) { + double left = 1.0; + double right = 1E4; + + for (int tt = 0; tt < 100; tt++) { + double r = (left + right) / 2.0; + + double rWinsProbability = 1.0; + for (PlayerResponse player : players) { + rWinsProbability *= getWinProbability(r, player.rating()); + } + + double rating = Math.log10(1 / rWinsProbability - 1) * 400 + r; + + if (rating > r) { + left = r; + } else { + right = r; + } + } + + return (left + right) / 2.0; + } + + private RatingCalculator() { + throw new UnsupportedOperationException("Utility class"); + } +} diff --git a/src/main/java/com/cf/cfteam/utils/codeforces/mappers/GroupMapper.java b/src/main/java/com/cf/cfteam/utils/codeforces/mappers/GroupMapper.java new file mode 100644 index 0000000..7de6312 --- /dev/null +++ b/src/main/java/com/cf/cfteam/utils/codeforces/mappers/GroupMapper.java @@ -0,0 +1,52 @@ +package com.cf.cfteam.utils.codeforces.mappers; + +import com.cf.cfteam.models.entities.codeforces.Group; +import com.cf.cfteam.models.entities.security.User; +import com.cf.cfteam.transfer.payloads.codeforces.GroupPayload; +import com.cf.cfteam.transfer.responses.codeforces.GroupResponse; +import com.cf.cfteam.transfer.responses.codeforces.PlayerResponse; +import com.cf.cfteam.transfer.responses.codeforces.TeamResponse; +import lombok.NoArgsConstructor; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Component; + +import java.util.ArrayList; +import java.util.List; + +@Component +@RequiredArgsConstructor +public final class GroupMapper { + + private final TeamMapper teamMapper; + + public Group fromPayloadToEntity(GroupPayload payload, User user) { + return Group.builder() + .name(payload.name()) + .description(payload.description()) + .user(user) + .build(); + } + + public Group updateEntityFromPayload(Group group, GroupPayload payload) { + group.setName(payload.name()); + group.setDescription(payload.description()); + return group; + } + + public GroupResponse fromEntityToResponse(Group group) { + List convertedTeams = new ArrayList<>(); + + if (group.getTeams() != null) { + convertedTeams = group.getTeams().stream() + .map(teamMapper::fromEntityToResponse) + .toList(); + } + + return GroupResponse.builder() + .id(group.getId()) + .name(group.getName()) + .description(group.getDescription()) + .teams(convertedTeams) + .build(); + } +} diff --git a/src/main/java/com/cf/cfteam/utils/codeforces/mappers/PlayerMapper.java b/src/main/java/com/cf/cfteam/utils/codeforces/mappers/PlayerMapper.java new file mode 100644 index 0000000..d5eda65 --- /dev/null +++ b/src/main/java/com/cf/cfteam/utils/codeforces/mappers/PlayerMapper.java @@ -0,0 +1,24 @@ +package com.cf.cfteam.utils.codeforces.mappers; + +import com.cf.cfteam.models.entities.codeforces.Player; +import com.cf.cfteam.transfer.responses.codeforces.PlayerResponse; +import com.github.benmanes.caffeine.cache.Cache; +import com.github.benmanes.caffeine.cache.LoadingCache; +import lombok.RequiredArgsConstructor; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +@Component +@RequiredArgsConstructor +public class PlayerMapper { + + private final LoadingCache ratingCache; + + public PlayerResponse fromEntityToResponse(Player player) { + return PlayerResponse.builder() + .id(player.getId()) + .login(player.getLogin()) + .rating(ratingCache.get(player.getLogin())) + .build(); + } +} diff --git a/src/main/java/com/cf/cfteam/utils/codeforces/mappers/TeamMapper.java b/src/main/java/com/cf/cfteam/utils/codeforces/mappers/TeamMapper.java new file mode 100644 index 0000000..d6c79e0 --- /dev/null +++ b/src/main/java/com/cf/cfteam/utils/codeforces/mappers/TeamMapper.java @@ -0,0 +1,39 @@ +package com.cf.cfteam.utils.codeforces.mappers; + +import com.cf.cfteam.models.entities.codeforces.Team; +import com.cf.cfteam.transfer.responses.codeforces.PlayerResponse; +import com.cf.cfteam.transfer.responses.codeforces.TeamResponse; +import com.cf.cfteam.utils.codeforces.RatingCalculator; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Component; + +import java.util.ArrayList; +import java.util.List; + +@Component +@RequiredArgsConstructor +public class TeamMapper { + + private final PlayerMapper playerMapper; + + public TeamResponse fromEntityToResponse(Team team) { + List convertedPlayers = new ArrayList<>(); + Double teamRating = 0.; + + if (team.getPlayers() != null) { + convertedPlayers = team.getPlayers().stream() + .map(playerMapper::fromEntityToResponse) + .toList(); + + teamRating = RatingCalculator.aggregateRatings(convertedPlayers); + } + + return TeamResponse.builder() + .id(team.getId()) + .name(team.getName()) + .description(team.getDescription()) + .players(convertedPlayers) + .teamRating(teamRating) + .build(); + } +} From 123c991a1cce30d15ff23451158da5016058f224 Mon Sep 17 00:00:00 2001 From: AlexanderGarifullin Date: Tue, 17 Dec 2024 04:26:47 +0500 Subject: [PATCH 32/60] =?UTF-8?q?dev/codeforces/=20=D0=94=D0=BE=D0=B1?= =?UTF-8?q?=D0=B0=D0=B2=D0=B8=D0=BB=20=D1=81=D0=B5=D1=80=D0=B2=D0=B8=D1=81?= =?UTF-8?q?=D1=8B=20=D0=B4=D0=BB=D1=8F=20=D0=BC=D0=BE=D0=B4=D0=B5=D0=BB?= =?UTF-8?q?=D0=B5=D0=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../services/codeforces/GroupService.java | 36 +++++++++++++------ .../services/codeforces/PlayerService.java | 33 +++++++++++++++++ .../services/codeforces/TeamService.java | 30 ++++++++++++++++ 3 files changed, 88 insertions(+), 11 deletions(-) diff --git a/src/main/java/com/cf/cfteam/services/codeforces/GroupService.java b/src/main/java/com/cf/cfteam/services/codeforces/GroupService.java index b033d84..2d004b5 100644 --- a/src/main/java/com/cf/cfteam/services/codeforces/GroupService.java +++ b/src/main/java/com/cf/cfteam/services/codeforces/GroupService.java @@ -2,16 +2,20 @@ import com.cf.cfteam.exceptions.codeforces.GroupNotFoundException; import com.cf.cfteam.exceptions.security.UserNotFoundException; -import com.cf.cfteam.utils.codeforces.GroupMapper; +import com.cf.cfteam.transfer.responses.codeforces.GroupResponse; +import com.cf.cfteam.utils.codeforces.mappers.GroupMapper; import com.cf.cfteam.models.entities.codeforces.Group; import com.cf.cfteam.models.entities.security.User; import com.cf.cfteam.repositories.jpa.codeforces.GroupRepository; import com.cf.cfteam.repositories.jpa.security.UserRepository; import com.cf.cfteam.transfer.payloads.codeforces.GroupPayload; +import com.cf.cfteam.utils.codeforces.mappers.TeamMapper; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; +import javax.swing.text.html.Option; import java.util.List; +import java.util.Optional; @Service @RequiredArgsConstructor @@ -19,34 +23,44 @@ public class GroupService { private final GroupRepository groupRepository; private final UserRepository userRepository; + private final GroupMapper groupMapper; - public List getAllGroupsByUser(Long userId) { + public List getAllGroupsByUser(Long userId) { User user = userRepository.findById(userId) .orElseThrow(() -> new UserNotFoundException(userId)); - return groupRepository.findByUser(user); + + List groups = groupRepository.findByUser(user); + + return groups.stream() + .map(groupMapper::fromEntityToResponse) + .toList(); } - public Group getGroupById(Long groupId) { - return groupRepository.findById(groupId) + public GroupResponse getGroupById(Long groupId) { + Group group = groupRepository.findById(groupId) .orElseThrow(() -> new GroupNotFoundException(groupId)); + + return groupMapper.fromEntityToResponse(group); } - public Group addGroupToUser(Long userId, GroupPayload groupPayload) { + public GroupResponse addGroupToUser(Long userId, GroupPayload groupPayload) { User user = userRepository.findById(userId) .orElseThrow(() -> new UserNotFoundException(userId)); - Group group = GroupMapper.fromPayloadToEntity(groupPayload, user); + Group group = groupMapper.fromPayloadToEntity(groupPayload, user); + group = groupRepository.save(group); - return groupRepository.save(group); + return groupMapper.fromEntityToResponse(group); } - public Group updateGroup(Long groupId, GroupPayload groupPayload) { + public GroupResponse updateGroup(Long groupId, GroupPayload groupPayload) { Group group = groupRepository.findById(groupId) .orElseThrow(() -> new GroupNotFoundException(groupId)); - Group updatedGroup = GroupMapper.updateEntityFromPayload(group, groupPayload); + Group updatedGroup = groupMapper.updateEntityFromPayload(group, groupPayload); + updatedGroup = groupRepository.save(updatedGroup); - return groupRepository.save(updatedGroup); + return groupMapper.fromEntityToResponse(updatedGroup); } diff --git a/src/main/java/com/cf/cfteam/services/codeforces/PlayerService.java b/src/main/java/com/cf/cfteam/services/codeforces/PlayerService.java index 8899242..0e134f8 100644 --- a/src/main/java/com/cf/cfteam/services/codeforces/PlayerService.java +++ b/src/main/java/com/cf/cfteam/services/codeforces/PlayerService.java @@ -1,9 +1,42 @@ package com.cf.cfteam.services.codeforces; +import com.cf.cfteam.models.entities.codeforces.Player; +import com.cf.cfteam.repositories.jpa.codeforces.PlayerRepository; +import com.cf.cfteam.transfer.payloads.codeforces.GroupPayload; +import com.cf.cfteam.transfer.payloads.codeforces.TeamPayload; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; +import java.util.List; + @Service @RequiredArgsConstructor public class PlayerService { + + private final PlayerRepository playerRepository; + + public List getAllPlayersByTeam(Long teamId) { + return null; + } + + public Player getPlayerById(Long playerId) { + return null; + } + + public Player addPlayerToTeam(Long teamId, TeamPayload teamPayload) { + return null; + } + + + public Player updatePlayer(Long playerId, Long teamId, GroupPayload groupPayload) { + return null; + } + + + public void deletePlayerFromTeam(Long playerId, Long teamId) { + } + + + public void deleteAllPlayersFromTeam(Long teamId) { + } } diff --git a/src/main/java/com/cf/cfteam/services/codeforces/TeamService.java b/src/main/java/com/cf/cfteam/services/codeforces/TeamService.java index 7a9f31f..ef78ea0 100644 --- a/src/main/java/com/cf/cfteam/services/codeforces/TeamService.java +++ b/src/main/java/com/cf/cfteam/services/codeforces/TeamService.java @@ -1,9 +1,39 @@ package com.cf.cfteam.services.codeforces; +import com.cf.cfteam.models.entities.codeforces.Team; +import com.cf.cfteam.repositories.jpa.codeforces.TeamRepository; +import com.cf.cfteam.transfer.payloads.codeforces.GroupPayload; +import com.cf.cfteam.transfer.payloads.codeforces.TeamPayload; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; +import java.util.List; + @Service @RequiredArgsConstructor public class TeamService { + + private final TeamRepository teamRepository; + + public List getAllTeamsByGroup(Long groupId) { + return null; + } + + public Team getTeamById(Long teamId) { + return teamRepository.findById(teamId).get(); + } + + public Team addTeamToGroup(Long groupId, TeamPayload teamPayload) { + return null; + } + + public Team updateTeam(Long teamId, GroupPayload groupPayload) { + return null; + } + + public void deleteTeam(Long teamId) { + } + + public void deleteAllTeamsByGroup(Long groupId) { + } } From 824c2a69af0b2c92506cb5bd704676526bd80ef1 Mon Sep 17 00:00:00 2001 From: AlexanderGarifullin Date: Tue, 17 Dec 2024 04:27:09 +0500 Subject: [PATCH 33/60] =?UTF-8?q?dev/codeforces/=20=D0=94=D0=BE=D0=B1?= =?UTF-8?q?=D0=B0=D0=B2=D0=B8=D0=BB=20DTO=20=D0=B4=D0=BB=D1=8F=20api?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../services/client/CodeforcesClient.java | 44 +++++++++++++++++++ .../client/CodeforcesPlayerResponse.java | 16 +++++++ .../responses/codeforces/GroupResponse.java | 14 ++++++ 3 files changed, 74 insertions(+) create mode 100644 src/main/java/com/cf/cfteam/services/client/CodeforcesClient.java create mode 100644 src/main/java/com/cf/cfteam/services/client/CodeforcesPlayerResponse.java create mode 100644 src/main/java/com/cf/cfteam/transfer/responses/codeforces/GroupResponse.java diff --git a/src/main/java/com/cf/cfteam/services/client/CodeforcesClient.java b/src/main/java/com/cf/cfteam/services/client/CodeforcesClient.java new file mode 100644 index 0000000..72141a7 --- /dev/null +++ b/src/main/java/com/cf/cfteam/services/client/CodeforcesClient.java @@ -0,0 +1,44 @@ +package com.cf.cfteam.services.client; + + +import com.cf.cfteam.exceptions.client.ClientErrorException; +import com.cf.cfteam.exceptions.client.ServerErrorException; +import lombok.RequiredArgsConstructor; + +import org.springframework.beans.factory.annotation.Value; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Service; +import org.springframework.web.client.RestClient; + +@Service +@RequiredArgsConstructor +public class CodeforcesClient { + + private final RestClient restClient; + + @Value("${codeforces.api.player.url}") + private String playerUrl; + + public Double fetchRatingFromApi(String login) { + ResponseEntity playerResponse = restClient.get() + .uri(uriBuilder -> uriBuilder + .path(playerUrl) + .queryParam("handles", login) + .queryParam("checkHistoricHandles", false) + .build()) + .retrieve() + .toEntity(UserInfoResponse.class); + if (playerResponse.getStatusCode().is2xxSuccessful() && playerResponse.getBody() != null && + playerResponse.getBody().getResult().size() == 1 && playerResponse.getBody().getResult().getFirst() != null) { + return playerResponse.getBody().getResult().getFirst().getRating() != null ? + playerResponse.getBody().getResult().getFirst().getRating() : 0.; + } + if (playerResponse.getStatusCode().is4xxClientError()) { + throw new ClientErrorException(playerResponse.getStatusCode().toString()); + } + if (playerResponse.getStatusCode().is5xxServerError()) { + throw new ServerErrorException(playerResponse.getStatusCode().toString()); + } + throw new RuntimeException("Error: " + playerResponse.getStatusCode()); + } +} diff --git a/src/main/java/com/cf/cfteam/services/client/CodeforcesPlayerResponse.java b/src/main/java/com/cf/cfteam/services/client/CodeforcesPlayerResponse.java new file mode 100644 index 0000000..68f4f67 --- /dev/null +++ b/src/main/java/com/cf/cfteam/services/client/CodeforcesPlayerResponse.java @@ -0,0 +1,16 @@ +package com.cf.cfteam.services.client; + +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +public class CodeforcesPlayerResponse { + + @JsonProperty("handle") + private String handle; + + @JsonProperty("rating") + private Double rating; +} diff --git a/src/main/java/com/cf/cfteam/transfer/responses/codeforces/GroupResponse.java b/src/main/java/com/cf/cfteam/transfer/responses/codeforces/GroupResponse.java new file mode 100644 index 0000000..6c76729 --- /dev/null +++ b/src/main/java/com/cf/cfteam/transfer/responses/codeforces/GroupResponse.java @@ -0,0 +1,14 @@ +package com.cf.cfteam.transfer.responses.codeforces; + +import lombok.Builder; + +import java.util.List; + +@Builder +public record GroupResponse( + Long id, + String name, + String description, + List teams +) { +} From 2b176b60401f9bd19b0ea7a5be99456b15b12411 Mon Sep 17 00:00:00 2001 From: AlexanderGarifullin Date: Tue, 17 Dec 2024 04:27:29 +0500 Subject: [PATCH 34/60] =?UTF-8?q?dev/codeforces/=20=D0=94=D0=BE=D0=B1?= =?UTF-8?q?=D0=B0=D0=B2=D0=B8=D0=BB=20=D0=BA=D0=BE=D0=BD=D1=82=D1=80=D0=BE?= =?UTF-8?q?=D0=BB=D0=BB=D0=B5=D1=80=D1=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../codeforces/PlayerController.java | 59 +++++++++++++++++++ .../codeforces/TeamController.java | 54 +++++++++++++++++ .../services/client/UserInfoResponse.java | 18 ++++++ 3 files changed, 131 insertions(+) create mode 100644 src/main/java/com/cf/cfteam/services/client/UserInfoResponse.java diff --git a/src/main/java/com/cf/cfteam/controllers/codeforces/PlayerController.java b/src/main/java/com/cf/cfteam/controllers/codeforces/PlayerController.java index 01812b3..eab95e6 100644 --- a/src/main/java/com/cf/cfteam/controllers/codeforces/PlayerController.java +++ b/src/main/java/com/cf/cfteam/controllers/codeforces/PlayerController.java @@ -1,4 +1,63 @@ package com.cf.cfteam.controllers.codeforces; +import com.cf.cfteam.models.entities.codeforces.Player; +import com.cf.cfteam.models.entities.codeforces.Team; +import com.cf.cfteam.services.codeforces.PlayerService; +import com.cf.cfteam.transfer.payloads.codeforces.GroupPayload; +import com.cf.cfteam.transfer.payloads.codeforces.TeamPayload; +import lombok.RequiredArgsConstructor; +import org.springframework.http.ResponseEntity; +import org.springframework.security.core.Authentication; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +@RestController +@RequiredArgsConstructor +@RequestMapping("api/cf/players") public class PlayerController { + + private final PlayerService playerService; + + @GetMapping("/team/{teamId}") + public ResponseEntity> getAllPlayersByTeam(@PathVariable Long teamId, Authentication authentication) { + List players = playerService.getAllPlayersByTeam(teamId); + return ResponseEntity.ok(players); + } + + @GetMapping("/{playerId}") + public ResponseEntity getPlayerById(@PathVariable Long playerId, Authentication authentication) { + Player player = playerService.getPlayerById(playerId); + return ResponseEntity.ok(player); + } + + @PostMapping("/team/{teamId}") + public ResponseEntity addPlayerToTeam(@PathVariable Long teamId, @RequestBody TeamPayload teamPayload, + Authentication authentication) { + Player player = playerService.addPlayerToTeam(teamId, teamPayload); + return ResponseEntity.ok(player); + } + + @PutMapping("/players/{playerId}/teams/{teamId}") + public ResponseEntity updatePlayerInTeam(@PathVariable Long playerId, + @PathVariable Long teamId, + @RequestBody GroupPayload groupPayload, + Authentication authentication) { + Player player = playerService.updatePlayer(playerId, teamId, groupPayload); + return ResponseEntity.ok(player); + } + + @DeleteMapping("/players/{playerId}/teams/{teamId}") + public ResponseEntity deletePlayerFromTeam(@PathVariable Long playerId, + @PathVariable Long teamId, + Authentication authentication) { + playerService.deletePlayerFromTeam(playerId, teamId); + return ResponseEntity.noContent().build(); + } + + @DeleteMapping("/team/{teamId}") + public ResponseEntity deleteAllPlayersFromTeam(@PathVariable Long teamId, Authentication authentication) { + playerService.deleteAllPlayersFromTeam(teamId); + return ResponseEntity.noContent().build(); + } } diff --git a/src/main/java/com/cf/cfteam/controllers/codeforces/TeamController.java b/src/main/java/com/cf/cfteam/controllers/codeforces/TeamController.java index b9d9ac0..57dd2b0 100644 --- a/src/main/java/com/cf/cfteam/controllers/codeforces/TeamController.java +++ b/src/main/java/com/cf/cfteam/controllers/codeforces/TeamController.java @@ -1,4 +1,58 @@ package com.cf.cfteam.controllers.codeforces; +import com.cf.cfteam.models.entities.codeforces.Team; +import com.cf.cfteam.services.codeforces.TeamService; +import com.cf.cfteam.transfer.payloads.codeforces.GroupPayload; +import com.cf.cfteam.transfer.payloads.codeforces.TeamPayload; +import lombok.RequiredArgsConstructor; +import org.springframework.http.ResponseEntity; +import org.springframework.security.core.Authentication; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +@RestController +@RequiredArgsConstructor +@RequestMapping("api/cf/teams") public class TeamController { + + private final TeamService teamService; + + @GetMapping("/group/{groupId}") + public ResponseEntity> getAllTeamsByGroup(@PathVariable Long groupId, Authentication authentication) { + List teams = teamService.getAllTeamsByGroup(groupId); + return ResponseEntity.ok(teams); + } + + @GetMapping("/{teamId}") + public ResponseEntity getTeamById(@PathVariable Long teamId, Authentication authentication) { + Team team = teamService.getTeamById(teamId); + return ResponseEntity.ok(team); + } + + @PostMapping("/group/{groupId}") + public ResponseEntity addTeamToGroup(@PathVariable Long groupId, @RequestBody TeamPayload teamPayload, + Authentication authentication) { + Team createdTeam = teamService.addTeamToGroup(groupId, teamPayload); + return ResponseEntity.ok(createdTeam); + } + + @PutMapping("/{teamId}") + public ResponseEntity updateTeam(@PathVariable Long teamId, @RequestBody GroupPayload groupPayload, + Authentication authentication) { + Team team = teamService.updateTeam(teamId, groupPayload); + return ResponseEntity.ok(team); + } + + @DeleteMapping("/{teamId}") + public ResponseEntity deleteTeam(@PathVariable Long teamId, Authentication authentication) { + teamService.deleteTeam(teamId); + return ResponseEntity.noContent().build(); + } + + @DeleteMapping("/group/{groupId}") + public ResponseEntity deleteAllTeamsByUser(@PathVariable Long groupId, Authentication authentication) { + teamService.deleteAllTeamsByGroup(groupId); + return ResponseEntity.noContent().build(); + } } diff --git a/src/main/java/com/cf/cfteam/services/client/UserInfoResponse.java b/src/main/java/com/cf/cfteam/services/client/UserInfoResponse.java new file mode 100644 index 0000000..c761839 --- /dev/null +++ b/src/main/java/com/cf/cfteam/services/client/UserInfoResponse.java @@ -0,0 +1,18 @@ +package com.cf.cfteam.services.client; + +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.Getter; +import lombok.Setter; + +import java.util.List; + +@Getter +@Setter +public class UserInfoResponse { + + @JsonProperty("status") + private String status; + + @JsonProperty("result") + private List result; +} From cd8c00b9f502ae8147f485d4c644cc646504a79a Mon Sep 17 00:00:00 2001 From: AlexanderGarifullin Date: Tue, 17 Dec 2024 04:27:51 +0500 Subject: [PATCH 35/60] =?UTF-8?q?dev/codeforces/=20=D0=90=D0=BA=D1=82?= =?UTF-8?q?=D1=83=D0=B0=D0=BB=D0=B8=D0=B7=D0=B8=D1=80=D0=BE=D0=B2=D0=B0?= =?UTF-8?q?=D0=BB=20=D1=82=D0=B5=D1=81=D1=82=D1=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../codeforces/GroupController.java | 18 +++---- .../GroupControllerIntegrationTest.java | 28 ++++++----- .../codeforces/GroupControllerTest.java | 47 ++++++++++++------- .../services/codeforces/GroupServiceTest.java | 33 +++++++++---- .../utils/codeforces/GroupMapperTest.java | 16 ++++++- 5 files changed, 91 insertions(+), 51 deletions(-) diff --git a/src/main/java/com/cf/cfteam/controllers/codeforces/GroupController.java b/src/main/java/com/cf/cfteam/controllers/codeforces/GroupController.java index b9a33dd..df43be2 100644 --- a/src/main/java/com/cf/cfteam/controllers/codeforces/GroupController.java +++ b/src/main/java/com/cf/cfteam/controllers/codeforces/GroupController.java @@ -1,8 +1,8 @@ package com.cf.cfteam.controllers.codeforces; -import com.cf.cfteam.models.entities.codeforces.Group; import com.cf.cfteam.services.codeforces.GroupService; import com.cf.cfteam.transfer.payloads.codeforces.GroupPayload; +import com.cf.cfteam.transfer.responses.codeforces.GroupResponse; import lombok.RequiredArgsConstructor; import org.springframework.http.ResponseEntity; import org.springframework.security.core.Authentication; @@ -18,28 +18,28 @@ public class GroupController { private final GroupService groupService; @GetMapping("/user/{userId}") - public ResponseEntity> getAllGroupsByUser(@PathVariable Long userId, Authentication authentication) { - List groups = groupService.getAllGroupsByUser(userId); + public ResponseEntity> getAllGroupsByUser(@PathVariable Long userId, Authentication authentication) { + List groups = groupService.getAllGroupsByUser(userId); return ResponseEntity.ok(groups); } @GetMapping("/{groupId}") - public ResponseEntity getGroupById(@PathVariable Long groupId, Authentication authentication) { - Group group = groupService.getGroupById(groupId); + public ResponseEntity getGroupById(@PathVariable Long groupId, Authentication authentication) { + GroupResponse group = groupService.getGroupById(groupId); return ResponseEntity.ok(group); } @PostMapping("/user/{userId}") - public ResponseEntity addGroupToUser(@PathVariable Long userId, @RequestBody GroupPayload groupPayload, + public ResponseEntity addGroupToUser(@PathVariable Long userId, @RequestBody GroupPayload groupPayload, Authentication authentication) { - Group createdGroup = groupService.addGroupToUser(userId, groupPayload); + GroupResponse createdGroup = groupService.addGroupToUser(userId, groupPayload); return ResponseEntity.ok(createdGroup); } @PutMapping("/{groupId}") - public ResponseEntity updateGroup(@PathVariable Long groupId, @RequestBody GroupPayload groupPayload, + public ResponseEntity updateGroup(@PathVariable Long groupId, @RequestBody GroupPayload groupPayload, Authentication authentication) { - Group group = groupService.updateGroup(groupId, groupPayload); + GroupResponse group = groupService.updateGroup(groupId, groupPayload); return ResponseEntity.ok(group); } diff --git a/src/test/java/com/cf/cfteam/controllers/codeforces/GroupControllerIntegrationTest.java b/src/test/java/com/cf/cfteam/controllers/codeforces/GroupControllerIntegrationTest.java index 79c62e9..0c2eed5 100644 --- a/src/test/java/com/cf/cfteam/controllers/codeforces/GroupControllerIntegrationTest.java +++ b/src/test/java/com/cf/cfteam/controllers/codeforces/GroupControllerIntegrationTest.java @@ -1,5 +1,7 @@ package com.cf.cfteam.controllers.codeforces; +import com.cf.cfteam.transfer.responses.codeforces.GroupResponse; +import com.cf.cfteam.utils.codeforces.mappers.GroupMapper; import com.fasterxml.jackson.core.type.TypeReference; import com.cf.cfteam.BaseIntegrationTest; import com.cf.cfteam.models.entities.codeforces.Group; @@ -35,6 +37,9 @@ public class GroupControllerIntegrationTest extends BaseIntegrationTest { @Autowired private UserRepository userRepository; + @Autowired + private GroupMapper groupMapper; + @Test @SneakyThrows public void getAllGroupsByUser_notEmpty_success() { @@ -55,12 +60,12 @@ public void getAllGroupsByUser_notEmpty_success() { var groups = objectMapper.readValue( mvcResponse.getContentAsString(), - new TypeReference>() { + new TypeReference>() { } ); assertThat(groups).hasSize(1) - .contains(group); + .contains(groupMapper.fromEntityToResponse(group)); deleteGroupFromDb(group); deleteUserFromDb(user); @@ -98,9 +103,9 @@ public void getGroupById_notEmpty() { .andReturn() .getResponse(); - var responseGroupe = objectMapper.readValue(mvcResponse.getContentAsString(), Group.class); + var responseGroupe = objectMapper.readValue(mvcResponse.getContentAsString(), GroupResponse.class); - assertThat(responseGroupe).isEqualTo(group); + assertThat(responseGroupe).isEqualTo(groupMapper.fromEntityToResponse(group)); deleteGroupFromDb(group); deleteUserFromDb(user); @@ -139,14 +144,13 @@ public void addGroupToUser_success() { .andReturn() .getResponse(); - var responseGroupe = objectMapper.readValue(mvcResponse.getContentAsString(), Group.class); - var groupFromDb = groupRepository.findById(responseGroupe.getId()); + var responseGroupe = objectMapper.readValue(mvcResponse.getContentAsString(), GroupResponse.class); + var groupFromDb = groupRepository.findById(responseGroupe.id()); assertAll( () -> assertThat(groupFromDb).isPresent(), - () -> assertThat(groupFromDb.get()).isEqualTo(responseGroupe), - () -> assertThat(responseGroupe.getDescription()).isEqualTo(payload.description()), - () -> assertThat(responseGroupe.getName()).isEqualTo(payload.name()) + () -> assertThat(responseGroupe.description()).isEqualTo(payload.description()), + () -> assertThat(responseGroupe.name()).isEqualTo(payload.name()) ); deleteGroupFromDb(groupFromDb.get()); @@ -195,8 +199,8 @@ public void updateGroup_success() { .getResponse(); - var responseGroupe = objectMapper.readValue(mvcResponse.getContentAsString(), Group.class); - var groupFromDb = groupRepository.findById(responseGroupe.getId()); + var responseGroupe = objectMapper.readValue(mvcResponse.getContentAsString(), GroupResponse.class); + var groupFromDb = groupRepository.findById(responseGroupe.id()); assertAll( () -> assertThat(groupFromDb).isPresent(), @@ -287,7 +291,7 @@ public void deleteAllGroupsByUser_success() { var groups = objectMapper.readValue( mvcResponse.getContentAsString(), - new TypeReference>() { + new TypeReference>() { } ); diff --git a/src/test/java/com/cf/cfteam/controllers/codeforces/GroupControllerTest.java b/src/test/java/com/cf/cfteam/controllers/codeforces/GroupControllerTest.java index cbf1c47..2a9d5ef 100644 --- a/src/test/java/com/cf/cfteam/controllers/codeforces/GroupControllerTest.java +++ b/src/test/java/com/cf/cfteam/controllers/codeforces/GroupControllerTest.java @@ -3,6 +3,8 @@ import com.cf.cfteam.models.entities.codeforces.Group; import com.cf.cfteam.services.codeforces.GroupService; import com.cf.cfteam.transfer.payloads.codeforces.GroupPayload; +import com.cf.cfteam.transfer.responses.codeforces.GroupResponse; +import com.cf.cfteam.utils.codeforces.mappers.GroupMapper; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.mockito.InjectMocks; @@ -23,75 +25,84 @@ class GroupControllerTest { @InjectMocks private GroupController groupController; + @Mock + private GroupMapper groupMapper; + @Mock private GroupService groupService; private GroupPayload groupPayload; - private Group group; +// private Group group; + private GroupResponse groupResponse; @BeforeEach void setUp() { MockitoAnnotations.openMocks(this); - group = Group.builder() +// group = Group.builder() +// .name("Test Group") +// .description("Test description") +// .user(null) +// .build(); + + groupPayload = GroupPayload.builder() .name("Test Group") .description("Test description") - .user(null) .build(); - groupPayload = GroupPayload.builder() + groupResponse = GroupResponse.builder() .name("Test Group") .description("Test description") + .teams(null) .build(); } @Test void shouldReturnGroupsByUserId() { - when(groupService.getAllGroupsByUser(1L)).thenReturn(List.of(group)); + when(groupService.getAllGroupsByUser(1L)).thenReturn(List.of(groupResponse)); - List groups = groupController.getAllGroupsByUser(1L, null).getBody(); + List groups = groupController.getAllGroupsByUser(1L, null).getBody(); verify(groupService, times(1)).getAllGroupsByUser(1L); assertThat(groups) .isNotNull() .hasSize(1) - .contains(group); + .contains(groupResponse); } @Test void shouldReturnGroupById() { - when(groupService.getGroupById(1L)).thenReturn(group); + when(groupService.getGroupById(1L)).thenReturn(groupResponse); - Group result = groupController.getGroupById(1L, null).getBody(); + GroupResponse result = groupController.getGroupById(1L, null).getBody(); verify(groupService, times(1)).getGroupById(1L); - assertThat(result).isEqualTo(group); + assertThat(result).isEqualTo(groupResponse); } @Test void shouldAddGroupToUser() { - when(groupService.addGroupToUser(1L, groupPayload)).thenReturn(group); - + when(groupService.addGroupToUser(1L, groupPayload)).thenReturn(groupResponse); - Group result = groupController.addGroupToUser(1L, groupPayload, null).getBody(); + GroupResponse result = groupController.addGroupToUser(1L, groupPayload, null).getBody(); verify(groupService, times(1)).addGroupToUser(1L, groupPayload); - assertThat(result).isEqualTo(group); + assertThat(result).isEqualTo(groupResponse); } @Test void shouldUpdateGroup() { - when(groupService.updateGroup(1L, groupPayload)).thenReturn(group); + when(groupService.updateGroup(1L, groupPayload)).thenReturn(groupResponse); - Group result = groupController.updateGroup(1L, groupPayload, null).getBody(); + GroupResponse result = groupController.updateGroup(1L, groupPayload, null).getBody(); verify(groupService, times(1)).updateGroup(1L, groupPayload); assertAll( () -> assertThat(result).isNotNull(), - () -> assertThat(result.getName()).isEqualTo(groupPayload.name()), - () -> assertThat(result.getDescription()).isEqualTo(groupPayload.description()) + () -> assertThat(result.name()).isEqualTo(groupPayload.name()), + () -> assertThat(result.description()).isEqualTo(groupPayload.description()) ); } diff --git a/src/test/java/com/cf/cfteam/services/codeforces/GroupServiceTest.java b/src/test/java/com/cf/cfteam/services/codeforces/GroupServiceTest.java index ada6193..dd63313 100644 --- a/src/test/java/com/cf/cfteam/services/codeforces/GroupServiceTest.java +++ b/src/test/java/com/cf/cfteam/services/codeforces/GroupServiceTest.java @@ -8,6 +8,8 @@ import com.cf.cfteam.repositories.jpa.codeforces.GroupRepository; import com.cf.cfteam.repositories.jpa.security.UserRepository; import com.cf.cfteam.transfer.payloads.codeforces.GroupPayload; +import com.cf.cfteam.transfer.responses.codeforces.GroupResponse; +import com.cf.cfteam.utils.codeforces.mappers.GroupMapper; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.mockito.InjectMocks; @@ -36,9 +38,13 @@ class GroupServiceTest { @Mock private UserRepository userRepository; + @Mock + private GroupMapper groupMapper; + private User user; private Group group; private GroupPayload groupPayload; + private GroupResponse groupResponse; @BeforeEach void setUp() { @@ -61,17 +67,24 @@ void setUp() { .name("Test Group") .description("Test description") .build(); + + groupResponse = GroupResponse.builder() + .name("Test Group") + .description("Test description") + .teams(null) + .build(); } @Test void getAllGroupsByUser_ShouldReturnGroups_WhenUserExists() { when(userRepository.findById(1L)).thenReturn(Optional.of(user)); when(groupRepository.findByUser(user)).thenReturn(List.of(group)); + when(groupMapper.fromEntityToResponse(group)).thenReturn(groupResponse); var groups = groupService.getAllGroupsByUser(1L); assertThat(groups).hasSize(1) - .contains(group); + .contains(groupResponse); } @Test @@ -86,10 +99,11 @@ void getAllGroupsByUser_ShouldThrowUserNotFoundException_WhenUserDoesNotExist() @Test void getGroupById_ShouldReturnGroup_WhenGroupExists() { when(groupRepository.findById(1L)).thenReturn(Optional.of(group)); + when(groupMapper.fromEntityToResponse(group)).thenReturn(groupResponse); var result = groupService.getGroupById(1L); - assertThat(result).isEqualTo(group); + assertThat(result).isEqualTo(groupResponse); } @Test @@ -105,10 +119,12 @@ void getGroupById_ShouldThrowGroupNotFoundException_WhenGroupDoesNotExist() { void addGroupToUser_ShouldAddGroup_WhenUserExists() { when(userRepository.findById(1L)).thenReturn(Optional.of(user)); when(groupRepository.save(any(Group.class))).thenReturn(group); + when(groupMapper.fromEntityToResponse(group)).thenReturn(groupResponse); + when(groupMapper.fromPayloadToEntity(groupPayload, user)).thenReturn(group); var result = groupService.addGroupToUser(1L, groupPayload); - assertThat(result).isEqualTo(group); + assertThat(result).isEqualTo(groupResponse); verify(groupRepository, times(1)).save(any(Group.class)); } @@ -125,17 +141,14 @@ void addGroupToUser_ShouldThrowUserNotFoundException_WhenUserDoesNotExist() { void updateGroup_ShouldUpdateGroup_WhenGroupExists() { when(groupRepository.findById(1L)).thenReturn(Optional.of(group)); when(groupRepository.save(any(Group.class))).thenReturn(group); - - groupPayload = GroupPayload.builder() - .name("NEW Test Group") - .description("NEW Test description") - .build(); + when(groupMapper.fromEntityToResponse(group)).thenReturn(groupResponse); + when(groupMapper.updateEntityFromPayload(group, groupPayload)).thenReturn(group); var result = groupService.updateGroup(1L, groupPayload); assertAll( - () -> assertThat(result.getDescription()).isEqualTo(groupPayload.description()), - () -> assertThat(result.getName()).isEqualTo(group.getName()) + () -> assertThat(result.description()).isEqualTo(groupPayload.description()), + () -> assertThat(result.name()).isEqualTo(group.getName()) ); verify(groupRepository, times(1)).save(any(Group.class)); } diff --git a/src/test/java/com/cf/cfteam/utils/codeforces/GroupMapperTest.java b/src/test/java/com/cf/cfteam/utils/codeforces/GroupMapperTest.java index ba8cbe2..4b4bc12 100644 --- a/src/test/java/com/cf/cfteam/utils/codeforces/GroupMapperTest.java +++ b/src/test/java/com/cf/cfteam/utils/codeforces/GroupMapperTest.java @@ -4,15 +4,27 @@ import com.cf.cfteam.models.entities.security.Role; import com.cf.cfteam.models.entities.security.User; import com.cf.cfteam.transfer.payloads.codeforces.GroupPayload; +import com.cf.cfteam.utils.codeforces.mappers.GroupMapper; +import com.cf.cfteam.utils.codeforces.mappers.TeamMapper; import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InjectMocks; +import org.mockito.Spy; +import org.mockito.junit.jupiter.MockitoExtension; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.ActiveProfiles; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.*; @ActiveProfiles("test") +@ExtendWith(MockitoExtension.class) class GroupMapperTest { + @InjectMocks + private GroupMapper groupMapper; + @Test void shouldMapPayloadToEntity() { GroupPayload payload = GroupPayload.builder() @@ -27,7 +39,7 @@ void shouldMapPayloadToEntity() { .build(); - Group group = GroupMapper.fromPayloadToEntity(payload, user); + Group group = groupMapper.fromPayloadToEntity(payload, user); assertAll( () -> assertThat(group).isNotNull(), @@ -49,7 +61,7 @@ void shouldUpdateEntityFromPayload() { .description("NewDescription") .build(); - Group updatedGroup = GroupMapper.updateEntityFromPayload(group, payload); + Group updatedGroup = groupMapper.updateEntityFromPayload(group, payload); assertAll( () -> assertThat(updatedGroup).isNotNull(), From 0109a2d068e628b6a227943805904026089fad2a Mon Sep 17 00:00:00 2001 From: AlexanderGarifullin Date: Tue, 17 Dec 2024 04:34:22 +0500 Subject: [PATCH 36/60] =?UTF-8?q?dev/codeforces/=20=D0=98=D1=81=D0=BF?= =?UTF-8?q?=D1=80=D0=B0=D0=B2=D0=B8=D0=BB=20=D0=BA=D0=BE=D0=B4=20=D0=BF?= =?UTF-8?q?=D0=BE=D0=B4=20checkStyle?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- config/checkstyle/checkstyle.xml | 24 +++++++++---------- .../java/com/cf/cfteam/config/AppConfig.java | 1 - .../com/cf/cfteam/config/CacheConfig.java | 2 -- .../codeforces/GroupController.java | 6 +++-- .../codeforces/PlayerController.java | 1 - .../models/entities/codeforces/Group.java | 1 - .../models/entities/codeforces/Team.java | 1 - .../services/client/CodeforcesClient.java | 9 +++---- .../services/codeforces/GroupService.java | 3 --- .../utils/codeforces/RatingCalculator.java | 2 +- .../utils/codeforces/mappers/GroupMapper.java | 2 -- .../codeforces/mappers/PlayerMapper.java | 2 -- 12 files changed, 22 insertions(+), 32 deletions(-) diff --git a/config/checkstyle/checkstyle.xml b/config/checkstyle/checkstyle.xml index b690f74..13c7990 100644 --- a/config/checkstyle/checkstyle.xml +++ b/config/checkstyle/checkstyle.xml @@ -56,12 +56,12 @@ - - - - - - + + + + + + @@ -277,12 +277,12 @@ - - - - - + + + + + + diff --git a/src/main/java/com/cf/cfteam/config/AppConfig.java b/src/main/java/com/cf/cfteam/config/AppConfig.java index c9f48a8..4c2d356 100644 --- a/src/main/java/com/cf/cfteam/config/AppConfig.java +++ b/src/main/java/com/cf/cfteam/config/AppConfig.java @@ -1,7 +1,6 @@ package com.cf.cfteam.config; import com.cf.cfteam.services.security.MyUserDetailsService; -import com.cf.cfteam.utils.codeforces.mappers.GroupMapper; import lombok.RequiredArgsConstructor; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; diff --git a/src/main/java/com/cf/cfteam/config/CacheConfig.java b/src/main/java/com/cf/cfteam/config/CacheConfig.java index 2e46488..5cacf6f 100644 --- a/src/main/java/com/cf/cfteam/config/CacheConfig.java +++ b/src/main/java/com/cf/cfteam/config/CacheConfig.java @@ -1,8 +1,6 @@ package com.cf.cfteam.config; import com.cf.cfteam.services.client.CodeforcesClient; -import com.github.benmanes.caffeine.cache.Cache; -import com.github.benmanes.caffeine.cache.CacheLoader; import com.github.benmanes.caffeine.cache.Caffeine; import com.github.benmanes.caffeine.cache.LoadingCache; import lombok.RequiredArgsConstructor; diff --git a/src/main/java/com/cf/cfteam/controllers/codeforces/GroupController.java b/src/main/java/com/cf/cfteam/controllers/codeforces/GroupController.java index df43be2..384a5fd 100644 --- a/src/main/java/com/cf/cfteam/controllers/codeforces/GroupController.java +++ b/src/main/java/com/cf/cfteam/controllers/codeforces/GroupController.java @@ -18,7 +18,8 @@ public class GroupController { private final GroupService groupService; @GetMapping("/user/{userId}") - public ResponseEntity> getAllGroupsByUser(@PathVariable Long userId, Authentication authentication) { + public ResponseEntity> getAllGroupsByUser(@PathVariable Long userId, + Authentication authentication) { List groups = groupService.getAllGroupsByUser(userId); return ResponseEntity.ok(groups); } @@ -30,7 +31,8 @@ public ResponseEntity getGroupById(@PathVariable Long groupId, Au } @PostMapping("/user/{userId}") - public ResponseEntity addGroupToUser(@PathVariable Long userId, @RequestBody GroupPayload groupPayload, + public ResponseEntity addGroupToUser(@PathVariable Long userId, + @RequestBody GroupPayload groupPayload, Authentication authentication) { GroupResponse createdGroup = groupService.addGroupToUser(userId, groupPayload); return ResponseEntity.ok(createdGroup); diff --git a/src/main/java/com/cf/cfteam/controllers/codeforces/PlayerController.java b/src/main/java/com/cf/cfteam/controllers/codeforces/PlayerController.java index eab95e6..929d094 100644 --- a/src/main/java/com/cf/cfteam/controllers/codeforces/PlayerController.java +++ b/src/main/java/com/cf/cfteam/controllers/codeforces/PlayerController.java @@ -1,7 +1,6 @@ package com.cf.cfteam.controllers.codeforces; import com.cf.cfteam.models.entities.codeforces.Player; -import com.cf.cfteam.models.entities.codeforces.Team; import com.cf.cfteam.services.codeforces.PlayerService; import com.cf.cfteam.transfer.payloads.codeforces.GroupPayload; import com.cf.cfteam.transfer.payloads.codeforces.TeamPayload; diff --git a/src/main/java/com/cf/cfteam/models/entities/codeforces/Group.java b/src/main/java/com/cf/cfteam/models/entities/codeforces/Group.java index 86b5ec2..f3d63d4 100644 --- a/src/main/java/com/cf/cfteam/models/entities/codeforces/Group.java +++ b/src/main/java/com/cf/cfteam/models/entities/codeforces/Group.java @@ -1,7 +1,6 @@ package com.cf.cfteam.models.entities.codeforces; import com.cf.cfteam.models.entities.security.User; -import com.fasterxml.jackson.annotation.JsonIgnore; import jakarta.persistence.*; import lombok.*; diff --git a/src/main/java/com/cf/cfteam/models/entities/codeforces/Team.java b/src/main/java/com/cf/cfteam/models/entities/codeforces/Team.java index 3344bbb..3452560 100644 --- a/src/main/java/com/cf/cfteam/models/entities/codeforces/Team.java +++ b/src/main/java/com/cf/cfteam/models/entities/codeforces/Team.java @@ -1,6 +1,5 @@ package com.cf.cfteam.models.entities.codeforces; -import com.fasterxml.jackson.annotation.JsonIgnore; import jakarta.persistence.*; import lombok.*; diff --git a/src/main/java/com/cf/cfteam/services/client/CodeforcesClient.java b/src/main/java/com/cf/cfteam/services/client/CodeforcesClient.java index 72141a7..1ed454f 100644 --- a/src/main/java/com/cf/cfteam/services/client/CodeforcesClient.java +++ b/src/main/java/com/cf/cfteam/services/client/CodeforcesClient.java @@ -28,10 +28,11 @@ public Double fetchRatingFromApi(String login) { .build()) .retrieve() .toEntity(UserInfoResponse.class); - if (playerResponse.getStatusCode().is2xxSuccessful() && playerResponse.getBody() != null && - playerResponse.getBody().getResult().size() == 1 && playerResponse.getBody().getResult().getFirst() != null) { - return playerResponse.getBody().getResult().getFirst().getRating() != null ? - playerResponse.getBody().getResult().getFirst().getRating() : 0.; + if (playerResponse.getStatusCode().is2xxSuccessful() && playerResponse.getBody() != null + && playerResponse.getBody().getResult().size() == 1 + && playerResponse.getBody().getResult().getFirst() != null) { + return playerResponse.getBody().getResult().getFirst().getRating() != null + ? playerResponse.getBody().getResult().getFirst().getRating() : 0.; } if (playerResponse.getStatusCode().is4xxClientError()) { throw new ClientErrorException(playerResponse.getStatusCode().toString()); diff --git a/src/main/java/com/cf/cfteam/services/codeforces/GroupService.java b/src/main/java/com/cf/cfteam/services/codeforces/GroupService.java index 2d004b5..dbe00c8 100644 --- a/src/main/java/com/cf/cfteam/services/codeforces/GroupService.java +++ b/src/main/java/com/cf/cfteam/services/codeforces/GroupService.java @@ -9,13 +9,10 @@ import com.cf.cfteam.repositories.jpa.codeforces.GroupRepository; import com.cf.cfteam.repositories.jpa.security.UserRepository; import com.cf.cfteam.transfer.payloads.codeforces.GroupPayload; -import com.cf.cfteam.utils.codeforces.mappers.TeamMapper; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; -import javax.swing.text.html.Option; import java.util.List; -import java.util.Optional; @Service @RequiredArgsConstructor diff --git a/src/main/java/com/cf/cfteam/utils/codeforces/RatingCalculator.java b/src/main/java/com/cf/cfteam/utils/codeforces/RatingCalculator.java index 52fc605..a013272 100644 --- a/src/main/java/com/cf/cfteam/utils/codeforces/RatingCalculator.java +++ b/src/main/java/com/cf/cfteam/utils/codeforces/RatingCalculator.java @@ -4,7 +4,7 @@ import java.util.List; -public class RatingCalculator { +public final class RatingCalculator { public static double getWinProbability(double ra, double rb) { return 1.0 / (1.0 + Math.pow(10.0, (rb - ra) / 400.0)); diff --git a/src/main/java/com/cf/cfteam/utils/codeforces/mappers/GroupMapper.java b/src/main/java/com/cf/cfteam/utils/codeforces/mappers/GroupMapper.java index 7de6312..fa523a9 100644 --- a/src/main/java/com/cf/cfteam/utils/codeforces/mappers/GroupMapper.java +++ b/src/main/java/com/cf/cfteam/utils/codeforces/mappers/GroupMapper.java @@ -4,9 +4,7 @@ import com.cf.cfteam.models.entities.security.User; import com.cf.cfteam.transfer.payloads.codeforces.GroupPayload; import com.cf.cfteam.transfer.responses.codeforces.GroupResponse; -import com.cf.cfteam.transfer.responses.codeforces.PlayerResponse; import com.cf.cfteam.transfer.responses.codeforces.TeamResponse; -import lombok.NoArgsConstructor; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Component; diff --git a/src/main/java/com/cf/cfteam/utils/codeforces/mappers/PlayerMapper.java b/src/main/java/com/cf/cfteam/utils/codeforces/mappers/PlayerMapper.java index d5eda65..046ae92 100644 --- a/src/main/java/com/cf/cfteam/utils/codeforces/mappers/PlayerMapper.java +++ b/src/main/java/com/cf/cfteam/utils/codeforces/mappers/PlayerMapper.java @@ -2,10 +2,8 @@ import com.cf.cfteam.models.entities.codeforces.Player; import com.cf.cfteam.transfer.responses.codeforces.PlayerResponse; -import com.github.benmanes.caffeine.cache.Cache; import com.github.benmanes.caffeine.cache.LoadingCache; import lombok.RequiredArgsConstructor; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @Component From 1ab0f1a55f244f555480e46f546fd07c1a515b8f Mon Sep 17 00:00:00 2001 From: AlexanderGarifullin Date: Tue, 17 Dec 2024 04:52:04 +0500 Subject: [PATCH 37/60] =?UTF-8?q?dev/codeforces/=20=D0=94=D0=BE=D0=B1?= =?UTF-8?q?=D0=B0=D0=B2=D0=B8=D0=BB=20=D0=BB=D0=BE=D0=B3=D0=B8=D0=BA=D1=83?= =?UTF-8?q?=20=D0=B4=D0=BB=D1=8F=20Team?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../codeforces/TeamController.java | 22 ++++---- .../codeforces/TeamNotFoundException.java | 14 +++++ .../jpa/codeforces/TeamRepository.java | 5 ++ .../services/codeforces/TeamService.java | 53 ++++++++++++++++--- .../payloads/codeforces/PlayerPayload.java | 2 +- .../payloads/codeforces/TeamPayload.java | 5 +- .../utils/codeforces/mappers/TeamMapper.java | 18 +++++++ 7 files changed, 98 insertions(+), 21 deletions(-) create mode 100644 src/main/java/com/cf/cfteam/exceptions/codeforces/TeamNotFoundException.java diff --git a/src/main/java/com/cf/cfteam/controllers/codeforces/TeamController.java b/src/main/java/com/cf/cfteam/controllers/codeforces/TeamController.java index 57dd2b0..302aa63 100644 --- a/src/main/java/com/cf/cfteam/controllers/codeforces/TeamController.java +++ b/src/main/java/com/cf/cfteam/controllers/codeforces/TeamController.java @@ -1,9 +1,9 @@ package com.cf.cfteam.controllers.codeforces; -import com.cf.cfteam.models.entities.codeforces.Team; import com.cf.cfteam.services.codeforces.TeamService; import com.cf.cfteam.transfer.payloads.codeforces.GroupPayload; import com.cf.cfteam.transfer.payloads.codeforces.TeamPayload; +import com.cf.cfteam.transfer.responses.codeforces.TeamResponse; import lombok.RequiredArgsConstructor; import org.springframework.http.ResponseEntity; import org.springframework.security.core.Authentication; @@ -15,32 +15,32 @@ @RequiredArgsConstructor @RequestMapping("api/cf/teams") public class TeamController { - + private final TeamService teamService; - + @GetMapping("/group/{groupId}") - public ResponseEntity> getAllTeamsByGroup(@PathVariable Long groupId, Authentication authentication) { - List teams = teamService.getAllTeamsByGroup(groupId); + public ResponseEntity> getAllTeamsByGroup(@PathVariable Long groupId, Authentication authentication) { + List teams = teamService.getAllTeamsByGroup(groupId); return ResponseEntity.ok(teams); } @GetMapping("/{teamId}") - public ResponseEntity getTeamById(@PathVariable Long teamId, Authentication authentication) { - Team team = teamService.getTeamById(teamId); + public ResponseEntity getTeamById(@PathVariable Long teamId, Authentication authentication) { + TeamResponse team = teamService.getTeamById(teamId); return ResponseEntity.ok(team); } @PostMapping("/group/{groupId}") - public ResponseEntity addTeamToGroup(@PathVariable Long groupId, @RequestBody TeamPayload teamPayload, + public ResponseEntity addTeamToGroup(@PathVariable Long groupId, @RequestBody TeamPayload teamPayload, Authentication authentication) { - Team createdTeam = teamService.addTeamToGroup(groupId, teamPayload); + TeamResponse createdTeam = teamService.addTeamToGroup(groupId, teamPayload); return ResponseEntity.ok(createdTeam); } @PutMapping("/{teamId}") - public ResponseEntity updateTeam(@PathVariable Long teamId, @RequestBody GroupPayload groupPayload, + public ResponseEntity updateTeam(@PathVariable Long teamId, @RequestBody TeamPayload teamPayload, Authentication authentication) { - Team team = teamService.updateTeam(teamId, groupPayload); + TeamResponse team = teamService.updateTeam(teamId, teamPayload); return ResponseEntity.ok(team); } diff --git a/src/main/java/com/cf/cfteam/exceptions/codeforces/TeamNotFoundException.java b/src/main/java/com/cf/cfteam/exceptions/codeforces/TeamNotFoundException.java new file mode 100644 index 0000000..4a01084 --- /dev/null +++ b/src/main/java/com/cf/cfteam/exceptions/codeforces/TeamNotFoundException.java @@ -0,0 +1,14 @@ +package com.cf.cfteam.exceptions.codeforces; + +import lombok.Getter; + +@Getter +public class TeamNotFoundException extends RuntimeException { + + private final Long id; + + public TeamNotFoundException(Long id) { + super("id.not_found"); + this.id = id; + } +} diff --git a/src/main/java/com/cf/cfteam/repositories/jpa/codeforces/TeamRepository.java b/src/main/java/com/cf/cfteam/repositories/jpa/codeforces/TeamRepository.java index b194985..fa32df3 100644 --- a/src/main/java/com/cf/cfteam/repositories/jpa/codeforces/TeamRepository.java +++ b/src/main/java/com/cf/cfteam/repositories/jpa/codeforces/TeamRepository.java @@ -1,7 +1,12 @@ package com.cf.cfteam.repositories.jpa.codeforces; +import com.cf.cfteam.models.entities.codeforces.Group; import com.cf.cfteam.models.entities.codeforces.Team; +import com.cf.cfteam.models.entities.security.User; import org.springframework.data.jpa.repository.JpaRepository; +import java.util.List; + public interface TeamRepository extends JpaRepository { + List findByGroup(Group group); } diff --git a/src/main/java/com/cf/cfteam/services/codeforces/TeamService.java b/src/main/java/com/cf/cfteam/services/codeforces/TeamService.java index ef78ea0..c5e8037 100644 --- a/src/main/java/com/cf/cfteam/services/codeforces/TeamService.java +++ b/src/main/java/com/cf/cfteam/services/codeforces/TeamService.java @@ -1,9 +1,17 @@ package com.cf.cfteam.services.codeforces; +import com.cf.cfteam.exceptions.codeforces.GroupNotFoundException; +import com.cf.cfteam.exceptions.codeforces.TeamNotFoundException; +import com.cf.cfteam.exceptions.security.UserNotFoundException; +import com.cf.cfteam.models.entities.codeforces.Group; import com.cf.cfteam.models.entities.codeforces.Team; +import com.cf.cfteam.models.entities.security.User; +import com.cf.cfteam.repositories.jpa.codeforces.GroupRepository; import com.cf.cfteam.repositories.jpa.codeforces.TeamRepository; import com.cf.cfteam.transfer.payloads.codeforces.GroupPayload; import com.cf.cfteam.transfer.payloads.codeforces.TeamPayload; +import com.cf.cfteam.transfer.responses.codeforces.TeamResponse; +import com.cf.cfteam.utils.codeforces.mappers.TeamMapper; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; @@ -14,26 +22,55 @@ public class TeamService { private final TeamRepository teamRepository; + private final GroupRepository groupRepository; + private final TeamMapper teamMapper; - public List getAllTeamsByGroup(Long groupId) { - return null; + public List getAllTeamsByGroup(Long groupId) { + Group group = groupRepository.findById(groupId) + .orElseThrow(() -> new GroupNotFoundException(groupId)); + + List teams = teamRepository.findByGroup(group); + + return teams.stream() + .map(teamMapper::fromEntityToResponse) + .toList(); } - public Team getTeamById(Long teamId) { - return teamRepository.findById(teamId).get(); + public TeamResponse getTeamById(Long teamId) { + Team team = teamRepository.findById(teamId) + .orElseThrow(() -> new TeamNotFoundException(teamId)); + + return teamMapper.fromEntityToResponse(team); } - public Team addTeamToGroup(Long groupId, TeamPayload teamPayload) { - return null; + public TeamResponse addTeamToGroup(Long groupId, TeamPayload teamPayload) { + Group group = groupRepository.findById(groupId) + .orElseThrow(() -> new GroupNotFoundException(groupId)); + + Team team = teamMapper.fromPayloadToEntity(teamPayload, group); + team = teamRepository.save(team); + + return teamMapper.fromEntityToResponse(team); } - public Team updateTeam(Long teamId, GroupPayload groupPayload) { - return null; + public TeamResponse updateTeam(Long teamId, TeamPayload teamPayload) { + Team team = teamRepository.findById(teamId) + .orElseThrow(() -> new TeamNotFoundException(teamId)); + + Team updatedTeam= teamMapper.updateEntityFromPayload(team, teamPayload); + updatedTeam = teamRepository.save(updatedTeam); + + return teamMapper.fromEntityToResponse(updatedTeam); } public void deleteTeam(Long teamId) { + teamRepository.deleteById(teamId); } public void deleteAllTeamsByGroup(Long groupId) { + Group group = groupRepository.findById(groupId) + .orElseThrow(() -> new GroupNotFoundException(groupId)); + List teams = teamRepository.findByGroup(group); + teamRepository.deleteAll(teams); } } diff --git a/src/main/java/com/cf/cfteam/transfer/payloads/codeforces/PlayerPayload.java b/src/main/java/com/cf/cfteam/transfer/payloads/codeforces/PlayerPayload.java index aec7e33..deeea71 100644 --- a/src/main/java/com/cf/cfteam/transfer/payloads/codeforces/PlayerPayload.java +++ b/src/main/java/com/cf/cfteam/transfer/payloads/codeforces/PlayerPayload.java @@ -3,5 +3,5 @@ import lombok.Builder; @Builder -public class PlayerPayload { +public record PlayerPayload() { } diff --git a/src/main/java/com/cf/cfteam/transfer/payloads/codeforces/TeamPayload.java b/src/main/java/com/cf/cfteam/transfer/payloads/codeforces/TeamPayload.java index db11fe6..3b6d0ed 100644 --- a/src/main/java/com/cf/cfteam/transfer/payloads/codeforces/TeamPayload.java +++ b/src/main/java/com/cf/cfteam/transfer/payloads/codeforces/TeamPayload.java @@ -3,5 +3,8 @@ import lombok.Builder; @Builder -public class TeamPayload { +public record TeamPayload( + String name, + String description +) { } diff --git a/src/main/java/com/cf/cfteam/utils/codeforces/mappers/TeamMapper.java b/src/main/java/com/cf/cfteam/utils/codeforces/mappers/TeamMapper.java index d6c79e0..c64b2d2 100644 --- a/src/main/java/com/cf/cfteam/utils/codeforces/mappers/TeamMapper.java +++ b/src/main/java/com/cf/cfteam/utils/codeforces/mappers/TeamMapper.java @@ -1,6 +1,10 @@ package com.cf.cfteam.utils.codeforces.mappers; +import com.cf.cfteam.models.entities.codeforces.Group; import com.cf.cfteam.models.entities.codeforces.Team; +import com.cf.cfteam.models.entities.security.User; +import com.cf.cfteam.transfer.payloads.codeforces.GroupPayload; +import com.cf.cfteam.transfer.payloads.codeforces.TeamPayload; import com.cf.cfteam.transfer.responses.codeforces.PlayerResponse; import com.cf.cfteam.transfer.responses.codeforces.TeamResponse; import com.cf.cfteam.utils.codeforces.RatingCalculator; @@ -36,4 +40,18 @@ public TeamResponse fromEntityToResponse(Team team) { .teamRating(teamRating) .build(); } + + public Team fromPayloadToEntity(TeamPayload payload, Group group) { + return Team.builder() + .group(group) + .name(payload.name()) + .description(payload.description()) + .build(); + } + + public Team updateEntityFromPayload(Team team, TeamPayload payload) { + team.setName(payload.name()); + team.setDescription(payload.description()); + return team; + } } From e1256551b9ef0494a54fccd04d10bca9e0e1a902 Mon Sep 17 00:00:00 2001 From: AlexanderGarifullin Date: Tue, 17 Dec 2024 05:20:21 +0500 Subject: [PATCH 38/60] =?UTF-8?q?dev/codeforces/=20=D0=94=D0=BE=D0=B1?= =?UTF-8?q?=D0=B0=D0=B2=D0=B8=D0=BB=20=D0=BB=D0=BE=D0=B3=D0=B8=D0=BA=D1=83?= =?UTF-8?q?=20=D0=B4=D0=BB=D1=8F=20Players?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../codeforces/PlayerController.java | 24 +++-- .../codeforces/PlayerNotFoundException.java | 14 +++ .../PlayerNotFromTeamException.java | 15 +++ .../jpa/codeforces/PlayerRepository.java | 3 + .../services/codeforces/PlayerService.java | 99 +++++++++++++++++-- .../payloads/codeforces/PlayerPayload.java | 4 +- .../codeforces/mappers/PlayerMapper.java | 15 +++ 7 files changed, 153 insertions(+), 21 deletions(-) create mode 100644 src/main/java/com/cf/cfteam/exceptions/codeforces/PlayerNotFoundException.java create mode 100644 src/main/java/com/cf/cfteam/exceptions/codeforces/PlayerNotFromTeamException.java diff --git a/src/main/java/com/cf/cfteam/controllers/codeforces/PlayerController.java b/src/main/java/com/cf/cfteam/controllers/codeforces/PlayerController.java index 929d094..115bb08 100644 --- a/src/main/java/com/cf/cfteam/controllers/codeforces/PlayerController.java +++ b/src/main/java/com/cf/cfteam/controllers/codeforces/PlayerController.java @@ -3,7 +3,9 @@ import com.cf.cfteam.models.entities.codeforces.Player; import com.cf.cfteam.services.codeforces.PlayerService; import com.cf.cfteam.transfer.payloads.codeforces.GroupPayload; +import com.cf.cfteam.transfer.payloads.codeforces.PlayerPayload; import com.cf.cfteam.transfer.payloads.codeforces.TeamPayload; +import com.cf.cfteam.transfer.responses.codeforces.PlayerResponse; import lombok.RequiredArgsConstructor; import org.springframework.http.ResponseEntity; import org.springframework.security.core.Authentication; @@ -19,30 +21,32 @@ public class PlayerController { private final PlayerService playerService; @GetMapping("/team/{teamId}") - public ResponseEntity> getAllPlayersByTeam(@PathVariable Long teamId, Authentication authentication) { - List players = playerService.getAllPlayersByTeam(teamId); + public ResponseEntity> getAllPlayersByTeam(@PathVariable Long teamId, + Authentication authentication) { + List players = playerService.getAllPlayersByTeam(teamId); return ResponseEntity.ok(players); } @GetMapping("/{playerId}") - public ResponseEntity getPlayerById(@PathVariable Long playerId, Authentication authentication) { - Player player = playerService.getPlayerById(playerId); + public ResponseEntity getPlayerById(@PathVariable Long playerId, Authentication authentication) { + PlayerResponse player = playerService.getPlayerById(playerId); return ResponseEntity.ok(player); } @PostMapping("/team/{teamId}") - public ResponseEntity addPlayerToTeam(@PathVariable Long teamId, @RequestBody TeamPayload teamPayload, - Authentication authentication) { - Player player = playerService.addPlayerToTeam(teamId, teamPayload); + public ResponseEntity addPlayerToTeam(@PathVariable Long teamId, + @RequestBody PlayerPayload playerPayload, + Authentication authentication) { + PlayerResponse player = playerService.addPlayerToTeam(teamId, playerPayload); return ResponseEntity.ok(player); } @PutMapping("/players/{playerId}/teams/{teamId}") - public ResponseEntity updatePlayerInTeam(@PathVariable Long playerId, + public ResponseEntity updatePlayerInTeam(@PathVariable Long playerId, @PathVariable Long teamId, - @RequestBody GroupPayload groupPayload, + @RequestBody PlayerPayload playerPayload, Authentication authentication) { - Player player = playerService.updatePlayer(playerId, teamId, groupPayload); + PlayerResponse player = playerService.updatePlayerInTeam(playerId, teamId, playerPayload); return ResponseEntity.ok(player); } diff --git a/src/main/java/com/cf/cfteam/exceptions/codeforces/PlayerNotFoundException.java b/src/main/java/com/cf/cfteam/exceptions/codeforces/PlayerNotFoundException.java new file mode 100644 index 0000000..f19e269 --- /dev/null +++ b/src/main/java/com/cf/cfteam/exceptions/codeforces/PlayerNotFoundException.java @@ -0,0 +1,14 @@ +package com.cf.cfteam.exceptions.codeforces; + +import lombok.Getter; + +@Getter +public class PlayerNotFoundException extends RuntimeException { + + private final Long id; + + public PlayerNotFoundException(Long id) { + super("id.not_found"); + this.id = id; + } +} \ No newline at end of file diff --git a/src/main/java/com/cf/cfteam/exceptions/codeforces/PlayerNotFromTeamException.java b/src/main/java/com/cf/cfteam/exceptions/codeforces/PlayerNotFromTeamException.java new file mode 100644 index 0000000..a7b85f1 --- /dev/null +++ b/src/main/java/com/cf/cfteam/exceptions/codeforces/PlayerNotFromTeamException.java @@ -0,0 +1,15 @@ +package com.cf.cfteam.exceptions.codeforces; + +import lombok.Getter; + +@Getter +public class PlayerNotFromTeamException extends RuntimeException { + + private final Long teamId, playerId; + + public PlayerNotFromTeamException(Long teamId, Long playerId) { + super("player.not_from_team"); + this.playerId = playerId; + this.teamId = teamId; + } +} \ No newline at end of file diff --git a/src/main/java/com/cf/cfteam/repositories/jpa/codeforces/PlayerRepository.java b/src/main/java/com/cf/cfteam/repositories/jpa/codeforces/PlayerRepository.java index eec3610..6798af5 100644 --- a/src/main/java/com/cf/cfteam/repositories/jpa/codeforces/PlayerRepository.java +++ b/src/main/java/com/cf/cfteam/repositories/jpa/codeforces/PlayerRepository.java @@ -3,5 +3,8 @@ import com.cf.cfteam.models.entities.codeforces.Player; import org.springframework.data.jpa.repository.JpaRepository; +import java.util.Optional; + public interface PlayerRepository extends JpaRepository { + Optional findByLogin(String login); } diff --git a/src/main/java/com/cf/cfteam/services/codeforces/PlayerService.java b/src/main/java/com/cf/cfteam/services/codeforces/PlayerService.java index 0e134f8..929f696 100644 --- a/src/main/java/com/cf/cfteam/services/codeforces/PlayerService.java +++ b/src/main/java/com/cf/cfteam/services/codeforces/PlayerService.java @@ -1,9 +1,15 @@ package com.cf.cfteam.services.codeforces; +import com.cf.cfteam.exceptions.codeforces.PlayerNotFoundException; +import com.cf.cfteam.exceptions.codeforces.PlayerNotFromTeamException; +import com.cf.cfteam.exceptions.codeforces.TeamNotFoundException; import com.cf.cfteam.models.entities.codeforces.Player; +import com.cf.cfteam.models.entities.codeforces.Team; import com.cf.cfteam.repositories.jpa.codeforces.PlayerRepository; -import com.cf.cfteam.transfer.payloads.codeforces.GroupPayload; -import com.cf.cfteam.transfer.payloads.codeforces.TeamPayload; +import com.cf.cfteam.repositories.jpa.codeforces.TeamRepository; +import com.cf.cfteam.transfer.payloads.codeforces.PlayerPayload; +import com.cf.cfteam.transfer.responses.codeforces.PlayerResponse; +import com.cf.cfteam.utils.codeforces.mappers.PlayerMapper; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; @@ -14,29 +20,102 @@ public class PlayerService { private final PlayerRepository playerRepository; + private final TeamRepository teamRepository; + private final PlayerMapper playerMapper; - public List getAllPlayersByTeam(Long teamId) { - return null; + public List getAllPlayersByTeam(Long teamId) { + var team = teamRepository.findById(teamId) + .orElseThrow(() -> new TeamNotFoundException(teamId)); + + return team.getPlayers().stream() + .map(playerMapper::fromEntityToResponse) + .toList(); + } + + public PlayerResponse getPlayerById(Long playerId) { + var player = playerRepository.findById(playerId) + .orElseThrow(() -> new PlayerNotFoundException(playerId)); + + return playerMapper.fromEntityToResponse(player); } - public Player getPlayerById(Long playerId) { - return null; + public PlayerResponse addPlayerToTeam(Long teamId, PlayerPayload payload) { + var team = teamRepository.findById(teamId) + .orElseThrow(() -> new TeamNotFoundException(teamId)); + + var player = createPlayer(payload); + + linkTeamAndPlayer(team, player); + + return playerMapper.fromEntityToResponse(player); } - public Player addPlayerToTeam(Long teamId, TeamPayload teamPayload) { - return null; + + public PlayerResponse updatePlayerInTeam(Long playerId, Long teamId, PlayerPayload payload) { + var player = playerRepository.findById(playerId) + .orElseThrow(() -> new PlayerNotFoundException(playerId)); + + var team = teamRepository.findById(teamId) + .orElseThrow(() -> new TeamNotFoundException(teamId)); + + if (!team.getPlayers().contains(player)) { + throw new PlayerNotFromTeamException(teamId, playerId); + } + + unlinkTeamAndPlayer(team, player);; + player = createPlayer(payload); + linkTeamAndPlayer(team, player); + + return playerMapper.fromEntityToResponse(player); } + private Player createPlayer(PlayerPayload payload) { + var exist = playerRepository.findByLogin(payload.login()); + if (exist.isPresent()) return exist.get(); - public Player updatePlayer(Long playerId, Long teamId, GroupPayload groupPayload) { - return null; + Player player = playerMapper.fromPayloadToEntity(payload); + return playerRepository.save(player); } public void deletePlayerFromTeam(Long playerId, Long teamId) { + var player = playerRepository.findById(playerId) + .orElseThrow(() -> new PlayerNotFoundException(playerId)); + + var team = teamRepository.findById(teamId) + .orElseThrow(() -> new TeamNotFoundException(teamId)); + + unlinkTeamAndPlayer(team, player); } public void deleteAllPlayersFromTeam(Long teamId) { + var team = teamRepository.findById(teamId) + .orElseThrow(() -> new TeamNotFoundException(teamId)); + + var players = team.getPlayers(); + + players.forEach(player -> player.getTeams().remove(team)); + team.getPlayers().clear(); + + teamRepository.save(team); + players.forEach(playerRepository::save); + } + + private void unlinkTeamAndPlayer(Team team, Player player) { + team.getPlayers().remove(player); + player.getTeams().remove(team); + saveTeamAndPlayer(team, player); + } + + private void linkTeamAndPlayer(Team team, Player player) { + team.getPlayers().add(player); + player.getTeams().add(team); + saveTeamAndPlayer(team, player); + } + + private void saveTeamAndPlayer(Team team, Player player) { + teamRepository.save(team); + playerRepository.save(player); } } diff --git a/src/main/java/com/cf/cfteam/transfer/payloads/codeforces/PlayerPayload.java b/src/main/java/com/cf/cfteam/transfer/payloads/codeforces/PlayerPayload.java index deeea71..ea2dff7 100644 --- a/src/main/java/com/cf/cfteam/transfer/payloads/codeforces/PlayerPayload.java +++ b/src/main/java/com/cf/cfteam/transfer/payloads/codeforces/PlayerPayload.java @@ -3,5 +3,7 @@ import lombok.Builder; @Builder -public record PlayerPayload() { +public record PlayerPayload( + String login +) { } diff --git a/src/main/java/com/cf/cfteam/utils/codeforces/mappers/PlayerMapper.java b/src/main/java/com/cf/cfteam/utils/codeforces/mappers/PlayerMapper.java index 046ae92..300e22d 100644 --- a/src/main/java/com/cf/cfteam/utils/codeforces/mappers/PlayerMapper.java +++ b/src/main/java/com/cf/cfteam/utils/codeforces/mappers/PlayerMapper.java @@ -1,11 +1,20 @@ package com.cf.cfteam.utils.codeforces.mappers; +import com.cf.cfteam.models.entities.codeforces.Group; import com.cf.cfteam.models.entities.codeforces.Player; +import com.cf.cfteam.models.entities.codeforces.Team; +import com.cf.cfteam.transfer.payloads.codeforces.PlayerPayload; +import com.cf.cfteam.transfer.payloads.codeforces.TeamPayload; import com.cf.cfteam.transfer.responses.codeforces.PlayerResponse; +import com.cf.cfteam.transfer.responses.codeforces.TeamResponse; +import com.cf.cfteam.utils.codeforces.RatingCalculator; import com.github.benmanes.caffeine.cache.LoadingCache; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Component; +import java.util.ArrayList; +import java.util.List; + @Component @RequiredArgsConstructor public class PlayerMapper { @@ -19,4 +28,10 @@ public PlayerResponse fromEntityToResponse(Player player) { .rating(ratingCache.get(player.getLogin())) .build(); } + + public Player fromPayloadToEntity(PlayerPayload payload) { + return Player.builder() + .login(payload.login()) + .build(); + } } From 4ed422402644e2eeac637544c9a825e7d65a88ec Mon Sep 17 00:00:00 2001 From: AlexanderGarifullin Date: Tue, 17 Dec 2024 05:23:39 +0500 Subject: [PATCH 39/60] =?UTF-8?q?dev/codeforces/=20=D0=9E=D1=82=D1=80?= =?UTF-8?q?=D0=B5=D1=84=D0=B0=D0=BA=D1=82=D0=BE=D1=80=D0=B8=D0=BB=20=D0=BA?= =?UTF-8?q?=D0=BE=D0=B4=20=D0=BF=D0=BE=D0=B4=20checkStyle?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../cfteam/controllers/codeforces/PlayerController.java | 3 --- .../cf/cfteam/controllers/codeforces/TeamController.java | 4 ++-- .../exceptions/codeforces/PlayerNotFromTeamException.java | 3 ++- .../repositories/jpa/codeforces/TeamRepository.java | 1 - .../com/cf/cfteam/services/codeforces/PlayerService.java | 2 +- .../com/cf/cfteam/services/codeforces/TeamService.java | 5 +---- .../cf/cfteam/utils/codeforces/mappers/PlayerMapper.java | 8 -------- .../cf/cfteam/utils/codeforces/mappers/TeamMapper.java | 2 -- 8 files changed, 6 insertions(+), 22 deletions(-) diff --git a/src/main/java/com/cf/cfteam/controllers/codeforces/PlayerController.java b/src/main/java/com/cf/cfteam/controllers/codeforces/PlayerController.java index 115bb08..e0ec4d5 100644 --- a/src/main/java/com/cf/cfteam/controllers/codeforces/PlayerController.java +++ b/src/main/java/com/cf/cfteam/controllers/codeforces/PlayerController.java @@ -1,10 +1,7 @@ package com.cf.cfteam.controllers.codeforces; -import com.cf.cfteam.models.entities.codeforces.Player; import com.cf.cfteam.services.codeforces.PlayerService; -import com.cf.cfteam.transfer.payloads.codeforces.GroupPayload; import com.cf.cfteam.transfer.payloads.codeforces.PlayerPayload; -import com.cf.cfteam.transfer.payloads.codeforces.TeamPayload; import com.cf.cfteam.transfer.responses.codeforces.PlayerResponse; import lombok.RequiredArgsConstructor; import org.springframework.http.ResponseEntity; diff --git a/src/main/java/com/cf/cfteam/controllers/codeforces/TeamController.java b/src/main/java/com/cf/cfteam/controllers/codeforces/TeamController.java index 302aa63..4e2f2e5 100644 --- a/src/main/java/com/cf/cfteam/controllers/codeforces/TeamController.java +++ b/src/main/java/com/cf/cfteam/controllers/codeforces/TeamController.java @@ -1,7 +1,6 @@ package com.cf.cfteam.controllers.codeforces; import com.cf.cfteam.services.codeforces.TeamService; -import com.cf.cfteam.transfer.payloads.codeforces.GroupPayload; import com.cf.cfteam.transfer.payloads.codeforces.TeamPayload; import com.cf.cfteam.transfer.responses.codeforces.TeamResponse; import lombok.RequiredArgsConstructor; @@ -19,7 +18,8 @@ public class TeamController { private final TeamService teamService; @GetMapping("/group/{groupId}") - public ResponseEntity> getAllTeamsByGroup(@PathVariable Long groupId, Authentication authentication) { + public ResponseEntity> getAllTeamsByGroup(@PathVariable Long groupId, + Authentication authentication) { List teams = teamService.getAllTeamsByGroup(groupId); return ResponseEntity.ok(teams); } diff --git a/src/main/java/com/cf/cfteam/exceptions/codeforces/PlayerNotFromTeamException.java b/src/main/java/com/cf/cfteam/exceptions/codeforces/PlayerNotFromTeamException.java index a7b85f1..6aadeef 100644 --- a/src/main/java/com/cf/cfteam/exceptions/codeforces/PlayerNotFromTeamException.java +++ b/src/main/java/com/cf/cfteam/exceptions/codeforces/PlayerNotFromTeamException.java @@ -5,7 +5,8 @@ @Getter public class PlayerNotFromTeamException extends RuntimeException { - private final Long teamId, playerId; + private final Long teamId; + private final Long playerId; public PlayerNotFromTeamException(Long teamId, Long playerId) { super("player.not_from_team"); diff --git a/src/main/java/com/cf/cfteam/repositories/jpa/codeforces/TeamRepository.java b/src/main/java/com/cf/cfteam/repositories/jpa/codeforces/TeamRepository.java index fa32df3..20e5108 100644 --- a/src/main/java/com/cf/cfteam/repositories/jpa/codeforces/TeamRepository.java +++ b/src/main/java/com/cf/cfteam/repositories/jpa/codeforces/TeamRepository.java @@ -2,7 +2,6 @@ import com.cf.cfteam.models.entities.codeforces.Group; import com.cf.cfteam.models.entities.codeforces.Team; -import com.cf.cfteam.models.entities.security.User; import org.springframework.data.jpa.repository.JpaRepository; import java.util.List; diff --git a/src/main/java/com/cf/cfteam/services/codeforces/PlayerService.java b/src/main/java/com/cf/cfteam/services/codeforces/PlayerService.java index 929f696..9d3a533 100644 --- a/src/main/java/com/cf/cfteam/services/codeforces/PlayerService.java +++ b/src/main/java/com/cf/cfteam/services/codeforces/PlayerService.java @@ -62,7 +62,7 @@ public PlayerResponse updatePlayerInTeam(Long playerId, Long teamId, PlayerPaylo throw new PlayerNotFromTeamException(teamId, playerId); } - unlinkTeamAndPlayer(team, player);; + unlinkTeamAndPlayer(team, player); player = createPlayer(payload); linkTeamAndPlayer(team, player); diff --git a/src/main/java/com/cf/cfteam/services/codeforces/TeamService.java b/src/main/java/com/cf/cfteam/services/codeforces/TeamService.java index c5e8037..b184b06 100644 --- a/src/main/java/com/cf/cfteam/services/codeforces/TeamService.java +++ b/src/main/java/com/cf/cfteam/services/codeforces/TeamService.java @@ -2,13 +2,10 @@ import com.cf.cfteam.exceptions.codeforces.GroupNotFoundException; import com.cf.cfteam.exceptions.codeforces.TeamNotFoundException; -import com.cf.cfteam.exceptions.security.UserNotFoundException; import com.cf.cfteam.models.entities.codeforces.Group; import com.cf.cfteam.models.entities.codeforces.Team; -import com.cf.cfteam.models.entities.security.User; import com.cf.cfteam.repositories.jpa.codeforces.GroupRepository; import com.cf.cfteam.repositories.jpa.codeforces.TeamRepository; -import com.cf.cfteam.transfer.payloads.codeforces.GroupPayload; import com.cf.cfteam.transfer.payloads.codeforces.TeamPayload; import com.cf.cfteam.transfer.responses.codeforces.TeamResponse; import com.cf.cfteam.utils.codeforces.mappers.TeamMapper; @@ -57,7 +54,7 @@ public TeamResponse updateTeam(Long teamId, TeamPayload teamPayload) { Team team = teamRepository.findById(teamId) .orElseThrow(() -> new TeamNotFoundException(teamId)); - Team updatedTeam= teamMapper.updateEntityFromPayload(team, teamPayload); + Team updatedTeam = teamMapper.updateEntityFromPayload(team, teamPayload); updatedTeam = teamRepository.save(updatedTeam); return teamMapper.fromEntityToResponse(updatedTeam); diff --git a/src/main/java/com/cf/cfteam/utils/codeforces/mappers/PlayerMapper.java b/src/main/java/com/cf/cfteam/utils/codeforces/mappers/PlayerMapper.java index 300e22d..9f61398 100644 --- a/src/main/java/com/cf/cfteam/utils/codeforces/mappers/PlayerMapper.java +++ b/src/main/java/com/cf/cfteam/utils/codeforces/mappers/PlayerMapper.java @@ -1,20 +1,12 @@ package com.cf.cfteam.utils.codeforces.mappers; -import com.cf.cfteam.models.entities.codeforces.Group; import com.cf.cfteam.models.entities.codeforces.Player; -import com.cf.cfteam.models.entities.codeforces.Team; import com.cf.cfteam.transfer.payloads.codeforces.PlayerPayload; -import com.cf.cfteam.transfer.payloads.codeforces.TeamPayload; import com.cf.cfteam.transfer.responses.codeforces.PlayerResponse; -import com.cf.cfteam.transfer.responses.codeforces.TeamResponse; -import com.cf.cfteam.utils.codeforces.RatingCalculator; import com.github.benmanes.caffeine.cache.LoadingCache; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Component; -import java.util.ArrayList; -import java.util.List; - @Component @RequiredArgsConstructor public class PlayerMapper { diff --git a/src/main/java/com/cf/cfteam/utils/codeforces/mappers/TeamMapper.java b/src/main/java/com/cf/cfteam/utils/codeforces/mappers/TeamMapper.java index c64b2d2..a63fba5 100644 --- a/src/main/java/com/cf/cfteam/utils/codeforces/mappers/TeamMapper.java +++ b/src/main/java/com/cf/cfteam/utils/codeforces/mappers/TeamMapper.java @@ -2,8 +2,6 @@ import com.cf.cfteam.models.entities.codeforces.Group; import com.cf.cfteam.models.entities.codeforces.Team; -import com.cf.cfteam.models.entities.security.User; -import com.cf.cfteam.transfer.payloads.codeforces.GroupPayload; import com.cf.cfteam.transfer.payloads.codeforces.TeamPayload; import com.cf.cfteam.transfer.responses.codeforces.PlayerResponse; import com.cf.cfteam.transfer.responses.codeforces.TeamResponse; From 71c3299eff35e0c3c111703a0e7036b2b9cf957c Mon Sep 17 00:00:00 2001 From: AlexanderGarifullin Date: Tue, 17 Dec 2024 10:52:14 +0500 Subject: [PATCH 40/60] =?UTF-8?q?dev/codeforces/=20=D0=94=D0=BE=D0=B1?= =?UTF-8?q?=D0=B0=D0=B2=D0=B8=D0=BB=20=D1=82=D0=B5=D1=81=D1=82=D1=8B=20?= =?UTF-8?q?=D0=B4=D0=BB=D1=8F=20TeamMapper?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../utils/codeforces/mappers/TeamMapper.java | 2 +- .../{ => mappers}/GroupMapperTest.java | 7 +- .../codeforces/mappers/TeamMapperTest.java | 89 +++++++++++++++++++ 3 files changed, 91 insertions(+), 7 deletions(-) rename src/test/java/com/cf/cfteam/utils/codeforces/{ => mappers}/GroupMapperTest.java (88%) create mode 100644 src/test/java/com/cf/cfteam/utils/codeforces/mappers/TeamMapperTest.java diff --git a/src/main/java/com/cf/cfteam/utils/codeforces/mappers/TeamMapper.java b/src/main/java/com/cf/cfteam/utils/codeforces/mappers/TeamMapper.java index a63fba5..875ad64 100644 --- a/src/main/java/com/cf/cfteam/utils/codeforces/mappers/TeamMapper.java +++ b/src/main/java/com/cf/cfteam/utils/codeforces/mappers/TeamMapper.java @@ -22,7 +22,7 @@ public TeamResponse fromEntityToResponse(Team team) { List convertedPlayers = new ArrayList<>(); Double teamRating = 0.; - if (team.getPlayers() != null) { + if (team.getPlayers() != null && !team.getPlayers().isEmpty()) { convertedPlayers = team.getPlayers().stream() .map(playerMapper::fromEntityToResponse) .toList(); diff --git a/src/test/java/com/cf/cfteam/utils/codeforces/GroupMapperTest.java b/src/test/java/com/cf/cfteam/utils/codeforces/mappers/GroupMapperTest.java similarity index 88% rename from src/test/java/com/cf/cfteam/utils/codeforces/GroupMapperTest.java rename to src/test/java/com/cf/cfteam/utils/codeforces/mappers/GroupMapperTest.java index 4b4bc12..89c99c0 100644 --- a/src/test/java/com/cf/cfteam/utils/codeforces/GroupMapperTest.java +++ b/src/test/java/com/cf/cfteam/utils/codeforces/mappers/GroupMapperTest.java @@ -1,18 +1,13 @@ -package com.cf.cfteam.utils.codeforces; +package com.cf.cfteam.utils.codeforces.mappers; import com.cf.cfteam.models.entities.codeforces.Group; import com.cf.cfteam.models.entities.security.Role; import com.cf.cfteam.models.entities.security.User; import com.cf.cfteam.transfer.payloads.codeforces.GroupPayload; -import com.cf.cfteam.utils.codeforces.mappers.GroupMapper; -import com.cf.cfteam.utils.codeforces.mappers.TeamMapper; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.InjectMocks; -import org.mockito.Spy; import org.mockito.junit.jupiter.MockitoExtension; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.ActiveProfiles; import static org.assertj.core.api.Assertions.assertThat; diff --git a/src/test/java/com/cf/cfteam/utils/codeforces/mappers/TeamMapperTest.java b/src/test/java/com/cf/cfteam/utils/codeforces/mappers/TeamMapperTest.java new file mode 100644 index 0000000..4d5466c --- /dev/null +++ b/src/test/java/com/cf/cfteam/utils/codeforces/mappers/TeamMapperTest.java @@ -0,0 +1,89 @@ +package com.cf.cfteam.utils.codeforces.mappers; + +import com.cf.cfteam.models.entities.codeforces.Group; +import com.cf.cfteam.models.entities.codeforces.Team; +import com.cf.cfteam.transfer.payloads.codeforces.TeamPayload; +import com.cf.cfteam.transfer.responses.codeforces.TeamResponse; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InjectMocks; +import org.mockito.junit.jupiter.MockitoExtension; +import org.springframework.test.context.ActiveProfiles; + +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertAll; + +@ActiveProfiles("test") +@ExtendWith(MockitoExtension.class) +class TeamMapperTest { + + @InjectMocks + private TeamMapper teamMapper; + + @Test + void shouldMapFromEntityToResponse() { + Team team = Team.builder() + .name("Team name") + .description(" Team description") + .id(1L) + .players(null) + .build(); + + TeamResponse response = teamMapper.fromEntityToResponse(team); + + assertAll( + () -> assertThat(response).isNotNull(), + () -> assertThat(response.name()).isEqualTo(team.getName()), + () -> assertThat(response.description()).isEqualTo(team.getDescription()), + () -> assertThat(response.id()).isEqualTo(team.getId()), + () -> assertThat(response.players()).isEqualTo(List.of()), + () -> assertThat(response.teamRating()).isEqualTo(0L) + ); + } + + @Test + void shouldMapFromPayloadToEntity() { + TeamPayload payload = TeamPayload.builder() + .name("team name") + .description("team description") + .build(); + Group group = Group.builder() + .name("group name") + .description("group descr") + .build(); + + Team team = teamMapper.fromPayloadToEntity(payload, group); + + assertAll( + () -> assertThat(team).isNotNull(), + () -> assertThat(team.getGroup()).isEqualTo(group), + () -> assertThat(team.getName()).isEqualTo(payload.name()), + () -> assertThat(team.getDescription()).isEqualTo(payload.description()) + ); + } + + @Test + void shouldUpdateEntityFromPayload() { + Team team = Team.builder() + .name("Team name") + .description(" Team description") + .id(1L) + .players(null) + .build(); + + TeamPayload payload = TeamPayload.builder() + .name("new team name") + .description("new team description") + .build(); + + Team updatedTeam = teamMapper.updateEntityFromPayload(team, payload); + + assertAll( + () -> assertThat(updatedTeam).isNotNull(), + () -> assertThat(updatedTeam.getName()).isEqualTo(payload.name()), + () -> assertThat(updatedTeam.getDescription()).isEqualTo(payload.description()) + ); + } +} \ No newline at end of file From 6a94375b451842dc7de0487fcfefcc14dd8b7050 Mon Sep 17 00:00:00 2001 From: AlexanderGarifullin Date: Tue, 17 Dec 2024 11:10:27 +0500 Subject: [PATCH 41/60] =?UTF-8?q?dev/codeforces/=20=D0=94=D0=BE=D0=B1?= =?UTF-8?q?=D0=B0=D0=B2=D0=B8=D0=BB=20=D1=82=D0=B5=D1=81=D1=82=D1=8B=20?= =?UTF-8?q?=D0=B4=D0=BB=D1=8F=20PlayerMapper?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../codeforces/mappers/PlayerMapperTest.java | 60 +++++++++++++++++++ 1 file changed, 60 insertions(+) create mode 100644 src/test/java/com/cf/cfteam/utils/codeforces/mappers/PlayerMapperTest.java diff --git a/src/test/java/com/cf/cfteam/utils/codeforces/mappers/PlayerMapperTest.java b/src/test/java/com/cf/cfteam/utils/codeforces/mappers/PlayerMapperTest.java new file mode 100644 index 0000000..d504991 --- /dev/null +++ b/src/test/java/com/cf/cfteam/utils/codeforces/mappers/PlayerMapperTest.java @@ -0,0 +1,60 @@ +package com.cf.cfteam.utils.codeforces.mappers; + +import com.cf.cfteam.models.entities.codeforces.Player; +import com.cf.cfteam.transfer.payloads.codeforces.PlayerPayload; +import com.cf.cfteam.transfer.responses.codeforces.PlayerResponse; +import com.github.benmanes.caffeine.cache.LoadingCache; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; +import org.springframework.test.context.ActiveProfiles; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.Mockito.when; + +@ActiveProfiles("test") +@ExtendWith(MockitoExtension.class) +class PlayerMapperTest { + + @InjectMocks + private PlayerMapper playerMapper; + + @Mock + private LoadingCache ratingCache; + + @Test + void shouldMapFromEntityToResponse() { + Player player = Player.builder() + .login("login") + .id(1L) + .build(); + + when(ratingCache.get(player.getLogin())).thenReturn(0.); + + PlayerResponse response = playerMapper.fromEntityToResponse(player); + + assertAll( + () -> assertThat(response).isNotNull(), + () -> assertThat(response.id()).isEqualTo(player.getId()), + () -> assertThat(response.rating()).isEqualTo(0.), + () -> assertThat(response.login()).isEqualTo(player.getLogin()) + ); + } + + @Test + void shouldMapFromPayloadToEntity() { + PlayerPayload payload = PlayerPayload.builder() + .login("player login") + .build(); + + Player player = playerMapper.fromPayloadToEntity(payload); + + assertAll( + () -> assertThat(player).isNotNull(), + () -> assertThat(player.getLogin()).isEqualTo(payload.login()) + ); + } +} \ No newline at end of file From 7e00f7c64ceb50f2f18ef1437ae87385fd9f83a3 Mon Sep 17 00:00:00 2001 From: AlexanderGarifullin Date: Tue, 17 Dec 2024 11:15:20 +0500 Subject: [PATCH 42/60] =?UTF-8?q?dev/codeforces/=20=D0=94=D0=BE=D0=B1?= =?UTF-8?q?=D0=B0=D0=B2=D0=B8=D0=BB=20=D1=82=D0=B5=D1=81=D1=82=D1=8B=20?= =?UTF-8?q?=D0=B4=D0=BB=D1=8F=20RatingCalculator?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../utils/codeforces/RatingCalculator.java | 2 +- .../codeforces/RatingCalculatorTest.java | 26 +++++++++++++++++++ 2 files changed, 27 insertions(+), 1 deletion(-) create mode 100644 src/test/java/com/cf/cfteam/utils/codeforces/RatingCalculatorTest.java diff --git a/src/main/java/com/cf/cfteam/utils/codeforces/RatingCalculator.java b/src/main/java/com/cf/cfteam/utils/codeforces/RatingCalculator.java index a013272..2f27662 100644 --- a/src/main/java/com/cf/cfteam/utils/codeforces/RatingCalculator.java +++ b/src/main/java/com/cf/cfteam/utils/codeforces/RatingCalculator.java @@ -6,7 +6,7 @@ public final class RatingCalculator { - public static double getWinProbability(double ra, double rb) { + private static double getWinProbability(double ra, double rb) { return 1.0 / (1.0 + Math.pow(10.0, (rb - ra) / 400.0)); } diff --git a/src/test/java/com/cf/cfteam/utils/codeforces/RatingCalculatorTest.java b/src/test/java/com/cf/cfteam/utils/codeforces/RatingCalculatorTest.java new file mode 100644 index 0000000..caea3d8 --- /dev/null +++ b/src/test/java/com/cf/cfteam/utils/codeforces/RatingCalculatorTest.java @@ -0,0 +1,26 @@ +package com.cf.cfteam.utils.codeforces; + +import com.cf.cfteam.transfer.responses.codeforces.PlayerResponse; +import org.junit.jupiter.api.Test; +import org.springframework.test.context.ActiveProfiles; + +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; + +@ActiveProfiles("test") +class RatingCalculatorTest { + + @Test + void testCalculateSoloRating() { + PlayerResponse response = PlayerResponse.builder() + .id(1L) + .login("login") + .rating(1000.) + .build(); + List players = List.of(response); + var result = RatingCalculator.aggregateRatings(players); + + assertThat(result).isEqualTo(1000.); + } +} \ No newline at end of file From be1df51fd4b9ab0d6f90c1a2aa7f28f7c1d2be08 Mon Sep 17 00:00:00 2001 From: AlexanderGarifullin Date: Tue, 17 Dec 2024 11:18:41 +0500 Subject: [PATCH 43/60] =?UTF-8?q?dev/codeforces/test=20=D0=A3=D0=B4=D0=B0?= =?UTF-8?q?=D0=BB=D0=B8=D0=BB=20=D0=BB=D0=B8=D1=88=D0=BD=D0=B8=D0=B5=20?= =?UTF-8?q?=D0=B8=D0=BC=D0=BF=D0=BE=D1=80=D1=82=D1=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../codeforces/GroupControllerTest.java | 6 ------ .../codeforces/TeamControllerTest.java | 16 ++++++++++++++++ 2 files changed, 16 insertions(+), 6 deletions(-) create mode 100644 src/test/java/com/cf/cfteam/controllers/codeforces/TeamControllerTest.java diff --git a/src/test/java/com/cf/cfteam/controllers/codeforces/GroupControllerTest.java b/src/test/java/com/cf/cfteam/controllers/codeforces/GroupControllerTest.java index 2a9d5ef..cc2c83e 100644 --- a/src/test/java/com/cf/cfteam/controllers/codeforces/GroupControllerTest.java +++ b/src/test/java/com/cf/cfteam/controllers/codeforces/GroupControllerTest.java @@ -1,10 +1,8 @@ package com.cf.cfteam.controllers.codeforces; -import com.cf.cfteam.models.entities.codeforces.Group; import com.cf.cfteam.services.codeforces.GroupService; import com.cf.cfteam.transfer.payloads.codeforces.GroupPayload; import com.cf.cfteam.transfer.responses.codeforces.GroupResponse; -import com.cf.cfteam.utils.codeforces.mappers.GroupMapper; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.mockito.InjectMocks; @@ -25,14 +23,10 @@ class GroupControllerTest { @InjectMocks private GroupController groupController; - @Mock - private GroupMapper groupMapper; - @Mock private GroupService groupService; private GroupPayload groupPayload; -// private Group group; private GroupResponse groupResponse; @BeforeEach diff --git a/src/test/java/com/cf/cfteam/controllers/codeforces/TeamControllerTest.java b/src/test/java/com/cf/cfteam/controllers/codeforces/TeamControllerTest.java new file mode 100644 index 0000000..2e1e049 --- /dev/null +++ b/src/test/java/com/cf/cfteam/controllers/codeforces/TeamControllerTest.java @@ -0,0 +1,16 @@ +package com.cf.cfteam.controllers.codeforces; + +import org.mockito.InjectMocks; +import org.springframework.test.context.ActiveProfiles; + +import static org.junit.jupiter.api.Assertions.*; + +@ActiveProfiles("test") +class TeamControllerTest { + + @InjectMocks + private TeamController teamController; + + + +} \ No newline at end of file From 80538c59288d8a5a0854896d970648e8c7741bf4 Mon Sep 17 00:00:00 2001 From: AlexanderGarifullin Date: Tue, 17 Dec 2024 11:28:24 +0500 Subject: [PATCH 44/60] =?UTF-8?q?dev/codeforces/test=20=D0=A3=D0=B4=D0=B0?= =?UTF-8?q?=D0=BB=D0=B8=D0=BB=20=D0=BB=D0=B8=D1=88=D0=BD=D0=B8=D0=B5=20?= =?UTF-8?q?=D0=B8=D0=BC=D0=BF=D0=BE=D1=80=D1=82=D1=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../codeforces/GroupControllerTest.java | 22 +++++++------------ .../codeforces/TeamControllerTest.java | 10 ++++++++- .../security/UserControllerTest.java | 8 +++---- .../services/codeforces/GroupServiceTest.java | 6 ++--- .../security/AuthenticationServiceTest.java | 10 +++------ .../security/MyUserDetailsServiceTest.java | 10 +++------ .../services/security/TokenServiceTest.java | 10 +++------ 7 files changed, 32 insertions(+), 44 deletions(-) diff --git a/src/test/java/com/cf/cfteam/controllers/codeforces/GroupControllerTest.java b/src/test/java/com/cf/cfteam/controllers/codeforces/GroupControllerTest.java index cc2c83e..fded720 100644 --- a/src/test/java/com/cf/cfteam/controllers/codeforces/GroupControllerTest.java +++ b/src/test/java/com/cf/cfteam/controllers/codeforces/GroupControllerTest.java @@ -3,11 +3,12 @@ import com.cf.cfteam.services.codeforces.GroupService; import com.cf.cfteam.transfer.payloads.codeforces.GroupPayload; import com.cf.cfteam.transfer.responses.codeforces.GroupResponse; -import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.InjectMocks; import org.mockito.Mock; -import org.mockito.MockitoAnnotations; +import org.mockito.junit.jupiter.MockitoExtension; import org.springframework.test.context.ActiveProfiles; import java.util.List; @@ -18,6 +19,7 @@ @ActiveProfiles("test") +@ExtendWith(MockitoExtension.class) class GroupControllerTest { @InjectMocks @@ -26,19 +28,11 @@ class GroupControllerTest { @Mock private GroupService groupService; - private GroupPayload groupPayload; - private GroupResponse groupResponse; - - @BeforeEach - void setUp() { - MockitoAnnotations.openMocks(this); - -// group = Group.builder() -// .name("Test Group") -// .description("Test description") -// .user(null) -// .build(); + private static GroupPayload groupPayload; + private static GroupResponse groupResponse; + @BeforeAll + static void setUp() { groupPayload = GroupPayload.builder() .name("Test Group") .description("Test description") diff --git a/src/test/java/com/cf/cfteam/controllers/codeforces/TeamControllerTest.java b/src/test/java/com/cf/cfteam/controllers/codeforces/TeamControllerTest.java index 2e1e049..2cb39d6 100644 --- a/src/test/java/com/cf/cfteam/controllers/codeforces/TeamControllerTest.java +++ b/src/test/java/com/cf/cfteam/controllers/codeforces/TeamControllerTest.java @@ -1,16 +1,24 @@ package com.cf.cfteam.controllers.codeforces; +import com.cf.cfteam.services.codeforces.TeamService; +import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; import org.springframework.test.context.ActiveProfiles; -import static org.junit.jupiter.api.Assertions.*; @ActiveProfiles("test") +@ExtendWith(MockitoExtension.class) class TeamControllerTest { @InjectMocks private TeamController teamController; + @Mock + private TeamService teamService; + + } \ No newline at end of file diff --git a/src/test/java/com/cf/cfteam/controllers/security/UserControllerTest.java b/src/test/java/com/cf/cfteam/controllers/security/UserControllerTest.java index fea4bc8..65c737c 100644 --- a/src/test/java/com/cf/cfteam/controllers/security/UserControllerTest.java +++ b/src/test/java/com/cf/cfteam/controllers/security/UserControllerTest.java @@ -8,9 +8,11 @@ import com.cf.cfteam.transfer.responses.security.JwtAuthenticationResponse; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.MockitoAnnotations; +import org.mockito.junit.jupiter.MockitoExtension; import org.springframework.test.context.ActiveProfiles; import org.springframework.security.core.Authentication; @@ -19,6 +21,7 @@ import static org.mockito.Mockito.when; @ActiveProfiles("test") +@ExtendWith(MockitoExtension.class) class UserControllerTest { @InjectMocks @@ -30,11 +33,6 @@ class UserControllerTest { @Mock private Authentication authentication; - @BeforeEach - void setUp() { - MockitoAnnotations.openMocks(this); - } - @Test void testRegister_success() { RegistrationPayload registrationPayload = getRegistrationPayload(); diff --git a/src/test/java/com/cf/cfteam/services/codeforces/GroupServiceTest.java b/src/test/java/com/cf/cfteam/services/codeforces/GroupServiceTest.java index dd63313..8a93107 100644 --- a/src/test/java/com/cf/cfteam/services/codeforces/GroupServiceTest.java +++ b/src/test/java/com/cf/cfteam/services/codeforces/GroupServiceTest.java @@ -12,9 +12,11 @@ import com.cf.cfteam.utils.codeforces.mappers.GroupMapper; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.MockitoAnnotations; +import org.mockito.junit.jupiter.MockitoExtension; import org.springframework.test.context.ActiveProfiles; import java.util.List; @@ -27,6 +29,7 @@ import static org.mockito.Mockito.*; @ActiveProfiles("test") +@ExtendWith(MockitoExtension.class) class GroupServiceTest { @InjectMocks @@ -48,7 +51,6 @@ class GroupServiceTest { @BeforeEach void setUp() { - MockitoAnnotations.openMocks(this); user = User.builder() .name("User name") @@ -164,8 +166,6 @@ void updateGroup_ShouldThrowGroupNotFoundException_WhenGroupDoesNotExist() { @Test void deleteGroup_ShouldDeleteGroup_WhenGroupExists() { - when(groupRepository.findById(1L)).thenReturn(Optional.of(group)); - groupService.deleteGroup(1L); verify(groupRepository, times(1)).deleteById(1L); diff --git a/src/test/java/com/cf/cfteam/services/security/AuthenticationServiceTest.java b/src/test/java/com/cf/cfteam/services/security/AuthenticationServiceTest.java index 7106988..218898e 100644 --- a/src/test/java/com/cf/cfteam/services/security/AuthenticationServiceTest.java +++ b/src/test/java/com/cf/cfteam/services/security/AuthenticationServiceTest.java @@ -12,11 +12,11 @@ import com.cf.cfteam.transfer.payloads.security.ChangePasswordPayload; import com.cf.cfteam.transfer.payloads.security.RegistrationPayload; import com.cf.cfteam.transfer.responses.security.JwtAuthenticationResponse; -import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.InjectMocks; import org.mockito.Mock; -import org.mockito.MockitoAnnotations; +import org.mockito.junit.jupiter.MockitoExtension; import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.core.Authentication; import org.springframework.security.crypto.password.PasswordEncoder; @@ -29,6 +29,7 @@ import static org.mockito.Mockito.*; @ActiveProfiles("test") +@ExtendWith(MockitoExtension.class) class AuthenticationServiceTest { @InjectMocks @@ -55,11 +56,6 @@ class AuthenticationServiceTest { @Mock private UserDetails userDetails; - @BeforeEach - void setUp() { - MockitoAnnotations.openMocks(this); - } - @Test void register_shouldThrowException_WhenUserAlreadyRegistered() { String login = "testLogin"; diff --git a/src/test/java/com/cf/cfteam/services/security/MyUserDetailsServiceTest.java b/src/test/java/com/cf/cfteam/services/security/MyUserDetailsServiceTest.java index 334b04c..834717b 100644 --- a/src/test/java/com/cf/cfteam/services/security/MyUserDetailsServiceTest.java +++ b/src/test/java/com/cf/cfteam/services/security/MyUserDetailsServiceTest.java @@ -2,11 +2,11 @@ import com.cf.cfteam.models.entities.security.User; import com.cf.cfteam.repositories.jpa.security.UserRepository; -import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.InjectMocks; import org.mockito.Mock; -import org.mockito.MockitoAnnotations; +import org.mockito.junit.jupiter.MockitoExtension; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.core.userdetails.UsernameNotFoundException; import org.springframework.test.context.ActiveProfiles; @@ -18,6 +18,7 @@ import static org.mockito.Mockito.when; @ActiveProfiles("test") +@ExtendWith(MockitoExtension.class) class MyUserDetailsServiceTest { @Mock @@ -26,11 +27,6 @@ class MyUserDetailsServiceTest { @InjectMocks private MyUserDetailsService userDetailsService; - @BeforeEach - void setUp() { - MockitoAnnotations.openMocks(this); - } - @Test void loadUserByUsername_shouldLoadUserByUsername_WhenUserExists() { String login = "testLogin"; diff --git a/src/test/java/com/cf/cfteam/services/security/TokenServiceTest.java b/src/test/java/com/cf/cfteam/services/security/TokenServiceTest.java index bd46dd7..fb8b285 100644 --- a/src/test/java/com/cf/cfteam/services/security/TokenServiceTest.java +++ b/src/test/java/com/cf/cfteam/services/security/TokenServiceTest.java @@ -4,11 +4,11 @@ import com.cf.cfteam.exceptions.security.TokenNotFoundException; import com.cf.cfteam.models.entities.security.Token; import com.cf.cfteam.repositories.jpa.security.TokenRepository; -import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.InjectMocks; import org.mockito.Mock; -import org.mockito.MockitoAnnotations; +import org.mockito.junit.jupiter.MockitoExtension; import org.springframework.test.context.ActiveProfiles; import java.util.Optional; @@ -18,6 +18,7 @@ import static org.mockito.Mockito.*; @ActiveProfiles("test") +@ExtendWith(MockitoExtension.class) class TokenServiceTest { @InjectMocks @@ -26,11 +27,6 @@ class TokenServiceTest { @Mock private TokenRepository tokenRepository; - @BeforeEach - void setUp() { - MockitoAnnotations.openMocks(this); - } - @Test void isTokenRevoked_shouldReturnTrue_whenTokenIsRevoked() { String tokenValue = "valid-token"; From d055d97ed66d798063a46c0fe941b9c4669bd18a Mon Sep 17 00:00:00 2001 From: AlexanderGarifullin Date: Tue, 17 Dec 2024 11:39:34 +0500 Subject: [PATCH 45/60] =?UTF-8?q?dev/codeforces/test=20=D0=9D=D0=B0=D0=BF?= =?UTF-8?q?=D0=B8=D1=81=D0=B0=D1=82=D1=8C=20unit=20=D1=82=D0=B5=D1=81?= =?UTF-8?q?=D1=82=D1=8B=20=D0=B4=D0=BB=D1=8F=20TeamController?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../codeforces/TeamController.java | 2 +- .../codeforces/TeamControllerTest.java | 88 +++++++++++++++++++ 2 files changed, 89 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/cf/cfteam/controllers/codeforces/TeamController.java b/src/main/java/com/cf/cfteam/controllers/codeforces/TeamController.java index 4e2f2e5..3c4ae91 100644 --- a/src/main/java/com/cf/cfteam/controllers/codeforces/TeamController.java +++ b/src/main/java/com/cf/cfteam/controllers/codeforces/TeamController.java @@ -51,7 +51,7 @@ public ResponseEntity deleteTeam(@PathVariable Long teamId, Authentication } @DeleteMapping("/group/{groupId}") - public ResponseEntity deleteAllTeamsByUser(@PathVariable Long groupId, Authentication authentication) { + public ResponseEntity deleteAllTeamsByGroup(@PathVariable Long groupId, Authentication authentication) { teamService.deleteAllTeamsByGroup(groupId); return ResponseEntity.noContent().build(); } diff --git a/src/test/java/com/cf/cfteam/controllers/codeforces/TeamControllerTest.java b/src/test/java/com/cf/cfteam/controllers/codeforces/TeamControllerTest.java index 2cb39d6..282595c 100644 --- a/src/test/java/com/cf/cfteam/controllers/codeforces/TeamControllerTest.java +++ b/src/test/java/com/cf/cfteam/controllers/codeforces/TeamControllerTest.java @@ -1,12 +1,22 @@ package com.cf.cfteam.controllers.codeforces; import com.cf.cfteam.services.codeforces.TeamService; +import com.cf.cfteam.transfer.payloads.codeforces.TeamPayload; +import com.cf.cfteam.transfer.responses.codeforces.TeamResponse; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; import org.springframework.test.context.ActiveProfiles; +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertAll; +import static org.mockito.Mockito.*; + @ActiveProfiles("test") @ExtendWith(MockitoExtension.class) @@ -18,7 +28,85 @@ class TeamControllerTest { @Mock private TeamService teamService; + private static TeamPayload teamPayload; + private static TeamResponse teamResponse; + + @BeforeAll + static void setUp() { + teamPayload = TeamPayload.builder() + .name("team name") + .description("team description") + .build(); + + teamResponse = TeamResponse.builder() + .id(1L) + .name("team name") + .description("team description") + .players(List.of()) + .teamRating(0.) + .build(); + } + + @Test + void shouldReturnAllTeamsByGroup() { + when(teamService.getAllTeamsByGroup(1L)).thenReturn(List.of(teamResponse)); + + var teams = teamController.getAllTeamsByGroup(1L, null).getBody(); + + verify(teamService, times(1)).getAllTeamsByGroup(1L); + + assertThat(teams) + .isNotNull() + .hasSize(1) + .contains(teamResponse); + } + + @Test + void shouldReturnTeamById() { + when(teamService.getTeamById(1L)).thenReturn(teamResponse); + + var result = teamController.getTeamById(1L, null).getBody(); + + verify(teamService, times(1)).getTeamById(1L); + assertThat(result).isEqualTo(teamResponse); + } + + @Test + void shouldAddTeamToGroup() { + when(teamService.addTeamToGroup(1L, teamPayload)).thenReturn(teamResponse); + + var result = teamController.addTeamToGroup(1L, teamPayload, null).getBody(); + + verify(teamService, times(1)).addTeamToGroup(1L, teamPayload); + + assertThat(result).isEqualTo(teamResponse); + } + + @Test + void shouldUpdateTeam() { + when(teamService.updateTeam(1L, teamPayload)).thenReturn(teamResponse); + + var result = teamController.updateTeam(1L, teamPayload, null).getBody(); + + verify(teamService, times(1)).updateTeam(1L, teamPayload); + assertAll( + () -> assertThat(result).isNotNull(), + () -> assertThat(result.name()).isEqualTo(teamResponse.name()), + () -> assertThat(result.description()).isEqualTo(teamResponse.description()) + ); + } + + @Test + void shouldDeleteGroup() { + teamController.deleteTeam(1L, null); + verify(teamService, times(1)).deleteTeam(1L); + } + @Test + void shouldDeleteAllGroupsByUser() { + teamController.deleteAllTeamsByGroup(1L, null); + verify(teamService, times(1)).deleteAllTeamsByGroup(1L); + } } \ No newline at end of file From 43a77e5080802527ce35f41eda70c60358543a36 Mon Sep 17 00:00:00 2001 From: AlexanderGarifullin Date: Tue, 17 Dec 2024 11:49:32 +0500 Subject: [PATCH 46/60] =?UTF-8?q?dev/codeforces/test=20=D0=9D=D0=B0=D0=BF?= =?UTF-8?q?=D0=B8=D1=81=D0=B0=D1=82=D1=8C=20unit=20=D1=82=D0=B5=D1=81?= =?UTF-8?q?=D1=82=D1=8B=20=D0=B4=D0=BB=D1=8F=20PlayerController?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../codeforces/PlayerControllerTest.java | 108 ++++++++++++++++++ 1 file changed, 108 insertions(+) create mode 100644 src/test/java/com/cf/cfteam/controllers/codeforces/PlayerControllerTest.java diff --git a/src/test/java/com/cf/cfteam/controllers/codeforces/PlayerControllerTest.java b/src/test/java/com/cf/cfteam/controllers/codeforces/PlayerControllerTest.java new file mode 100644 index 0000000..db0f0e5 --- /dev/null +++ b/src/test/java/com/cf/cfteam/controllers/codeforces/PlayerControllerTest.java @@ -0,0 +1,108 @@ +package com.cf.cfteam.controllers.codeforces; + +import com.cf.cfteam.services.codeforces.PlayerService; +import com.cf.cfteam.transfer.payloads.codeforces.PlayerPayload; +import com.cf.cfteam.transfer.responses.codeforces.PlayerResponse; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; +import org.springframework.test.context.ActiveProfiles; + +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertAll; +import static org.mockito.Mockito.*; + + +@ActiveProfiles("test") +@ExtendWith(MockitoExtension.class) +class PlayerControllerTest { + + @InjectMocks + private PlayerController playerController; + + @Mock + private PlayerService playerService; + + private static PlayerPayload playerPayload; + private static PlayerResponse playerResponse; + + @BeforeAll + static void setUp() { + playerPayload = PlayerPayload.builder() + .login("login") + .build(); + + playerResponse = PlayerResponse.builder() + .id(1L) + .rating(1000.) + .login("login") + .build(); + } + + @Test + void shouldReturnAllPlayersByTeam() { + when(playerService.getAllPlayersByTeam(1L)).thenReturn(List.of(playerResponse)); + + var players = playerController.getAllPlayersByTeam(1L, null).getBody(); + + verify(playerService, times(1)).getAllPlayersByTeam(1L); + + assertThat(players) + .isNotNull() + .hasSize(1) + .contains(playerResponse); + } + + @Test + void shouldReturnPlayerById() { + when(playerService.getPlayerById(1L)).thenReturn(playerResponse); + + var result = playerController.getPlayerById(1L, null).getBody(); + + verify(playerService, times(1)).getPlayerById(1L); + assertThat(result).isEqualTo(playerResponse); + } + + @Test + void shouldAddPlayerToTeam() { + when(playerService.addPlayerToTeam(1L, playerPayload)).thenReturn(playerResponse); + + var result = playerController.addPlayerToTeam(1L, playerPayload, null).getBody(); + + verify(playerService, times(1)).addPlayerToTeam(1L, playerPayload); + + assertThat(result).isEqualTo(playerResponse); + } + + @Test + void shouldUpdatePlayerInTeam() { + when(playerService.updatePlayerInTeam(1L, 1L, playerPayload)).thenReturn(playerResponse); + + var result = playerController.updatePlayerInTeam(1L, 1L, playerPayload, null).getBody(); + + verify(playerService, times(1)).updatePlayerInTeam(1L, 1L, playerPayload); + assertAll( + () -> assertThat(result).isNotNull(), + () -> assertThat(result.login()).isEqualTo(playerResponse.login()) + ); + } + + @Test + void shouldDeletePlayerFromTeam() { + playerController.deletePlayerFromTeam(1L, 1L, null); + + verify(playerService, times(1)).deletePlayerFromTeam(1L, 1L); + } + + @Test + void shouldDeleteAllPlayersFromTeam() { + playerController.deleteAllPlayersFromTeam(1L, null); + + verify(playerService, times(1)).deleteAllPlayersFromTeam(1L); + } +} \ No newline at end of file From e0d4372fc05deb6c735a13b6359d2ffd78e4a8f3 Mon Sep 17 00:00:00 2001 From: AlexanderGarifullin Date: Tue, 17 Dec 2024 11:52:24 +0500 Subject: [PATCH 47/60] =?UTF-8?q?dev/codeforces/test=20=D0=9E=D1=82=D1=80?= =?UTF-8?q?=D0=B5=D1=84=D0=B0=D0=BA=D1=82=D0=BE=D1=80=D0=B8=D0=BB=20GroupS?= =?UTF-8?q?erviceTest?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../services/codeforces/GroupServiceTest.java | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/src/test/java/com/cf/cfteam/services/codeforces/GroupServiceTest.java b/src/test/java/com/cf/cfteam/services/codeforces/GroupServiceTest.java index 8a93107..e8fbb1a 100644 --- a/src/test/java/com/cf/cfteam/services/codeforces/GroupServiceTest.java +++ b/src/test/java/com/cf/cfteam/services/codeforces/GroupServiceTest.java @@ -10,12 +10,11 @@ import com.cf.cfteam.transfer.payloads.codeforces.GroupPayload; import com.cf.cfteam.transfer.responses.codeforces.GroupResponse; import com.cf.cfteam.utils.codeforces.mappers.GroupMapper; -import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.InjectMocks; import org.mockito.Mock; -import org.mockito.MockitoAnnotations; import org.mockito.junit.jupiter.MockitoExtension; import org.springframework.test.context.ActiveProfiles; @@ -44,13 +43,13 @@ class GroupServiceTest { @Mock private GroupMapper groupMapper; - private User user; - private Group group; - private GroupPayload groupPayload; - private GroupResponse groupResponse; + private static User user; + private static Group group; + private static GroupPayload groupPayload; + private static GroupResponse groupResponse; - @BeforeEach - void setUp() { + @BeforeAll + static void setUp() { user = User.builder() .name("User name") From ca912d2a7e09b7681ef8bd6beed34adcc163c012 Mon Sep 17 00:00:00 2001 From: AlexanderGarifullin Date: Tue, 17 Dec 2024 12:11:54 +0500 Subject: [PATCH 48/60] =?UTF-8?q?dev/codeforces/test=20=D0=9D=D0=B0=D0=BF?= =?UTF-8?q?=D0=B8=D1=81=D0=B0=D0=BB=20unit=20=D1=82=D0=B5=D1=81=D1=82?= =?UTF-8?q?=D1=8B=20=D0=B4=D0=BB=D1=8F=20Teamservice?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../services/codeforces/TeamServiceTest.java | 197 ++++++++++++++++++ 1 file changed, 197 insertions(+) create mode 100644 src/test/java/com/cf/cfteam/services/codeforces/TeamServiceTest.java diff --git a/src/test/java/com/cf/cfteam/services/codeforces/TeamServiceTest.java b/src/test/java/com/cf/cfteam/services/codeforces/TeamServiceTest.java new file mode 100644 index 0000000..4230447 --- /dev/null +++ b/src/test/java/com/cf/cfteam/services/codeforces/TeamServiceTest.java @@ -0,0 +1,197 @@ +package com.cf.cfteam.services.codeforces; + +import com.cf.cfteam.exceptions.codeforces.GroupNotFoundException; +import com.cf.cfteam.exceptions.codeforces.TeamNotFoundException; +import com.cf.cfteam.exceptions.security.UserNotFoundException; +import com.cf.cfteam.models.entities.codeforces.Group; +import com.cf.cfteam.models.entities.codeforces.Team; +import com.cf.cfteam.models.entities.security.Role; +import com.cf.cfteam.models.entities.security.User; +import com.cf.cfteam.repositories.jpa.codeforces.GroupRepository; +import com.cf.cfteam.repositories.jpa.codeforces.TeamRepository; +import com.cf.cfteam.transfer.payloads.codeforces.GroupPayload; +import com.cf.cfteam.transfer.payloads.codeforces.TeamPayload; +import com.cf.cfteam.transfer.responses.codeforces.GroupResponse; +import com.cf.cfteam.transfer.responses.codeforces.TeamResponse; +import com.cf.cfteam.utils.codeforces.mappers.TeamMapper; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; +import org.springframework.test.context.ActiveProfiles; + +import java.util.List; +import java.util.Optional; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.*; + +@ActiveProfiles("test") +@ExtendWith(MockitoExtension.class) +class TeamServiceTest { + + @InjectMocks + private TeamService teamService; + + @Mock + private TeamRepository teamRepository; + + @Mock + private GroupRepository groupRepository; + + @Mock + private TeamMapper teamMapper; + + private static Group group; + private static Team team; + private static TeamPayload teamPayload; + private static TeamResponse teamResponse; + + @BeforeAll + static void setUp() { + group = Group.builder() + .name("Test Group") + .description("Test description") + .user(null) + .build(); + + team = Team.builder() + .name("team") + .description("team description") + .group(group) + .build(); + + teamPayload = TeamPayload.builder() + .name("team") + .description("team description") + .build(); + + teamResponse = TeamResponse.builder() + .name("team") + .description("team description") + .players(List.of()) + .teamRating(0.) + .build(); + } + + @Test + void getAllTeamsByGroup_ShouldReturnTeams_WhenGroupExists() { + when(groupRepository.findById(1L)).thenReturn(Optional.of(group)); + when(teamRepository.findByGroup(group)).thenReturn(List.of(team)); + when(teamMapper.fromEntityToResponse(team)).thenReturn(teamResponse); + + var teams = teamService.getAllTeamsByGroup(1L); + + assertThat(teams).hasSize(1) + .contains(teamResponse); + } + + @Test + void getAllTeamsByGroup_ShouldThrowGroupNotFoundException_WhenGroupDoesNotExist() { + when(groupRepository.findById(1L)).thenReturn(Optional.empty()); + + assertThatThrownBy(() -> teamService.getAllTeamsByGroup(1L)) + .isInstanceOf(GroupNotFoundException.class) + .hasMessageContaining("id.not_found"); + } + + @Test + void getTeamById_ShouldReturnTeam_WhenTeamExists() { + when(teamRepository.findById(1L)).thenReturn(Optional.of(team)); + when(teamMapper.fromEntityToResponse(team)).thenReturn(teamResponse); + + var result = teamService.getTeamById(1L); + + assertThat(result).isEqualTo(teamResponse); + } + + @Test + void getTeamById_ShouldThrowTeamNotFoundException_WhenTeanDoesNotExist() { + when(teamRepository.findById(1L)).thenReturn(Optional.empty()); + + assertThatThrownBy(() -> teamService.getTeamById(1L)) + .isInstanceOf(TeamNotFoundException.class) + .hasMessageContaining("id.not_found"); + } + + @Test + void addTeamToGroup_ShouldAddTeam_WhenGroupExists() { + when(groupRepository.findById(1L)).thenReturn(Optional.of(group)); + when(teamRepository.save(any(Team.class))).thenReturn(team); + + when(teamMapper.fromPayloadToEntity(teamPayload, group)).thenReturn(team); + when(teamMapper.fromEntityToResponse(team)).thenReturn(teamResponse); + + var result = teamService.addTeamToGroup(1L, teamPayload); + + assertThat(result).isEqualTo(teamResponse); + verify(teamRepository, times(1)).save(any(Team.class)); + } + + @Test + void addTeamToGroup_ShouldThrowUserNotFoundException_WhenUserDoesNotExist() { + when(groupRepository.findById(1L)).thenReturn(Optional.empty()); + + assertThatThrownBy(() -> teamService.addTeamToGroup(1L, teamPayload)) + .isInstanceOf(GroupNotFoundException.class) + .hasMessageContaining("id.not_found"); + } + + @Test + void updateTeam_ShouldUpdateTeam_WhenTeamExists() { + when(teamRepository.findById(1L)).thenReturn(Optional.of(team)); + when(teamRepository.save(any(Team.class))).thenReturn(team); + + when(teamMapper.updateEntityFromPayload(team, teamPayload)).thenReturn(team); + when(teamMapper.fromEntityToResponse(team)).thenReturn(teamResponse); + + var result = teamService.updateTeam(1L, teamPayload); + + assertAll( + () -> assertThat(result.description()).isEqualTo(teamPayload.description()), + () -> assertThat(result.name()).isEqualTo(teamPayload.name()) + ); + verify(teamRepository, times(1)).save(any(Team.class)); + } + + @Test + void updateTeam_ShouldThrowTeamNotFoundException_WhenTeamDoesNotExist() { + when(teamRepository.findById(1L)).thenReturn(Optional.empty()); + + assertThatThrownBy(() -> teamService.updateTeam(1L, teamPayload)) + .isInstanceOf(TeamNotFoundException.class) + .hasMessageContaining("id.not_found"); + } + + @Test + void deleteTeam_ShouldDeleteTeam_WhenTeamExists() { + teamService.deleteTeam(1L); + + verify(teamRepository, times(1)).deleteById(1L); + } + + @Test + void deleteAllTeamsByGroup_ShouldDeleteAllTeams_WhenGroupExists() { + when(groupRepository.findById(1L)).thenReturn(Optional.of(group)); + when(teamRepository.findByGroup(group)).thenReturn(List.of(team)); + + teamService.deleteAllTeamsByGroup(1L); + + verify(teamRepository, times(1)).deleteAll(List.of(team)); + } + + @Test + void deleteAllTeamsByGroup_ShouldThrowGroupNotFoundException_WhenGroupDoesNotExist() { + when(groupRepository.findById(1L)).thenReturn(Optional.empty()); + + assertThatThrownBy(() -> teamService.deleteAllTeamsByGroup(1L)) + .isInstanceOf(GroupNotFoundException.class) + .hasMessageContaining("id.not_found"); + } + +} \ No newline at end of file From 9bcbc046d99283bc498a80db0cb8aa7e6fe071e7 Mon Sep 17 00:00:00 2001 From: AlexanderGarifullin Date: Tue, 17 Dec 2024 12:13:08 +0500 Subject: [PATCH 49/60] =?UTF-8?q?dev/codeforces/test=20=D0=A3=D0=B4=D0=B0?= =?UTF-8?q?=D0=BB=D0=B8=D0=BB=20=D0=BB=D0=B8=D1=88=D0=BD=D0=B8=D0=B5=20?= =?UTF-8?q?=D0=B8=D0=BC=D0=BF=D0=BE=D1=80=D1=82=D1=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/cf/cfteam/services/codeforces/TeamServiceTest.java | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/test/java/com/cf/cfteam/services/codeforces/TeamServiceTest.java b/src/test/java/com/cf/cfteam/services/codeforces/TeamServiceTest.java index 4230447..d0f9d27 100644 --- a/src/test/java/com/cf/cfteam/services/codeforces/TeamServiceTest.java +++ b/src/test/java/com/cf/cfteam/services/codeforces/TeamServiceTest.java @@ -2,16 +2,11 @@ import com.cf.cfteam.exceptions.codeforces.GroupNotFoundException; import com.cf.cfteam.exceptions.codeforces.TeamNotFoundException; -import com.cf.cfteam.exceptions.security.UserNotFoundException; import com.cf.cfteam.models.entities.codeforces.Group; import com.cf.cfteam.models.entities.codeforces.Team; -import com.cf.cfteam.models.entities.security.Role; -import com.cf.cfteam.models.entities.security.User; import com.cf.cfteam.repositories.jpa.codeforces.GroupRepository; import com.cf.cfteam.repositories.jpa.codeforces.TeamRepository; -import com.cf.cfteam.transfer.payloads.codeforces.GroupPayload; import com.cf.cfteam.transfer.payloads.codeforces.TeamPayload; -import com.cf.cfteam.transfer.responses.codeforces.GroupResponse; import com.cf.cfteam.transfer.responses.codeforces.TeamResponse; import com.cf.cfteam.utils.codeforces.mappers.TeamMapper; import org.junit.jupiter.api.BeforeAll; From 66a5249401a77a6b21c0f1424de7a5449e061db9 Mon Sep 17 00:00:00 2001 From: AlexanderGarifullin Date: Tue, 17 Dec 2024 12:32:06 +0500 Subject: [PATCH 50/60] =?UTF-8?q?dev/codeforces/test=20=D0=98=D1=81=D0=BF?= =?UTF-8?q?=D1=80=D0=B0=D0=B2=D0=B8=D0=BB=20=D0=BE=D1=88=D0=B8=D0=B1=D0=BA?= =?UTF-8?q?=D1=83=20=D0=B2=20=D0=BD=D0=B0=D0=B7=D0=B2=D0=B0=D0=BD=D0=B8?= =?UTF-8?q?=D0=B8=20=D1=82=D0=B5=D1=81=D1=82=D0=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/cf/cfteam/services/codeforces/TeamServiceTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/java/com/cf/cfteam/services/codeforces/TeamServiceTest.java b/src/test/java/com/cf/cfteam/services/codeforces/TeamServiceTest.java index d0f9d27..73957c9 100644 --- a/src/test/java/com/cf/cfteam/services/codeforces/TeamServiceTest.java +++ b/src/test/java/com/cf/cfteam/services/codeforces/TeamServiceTest.java @@ -106,7 +106,7 @@ void getTeamById_ShouldReturnTeam_WhenTeamExists() { } @Test - void getTeamById_ShouldThrowTeamNotFoundException_WhenTeanDoesNotExist() { + void getTeamById_ShouldThrowTeamNotFoundException_WhenTeamDoesNotExist() { when(teamRepository.findById(1L)).thenReturn(Optional.empty()); assertThatThrownBy(() -> teamService.getTeamById(1L)) From 4c3a62e4820790fcb942ec06c3a0169e9193d196 Mon Sep 17 00:00:00 2001 From: AlexanderGarifullin Date: Tue, 17 Dec 2024 13:40:22 +0500 Subject: [PATCH 51/60] =?UTF-8?q?dev/codeforces/test=20=D0=9D=D0=B0=D0=BF?= =?UTF-8?q?=D0=B8=D1=81=D0=B0=D1=82=20unit=20=D1=82=D0=B5=D1=81=D1=82?= =?UTF-8?q?=D1=8B=20=D0=B4=D0=BB=D1=8F=20PlayerService?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../PlayerAlreadyInTeamException.java | 13 + .../services/codeforces/PlayerService.java | 33 +-- .../services/codeforces/TeamPlayerLinker.java | 33 +++ .../codeforces/PlayerServiceTest.java | 260 ++++++++++++++++++ 4 files changed, 317 insertions(+), 22 deletions(-) create mode 100644 src/main/java/com/cf/cfteam/exceptions/codeforces/PlayerAlreadyInTeamException.java create mode 100644 src/main/java/com/cf/cfteam/services/codeforces/TeamPlayerLinker.java create mode 100644 src/test/java/com/cf/cfteam/services/codeforces/PlayerServiceTest.java diff --git a/src/main/java/com/cf/cfteam/exceptions/codeforces/PlayerAlreadyInTeamException.java b/src/main/java/com/cf/cfteam/exceptions/codeforces/PlayerAlreadyInTeamException.java new file mode 100644 index 0000000..37060c3 --- /dev/null +++ b/src/main/java/com/cf/cfteam/exceptions/codeforces/PlayerAlreadyInTeamException.java @@ -0,0 +1,13 @@ +package com.cf.cfteam.exceptions.codeforces; + +import lombok.Getter; + +@Getter +public class PlayerAlreadyInTeamException extends RuntimeException { + private final String login; + + public PlayerAlreadyInTeamException(String login) { + super("player.already_in_team"); + this.login = login; + } +} diff --git a/src/main/java/com/cf/cfteam/services/codeforces/PlayerService.java b/src/main/java/com/cf/cfteam/services/codeforces/PlayerService.java index 9d3a533..716fd7f 100644 --- a/src/main/java/com/cf/cfteam/services/codeforces/PlayerService.java +++ b/src/main/java/com/cf/cfteam/services/codeforces/PlayerService.java @@ -1,5 +1,6 @@ package com.cf.cfteam.services.codeforces; +import com.cf.cfteam.exceptions.codeforces.PlayerAlreadyInTeamException; import com.cf.cfteam.exceptions.codeforces.PlayerNotFoundException; import com.cf.cfteam.exceptions.codeforces.PlayerNotFromTeamException; import com.cf.cfteam.exceptions.codeforces.TeamNotFoundException; @@ -22,6 +23,7 @@ public class PlayerService { private final PlayerRepository playerRepository; private final TeamRepository teamRepository; private final PlayerMapper playerMapper; + private final TeamPlayerLinker teamPlayerLinker; public List getAllPlayersByTeam(Long teamId) { var team = teamRepository.findById(teamId) @@ -45,7 +47,11 @@ public PlayerResponse addPlayerToTeam(Long teamId, PlayerPayload payload) { var player = createPlayer(payload); - linkTeamAndPlayer(team, player); + if (team.getPlayers().contains(player)) { + throw new PlayerAlreadyInTeamException(player.getLogin()); + } + + teamPlayerLinker.linkTeamAndPlayer(team, player); return playerMapper.fromEntityToResponse(player); } @@ -62,9 +68,9 @@ public PlayerResponse updatePlayerInTeam(Long playerId, Long teamId, PlayerPaylo throw new PlayerNotFromTeamException(teamId, playerId); } - unlinkTeamAndPlayer(team, player); + teamPlayerLinker.unlinkTeamAndPlayer(team, player); player = createPlayer(payload); - linkTeamAndPlayer(team, player); + teamPlayerLinker.linkTeamAndPlayer(team, player); return playerMapper.fromEntityToResponse(player); } @@ -85,7 +91,7 @@ public void deletePlayerFromTeam(Long playerId, Long teamId) { var team = teamRepository.findById(teamId) .orElseThrow(() -> new TeamNotFoundException(teamId)); - unlinkTeamAndPlayer(team, player); + teamPlayerLinker.unlinkTeamAndPlayer(team, player); } @@ -93,7 +99,7 @@ public void deleteAllPlayersFromTeam(Long teamId) { var team = teamRepository.findById(teamId) .orElseThrow(() -> new TeamNotFoundException(teamId)); - var players = team.getPlayers(); + var players = List.copyOf(team.getPlayers()); players.forEach(player -> player.getTeams().remove(team)); team.getPlayers().clear(); @@ -101,21 +107,4 @@ public void deleteAllPlayersFromTeam(Long teamId) { teamRepository.save(team); players.forEach(playerRepository::save); } - - private void unlinkTeamAndPlayer(Team team, Player player) { - team.getPlayers().remove(player); - player.getTeams().remove(team); - saveTeamAndPlayer(team, player); - } - - private void linkTeamAndPlayer(Team team, Player player) { - team.getPlayers().add(player); - player.getTeams().add(team); - saveTeamAndPlayer(team, player); - } - - private void saveTeamAndPlayer(Team team, Player player) { - teamRepository.save(team); - playerRepository.save(player); - } } diff --git a/src/main/java/com/cf/cfteam/services/codeforces/TeamPlayerLinker.java b/src/main/java/com/cf/cfteam/services/codeforces/TeamPlayerLinker.java new file mode 100644 index 0000000..8086027 --- /dev/null +++ b/src/main/java/com/cf/cfteam/services/codeforces/TeamPlayerLinker.java @@ -0,0 +1,33 @@ +package com.cf.cfteam.services.codeforces; + +import com.cf.cfteam.models.entities.codeforces.Player; +import com.cf.cfteam.models.entities.codeforces.Team; +import com.cf.cfteam.repositories.jpa.codeforces.PlayerRepository; +import com.cf.cfteam.repositories.jpa.codeforces.TeamRepository; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +@Service +@RequiredArgsConstructor +public class TeamPlayerLinker { + + private final TeamRepository teamRepository; + private final PlayerRepository playerRepository; + + public void unlinkTeamAndPlayer(Team team, Player player) { + team.getPlayers().remove(player); + player.getTeams().remove(team); + saveTeamAndPlayer(team, player); + } + + public void linkTeamAndPlayer(Team team, Player player) { + team.getPlayers().add(player); + player.getTeams().add(team); + saveTeamAndPlayer(team, player); + } + + public void saveTeamAndPlayer(Team team, Player player) { + teamRepository.save(team); + playerRepository.save(player); + } +} diff --git a/src/test/java/com/cf/cfteam/services/codeforces/PlayerServiceTest.java b/src/test/java/com/cf/cfteam/services/codeforces/PlayerServiceTest.java new file mode 100644 index 0000000..3bd64a5 --- /dev/null +++ b/src/test/java/com/cf/cfteam/services/codeforces/PlayerServiceTest.java @@ -0,0 +1,260 @@ +package com.cf.cfteam.services.codeforces; + + +import com.cf.cfteam.exceptions.codeforces.*; +import com.cf.cfteam.models.entities.codeforces.Player; +import com.cf.cfteam.models.entities.codeforces.Team; +import com.cf.cfteam.repositories.jpa.codeforces.PlayerRepository; +import com.cf.cfteam.repositories.jpa.codeforces.TeamRepository; +import com.cf.cfteam.transfer.payloads.codeforces.PlayerPayload; +import com.cf.cfteam.transfer.responses.codeforces.PlayerResponse; +import com.cf.cfteam.utils.codeforces.mappers.PlayerMapper; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; +import org.springframework.test.context.ActiveProfiles; + +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.mockito.Mockito.*; + +@ActiveProfiles("test") +@ExtendWith(MockitoExtension.class) +class PlayerServiceTest { + + @InjectMocks + private PlayerService playerService; + + @Mock + private PlayerRepository playerRepository; + + @Mock + private TeamRepository teamRepository; + + @Mock + private PlayerMapper playerMapper; + + @Mock + private TeamPlayerLinker teamPlayerLinker; + + private Team team; + private Player player; + private PlayerPayload playerPayload; + private PlayerResponse playerResponse; + + @BeforeEach + void setUp() { + team = Team.builder() + .id(1L) + .name("team") + .description("team description") + .build(); + + player = Player.builder() + .id(1L) + .login("login") + .teams(List.of()) + .build(); + + + playerPayload = PlayerPayload.builder() + .login("login") + .build(); + + playerResponse = PlayerResponse.builder() + .login("login") + .rating(1000.) + .id(1L) + .build(); + } + + + @Test + void getAllPlayersByTeam_ShouldReturnPlayers_WhenTeamExists() { + team.setPlayers(List.of(player)); + when(teamRepository.findById(1L)).thenReturn(Optional.of(team)); + + when(playerMapper.fromEntityToResponse(player)).thenReturn(playerResponse); + + var players = playerService.getAllPlayersByTeam(1L); + + assertThat(players).hasSize(1) + .contains(playerResponse); + } + + @Test + void getAllPlayersByTeam_ShouldThrowTeamNotFoundException_WhenTeamDoesNotExist() { + when(teamRepository.findById(1L)).thenReturn(Optional.empty()); + + assertThatThrownBy(() -> playerService.getAllPlayersByTeam(1L)) + .isInstanceOf(TeamNotFoundException.class) + .hasMessageContaining("id.not_found"); + } + + @Test + void getPlayerById_ShouldReturnPlayer_WhenPlayerExists() { + when(playerRepository.findById(1L)).thenReturn(Optional.of(player)); + when(playerMapper.fromEntityToResponse(player)).thenReturn(playerResponse); + + var result = playerService.getPlayerById(1L); + + assertThat(result).isEqualTo(playerResponse); + } + + @Test + void getPlayerById_ShouldThrowPlayerNotFoundException_WhenPlayerDoesNotExist() { + when(playerRepository.findById(1L)).thenReturn(Optional.empty()); + + assertThatThrownBy(() -> playerService.getPlayerById(1L)) + .isInstanceOf(PlayerNotFoundException.class) + .hasMessageContaining("id.not_found"); + } + + @Test + void addPlayerToTeam_ShouldAddPlayer_WhenTeamExists() { + when(teamRepository.findById(1L)).thenReturn(Optional.of(team)); + + when(playerRepository.findByLogin("login")).thenReturn(Optional.of(player)); + + doNothing().when(teamPlayerLinker).linkTeamAndPlayer(team, player); + + doReturn(playerResponse).when(playerMapper).fromEntityToResponse(player); + + var result = playerService.addPlayerToTeam(1L, playerPayload); + + assertThat(result).isEqualTo(playerResponse); + verify(teamPlayerLinker, times(1)).linkTeamAndPlayer(team, player); + } + + @Test + void addPlayerToTeam_ShouldThrowTeamNotFoundException_WhenTeamDoesNotExist() { + when(teamRepository.findById(1L)).thenReturn(Optional.empty()); + + assertThatThrownBy(() -> playerService.addPlayerToTeam(1L, playerPayload)) + .isInstanceOf(TeamNotFoundException.class) + .hasMessageContaining("id.not_found"); + } + + @Test + void addPlayerToTeam_ShouldThrowPlayerAlreadyInTeamException_WhenPlayerAlreadyInTeamException() { + when(teamRepository.findById(1L)).thenReturn(Optional.of(team)); + when(playerRepository.findByLogin("login")).thenReturn(Optional.of(player)); + + team.setPlayers(List.of(player)); + + assertThatThrownBy(() -> playerService.addPlayerToTeam(1L, playerPayload)) + .isInstanceOf(PlayerAlreadyInTeamException.class) + .hasMessageContaining("player.already_in_team"); + } + + @Test + void updatePlayerInTeam_ShouldUpdatePlayer_WhenTeamAndPlayerExistsAndFromOneTeam() { + team.setPlayers(List.of(player)); + + when(playerRepository.findById(1L)).thenReturn(Optional.of(player)); + when(teamRepository.findById(1L)).thenReturn(Optional.of(team)); + + doNothing().when(teamPlayerLinker).unlinkTeamAndPlayer(team, player); + when(playerRepository.findByLogin("login")).thenReturn(Optional.of(player)); + doNothing().when(teamPlayerLinker).linkTeamAndPlayer(team, player); + + when(playerRepository.findByLogin("login")).thenReturn(Optional.of(player)); + + doReturn(playerResponse).when(playerMapper).fromEntityToResponse(player); + + var result = playerService.updatePlayerInTeam(1L, 1L, playerPayload); + + assertThat(result).isEqualTo(playerResponse); + verify(teamPlayerLinker, times(1)).unlinkTeamAndPlayer(team, player); + verify(teamPlayerLinker, times(1)).linkTeamAndPlayer(team, player); + } + + @Test + void updatePlayerInTeam_ShouldThrowPlayerNotFoundException_WhenPlayerDoesNotExist() { + when(playerRepository.findById(1L)).thenReturn(Optional.empty()); + + assertThatThrownBy(() -> playerService.updatePlayerInTeam(1L, 1L, playerPayload)) + .isInstanceOf(PlayerNotFoundException.class) + .hasMessageContaining("id.not_found"); + } + + @Test + void updatePlayerInTeam_ShouldThrowTeamNotFoundException_WhenTeamDoesNotExist() { + when(playerRepository.findById(1L)).thenReturn(Optional.of(player)); + when(teamRepository.findById(1L)).thenReturn(Optional.empty()); + + assertThatThrownBy(() -> playerService.updatePlayerInTeam(1L, 1L, playerPayload)) + .isInstanceOf(TeamNotFoundException.class) + .hasMessageContaining("id.not_found"); + } + + @Test + void updatePlayerInTeam_ShouldThrowPlayerNotFromTeamException_WhenPlayerNotFromTeam() { + when(playerRepository.findById(1L)).thenReturn(Optional.of(player)); + when(teamRepository.findById(1L)).thenReturn(Optional.of(team)); + + assertThatThrownBy(() -> playerService.updatePlayerInTeam(1L, 1L, playerPayload)) + .isInstanceOf(PlayerNotFromTeamException.class) + .hasMessageContaining("player.not_from_team"); + } + + @Test + void deletePlayerFromTeam_ShouldDeletePlayerFromTeam_WhenTeamNadPlayerExists() { + when(playerRepository.findById(1L)).thenReturn(Optional.of(player)); + when(teamRepository.findById(1L)).thenReturn(Optional.of(team)); + + doNothing().when(teamPlayerLinker).unlinkTeamAndPlayer(team, player); + playerService.deletePlayerFromTeam(1L, 1L); + verify(teamPlayerLinker, times(1)).unlinkTeamAndPlayer(team, player); + } + + @Test + void deletePlayerFromTeam_ShouldThrowPlayerNotFoundException_WhenPlayerNotFound() { + when(playerRepository.findById(1L)).thenReturn(Optional.empty()); + + assertThatThrownBy(() -> playerService.deletePlayerFromTeam(1L, 1L)) + .isInstanceOf(PlayerNotFoundException.class) + .hasMessageContaining("id.not_found"); + } + + @Test + void deletePlayerFromTeam_ShouldThrowTeamNotFoundException_WhenTeamNotFound() { + when(playerRepository.findById(1L)).thenReturn(Optional.of(player)); + when(teamRepository.findById(1L)).thenReturn(Optional.empty()); + + assertThatThrownBy(() -> playerService.deletePlayerFromTeam(1L, 1L)) + .isInstanceOf(TeamNotFoundException.class) + .hasMessageContaining("id.not_found"); + } + + @Test + void deleteAllPlayersFromTeam_ShouldDeleteAllPlayersFromTeam_WhenTeamPlayerExists() { + when(teamRepository.findById(1L)).thenReturn(Optional.of(team)); + team.setPlayers(new ArrayList<>(List.of(player))); + player.setTeams(new ArrayList<>(List.of(team))); + + doReturn(team).when(teamRepository).save(team); + doReturn(player).when(playerRepository).save(player); + + playerService.deleteAllPlayersFromTeam(1L); + + verify(teamRepository, times(1)).save(team); + verify(playerRepository, times(1)).save(player); + } + + @Test + void deleteAllPlayersFromTeam_ShouldThrowTeamNotFoundException_WhenTeamNotFound() { + when(teamRepository.findById(1L)).thenReturn(Optional.empty()); + + assertThatThrownBy(() -> playerService.deleteAllPlayersFromTeam(1L)) + .isInstanceOf(TeamNotFoundException.class) + .hasMessageContaining("id.not_found"); + } +} \ No newline at end of file From f0c092c39df705441504a93cb1606abef4ade3c7 Mon Sep 17 00:00:00 2001 From: AlexanderGarifullin Date: Tue, 17 Dec 2024 13:44:21 +0500 Subject: [PATCH 52/60] =?UTF-8?q?dev/codeforces/ref=20=D1=83=D0=B4=D0=B0?= =?UTF-8?q?=D0=BB=D0=B8=D0=BB=20=D0=BB=D0=B8=D1=88=D0=BD=D0=B8=D0=B5=20?= =?UTF-8?q?=D0=B8=D0=BC=D0=BF=D0=BE=D1=80=D1=82=D1=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/cf/cfteam/services/codeforces/PlayerService.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/java/com/cf/cfteam/services/codeforces/PlayerService.java b/src/main/java/com/cf/cfteam/services/codeforces/PlayerService.java index 716fd7f..50bed0d 100644 --- a/src/main/java/com/cf/cfteam/services/codeforces/PlayerService.java +++ b/src/main/java/com/cf/cfteam/services/codeforces/PlayerService.java @@ -5,7 +5,6 @@ import com.cf.cfteam.exceptions.codeforces.PlayerNotFromTeamException; import com.cf.cfteam.exceptions.codeforces.TeamNotFoundException; import com.cf.cfteam.models.entities.codeforces.Player; -import com.cf.cfteam.models.entities.codeforces.Team; import com.cf.cfteam.repositories.jpa.codeforces.PlayerRepository; import com.cf.cfteam.repositories.jpa.codeforces.TeamRepository; import com.cf.cfteam.transfer.payloads.codeforces.PlayerPayload; From b44bc08c8570e4c70a07bda4df038acb327da380 Mon Sep 17 00:00:00 2001 From: AlexanderGarifullin Date: Tue, 17 Dec 2024 14:37:08 +0500 Subject: [PATCH 53/60] =?UTF-8?q?dev/codeforces/test=20=D0=9D=D0=B0=D0=BF?= =?UTF-8?q?=D0=B8=D1=81=D0=B0=D0=BB=20=D0=B8=D0=BD=D1=82=D0=B5=D0=B3=D1=80?= =?UTF-8?q?=D0=B0=D1=86=D0=B8=D0=BE=D0=BD=D0=BD=D1=8B=D0=B5=20=D1=82=D0=B5?= =?UTF-8?q?=D1=81=D1=82=D1=8B=20=D0=B4=D0=BB=D1=8F=20TeamController?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../CodeforcesExceptionHandler.java | 37 +- .../TeamControllerIntegrationTest.java | 375 ++++++++++++++++++ 2 files changed, 411 insertions(+), 1 deletion(-) create mode 100644 src/test/java/com/cf/cfteam/controllers/codeforces/TeamControllerIntegrationTest.java diff --git a/src/main/java/com/cf/cfteam/advicers/codeforces/CodeforcesExceptionHandler.java b/src/main/java/com/cf/cfteam/advicers/codeforces/CodeforcesExceptionHandler.java index 99433e1..c1655da 100644 --- a/src/main/java/com/cf/cfteam/advicers/codeforces/CodeforcesExceptionHandler.java +++ b/src/main/java/com/cf/cfteam/advicers/codeforces/CodeforcesExceptionHandler.java @@ -1,21 +1,56 @@ package com.cf.cfteam.advicers.codeforces; -import com.cf.cfteam.exceptions.codeforces.GroupNotFoundException; +import com.cf.cfteam.exceptions.codeforces.*; import com.cf.cfteam.utils.ErrorResponseBuilder; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.bind.annotation.ExceptionHandler; +import java.util.HashMap; import java.util.Map; @ControllerAdvice public class CodeforcesExceptionHandler { private static final String ID = "id"; + private static final String LOGIN = "login"; + private static final String TEAM_ID = "teamId"; + private static final String PLAYER_ID = "playerId"; @ExceptionHandler(GroupNotFoundException.class) public ResponseEntity handleUserNotFoundException(GroupNotFoundException ex) { return ErrorResponseBuilder.buildErrorResponse(ex.getMessage(), HttpStatus.NOT_FOUND, Map.of(ID, ex.getId())); } + @ExceptionHandler(TeamNotFoundException.class) + public ResponseEntity handleTeamNotFoundException(TeamNotFoundException ex) { + return ErrorResponseBuilder.buildErrorResponse(ex.getMessage(), HttpStatus.NOT_FOUND, Map.of(ID, ex.getId())); + } + + @ExceptionHandler(PlayerNotFoundException.class) + public ResponseEntity handlePayerNotFoundException(PlayerNotFoundException ex) { + return ErrorResponseBuilder.buildErrorResponse(ex.getMessage(), HttpStatus.NOT_FOUND, Map.of(ID, ex.getId())); + } + + @ExceptionHandler(PlayerAlreadyInTeamException.class) + public ResponseEntity handlePlayerAlreadyInTeamException(PlayerAlreadyInTeamException ex) { + return ErrorResponseBuilder.buildErrorResponse(ex.getMessage(), HttpStatus.NOT_FOUND, Map.of(LOGIN, ex.getLogin())); + } + + @ExceptionHandler(PlayerNotFromTeamException.class) + public ResponseEntity handlePlayerNotFromTeamException(PlayerNotFromTeamException ex) { + Map details = new HashMap<>(); + if (ex.getPlayerId() != null) { + details.put(PLAYER_ID, ex.getPlayerId()); + } + if (ex.getTeamId() != null) { + details.put(TEAM_ID, ex.getTeamId()); + } + + return ErrorResponseBuilder.buildErrorResponse( + ex.getMessage(), + HttpStatus.NOT_FOUND, + details + ); + } } diff --git a/src/test/java/com/cf/cfteam/controllers/codeforces/TeamControllerIntegrationTest.java b/src/test/java/com/cf/cfteam/controllers/codeforces/TeamControllerIntegrationTest.java new file mode 100644 index 0000000..2e01f88 --- /dev/null +++ b/src/test/java/com/cf/cfteam/controllers/codeforces/TeamControllerIntegrationTest.java @@ -0,0 +1,375 @@ +package com.cf.cfteam.controllers.codeforces; + +import com.cf.cfteam.models.entities.codeforces.Team; +import com.cf.cfteam.repositories.jpa.codeforces.TeamRepository; +import com.cf.cfteam.transfer.payloads.codeforces.TeamPayload; +import com.cf.cfteam.transfer.responses.codeforces.TeamResponse; +import com.cf.cfteam.utils.codeforces.mappers.TeamMapper; +import com.fasterxml.jackson.core.type.TypeReference; +import com.cf.cfteam.BaseIntegrationTest; +import com.cf.cfteam.models.entities.codeforces.Group; +import com.cf.cfteam.models.entities.security.Role; +import com.cf.cfteam.models.entities.security.User; +import com.cf.cfteam.repositories.jpa.codeforces.GroupRepository; +import com.cf.cfteam.repositories.jpa.security.UserRepository; +import lombok.SneakyThrows; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.MediaType; +import org.springframework.test.context.ActiveProfiles; + +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertAll; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; + + +@ActiveProfiles("test") +public class TeamControllerIntegrationTest extends BaseIntegrationTest { + + private static final String URI = "/api/cf/teams"; + + private static final Long BAD_TEAM_ID = 9999L; + private static final Long BAD_GROUP_ID = 9999L; + + @Autowired + private TeamRepository teamRepository; + + @Autowired + private GroupRepository groupRepository; + + @Autowired + private UserRepository userRepository; + + @Autowired + private TeamMapper teamMapper; + + private static User user; + + @BeforeEach + void init() { + user = createUser(); + user = userRepository.save(user); + } + + @AfterEach + void postDelete() { + deleteUserFromDb(user); + } + + @Test + @SneakyThrows + public void getAllGroupsByUser_notEmpty_success() { + Group group = createGroup(user); + group = groupRepository.save(group); + + Team team = createTeam(group); + team = teamRepository.save(team); + + var mvcResponse = mockMvc.perform(get(URI + "/group/" + group.getId()) + .header("Authorization", userBearerToken)) + .andExpectAll( + status().isOk(), + content().contentType(MediaType.APPLICATION_JSON)) + .andReturn() + .getResponse(); + + var teams = objectMapper.readValue( + mvcResponse.getContentAsString(), + new TypeReference>() { + } + ); + + assertThat(teams).hasSize(1) + .contains(teamMapper.fromEntityToResponse(team)); + + deleteTeamFromDb(team); + deleteGroupFromDb(group); + } + + @Test + @SneakyThrows + void getAllTeamsByGroup_shouldThrowGroupNotFoundException_whenGroupNotFound() { + mockMvc.perform(get(URI + "/group/" + BAD_GROUP_ID) + .header("Authorization", userBearerToken)) + .andExpectAll( + status().isNotFound(), + content().contentType(MediaType.APPLICATION_JSON), + jsonPath("$.details.id").value(BAD_GROUP_ID), + jsonPath("$.message").value("id.not_found"), + jsonPath("$.error").value("Not Found"), + jsonPath("$.status").value(404) + ); + } + + @Test + @SneakyThrows + public void getTeamById_notEmpty() { + Group group = createGroup(user); + group = groupRepository.save(group); + + Team team = createTeam(group); + team = teamRepository.save(team); + + var mvcResponse = mockMvc.perform(get(URI + "/" + team.getId()) + .header("Authorization", userBearerToken)) + .andExpectAll( + status().isOk(), + content().contentType(MediaType.APPLICATION_JSON)) + .andReturn() + .getResponse(); + + var response = objectMapper.readValue(mvcResponse.getContentAsString(), TeamResponse.class); + + assertThat(response).isEqualTo(teamMapper.fromEntityToResponse(team)); + + deleteTeamFromDb(team); + deleteGroupFromDb(group); + } + + @Test + @SneakyThrows + void getTeamById_shouldThrowTeamNotFoundException_whenTeamNotFoundE() { + mockMvc.perform(get(URI + "/" + BAD_TEAM_ID) + .header("Authorization", userBearerToken)) + .andExpectAll( + status().isNotFound(), + content().contentType(MediaType.APPLICATION_JSON), + jsonPath("$.details.id").value(BAD_TEAM_ID), + jsonPath("$.message").value("id.not_found"), + jsonPath("$.error").value("Not Found"), + jsonPath("$.status").value(404) + ); + } + + @Test + @SneakyThrows + public void addTeamToGroup_success() { + Group group = createGroup(user); + group = groupRepository.save(group); + + var payload = createTeamPayload(); + + var mvcResponse = mockMvc.perform(post(URI + "/group/" + group.getId()) + .header("Authorization", userBearerToken) + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(payload))) + .andExpectAll( + status().isOk(), + content().contentType(MediaType.APPLICATION_JSON)) + .andReturn() + .getResponse(); + + var response = objectMapper.readValue(mvcResponse.getContentAsString(), TeamResponse.class); + var teamFromDb = teamRepository.findById(response.id()); + + assertAll( + () -> assertThat(teamFromDb).isPresent(), + () -> assertThat(response.description()).isEqualTo(payload.description()), + () -> assertThat(response.name()).isEqualTo(payload.name()) + ); + + deleteTeamFromDb(teamFromDb.get()); + deleteGroupFromDb(group); + } + + @Test + @SneakyThrows + void addTeamToGroup_shouldThrowGroupNotFoundException_whenGroupNotFound() { + var payload = createTeamPayload(); + + mockMvc.perform(post(URI + "/group/" + BAD_GROUP_ID) + .header("Authorization", userBearerToken) + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(payload))) + .andExpectAll( + status().isNotFound(), + content().contentType(MediaType.APPLICATION_JSON), + jsonPath("$.details.id").value(BAD_GROUP_ID), + jsonPath("$.message").value("id.not_found"), + jsonPath("$.error").value("Not Found"), + jsonPath("$.status").value(404) + ); + } + + @Test + @SneakyThrows + public void updateTeam_success() { + Group group = createGroup(user); + group = groupRepository.save(group); + + var payload = createTeamPayload("new name", "new description"); + + Team team = createTeam(group); + team = teamRepository.save(team); + + + var mvcResponse = mockMvc.perform(put(URI + "/" + team.getId()) + .header("Authorization", userBearerToken) + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(payload))) + .andExpectAll( + status().isOk(), + content().contentType(MediaType.APPLICATION_JSON)) + .andReturn() + .getResponse(); + + + var response = objectMapper.readValue(mvcResponse.getContentAsString(), TeamResponse.class); + var teamFromDb = teamRepository.findById(response.id()); + + assertAll( + () -> assertThat(teamFromDb).isPresent(), + () -> assertThat(teamFromDb.get().getDescription()).isEqualTo(payload.description()), + () -> assertThat(teamFromDb.get().getName()).isEqualTo(payload.name()) + ); + + deleteTeamFromDb(teamFromDb.get()); + deleteGroupFromDb(group); + } + + @Test + @SneakyThrows + void updateTeam_shouldThrowTeamNotFoundException_whenTeamNotFound() { + var payload = createTeamPayload(); + + mockMvc.perform(put(URI + "/" + BAD_TEAM_ID) + .header("Authorization", userBearerToken) + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(payload))) + .andExpectAll( + status().isNotFound(), + content().contentType(MediaType.APPLICATION_JSON), + jsonPath("$.details.id").value(BAD_TEAM_ID), + jsonPath("$.message").value("id.not_found"), + jsonPath("$.error").value("Not Found"), + jsonPath("$.status").value(404) + ); + } + + @Test + @SneakyThrows + public void deleteTeam_success() { + Group group = createGroup(user); + group = groupRepository.save(group); + + Team team = createTeam(group); + team = teamRepository.save(team); + + mockMvc.perform(delete(URI + "/" + group.getId()) + .header("Authorization", userBearerToken)) + .andExpectAll( + status().isNoContent(), + content().string("") + ); + + var teamFromDb = teamRepository.findById(team.getId()); + + assertThat(teamFromDb).isNotPresent(); + + deleteGroupFromDb(group); + } + + @Test + @SneakyThrows + public void deleteAllTeamsByGroup_success() { + Group group = createGroup(user); + group = groupRepository.save(group); + + Team team1 = createTeam(group); + team1 = teamRepository.save(team1); + + Team team2 = createTeam(group); + team2 = teamRepository.save(team2); + + mockMvc.perform(delete(URI + "/group/" + group.getId()) + .header("Authorization", userBearerToken)) + .andExpectAll( + status().isNoContent(), + content().string("") + ); + + var teamFromDb1 = teamRepository.findById(team1.getId()); + var teamFromDb2 = teamRepository.findById(team2.getId()); + + assertAll( + () -> assertThat(teamFromDb1).isNotPresent(), + () -> assertThat(teamFromDb2).isNotPresent() + ); + + var mvcResponse = mockMvc.perform(get(URI + "/group/" + group.getId()) + .header("Authorization", userBearerToken)) + .andExpectAll( + status().isOk(), + content().contentType(MediaType.APPLICATION_JSON)) + .andReturn() + .getResponse(); + + var teams = objectMapper.readValue( + mvcResponse.getContentAsString(), + new TypeReference>() { + } + ); + + assertThat(teams).isEmpty(); + + deleteGroupFromDb(group); + } + + + private TeamPayload createTeamPayload() { + return TeamPayload.builder() + .name("name") + .description("description") + .build(); + } + + private TeamPayload createTeamPayload(String name, String description) { + return TeamPayload.builder() + .name(name) + .description(description) + .build(); + } + + private User createUser() { + return User.builder() + .name("User name") + .login("User login") + .hashedPassword("Password") + .role(Role.USER) + .build(); + } + + private Group createGroup(User user) { + return Group.builder() + .name("Test Group") + .description("Test description") + .user(user) + .build(); + } + + private Team createTeam(Group group) { + return Team.builder() + .name("team") + .description("team description") + .group(group) + .build(); + } + + + private void deleteTeamFromDb(Team team) { + teamRepository.delete(team); + } + + private void deleteGroupFromDb(Group group) { + groupRepository.delete(group); + } + + private void deleteUserFromDb(User user) { + userRepository.delete(user); + } +} From d1e4eb500a2e288bf8de210a046e716b29b9c68e Mon Sep 17 00:00:00 2001 From: AlexanderGarifullin Date: Tue, 17 Dec 2024 14:50:56 +0500 Subject: [PATCH 54/60] =?UTF-8?q?dev/codeforces/test=20=D0=98=D1=81=D0=BF?= =?UTF-8?q?=D1=80=D0=B0=D0=B2=D0=B8=D0=BB=20=D1=82=D0=B5=D1=81=D1=82=D1=8B?= =?UTF-8?q?=20=D0=B8=20=D0=BA=D0=BE=D0=B4=20=D0=BF=D0=BE=D0=B4=20checkStyl?= =?UTF-8?q?e?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../CodeforcesExceptionHandler.java | 3 +- .../TeamControllerIntegrationTest.java | 39 ++++++++++--------- 2 files changed, 23 insertions(+), 19 deletions(-) diff --git a/src/main/java/com/cf/cfteam/advicers/codeforces/CodeforcesExceptionHandler.java b/src/main/java/com/cf/cfteam/advicers/codeforces/CodeforcesExceptionHandler.java index c1655da..d77996f 100644 --- a/src/main/java/com/cf/cfteam/advicers/codeforces/CodeforcesExceptionHandler.java +++ b/src/main/java/com/cf/cfteam/advicers/codeforces/CodeforcesExceptionHandler.java @@ -34,7 +34,8 @@ public ResponseEntity handlePayerNotFoundException(PlayerNotFoundExcepti @ExceptionHandler(PlayerAlreadyInTeamException.class) public ResponseEntity handlePlayerAlreadyInTeamException(PlayerAlreadyInTeamException ex) { - return ErrorResponseBuilder.buildErrorResponse(ex.getMessage(), HttpStatus.NOT_FOUND, Map.of(LOGIN, ex.getLogin())); + return ErrorResponseBuilder.buildErrorResponse(ex.getMessage(), HttpStatus.NOT_FOUND, + Map.of(LOGIN, ex.getLogin())); } @ExceptionHandler(PlayerNotFromTeamException.class) diff --git a/src/test/java/com/cf/cfteam/controllers/codeforces/TeamControllerIntegrationTest.java b/src/test/java/com/cf/cfteam/controllers/codeforces/TeamControllerIntegrationTest.java index 2e01f88..10cf41d 100644 --- a/src/test/java/com/cf/cfteam/controllers/codeforces/TeamControllerIntegrationTest.java +++ b/src/test/java/com/cf/cfteam/controllers/codeforces/TeamControllerIntegrationTest.java @@ -13,8 +13,6 @@ import com.cf.cfteam.repositories.jpa.codeforces.GroupRepository; import com.cf.cfteam.repositories.jpa.security.UserRepository; import lombok.SneakyThrows; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.MediaType; @@ -48,22 +46,12 @@ public class TeamControllerIntegrationTest extends BaseIntegrationTest { @Autowired private TeamMapper teamMapper; - private static User user; - - @BeforeEach - void init() { - user = createUser(); - user = userRepository.save(user); - } - - @AfterEach - void postDelete() { - deleteUserFromDb(user); - } - @Test @SneakyThrows public void getAllGroupsByUser_notEmpty_success() { + User user = createUser("getAllGroupsByUser_notEmpty_success"); + user = userRepository.save(user); + Group group = createGroup(user); group = groupRepository.save(group); @@ -109,6 +97,9 @@ void getAllTeamsByGroup_shouldThrowGroupNotFoundException_whenGroupNotFound() { @Test @SneakyThrows public void getTeamById_notEmpty() { + User user = createUser("getTeamById_notEmpty"); + user = userRepository.save(user); + Group group = createGroup(user); group = groupRepository.save(group); @@ -149,6 +140,9 @@ void getTeamById_shouldThrowTeamNotFoundException_whenTeamNotFoundE() { @Test @SneakyThrows public void addTeamToGroup_success() { + User user = createUser("addTeamToGroup_success"); + user = userRepository.save(user); + Group group = createGroup(user); group = groupRepository.save(group); @@ -199,6 +193,9 @@ void addTeamToGroup_shouldThrowGroupNotFoundException_whenGroupNotFound() { @Test @SneakyThrows public void updateTeam_success() { + User user = createUser("updateTeam_success"); + user = userRepository.save(user); + Group group = createGroup(user); group = groupRepository.save(group); @@ -254,6 +251,9 @@ void updateTeam_shouldThrowTeamNotFoundException_whenTeamNotFound() { @Test @SneakyThrows public void deleteTeam_success() { + User user = createUser("deleteTeam_success"); + user = userRepository.save(user); + Group group = createGroup(user); group = groupRepository.save(group); @@ -277,6 +277,9 @@ public void deleteTeam_success() { @Test @SneakyThrows public void deleteAllTeamsByGroup_success() { + User user = createUser("deleteAllTeamsByGroup_success"); + user = userRepository.save(user); + Group group = createGroup(user); group = groupRepository.save(group); @@ -335,10 +338,10 @@ private TeamPayload createTeamPayload(String name, String description) { .build(); } - private User createUser() { + private User createUser(String login) { return User.builder() - .name("User name") - .login("User login") + .name("Team controller User name") + .login(login) .hashedPassword("Password") .role(Role.USER) .build(); From f4d696a3687b847f4d8401c67a251c1adf6986df Mon Sep 17 00:00:00 2001 From: AlexanderGarifullin Date: Tue, 17 Dec 2024 15:03:29 +0500 Subject: [PATCH 55/60] =?UTF-8?q?dev/codeforces/test=20=D0=98=D1=81=D0=BF?= =?UTF-8?q?=D1=80=D0=B0=D0=B2=D0=B8=D0=BB=20=D1=82=D0=B5=D1=81=D1=82=20del?= =?UTF-8?q?eteTeam=5Fsuccess=D0=B2=20TeamControllerIntegrationTest?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controllers/codeforces/TeamControllerIntegrationTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/java/com/cf/cfteam/controllers/codeforces/TeamControllerIntegrationTest.java b/src/test/java/com/cf/cfteam/controllers/codeforces/TeamControllerIntegrationTest.java index 10cf41d..01e6176 100644 --- a/src/test/java/com/cf/cfteam/controllers/codeforces/TeamControllerIntegrationTest.java +++ b/src/test/java/com/cf/cfteam/controllers/codeforces/TeamControllerIntegrationTest.java @@ -260,7 +260,7 @@ public void deleteTeam_success() { Team team = createTeam(group); team = teamRepository.save(team); - mockMvc.perform(delete(URI + "/" + group.getId()) + mockMvc.perform(delete(URI + "/" + team.getId()) .header("Authorization", userBearerToken)) .andExpectAll( status().isNoContent(), From 718b7aa39a6cda92d4f4feea39389352f8d2b790 Mon Sep 17 00:00:00 2001 From: AlexanderGarifullin Date: Tue, 17 Dec 2024 17:04:26 +0500 Subject: [PATCH 56/60] =?UTF-8?q?dev/codeforces/test=20=D0=9D=D0=B0=D0=BF?= =?UTF-8?q?=D0=B8=D1=81=D0=B0=D0=BB=20=D1=82=D0=B5=D1=81=D1=82=D1=8B=20?= =?UTF-8?q?=D0=B4=D0=BB=D1=8F=20CodeforcesClient?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../services/client/CodeforcesClientTest.java | 53 +++++++++++++++++++ .../codeforces/responses/tourist.json | 9 ++++ 2 files changed, 62 insertions(+) create mode 100644 src/test/java/com/cf/cfteam/services/client/CodeforcesClientTest.java create mode 100644 src/test/resources/codeforces/responses/tourist.json diff --git a/src/test/java/com/cf/cfteam/services/client/CodeforcesClientTest.java b/src/test/java/com/cf/cfteam/services/client/CodeforcesClientTest.java new file mode 100644 index 0000000..740a984 --- /dev/null +++ b/src/test/java/com/cf/cfteam/services/client/CodeforcesClientTest.java @@ -0,0 +1,53 @@ +package com.cf.cfteam.services.client; + +import com.github.tomakehurst.wiremock.junit5.WireMockTest; +import lombok.SneakyThrows; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.http.MediaType; +import org.springframework.test.context.DynamicPropertyRegistry; +import org.springframework.test.context.DynamicPropertySource; +import org.springframework.web.client.HttpClientErrorException; + +import java.nio.file.Files; +import java.nio.file.Paths; + +import static com.github.tomakehurst.wiremock.client.WireMock.*; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + + +@SpringBootTest +@WireMockTest(httpPort = 8080) +class CodeforcesClientTest { + + @Autowired + private CodeforcesClient codeforcesClient; + + private static final String MOCK_JSON_PATH = "src/test/resources/codeforces/responses/"; + + + @DynamicPropertySource + static void setProperties(DynamicPropertyRegistry registry) { + registry.add("codeforces.api.base.url", () -> "http://localhost:8080/api"); + } + + @Test + @SneakyThrows + void fetchRatingFromApi_ShouldReturnRating() { + String responseBody = Files.readString(Paths.get(MOCK_JSON_PATH + "tourist.json")); + + stubFor(get(urlPathEqualTo("/api/user.info")) + .withQueryParam("handles", equalTo("tourist")) + .withQueryParam("checkHistoricHandles", equalTo("false")) + .willReturn(aResponse() + .withStatus(200) + .withHeader("Content-Type", MediaType.APPLICATION_JSON_VALUE) + .withBody(responseBody))); + + Double rating = codeforcesClient.fetchRatingFromApi("tourist"); + + assertThat(rating).isEqualTo(4009); + } +} \ No newline at end of file diff --git a/src/test/resources/codeforces/responses/tourist.json b/src/test/resources/codeforces/responses/tourist.json new file mode 100644 index 0000000..0cd2b57 --- /dev/null +++ b/src/test/resources/codeforces/responses/tourist.json @@ -0,0 +1,9 @@ +{ + "status": "OK", + "result": [ + { + "handle": "tourist", + "rating": 4009 + } + ] +} From 46ca4ff7be4ebf263be50ce2d98f75233fdcb2e4 Mon Sep 17 00:00:00 2001 From: AlexanderGarifullin Date: Tue, 17 Dec 2024 17:05:28 +0500 Subject: [PATCH 57/60] =?UTF-8?q?dev/codeforces/test=20=D0=9D=D0=B5=D0=BC?= =?UTF-8?q?=D0=BD=D0=BE=D0=B3=D0=BE=20=D0=BE=D1=82=D1=80=D0=B5=D1=84=D0=B0?= =?UTF-8?q?=D0=BA=D1=82=D0=BE=D1=80=D0=B8=D0=BB=20=D0=BA=D0=BE=D0=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../{ => integration}/GroupControllerIntegrationTest.java | 2 +- .../{ => integration}/TeamControllerIntegrationTest.java | 2 +- .../controllers/codeforces/{ => unit}/GroupControllerTest.java | 3 ++- .../codeforces/{ => unit}/PlayerControllerTest.java | 3 ++- .../controllers/codeforces/{ => unit}/TeamControllerTest.java | 3 ++- .../com/cf/cfteam/services/client/CodeforcesClientTest.java | 3 --- 6 files changed, 8 insertions(+), 8 deletions(-) rename src/test/java/com/cf/cfteam/controllers/codeforces/{ => integration}/GroupControllerIntegrationTest.java (99%) rename src/test/java/com/cf/cfteam/controllers/codeforces/{ => integration}/TeamControllerIntegrationTest.java (99%) rename src/test/java/com/cf/cfteam/controllers/codeforces/{ => unit}/GroupControllerTest.java (96%) rename src/test/java/com/cf/cfteam/controllers/codeforces/{ => unit}/PlayerControllerTest.java (96%) rename src/test/java/com/cf/cfteam/controllers/codeforces/{ => unit}/TeamControllerTest.java (96%) diff --git a/src/test/java/com/cf/cfteam/controllers/codeforces/GroupControllerIntegrationTest.java b/src/test/java/com/cf/cfteam/controllers/codeforces/integration/GroupControllerIntegrationTest.java similarity index 99% rename from src/test/java/com/cf/cfteam/controllers/codeforces/GroupControllerIntegrationTest.java rename to src/test/java/com/cf/cfteam/controllers/codeforces/integration/GroupControllerIntegrationTest.java index 0c2eed5..9cd44a1 100644 --- a/src/test/java/com/cf/cfteam/controllers/codeforces/GroupControllerIntegrationTest.java +++ b/src/test/java/com/cf/cfteam/controllers/codeforces/integration/GroupControllerIntegrationTest.java @@ -1,4 +1,4 @@ -package com.cf.cfteam.controllers.codeforces; +package com.cf.cfteam.controllers.codeforces.integration; import com.cf.cfteam.transfer.responses.codeforces.GroupResponse; import com.cf.cfteam.utils.codeforces.mappers.GroupMapper; diff --git a/src/test/java/com/cf/cfteam/controllers/codeforces/TeamControllerIntegrationTest.java b/src/test/java/com/cf/cfteam/controllers/codeforces/integration/TeamControllerIntegrationTest.java similarity index 99% rename from src/test/java/com/cf/cfteam/controllers/codeforces/TeamControllerIntegrationTest.java rename to src/test/java/com/cf/cfteam/controllers/codeforces/integration/TeamControllerIntegrationTest.java index 01e6176..41fcabb 100644 --- a/src/test/java/com/cf/cfteam/controllers/codeforces/TeamControllerIntegrationTest.java +++ b/src/test/java/com/cf/cfteam/controllers/codeforces/integration/TeamControllerIntegrationTest.java @@ -1,4 +1,4 @@ -package com.cf.cfteam.controllers.codeforces; +package com.cf.cfteam.controllers.codeforces.integration; import com.cf.cfteam.models.entities.codeforces.Team; import com.cf.cfteam.repositories.jpa.codeforces.TeamRepository; diff --git a/src/test/java/com/cf/cfteam/controllers/codeforces/GroupControllerTest.java b/src/test/java/com/cf/cfteam/controllers/codeforces/unit/GroupControllerTest.java similarity index 96% rename from src/test/java/com/cf/cfteam/controllers/codeforces/GroupControllerTest.java rename to src/test/java/com/cf/cfteam/controllers/codeforces/unit/GroupControllerTest.java index fded720..8199621 100644 --- a/src/test/java/com/cf/cfteam/controllers/codeforces/GroupControllerTest.java +++ b/src/test/java/com/cf/cfteam/controllers/codeforces/unit/GroupControllerTest.java @@ -1,5 +1,6 @@ -package com.cf.cfteam.controllers.codeforces; +package com.cf.cfteam.controllers.codeforces.unit; +import com.cf.cfteam.controllers.codeforces.GroupController; import com.cf.cfteam.services.codeforces.GroupService; import com.cf.cfteam.transfer.payloads.codeforces.GroupPayload; import com.cf.cfteam.transfer.responses.codeforces.GroupResponse; diff --git a/src/test/java/com/cf/cfteam/controllers/codeforces/PlayerControllerTest.java b/src/test/java/com/cf/cfteam/controllers/codeforces/unit/PlayerControllerTest.java similarity index 96% rename from src/test/java/com/cf/cfteam/controllers/codeforces/PlayerControllerTest.java rename to src/test/java/com/cf/cfteam/controllers/codeforces/unit/PlayerControllerTest.java index db0f0e5..df33038 100644 --- a/src/test/java/com/cf/cfteam/controllers/codeforces/PlayerControllerTest.java +++ b/src/test/java/com/cf/cfteam/controllers/codeforces/unit/PlayerControllerTest.java @@ -1,5 +1,6 @@ -package com.cf.cfteam.controllers.codeforces; +package com.cf.cfteam.controllers.codeforces.unit; +import com.cf.cfteam.controllers.codeforces.PlayerController; import com.cf.cfteam.services.codeforces.PlayerService; import com.cf.cfteam.transfer.payloads.codeforces.PlayerPayload; import com.cf.cfteam.transfer.responses.codeforces.PlayerResponse; diff --git a/src/test/java/com/cf/cfteam/controllers/codeforces/TeamControllerTest.java b/src/test/java/com/cf/cfteam/controllers/codeforces/unit/TeamControllerTest.java similarity index 96% rename from src/test/java/com/cf/cfteam/controllers/codeforces/TeamControllerTest.java rename to src/test/java/com/cf/cfteam/controllers/codeforces/unit/TeamControllerTest.java index 282595c..4438f2c 100644 --- a/src/test/java/com/cf/cfteam/controllers/codeforces/TeamControllerTest.java +++ b/src/test/java/com/cf/cfteam/controllers/codeforces/unit/TeamControllerTest.java @@ -1,5 +1,6 @@ -package com.cf.cfteam.controllers.codeforces; +package com.cf.cfteam.controllers.codeforces.unit; +import com.cf.cfteam.controllers.codeforces.TeamController; import com.cf.cfteam.services.codeforces.TeamService; import com.cf.cfteam.transfer.payloads.codeforces.TeamPayload; import com.cf.cfteam.transfer.responses.codeforces.TeamResponse; diff --git a/src/test/java/com/cf/cfteam/services/client/CodeforcesClientTest.java b/src/test/java/com/cf/cfteam/services/client/CodeforcesClientTest.java index 740a984..3ef592e 100644 --- a/src/test/java/com/cf/cfteam/services/client/CodeforcesClientTest.java +++ b/src/test/java/com/cf/cfteam/services/client/CodeforcesClientTest.java @@ -8,15 +8,12 @@ import org.springframework.http.MediaType; import org.springframework.test.context.DynamicPropertyRegistry; import org.springframework.test.context.DynamicPropertySource; -import org.springframework.web.client.HttpClientErrorException; import java.nio.file.Files; import java.nio.file.Paths; import static com.github.tomakehurst.wiremock.client.WireMock.*; import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatThrownBy; - @SpringBootTest @WireMockTest(httpPort = 8080) From cdd2495f1aaa5b9ee820a4fb2a3cbd9e001eaafe Mon Sep 17 00:00:00 2001 From: AlexanderGarifullin Date: Tue, 17 Dec 2024 17:11:49 +0500 Subject: [PATCH 58/60] =?UTF-8?q?dev/codeforces/test=20=D0=94=D0=BE=D0=B1?= =?UTF-8?q?=D0=B0=D0=B2=D0=B8=D0=BB=20=D0=BF=D1=80=D0=BE=D1=84=D0=B8=D0=BB?= =?UTF-8?q?=D1=8C=20test=20=D1=82=D0=B5=D1=81=D1=82=D1=83=20CodeforcesClie?= =?UTF-8?q?ntTest?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/cf/cfteam/services/client/CodeforcesClientTest.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/test/java/com/cf/cfteam/services/client/CodeforcesClientTest.java b/src/test/java/com/cf/cfteam/services/client/CodeforcesClientTest.java index 3ef592e..be982a8 100644 --- a/src/test/java/com/cf/cfteam/services/client/CodeforcesClientTest.java +++ b/src/test/java/com/cf/cfteam/services/client/CodeforcesClientTest.java @@ -6,6 +6,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.http.MediaType; +import org.springframework.test.context.ActiveProfiles; import org.springframework.test.context.DynamicPropertyRegistry; import org.springframework.test.context.DynamicPropertySource; @@ -15,6 +16,7 @@ import static com.github.tomakehurst.wiremock.client.WireMock.*; import static org.assertj.core.api.Assertions.assertThat; +@ActiveProfiles("test") @SpringBootTest @WireMockTest(httpPort = 8080) class CodeforcesClientTest { From 305dfacbd3147cdb801105d919fb1e89554a6f58 Mon Sep 17 00:00:00 2001 From: AlexanderGarifullin Date: Tue, 17 Dec 2024 17:14:26 +0500 Subject: [PATCH 59/60] =?UTF-8?q?dev/codeforces/test=20=D0=BF=D0=BE=D0=BF?= =?UTF-8?q?=D1=8B=D1=82=D0=BA=D0=B0=20=D0=B8=D1=81=D0=BF=D1=80=D0=B0=D0=B2?= =?UTF-8?q?=D0=B8=D1=82=D1=8C=20CodeforcesClientTest?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/cf/cfteam/services/client/CodeforcesClientTest.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/test/java/com/cf/cfteam/services/client/CodeforcesClientTest.java b/src/test/java/com/cf/cfteam/services/client/CodeforcesClientTest.java index be982a8..1cd940e 100644 --- a/src/test/java/com/cf/cfteam/services/client/CodeforcesClientTest.java +++ b/src/test/java/com/cf/cfteam/services/client/CodeforcesClientTest.java @@ -1,5 +1,6 @@ package com.cf.cfteam.services.client; +import com.cf.cfteam.BaseIntegrationTest; import com.github.tomakehurst.wiremock.junit5.WireMockTest; import lombok.SneakyThrows; import org.junit.jupiter.api.Test; @@ -19,7 +20,7 @@ @ActiveProfiles("test") @SpringBootTest @WireMockTest(httpPort = 8080) -class CodeforcesClientTest { +class CodeforcesClientTest extends BaseIntegrationTest { @Autowired private CodeforcesClient codeforcesClient; From 700d62667d4f01e6128f243005c5237194a35b6c Mon Sep 17 00:00:00 2001 From: AlexanderGarifullin Date: Tue, 17 Dec 2024 18:43:15 +0500 Subject: [PATCH 60/60] =?UTF-8?q?dev/codeforces/test=20=D0=9D=D0=B0=D0=BF?= =?UTF-8?q?=D0=B8=D1=81=D0=B0=D0=BB=20=D0=B8=D0=BD=D1=82=D0=B5=D0=B3=D1=80?= =?UTF-8?q?=D0=B0=D1=86=D0=B8=D0=BE=D0=BD=D0=BD=D1=8B=D0=B5=20=D1=82=D0=B5?= =?UTF-8?q?=D1=81=D1=82=D1=8B=20=D0=B4=D0=BB=D1=8F=20PlayerControllerInteg?= =?UTF-8?q?ration?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../CodeforcesExceptionHandler.java | 4 +- .../PlayerControllerIntegrationTest.java | 630 ++++++++++++++++++ 2 files changed, 632 insertions(+), 2 deletions(-) create mode 100644 src/test/java/com/cf/cfteam/controllers/codeforces/integration/PlayerControllerIntegrationTest.java diff --git a/src/main/java/com/cf/cfteam/advicers/codeforces/CodeforcesExceptionHandler.java b/src/main/java/com/cf/cfteam/advicers/codeforces/CodeforcesExceptionHandler.java index d77996f..07a59de 100644 --- a/src/main/java/com/cf/cfteam/advicers/codeforces/CodeforcesExceptionHandler.java +++ b/src/main/java/com/cf/cfteam/advicers/codeforces/CodeforcesExceptionHandler.java @@ -34,7 +34,7 @@ public ResponseEntity handlePayerNotFoundException(PlayerNotFoundExcepti @ExceptionHandler(PlayerAlreadyInTeamException.class) public ResponseEntity handlePlayerAlreadyInTeamException(PlayerAlreadyInTeamException ex) { - return ErrorResponseBuilder.buildErrorResponse(ex.getMessage(), HttpStatus.NOT_FOUND, + return ErrorResponseBuilder.buildErrorResponse(ex.getMessage(), HttpStatus.CONFLICT, Map.of(LOGIN, ex.getLogin())); } @@ -50,7 +50,7 @@ public ResponseEntity handlePlayerNotFromTeamException(PlayerNotFromTeam return ErrorResponseBuilder.buildErrorResponse( ex.getMessage(), - HttpStatus.NOT_FOUND, + HttpStatus.CONFLICT, details ); } diff --git a/src/test/java/com/cf/cfteam/controllers/codeforces/integration/PlayerControllerIntegrationTest.java b/src/test/java/com/cf/cfteam/controllers/codeforces/integration/PlayerControllerIntegrationTest.java new file mode 100644 index 0000000..b7d96e9 --- /dev/null +++ b/src/test/java/com/cf/cfteam/controllers/codeforces/integration/PlayerControllerIntegrationTest.java @@ -0,0 +1,630 @@ +package com.cf.cfteam.controllers.codeforces.integration; + +import com.cf.cfteam.BaseIntegrationTest; +import com.cf.cfteam.models.entities.codeforces.Group; +import com.cf.cfteam.models.entities.codeforces.Player; +import com.cf.cfteam.models.entities.codeforces.Team; +import com.cf.cfteam.models.entities.security.Role; +import com.cf.cfteam.models.entities.security.User; +import com.cf.cfteam.repositories.jpa.codeforces.GroupRepository; +import com.cf.cfteam.repositories.jpa.codeforces.PlayerRepository; +import com.cf.cfteam.repositories.jpa.codeforces.TeamRepository; +import com.cf.cfteam.repositories.jpa.security.UserRepository; +import com.cf.cfteam.transfer.payloads.codeforces.PlayerPayload; +import com.cf.cfteam.transfer.responses.codeforces.PlayerResponse; +import com.cf.cfteam.utils.codeforces.mappers.PlayerMapper; +import com.fasterxml.jackson.core.type.TypeReference; +import com.github.benmanes.caffeine.cache.LoadingCache; +import jakarta.transaction.Transactional; +import lombok.SneakyThrows; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.http.MediaType; +import org.springframework.test.context.ActiveProfiles; + +import java.util.ArrayList; +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertAll; +import static org.mockito.Mockito.when; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; + + +@ActiveProfiles("test") +class PlayerControllerIntegrationTest extends BaseIntegrationTest { + + private static final String URI = "/api/cf/players"; + + private static final Long BAD_TEAM_ID = 9999L; + private static final Long BAD_PLAYER_ID = 9999L; + + + @Autowired + private PlayerRepository playerRepository; + + @Autowired + private TeamRepository teamRepository; + + @Autowired + private GroupRepository groupRepository; + + @Autowired + private UserRepository userRepository; + + @Autowired + private PlayerMapper playerMapper; + + @MockBean + private LoadingCache ratingCache; + + @Test + @SneakyThrows + public void getAllPlayersByTeam_notEmpty_success() { + User user = createUser("getAllPlayersByTeam_notEmpty_success"); + user = userRepository.save(user); + + Group group = createGroup(user); + group = groupRepository.save(group); + + Team team = createTeam(group); + team = teamRepository.save(team); + + Player player = createPlayer(); + player = playerRepository.save(player); + + team.setPlayers(List.of(player)); + team = teamRepository.save(team); + + when(ratingCache.get(player.getLogin())).thenReturn(0.); + + var mvcResponse = mockMvc.perform(get(URI + "/team/" + team.getId()) + .header("Authorization", userBearerToken)) + .andExpectAll( + status().isOk(), + content().contentType(MediaType.APPLICATION_JSON)) + .andReturn() + .getResponse(); + + var players = objectMapper.readValue( + mvcResponse.getContentAsString(), + new TypeReference>() { + } + ); + + assertThat(players).hasSize(1) + .contains(playerMapper.fromEntityToResponse(player)); + + deletePlayer(player); + deleteTeamFromDb(team); + deleteGroupFromDb(group); + deleteUserFromDb(user); + } + + @Test + @SneakyThrows + void getAllPlayersByTeam_shouldThrowTeamNotFoundException_whenTeamNotFoundException() { + mockMvc.perform(get(URI + "/team/" + BAD_TEAM_ID) + .header("Authorization", userBearerToken)) + .andExpectAll( + status().isNotFound(), + content().contentType(MediaType.APPLICATION_JSON), + jsonPath("$.details.id").value(BAD_TEAM_ID), + jsonPath("$.message").value("id.not_found"), + jsonPath("$.error").value("Not Found"), + jsonPath("$.status").value(404) + ); + } + + @Test + @SneakyThrows + public void getPlayerById_notEmpty() { + Player player = createPlayer(); + player = playerRepository.save(player); + when(ratingCache.get(player.getLogin())).thenReturn(0.); + + var mvcResponse = mockMvc.perform(get(URI + "/" + player.getId()) + .header("Authorization", userBearerToken)) + .andExpectAll( + status().isOk(), + content().contentType(MediaType.APPLICATION_JSON)) + .andReturn() + .getResponse(); + + var response = objectMapper.readValue(mvcResponse.getContentAsString(), PlayerResponse.class); + + assertThat(response).isEqualTo(playerMapper.fromEntityToResponse(player)); + + deletePlayer(player); + } + + @Test + @SneakyThrows + void getPlayerById_shouldThrowPlayerNotFoundException_whenPlayerNotFound() { + mockMvc.perform(get(URI + "/" + BAD_PLAYER_ID) + .header("Authorization", userBearerToken)) + .andExpectAll( + status().isNotFound(), + content().contentType(MediaType.APPLICATION_JSON), + jsonPath("$.details.id").value(BAD_TEAM_ID), + jsonPath("$.message").value("id.not_found"), + jsonPath("$.error").value("Not Found"), + jsonPath("$.status").value(404) + ); + } + + @Test + @SneakyThrows + @Transactional + public void addPlayerToTeam_success() { + + User user = createUser("addPlayerToTeam_success"); + user = userRepository.save(user); + + Group group = createGroup(user); + group = groupRepository.save(group); + + Team team = createTeam(group); + team = teamRepository.save(team); + + var payload = createPlayerPayload(); + + when(ratingCache.get(payload.login())).thenReturn(0.); + + var mvcResponse = mockMvc.perform(post(URI + "/team/" + team.getId()) + .header("Authorization", userBearerToken) + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(payload))) + .andExpectAll( + status().isOk(), + content().contentType(MediaType.APPLICATION_JSON)) + .andReturn() + .getResponse(); + + var response = objectMapper.readValue(mvcResponse.getContentAsString(), PlayerResponse.class); + var playerFromDb = playerRepository.findById(response.id()); + + assertAll( + () -> assertThat(playerFromDb).isPresent(), + () -> assertThat(response.login()).isEqualTo(payload.login()), + () -> assertThat(response.rating()).isEqualTo(0.), + () -> assertThat(playerFromDb.get().getTeams()).hasSize(1) + ); + + deletePlayer(playerFromDb.get()); + deleteTeamFromDb(team); + deleteGroupFromDb(group); + deleteUserFromDb(user); + } + + @Test + @SneakyThrows + void addPlayerToTeam_shouldThrowTeamNotFoundException_whenTeamNotFound() { + var payload = createPlayerPayload(); + + mockMvc.perform(post(URI + "/team/" + BAD_TEAM_ID) + .header("Authorization", userBearerToken) + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(payload))) + .andExpectAll( + status().isNotFound(), + content().contentType(MediaType.APPLICATION_JSON), + jsonPath("$.details.id").value(BAD_TEAM_ID), + jsonPath("$.message").value("id.not_found"), + jsonPath("$.error").value("Not Found"), + jsonPath("$.status").value(404) + ); + } + + @Test + @SneakyThrows + void addPlayerToTeam_shouldThrowPlayerAlreadyInTeamException_whenPlayerAlreadyInTeam() { + User user = createUser("addPlayerToTeam_shouldThrowPlayerAlreadyInTeamException_whenPlayerAlreadyInTeam"); + user = userRepository.save(user); + + Group group = createGroup(user); + group = groupRepository.save(group); + + Team team = createTeam(group); + team = teamRepository.save(team); + + Player player = createPlayer(); + player = playerRepository.save(player); + + team.setPlayers(List.of(player)); + team = teamRepository.save(team); + + var payload = createPlayerPayload(); + + mockMvc.perform(post(URI + "/team/" + team.getId()) + .header("Authorization", userBearerToken) + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(payload))) + .andExpectAll( + status().isConflict(), + content().contentType(MediaType.APPLICATION_JSON), + jsonPath("$.details.login").value(player.getLogin()), + jsonPath("$.message").value("player.already_in_team"), + jsonPath("$.error").value("Conflict"), + jsonPath("$.status").value(409) + ); + + deletePlayer(player); + deleteTeamFromDb(team); + deleteGroupFromDb(group); + deleteUserFromDb(user); + } + + @Test + @SneakyThrows + @Transactional + public void updatePlayerInTeam_success() { + User user = createUser("updatePlayerInTeam_success"); + user = userRepository.save(user); + + Group group = createGroup(user); + group = groupRepository.save(group); + + Team team = createTeam(group); + team = teamRepository.save(team); + + Player player = createPlayer(); + player = playerRepository.save(player); + + team.setPlayers(new ArrayList<>(List.of(player))); + team = teamRepository.save(team); + + var payload = createPlayerPayload("awoo"); + + when(ratingCache.get(payload.login())).thenReturn(0.); + + var mvcResponse = mockMvc.perform(put(URI + "/players/" + player.getId() + + "/teams/" + team.getId()) + .header("Authorization", userBearerToken) + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(payload))) + .andExpectAll( + status().isOk(), + content().contentType(MediaType.APPLICATION_JSON)) + .andReturn() + .getResponse(); + + + var response = objectMapper.readValue(mvcResponse.getContentAsString(), PlayerResponse.class); + var playerFromDb = playerRepository.findById(response.id()); + + assertAll( + () -> assertThat(playerFromDb).isPresent(), + () -> assertThat(response.login()).isEqualTo(payload.login()), + () -> assertThat(response.rating()).isEqualTo(0.), + () -> assertThat(playerFromDb.get().getTeams()).hasSize(1) + ); + + deletePlayer(player); + deletePlayer(playerFromDb.get()); + deleteTeamFromDb(team); + deleteGroupFromDb(group); + deleteUserFromDb(user); + } + + @Test + @SneakyThrows + void updatePlayerInTeam_shouldThrowPlayerNotFoundException_whenPlayerNotFound() { + var payload = createPlayerPayload(); + + var mvcResponse = mockMvc.perform(put(URI + "/players/" + BAD_PLAYER_ID + + "/teams/" + 1L) + .header("Authorization", userBearerToken) + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(payload))) + .andExpectAll( + status().isNotFound(), + content().contentType(MediaType.APPLICATION_JSON), + jsonPath("$.details.id").value(BAD_PLAYER_ID), + jsonPath("$.message").value("id.not_found"), + jsonPath("$.error").value("Not Found"), + jsonPath("$.status").value(404) + ); + } + + + @Test + @SneakyThrows + void updatePlayerInTeam_shouldThrowTeamNotFoundException_whenTeamNotFound() { + Player player = createPlayer(); + player = playerRepository.save(player); + + var payload = createPlayerPayload(); + + var mvcResponse = mockMvc.perform(put(URI + "/players/" + player.getId() + + "/teams/" + BAD_TEAM_ID) + .header("Authorization", userBearerToken) + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(payload))) + .andExpectAll( + status().isNotFound(), + content().contentType(MediaType.APPLICATION_JSON), + jsonPath("$.details.id").value(BAD_TEAM_ID), + jsonPath("$.message").value("id.not_found"), + jsonPath("$.error").value("Not Found"), + jsonPath("$.status").value(404) + ); + + deletePlayer(player); + } + + @Test + @SneakyThrows + void updatePlayerInTeam_shouldThrowPlayerNotFromTeamException_whenPlayerNotFromTeam() { + User user = createUser("updatePlayerInTeam_shouldThrowPlayerNotFromTeamException_whenPlayerNotFromTeam"); + user = userRepository.save(user); + + Group group = createGroup(user); + group = groupRepository.save(group); + + Team team = createTeam(group); + team = teamRepository.save(team); + + Player player = createPlayer(); + player = playerRepository.save(player); + + var payload = createPlayerPayload(); + + var mvcResponse = mockMvc.perform(put(URI + "/players/" + player.getId() + + "/teams/" + team.getId()) + .header("Authorization", userBearerToken) + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(payload))) + .andExpectAll( + status().isConflict(), + content().contentType(MediaType.APPLICATION_JSON), + jsonPath("$.details.playerId").value(player.getId()), + jsonPath("$.details.teamId").value(team.getId()), + jsonPath("$.message").value("player.not_from_team"), + jsonPath("$.error").value("Conflict"), + jsonPath("$.status").value(409) + ); + + deletePlayer(player); + deleteTeamFromDb(team); + deleteGroupFromDb(group); + deleteUserFromDb(user); + } + + @Test + @SneakyThrows + @Transactional + public void deletePlayerFromTeam_success() { + User user = createUser("deletePlayerFromTeam"); + user = userRepository.save(user); + + Group group = createGroup(user); + group = groupRepository.save(group); + + Team team = createTeam(group); + team = teamRepository.save(team); + + Player player = createPlayer(); + player = playerRepository.save(player); + + team.setPlayers(new ArrayList<>(List.of(player))); + team = teamRepository.save(team); + + mockMvc.perform(delete(URI + "/players/" + player.getId() + + "/teams/" + team.getId()) + .header("Authorization", userBearerToken)) + .andExpectAll( + status().isNoContent(), + content().string("") + ); + + var teamFromDb = teamRepository.findById(team.getId()); + var playerFromDb = playerRepository.findById(player.getId()); + + assertAll( + () -> assertThat(teamFromDb).isPresent(), + () -> assertThat(teamFromDb.get().getPlayers()).isEmpty(), + () -> assertThat(playerFromDb).isPresent(), + () -> assertThat(playerFromDb.get().getTeams()).isEmpty() + ); + + deletePlayer(player); + deleteTeamFromDb(team); + deleteGroupFromDb(group); + deleteUserFromDb(user); + } + + @Test + @SneakyThrows + void deletePlayerFromTeam_shouldThrowPlayerNotFoundException_whenPlayerNotFound() { + mockMvc.perform(delete(URI + "/players/" + BAD_PLAYER_ID+ + "/teams/" + 1L) + .header("Authorization", userBearerToken)) + .andExpectAll( + status().isNotFound(), + content().contentType(MediaType.APPLICATION_JSON), + jsonPath("$.details.id").value(BAD_TEAM_ID), + jsonPath("$.message").value("id.not_found"), + jsonPath("$.error").value("Not Found"), + jsonPath("$.status").value(404) + ); + } + + @Test + @SneakyThrows + void deletePlayerFromTeam_shouldThrowTeamNotFoundException_whenTeamNotFound() { + Player player = createPlayer(); + player = playerRepository.save(player); + + + mockMvc.perform(delete(URI + "/players/" + BAD_PLAYER_ID+ + "/teams/" + BAD_TEAM_ID) + .header("Authorization", userBearerToken)) + .andExpectAll( + status().isNotFound(), + content().contentType(MediaType.APPLICATION_JSON), + jsonPath("$.details.id").value(BAD_TEAM_ID), + jsonPath("$.message").value("id.not_found"), + jsonPath("$.error").value("Not Found"), + jsonPath("$.status").value(404) + ); + + deletePlayer(player); + } + + @Test + @SneakyThrows + @Transactional + public void deleteAllPlayersFromTeam_success() { + User user = createUser("deleteAllTeamsByGroup_success"); + user = userRepository.save(user); + + Group group = createGroup(user); + group = groupRepository.save(group); + + Team team = createTeam(group); + + Player player1 = createPlayer("p1"); + Player player2 = createPlayer("p2"); + + player1.setTeams(new ArrayList<>(List.of(team))); + player2.setTeams(new ArrayList<>(List.of(team))); + + player1 = playerRepository.save(player1); + player2 = playerRepository.save(player2); + + mockMvc.perform(delete(URI + "/team/" + team.getId()) + .header("Authorization", userBearerToken)) + .andExpectAll( + status().isNoContent(), + content().string("") + ); + + var teamFromDb = teamRepository.findById(team.getId()); + var playerFromDb1 = playerRepository.findById(player1.getId()); + var playerFromDb2 = playerRepository.findById(player2.getId()); + + assertAll( + () -> assertThat(teamFromDb).isPresent(), + () -> assertThat(playerFromDb1).isPresent(), + () -> assertThat(playerFromDb2).isPresent(), + () -> assertThat(teamFromDb.get().getPlayers()).isEmpty(), + () -> assertThat(playerFromDb1.get().getTeams()).hasSize(1), + () -> assertThat(playerFromDb2.get().getTeams()).hasSize(1) + ); + + var mvcResponse = mockMvc.perform(get(URI + "/team/" + team.getId()) + .header("Authorization", userBearerToken)) + .andExpectAll( + status().isOk(), + content().contentType(MediaType.APPLICATION_JSON)) + .andReturn() + .getResponse(); + + var players = objectMapper.readValue( + mvcResponse.getContentAsString(), + new TypeReference>() { + } + ); + + assertThat(players).isEmpty(); + + deletePlayer(player1); + deletePlayer(player2); + deleteTeamFromDb(team); + deleteGroupFromDb(group); + deleteUserFromDb(user);; + } + + @Test + @SneakyThrows + void deleteAllPlayersFromTeam_shouldThrowTeamNotFoundException_whenTeamNotFound() { + mockMvc.perform(delete(URI + "/team/" + BAD_TEAM_ID) + .header("Authorization", userBearerToken)) + .andExpectAll( + status().isNotFound(), + content().contentType(MediaType.APPLICATION_JSON), + jsonPath("$.details.id").value(BAD_TEAM_ID), + jsonPath("$.message").value("id.not_found"), + jsonPath("$.error").value("Not Found"), + jsonPath("$.status").value(404) + ); + } + + + private PlayerPayload createPlayerPayload() { + return PlayerPayload.builder() + .login("tourist") + .build(); + } + + private PlayerPayload createPlayerPayload(String login) { + return PlayerPayload.builder() + .login(login) + .build(); + } + + private User createUser(String login) { + return User.builder() + .name("Team controller User name") + .login(login) + .hashedPassword("Password") + .role(Role.USER) + .build(); + } + + private Group createGroup(User user) { + return Group.builder() + .name("Test Group") + .description("Test description") + .user(user) + .build(); + } + + private Team createTeam(Group group) { + return Team.builder() + .name("team") + .description("team description") + .group(group) + .build(); + } + + private Player createPlayer() { + return Player.builder() + .login("tourist") + .build(); + } + + private Player createPlayer(String login) { + return Player.builder() + .login(login) + .build(); + } + + private void deleteTeamFromDb(Team team) { + teamRepository.delete(team); + } + + private void deleteGroupFromDb(Group group) { + groupRepository.delete(group); + } + + private void deleteUserFromDb(User user) { + userRepository.delete(user); + } + + private void deletePlayer(Player player) { + for (Team team : player.getTeams()) { + team.getPlayers().remove(player); + } + + var teams = List.copyOf(player.getTeams()); + player.setTeams(List.of()); + + teamRepository.saveAll(teams); + playerRepository.delete(player); + } +} \ No newline at end of file