diff --git a/server/build.gradle b/server/build.gradle index b941426..5ccf8d5 100644 --- a/server/build.gradle +++ b/server/build.gradle @@ -78,3 +78,7 @@ bootJar { // Spring Rest Docs into 'static/docs' } } + +test { + exclude '**/*' +} \ No newline at end of file diff --git a/server/src/main/java/com/codestates/Pre038Application.java b/server/src/main/java/com/codestates/Pre038Application.java index 747354e..46ff691 100644 --- a/server/src/main/java/com/codestates/Pre038Application.java +++ b/server/src/main/java/com/codestates/Pre038Application.java @@ -4,7 +4,6 @@ import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.data.jpa.repository.config.EnableJpaAuditing; -@EnableJpaAuditing @SpringBootApplication public class Pre038Application { diff --git a/server/src/main/java/com/codestates/answer/controller/AnswerController.java b/server/src/main/java/com/codestates/answer/controller/AnswerController.java index c5acde0..d502f5f 100644 --- a/server/src/main/java/com/codestates/answer/controller/AnswerController.java +++ b/server/src/main/java/com/codestates/answer/controller/AnswerController.java @@ -18,8 +18,10 @@ import javax.validation.constraints.Positive; import java.util.List; -@CrossOrigin(origins = {"http://pre-project-038-client.s3-website.ap-northeast-2.amazonaws.com", - "http://ec2-13-125-208-244.ap-northeast-2.compute.amazonaws.com:8080"}) +@CrossOrigin(origins = {"http://localhost:3000", + "http://pre-project-038-client.s3-website.ap-northeast-2.amazonaws.com", + "http://seb40-pre-038.vercel.app", + "http://ec2-13-125-208-244.ap-northeast-2.compute.amazonaws.com:8080"}, allowCredentials = "true") @RestController @Validated @RequestMapping("/api") @@ -69,18 +71,6 @@ public ResponseEntity voteAnswer(@PathVariable("answer-id") @Positive long answe HttpStatus.OK); } - /*@PatchMapping("/{answer-id}/best") // QuestionController에서 동작 - public ResponseEntity patchStatus(@PathVariable("answer-id") @Positive long answerId, - @Valid @RequestBody AnswerBestDto answerBestDto) { - answerBestDto.setAnswerId(answerId); - - Answer answer = answerService.updateStatus(mapper.answerBestDtoToAnswer(answerBestDto)); - - return new ResponseEntity<>( - new SingleResponseDto<>(mapper.answerToAnswerResponseDto(answer)), - HttpStatus.OK); - }*/ - @GetMapping("/questions/{question-id}/answers") public ResponseEntity getAnswers(@PathVariable("question-id") @Positive long questionId) { List answers = answerService.findAnswers(questionId); diff --git a/server/src/main/java/com/codestates/answer/dto/AnswerPostDto.java b/server/src/main/java/com/codestates/answer/dto/AnswerPostDto.java index 2936ea5..45e3caa 100644 --- a/server/src/main/java/com/codestates/answer/dto/AnswerPostDto.java +++ b/server/src/main/java/com/codestates/answer/dto/AnswerPostDto.java @@ -5,7 +5,6 @@ import lombok.NoArgsConstructor; import javax.validation.constraints.NotEmpty; -import javax.validation.constraints.Positive; import javax.validation.constraints.Size; @@ -16,7 +15,4 @@ public class AnswerPostDto { @NotEmpty(message = "내용을 입력하셔야 합니다.") @Size(min = 20, message = "20자 이상 입력하셔야 합니다.") private String body; - - /*@Positive - private long userId;*/ } diff --git a/server/src/main/java/com/codestates/answer/dto/AnswerResponseDto.java b/server/src/main/java/com/codestates/answer/dto/AnswerResponseDto.java index f6569f7..4292a9e 100644 --- a/server/src/main/java/com/codestates/answer/dto/AnswerResponseDto.java +++ b/server/src/main/java/com/codestates/answer/dto/AnswerResponseDto.java @@ -2,7 +2,6 @@ import com.codestates.answer.entity.Answer; import com.codestates.comment.CommentDto; -import com.codestates.comment.entity.Comment; import com.codestates.user.dto.UserDto; import lombok.*; diff --git a/server/src/main/java/com/codestates/answer/dto/AnswerVoteDto.java b/server/src/main/java/com/codestates/answer/dto/AnswerVoteDto.java index 63e796b..15af021 100644 --- a/server/src/main/java/com/codestates/answer/dto/AnswerVoteDto.java +++ b/server/src/main/java/com/codestates/answer/dto/AnswerVoteDto.java @@ -2,15 +2,10 @@ import lombok.Getter; -import javax.validation.constraints.Positive; - @Getter public class AnswerVoteDto { private long answerId; -/* @Positive - private long userId;*/ - private int vote; public void setAnswerId(long answerId) { diff --git a/server/src/main/java/com/codestates/answer/entity/Answer.java b/server/src/main/java/com/codestates/answer/entity/Answer.java index fc32ff8..1d974de 100644 --- a/server/src/main/java/com/codestates/answer/entity/Answer.java +++ b/server/src/main/java/com/codestates/answer/entity/Answer.java @@ -1,6 +1,5 @@ package com.codestates.answer.entity; -import com.codestates.audit.Auditable; import com.codestates.user.entity.User; import com.codestates.question.Question; import com.codestates.comment.entity.Comment; @@ -10,8 +9,6 @@ import lombok.Getter; import lombok.NoArgsConstructor; import lombok.Setter; -import org.springframework.data.annotation.CreatedDate; -import org.springframework.data.annotation.LastModifiedDate; import javax.persistence.*; import java.time.LocalDateTime; diff --git a/server/src/main/java/com/codestates/answer/mapper/AnswerMapper.java b/server/src/main/java/com/codestates/answer/mapper/AnswerMapper.java index d3acd95..51d6159 100644 --- a/server/src/main/java/com/codestates/answer/mapper/AnswerMapper.java +++ b/server/src/main/java/com/codestates/answer/mapper/AnswerMapper.java @@ -7,7 +7,6 @@ import com.codestates.user.dto.UserDto; import com.codestates.user.entity.User; import com.codestates.question.Question; -import com.codestates.user.service.UserService; import org.mapstruct.Mapper; import java.util.List; diff --git a/server/src/main/java/com/codestates/answer/repository/AnswerRepository.java b/server/src/main/java/com/codestates/answer/repository/AnswerRepository.java index 3cd58a2..efaef9d 100644 --- a/server/src/main/java/com/codestates/answer/repository/AnswerRepository.java +++ b/server/src/main/java/com/codestates/answer/repository/AnswerRepository.java @@ -1,7 +1,6 @@ package com.codestates.answer.repository; import com.codestates.answer.entity.Answer; -import org.springframework.data.domain.Sort; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Query; diff --git a/server/src/main/java/com/codestates/answer/service/AnswerService.java b/server/src/main/java/com/codestates/answer/service/AnswerService.java index 7c9ce28..6f907b1 100644 --- a/server/src/main/java/com/codestates/answer/service/AnswerService.java +++ b/server/src/main/java/com/codestates/answer/service/AnswerService.java @@ -7,9 +7,6 @@ import com.codestates.question.Question; import com.codestates.user.entity.User; import com.codestates.user.service.UserService; -import org.springframework.data.domain.Page; -import org.springframework.data.domain.PageRequest; -import org.springframework.data.domain.Sort; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; diff --git a/server/src/main/java/com/codestates/audit/Auditable.java b/server/src/main/java/com/codestates/audit/Auditable.java deleted file mode 100644 index 2217bc1..0000000 --- a/server/src/main/java/com/codestates/audit/Auditable.java +++ /dev/null @@ -1,24 +0,0 @@ -package com.codestates.audit; - -import lombok.Getter; -import org.springframework.data.annotation.CreatedDate; -import org.springframework.data.annotation.LastModifiedDate; -import org.springframework.data.jpa.domain.support.AuditingEntityListener; - -import javax.persistence.Column; -import javax.persistence.EntityListeners; -import javax.persistence.MappedSuperclass; -import java.time.LocalDateTime; - -@Getter -@MappedSuperclass -@EntityListeners(AuditingEntityListener.class) -public class Auditable { -// @CreatedDate -// @Column(name = "CREATED_AT", updatable = false) -// private LocalDateTime createdAt; -// -// @LastModifiedDate -// @Column(name = "LAST_MODIFIED_AT") -// private LocalDateTime modifiedAt; -} diff --git a/server/src/main/java/com/codestates/auth/filter/JwtAuthenticationFilter.java b/server/src/main/java/com/codestates/auth/filter/JwtAuthenticationFilter.java index 933b6d5..f80641e 100644 --- a/server/src/main/java/com/codestates/auth/filter/JwtAuthenticationFilter.java +++ b/server/src/main/java/com/codestates/auth/filter/JwtAuthenticationFilter.java @@ -9,6 +9,7 @@ import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.core.Authentication; import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; +import org.springframework.web.bind.annotation.CrossOrigin; import javax.servlet.FilterChain; import javax.servlet.ServletException; @@ -28,6 +29,7 @@ public JwtAuthenticationFilter(AuthenticationManager authenticationManager, JwtT this.jwtTokenizer = jwtTokenizer; } + @CrossOrigin(exposedHeaders = "Authorization") @SneakyThrows @Override public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) { diff --git a/server/src/main/java/com/codestates/comment/CommentController.java b/server/src/main/java/com/codestates/comment/CommentController.java index a7b947f..445633c 100644 --- a/server/src/main/java/com/codestates/comment/CommentController.java +++ b/server/src/main/java/com/codestates/comment/CommentController.java @@ -16,8 +16,10 @@ import javax.validation.constraints.Positive; import java.util.List; -@CrossOrigin(origins = {"http://pre-project-038-client.s3-website.ap-northeast-2.amazonaws.com", - "http://ec2-13-125-208-244.ap-northeast-2.compute.amazonaws.com:8080"}) +@CrossOrigin(origins = {"http://localhost:3000", + "http://pre-project-038-client.s3-website.ap-northeast-2.amazonaws.com", + "http://seb40-pre-038.vercel.app", + "http://ec2-13-125-208-244.ap-northeast-2.compute.amazonaws.com:8080"}, allowCredentials = "true") @Validated @RestController @RequestMapping("/api") diff --git a/server/src/main/java/com/codestates/comment/entity/Comment.java b/server/src/main/java/com/codestates/comment/entity/Comment.java index 05d9d30..5010608 100644 --- a/server/src/main/java/com/codestates/comment/entity/Comment.java +++ b/server/src/main/java/com/codestates/comment/entity/Comment.java @@ -1,7 +1,6 @@ package com.codestates.comment.entity; import com.codestates.answer.entity.Answer; -import com.codestates.audit.Auditable; import com.codestates.user.entity.User; import com.codestates.question.Question; import com.fasterxml.jackson.annotation.JsonBackReference; @@ -20,7 +19,7 @@ @NoArgsConstructor @AllArgsConstructor @Entity -public class Comment extends Auditable { +public class Comment { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) diff --git a/server/src/main/java/com/codestates/configuration/SecurityConfiguration.java b/server/src/main/java/com/codestates/configuration/SecurityConfiguration.java index e65f25c..2eab93b 100644 --- a/server/src/main/java/com/codestates/configuration/SecurityConfiguration.java +++ b/server/src/main/java/com/codestates/configuration/SecurityConfiguration.java @@ -74,19 +74,22 @@ public PasswordEncoder passwordEncoder() { return PasswordEncoderFactories.createDelegatingPasswordEncoder(); } -// @Bean -// CorsConfigurationSource corsConfigurationSource() { -// CorsConfiguration configuration = new CorsConfiguration(); -// configuration.addAllowedOrigin("*"); -// configuration.addAllowedMethod("*"); -// configuration.addAllowedHeader("*"); -// configuration.setAllowCredentials(true); -//// configuration.setAllowedOrigins(Arrays.asList("*")); -//// configuration.setAllowedMethods(Arrays.asList("GET","POST", "PATCH", "DELETE")); -// UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); -// source.registerCorsConfiguration("/**", configuration); -// return source; -// } + @Bean + CorsConfigurationSource corsConfigurationSource() { + CorsConfiguration configuration = new CorsConfiguration(); + configuration.setAllowedOrigins(Arrays.asList("http://localhost:3000", + "http://pre-project-038-client.s3-website.ap-northeast-2.amazonaws.com", + "http://seb40-pre-038.vercel.app")); + configuration.addAllowedMethod("*"); + configuration.addAllowedHeader("*"); + configuration.setExposedHeaders(Arrays.asList("Authorization")); + configuration.setAllowCredentials(true); +// configuration.setAllowedOrigins(Arrays.asList("*")); +// configuration.setAllowedMethods(Arrays.asList("GET","POST", "PATCH", "DELETE")); + UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); + source.registerCorsConfiguration("/**", configuration); + return source; + } public class CustomFilterConfigurer extends AbstractHttpConfigurer { @Override diff --git a/server/src/main/java/com/codestates/question/Question.java b/server/src/main/java/com/codestates/question/Question.java index 2683dc3..b73b866 100644 --- a/server/src/main/java/com/codestates/question/Question.java +++ b/server/src/main/java/com/codestates/question/Question.java @@ -1,15 +1,12 @@ package com.codestates.question; import com.codestates.answer.entity.Answer; -import com.codestates.audit.Auditable; import com.codestates.user.entity.User; import com.codestates.comment.entity.Comment; import com.codestates.vote.QuestionVote.QuestionVote; import com.fasterxml.jackson.annotation.JsonBackReference; import com.fasterxml.jackson.annotation.JsonManagedReference; import lombok.*; -import org.springframework.data.annotation.CreatedDate; -import org.springframework.data.annotation.LastModifiedDate; import javax.persistence.*; import java.time.LocalDateTime; @@ -77,11 +74,9 @@ public void addComment(Comment comment) { comments.add(comment); } - //@CreatedDate @Column(nullable = false, updatable = false, name = "CREATED_AT") private LocalDateTime createdAt = LocalDateTime.now(); - //@LastModifiedDate @Column(nullable = false, name = "LAST_MODIFIED_AT") private LocalDateTime modifiedAt = LocalDateTime.now(); diff --git a/server/src/main/java/com/codestates/question/QuestionController.java b/server/src/main/java/com/codestates/question/QuestionController.java index 7151432..31f30db 100644 --- a/server/src/main/java/com/codestates/question/QuestionController.java +++ b/server/src/main/java/com/codestates/question/QuestionController.java @@ -22,8 +22,10 @@ import java.util.Objects; import java.util.stream.Collectors; -@CrossOrigin(origins = {"http://pre-project-038-client.s3-website.ap-northeast-2.amazonaws.com", - "http://ec2-13-125-208-244.ap-northeast-2.compute.amazonaws.com:8080"}) +@CrossOrigin(origins = {"http://localhost:3000", + "http://pre-project-038-client.s3-website.ap-northeast-2.amazonaws.com", + "http://seb40-pre-038.vercel.app", + "http://ec2-13-125-208-244.ap-northeast-2.compute.amazonaws.com:8080"}, allowCredentials = "true") @Validated @RestController @RequestMapping("/api/questions") diff --git a/server/src/main/java/com/codestates/search/SearchController.java b/server/src/main/java/com/codestates/search/SearchController.java index 4f52819..e89df94 100644 --- a/server/src/main/java/com/codestates/search/SearchController.java +++ b/server/src/main/java/com/codestates/search/SearchController.java @@ -9,15 +9,16 @@ import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; -import javax.validation.Valid; import javax.validation.constraints.NotBlank; import javax.validation.constraints.Positive; import java.io.UnsupportedEncodingException; import java.net.URLDecoder; import java.util.List; -@CrossOrigin(origins = {"http://pre-project-038-client.s3-website.ap-northeast-2.amazonaws.com", - "http://ec2-13-125-208-244.ap-northeast-2.compute.amazonaws.com:8080"}) +@CrossOrigin(origins = {"http://localhost:3000", + "http://pre-project-038-client.s3-website.ap-northeast-2.amazonaws.com", + "http://seb40-pre-038.vercel.app", + "http://ec2-13-125-208-244.ap-northeast-2.compute.amazonaws.com:8080"}, allowCredentials = "true") @RestController @Validated @RequestMapping("/api/search") diff --git a/server/src/main/java/com/codestates/search/SearchRepository.java b/server/src/main/java/com/codestates/search/SearchRepository.java index fd046d5..539d009 100644 --- a/server/src/main/java/com/codestates/search/SearchRepository.java +++ b/server/src/main/java/com/codestates/search/SearchRepository.java @@ -1,23 +1,9 @@ package com.codestates.search; -//import com.codestates.user.entity.user; import com.codestates.question.Question; -import com.codestates.user.entity.User; -import org.springframework.data.domain.Page; -import org.springframework.data.domain.Pageable; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.JpaSpecificationExecutor; -import org.springframework.data.jpa.repository.Query; public interface SearchRepository extends JpaRepository, JpaSpecificationExecutor { - /*@Query(nativeQuery = true, - value = "select * from Answer a where a.status > 0 and a.question_id = :questionId" - + " order by status asc, vote desc, answer_id desc" - )*/ - /*Page findAllByTitleContainingOrProblemContainingOrExpectContaining(String title, String problem, String expect, Pageable pageable); - - Page findAllByUser(User user, Pageable pageable); - - Page findAllByTagList(String tagBody, Pageable pageable);*/ } diff --git a/server/src/main/java/com/codestates/search/SearchService.java b/server/src/main/java/com/codestates/search/SearchService.java index 8cb84d5..2815a59 100644 --- a/server/src/main/java/com/codestates/search/SearchService.java +++ b/server/src/main/java/com/codestates/search/SearchService.java @@ -1,6 +1,5 @@ package com.codestates.search; -import com.codestates.user.entity.User; import com.codestates.user.service.UserService; import com.codestates.question.Question; import org.springframework.data.domain.Page; @@ -10,7 +9,6 @@ import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; -import java.lang.annotation.Target; import java.util.ArrayList; import java.util.Arrays; import java.util.List; @@ -28,32 +26,34 @@ public SearchService(SearchRepository searchRepository, UserService userService) public Page findContent(String all, String tab, int page, int size) { String tag = null; - long userId = 0; + String userNickName = null; List contents = new ArrayList<>(); - //all = all.replaceAll( "[^\uAC00-\uD7A30-9a-zA-Z\\[\\]\\s]", ""); // 특수문자 제거 + //all = all.replaceAll( "[^\uAC00-\uD7A30-9a-zA-Z\\[\\]\\s]", ""); // 특수문자 제거 ([,] 빼고) List findAll = Arrays.asList(all.split(" ")); for(String find : findAll) { + System.out.println("find:"+find); if(find.length() >= 3 && find.charAt(0) == '[' && find.charAt(find.length() - 1) == ']') // 태그 검색일 경우 tag = find.substring(1, find.length() - 1); else if (find.length() >= 6 && find.substring(0,5).equals("user:")) // 유저 검색일 경우 - userId = Long.parseLong(find.substring(5)); + userNickName = find.substring(5); else contents.add(find); // 일반 검색일 경우 keyword로 나누기 } + System.out.println("TAG:"+tag + ",USER:"+userNickName); - return findTagUserContent(tag, userId, contents, tab, page, size); // 검색 + return findTagUserContent(tag, userNickName, contents, tab, page, size); // 검색 } - private Page findTagUserContent(String tag, long userId, List contents, String tab, int page, int size) { // 질문 내용 검색 + private Page findTagUserContent(String tag, String userNickName, List contents, String tab, int page, int size) { // 질문 내용 검색 Specification spec = null; if(tag != null) // tag 검색이 있을 경우 spec = (spec == null? SearchSpecification.containsTag(tag) : spec.and(SearchSpecification.containsTag(tag))); - if(userId != 0) { // user 검색이 있을 경우 + if(userNickName != null) { // user 검색이 있을 경우 //User user = userService.findVerifiedUser(userId); - spec = (spec == null ? SearchSpecification.equalToUser(userId) : spec.and(SearchSpecification.equalToUser(userId))); + spec = (spec == null ? SearchSpecification.equalToUser(userNickName) : spec.and(SearchSpecification.equalToUser(userNickName))); } if(contents != null) { // 검색어가 있을 경우 diff --git a/server/src/main/java/com/codestates/search/SearchSpecification.java b/server/src/main/java/com/codestates/search/SearchSpecification.java index 37e56d6..e38cbb5 100644 --- a/server/src/main/java/com/codestates/search/SearchSpecification.java +++ b/server/src/main/java/com/codestates/search/SearchSpecification.java @@ -1,10 +1,8 @@ package com.codestates.search; import com.codestates.question.Question; -import com.codestates.user.entity.User; import org.springframework.data.jpa.domain.Specification; -import javax.persistence.criteria.Expression; import javax.persistence.criteria.Predicate; public class SearchSpecification { @@ -18,17 +16,13 @@ public static Specification containsTag(String tag) { }; } - public static Specification equalToUser(long userId) { + public static Specification equalToUser(String userNickName) { return (root, query, criteriaBuilder) -> - criteriaBuilder.equal(root.get("user").get("userId"), userId); + criteriaBuilder.equal(root.get("user").get("nickName"), userNickName); } public static Specification containsTitleProblemExpect(String searchWord) { return (root, query, criteriaBuilder) -> { - Expression titleLowerCase = criteriaBuilder.lower(root.get("title")); - Expression problemLowerCase = criteriaBuilder.lower(root.get("problem")); - Expression expectLowerCase = criteriaBuilder.lower(root.get("expect")); - Predicate titleContains = criteriaBuilder.like(root.get("title"), "%" + searchWord + "%"); Predicate problemContains = criteriaBuilder.like(root.get("problem"), "%" + searchWord + "%"); Predicate expectContains = criteriaBuilder.like(root.get("expect"), "%" + searchWord + "%"); diff --git a/server/src/main/java/com/codestates/user/assembler/UserAssembler.java b/server/src/main/java/com/codestates/user/assembler/UserAssembler.java index e718ed6..e6aafb8 100644 --- a/server/src/main/java/com/codestates/user/assembler/UserAssembler.java +++ b/server/src/main/java/com/codestates/user/assembler/UserAssembler.java @@ -1,7 +1,7 @@ package com.codestates.user.assembler; -import com.codestates.user.entity.User; import com.codestates.user.controller.UserController; +import com.codestates.user.dto.UserDto; import org.springframework.hateoas.EntityModel; import org.springframework.hateoas.server.RepresentationModelAssembler; import org.springframework.hateoas.server.mvc.WebMvcLinkBuilder; @@ -11,12 +11,12 @@ import static org.springframework.hateoas.server.mvc.WebMvcLinkBuilder.methodOn; @Component -public class UserAssembler implements RepresentationModelAssembler > { +public class UserAssembler implements RepresentationModelAssembler > { @Override - public EntityModel toModel(User user) { - return EntityModel.of(user, - WebMvcLinkBuilder.linkTo(methodOn(UserController.class).getUser(user.getUserId())).withSelfRel(), + public EntityModel toModel(UserDto.Response response) { + return EntityModel.of(response, + WebMvcLinkBuilder.linkTo(methodOn(UserController.class).getUser(response.getUserId())).withSelfRel(), linkTo(methodOn(UserController.class).getUsers()).withRel("users")); } diff --git a/server/src/main/java/com/codestates/user/controller/UserController.java b/server/src/main/java/com/codestates/user/controller/UserController.java index 2ef449e..08f9d83 100644 --- a/server/src/main/java/com/codestates/user/controller/UserController.java +++ b/server/src/main/java/com/codestates/user/controller/UserController.java @@ -19,8 +19,10 @@ import static org.springframework.hateoas.server.mvc.WebMvcLinkBuilder.linkTo; import static org.springframework.hateoas.server.mvc.WebMvcLinkBuilder.methodOn; -@CrossOrigin(origins = {"http://pre-project-038-client.s3-website.ap-northeast-2.amazonaws.com", - "http://ec2-13-125-208-244.ap-northeast-2.compute.amazonaws.com:8080"}) +@CrossOrigin(origins = {"http://localhost:3000", + "http://pre-project-038-client.s3-website.ap-northeast-2.amazonaws.com", + "http://seb40-pre-038.vercel.app", + "http://ec2-13-125-208-244.ap-northeast-2.compute.amazonaws.com:8080"}, allowCredentials = "true") @RestController @RequestMapping("/api/users") @Validated @@ -38,14 +40,16 @@ public UserController(UserService userService, UserAssembler assembler, UserMapp } @GetMapping("/{id}") - public EntityModel getUser(@PathVariable long id) { + public EntityModel getUser(@PathVariable long id) { User user = userService.findOne(id); - return assembler.toModel(user); + UserDto.Response response = mapper.userToUserResponseDto(user); + return assembler.toModel(response); } @GetMapping - public CollectionModel> getUsers() { - List> users = userService.findAll().stream() + public CollectionModel> getUsers() { + List> users = userService.findAll().stream() + .map(mapper::userToUserResponseDto) .map(assembler::toModel) .collect(Collectors.toList()); @@ -55,17 +59,18 @@ public CollectionModel> getUsers() { @PostMapping public ResponseEntity postUser(@Valid @RequestBody UserDto.Post requestBody) { - // Test - using Mapper User user = mapper.userPostToUser(requestBody); - EntityModel entityModel = assembler.toModel(userService.createOne(user)); + UserDto.Response response = mapper.userToUserResponseDto(userService.createOne(user)); + EntityModel entityModel = assembler.toModel(response); return ResponseEntity .created(entityModel.getRequiredLink(IanaLinkRelations.SELF).toUri()) .body(entityModel); } @PatchMapping("/{id}") - public ResponseEntity patchUser(@RequestBody User user, @PathVariable long id) { - EntityModel entityModel = assembler.toModel(userService.updateOne(user, id)); + public ResponseEntity patchUser(@Valid @RequestBody UserDto.Patch requestBody, @PathVariable long id) { + User user = userService.updateOne(mapper.userPatchDtoToUser(requestBody), id); + EntityModel entityModel = assembler.toModel(mapper.userToUserResponseDto(user)); return ResponseEntity .created(entityModel.getRequiredLink(IanaLinkRelations.SELF).toUri()) .body(entityModel); diff --git a/server/src/main/java/com/codestates/user/dto/UserDto.java b/server/src/main/java/com/codestates/user/dto/UserDto.java index 26cbf9d..b3cc74d 100644 --- a/server/src/main/java/com/codestates/user/dto/UserDto.java +++ b/server/src/main/java/com/codestates/user/dto/UserDto.java @@ -1,5 +1,6 @@ package com.codestates.user.dto; +import com.codestates.user.entity.User; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Getter; @@ -8,9 +9,6 @@ import javax.validation.constraints.Email; import javax.validation.constraints.NotBlank; - -// Not used yet - public class UserDto { @Getter @@ -18,7 +16,7 @@ public class UserDto { public static class Post { @NotBlank(message = "NickName cannot be empty") - private String nickName; // "Display name": Optional + private String nickName; @NotBlank(message = "Email cannot be empty.") @Email @@ -29,6 +27,29 @@ public static class Post { } + @Getter + @AllArgsConstructor + public static class Patch { + + private Long userId; + + @NotBlank(message = "NickName cannot be empty.") + private String nickName; + + @NotBlank(message = "Email cannot be empty.") + @Email + private String email; + + @NotBlank + private String password; + + private User.UserStatus userStatus; + + public void setUserId(Long userId) { + this.userId = userId; + } + } + @Getter @Setter @Builder @@ -38,5 +59,6 @@ public static class Response { private String nickName; private String email; private int reputation; +// private User.UserStatus userStatus; } } diff --git a/server/src/main/java/com/codestates/user/entity/User.java b/server/src/main/java/com/codestates/user/entity/User.java index 24e4c32..96a164a 100644 --- a/server/src/main/java/com/codestates/user/entity/User.java +++ b/server/src/main/java/com/codestates/user/entity/User.java @@ -1,7 +1,6 @@ package com.codestates.user.entity; import com.codestates.answer.entity.Answer; -import com.codestates.audit.Auditable; import com.codestates.comment.entity.Comment; import com.codestates.question.Question; import com.fasterxml.jackson.annotation.JsonIgnore; @@ -20,7 +19,7 @@ @NoArgsConstructor @Entity @Table(name = "USERS") -public class User extends Auditable { +public class User { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) diff --git a/server/src/main/java/com/codestates/user/mapper/UserMapper.java b/server/src/main/java/com/codestates/user/mapper/UserMapper.java index e43bf5b..2a801bb 100644 --- a/server/src/main/java/com/codestates/user/mapper/UserMapper.java +++ b/server/src/main/java/com/codestates/user/mapper/UserMapper.java @@ -4,9 +4,15 @@ import com.codestates.user.entity.User; import org.mapstruct.Mapper; +import java.util.List; + @Mapper(componentModel = "spring") public interface UserMapper { User userPostToUser(UserDto.Post requestBody); UserDto.Response userToUserResponseDto(User user); + + User userPatchDtoToUser(UserDto.Patch requestBody); + + List userToUserResponses(List users); } diff --git a/server/src/main/resources/static/docs/index.html b/server/src/main/resources/static/docs/index.html index e56c09d..579576e 100644 --- a/server/src/main/resources/static/docs/index.html +++ b/server/src/main/resources/static/docs/index.html @@ -594,8 +594,8 @@

1.1. 질문 등록

"tagList" : [ "tag", "body" ], "view" : 0, "vote" : 0, - "createdAt" : "2022-11-06T22:35:14.811876", - "modifiedAt" : "2022-11-06T22:35:14.811879", + "createdAt" : "2022-11-07T14:12:31.019135", + "modifiedAt" : "2022-11-07T14:12:31.019139", "answerCount" : 0, "commentsWithUser" : null, "actionStatus" : "asked" @@ -840,8 +840,8 @@

1.2. 질문 수정

"tagList" : [ "changed", "tag", "body" ], "view" : 0, "vote" : 0, - "createdAt" : "2022-11-06T22:35:14.796188", - "modifiedAt" : "2022-11-06T22:35:14.796191", + "createdAt" : "2022-11-07T14:12:30.999696", + "modifiedAt" : "2022-11-07T14:12:30.999698", "answerCount" : 0, "commentsWithUser" : null, "actionStatus" : "modified" @@ -988,6 +988,10 @@

1.3. 질문 조회

Host: localhost:8080 +
+
Request-Fields
+

Unresolved directive in index.adoc - include::/Users/gnidinger/Documents/40th Projects/seb40_pre_038/server/build/generated-snippets/get-question/request-fields.adoc[]

+
Http-Response
@@ -1019,8 +1023,8 @@

1.3. 질문 조회

"tagList" : [ "tag", "body" ], "view" : 0, "vote" : 0, - "createdAt" : "2022-11-06T22:35:14.822233", - "modifiedAt" : "2022-11-06T22:35:14.822236", + "createdAt" : "2022-11-07T14:12:31.032836", + "modifiedAt" : "2022-11-07T14:12:31.032838", "answerCount" : 0, "commentsWithUser" : null, "actionStatus" : "asked" @@ -1187,8 +1191,8 @@

1.4. 질문 전체 조회

"tagList" : [ "tag1", "body1" ], "view" : 0, "vote" : 0, - "createdAt" : "2022-11-06T22:35:14.770386", - "modifiedAt" : "2022-11-06T22:35:14.770386", + "createdAt" : "2022-11-07T14:12:30.963049", + "modifiedAt" : "2022-11-07T14:12:30.963049", "answerCount" : 0, "commentsWithUser" : null, "actionStatus" : "asked" @@ -1206,8 +1210,8 @@

1.4. 질문 전체 조회

"tagList" : [ "tag2", "body2" ], "view" : 0, "vote" : 0, - "createdAt" : "2022-11-06T22:35:14.770389", - "modifiedAt" : "2022-11-06T22:35:14.770389", + "createdAt" : "2022-11-07T14:12:30.963053", + "modifiedAt" : "2022-11-07T14:12:30.963053", "answerCount" : 0, "commentsWithUser" : null, "actionStatus" : "asked" @@ -1427,8 +1431,8 @@

2.1. 답변 등록

"questionId" : 1, "body" : "Answer should have more than 20 characters", "vote" : 0, - "createdAt" : "2022-11-06T22:35:13.416623", - "modifiedAt" : "2022-11-06T22:35:13.416625", + "createdAt" : "2022-11-07T14:12:29.496968", + "modifiedAt" : "2022-11-07T14:12:29.496971", "commentsWithUser" : null, "actionStatus" : "answered" } @@ -1627,8 +1631,8 @@

2.2. 답변 수정

"questionId" : 1, "body" : "Changed answer should have more than 20 characters", "vote" : 0, - "createdAt" : "2022-11-06T22:35:13.43993", - "modifiedAt" : "2022-11-06T22:35:13.439932", + "createdAt" : "2022-11-07T14:12:29.53098", + "modifiedAt" : "2022-11-07T14:12:29.530983", "commentsWithUser" : null, "actionStatus" : "modified" } @@ -1762,7 +1766,7 @@

2.3. 답변 전체 조회

Pragma: no-cache Expires: 0 X-Frame-Options: SAMEORIGIN -Content-Length: 979 +Content-Length: 978 { "data" : [ { @@ -1777,8 +1781,8 @@

2.3. 답변 전체 조회

"questionId" : 1, "body" : "Answer1 should have more than 20 characters", "vote" : 0, - "createdAt" : "2022-11-06T22:35:13.395105", - "modifiedAt" : "2022-11-06T22:35:13.395108", + "createdAt" : "2022-11-07T14:12:29.47225", + "modifiedAt" : "2022-11-07T14:12:29.472253", "commentsWithUser" : null, "actionStatus" : "answered" }, { @@ -1793,8 +1797,8 @@

2.3. 답변 전체 조회

"questionId" : 2, "body" : "Answer2 should have more than 20 characters", "vote" : 0, - "createdAt" : "2022-11-06T22:35:13.395161", - "modifiedAt" : "2022-11-06T22:35:13.395161", + "createdAt" : "2022-11-07T14:12:29.472298", + "modifiedAt" : "2022-11-07T14:12:29.472299", "commentsWithUser" : null, "actionStatus" : "modified" } ] @@ -1969,8 +1973,8 @@

3.1. 질문 댓글 등록

"reputation" : 1234567890 }, "body" : "Question-Comment should not be empty", - "createdAt" : "2022-11-06T22:35:14.160522", - "modifiedAt" : "2022-11-06T22:35:14.160522", + "createdAt" : "2022-11-07T14:12:30.298374", + "modifiedAt" : "2022-11-07T14:12:30.298375", "commentType" : "QUESTION" } } @@ -2119,8 +2123,8 @@

3.2. 답변 댓글 등록

"reputation" : 1234567890 }, "body" : "Answer-Comment should not be empty", - "createdAt" : "2022-11-06T22:35:14.126574", - "modifiedAt" : "2022-11-06T22:35:14.126574", + "createdAt" : "2022-11-07T14:12:30.256686", + "modifiedAt" : "2022-11-07T14:12:30.256686", "commentType" : "ANSWER" } } @@ -2295,8 +2299,8 @@

3.3. 댓글 수정

"reputation" : 1234567890 }, "body" : "Changed comment should not be empty", - "createdAt" : "2022-11-06T22:35:14.148138", - "modifiedAt" : "2022-11-06T22:35:14.148139", + "createdAt" : "2022-11-07T14:12:30.284294", + "modifiedAt" : "2022-11-07T14:12:30.284296", "commentType" : "QUESTION" } } @@ -2421,8 +2425,8 @@

3.4. 댓글 전체 조회

"reputation" : 1234567890 }, "body" : "Changed comment should not be empty", - "createdAt" : "2022-11-06T22:35:14.106146", - "modifiedAt" : "2022-11-06T22:35:14.106147", + "createdAt" : "2022-11-07T14:12:30.229294", + "modifiedAt" : "2022-11-07T14:12:30.229295", "commentType" : "QUESTION" }, { "commentId" : 1, @@ -2433,8 +2437,8 @@

3.4. 댓글 전체 조회

"reputation" : 1234567890 }, "body" : "Changed comment should not be empty", - "createdAt" : "2022-11-06T22:35:14.106156", - "modifiedAt" : "2022-11-06T22:35:14.106156", + "createdAt" : "2022-11-07T14:12:30.229302", + "modifiedAt" : "2022-11-07T14:12:30.229303", "commentType" : "QUESTION" } ], "pageInfo" : { diff --git a/server/src/test/java/com/codestates/restdocs/UserControllerRestDoc.java b/server/src/test/java/com/codestates/restdocs/UserControllerRestDoc.java index c32eaba..96246ef 100644 --- a/server/src/test/java/com/codestates/restdocs/UserControllerRestDoc.java +++ b/server/src/test/java/com/codestates/restdocs/UserControllerRestDoc.java @@ -9,7 +9,6 @@ import com.codestates.question.QuestionMapper; import com.codestates.question.QuestionService; import com.codestates.user.assembler.UserAssembler; -import com.codestates.user.controller.UserController; import com.codestates.user.dto.UserDto; import com.codestates.user.entity.User; import com.codestates.user.mapper.UserMapper; @@ -17,26 +16,27 @@ import com.google.gson.Gson; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import org.mockito.Mock; import org.mockito.Mockito; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.restdocs.AutoConfigureRestDocs; import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; -import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageImpl; -import org.springframework.hateoas.EntityModel; -import org.springframework.hateoas.server.mvc.WebMvcLinkBuilder; +import org.springframework.hateoas.*; import org.springframework.http.MediaType; import org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders; import org.springframework.restdocs.payload.JsonFieldType; import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.ResultActions; import org.springframework.transaction.annotation.Transactional; +import org.springframework.web.util.UriComponents; import java.time.LocalDateTime; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; import static com.codestates.util.ApiDocumentUtils.getDocumentRequest; @@ -44,8 +44,6 @@ import static org.mockito.ArgumentMatchers.*; import static org.mockito.BDDMockito.given; import static org.mockito.Mockito.doNothing; -import static org.springframework.hateoas.server.mvc.WebMvcLinkBuilder.linkTo; -import static org.springframework.hateoas.server.mvc.WebMvcLinkBuilder.methodOn; import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.document; import static org.springframework.restdocs.payload.PayloadDocumentation.*; import static org.springframework.restdocs.request.RequestDocumentation.*; @@ -77,6 +75,9 @@ public class UserControllerRestDoc { @MockBean private UserAssembler userAssembler; + @MockBean + private CollectionModel collectionModel; + @MockBean private UserMapper userMapper; @@ -304,15 +305,76 @@ void patchQuestionTest() throws Exception { )); } + @Test + void getUserTest() throws Exception { + + long userId = 1; + + User user = new User( + 1L, + "Stub_Potato", + "stub_email@user.com", + "e487275780", + User.UserStatus.USER_ACTIVE, + null, + null, + null, + null, + 1234567890 + ); + + EntityModel response = EntityModel.of(user, + Arrays.asList(Link.of("http://localhost:8080/api/users/1", "self"), + Link.of("http://localhost:8080/api/users", "users"))); + + given(userService.findOne(anyLong())).willReturn(new User()); + + given(userAssembler.toModel(Mockito.any(User.class))).willReturn(response); + + + ResultActions actions = + mockMvc.perform( + RestDocumentationRequestBuilders.get("/api/users/{userId}", userId) + .accept(MediaType.APPLICATION_JSON) + ); + + actions + .andExpect(status().isOk()) + .andDo(document( + "get-user", + getDocumentRequest(), + getDocumentResponse(), + pathParameters( + parameterWithName("userId").description("회원 번호") + ), + responseFields( + List.of( +// fieldWithPath("data.").type(JsonFieldType.OBJECT).description("결과 데이터"), + fieldWithPath("userId").type((JsonFieldType.NUMBER)).description("유저 번호"), + fieldWithPath("nickName").type((JsonFieldType.STRING)).description("유저 이름"), + fieldWithPath("email").type((JsonFieldType.STRING)).description("유저 이메일 주소"), + fieldWithPath("password").type((JsonFieldType.STRING)).description("유저 비밀번호"), + fieldWithPath("userStatus").type((JsonFieldType.STRING)).description("유저 상태"), + fieldWithPath("roles").type((JsonFieldType.NULL)).description("유저 역할"), + fieldWithPath("questions").type((JsonFieldType.NULL)).description("유저 질문"), + fieldWithPath("answers").type((JsonFieldType.NULL)).description("유저 답변"), + fieldWithPath("comments").type((JsonFieldType.NULL)).description("유저 댓글"), + fieldWithPath("reputation").type((JsonFieldType.NUMBER)).description("유저 명성"), + fieldWithPath("_links").type(JsonFieldType.OBJECT).description("링크"), + fieldWithPath("_links.self.href").type(JsonFieldType.STRING).description("유저 정보 링크"), + fieldWithPath("_links.users.href").type(JsonFieldType.STRING).description("전체 유저 정보 링크") + ) + ) + )); + } + // @Test -// void getQuestionTest() throws Exception { +// void getUsersTest() throws Exception { // -// long userId = 1; -// -// User user = new User( +// User user1 = new User( // 1L, -// "Stub_Potato", -// "stub_email@user.com", +// "Stub_Potato1", +// "stub_email1@user.com", // "e487275780", // User.UserStatus.USER_ACTIVE, // null, @@ -322,226 +384,80 @@ void patchQuestionTest() throws Exception { // 1234567890 // ); // -//// of response = new EntityModel.of( -//// new User( -//// 1L, -//// "Stub_Potato", -//// "stub_email@user.com", -//// "e487275780", -//// User.UserStatus.USER_ACTIVE, -//// null, -//// null, -//// null, -//// null, -//// 1234567890 -//// ), -//// "http://localhost:8080/api/users/1", -//// "http://localhost:8080/api/users" -//// ); +// EntityModel userEntityModel1 = EntityModel.of(user1, +// Arrays.asList(Link.of("http://localhost:8080/api/users/1", "self"), +// Link.of("http://localhost:8080/api/users", "users"))); // -//// UserDto.Response response = -//// new UserDto.Response( -//// 1L, -//// "Stub_Potato", -//// "stub_email@user.com", -//// 1234567890 -//// ); +// User user2 = new User( +// 2L, +// "Stub_Potato2", +// "stub_email2@user.com", +// "e487275780", +// User.UserStatus.USER_ACTIVE, +// null, +// null, +// null, +// null, +// 1234567890 +// ); // -// given(userService.findOne(anyLong())).willReturn(new User()); +// EntityModel userEntityModel2 = EntityModel.of(user1, +// Arrays.asList(Link.of("http://localhost:8080/api/users/2", "self"), +// Link.of("http://localhost:8080/api/users", "users"))); // -//// given(userAssembler.toModel(Mockito.any(User.class))).willReturn(response); +// List> userList = List.of(userEntityModel1, userEntityModel2); // -//// given(EntityModel.of(Mockito.any(User.class), anyList())).willReturn(user); +// CollectionModel responses = CollectionModel.of(userList, +// Arrays.asList(Link.of("http://localhost:8080", "self")) +// ); // -// given(userAssembler.toModel(Mockito.any(User.class))).willReturn( -// new User( -// 1L, -// "Stub_Potato", -// "stub_email@user.com", -// "e487275780", -// User.UserStatus.USER_ACTIVE, -// null, -// null, -// null, -// null, -// 1234567890 -// ), -// ("http://localhost:8080/api/users/1"), -// ("http://localhost:8080/api/users") -// ); +// given(userService.findAll()).willReturn(new ArrayList<>()); // +// given(collectionModel.of(Mockito.anyList())).willReturn(responses); // // ResultActions actions = // mockMvc.perform( -// RestDocumentationRequestBuilders.get("/api/users/{userId}", userId) +// RestDocumentationRequestBuilders.get("/api/questions") // .accept(MediaType.APPLICATION_JSON) // ); // -// actions -// .andExpect(status().isOk()) -//// .andExpect(jsonPath("$.data.userId").value(response.getUserId())) -//// .andExpect(jsonPath("$.data.nickName").value(response.getNickName())) -//// .andExpect(jsonPath("$.data.email").value(response.getEmail())) -//// .andExpect(jsonPath("$.data.reputation").value(response.getReputation())) -// .andDo(document( -// "get-user", +// actions.andExpect(status().isOk()) +// .andDo(document("get-questions", // getDocumentRequest(), // getDocumentResponse(), -// pathParameters( -// parameterWithName("userId").description("회원 번호") +// requestParameters( +// parameterWithName("page").description("페이지"), +// parameterWithName("size").description("페이지 크기") // ), // responseFields( // List.of( -// fieldWithPath("data.").type(JsonFieldType.OBJECT).description("결과 데이터") -//// fieldWithPath("data.questionId").type((JsonFieldType.NUMBER)).description("질문 번호"), -//// fieldWithPath("data.userInformation.userId").type((JsonFieldType.NUMBER)).description("질문 유저 번호"), -//// fieldWithPath("data.userInformation.nickName").type((JsonFieldType.STRING)).description("질문 유저 이름"), -//// fieldWithPath("data.userInformation.email").type((JsonFieldType.STRING)).description("질문 유저 이메일 주소"), -//// fieldWithPath("data.userInformation.reputation").type((JsonFieldType.NUMBER)).description("질문 유저 명성"), -//// fieldWithPath("data.title").type(JsonFieldType.STRING).description("제목"), -//// fieldWithPath("data.problem").type(JsonFieldType.STRING).description("문제"), -//// fieldWithPath("data.expect").type(JsonFieldType.STRING).description("기대"), -//// fieldWithPath("data.tagList").type(JsonFieldType.ARRAY).description("태그 리스트"), -//// fieldWithPath("data.view").type(JsonFieldType.NUMBER).description("조회수"), -//// fieldWithPath("data.vote").type(JsonFieldType.NUMBER).description("투표"), -//// fieldWithPath("data.createdAt").type(JsonFieldType.STRING).description("생성 날짜"), -//// fieldWithPath("data.modifiedAt").type(JsonFieldType.STRING).description("마지막 수정 날짜"), -//// fieldWithPath("data.answerCount").type(JsonFieldType.NUMBER).description("답변 개수"), -//// fieldWithPath("data.commentsWithUser").type(JsonFieldType.NULL).description("댓글"), -//// fieldWithPath("data.actionStatus").type(JsonFieldType.STRING).description("질문 상태") +// fieldWithPath("data.").type(JsonFieldType.ARRAY).description("결과 데이터"), +// fieldWithPath("data[].questionId").type((JsonFieldType.NUMBER)).description("질문 번호"), +// fieldWithPath("data[].userInformation.userId").type((JsonFieldType.NUMBER)).description("질문 유저 번호"), +// fieldWithPath("data[].userInformation.nickName").type((JsonFieldType.STRING)).description("질문 유저 이름"), +// fieldWithPath("data[].userInformation.email").type((JsonFieldType.STRING)).description("질문 유저 이메일 주소"), +// fieldWithPath("data[].userInformation.reputation").type((JsonFieldType.NUMBER)).description("질문 유저 명성"), +// fieldWithPath("data[].title").type(JsonFieldType.STRING).description("제목"), +// fieldWithPath("data[].problem").type(JsonFieldType.STRING).description("문제"), +// fieldWithPath("data[].expect").type(JsonFieldType.STRING).description("기대"), +// fieldWithPath("data[].tagList").type(JsonFieldType.ARRAY).description("태그 리스트"), +// fieldWithPath("data[].view").type(JsonFieldType.NUMBER).description("조회수"), +// fieldWithPath("data[].vote").type(JsonFieldType.NUMBER).description("투표"), +// fieldWithPath("data[].createdAt").type(JsonFieldType.STRING).description("생성 날짜"), +// fieldWithPath("data[].modifiedAt").type(JsonFieldType.STRING).description("마지막 수정 날짜"), +// fieldWithPath("data[].answerCount").type(JsonFieldType.NUMBER).description("답변 개수"), +// fieldWithPath("data[].commentsWithUser").type(JsonFieldType.NULL).description("댓글"), +// fieldWithPath("data[].actionStatus").type(JsonFieldType.STRING).description("질문 상태"), +// fieldWithPath("pageInfo.page").type(JsonFieldType.NUMBER).description("페이지"), +// fieldWithPath("pageInfo.size").type(JsonFieldType.NUMBER).description("페이지 크기"), +// fieldWithPath("pageInfo.totalElements").type(JsonFieldType.NUMBER).description("총 질문 수"), +// fieldWithPath("pageInfo.totalPages").type(JsonFieldType.NUMBER).description("총 페이지 수") // ) // ) // )); +// // } - @Test - void getQuestionsTest() throws Exception { - - Question question1 = new Question( - 1L, - new User(1L, - "Stub_Potato1", - "stub_email1@user.com", - 1234567890), - "Title1", - "Problem1 should have more than 20 characters", - "Expect1 should have more than 20 characters", - List.of("tag1", "body1"), - 0, 0, - LocalDateTime.now(), - LocalDateTime.now(), - null, - Question.ActionStatus.ACTION_ASKED - ); - - Question question2 = new Question( - 2L, - new User(2L, - "Stub_Potato2", - "stub_email2@user.com", - 1234567890), - "Title2", - "Problem2 should have more than 20 characters", - "Expect2 should have more than 20 characters", - List.of("tag2", "body2"), - 0, 0, - LocalDateTime.now(), - LocalDateTime.now(), - null, - Question.ActionStatus.ACTION_ASKED - ); - - List responses = List.of( - - new QuestionDto.Response(1L, - new UserDto.Response(1L, - "Stub_Potato1", - "stub_email1@user.com", - 1234567890), -// userMapper.userToUserResponseDto(new User()), - "Title1", - "Problem1 should have more than 20 characters", - "Expect1 should have more than 20 characters", - List.of("tag1", "body1"), - 0, 0, - LocalDateTime.now(), - LocalDateTime.now(), - 0, - null, - "asked" - ), - - new QuestionDto.Response(2L, - new UserDto.Response(2L, - "Stub_Potato2", - "stub_email2@user.com", - 1234567890), -// userMapper.userToUserResponseDto(new User()), - "Title2", - "Problem2 should have more than 20 characters", - "Expect2 should have more than 20 characters", - List.of("tag2", "body2"), - 0, 0, - LocalDateTime.now(), - LocalDateTime.now(), - 0, - null, - "asked" - ) - - ); - - Page questionPage = new PageImpl<>(List.of()); - - given(questionService.findQuestions(Mockito.anyInt(), Mockito.anyInt())).willReturn(questionPage); - - given(questionMapper.questionsToQuestionResponses(Mockito.anyList())).willReturn(responses); - - ResultActions actions = - mockMvc.perform( - RestDocumentationRequestBuilders.get("/api/questions") - .param("page", "1") - .param("size", "15") - .accept(MediaType.APPLICATION_JSON) - ); - - actions.andExpect(status().isOk()) - .andDo(document("get-questions", - getDocumentRequest(), - getDocumentResponse(), - requestParameters( - parameterWithName("page").description("페이지"), - parameterWithName("size").description("페이지 크기") - ), - responseFields( - List.of( - fieldWithPath("data.").type(JsonFieldType.ARRAY).description("결과 데이터"), - fieldWithPath("data[].questionId").type((JsonFieldType.NUMBER)).description("질문 번호"), - fieldWithPath("data[].userInformation.userId").type((JsonFieldType.NUMBER)).description("질문 유저 번호"), - fieldWithPath("data[].userInformation.nickName").type((JsonFieldType.STRING)).description("질문 유저 이름"), - fieldWithPath("data[].userInformation.email").type((JsonFieldType.STRING)).description("질문 유저 이메일 주소"), - fieldWithPath("data[].userInformation.reputation").type((JsonFieldType.NUMBER)).description("질문 유저 명성"), - fieldWithPath("data[].title").type(JsonFieldType.STRING).description("제목"), - fieldWithPath("data[].problem").type(JsonFieldType.STRING).description("문제"), - fieldWithPath("data[].expect").type(JsonFieldType.STRING).description("기대"), - fieldWithPath("data[].tagList").type(JsonFieldType.ARRAY).description("태그 리스트"), - fieldWithPath("data[].view").type(JsonFieldType.NUMBER).description("조회수"), - fieldWithPath("data[].vote").type(JsonFieldType.NUMBER).description("투표"), - fieldWithPath("data[].createdAt").type(JsonFieldType.STRING).description("생성 날짜"), - fieldWithPath("data[].modifiedAt").type(JsonFieldType.STRING).description("마지막 수정 날짜"), - fieldWithPath("data[].answerCount").type(JsonFieldType.NUMBER).description("답변 개수"), - fieldWithPath("data[].commentsWithUser").type(JsonFieldType.NULL).description("댓글"), - fieldWithPath("data[].actionStatus").type(JsonFieldType.STRING).description("질문 상태"), - fieldWithPath("pageInfo.page").type(JsonFieldType.NUMBER).description("페이지"), - fieldWithPath("pageInfo.size").type(JsonFieldType.NUMBER).description("페이지 크기"), - fieldWithPath("pageInfo.totalElements").type(JsonFieldType.NUMBER).description("총 질문 수"), - fieldWithPath("pageInfo.totalPages").type(JsonFieldType.NUMBER).description("총 페이지 수") - ) - ) - )); - - } - @Test void deleteQuestionTest() throws Exception {