diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS new file mode 100644 index 000000000..06032ab2f --- /dev/null +++ b/.github/CODEOWNERS @@ -0,0 +1,3 @@ +* @chysis @BadaHertz52 @soosoo22 @ImxYJL @donghoony @Kimprodp @nayonsoso @skylar1220 +/frontend/ @chysis @BadaHertz52 @soosoo22 @ImxYJL +/backend/ @donghoony @Kimprodp @nayonsoso @skylar1220 diff --git a/.github/workflows/discord-pull-request-comment.yml b/.github/workflows/discord-pull-request-comment.yml index e1a3fc36b..d3594088f 100644 --- a/.github/workflows/discord-pull-request-comment.yml +++ b/.github/workflows/discord-pull-request-comment.yml @@ -31,7 +31,7 @@ jobs: elif [ "$PR_PREFIX" = '[FE]' ]; then echo Frontend PR Found! echo "PR_PREFIX=FE" >> $GITHUB_ENV - elif [ "$PR_PREFIX" = '[All]' ]; then + elif [ "$PR_PREFIX" = '[All]' ] || [ "$PR_PREFIX" = '[Release]' ]; then echo All PR Found! echo "PR_PREFIX=All" >> $GITHUB_ENV fi diff --git a/.github/workflows/discord-pull-request.yml b/.github/workflows/discord-pull-request.yml index 52b446ebb..9f9919b42 100644 --- a/.github/workflows/discord-pull-request.yml +++ b/.github/workflows/discord-pull-request.yml @@ -31,7 +31,7 @@ jobs: elif [ "$PR_PREFIX" = '[FE]' ]; then echo Frontend PR Found! echo "PR_PREFIX=FE" >> $GITHUB_ENV - elif [ "$PR_PREFIX" = '[All]' ]; then + elif [ "$PR_PREFIX" = '[All]' ] || [ "$PR_PREFIX" = '[Release]' ]; then echo All PR Found! echo "PR_PREFIX=All" >> $GITHUB_ENV fi diff --git a/README.md b/README.md index 7f807fd6a..63ae0b310 100644 --- a/README.md +++ b/README.md @@ -48,6 +48,9 @@ ### ๋ฐฑ์—”๋“œ

+### Infrastructure +

+ ## ๐Ÿง‘โ€๐Ÿ’ป ํŒ€์› ์†Œ๊ฐœ ### ํ”„๋ก ํŠธ์—”๋“œ @@ -59,3 +62,4 @@ | | | | | | :---: | :---: | :---: | :---: | | [๐Ÿฆง ์‚ฐ์ดˆ](https://github.com/nayonsoso) | [๐Ÿคธ๐Ÿปโ€โ™‚๏ธ ์•„๋ฃจ](https://github.com/donghoony) | [๐Ÿ’ƒ ์ปค๋น„](https://github.com/skylar1220) | [๐Ÿป ํ…Œ๋“œ](https://github.com/Kimprodp) | + diff --git a/backend/src/main/java/reviewme/DatabaseInitializer.java b/backend/src/main/java/reviewme/DatabaseInitializer.java index 38d1e3496..71c18843b 100644 --- a/backend/src/main/java/reviewme/DatabaseInitializer.java +++ b/backend/src/main/java/reviewme/DatabaseInitializer.java @@ -5,14 +5,14 @@ import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Component; import org.springframework.transaction.annotation.Transactional; -import reviewme.question.domain.OptionGroup; -import reviewme.question.domain.OptionItem; -import reviewme.question.domain.OptionType; -import reviewme.question.domain.Question; -import reviewme.question.domain.QuestionType; -import reviewme.question.repository.OptionGroupRepository; -import reviewme.question.repository.OptionItemRepository; -import reviewme.question.repository.QuestionRepository; +import reviewme.template.domain.OptionGroup; +import reviewme.template.domain.OptionItem; +import reviewme.template.domain.OptionType; +import reviewme.template.domain.Question; +import reviewme.template.domain.QuestionType; +import reviewme.template.repository.OptionGroupRepository; +import reviewme.template.repository.OptionItemRepository; +import reviewme.template.repository.QuestionRepository; import reviewme.template.domain.Section; import reviewme.template.domain.Template; import reviewme.template.domain.VisibleType; diff --git a/backend/src/main/java/reviewme/config/WebConfig.java b/backend/src/main/java/reviewme/config/WebConfig.java index 916ea5a41..d855040f0 100644 --- a/backend/src/main/java/reviewme/config/WebConfig.java +++ b/backend/src/main/java/reviewme/config/WebConfig.java @@ -3,11 +3,8 @@ import java.util.List; import lombok.RequiredArgsConstructor; import org.springframework.context.annotation.Configuration; -import org.springframework.data.redis.core.RedisTemplate; import org.springframework.web.method.support.HandlerMethodArgumentResolver; -import org.springframework.web.servlet.config.annotation.InterceptorRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; -import reviewme.global.RequestLimitInterceptor; import reviewme.reviewgroup.controller.ReviewGroupSessionResolver; import reviewme.reviewgroup.service.ReviewGroupService; @@ -16,16 +13,9 @@ public class WebConfig implements WebMvcConfigurer { private final ReviewGroupService reviewGroupService; - private final RedisTemplate redisTemplate; - private final RequestLimitProperties requestLimitProperties; @Override public void addArgumentResolvers(List resolvers) { resolvers.add(new ReviewGroupSessionResolver(reviewGroupService)); } - - @Override - public void addInterceptors(InterceptorRegistry registry) { - registry.addInterceptor(new RequestLimitInterceptor(redisTemplate, requestLimitProperties)); - } } diff --git a/backend/src/main/java/reviewme/config/CorsConfig.java b/backend/src/main/java/reviewme/config/cors/CorsConfig.java similarity index 90% rename from backend/src/main/java/reviewme/config/CorsConfig.java rename to backend/src/main/java/reviewme/config/cors/CorsConfig.java index 2f51720ea..ff1a483a3 100644 --- a/backend/src/main/java/reviewme/config/CorsConfig.java +++ b/backend/src/main/java/reviewme/config/cors/CorsConfig.java @@ -1,18 +1,16 @@ -package reviewme.config; +package reviewme.config.cors; import lombok.RequiredArgsConstructor; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; +import lombok.extern.slf4j.Slf4j; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Profile; import org.springframework.web.servlet.config.annotation.CorsRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; +@Slf4j public class CorsConfig { - private static final Logger log = LoggerFactory.getLogger(CorsConfig.class); - private CorsConfig() { } diff --git a/backend/src/main/java/reviewme/config/CorsProperties.java b/backend/src/main/java/reviewme/config/cors/CorsProperties.java similarity index 91% rename from backend/src/main/java/reviewme/config/CorsProperties.java rename to backend/src/main/java/reviewme/config/cors/CorsProperties.java index 69a7d1c4d..e11a93667 100644 --- a/backend/src/main/java/reviewme/config/CorsProperties.java +++ b/backend/src/main/java/reviewme/config/cors/CorsProperties.java @@ -1,4 +1,4 @@ -package reviewme.config; +package reviewme.config.cors; import java.util.List; import org.springframework.boot.context.properties.ConfigurationProperties; diff --git a/backend/src/main/java/reviewme/config/DataSourceType.java b/backend/src/main/java/reviewme/config/datasource/DataSourceType.java similarity index 62% rename from backend/src/main/java/reviewme/config/DataSourceType.java rename to backend/src/main/java/reviewme/config/datasource/DataSourceType.java index c48080ab4..b40750df2 100644 --- a/backend/src/main/java/reviewme/config/DataSourceType.java +++ b/backend/src/main/java/reviewme/config/datasource/DataSourceType.java @@ -1,4 +1,4 @@ -package reviewme.config; +package reviewme.config.datasource; public enum DataSourceType { READ, diff --git a/backend/src/main/java/reviewme/config/ReplicationDatasourceConfig.java b/backend/src/main/java/reviewme/config/datasource/ReplicationDatasourceConfig.java similarity index 98% rename from backend/src/main/java/reviewme/config/ReplicationDatasourceConfig.java rename to backend/src/main/java/reviewme/config/datasource/ReplicationDatasourceConfig.java index 6a33a9e08..fb59b2498 100644 --- a/backend/src/main/java/reviewme/config/ReplicationDatasourceConfig.java +++ b/backend/src/main/java/reviewme/config/datasource/ReplicationDatasourceConfig.java @@ -1,4 +1,4 @@ -package reviewme.config; +package reviewme.config.datasource; import java.util.HashMap; import java.util.Map; @@ -54,4 +54,3 @@ public DataSource dataSource(@Qualifier(ROUTING_DATA_SOURCE_NAME) DataSource rou return new LazyConnectionDataSourceProxy(routingDataSource); } } - diff --git a/backend/src/main/java/reviewme/config/ReplicationRoutingDataSource.java b/backend/src/main/java/reviewme/config/datasource/ReplicationRoutingDataSource.java similarity index 93% rename from backend/src/main/java/reviewme/config/ReplicationRoutingDataSource.java rename to backend/src/main/java/reviewme/config/datasource/ReplicationRoutingDataSource.java index 49b7aa22b..f8a802467 100644 --- a/backend/src/main/java/reviewme/config/ReplicationRoutingDataSource.java +++ b/backend/src/main/java/reviewme/config/datasource/ReplicationRoutingDataSource.java @@ -1,4 +1,4 @@ -package reviewme.config; +package reviewme.config.datasource; import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource; import org.springframework.transaction.support.TransactionSynchronizationManager; diff --git a/backend/src/main/java/reviewme/global/RequestLimitInterceptor.java b/backend/src/main/java/reviewme/config/requestlimit/RequestLimitInterceptor.java similarity index 93% rename from backend/src/main/java/reviewme/global/RequestLimitInterceptor.java rename to backend/src/main/java/reviewme/config/requestlimit/RequestLimitInterceptor.java index b5747dfd1..ef25b711e 100644 --- a/backend/src/main/java/reviewme/global/RequestLimitInterceptor.java +++ b/backend/src/main/java/reviewme/config/requestlimit/RequestLimitInterceptor.java @@ -1,4 +1,4 @@ -package reviewme.global; +package reviewme.config.requestlimit; import static org.springframework.http.HttpHeaders.USER_AGENT; @@ -11,8 +11,6 @@ import org.springframework.http.HttpMethod; import org.springframework.stereotype.Component; import org.springframework.web.servlet.HandlerInterceptor; -import reviewme.config.RequestLimitProperties; -import reviewme.global.exception.TooManyRequestException; @Component @EnableConfigurationProperties(RequestLimitProperties.class) diff --git a/backend/src/main/java/reviewme/config/RequestLimitProperties.java b/backend/src/main/java/reviewme/config/requestlimit/RequestLimitProperties.java similarity index 50% rename from backend/src/main/java/reviewme/config/RequestLimitProperties.java rename to backend/src/main/java/reviewme/config/requestlimit/RequestLimitProperties.java index efea3b4f8..558378094 100644 --- a/backend/src/main/java/reviewme/config/RequestLimitProperties.java +++ b/backend/src/main/java/reviewme/config/requestlimit/RequestLimitProperties.java @@ -1,13 +1,8 @@ -package reviewme.config; +package reviewme.config.requestlimit; import java.time.Duration; import org.springframework.boot.context.properties.ConfigurationProperties; @ConfigurationProperties(prefix = "request-limit") -public record RequestLimitProperties( - long threshold, - Duration duration, - String host, - int port -) { +public record RequestLimitProperties(long threshold, Duration duration, String host, int port) { } diff --git a/backend/src/main/java/reviewme/config/RequestLimitRedisConfig.java b/backend/src/main/java/reviewme/config/requestlimit/RequestLimitRedisConfig.java similarity index 97% rename from backend/src/main/java/reviewme/config/RequestLimitRedisConfig.java rename to backend/src/main/java/reviewme/config/requestlimit/RequestLimitRedisConfig.java index a8307db5f..d8bb458a9 100644 --- a/backend/src/main/java/reviewme/config/RequestLimitRedisConfig.java +++ b/backend/src/main/java/reviewme/config/requestlimit/RequestLimitRedisConfig.java @@ -1,4 +1,4 @@ -package reviewme.config; +package reviewme.config.requestlimit; import lombok.RequiredArgsConstructor; import org.springframework.boot.context.properties.EnableConfigurationProperties; diff --git a/backend/src/main/java/reviewme/config/requestlimit/RequestLimitWebConfig.java b/backend/src/main/java/reviewme/config/requestlimit/RequestLimitWebConfig.java new file mode 100644 index 000000000..19f3b2fe4 --- /dev/null +++ b/backend/src/main/java/reviewme/config/requestlimit/RequestLimitWebConfig.java @@ -0,0 +1,20 @@ +package reviewme.config.requestlimit; + +import lombok.RequiredArgsConstructor; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.web.servlet.config.annotation.InterceptorRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; + +@Configuration +@RequiredArgsConstructor +public class RequestLimitWebConfig implements WebMvcConfigurer { + + private final RedisTemplate redisTemplate; + private final RequestLimitProperties requestLimitProperties; + + @Override + public void addInterceptors(InterceptorRegistry registry) { + registry.addInterceptor(new RequestLimitInterceptor(redisTemplate, requestLimitProperties)); + } +} diff --git a/backend/src/main/java/reviewme/global/exception/TooManyRequestException.java b/backend/src/main/java/reviewme/config/requestlimit/TooManyRequestException.java similarity index 80% rename from backend/src/main/java/reviewme/global/exception/TooManyRequestException.java rename to backend/src/main/java/reviewme/config/requestlimit/TooManyRequestException.java index 4f26fee3e..544fb5885 100644 --- a/backend/src/main/java/reviewme/global/exception/TooManyRequestException.java +++ b/backend/src/main/java/reviewme/config/requestlimit/TooManyRequestException.java @@ -1,6 +1,7 @@ -package reviewme.global.exception; +package reviewme.config.requestlimit; import lombok.extern.slf4j.Slf4j; +import reviewme.global.exception.ReviewMeException; @Slf4j public class TooManyRequestException extends ReviewMeException { diff --git a/backend/src/main/java/reviewme/global/GlobalExceptionHandler.java b/backend/src/main/java/reviewme/global/GlobalExceptionHandler.java index 9d4511618..161e43172 100644 --- a/backend/src/main/java/reviewme/global/GlobalExceptionHandler.java +++ b/backend/src/main/java/reviewme/global/GlobalExceptionHandler.java @@ -22,7 +22,7 @@ import org.springframework.web.servlet.resource.NoResourceFoundException; import reviewme.global.exception.BadRequestException; import reviewme.global.exception.DataInconsistencyException; -import reviewme.global.exception.TooManyRequestException; +import reviewme.config.requestlimit.TooManyRequestException; import reviewme.global.exception.FieldErrorResponse; import reviewme.global.exception.NotFoundException; import reviewme.global.exception.UnauthorizedException; diff --git a/backend/src/main/java/reviewme/global/exception/FieldErrorResponse.java b/backend/src/main/java/reviewme/global/exception/FieldErrorResponse.java index e44edf619..ae0c678a4 100644 --- a/backend/src/main/java/reviewme/global/exception/FieldErrorResponse.java +++ b/backend/src/main/java/reviewme/global/exception/FieldErrorResponse.java @@ -1,8 +1,4 @@ package reviewme.global.exception; -public record FieldErrorResponse( - String field, - Object value, - String message -) { +public record FieldErrorResponse(String field, Object value, String message) { } diff --git a/backend/src/main/java/reviewme/highlight/domain/HighlightedLines.java b/backend/src/main/java/reviewme/highlight/domain/HighlightedLines.java index f7000ecb2..f24827d30 100644 --- a/backend/src/main/java/reviewme/highlight/domain/HighlightedLines.java +++ b/backend/src/main/java/reviewme/highlight/domain/HighlightedLines.java @@ -2,6 +2,8 @@ import java.util.Arrays; import java.util.List; +import java.util.function.Function; +import java.util.stream.IntStream; import lombok.Getter; import reviewme.highlight.domain.exception.InvalidHighlightLineIndexException; import reviewme.highlight.domain.exception.NegativeHighlightLineIndexException; @@ -37,4 +39,12 @@ private void validateLineIndexRange(int lineIndex) { throw new InvalidHighlightLineIndexException(lineIndex, lines.size()); } } + + public List toHighlights(long answerId) { + return IntStream.range(0, lines.size()) + .mapToObj(lineIndex -> lines.get(lineIndex).getRanges().stream() + .map(range -> new Highlight(answerId, lineIndex, range))) + .flatMap(Function.identity()) + .toList(); + } } diff --git a/backend/src/main/java/reviewme/highlight/domain/exception/HighlightStartIndexExceedEndIndexException.java b/backend/src/main/java/reviewme/highlight/domain/exception/HighlightStartIndexExceedEndIndexException.java deleted file mode 100644 index 38c99ac9a..000000000 --- a/backend/src/main/java/reviewme/highlight/domain/exception/HighlightStartIndexExceedEndIndexException.java +++ /dev/null @@ -1,13 +0,0 @@ -package reviewme.highlight.domain.exception; - -import lombok.extern.slf4j.Slf4j; -import reviewme.global.exception.BadRequestException; - -@Slf4j -public class HighlightStartIndexExceedEndIndexException extends BadRequestException { - - public HighlightStartIndexExceedEndIndexException(int startIndex, int endIndex) { - super("ํ•˜์ด๋ผ์ดํŠธ ๋ ์œ„์น˜๋Š” ์‹œ์ž‘ ์œ„์น˜๋ณด๋‹ค ๊ฐ™๊ฑฐ๋‚˜ ์ปค์•ผ ํ•ด์š”."); - log.info("Highlight start index exceed end index - startIndex: {}, endIndex: {}", startIndex, endIndex); - } -} diff --git a/backend/src/main/java/reviewme/highlight/repository/HighlightJdbcRepository.java b/backend/src/main/java/reviewme/highlight/repository/HighlightJdbcRepository.java new file mode 100644 index 000000000..b1e20ef36 --- /dev/null +++ b/backend/src/main/java/reviewme/highlight/repository/HighlightJdbcRepository.java @@ -0,0 +1,9 @@ +package reviewme.highlight.repository; + +import java.util.Collection; +import reviewme.highlight.domain.Highlight; + +public interface HighlightJdbcRepository { + + void saveAll(Collection highlights); +} diff --git a/backend/src/main/java/reviewme/highlight/repository/HighlightJdbcRepositoryImpl.java b/backend/src/main/java/reviewme/highlight/repository/HighlightJdbcRepositoryImpl.java new file mode 100644 index 000000000..077f6a531 --- /dev/null +++ b/backend/src/main/java/reviewme/highlight/repository/HighlightJdbcRepositoryImpl.java @@ -0,0 +1,24 @@ +package reviewme.highlight.repository; + +import java.util.Collection; +import lombok.RequiredArgsConstructor; +import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; +import org.springframework.jdbc.core.namedparam.SqlParameterSource; +import org.springframework.jdbc.core.namedparam.SqlParameterSourceUtils; +import reviewme.highlight.domain.Highlight; + +@RequiredArgsConstructor +public class HighlightJdbcRepositoryImpl implements HighlightJdbcRepository { + + private final NamedParameterJdbcTemplate namedParameterJdbcTemplate; + + @Override + public void saveAll(Collection highlights) { + SqlParameterSource[] parameterSources = SqlParameterSourceUtils.createBatch(highlights.toArray()); + String insertSql = """ + INSERT INTO highlight (answer_id, line_index, start_index, end_index) + VALUES (:answerId, :lineIndex, :highlightRange.startIndex, :highlightRange.endIndex) + """; + namedParameterJdbcTemplate.batchUpdate(insertSql, parameterSources); + } +} diff --git a/backend/src/main/java/reviewme/highlight/repository/HighlightRepository.java b/backend/src/main/java/reviewme/highlight/repository/HighlightRepository.java index 74760e09c..2733b2027 100644 --- a/backend/src/main/java/reviewme/highlight/repository/HighlightRepository.java +++ b/backend/src/main/java/reviewme/highlight/repository/HighlightRepository.java @@ -2,25 +2,32 @@ import java.util.Collection; import java.util.List; -import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Modifying; import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.Repository; import reviewme.highlight.domain.Highlight; -public interface HighlightRepository extends JpaRepository { +public interface HighlightRepository extends Repository, HighlightJdbcRepository { - @Modifying - @Query(""" - DELETE FROM Highlight h - WHERE h.answerId IN :answerIds - """) - void deleteAllByAnswerIds(Collection answerIds); + Highlight save(Highlight highlight); + + boolean existsById(long id); @Query(""" - SELECT h - FROM Highlight h + SELECT h FROM Highlight h WHERE h.answerId IN :answerIds ORDER BY h.lineIndex, h.highlightRange.startIndex ASC """) List findAllByAnswerIdsOrderedAsc(Collection answerIds); + + @Modifying + @Query(""" + DELETE FROM Highlight h + WHERE h.answerId IN ( + SELECT a.id FROM Answer a + JOIN Review r ON a.reviewId = r.id + WHERE r.reviewGroupId = :reviewGroupId AND a.questionId = :questionId + ) + """) + void deleteByReviewGroupIdAndQuestionId(long reviewGroupId, long questionId); } diff --git a/backend/src/main/java/reviewme/highlight/service/HighlightService.java b/backend/src/main/java/reviewme/highlight/service/HighlightService.java index 7cb9f9c70..8651bca86 100644 --- a/backend/src/main/java/reviewme/highlight/service/HighlightService.java +++ b/backend/src/main/java/reviewme/highlight/service/HighlightService.java @@ -1,7 +1,6 @@ package reviewme.highlight.service; import java.util.List; -import java.util.Set; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -9,8 +8,7 @@ import reviewme.highlight.repository.HighlightRepository; import reviewme.highlight.service.dto.HighlightsRequest; import reviewme.highlight.service.mapper.HighlightMapper; -import reviewme.highlight.service.validator.HighlightValidator; -import reviewme.review.repository.AnswerRepository; +import reviewme.review.service.validator.AnswerValidator; import reviewme.reviewgroup.domain.ReviewGroup; @Service @@ -18,19 +16,18 @@ public class HighlightService { private final HighlightRepository highlightRepository; - private final AnswerRepository answerRepository; - private final HighlightValidator highlightValidator; private final HighlightMapper highlightMapper; + private final AnswerValidator answerValidator; @Transactional public void editHighlight(HighlightsRequest highlightsRequest, ReviewGroup reviewGroup) { - highlightValidator.validate(highlightsRequest, reviewGroup); - List highlights = highlightMapper.mapToHighlights(highlightsRequest); - - Set answerIds = answerRepository.findIdsByQuestionId(highlightsRequest.questionId()); - highlightRepository.deleteAllByAnswerIds(answerIds); + List requestedAnswerIds = highlightsRequest.getUniqueAnswerIds(); + answerValidator.validateQuestionContainsAnswers(highlightsRequest.questionId(), requestedAnswerIds); + answerValidator.validateReviewGroupContainsAnswers(reviewGroup, requestedAnswerIds); + List highlights = highlightMapper.mapToHighlights(highlightsRequest); + highlightRepository.deleteByReviewGroupIdAndQuestionId(reviewGroup.getId(), highlightsRequest.questionId()); highlightRepository.saveAll(highlights); } } diff --git a/backend/src/main/java/reviewme/highlight/service/dto/HighlightRequest.java b/backend/src/main/java/reviewme/highlight/service/dto/HighlightRequest.java index 673cc8e6a..1371c6959 100644 --- a/backend/src/main/java/reviewme/highlight/service/dto/HighlightRequest.java +++ b/backend/src/main/java/reviewme/highlight/service/dto/HighlightRequest.java @@ -4,6 +4,8 @@ import jakarta.validation.constraints.NotEmpty; import jakarta.validation.constraints.NotNull; import java.util.List; +import java.util.stream.Stream; +import reviewme.highlight.service.mapper.HighlightFragment; public record HighlightRequest( @@ -13,4 +15,15 @@ public record HighlightRequest( @Valid @NotEmpty(message = "ํ•˜์ด๋ผ์ดํŠธ ๋œ ๋ผ์ธ์„ ์ž…๋ ฅํ•ด์ฃผ์„ธ์š”.") List lines ) { + public List toFragments() { + return lines.stream() + .flatMap(this::mapRangesToFragment) + .toList(); + } + + private Stream mapRangesToFragment(HighlightedLineRequest line) { + return line.ranges() + .stream() + .map(range -> new HighlightFragment(answerId, line.index(), range.startIndex(), range.endIndex())); + } } diff --git a/backend/src/main/java/reviewme/highlight/service/dto/HighlightsRequest.java b/backend/src/main/java/reviewme/highlight/service/dto/HighlightsRequest.java index b8f26cba6..b1f7f6de3 100644 --- a/backend/src/main/java/reviewme/highlight/service/dto/HighlightsRequest.java +++ b/backend/src/main/java/reviewme/highlight/service/dto/HighlightsRequest.java @@ -3,6 +3,7 @@ import jakarta.validation.Valid; import jakarta.validation.constraints.NotNull; import java.util.List; +import reviewme.highlight.service.mapper.HighlightFragment; public record HighlightsRequest( @@ -20,4 +21,10 @@ public List getUniqueAnswerIds() { .distinct() .toList(); } + + public List toFragments() { + return highlights.stream() + .flatMap(request -> request.toFragments().stream()) + .toList(); + } } diff --git a/backend/src/main/java/reviewme/highlight/service/exception/SubmittedAnswerAndProvidedAnswerMismatchException.java b/backend/src/main/java/reviewme/highlight/service/exception/SubmittedAnswerAndProvidedAnswerMismatchException.java deleted file mode 100644 index 0282bd983..000000000 --- a/backend/src/main/java/reviewme/highlight/service/exception/SubmittedAnswerAndProvidedAnswerMismatchException.java +++ /dev/null @@ -1,16 +0,0 @@ -package reviewme.highlight.service.exception; - -import java.util.Collection; -import lombok.extern.slf4j.Slf4j; -import reviewme.global.exception.BadRequestException; - -@Slf4j -public class SubmittedAnswerAndProvidedAnswerMismatchException extends BadRequestException { - - public SubmittedAnswerAndProvidedAnswerMismatchException(Collection providedAnswerIds, - Collection submittedAnswerIds) { - super("์ œ์ถœ๋œ ์‘๋‹ต์ด ์ œ๊ณต๋œ ์‘๋‹ต๊ณผ ์ผ์น˜ํ•˜์ง€ ์•Š์•„์š”."); - log.info("SubmittedAnswer and providedAnswer mismatch - providedAnswerIds: {}, submittedAnswerIds: {}", - providedAnswerIds, submittedAnswerIds); - } -} diff --git a/backend/src/main/java/reviewme/highlight/service/mapper/HighlightFragment.java b/backend/src/main/java/reviewme/highlight/service/mapper/HighlightFragment.java new file mode 100644 index 000000000..33e08f56e --- /dev/null +++ b/backend/src/main/java/reviewme/highlight/service/mapper/HighlightFragment.java @@ -0,0 +1,4 @@ +package reviewme.highlight.service.mapper; + +public record HighlightFragment(long answerId, int lineIndex, int startIndex, int endIndex) { +} diff --git a/backend/src/main/java/reviewme/highlight/service/mapper/HighlightMapper.java b/backend/src/main/java/reviewme/highlight/service/mapper/HighlightMapper.java index edbec9013..512546030 100644 --- a/backend/src/main/java/reviewme/highlight/service/mapper/HighlightMapper.java +++ b/backend/src/main/java/reviewme/highlight/service/mapper/HighlightMapper.java @@ -1,21 +1,14 @@ package reviewme.highlight.service.mapper; -import java.util.ArrayList; import java.util.List; import java.util.Map; -import java.util.Map.Entry; import java.util.stream.Collectors; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Component; -import reviewme.highlight.domain.HighlightedLines; -import reviewme.highlight.domain.HighlightedLine; import reviewme.highlight.domain.Highlight; -import reviewme.highlight.domain.HighlightRange; -import reviewme.highlight.service.dto.HighlightIndexRangeRequest; -import reviewme.highlight.service.dto.HighlightRequest; -import reviewme.highlight.service.dto.HighlightedLineRequest; +import reviewme.highlight.domain.HighlightedLines; import reviewme.highlight.service.dto.HighlightsRequest; -import reviewme.review.domain.Answer; +import reviewme.review.domain.TextAnswer; import reviewme.review.repository.TextAnswerRepository; @Component @@ -25,53 +18,19 @@ public class HighlightMapper { private final TextAnswerRepository textAnswerRepository; public List mapToHighlights(HighlightsRequest highlightsRequest) { - Map answerHighlightLines = textAnswerRepository + Map answerIdHighlightedLines = textAnswerRepository .findAllById(highlightsRequest.getUniqueAnswerIds()) .stream() - .collect(Collectors.toMap(Answer::getId, answer -> new HighlightedLines(answer.getContent()))); - addIndexRanges(highlightsRequest, answerHighlightLines); - return mapLinesToHighlights(answerHighlightLines); - } - - private void addIndexRanges(HighlightsRequest highlightsRequest, Map answerHighlightLines) { - for (HighlightRequest highlightRequest : highlightsRequest.highlights()) { - HighlightedLines highlightedLines = answerHighlightLines.get(highlightRequest.answerId()); - addIndexRangesForAnswer(highlightRequest, highlightedLines); - } - } - - private void addIndexRangesForAnswer(HighlightRequest highlightRequest, HighlightedLines highlightedLines) { - for (HighlightedLineRequest lineRequest : highlightRequest.lines()) { - int lineIndex = lineRequest.index(); - for (HighlightIndexRangeRequest rangeRequest : lineRequest.ranges()) { - highlightedLines.addRange(lineIndex, rangeRequest.startIndex(), rangeRequest.endIndex()); - } - } - } - - private List mapLinesToHighlights(Map answerHighlightLines) { - List highlights = new ArrayList<>(); - for (Entry answerHighlightLine : answerHighlightLines.entrySet()) { - createHighlightsForAnswer(answerHighlightLine, highlights); - } - return highlights; - } + .collect(Collectors.toMap(TextAnswer::getId, answer -> new HighlightedLines(answer.getContent()))); - private void createHighlightsForAnswer(Entry answerHighlightLine, - List highlights) { - long answerId = answerHighlightLine.getKey(); - List highlightedLines = answerHighlightLine.getValue().getLines(); - - for (int lineIndex = 0; lineIndex < highlightedLines.size(); lineIndex++) { - createHighlightForLine(highlightedLines, lineIndex, answerId, highlights); + for (HighlightFragment fragment : highlightsRequest.toFragments()) { + HighlightedLines highlightedLines = answerIdHighlightedLines.get(fragment.answerId()); + highlightedLines.addRange(fragment.lineIndex(), fragment.startIndex(), fragment.endIndex()); } - } - private void createHighlightForLine(List highlightedLines, int lineIndex, long answerId, - List highlights) { - for (HighlightRange range : highlightedLines.get(lineIndex).getRanges()) { - Highlight highlight = new Highlight(answerId, lineIndex, range); - highlights.add(highlight); - } + return answerIdHighlightedLines.entrySet() + .stream() + .flatMap(entry -> entry.getValue().toHighlights(entry.getKey()).stream()) + .toList(); } } diff --git a/backend/src/main/java/reviewme/highlight/service/validator/HighlightValidator.java b/backend/src/main/java/reviewme/highlight/service/validator/HighlightValidator.java deleted file mode 100644 index e05f0f9df..000000000 --- a/backend/src/main/java/reviewme/highlight/service/validator/HighlightValidator.java +++ /dev/null @@ -1,41 +0,0 @@ - -package reviewme.highlight.service.validator; - -import java.util.List; -import java.util.Set; -import lombok.RequiredArgsConstructor; -import org.springframework.stereotype.Component; -import reviewme.highlight.service.dto.HighlightsRequest; -import reviewme.highlight.service.exception.SubmittedAnswerAndProvidedAnswerMismatchException; -import reviewme.review.repository.AnswerRepository; -import reviewme.reviewgroup.domain.ReviewGroup; - -@Component -@RequiredArgsConstructor -public class HighlightValidator { - - private final AnswerRepository answerRepository; - - public void validate(HighlightsRequest request, ReviewGroup reviewGroup) { - validateQuestionContainsAnswer(request); - validateReviewGroupContainsAnswer(request, reviewGroup); - } - - private void validateQuestionContainsAnswer(HighlightsRequest request) { - Set providedAnswerIds = answerRepository.findIdsByQuestionId(request.questionId()); - List submittedAnswerIds = request.getUniqueAnswerIds(); - - if (!providedAnswerIds.containsAll(submittedAnswerIds)) { - throw new SubmittedAnswerAndProvidedAnswerMismatchException(providedAnswerIds, submittedAnswerIds); - } - } - - private void validateReviewGroupContainsAnswer(HighlightsRequest request, ReviewGroup reviewGroup) { - Set providedAnswerIds = answerRepository.findIdsByReviewGroupId(reviewGroup.getId()); - List submittedAnswerIds = request.getUniqueAnswerIds(); - - if (!providedAnswerIds.containsAll(submittedAnswerIds)) { - throw new SubmittedAnswerAndProvidedAnswerMismatchException(providedAnswerIds, submittedAnswerIds); - } - } -} diff --git a/backend/src/main/java/reviewme/review/domain/exception/MissingTextAnswerForQuestionException.java b/backend/src/main/java/reviewme/review/domain/exception/MissingTextAnswerForQuestionException.java deleted file mode 100644 index 674dce41c..000000000 --- a/backend/src/main/java/reviewme/review/domain/exception/MissingTextAnswerForQuestionException.java +++ /dev/null @@ -1,13 +0,0 @@ -package reviewme.review.domain.exception; - -import lombok.extern.slf4j.Slf4j; -import reviewme.global.exception.DataInconsistencyException; - -@Slf4j -public class MissingTextAnswerForQuestionException extends DataInconsistencyException { - - public MissingTextAnswerForQuestionException(long questionId) { - super("์„œ๋ฒ„ ๋‚ด๋ถ€์— ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ–ˆ์Šต๋‹ˆ๋‹ค. ์ž ์‹œ ํ›„ ๋‹ค์‹œ ์‹œ๋„ํ•ด์ฃผ์„ธ์š”."); - log.error("The question is a text question but text answer not found for questionId: {}", questionId, this); - } -} diff --git a/backend/src/main/java/reviewme/review/service/ReviewGatheredLookupService.java b/backend/src/main/java/reviewme/review/service/ReviewGatheredLookupService.java index 703348c9e..82de0ab16 100644 --- a/backend/src/main/java/reviewme/review/service/ReviewGatheredLookupService.java +++ b/backend/src/main/java/reviewme/review/service/ReviewGatheredLookupService.java @@ -9,8 +9,8 @@ import org.springframework.transaction.annotation.Transactional; import reviewme.highlight.domain.Highlight; import reviewme.highlight.repository.HighlightRepository; -import reviewme.question.domain.Question; -import reviewme.question.repository.QuestionRepository; +import reviewme.template.domain.Question; +import reviewme.template.repository.QuestionRepository; import reviewme.review.domain.Answer; import reviewme.review.repository.AnswerRepository; import reviewme.review.service.dto.response.gathered.ReviewsGatheredBySectionResponse; diff --git a/backend/src/main/java/reviewme/review/service/ReviewRegisterService.java b/backend/src/main/java/reviewme/review/service/ReviewRegisterService.java index 966eaa602..87e5f8538 100644 --- a/backend/src/main/java/reviewme/review/service/ReviewRegisterService.java +++ b/backend/src/main/java/reviewme/review/service/ReviewRegisterService.java @@ -1,8 +1,6 @@ package reviewme.review.service; import lombok.RequiredArgsConstructor; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import reviewme.review.domain.Review; @@ -15,8 +13,6 @@ @RequiredArgsConstructor public class ReviewRegisterService { - private static final Logger log = LoggerFactory.getLogger(ReviewRegisterService.class); - private final ReviewMapper reviewMapper; private final ReviewValidator reviewValidator; private final ReviewRepository reviewRepository; diff --git a/backend/src/main/java/reviewme/review/service/dto/response/detail/QuestionAnswerResponse.java b/backend/src/main/java/reviewme/review/service/dto/response/detail/QuestionAnswerResponse.java index 000eb83c8..fccc3c752 100644 --- a/backend/src/main/java/reviewme/review/service/dto/response/detail/QuestionAnswerResponse.java +++ b/backend/src/main/java/reviewme/review/service/dto/response/detail/QuestionAnswerResponse.java @@ -1,7 +1,7 @@ package reviewme.review.service.dto.response.detail; import jakarta.annotation.Nullable; -import reviewme.question.domain.QuestionType; +import reviewme.template.domain.QuestionType; public record QuestionAnswerResponse( long questionId, diff --git a/backend/src/main/java/reviewme/review/service/dto/response/gathered/SimpleQuestionResponse.java b/backend/src/main/java/reviewme/review/service/dto/response/gathered/SimpleQuestionResponse.java index e16df25e6..d7f1647d9 100644 --- a/backend/src/main/java/reviewme/review/service/dto/response/gathered/SimpleQuestionResponse.java +++ b/backend/src/main/java/reviewme/review/service/dto/response/gathered/SimpleQuestionResponse.java @@ -1,6 +1,6 @@ package reviewme.review.service.dto.response.gathered; -import reviewme.question.domain.QuestionType; +import reviewme.template.domain.QuestionType; public record SimpleQuestionResponse( long id, diff --git a/backend/src/main/java/reviewme/review/service/exception/AnswerNotFoundByIdException.java b/backend/src/main/java/reviewme/review/service/exception/AnswerNotFoundByIdException.java deleted file mode 100644 index aef381ffc..000000000 --- a/backend/src/main/java/reviewme/review/service/exception/AnswerNotFoundByIdException.java +++ /dev/null @@ -1,13 +0,0 @@ -package reviewme.review.service.exception; - -import lombok.extern.slf4j.Slf4j; -import reviewme.global.exception.NotFoundException; - -@Slf4j -public class AnswerNotFoundByIdException extends NotFoundException { - - public AnswerNotFoundByIdException(long answerId) { - super("๋‹ต๋ณ€์„ ์ฐพ์„ ์ˆ˜ ์—†์–ด์š”."); - log.info("Answer not found by id - answerId: {}", answerId); - } -} diff --git a/backend/src/main/java/reviewme/review/service/exception/InvalidTextAnswerLengthException.java b/backend/src/main/java/reviewme/review/service/exception/InvalidTextAnswerLengthException.java index 01c02ceb7..314f72673 100644 --- a/backend/src/main/java/reviewme/review/service/exception/InvalidTextAnswerLengthException.java +++ b/backend/src/main/java/reviewme/review/service/exception/InvalidTextAnswerLengthException.java @@ -8,7 +8,7 @@ public class InvalidTextAnswerLengthException extends BadRequestException { public InvalidTextAnswerLengthException(long questionId, int answerLength, int minLength, int maxLength) { super("๋‹ต๋ณ€์˜ ๊ธธ์ด๋Š” %d์ž ์ด์ƒ %d์ž ์ดํ•˜์—ฌ์•ผ ํ•ด์š”.".formatted(minLength, maxLength)); - log.warn("AnswerLength is out of bound - questionId: {}, answerLength: {}, minLength: {}, maxLength: {}", + log.info("AnswerLength is out of bound - questionId: {}, answerLength: {}, minLength: {}, maxLength: {}", questionId, answerLength, minLength, maxLength, this); } diff --git a/backend/src/main/java/reviewme/review/service/exception/QuestionNotContainingAnswersException.java b/backend/src/main/java/reviewme/review/service/exception/QuestionNotContainingAnswersException.java new file mode 100644 index 000000000..3a7740787 --- /dev/null +++ b/backend/src/main/java/reviewme/review/service/exception/QuestionNotContainingAnswersException.java @@ -0,0 +1,15 @@ +package reviewme.review.service.exception; + +import java.util.Collection; +import lombok.extern.slf4j.Slf4j; +import reviewme.global.exception.ReviewMeException; + +@Slf4j +public class QuestionNotContainingAnswersException extends ReviewMeException { + + public QuestionNotContainingAnswersException(long questionId, Collection providedAnswerIds) { + super("์งˆ๋ฌธ์— ์†ํ•˜์ง€ ์•Š๋Š” ๋‹ต๋ณ€์ด์˜ˆ์š”."); + log.info("Question not containing provided answers - questionId: {}, providedAnswerIds: {}", + questionId, providedAnswerIds); + } +} diff --git a/backend/src/main/java/reviewme/review/service/exception/ReviewGroupNotContainingAnswersException.java b/backend/src/main/java/reviewme/review/service/exception/ReviewGroupNotContainingAnswersException.java new file mode 100644 index 000000000..7f641512f --- /dev/null +++ b/backend/src/main/java/reviewme/review/service/exception/ReviewGroupNotContainingAnswersException.java @@ -0,0 +1,15 @@ +package reviewme.review.service.exception; + +import java.util.Collection; +import lombok.extern.slf4j.Slf4j; +import reviewme.global.exception.ReviewMeException; + +@Slf4j +public class ReviewGroupNotContainingAnswersException extends ReviewMeException { + + public ReviewGroupNotContainingAnswersException(long reviewGroupId, Collection providedAnswerIds) { + super("๋ฆฌ๋ทฐ ๊ทธ๋ฃน์— ์†ํ•˜์ง€ ์•Š๋Š” ๋‹ต๋ณ€์ด์˜ˆ์š”."); + log.info("ReviewGroup not containing provided answers - reviewGroupId: {}, providedAnswerIds: {}", + reviewGroupId, providedAnswerIds); + } +} diff --git a/backend/src/main/java/reviewme/review/service/exception/SubmittedQuestionAndProvidedQuestionMismatchException.java b/backend/src/main/java/reviewme/review/service/exception/SubmittedQuestionAndProvidedQuestionMismatchException.java index 1924b1cf5..97b0f77d9 100644 --- a/backend/src/main/java/reviewme/review/service/exception/SubmittedQuestionAndProvidedQuestionMismatchException.java +++ b/backend/src/main/java/reviewme/review/service/exception/SubmittedQuestionAndProvidedQuestionMismatchException.java @@ -1,7 +1,6 @@ package reviewme.review.service.exception; import java.util.Collection; -import java.util.List; import lombok.extern.slf4j.Slf4j; import reviewme.global.exception.BadRequestException; @@ -16,9 +15,4 @@ public SubmittedQuestionAndProvidedQuestionMismatchException(Collection su submittedQuestionIds, providedQuestionIds, this ); } - - public SubmittedQuestionAndProvidedQuestionMismatchException(long submittedQuestionId, - Collection providedQuestionIds) { - this(List.of(submittedQuestionId), providedQuestionIds); - } } diff --git a/backend/src/main/java/reviewme/review/service/mapper/AnswerMapper.java b/backend/src/main/java/reviewme/review/service/mapper/AnswerMapper.java index 7b3cbb631..1181808a5 100644 --- a/backend/src/main/java/reviewme/review/service/mapper/AnswerMapper.java +++ b/backend/src/main/java/reviewme/review/service/mapper/AnswerMapper.java @@ -1,6 +1,6 @@ package reviewme.review.service.mapper; -import reviewme.question.domain.QuestionType; +import reviewme.template.domain.QuestionType; import reviewme.review.domain.Answer; import reviewme.review.service.dto.request.ReviewAnswerRequest; diff --git a/backend/src/main/java/reviewme/review/service/mapper/AnswerMapperFactory.java b/backend/src/main/java/reviewme/review/service/mapper/AnswerMapperFactory.java index 6dc804547..624c3ba81 100644 --- a/backend/src/main/java/reviewme/review/service/mapper/AnswerMapperFactory.java +++ b/backend/src/main/java/reviewme/review/service/mapper/AnswerMapperFactory.java @@ -3,7 +3,7 @@ import java.util.List; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Component; -import reviewme.question.domain.QuestionType; +import reviewme.template.domain.QuestionType; @Component @RequiredArgsConstructor diff --git a/backend/src/main/java/reviewme/review/service/mapper/CheckboxAnswerMapper.java b/backend/src/main/java/reviewme/review/service/mapper/CheckboxAnswerMapper.java index 3648e32f6..7fb87b0dc 100644 --- a/backend/src/main/java/reviewme/review/service/mapper/CheckboxAnswerMapper.java +++ b/backend/src/main/java/reviewme/review/service/mapper/CheckboxAnswerMapper.java @@ -1,7 +1,7 @@ package reviewme.review.service.mapper; import org.springframework.stereotype.Component; -import reviewme.question.domain.QuestionType; +import reviewme.template.domain.QuestionType; import reviewme.review.domain.CheckboxAnswer; import reviewme.review.service.dto.request.ReviewAnswerRequest; import reviewme.review.service.exception.CheckBoxAnswerIncludedTextException; diff --git a/backend/src/main/java/reviewme/review/service/mapper/ReviewDetailMapper.java b/backend/src/main/java/reviewme/review/service/mapper/ReviewDetailMapper.java index 7121d99b5..c2874c1c1 100644 --- a/backend/src/main/java/reviewme/review/service/mapper/ReviewDetailMapper.java +++ b/backend/src/main/java/reviewme/review/service/mapper/ReviewDetailMapper.java @@ -7,12 +7,12 @@ import java.util.stream.Collectors; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Component; -import reviewme.question.domain.OptionGroup; -import reviewme.question.domain.OptionItem; -import reviewme.question.domain.Question; -import reviewme.question.repository.OptionGroupRepository; -import reviewme.question.repository.OptionItemRepository; -import reviewme.question.repository.QuestionRepository; +import reviewme.template.domain.OptionGroup; +import reviewme.template.domain.OptionItem; +import reviewme.template.domain.Question; +import reviewme.template.repository.OptionGroupRepository; +import reviewme.template.repository.OptionItemRepository; +import reviewme.template.repository.QuestionRepository; import reviewme.review.domain.CheckboxAnswer; import reviewme.review.domain.CheckboxAnswerSelectedOption; import reviewme.review.domain.Review; diff --git a/backend/src/main/java/reviewme/review/service/mapper/ReviewGatherMapper.java b/backend/src/main/java/reviewme/review/service/mapper/ReviewGatherMapper.java index 2a1f4e135..d53fd0905 100644 --- a/backend/src/main/java/reviewme/review/service/mapper/ReviewGatherMapper.java +++ b/backend/src/main/java/reviewme/review/service/mapper/ReviewGatherMapper.java @@ -7,9 +7,9 @@ import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Component; import reviewme.highlight.domain.Highlight; -import reviewme.question.domain.OptionItem; -import reviewme.question.domain.Question; -import reviewme.question.repository.QuestionRepository; +import reviewme.template.domain.OptionItem; +import reviewme.template.domain.Question; +import reviewme.template.repository.QuestionRepository; import reviewme.review.domain.Answer; import reviewme.review.domain.CheckboxAnswer; import reviewme.review.domain.CheckboxAnswerSelectedOption; diff --git a/backend/src/main/java/reviewme/review/service/mapper/ReviewListMapper.java b/backend/src/main/java/reviewme/review/service/mapper/ReviewListMapper.java index aa882802a..ab5ec4327 100644 --- a/backend/src/main/java/reviewme/review/service/mapper/ReviewListMapper.java +++ b/backend/src/main/java/reviewme/review/service/mapper/ReviewListMapper.java @@ -5,9 +5,9 @@ import java.util.stream.Collectors; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Component; -import reviewme.question.domain.OptionItem; -import reviewme.question.domain.OptionType; -import reviewme.question.repository.OptionItemRepository; +import reviewme.template.domain.OptionItem; +import reviewme.template.domain.OptionType; +import reviewme.template.repository.OptionItemRepository; import reviewme.review.domain.CheckboxAnswer; import reviewme.review.domain.CheckboxAnswerSelectedOption; import reviewme.review.domain.Review; diff --git a/backend/src/main/java/reviewme/review/service/mapper/ReviewMapper.java b/backend/src/main/java/reviewme/review/service/mapper/ReviewMapper.java index 68ee776b9..58d0c6a6f 100644 --- a/backend/src/main/java/reviewme/review/service/mapper/ReviewMapper.java +++ b/backend/src/main/java/reviewme/review/service/mapper/ReviewMapper.java @@ -8,8 +8,8 @@ import lombok.AccessLevel; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Component; -import reviewme.question.domain.Question; -import reviewme.question.repository.QuestionRepository; +import reviewme.template.domain.Question; +import reviewme.template.repository.QuestionRepository; import reviewme.review.domain.Answer; import reviewme.review.domain.Review; import reviewme.review.service.dto.request.ReviewAnswerRequest; diff --git a/backend/src/main/java/reviewme/review/service/mapper/TextAnswerMapper.java b/backend/src/main/java/reviewme/review/service/mapper/TextAnswerMapper.java index afd47ac97..48bd55789 100644 --- a/backend/src/main/java/reviewme/review/service/mapper/TextAnswerMapper.java +++ b/backend/src/main/java/reviewme/review/service/mapper/TextAnswerMapper.java @@ -1,7 +1,7 @@ package reviewme.review.service.mapper; import org.springframework.stereotype.Component; -import reviewme.question.domain.QuestionType; +import reviewme.template.domain.QuestionType; import reviewme.review.domain.TextAnswer; import reviewme.review.service.dto.request.ReviewAnswerRequest; import reviewme.review.service.exception.TextAnswerIncludedOptionItemException; diff --git a/backend/src/main/java/reviewme/review/service/mapper/UnsupportedQuestionTypeException.java b/backend/src/main/java/reviewme/review/service/mapper/UnsupportedQuestionTypeException.java index b08870515..26a22f0fd 100644 --- a/backend/src/main/java/reviewme/review/service/mapper/UnsupportedQuestionTypeException.java +++ b/backend/src/main/java/reviewme/review/service/mapper/UnsupportedQuestionTypeException.java @@ -2,7 +2,7 @@ import lombok.extern.slf4j.Slf4j; import reviewme.global.exception.DataInconsistencyException; -import reviewme.question.domain.QuestionType; +import reviewme.template.domain.QuestionType; @Slf4j public class UnsupportedQuestionTypeException extends DataInconsistencyException { diff --git a/backend/src/main/java/reviewme/review/service/validator/AnswerValidator.java b/backend/src/main/java/reviewme/review/service/validator/AnswerValidator.java index 11162cc26..bb9f85434 100644 --- a/backend/src/main/java/reviewme/review/service/validator/AnswerValidator.java +++ b/backend/src/main/java/reviewme/review/service/validator/AnswerValidator.java @@ -1,10 +1,31 @@ package reviewme.review.service.validator; -import reviewme.review.domain.Answer; +import java.util.Collection; +import java.util.Set; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Component; +import reviewme.review.repository.AnswerRepository; +import reviewme.review.service.exception.QuestionNotContainingAnswersException; +import reviewme.review.service.exception.ReviewGroupNotContainingAnswersException; +import reviewme.reviewgroup.domain.ReviewGroup; -public interface AnswerValidator { +@Component +@RequiredArgsConstructor +public class AnswerValidator { - boolean supports(Class answerClass); + private final AnswerRepository answerRepository; - void validate(Answer answer); + public void validateQuestionContainsAnswers(long questionId, Collection answerIds) { + Set receivedAnswerIds = answerRepository.findIdsByQuestionId(questionId); + if (!receivedAnswerIds.containsAll(answerIds)) { + throw new QuestionNotContainingAnswersException(questionId, answerIds); + } + } + + public void validateReviewGroupContainsAnswers(ReviewGroup reviewGroup, Collection answerIds) { + Set receivedAnswerIds = answerRepository.findIdsByReviewGroupId(reviewGroup.getId()); + if (!receivedAnswerIds.containsAll(answerIds)) { + throw new ReviewGroupNotContainingAnswersException(reviewGroup.getId(), answerIds); + } + } } diff --git a/backend/src/main/java/reviewme/review/service/validator/CheckboxAnswerValidator.java b/backend/src/main/java/reviewme/review/service/validator/CheckboxTypedAnswerValidator.java similarity index 89% rename from backend/src/main/java/reviewme/review/service/validator/CheckboxAnswerValidator.java rename to backend/src/main/java/reviewme/review/service/validator/CheckboxTypedAnswerValidator.java index 62d39728b..d6cd50eec 100644 --- a/backend/src/main/java/reviewme/review/service/validator/CheckboxAnswerValidator.java +++ b/backend/src/main/java/reviewme/review/service/validator/CheckboxTypedAnswerValidator.java @@ -5,12 +5,12 @@ import lombok.AccessLevel; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Component; -import reviewme.question.domain.OptionGroup; -import reviewme.question.domain.OptionItem; -import reviewme.question.domain.Question; -import reviewme.question.repository.OptionGroupRepository; -import reviewme.question.repository.OptionItemRepository; -import reviewme.question.repository.QuestionRepository; +import reviewme.template.domain.OptionGroup; +import reviewme.template.domain.OptionItem; +import reviewme.template.domain.Question; +import reviewme.template.repository.OptionGroupRepository; +import reviewme.template.repository.OptionItemRepository; +import reviewme.template.repository.QuestionRepository; import reviewme.review.domain.Answer; import reviewme.review.domain.CheckboxAnswerSelectedOption; import reviewme.review.domain.CheckboxAnswer; @@ -21,7 +21,7 @@ @Component @RequiredArgsConstructor(access = AccessLevel.PROTECTED) -public class CheckboxAnswerValidator implements AnswerValidator { +public class CheckboxTypedAnswerValidator implements TypedAnswerValidator { private final QuestionRepository questionRepository; private final OptionGroupRepository optionGroupRepository; diff --git a/backend/src/main/java/reviewme/review/service/validator/ReviewValidator.java b/backend/src/main/java/reviewme/review/service/validator/ReviewValidator.java index 2906a8507..96fb55ec4 100644 --- a/backend/src/main/java/reviewme/review/service/validator/ReviewValidator.java +++ b/backend/src/main/java/reviewme/review/service/validator/ReviewValidator.java @@ -7,23 +7,23 @@ import lombok.AccessLevel; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Component; -import reviewme.question.domain.Question; -import reviewme.question.repository.QuestionRepository; import reviewme.review.domain.Answer; -import reviewme.review.domain.CheckboxAnswerSelectedOption; import reviewme.review.domain.CheckboxAnswer; +import reviewme.review.domain.CheckboxAnswerSelectedOption; import reviewme.review.domain.Review; import reviewme.review.service.exception.MissingRequiredQuestionException; import reviewme.review.service.exception.SubmittedQuestionAndProvidedQuestionMismatchException; +import reviewme.template.domain.Question; import reviewme.template.domain.Section; import reviewme.template.domain.SectionQuestion; +import reviewme.template.repository.QuestionRepository; import reviewme.template.repository.SectionRepository; @Component @RequiredArgsConstructor(access = AccessLevel.PROTECTED) public class ReviewValidator { - private final AnswerValidatorFactory answerValidatorFactory; + private final TypedAnswerValidatorFactory typedAnswerValidatorFactory; private final SectionRepository sectionRepository; private final QuestionRepository questionRepository; @@ -36,8 +36,8 @@ public void validate(Review review) { private void validateAnswer(List answers) { for (Answer answer : answers) { - AnswerValidator validator = answerValidatorFactory.getAnswerValidator(answer.getClass()); - validator.validate(answer); + typedAnswerValidatorFactory.getAnswerValidator(answer.getClass()) + .validate(answer); } } diff --git a/backend/src/main/java/reviewme/review/service/validator/TextAnswerValidator.java b/backend/src/main/java/reviewme/review/service/validator/TextTypedAnswerValidator.java similarity index 88% rename from backend/src/main/java/reviewme/review/service/validator/TextAnswerValidator.java rename to backend/src/main/java/reviewme/review/service/validator/TextTypedAnswerValidator.java index 78a0701dd..0dffa56c1 100644 --- a/backend/src/main/java/reviewme/review/service/validator/TextAnswerValidator.java +++ b/backend/src/main/java/reviewme/review/service/validator/TextTypedAnswerValidator.java @@ -3,8 +3,8 @@ import lombok.AccessLevel; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Component; -import reviewme.question.domain.Question; -import reviewme.question.repository.QuestionRepository; +import reviewme.template.domain.Question; +import reviewme.template.repository.QuestionRepository; import reviewme.review.domain.Answer; import reviewme.review.domain.TextAnswer; import reviewme.review.service.exception.InvalidTextAnswerLengthException; @@ -12,9 +12,8 @@ @Component @RequiredArgsConstructor(access = AccessLevel.PROTECTED) -public class TextAnswerValidator implements AnswerValidator { +public class TextTypedAnswerValidator implements TypedAnswerValidator { - private static final int ZERO_LENGTH = 0; private static final int MIN_LENGTH = 20; private static final int MAX_LENGTH = 1_000; diff --git a/backend/src/main/java/reviewme/review/service/validator/TypedAnswerValidator.java b/backend/src/main/java/reviewme/review/service/validator/TypedAnswerValidator.java new file mode 100644 index 000000000..2bc060c52 --- /dev/null +++ b/backend/src/main/java/reviewme/review/service/validator/TypedAnswerValidator.java @@ -0,0 +1,10 @@ +package reviewme.review.service.validator; + +import reviewme.review.domain.Answer; + +public interface TypedAnswerValidator { + + boolean supports(Class answerClass); + + void validate(Answer answer); +} diff --git a/backend/src/main/java/reviewme/review/service/validator/AnswerValidatorFactory.java b/backend/src/main/java/reviewme/review/service/validator/TypedAnswerValidatorFactory.java similarity index 68% rename from backend/src/main/java/reviewme/review/service/validator/AnswerValidatorFactory.java rename to backend/src/main/java/reviewme/review/service/validator/TypedAnswerValidatorFactory.java index b1adc5933..a0ff54733 100644 --- a/backend/src/main/java/reviewme/review/service/validator/AnswerValidatorFactory.java +++ b/backend/src/main/java/reviewme/review/service/validator/TypedAnswerValidatorFactory.java @@ -8,12 +8,12 @@ @Component @RequiredArgsConstructor(access = AccessLevel.PROTECTED) -public class AnswerValidatorFactory { +public class TypedAnswerValidatorFactory { - private final List answerValidators; + private final List validators; - public AnswerValidator getAnswerValidator(Class answerClass) { - return answerValidators.stream() + public TypedAnswerValidator getAnswerValidator(Class answerClass) { + return validators.stream() .filter(validator -> validator.supports(answerClass)) .findFirst() .orElseThrow(() -> new UnsupportedAnswerTypeException(answerClass)); diff --git a/backend/src/main/java/reviewme/question/domain/OptionGroup.java b/backend/src/main/java/reviewme/template/domain/OptionGroup.java similarity index 96% rename from backend/src/main/java/reviewme/question/domain/OptionGroup.java rename to backend/src/main/java/reviewme/template/domain/OptionGroup.java index 61aa3d23a..a5ee115ca 100644 --- a/backend/src/main/java/reviewme/question/domain/OptionGroup.java +++ b/backend/src/main/java/reviewme/template/domain/OptionGroup.java @@ -1,4 +1,4 @@ -package reviewme.question.domain; +package reviewme.template.domain; import jakarta.persistence.Column; import jakarta.persistence.Entity; diff --git a/backend/src/main/java/reviewme/question/domain/OptionItem.java b/backend/src/main/java/reviewme/template/domain/OptionItem.java similarity index 97% rename from backend/src/main/java/reviewme/question/domain/OptionItem.java rename to backend/src/main/java/reviewme/template/domain/OptionItem.java index 59b29bc3b..7232dd3df 100644 --- a/backend/src/main/java/reviewme/question/domain/OptionItem.java +++ b/backend/src/main/java/reviewme/template/domain/OptionItem.java @@ -1,4 +1,4 @@ -package reviewme.question.domain; +package reviewme.template.domain; import jakarta.persistence.Column; import jakarta.persistence.Entity; diff --git a/backend/src/main/java/reviewme/question/domain/OptionType.java b/backend/src/main/java/reviewme/template/domain/OptionType.java similarity index 61% rename from backend/src/main/java/reviewme/question/domain/OptionType.java rename to backend/src/main/java/reviewme/template/domain/OptionType.java index dfa86920b..80e4e2c1b 100644 --- a/backend/src/main/java/reviewme/question/domain/OptionType.java +++ b/backend/src/main/java/reviewme/template/domain/OptionType.java @@ -1,4 +1,4 @@ -package reviewme.question.domain; +package reviewme.template.domain; public enum OptionType { CATEGORY, diff --git a/backend/src/main/java/reviewme/question/domain/Question.java b/backend/src/main/java/reviewme/template/domain/Question.java similarity index 97% rename from backend/src/main/java/reviewme/question/domain/Question.java rename to backend/src/main/java/reviewme/template/domain/Question.java index f59e4ae87..f4384d854 100644 --- a/backend/src/main/java/reviewme/question/domain/Question.java +++ b/backend/src/main/java/reviewme/template/domain/Question.java @@ -1,4 +1,4 @@ -package reviewme.question.domain; +package reviewme.template.domain; import jakarta.persistence.Column; import jakarta.persistence.Entity; diff --git a/backend/src/main/java/reviewme/question/domain/QuestionType.java b/backend/src/main/java/reviewme/template/domain/QuestionType.java similarity index 64% rename from backend/src/main/java/reviewme/question/domain/QuestionType.java rename to backend/src/main/java/reviewme/template/domain/QuestionType.java index 863ba56e5..78b84fb58 100644 --- a/backend/src/main/java/reviewme/question/domain/QuestionType.java +++ b/backend/src/main/java/reviewme/template/domain/QuestionType.java @@ -1,4 +1,4 @@ -package reviewme.question.domain; +package reviewme.template.domain; public enum QuestionType { CHECKBOX, diff --git a/backend/src/main/java/reviewme/question/repository/OptionGroupRepository.java b/backend/src/main/java/reviewme/template/repository/OptionGroupRepository.java similarity index 87% rename from backend/src/main/java/reviewme/question/repository/OptionGroupRepository.java rename to backend/src/main/java/reviewme/template/repository/OptionGroupRepository.java index ad2994537..ce57a64e7 100644 --- a/backend/src/main/java/reviewme/question/repository/OptionGroupRepository.java +++ b/backend/src/main/java/reviewme/template/repository/OptionGroupRepository.java @@ -1,11 +1,11 @@ -package reviewme.question.repository; +package reviewme.template.repository; import java.util.List; import java.util.Optional; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Query; import org.springframework.stereotype.Repository; -import reviewme.question.domain.OptionGroup; +import reviewme.template.domain.OptionGroup; @Repository public interface OptionGroupRepository extends JpaRepository { diff --git a/backend/src/main/java/reviewme/question/repository/OptionItemRepository.java b/backend/src/main/java/reviewme/template/repository/OptionItemRepository.java similarity index 86% rename from backend/src/main/java/reviewme/question/repository/OptionItemRepository.java rename to backend/src/main/java/reviewme/template/repository/OptionItemRepository.java index e42274c33..305df2ef1 100644 --- a/backend/src/main/java/reviewme/question/repository/OptionItemRepository.java +++ b/backend/src/main/java/reviewme/template/repository/OptionItemRepository.java @@ -1,11 +1,11 @@ -package reviewme.question.repository; +package reviewme.template.repository; import java.util.List; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Query; import org.springframework.stereotype.Repository; -import reviewme.question.domain.OptionItem; -import reviewme.question.domain.OptionType; +import reviewme.template.domain.OptionItem; +import reviewme.template.domain.OptionType; @Repository public interface OptionItemRepository extends JpaRepository { diff --git a/backend/src/main/java/reviewme/question/repository/QuestionRepository.java b/backend/src/main/java/reviewme/template/repository/QuestionRepository.java similarity index 92% rename from backend/src/main/java/reviewme/question/repository/QuestionRepository.java rename to backend/src/main/java/reviewme/template/repository/QuestionRepository.java index 9db137d25..aa21a0167 100644 --- a/backend/src/main/java/reviewme/question/repository/QuestionRepository.java +++ b/backend/src/main/java/reviewme/template/repository/QuestionRepository.java @@ -1,12 +1,12 @@ -package reviewme.question.repository; +package reviewme.template.repository; import java.util.List; import java.util.Set; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Query; import org.springframework.stereotype.Repository; -import reviewme.question.domain.OptionItem; -import reviewme.question.domain.Question; +import reviewme.template.domain.OptionItem; +import reviewme.template.domain.Question; @Repository public interface QuestionRepository extends JpaRepository { diff --git a/backend/src/main/java/reviewme/template/service/TemplateService.java b/backend/src/main/java/reviewme/template/service/TemplateService.java index a49fc5160..1b6370878 100644 --- a/backend/src/main/java/reviewme/template/service/TemplateService.java +++ b/backend/src/main/java/reviewme/template/service/TemplateService.java @@ -3,9 +3,8 @@ import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; -import reviewme.review.service.exception.ReviewGroupNotFoundByReviewRequestCodeException; import reviewme.reviewgroup.domain.ReviewGroup; -import reviewme.reviewgroup.repository.ReviewGroupRepository; +import reviewme.reviewgroup.service.ReviewGroupService; import reviewme.template.service.dto.response.TemplateResponse; import reviewme.template.service.mapper.TemplateMapper; @@ -13,17 +12,12 @@ @RequiredArgsConstructor public class TemplateService { - private final ReviewGroupRepository reviewGroupRepository; + private final ReviewGroupService reviewGroupService; private final TemplateMapper templateMapper; @Transactional(readOnly = true) public TemplateResponse generateReviewForm(String reviewRequestCode) { - ReviewGroup reviewGroup = findReviewGroupByRequestCodeOrThrow(reviewRequestCode); + ReviewGroup reviewGroup = reviewGroupService.getReviewGroupByReviewRequestCode(reviewRequestCode); return templateMapper.mapToTemplateResponse(reviewGroup); } - - private ReviewGroup findReviewGroupByRequestCodeOrThrow(String reviewRequestCode) { - return reviewGroupRepository.findByReviewRequestCode(reviewRequestCode) - .orElseThrow(() -> new ReviewGroupNotFoundByReviewRequestCodeException(reviewRequestCode)); - } } diff --git a/backend/src/main/java/reviewme/template/service/mapper/TemplateMapper.java b/backend/src/main/java/reviewme/template/service/mapper/TemplateMapper.java index 02b6084f1..7151003d5 100644 --- a/backend/src/main/java/reviewme/template/service/mapper/TemplateMapper.java +++ b/backend/src/main/java/reviewme/template/service/mapper/TemplateMapper.java @@ -3,12 +3,12 @@ import java.util.List; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Component; -import reviewme.question.domain.OptionGroup; -import reviewme.question.domain.OptionItem; -import reviewme.question.domain.Question; -import reviewme.question.repository.OptionGroupRepository; -import reviewme.question.repository.OptionItemRepository; -import reviewme.question.repository.QuestionRepository; +import reviewme.template.domain.OptionGroup; +import reviewme.template.domain.OptionItem; +import reviewme.template.domain.Question; +import reviewme.template.repository.OptionGroupRepository; +import reviewme.template.repository.OptionItemRepository; +import reviewme.template.repository.QuestionRepository; import reviewme.reviewgroup.domain.ReviewGroup; import reviewme.template.domain.Section; import reviewme.template.domain.SectionQuestion; diff --git a/backend/src/test/java/reviewme/api/ReviewApiTest.java b/backend/src/test/java/reviewme/api/ReviewApiTest.java index 5add4cfbd..4552b02d5 100644 --- a/backend/src/test/java/reviewme/api/ReviewApiTest.java +++ b/backend/src/test/java/reviewme/api/ReviewApiTest.java @@ -3,7 +3,6 @@ import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.anyLong; -import static org.mockito.ArgumentMatchers.anyString; import static org.springframework.restdocs.cookies.CookieDocumentation.cookieWithName; import static org.springframework.restdocs.cookies.CookieDocumentation.requestCookies; import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.document; @@ -22,7 +21,7 @@ import org.springframework.restdocs.mockmvc.RestDocumentationResultHandler; import org.springframework.restdocs.payload.FieldDescriptor; import org.springframework.restdocs.request.ParameterDescriptor; -import reviewme.question.domain.QuestionType; +import reviewme.template.domain.QuestionType; import reviewme.review.service.dto.request.ReviewRegisterRequest; import reviewme.review.service.dto.response.gathered.HighlightResponse; import reviewme.review.service.dto.response.gathered.RangeResponse; diff --git a/backend/src/test/java/reviewme/api/TemplateFixture.java b/backend/src/test/java/reviewme/api/TemplateFixture.java index aba719fbb..7a8f3c194 100644 --- a/backend/src/test/java/reviewme/api/TemplateFixture.java +++ b/backend/src/test/java/reviewme/api/TemplateFixture.java @@ -2,7 +2,7 @@ import java.time.LocalDate; import java.util.List; -import reviewme.question.domain.QuestionType; +import reviewme.template.domain.QuestionType; import reviewme.review.service.dto.response.detail.OptionGroupAnswerResponse; import reviewme.review.service.dto.response.detail.OptionItemAnswerResponse; import reviewme.review.service.dto.response.detail.QuestionAnswerResponse; diff --git a/backend/src/test/java/reviewme/config/CorsConfigTest.java b/backend/src/test/java/reviewme/config/cors/CorsConfigTest.java similarity index 93% rename from backend/src/test/java/reviewme/config/CorsConfigTest.java rename to backend/src/test/java/reviewme/config/cors/CorsConfigTest.java index 90af4a342..d7f20bfd2 100644 --- a/backend/src/test/java/reviewme/config/CorsConfigTest.java +++ b/backend/src/test/java/reviewme/config/cors/CorsConfigTest.java @@ -1,4 +1,4 @@ -package reviewme.config; +package reviewme.config.cors; import org.junit.jupiter.api.BeforeEach; import org.springframework.beans.factory.annotation.Autowired; @@ -32,6 +32,7 @@ void setUp() { static class TestController { @RequestMapping("/test") public void test() { + // Testing controller calls, no-op } } } diff --git a/backend/src/test/java/reviewme/config/ExternalCorsConfigTest.java b/backend/src/test/java/reviewme/config/cors/ExternalCorsConfigTest.java similarity index 98% rename from backend/src/test/java/reviewme/config/ExternalCorsConfigTest.java rename to backend/src/test/java/reviewme/config/cors/ExternalCorsConfigTest.java index 095bb1bc7..39445b70f 100644 --- a/backend/src/test/java/reviewme/config/ExternalCorsConfigTest.java +++ b/backend/src/test/java/reviewme/config/cors/ExternalCorsConfigTest.java @@ -1,4 +1,4 @@ -package reviewme.config; +package reviewme.config.cors; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.options; import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; diff --git a/backend/src/test/java/reviewme/config/LocalCorsConfigTest.java b/backend/src/test/java/reviewme/config/cors/LocalCorsConfigTest.java similarity index 97% rename from backend/src/test/java/reviewme/config/LocalCorsConfigTest.java rename to backend/src/test/java/reviewme/config/cors/LocalCorsConfigTest.java index cd050b988..214de0857 100644 --- a/backend/src/test/java/reviewme/config/LocalCorsConfigTest.java +++ b/backend/src/test/java/reviewme/config/cors/LocalCorsConfigTest.java @@ -1,4 +1,4 @@ -package reviewme.config; +package reviewme.config.cors; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.options; import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; diff --git a/backend/src/test/java/reviewme/global/RequestLimitInterceptorTest.java b/backend/src/test/java/reviewme/config/requestlimit/RequestLimitInterceptorTest.java similarity index 93% rename from backend/src/test/java/reviewme/global/RequestLimitInterceptorTest.java rename to backend/src/test/java/reviewme/config/requestlimit/RequestLimitInterceptorTest.java index 998639691..969040683 100644 --- a/backend/src/test/java/reviewme/global/RequestLimitInterceptorTest.java +++ b/backend/src/test/java/reviewme/config/requestlimit/RequestLimitInterceptorTest.java @@ -1,4 +1,4 @@ -package reviewme.global; +package reviewme.config.requestlimit; import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.assertj.core.api.AssertionsForClassTypes.assertThat; @@ -14,8 +14,6 @@ import org.junit.jupiter.api.Test; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.core.ValueOperations; -import reviewme.config.RequestLimitProperties; -import reviewme.global.exception.TooManyRequestException; class RequestLimitInterceptorTest { @@ -41,7 +39,6 @@ void setUp() { @Test void POST_์š”์ฒญ์ด_์•„๋‹ˆ๋ฉด_ํ†ต๊ณผํ•œ๋‹ค() { // given - HttpServletRequest request = mock(HttpServletRequest.class); given(request.getMethod()).willReturn("GET"); // when diff --git a/backend/src/test/java/reviewme/fixture/OptionGroupFixture.java b/backend/src/test/java/reviewme/fixture/OptionGroupFixture.java index 259a3ebcf..f880cbfb7 100644 --- a/backend/src/test/java/reviewme/fixture/OptionGroupFixture.java +++ b/backend/src/test/java/reviewme/fixture/OptionGroupFixture.java @@ -1,6 +1,6 @@ package reviewme.fixture; -import reviewme.question.domain.OptionGroup; +import reviewme.template.domain.OptionGroup; public class OptionGroupFixture { diff --git a/backend/src/test/java/reviewme/fixture/OptionItemFixture.java b/backend/src/test/java/reviewme/fixture/OptionItemFixture.java index 3b7e50725..c076cb205 100644 --- a/backend/src/test/java/reviewme/fixture/OptionItemFixture.java +++ b/backend/src/test/java/reviewme/fixture/OptionItemFixture.java @@ -1,7 +1,7 @@ package reviewme.fixture; -import reviewme.question.domain.OptionItem; -import reviewme.question.domain.OptionType; +import reviewme.template.domain.OptionItem; +import reviewme.template.domain.OptionType; public class OptionItemFixture { diff --git a/backend/src/test/java/reviewme/fixture/QuestionFixture.java b/backend/src/test/java/reviewme/fixture/QuestionFixture.java index f4ce28b88..3484116af 100644 --- a/backend/src/test/java/reviewme/fixture/QuestionFixture.java +++ b/backend/src/test/java/reviewme/fixture/QuestionFixture.java @@ -1,7 +1,7 @@ package reviewme.fixture; -import reviewme.question.domain.Question; -import reviewme.question.domain.QuestionType; +import reviewme.template.domain.Question; +import reviewme.template.domain.QuestionType; public class QuestionFixture { diff --git a/backend/src/test/java/reviewme/highlight/domain/HighlightedLinesTest.java b/backend/src/test/java/reviewme/highlight/domain/HighlightedLinesTest.java index 53d81c209..d3e4a443c 100644 --- a/backend/src/test/java/reviewme/highlight/domain/HighlightedLinesTest.java +++ b/backend/src/test/java/reviewme/highlight/domain/HighlightedLinesTest.java @@ -84,4 +84,21 @@ class HighlightedLinesTest { assertThatCode(() -> highlightedLines.addRange(invalidLineIndex, 0, 1)) .isInstanceOf(InvalidHighlightLineIndexException.class); } + + @Test + void ํ•˜์ด๋ผ์ดํŠธ๊ฐ€_์กด์žฌํ•˜๋Š”_๋ถ€๋ถ„๋งŒ_์—”ํ‹ฐํ‹ฐ๋กœ_๋ณ€ํ™˜ํ•œ๋‹ค() { + // given + HighlightedLines lines = new HighlightedLines("0\n11\n222"); + lines.addRange(0, 0, 0); + lines.addRange(2, 2, 2); + + // when + List highlights = lines.toHighlights(1L); + + // then + assertThat(highlights).containsExactly( + new Highlight(1L, 0, new HighlightRange(0, 0)), + new Highlight(1L, 2, new HighlightRange(2, 2)) + ); + } } diff --git a/backend/src/test/java/reviewme/highlight/repository/HighlightRepositoryTest.java b/backend/src/test/java/reviewme/highlight/repository/HighlightRepositoryTest.java index 40b584f47..528ccbfff 100644 --- a/backend/src/test/java/reviewme/highlight/repository/HighlightRepositoryTest.java +++ b/backend/src/test/java/reviewme/highlight/repository/HighlightRepositoryTest.java @@ -2,13 +2,21 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertAll; +import static reviewme.fixture.ReviewGroupFixture.๋ฆฌ๋ทฐ_๊ทธ๋ฃน; +import java.util.ArrayList; import java.util.List; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; import reviewme.highlight.domain.Highlight; import reviewme.highlight.domain.HighlightRange; +import reviewme.review.domain.Answer; +import reviewme.review.domain.Review; +import reviewme.review.domain.TextAnswer; +import reviewme.review.repository.ReviewRepository; +import reviewme.reviewgroup.domain.ReviewGroup; +import reviewme.reviewgroup.repository.ReviewGroupRepository; @DataJpaTest class HighlightRepositoryTest { @@ -16,6 +24,30 @@ class HighlightRepositoryTest { @Autowired private HighlightRepository highlightRepository; + @Autowired + private ReviewRepository reviewRepository; + + @Autowired + private ReviewGroupRepository reviewGroupRepository; + + @Test + void ํ•œ_๋ฒˆ์—_์—ฌ๋Ÿฌ_ํ•˜์ด๋ผ์ดํŠธ๋ฅผ_๋ฒŒํฌ_์‚ฝ์ž…ํ•œ๋‹ค() { + // given + List highlights = List.of( + new Highlight(1L, 1, new HighlightRange(1, 2)), + new Highlight(1L, 1, new HighlightRange(3, 5)) + ); + + // when + highlightRepository.saveAll(highlights); + + // then + List actual = highlightRepository.findAllByAnswerIdsOrderedAsc(List.of(1L)); + assertThat(actual) + .extracting(Highlight::getHighlightRange) + .containsExactly(new HighlightRange(1, 2), new HighlightRange(3, 5)); + } + @Test void ํ•˜์ด๋ผ์ดํŠธ๋ฅผ_์ค„๋ฒˆํ˜ธ_์‹œ์ž‘_์ธ๋ฑ์Šค_์ˆœ์„œ๋Œ€๋กœ_์ •๋ ฌํ•ด์„œ_๊ฐ€์ ธ์˜จ๋‹ค() { // given @@ -44,4 +76,43 @@ class HighlightRepositoryTest { .containsExactly(1, 4, 2, 6, 3) ); } + + @Test + void ๊ทธ๋ฃน_์•„์ด๋””์™€_์งˆ๋ฌธ_์•„์ด๋””๋กœ_ํ•˜์ด๋ผ์ดํŠธ๋ฅผ_์‚ญ์ œํ•œ๋‹ค() { + // given + ReviewGroup reviewGroup1 = reviewGroupRepository.save(๋ฆฌ๋ทฐ_๊ทธ๋ฃน()); + ReviewGroup reviewGroup2 = reviewGroupRepository.save(๋ฆฌ๋ทฐ_๊ทธ๋ฃน()); + + List answers1 = List.of( + new TextAnswer(1L, "A1"), + new TextAnswer(2L, "A2"), + new TextAnswer(3L, "A3") + ); + List answers2 = List.of( + new TextAnswer(1L, "B1"), + new TextAnswer(2L, "B2"), + new TextAnswer(3L, "B3") + ); + reviewRepository.save(new Review(1L, reviewGroup1.getId(), answers1)); + reviewRepository.save(new Review(2L, reviewGroup2.getId(), answers2)); + + List answerIds = new ArrayList<>(); + answerIds.addAll(answers1.stream().map(Answer::getId).toList()); + answerIds.addAll(answers2.stream().map(Answer::getId).toList()); + + HighlightRange range = new HighlightRange(0, 1); + answerIds.stream() + .map(answerId -> new Highlight(answerId, 0, range)) + .forEach(highlightRepository::save); + + // when + highlightRepository.deleteByReviewGroupIdAndQuestionId(reviewGroup1.getId(), 1L); + + // then + List actual = highlightRepository.findAllByAnswerIdsOrderedAsc(answerIds); + assertAll( + () -> assertThat(actual).hasSize(5), + () -> assertThat(actual).extracting(Highlight::getAnswerId).doesNotContain(answers1.get(0).getId()) + ); + } } diff --git a/backend/src/test/java/reviewme/highlight/service/HighlightServiceTest.java b/backend/src/test/java/reviewme/highlight/service/HighlightServiceTest.java index 32eed36b8..c4ea9f3bb 100644 --- a/backend/src/test/java/reviewme/highlight/service/HighlightServiceTest.java +++ b/backend/src/test/java/reviewme/highlight/service/HighlightServiceTest.java @@ -17,7 +17,7 @@ import reviewme.highlight.service.dto.HighlightRequest; import reviewme.highlight.service.dto.HighlightedLineRequest; import reviewme.highlight.service.dto.HighlightsRequest; -import reviewme.question.repository.QuestionRepository; +import reviewme.template.repository.QuestionRepository; import reviewme.review.domain.Review; import reviewme.review.domain.TextAnswer; import reviewme.review.repository.ReviewRepository; @@ -102,7 +102,7 @@ class HighlightServiceTest { highlightService.editHighlight(highlightsRequest, reviewGroup); // then - List highlights = highlightRepository.findAll(); + List highlights = highlightRepository.findAllByAnswerIdsOrderedAsc(List.of(textAnswer.getId())); assertAll( () -> assertThat(highlights.get(0).getAnswerId()).isEqualTo(textAnswer.getId()), () -> assertThat(highlights.get(0).getHighlightRange()).isEqualTo( diff --git a/backend/src/test/java/reviewme/highlight/service/mapper/HighlightMapperTest.java b/backend/src/test/java/reviewme/highlight/service/mapper/HighlightMapperTest.java index 14a6639f9..66101cf31 100644 --- a/backend/src/test/java/reviewme/highlight/service/mapper/HighlightMapperTest.java +++ b/backend/src/test/java/reviewme/highlight/service/mapper/HighlightMapperTest.java @@ -17,7 +17,7 @@ import reviewme.highlight.service.dto.HighlightRequest; import reviewme.highlight.service.dto.HighlightedLineRequest; import reviewme.highlight.service.dto.HighlightsRequest; -import reviewme.question.repository.QuestionRepository; +import reviewme.template.repository.QuestionRepository; import reviewme.review.domain.Review; import reviewme.review.domain.TextAnswer; import reviewme.review.repository.ReviewRepository; diff --git a/backend/src/test/java/reviewme/highlight/service/validator/HighlightValidatorTest.java b/backend/src/test/java/reviewme/highlight/service/validator/HighlightValidatorTest.java deleted file mode 100644 index 84bf793d2..000000000 --- a/backend/src/test/java/reviewme/highlight/service/validator/HighlightValidatorTest.java +++ /dev/null @@ -1,109 +0,0 @@ -package reviewme.highlight.service.validator; - -import static org.assertj.core.api.Assertions.assertThatCode; -import static reviewme.fixture.QuestionFixture.์„œ์ˆ ํ˜•_ํ•„์ˆ˜_์งˆ๋ฌธ; -import static reviewme.fixture.ReviewGroupFixture.๋ฆฌ๋ทฐ_๊ทธ๋ฃน; -import static reviewme.fixture.SectionFixture.ํ•ญ์ƒ_๋ณด์ด๋Š”_์„น์…˜; -import static reviewme.fixture.TemplateFixture.ํ…œํ”Œ๋ฆฟ; - -import java.util.List; -import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; -import reviewme.highlight.service.dto.HighlightRequest; -import reviewme.highlight.service.dto.HighlightsRequest; -import reviewme.highlight.service.exception.SubmittedAnswerAndProvidedAnswerMismatchException; -import reviewme.question.repository.QuestionRepository; -import reviewme.review.domain.Review; -import reviewme.review.domain.TextAnswer; -import reviewme.review.repository.ReviewRepository; -import reviewme.reviewgroup.domain.ReviewGroup; -import reviewme.reviewgroup.repository.ReviewGroupRepository; -import reviewme.support.ServiceTest; -import reviewme.template.domain.Section; -import reviewme.template.domain.Template; -import reviewme.template.repository.SectionRepository; -import reviewme.template.repository.TemplateRepository; - -@ServiceTest -class HighlightValidatorTest { - - @Autowired - private HighlightValidator highlightValidator; - - @Autowired - private ReviewGroupRepository reviewGroupRepository; - - @Autowired - private ReviewRepository reviewRepository; - - @Autowired - private QuestionRepository questionRepository; - - @Autowired - private SectionRepository sectionRepository; - - @Autowired - private TemplateRepository templateRepository; - - @Test - void ํ•˜์ด๋ผ์ดํŠธ์˜_๋‹ต๋ณ€_id๊ฐ€_ํ•˜์ด๋ผ์ดํŠธ์˜_์งˆ๋ฌธ_id์—_ํ•ด๋‹นํ•˜๋Š”_๋‹ต๋ณ€์ด_์•„๋‹ˆ๋ฉด_์˜ˆ์™ธ๋ฅผ_๋ฐœ์ƒํ•œ๋‹ค() { - // given - long questionId1 = questionRepository.save(์„œ์ˆ ํ˜•_ํ•„์ˆ˜_์งˆ๋ฌธ()).getId(); - long questionId2 = questionRepository.save(์„œ์ˆ ํ˜•_ํ•„์ˆ˜_์งˆ๋ฌธ()).getId(); - Section section = sectionRepository.save(ํ•ญ์ƒ_๋ณด์ด๋Š”_์„น์…˜(List.of(questionId1, questionId2))); - Template template = templateRepository.save(ํ…œํ”Œ๋ฆฟ(List.of(section.getId()))); - - ReviewGroup reviewGroup = reviewGroupRepository.save(๋ฆฌ๋ทฐ_๊ทธ๋ฃน()); - TextAnswer textAnswer_Q1 = new TextAnswer(questionId1, "text answer 1"); - - HighlightRequest highlightRequest = new HighlightRequest(textAnswer_Q1.getId(), List.of()); - HighlightsRequest highlightsRequest = new HighlightsRequest(questionId2, List.of(highlightRequest)); - - // when && then - assertThatCode(() -> highlightValidator.validate(highlightsRequest, reviewGroup)) - .isInstanceOf(SubmittedAnswerAndProvidedAnswerMismatchException.class); - } - - @Test - void ํ•˜์ด๋ผ์ดํŠธ์˜_๋‹ต๋ณ€_id๊ฐ€_๋ฆฌ๋ทฐ_๊ทธ๋ฃน์—_๋‹ฌ๋ฆฐ_๋‹ต๋ณ€์ด_์•„๋‹ˆ๋ฉด_์˜ˆ์™ธ๋ฅผ_๋ฐœ์ƒํ•œ๋‹ค() { - // given - long questionId = questionRepository.save(์„œ์ˆ ํ˜•_ํ•„์ˆ˜_์งˆ๋ฌธ()).getId(); - Section section = sectionRepository.save(ํ•ญ์ƒ_๋ณด์ด๋Š”_์„น์…˜(List.of(questionId))); - Template template = templateRepository.save(ํ…œํ”Œ๋ฆฟ(List.of(section.getId()))); - - ReviewGroup reviewGroup1 = reviewGroupRepository.save(๋ฆฌ๋ทฐ_๊ทธ๋ฃน()); - ReviewGroup reviewGroup2 = reviewGroupRepository.save(๋ฆฌ๋ทฐ_๊ทธ๋ฃน()); - TextAnswer textAnswer1 = new TextAnswer(questionId, "text answer1"); - TextAnswer textAnswer2 = new TextAnswer(questionId, "text answer2"); - reviewRepository.saveAll(List.of( - new Review(template.getId(), reviewGroup1.getId(), List.of(textAnswer1)), - new Review(template.getId(), reviewGroup2.getId(), List.of(textAnswer2)) - )); - - HighlightRequest highlightRequest = new HighlightRequest(textAnswer2.getId(), List.of()); - HighlightsRequest highlightsRequest = new HighlightsRequest(1L, List.of(highlightRequest)); - - // when && then - assertThatCode(() -> highlightValidator.validate(highlightsRequest, reviewGroup1)) - .isInstanceOf(SubmittedAnswerAndProvidedAnswerMismatchException.class); - } - - @Test - void ํ•˜์ด๋ผ์ดํŠธ์˜_์งˆ๋ฌธ_id๊ฐ€_๋ฆฌ๋ทฐ_๊ทธ๋ฃน์˜_ํ…œํ”Œ๋ฆฟ์—_์†ํ•œ_์งˆ๋ฌธ์ด_์•„๋‹ˆ๋ฉด_์˜ˆ์™ธ๋ฅผ_๋ฐœ์ƒํ•œ๋‹ค() { - // given - long questionId1 = questionRepository.save(์„œ์ˆ ํ˜•_ํ•„์ˆ˜_์งˆ๋ฌธ()).getId(); - long questionId2 = questionRepository.save(์„œ์ˆ ํ˜•_ํ•„์ˆ˜_์งˆ๋ฌธ()).getId(); - Section section = sectionRepository.save(ํ•ญ์ƒ_๋ณด์ด๋Š”_์„น์…˜(List.of(questionId1))); - Template template = templateRepository.save(ํ…œํ”Œ๋ฆฟ(List.of(section.getId()))); - - ReviewGroup reviewGroup = reviewGroupRepository.save(๋ฆฌ๋ทฐ_๊ทธ๋ฃน()); - TextAnswer textAnswer_Q1 = new TextAnswer(questionId1, "text answer 1"); - - HighlightRequest highlightRequest = new HighlightRequest(textAnswer_Q1.getId(), List.of()); - HighlightsRequest highlightsRequest = new HighlightsRequest(questionId2, List.of(highlightRequest)); - - // when && then - assertThatCode(() -> highlightValidator.validate(highlightsRequest, reviewGroup)) - .isInstanceOf(SubmittedAnswerAndProvidedAnswerMismatchException.class); - } -} diff --git a/backend/src/test/java/reviewme/review/repository/AnswerRepositoryTest.java b/backend/src/test/java/reviewme/review/repository/AnswerRepositoryTest.java index e13ce1427..9d2ad447d 100644 --- a/backend/src/test/java/reviewme/review/repository/AnswerRepositoryTest.java +++ b/backend/src/test/java/reviewme/review/repository/AnswerRepositoryTest.java @@ -11,8 +11,8 @@ import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; -import reviewme.question.domain.Question; -import reviewme.question.repository.QuestionRepository; +import reviewme.template.domain.Question; +import reviewme.template.repository.QuestionRepository; import reviewme.review.domain.Answer; import reviewme.review.domain.Review; import reviewme.review.domain.TextAnswer; diff --git a/backend/src/test/java/reviewme/review/repository/ReviewRepositoryTest.java b/backend/src/test/java/reviewme/review/repository/ReviewRepositoryTest.java index 2149c7ed9..3855c1520 100644 --- a/backend/src/test/java/reviewme/review/repository/ReviewRepositoryTest.java +++ b/backend/src/test/java/reviewme/review/repository/ReviewRepositoryTest.java @@ -13,8 +13,8 @@ import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; -import reviewme.question.domain.Question; -import reviewme.question.repository.QuestionRepository; +import reviewme.template.domain.Question; +import reviewme.template.repository.QuestionRepository; import reviewme.review.domain.Review; import reviewme.reviewgroup.domain.ReviewGroup; import reviewme.reviewgroup.repository.ReviewGroupRepository; diff --git a/backend/src/test/java/reviewme/review/service/ReviewDetailLookupServiceTest.java b/backend/src/test/java/reviewme/review/service/ReviewDetailLookupServiceTest.java index ab296d796..236143e75 100644 --- a/backend/src/test/java/reviewme/review/service/ReviewDetailLookupServiceTest.java +++ b/backend/src/test/java/reviewme/review/service/ReviewDetailLookupServiceTest.java @@ -17,12 +17,12 @@ import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; -import reviewme.question.domain.OptionGroup; -import reviewme.question.domain.OptionItem; -import reviewme.question.domain.Question; -import reviewme.question.repository.OptionGroupRepository; -import reviewme.question.repository.OptionItemRepository; -import reviewme.question.repository.QuestionRepository; +import reviewme.template.domain.OptionGroup; +import reviewme.template.domain.OptionItem; +import reviewme.template.domain.Question; +import reviewme.template.repository.OptionGroupRepository; +import reviewme.template.repository.OptionItemRepository; +import reviewme.template.repository.QuestionRepository; import reviewme.review.domain.Answer; import reviewme.review.domain.CheckboxAnswer; import reviewme.review.domain.Review; diff --git a/backend/src/test/java/reviewme/review/service/ReviewGatheredLookupServiceTest.java b/backend/src/test/java/reviewme/review/service/ReviewGatheredLookupServiceTest.java index 141992950..f6c8c4690 100644 --- a/backend/src/test/java/reviewme/review/service/ReviewGatheredLookupServiceTest.java +++ b/backend/src/test/java/reviewme/review/service/ReviewGatheredLookupServiceTest.java @@ -18,14 +18,14 @@ import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; -import reviewme.question.domain.OptionGroup; -import reviewme.question.domain.OptionItem; -import reviewme.question.domain.OptionType; -import reviewme.question.domain.Question; -import reviewme.question.domain.QuestionType; -import reviewme.question.repository.OptionGroupRepository; -import reviewme.question.repository.OptionItemRepository; -import reviewme.question.repository.QuestionRepository; +import reviewme.template.domain.OptionGroup; +import reviewme.template.domain.OptionItem; +import reviewme.template.domain.OptionType; +import reviewme.template.domain.Question; +import reviewme.template.domain.QuestionType; +import reviewme.template.repository.OptionGroupRepository; +import reviewme.template.repository.OptionItemRepository; +import reviewme.template.repository.QuestionRepository; import reviewme.review.domain.CheckboxAnswer; import reviewme.review.domain.Review; import reviewme.review.domain.TextAnswer; diff --git a/backend/src/test/java/reviewme/review/service/ReviewListLookupServiceTest.java b/backend/src/test/java/reviewme/review/service/ReviewListLookupServiceTest.java index d8384afe5..ebc559924 100644 --- a/backend/src/test/java/reviewme/review/service/ReviewListLookupServiceTest.java +++ b/backend/src/test/java/reviewme/review/service/ReviewListLookupServiceTest.java @@ -12,12 +12,12 @@ import java.util.List; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; -import reviewme.question.domain.OptionGroup; -import reviewme.question.domain.OptionItem; -import reviewme.question.domain.Question; -import reviewme.question.repository.OptionGroupRepository; -import reviewme.question.repository.OptionItemRepository; -import reviewme.question.repository.QuestionRepository; +import reviewme.template.domain.OptionGroup; +import reviewme.template.domain.OptionItem; +import reviewme.template.domain.Question; +import reviewme.template.repository.OptionGroupRepository; +import reviewme.template.repository.OptionItemRepository; +import reviewme.template.repository.QuestionRepository; import reviewme.review.domain.CheckboxAnswer; import reviewme.review.domain.Review; import reviewme.review.domain.TextAnswer; diff --git a/backend/src/test/java/reviewme/review/service/ReviewRegisterServiceTest.java b/backend/src/test/java/reviewme/review/service/ReviewRegisterServiceTest.java index 73ab64897..5852dae7c 100644 --- a/backend/src/test/java/reviewme/review/service/ReviewRegisterServiceTest.java +++ b/backend/src/test/java/reviewme/review/service/ReviewRegisterServiceTest.java @@ -15,12 +15,12 @@ import java.util.List; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; -import reviewme.question.domain.OptionGroup; -import reviewme.question.domain.OptionItem; -import reviewme.question.domain.Question; -import reviewme.question.repository.OptionGroupRepository; -import reviewme.question.repository.OptionItemRepository; -import reviewme.question.repository.QuestionRepository; +import reviewme.template.domain.OptionGroup; +import reviewme.template.domain.OptionItem; +import reviewme.template.domain.Question; +import reviewme.template.repository.OptionGroupRepository; +import reviewme.template.repository.OptionItemRepository; +import reviewme.template.repository.QuestionRepository; import reviewme.review.domain.CheckboxAnswer; import reviewme.review.domain.Review; import reviewme.review.domain.TextAnswer; diff --git a/backend/src/test/java/reviewme/review/service/ReviewSummaryServiceTest.java b/backend/src/test/java/reviewme/review/service/ReviewSummaryServiceTest.java index 2a2ffa7a5..0f83f4c3f 100644 --- a/backend/src/test/java/reviewme/review/service/ReviewSummaryServiceTest.java +++ b/backend/src/test/java/reviewme/review/service/ReviewSummaryServiceTest.java @@ -10,8 +10,8 @@ import java.util.List; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; -import reviewme.question.domain.Question; -import reviewme.question.repository.QuestionRepository; +import reviewme.template.domain.Question; +import reviewme.template.repository.QuestionRepository; import reviewme.review.domain.Review; import reviewme.review.repository.ReviewRepository; import reviewme.review.service.dto.response.list.ReceivedReviewsSummaryResponse; diff --git a/backend/src/test/java/reviewme/review/service/mapper/AnswerMapperFactoryTest.java b/backend/src/test/java/reviewme/review/service/mapper/AnswerMapperFactoryTest.java index 25d1b5018..bdf37e905 100644 --- a/backend/src/test/java/reviewme/review/service/mapper/AnswerMapperFactoryTest.java +++ b/backend/src/test/java/reviewme/review/service/mapper/AnswerMapperFactoryTest.java @@ -8,7 +8,7 @@ import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.boot.test.system.CapturedOutput; import org.springframework.boot.test.system.OutputCaptureExtension; -import reviewme.question.domain.QuestionType; +import reviewme.template.domain.QuestionType; import reviewme.review.domain.Answer; import reviewme.review.service.dto.request.ReviewAnswerRequest; diff --git a/backend/src/test/java/reviewme/review/service/mapper/ReviewGatherMapperTest.java b/backend/src/test/java/reviewme/review/service/mapper/ReviewGatherMapperTest.java index 1e411f13e..63fcd7615 100644 --- a/backend/src/test/java/reviewme/review/service/mapper/ReviewGatherMapperTest.java +++ b/backend/src/test/java/reviewme/review/service/mapper/ReviewGatherMapperTest.java @@ -12,12 +12,12 @@ import org.assertj.core.groups.Tuple; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; -import reviewme.question.domain.OptionGroup; -import reviewme.question.domain.OptionItem; -import reviewme.question.domain.Question; -import reviewme.question.repository.OptionGroupRepository; -import reviewme.question.repository.OptionItemRepository; -import reviewme.question.repository.QuestionRepository; +import reviewme.template.domain.OptionGroup; +import reviewme.template.domain.OptionItem; +import reviewme.template.domain.Question; +import reviewme.template.repository.OptionGroupRepository; +import reviewme.template.repository.OptionItemRepository; +import reviewme.template.repository.QuestionRepository; import reviewme.review.domain.CheckboxAnswer; import reviewme.review.domain.Review; import reviewme.review.domain.TextAnswer; diff --git a/backend/src/test/java/reviewme/review/service/mapper/ReviewListMapperTest.java b/backend/src/test/java/reviewme/review/service/mapper/ReviewListMapperTest.java index 0cdfe0a32..0032b7cb2 100644 --- a/backend/src/test/java/reviewme/review/service/mapper/ReviewListMapperTest.java +++ b/backend/src/test/java/reviewme/review/service/mapper/ReviewListMapperTest.java @@ -10,8 +10,8 @@ import java.util.List; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; -import reviewme.question.domain.Question; -import reviewme.question.repository.QuestionRepository; +import reviewme.template.domain.Question; +import reviewme.template.repository.QuestionRepository; import reviewme.review.domain.Review; import reviewme.review.domain.TextAnswer; import reviewme.review.repository.ReviewRepository; diff --git a/backend/src/test/java/reviewme/review/service/mapper/ReviewMapperTest.java b/backend/src/test/java/reviewme/review/service/mapper/ReviewMapperTest.java index 8ca15f312..4065c63de 100644 --- a/backend/src/test/java/reviewme/review/service/mapper/ReviewMapperTest.java +++ b/backend/src/test/java/reviewme/review/service/mapper/ReviewMapperTest.java @@ -16,12 +16,12 @@ import java.util.List; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; -import reviewme.question.domain.OptionGroup; -import reviewme.question.domain.OptionItem; -import reviewme.question.domain.Question; -import reviewme.question.repository.OptionGroupRepository; -import reviewme.question.repository.OptionItemRepository; -import reviewme.question.repository.QuestionRepository; +import reviewme.template.domain.OptionGroup; +import reviewme.template.domain.OptionItem; +import reviewme.template.domain.Question; +import reviewme.template.repository.OptionGroupRepository; +import reviewme.template.repository.OptionItemRepository; +import reviewme.template.repository.QuestionRepository; import reviewme.review.domain.CheckboxAnswer; import reviewme.review.domain.Review; import reviewme.review.domain.TextAnswer; diff --git a/backend/src/test/java/reviewme/review/service/validator/AnswerValidatorTest.java b/backend/src/test/java/reviewme/review/service/validator/AnswerValidatorTest.java new file mode 100644 index 000000000..9cce52a1b --- /dev/null +++ b/backend/src/test/java/reviewme/review/service/validator/AnswerValidatorTest.java @@ -0,0 +1,90 @@ +package reviewme.review.service.validator; + +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.junit.jupiter.api.Assertions.assertAll; +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; +import static reviewme.fixture.QuestionFixture.์„œ์ˆ ํ˜•_ํ•„์ˆ˜_์งˆ๋ฌธ; +import static reviewme.fixture.ReviewGroupFixture.๋ฆฌ๋ทฐ_๊ทธ๋ฃน; + +import java.util.ArrayList; +import java.util.List; +import java.util.Set; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import reviewme.review.domain.Answer; +import reviewme.review.domain.Review; +import reviewme.review.domain.TextAnswer; +import reviewme.review.repository.ReviewRepository; +import reviewme.review.service.exception.QuestionNotContainingAnswersException; +import reviewme.review.service.exception.ReviewGroupNotContainingAnswersException; +import reviewme.reviewgroup.domain.ReviewGroup; +import reviewme.reviewgroup.repository.ReviewGroupRepository; +import reviewme.support.ServiceTest; +import reviewme.template.domain.Question; +import reviewme.template.repository.QuestionRepository; + +@ServiceTest +class AnswerValidatorTest { + + @Autowired + private AnswerValidator answerValidator; + + @Autowired + private ReviewGroupRepository reviewGroupRepository; + + @Autowired + private ReviewRepository reviewRepository; + + @Autowired + private QuestionRepository questionRepository; + + @Test + void ๋‹ต๋ณ€์ด_์งˆ๋ฌธ์—_์†ํ•˜๋Š”์ง€_๊ฒ€์ฆํ•œ๋‹ค() { + // given + ReviewGroup reviewGroup = reviewGroupRepository.save(๋ฆฌ๋ทฐ_๊ทธ๋ฃน()); + Question question1 = questionRepository.save(์„œ์ˆ ํ˜•_ํ•„์ˆ˜_์งˆ๋ฌธ()); + Question question2 = questionRepository.save(์„œ์ˆ ํ˜•_ํ•„์ˆ˜_์งˆ๋ฌธ()); + List answers = List.of( + new TextAnswer(question1.getId(), "๋‹ต๋ณ€1"), + new TextAnswer(question2.getId(), "๋‹ต๋ณ€2") + ); + Review review = reviewRepository.save(new Review(1L, reviewGroup.getId(), answers)); + Set answerIds = review.getAnsweredQuestionIds(); + List firstAnswerId = List.of(answers.get(0).getId()); + + // when, then + assertAll( + () -> assertDoesNotThrow( + () -> answerValidator.validateQuestionContainsAnswers(question1.getId(), firstAnswerId)), + () -> assertThatThrownBy( + () -> answerValidator.validateQuestionContainsAnswers(question1.getId(), answerIds)) + .isInstanceOf(QuestionNotContainingAnswersException.class) + ); + } + + @Test + void ๋‹ต๋ณ€์ด_๋ฆฌ๋ทฐ๊ทธ๋ฃน์—_์†ํ•˜๋Š”์ง€_๊ฒ€์ฆํ•œ๋‹ค() { + // given + ReviewGroup reviewGroup = reviewGroupRepository.save(๋ฆฌ๋ทฐ_๊ทธ๋ฃน()); + Question question1 = questionRepository.save(์„œ์ˆ ํ˜•_ํ•„์ˆ˜_์งˆ๋ฌธ()); + Question question2 = questionRepository.save(์„œ์ˆ ํ˜•_ํ•„์ˆ˜_์งˆ๋ฌธ()); + List answers = List.of( + new TextAnswer(question1.getId(), "๋‹ต๋ณ€1"), + new TextAnswer(question2.getId(), "๋‹ต๋ณ€2") + ); + Review review = reviewRepository.save(new Review(1L, reviewGroup.getId(), answers)); + + List answerIds = review.getAnswers().stream().map(Answer::getQuestionId).toList(); + List wrongAnswerIds = new ArrayList<>(answerIds); + wrongAnswerIds.add(Long.MAX_VALUE); + + // when, then + assertAll( + () -> assertDoesNotThrow( + () -> answerValidator.validateReviewGroupContainsAnswers(reviewGroup, answerIds)), + () -> assertThatThrownBy( + () -> answerValidator.validateReviewGroupContainsAnswers(reviewGroup, wrongAnswerIds)) + .isInstanceOf(ReviewGroupNotContainingAnswersException.class) + ); + } +} diff --git a/backend/src/test/java/reviewme/review/service/validator/CheckboxAnswerValidatorTest.java b/backend/src/test/java/reviewme/review/service/validator/CheckboxTypedAnswerValidatorTest.java similarity index 91% rename from backend/src/test/java/reviewme/review/service/validator/CheckboxAnswerValidatorTest.java rename to backend/src/test/java/reviewme/review/service/validator/CheckboxTypedAnswerValidatorTest.java index 5c64c2503..57e7dfd4b 100644 --- a/backend/src/test/java/reviewme/review/service/validator/CheckboxAnswerValidatorTest.java +++ b/backend/src/test/java/reviewme/review/service/validator/CheckboxTypedAnswerValidatorTest.java @@ -8,12 +8,12 @@ import java.util.List; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; -import reviewme.question.domain.OptionGroup; -import reviewme.question.domain.OptionItem; -import reviewme.question.domain.Question; -import reviewme.question.repository.OptionGroupRepository; -import reviewme.question.repository.OptionItemRepository; -import reviewme.question.repository.QuestionRepository; +import reviewme.template.domain.OptionGroup; +import reviewme.template.domain.OptionItem; +import reviewme.template.domain.Question; +import reviewme.template.repository.OptionGroupRepository; +import reviewme.template.repository.OptionItemRepository; +import reviewme.template.repository.QuestionRepository; import reviewme.review.domain.CheckboxAnswer; import reviewme.review.service.exception.CheckBoxAnswerIncludedNotProvidedOptionItemException; import reviewme.review.service.exception.OptionGroupNotFoundByQuestionIdException; @@ -22,10 +22,10 @@ import reviewme.support.ServiceTest; @ServiceTest -class CheckboxAnswerValidatorTest { +class CheckboxTypedAnswerValidatorTest { @Autowired - private CheckboxAnswerValidator checkBoxAnswerValidator; + private CheckboxTypedAnswerValidator checkBoxAnswerValidator; @Autowired private QuestionRepository questionRepository; diff --git a/backend/src/test/java/reviewme/review/service/validator/ReviewValidatorTest.java b/backend/src/test/java/reviewme/review/service/validator/ReviewValidatorTest.java index dca5dd59d..dd8ebfc94 100644 --- a/backend/src/test/java/reviewme/review/service/validator/ReviewValidatorTest.java +++ b/backend/src/test/java/reviewme/review/service/validator/ReviewValidatorTest.java @@ -15,12 +15,12 @@ import java.util.List; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; -import reviewme.question.domain.OptionGroup; -import reviewme.question.domain.OptionItem; -import reviewme.question.domain.Question; -import reviewme.question.repository.OptionGroupRepository; -import reviewme.question.repository.OptionItemRepository; -import reviewme.question.repository.QuestionRepository; +import reviewme.template.domain.OptionGroup; +import reviewme.template.domain.OptionItem; +import reviewme.template.domain.Question; +import reviewme.template.repository.OptionGroupRepository; +import reviewme.template.repository.OptionItemRepository; +import reviewme.template.repository.QuestionRepository; import reviewme.review.domain.CheckboxAnswer; import reviewme.review.domain.Review; import reviewme.review.domain.TextAnswer; diff --git a/backend/src/test/java/reviewme/review/service/validator/TextAnswerValidatorTest.java b/backend/src/test/java/reviewme/review/service/validator/TextTypedAnswerValidatorTest.java similarity index 93% rename from backend/src/test/java/reviewme/review/service/validator/TextAnswerValidatorTest.java rename to backend/src/test/java/reviewme/review/service/validator/TextTypedAnswerValidatorTest.java index 0e8265bb6..9773112e8 100644 --- a/backend/src/test/java/reviewme/review/service/validator/TextAnswerValidatorTest.java +++ b/backend/src/test/java/reviewme/review/service/validator/TextTypedAnswerValidatorTest.java @@ -9,18 +9,18 @@ import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.ValueSource; import org.springframework.beans.factory.annotation.Autowired; -import reviewme.question.domain.Question; -import reviewme.question.repository.QuestionRepository; +import reviewme.template.domain.Question; +import reviewme.template.repository.QuestionRepository; import reviewme.review.domain.TextAnswer; import reviewme.review.service.exception.InvalidTextAnswerLengthException; import reviewme.review.service.exception.SubmittedQuestionNotFoundException; import reviewme.support.ServiceTest; @ServiceTest -class TextAnswerValidatorTest { +class TextTypedAnswerValidatorTest { @Autowired - private TextAnswerValidator textAnswerValidator; + private TextTypedAnswerValidator textAnswerValidator; @Autowired private QuestionRepository questionRepository; diff --git a/backend/src/test/java/reviewme/review/service/validator/AnswerValidatorFactoryTest.java b/backend/src/test/java/reviewme/review/service/validator/TypedTypedAnswerValidatorFactoryTest.java similarity index 68% rename from backend/src/test/java/reviewme/review/service/validator/AnswerValidatorFactoryTest.java rename to backend/src/test/java/reviewme/review/service/validator/TypedTypedAnswerValidatorFactoryTest.java index 0a6e75db5..d808c53d3 100644 --- a/backend/src/test/java/reviewme/review/service/validator/AnswerValidatorFactoryTest.java +++ b/backend/src/test/java/reviewme/review/service/validator/TypedTypedAnswerValidatorFactoryTest.java @@ -8,9 +8,9 @@ import reviewme.review.domain.Answer; import reviewme.review.domain.CheckboxAnswer; -class AnswerValidatorFactoryTest { +class TypedTypedAnswerValidatorFactoryTest { - private final AnswerValidator validator = new AnswerValidator() { + private final TypedAnswerValidator validator = new TypedAnswerValidator() { @Override public boolean supports(Class answerClass) { @@ -19,17 +19,18 @@ public boolean supports(Class answerClass) { @Override public void validate(Answer answer) { + // no-op } }; @Test void ์ง€์›ํ•˜๋Š”_ํƒ€์ž…์—_๋”ฐ๋ฅธ_๋ฐธ๋ฆฌ๋ฐ์ดํ„ฐ๋ฅผ_๊ฐ€์ ธ์˜จ๋‹ค() { // given - List validators = List.of(validator); - AnswerValidatorFactory factory = new AnswerValidatorFactory(validators); + List validators = List.of(validator); + TypedAnswerValidatorFactory factory = new TypedAnswerValidatorFactory(validators); // when - AnswerValidator actual = factory.getAnswerValidator(CheckboxAnswer.class); + TypedAnswerValidator actual = factory.getAnswerValidator(CheckboxAnswer.class); // then assertThat(actual).isEqualTo(validator); @@ -38,7 +39,7 @@ public void validate(Answer answer) { @Test void ์ง€์›ํ•˜์ง€_์•Š๋Š”_ํƒ€์ž…์—_๋Œ€ํ•œ_๋ฐธ๋ฆฌ๋ฐ์ดํ„ฐ_์š”์ฒญ_์‹œ_์˜ˆ์™ธ๊ฐ€_๋ฐœ์ƒํ•œ๋‹ค() { // given - AnswerValidatorFactory factory = new AnswerValidatorFactory(List.of()); + TypedAnswerValidatorFactory factory = new TypedAnswerValidatorFactory(List.of()); // when, then assertThatThrownBy(() -> factory.getAnswerValidator(CheckboxAnswer.class)) diff --git a/backend/src/test/java/reviewme/question/repository/OptionGroupRepositoryTest.java b/backend/src/test/java/reviewme/template/repository/OptionGroupRepositoryTest.java similarity index 88% rename from backend/src/test/java/reviewme/question/repository/OptionGroupRepositoryTest.java rename to backend/src/test/java/reviewme/template/repository/OptionGroupRepositoryTest.java index 1bc3ea107..d121c3688 100644 --- a/backend/src/test/java/reviewme/question/repository/OptionGroupRepositoryTest.java +++ b/backend/src/test/java/reviewme/template/repository/OptionGroupRepositoryTest.java @@ -1,7 +1,6 @@ -package reviewme.question.repository; +package reviewme.template.repository; import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.jupiter.api.Assertions.*; import static reviewme.fixture.OptionGroupFixture.์„ ํƒ์ง€_๊ทธ๋ฃน; import static reviewme.fixture.QuestionFixture.์„ ํƒํ˜•_ํ•„์ˆ˜_์งˆ๋ฌธ; @@ -9,8 +8,10 @@ import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; -import reviewme.question.domain.OptionGroup; -import reviewme.question.domain.Question; +import reviewme.template.domain.OptionGroup; +import reviewme.template.domain.Question; +import reviewme.template.repository.OptionGroupRepository; +import reviewme.template.repository.QuestionRepository; @DataJpaTest class OptionGroupRepositoryTest { diff --git a/backend/src/test/java/reviewme/question/repository/OptionItemRepositoryTest.java b/backend/src/test/java/reviewme/template/repository/OptionItemRepositoryTest.java similarity index 87% rename from backend/src/test/java/reviewme/question/repository/OptionItemRepositoryTest.java rename to backend/src/test/java/reviewme/template/repository/OptionItemRepositoryTest.java index 5aebbf06b..5e1c7a288 100644 --- a/backend/src/test/java/reviewme/question/repository/OptionItemRepositoryTest.java +++ b/backend/src/test/java/reviewme/template/repository/OptionItemRepositoryTest.java @@ -1,4 +1,4 @@ -package reviewme.question.repository; +package reviewme.template.repository; import static org.assertj.core.api.Assertions.assertThat; import static reviewme.fixture.OptionGroupFixture.์„ ํƒ์ง€_๊ทธ๋ฃน; @@ -9,10 +9,13 @@ import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; -import reviewme.question.domain.OptionGroup; -import reviewme.question.domain.OptionItem; -import reviewme.question.domain.OptionType; -import reviewme.question.domain.Question; +import reviewme.template.domain.OptionGroup; +import reviewme.template.domain.OptionItem; +import reviewme.template.domain.OptionType; +import reviewme.template.domain.Question; +import reviewme.template.repository.OptionGroupRepository; +import reviewme.template.repository.OptionItemRepository; +import reviewme.template.repository.QuestionRepository; @DataJpaTest class OptionItemRepositoryTest { diff --git a/backend/src/test/java/reviewme/question/repository/QuestionRepositoryTest.java b/backend/src/test/java/reviewme/template/repository/QuestionRepositoryTest.java similarity index 94% rename from backend/src/test/java/reviewme/question/repository/QuestionRepositoryTest.java rename to backend/src/test/java/reviewme/template/repository/QuestionRepositoryTest.java index da694e335..584057104 100644 --- a/backend/src/test/java/reviewme/question/repository/QuestionRepositoryTest.java +++ b/backend/src/test/java/reviewme/template/repository/QuestionRepositoryTest.java @@ -1,4 +1,4 @@ -package reviewme.question.repository; +package reviewme.template.repository; import static org.assertj.core.api.Assertions.assertThat; import static reviewme.fixture.OptionGroupFixture.์„ ํƒ์ง€_๊ทธ๋ฃน; @@ -13,13 +13,16 @@ import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; -import reviewme.question.domain.OptionGroup; -import reviewme.question.domain.OptionItem; -import reviewme.question.domain.Question; +import reviewme.template.domain.OptionGroup; +import reviewme.template.domain.OptionItem; +import reviewme.template.domain.Question; import reviewme.reviewgroup.domain.ReviewGroup; import reviewme.reviewgroup.repository.ReviewGroupRepository; import reviewme.template.domain.Section; import reviewme.template.domain.Template; +import reviewme.template.repository.OptionGroupRepository; +import reviewme.template.repository.OptionItemRepository; +import reviewme.template.repository.QuestionRepository; import reviewme.template.repository.SectionRepository; import reviewme.template.repository.TemplateRepository; diff --git a/backend/src/test/java/reviewme/template/service/TemplateServiceTest.java b/backend/src/test/java/reviewme/template/service/TemplateServiceTest.java index 7c512d99f..9f372e1d8 100644 --- a/backend/src/test/java/reviewme/template/service/TemplateServiceTest.java +++ b/backend/src/test/java/reviewme/template/service/TemplateServiceTest.java @@ -5,7 +5,6 @@ import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; -import reviewme.review.service.exception.ReviewGroupNotFoundByReviewRequestCodeException; import reviewme.reviewgroup.domain.ReviewGroup; import reviewme.reviewgroup.repository.ReviewGroupRepository; import reviewme.support.ServiceTest; @@ -20,23 +19,14 @@ class TemplateServiceTest { @Autowired private ReviewGroupRepository reviewGroupRepository; - @Test - void ์ž˜๋ชป๋œ_๋ฆฌ๋ทฐ_์š”์ฒญ_์ฝ”๋“œ๋กœ_๋ฆฌ๋ทฐ_์ž‘์„ฑํผ์„_์š”์ฒญํ• _๊ฒฝ์šฐ_์˜ˆ์™ธ๊ฐ€_๋ฐœ์ƒํ•œ๋‹ค() { - // given - ReviewGroup reviewGroup = reviewGroupRepository.save(๋ฆฌ๋ทฐ_๊ทธ๋ฃน()); - - // when, then - assertThatThrownBy(() -> templateService.generateReviewForm(reviewGroup.getReviewRequestCode() + " ")) - .isInstanceOf(ReviewGroupNotFoundByReviewRequestCodeException.class); - } - @Test void ๋ฆฌ๋ทฐ์ด์—๊ฒŒ_์ž‘์„ฑ๋ _๋ฆฌ๋ทฐ_์–‘์‹_์ƒ์„ฑ_์‹œ_์ €์žฅ๋œ_ํ…œํ”Œ๋ฆฟ์ด_์—†์„_๊ฒฝ์šฐ_์˜ˆ์™ธ๊ฐ€_๋ฐœ์ƒํ•œ๋‹ค() { // given ReviewGroup reviewGroup = reviewGroupRepository.save(๋ฆฌ๋ทฐ_๊ทธ๋ฃน()); + String reviewRequestCode = reviewGroup.getReviewRequestCode(); // when, then - assertThatThrownBy(() -> templateService.generateReviewForm(reviewGroup.getReviewRequestCode())) + assertThatThrownBy(() -> templateService.generateReviewForm(reviewRequestCode)) .isInstanceOf(TemplateNotFoundByReviewGroupException.class); } } diff --git a/backend/src/test/java/reviewme/template/service/mapper/TemplateMapperTest.java b/backend/src/test/java/reviewme/template/service/mapper/TemplateMapperTest.java index e1a0f1853..0814b4400 100644 --- a/backend/src/test/java/reviewme/template/service/mapper/TemplateMapperTest.java +++ b/backend/src/test/java/reviewme/template/service/mapper/TemplateMapperTest.java @@ -14,11 +14,11 @@ import java.util.List; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; -import reviewme.question.domain.OptionGroup; -import reviewme.question.domain.Question; -import reviewme.question.repository.OptionGroupRepository; -import reviewme.question.repository.OptionItemRepository; -import reviewme.question.repository.QuestionRepository; +import reviewme.template.domain.OptionGroup; +import reviewme.template.domain.Question; +import reviewme.template.repository.OptionGroupRepository; +import reviewme.template.repository.OptionItemRepository; +import reviewme.template.repository.QuestionRepository; import reviewme.reviewgroup.domain.ReviewGroup; import reviewme.reviewgroup.repository.ReviewGroupRepository; import reviewme.support.ServiceTest; diff --git a/frontend/src/components/highlight/components/HighlightEditor/hooks/useHighlight.ts b/frontend/src/components/highlight/components/HighlightEditor/hooks/useHighlight.ts index 703f8acd7..2b91ac8e3 100644 --- a/frontend/src/components/highlight/components/HighlightEditor/hooks/useHighlight.ts +++ b/frontend/src/components/highlight/components/HighlightEditor/hooks/useHighlight.ts @@ -1,11 +1,6 @@ -import { useEffect, useState } from 'react'; +import { useState } from 'react'; -import { - EDITOR_ANSWER_CLASS_NAME, - HIGHLIGHT_EVENT_NAME, - HIGHLIGHT_SPAN_CLASS_NAME, - SESSION_STORAGE_KEY, -} from '@/constants'; +import { EDITOR_ANSWER_CLASS_NAME, HIGHLIGHT_EVENT_NAME, HIGHLIGHT_SPAN_CLASS_NAME } from '@/constants'; import { EditorAnswerMap, EditorLine, HighlightResponseData, ReviewAnswerResponseData } from '@/types'; import { getEndLineOffset, @@ -76,14 +71,6 @@ const useHighlight = ({ handleModalMessage, }: UseHighlightProps) => { const [editorAnswerMap, setEditorAnswerMap] = useState(makeInitialEditorAnswerMap(answerList)); - const storageKey = `${SESSION_STORAGE_KEY.editorAnswerMap}-${questionId}`; - - useEffect(() => { - const item = localStorage.getItem(storageKey); - if (item) { - setEditorAnswerMap(new Map(JSON.parse(item)) as EditorAnswerMap); - } - }, []); // span ํด๋ฆญ ์‹œ, ์ œ๊ณต๋˜๋Š” ํ˜•๊ด‘ํŽœ ์‚ญ์ œ ๊ธฐ๋Šฅ ํƒ€๊ฒŸ const [longPressRemovalTarget, setLongPressRemovalTarget] = useState(null); @@ -92,8 +79,6 @@ const useHighlight = ({ const updateEditorAnswerMap = (newEditorAnswerMap: EditorAnswerMap) => { setEditorAnswerMap(newEditorAnswerMap); - // editorAnswerMap์ด ๋ณ€๊ฒฝ๋  ๋•Œ ์ƒˆ๋กœ์šด ๊ฐ’์„ ๋กœ์ปฌ ์Šคํ† ๋ฆฌ์ง€์— ์ €์žฅ - localStorage.setItem(storageKey, JSON.stringify(Array.from(newEditorAnswerMap))); }; const resetHighlightMenu = () => { diff --git a/frontend/src/components/highlight/components/HighlightEditor/hooks/useMutateHighlight/index.ts b/frontend/src/components/highlight/components/HighlightEditor/hooks/useMutateHighlight/index.ts index 56681e41e..d607901cc 100644 --- a/frontend/src/components/highlight/components/HighlightEditor/hooks/useMutateHighlight/index.ts +++ b/frontend/src/components/highlight/components/HighlightEditor/hooks/useMutateHighlight/index.ts @@ -1,7 +1,7 @@ -import { useMutation } from '@tanstack/react-query'; +import { useMutation, useQueryClient } from '@tanstack/react-query'; import { postHighlight } from '@/apis/highlight'; -import { LOCAL_STORAGE_KEY } from '@/constants'; +import { LOCAL_STORAGE_KEY, REVIEW_QUERY_KEY, SESSION_STORAGE_KEY } from '@/constants'; import { EditorAnswerMap } from '@/types'; export interface UseMutateHighlightProps { @@ -17,6 +17,21 @@ const useMutateHighlight = ({ updateEditorAnswerMap, resetHighlightMenu, }: UseMutateHighlightProps) => { + const queryClient = useQueryClient(); + /** + * ํ˜•๊ด‘ํŽœ API ์„ฑ๊ณต ํ›„, ํ˜„์žฌ ์งˆ๋ฌธ์— ๋Œ€ํ•œ ์ฟผ๋ฆฌ ์บ์‹œ ๋ฌดํšจํ™”ํ•ด์„œ, ๋ณ€๊ฒฝ๋œ ํ˜•๊ด‘ํŽœ ๋ฐ์ดํ„ฐ ๋ถˆ๋Ÿฌ์˜ค๋„๋ก ํ•จ + */ + const invalidateCurrentSectionQuery = () => { + const sectionId = sessionStorage.getItem(SESSION_STORAGE_KEY.currentReviewCollectionSectionId); + + if (sectionId) { + queryClient.invalidateQueries({ + predicate: (query) => + query.queryKey[0] === REVIEW_QUERY_KEY.groupedReviews && query.queryKey[1] === Number(sectionId), + }); + } + }; + const mutation = useMutation({ mutationFn: (newEditorAnswerMap: EditorAnswerMap) => postHighlight(newEditorAnswerMap, questionId), onMutate: () => { @@ -28,6 +43,8 @@ const useMutateHighlight = ({ // ํ† ์ŠคํŠธ ๋ชจ๋‹ฌ ์ง€์šฐ๊ธฐ handleErrorModal(false); localStorage.removeItem(LOCAL_STORAGE_KEY.isHighlightError); + // ํ•ด๋‹น ์งˆ๋ฌธ ์ฟผ๋ฆฌ ์บ์‹œ ๋ฌดํšจํ™” + invalidateCurrentSectionQuery(); }, onError: (error) => { //ํ† ์ŠคํŠธ ๋ชจ๋‹ฌ ๋„์›€ diff --git a/frontend/src/constants/storageKey.ts b/frontend/src/constants/storageKey.ts index f25f48312..5fb04d984 100644 --- a/frontend/src/constants/storageKey.ts +++ b/frontend/src/constants/storageKey.ts @@ -4,5 +4,5 @@ export const LOCAL_STORAGE_KEY = { }; export const SESSION_STORAGE_KEY = { - editorAnswerMap: 'editorAnswerMap-question', + currentReviewCollectionSectionId: 'currentReviewCollectionSectionId', }; diff --git a/frontend/src/mocks/mockData/reviewCollection.ts b/frontend/src/mocks/mockData/reviewCollection.ts index c2946f3bf..4b8b5df43 100644 --- a/frontend/src/mocks/mockData/reviewCollection.ts +++ b/frontend/src/mocks/mockData/reviewCollection.ts @@ -115,7 +115,7 @@ export const GROUPED_REVIEWS_MOCK_DATA: GroupedReviews[] = [ { id: 2, content: - 'http://localhost:3000/user/review-zone/5WkYQLqW1http://localhost:3000/user/review-zone/5WkYQLqW2http://localhost:3000/user/review-zone/5WkYQLqW3http://localhost:3000/user/review-zone/5WkYQLqW4http://localhost:3000/user/review-zone/5WkYQLqW5http://localhost:3000/user/review-zone/5WkYQLqW6http://localhost:3000/user/review-zone/5WkYQLqW7http://localhost:3000/user/review-zone/5WkYQLqW8http://localhost:3000/user/review-zone/5WkYQLqW9http://localhost:3000/user/review-zone/5WkYQLqW10', + ' ๋ณต์žกํ•œ ๋ฌธ์ œ๋ฅผ ์ฒด๊ณ„์ ์œผ๋กœ ๋ถ„์„ํ•˜๊ณ , ์ฐฝ์˜์ ์ธ ํ•ด๊ฒฐ์ฑ…์„ ์ œ์•ˆํ•˜๋ฉฐ ์ด๋ฅผ ์‹คํ–‰ํ•˜๋Š” ๋ฐ ๋›ฐ์–ด๋‚œ ์—ญ๋Ÿ‰์„ ๋ณด์—ฌ์ค๋‹ˆ๋‹ค. ํŠนํžˆ, ์ œํ•œ๋œ ์‹œ๊ฐ„๊ณผ ์ž์› ์†์—์„œ๋„ ํšจ๊ณผ์ ์œผ๋กœ ์šฐ์„ ์ˆœ์œ„๋ฅผ ์ •ํ•˜๊ณ  ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๋Š” ๋ชจ์Šต์„ ํ†ตํ•ด ํŒ€์— ํฐ ์‹ ๋ขฐ๋ฅผ ์ฃผ์—ˆ์Šต๋‹ˆ๋‹ค. ์ด๋Ÿฌํ•œ ๋Šฅ๋ ฅ์€ ํŒ€์˜ ๋ชฉํ‘œ ๋‹ฌ์„ฑ๊ณผ ์„ฑ์žฅ์— ํฐ ๊ธฐ์—ฌ๋ฅผ ํ•˜๋ฉฐ, ์•ž์œผ๋กœ๋„ ๋” ๋งŽ์€ ์„ฑ๊ณผ๋ฅผ ๋‚ผ ์ˆ˜ ์žˆ์„ ๊ฒƒ์œผ๋กœ ๊ธฐ๋Œ€๋ฉ๋‹ˆ๋‹ค.!!!!!', highlights: [ { lineIndex: 0, @@ -132,13 +132,13 @@ export const GROUPED_REVIEWS_MOCK_DATA: GroupedReviews[] = [ { id: 3, content: - '์žฅ์˜ ์‹œ์ž‘๋ถ€๋ถ„์€ ์งง๊ณ  ์ง์ ‘์ ์ด๋ฉฐ, ๋’ค๋”ฐ๋ผ ๋‚˜์˜ฌ ๋ณต์žกํ•œ ์ •๋ณด๋ฅผ ์–ด๋–ป๊ฒŒ ํ•ด์„ํ•ด์•ผ ํ•  ๊ฒƒ์ธ์ง€ ํ”„๋ ˆ์ž„์„ ์งœ์ฃผ๋Š” ์—ญํ• ์„ ํ•ด์•ผ ํ•œ๋‹ค. ๊ทธ๋Ÿฌ๋ฉด ์•„๋ฌด๋ฆฌ ๊ธด ๋ฌธ์žฅ์ด๋ผ๋„ ์‰ฝ๊ฒŒ ์ฝํžŒ๋‹ค.', + '๋ฌธ์ œ์˜ ํ•ต์‹ฌ ์›์ธ์„ ๋น ๋ฅด๊ฒŒ ํŒŒ์•…ํ•˜๊ณ , ์ด๋ฅผ ๋ฐ”ํƒ•์œผ๋กœ ์‹คํ–‰ ๊ฐ€๋Šฅํ•œ ์†”๋ฃจ์…˜์„ ์ œ์‹œํ•˜๋ฉฐ ํŒ€์˜ ๋ชฉํ‘œ๋ฅผ ๋‹ฌ์„ฑํ•˜๋Š” ๋ฐ ํฐ ๊ธฐ์—ฌ๋ฅผ ํ–ˆ์Šต๋‹ˆ๋‹ค. ํŠนํžˆ, ์˜ˆ์ƒ์น˜ ๋ชปํ•œ ์ƒํ™ฉ์—์„œ๋„ ๋ƒ‰์ฒ ํ•œ ํŒ๋‹จ๊ณผ ์ ๊ทน์ ์ธ ํƒœ๋„๋กœ ํ•ด๊ฒฐ์ฑ…์„ ์ฐพ์•„๊ฐ€๋Š” ๋ชจ์Šต์€ ํŒ€์›๋“ค์—๊ฒŒ ์ข‹์€ ์ž๊ทน์ด ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.', highlights: [], }, { id: 4, content: - '๊ณ ์•ก๊ณต์ œ๊ฑด๊ฐ•๋ณดํ—˜๊ณผ ๊ฑด๊ฐ•์ €์ถ•๊ณ„์ขŒ๋ฅผ ๋งŒ๋“ค์–ด ๋…ธ๋™์ž์™€ ๊ณ ์šฉ์ฃผ๊ฐ€ ์„ธ๊ธˆ๊ณต์ œ๋ฅผ ๋ฐ›์„ ์ˆ˜ ์žˆ๋„๋ก ํ•˜๋ฉด ๊ฒฐ๊ณผ์ ์œผ๋กœ ๋…ธ๋™์ž์˜ ์˜๋ฃŒ๋ณดํ—˜ ๋ถ€๋‹ด์ด ์ปค์ง„๋‹ค. ์„ธ๊ธˆ๊ณต์ œ๋ฅผ ๋ฐ›์„ ์ˆ˜ ์žˆ๋„๋ก ํ•˜๋ฉด------------------------------------------- ๊ฒฐ๊ณผ์ ์œผ๋กœ ๋…ธ๋™์ž์˜ ์˜๋ฃŒ๋ณดํ—˜ ๋ถ€๋‹ด์ด ์ปค์ง„๋‹ค.', + '๋ฌธ์ œ๋ฅผ ๋‹ค์–‘ํ•œ ๊ด€์ ์—์„œ ๋ฐ”๋ผ๋ณด๋ฉฐ ๊ฐ€์žฅ ์ ํ•ฉํ•œ ํ•ด๊ฒฐ์ฑ…์„ ์ฐพ์•„๋‚ด๋Š” ๋Šฅ๋ ฅ์ด ๋›ฐ์–ด๋‚ฉ๋‹ˆ๋‹ค. ํŠนํžˆ, ์—ฌ๋Ÿฌ ์ดํ•ด๊ด€๊ณ„์ž ๊ฐ„์˜ ์˜๊ฒฌ์„ ์กฐ์œจํ•˜๋ฉฐ ๋ชจ๋‘๊ฐ€ ๋งŒ์กฑํ•  ์ˆ˜ ์žˆ๋Š” ๋ฐฉ์•ˆ์„ ์ œ์•ˆํ•œ ์ ์ด ๋‹๋ณด์˜€์Šต๋‹ˆ๋‹ค. ์ด ๊ณผ์ •์—์„œ ๋ณด์—ฌ์ค€ ์ ๊ทน์ ์ธ ์†Œํ†ต๊ณผ ๋…ผ๋ฆฌ์ ์ธ ์ ‘๊ทผ๋ฒ•์€ ํŒ€์˜ ์‹ ๋ขฐ๋ฅผ ๋”์šฑ ๋†’์˜€๊ณ , ์–ด๋ ค์šด ๊ณผ์ œ๋ฅผ ์„ฑ๊ณต์ ์œผ๋กœ ๋งˆ๋ฌด๋ฆฌํ•  ์ˆ˜ ์žˆ๋Š” ์›๋™๋ ฅ์ด ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.', highlights: [], }, ], @@ -181,7 +181,7 @@ export const GROUPED_REVIEWS_MOCK_DATA: GroupedReviews[] = [ { id: 2, content: - 'http://localhost:3000/user/review-zone/5WkYQLqW1http://localhost:3000/user/review-zone/5WkYQLqW2http://localhost:3000/user/review-zone/5WkYQLqW3http://localhost:3000/user/review-zone/5WkYQLqW4http://localhost:3000/user/review-zone/5WkYQLqW5http://localhost:3000/user/review-zone/5WkYQLqW6http://localhost:3000/user/review-zone/5WkYQLqW7http://localhost:3000/user/review-zone/5WkYQLqW8http://localhost:3000/user/review-zone/5WkYQLqW9http://localhost:3000/user/review-zone/5WkYQLqW10', + 'ํšจ์œจ์ ์ธ ์‹œ๊ฐ„ ๊ด€๋ฆฌ ๋Šฅ๋ ฅ์„ ํ†ตํ•ด ์ค‘์š”ํ•œ ์ž‘์—…์„ ๊ธฐํ•œ ๋‚ด์— ์™„์ˆ˜ํ•˜๋Š” ๋ชจ์Šต์ด ๋งค์šฐ ์ธ์ƒ์ ์ด์—ˆ์Šต๋‹ˆ๋‹ค. ํŠนํžˆ, ์ž‘์—…์˜ ์šฐ์„ ์ˆœ์œ„๋ฅผ ๋ช…ํ™•ํžˆ ๊ตฌ๋ถ„ํ•˜๊ณ  ์ด๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ์ฒด๊ณ„์ ์œผ๋กœ ๊ณ„ํš์„ ์„ธ์›Œ ์ง„ํ–‰ํ•˜๋Š” ์ ์ด ๋‹๋ณด์˜€์Šต๋‹ˆ๋‹ค. ์ด๋Ÿฌํ•œ ๋Šฅ๋ ฅ ๋•๋ถ„์— ํŒ€ ์ „์ฒด์˜ ์ƒ์‚ฐ์„ฑ์ด ํ–ฅ์ƒ๋˜์—ˆ๊ณ , ์˜ˆ์ƒ์น˜ ๋ชปํ•œ ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ–ˆ์„ ๋•Œ๋„ ์œ ์—ฐํ•˜๊ฒŒ ๋Œ€์ฒ˜ํ•˜๋ฉฐ ํ”„๋กœ์ ํŠธ๋ฅผ ์„ฑ๊ณต์ ์œผ๋กœ ์ด๋Œ์—ˆ์Šต๋‹ˆ๋‹ค.', highlights: [ { lineIndex: 0, @@ -198,13 +198,13 @@ export const GROUPED_REVIEWS_MOCK_DATA: GroupedReviews[] = [ { id: 3, content: - '์žฅ์˜ ์‹œ์ž‘๋ถ€๋ถ„์€ ์งง๊ณ  ์ง์ ‘์ ์ด๋ฉฐ, ๋’ค๋”ฐ๋ผ ๋‚˜์˜ฌ ๋ณต์žกํ•œ ์ •๋ณด๋ฅผ ์–ด๋–ป๊ฒŒ ํ•ด์„ํ•ด์•ผ ํ•  ๊ฒƒ์ธ์ง€ ํ”„๋ ˆ์ž„์„ ์งœ์ฃผ๋Š” ์—ญํ• ์„ ํ•ด์•ผ ํ•œ๋‹ค. ๊ทธ๋Ÿฌ๋ฉด ์•„๋ฌด๋ฆฌ ๊ธด ๋ฌธ์žฅ์ด๋ผ๋„ ์‰ฝ๊ฒŒ ์ฝํžŒ๋‹ค.', + '์‹œ๊ฐ„์„ ํšจ์œจ์ ์œผ๋กœ ํ™œ์šฉํ•˜๋Š” ๋›ฐ์–ด๋‚œ ๋Šฅ๋ ฅ์„ ๋ณด์—ฌ์ฃผ์…จ์Šต๋‹ˆ๋‹ค. ์ž‘์—… ์ดˆ๊ธฐ๋ถ€ํ„ฐ ๋ช…ํ™•ํ•œ ๊ณ„ํš์„ ์ˆ˜๋ฆฝํ•˜๊ณ  ์ด๋ฅผ ๋๊นŒ์ง€ ์œ ์ง€ํ•˜๋Š” ๋ชจ์Šต์ด ์ธ์ƒ์ ์ด์—ˆ์œผ๋ฉฐ, ์˜ˆ์ƒ์น˜ ๋ชปํ•œ ๋ณ€์ˆ˜์—๋„ ์นจ์ฐฉํ•˜๊ฒŒ ๋Œ€์ฒ˜ํ•˜๋ฉฐ ํ”„๋กœ์ ํŠธ์˜ ์ผ์ •๊ณผ ํ’ˆ์งˆ์„ ๋ชจ๋‘ ์ถฉ์กฑ์‹œ์ผฐ์Šต๋‹ˆ๋‹ค. ์ด๋Ÿฌํ•œ ์ ์€ ํŒ€์— ํฐ ์•ˆ์ •๊ฐ์„ ์ฃผ์—ˆ๊ณ , ํ•จ๊ป˜ ์ผํ•˜๋Š” ์‚ฌ๋žŒ๋“ค์—๊ฒŒ๋„ ์ข‹์€ ๋ณธ๋ณด๊ธฐ๊ฐ€ ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.', highlights: [], }, { id: 4, content: - '๊ณ ์•ก๊ณต์ œ๊ฑด๊ฐ•๋ณดํ—˜๊ณผ ๊ฑด๊ฐ•์ €์ถ•๊ณ„์ขŒ๋ฅผ ๋งŒ๋“ค์–ด ๋…ธ๋™์ž์™€ ๊ณ ์šฉ์ฃผ๊ฐ€ ์„ธ๊ธˆ๊ณต์ œ๋ฅผ ๋ฐ›์„ ์ˆ˜ ์žˆ๋„๋ก ํ•˜๋ฉด ๊ฒฐ๊ณผ์ ์œผ๋กœ ๋…ธ๋™์ž์˜ ์˜๋ฃŒ๋ณดํ—˜ ๋ถ€๋‹ด์ด ์ปค์ง„๋‹ค. ์„ธ๊ธˆ๊ณต์ œ๋ฅผ ๋ฐ›์„ ์ˆ˜ ์žˆ๋„๋ก ํ•˜๋ฉด------------------------------------------- ๊ฒฐ๊ณผ์ ์œผ๋กœ ๋…ธ๋™์ž์˜ ์˜๋ฃŒ๋ณดํ—˜ ๋ถ€๋‹ด์ด ์ปค์ง„๋‹ค.', + 'ํƒ€์ดํŠธํ•œ ์ผ์ • ์†์—์„œ๋„ ์ฃผ์–ด์ง„ ๋ชฉํ‘œ๋ฅผ ์ฒด๊ณ„์ ์œผ๋กœ ๋‹ฌ์„ฑํ•˜๋ฉฐ, ๋™์‹œ์— ์„ธ๋ถ€์ ์ธ ๋””ํ…Œ์ผ๊นŒ์ง€ ๋†“์น˜์ง€ ์•Š๋Š” ๋ชจ์Šต์„ ๋ณด์—ฌ์ฃผ์…จ์Šต๋‹ˆ๋‹ค. ํŠนํžˆ, ์ž‘์—… ๊ณผ์ •์—์„œ ์šฐ์„ ์ˆœ์œ„๋ฅผ ๋ช…ํ™•ํžˆ ์„ค์ •ํ•˜๊ณ , ๋ถˆํ•„์š”ํ•œ ์‹œ๊ฐ„ ๋‚ญ๋น„๋ฅผ ์ค„์ด๋Š” ํšจ์œจ์ ์ธ ์ ‘๊ทผ ๋ฐฉ์‹์€ ํŒ€์˜ ์ „๋ฐ˜์ ์ธ ์†๋„์™€ ์„ฑ๊ณผ์— ํฌ๊ฒŒ ๊ธฐ์—ฌํ–ˆ์Šต๋‹ˆ๋‹ค. ์•ž์œผ๋กœ๋„ ์ด๋Ÿฐ ์‹œ๊ฐ„ ๊ด€๋ฆฌ ๋Šฅ๋ ฅ์„ ํ†ตํ•ด ๋” ๋งŽ์€ ์„ฑ๊ณผ๋ฅผ ์ด๋ฃจ์‹œ๋ฆฌ๋ผ ๋ฏฟ์Šต๋‹ˆ๋‹ค.', highlights: [], }, ], diff --git a/frontend/src/pages/ReviewCollectionPage/components/ReviewCollectionPageContents/index.tsx b/frontend/src/pages/ReviewCollectionPage/components/ReviewCollectionPageContents/index.tsx index 5b8f77b54..44cd6c5e0 100644 --- a/frontend/src/pages/ReviewCollectionPage/components/ReviewCollectionPageContents/index.tsx +++ b/frontend/src/pages/ReviewCollectionPage/components/ReviewCollectionPageContents/index.tsx @@ -1,10 +1,10 @@ -import React, { useContext, useState } from 'react'; +import { useContext, useEffect, useState } from 'react'; import { Accordion, Dropdown, HighlightEditorContainer } from '@/components'; import { DropdownItem } from '@/components/common/Dropdown'; import ReviewEmptySection from '@/components/common/ReviewEmptySection'; import { ReviewInfoDataContext } from '@/components/layouts/ReviewDisplayLayout/ReviewInfoDataProvider'; -import { REVIEW_EMPTY } from '@/constants'; +import { REVIEW_EMPTY, SESSION_STORAGE_KEY } from '@/constants'; import { GroupedReview } from '@/types'; import { substituteString } from '@/utils'; @@ -18,6 +18,7 @@ const ReviewCollectionPageContents = () => { const { revieweeName, projectName, totalReviewCount } = useContext(ReviewInfoDataContext); const { data: reviewSectionList } = useGetSectionList(); + const dropdownSectionList = reviewSectionList.sections.map((section) => { return { text: section.name, value: section.id }; }); @@ -29,6 +30,12 @@ const ReviewCollectionPageContents = () => { review.votes?.sort((voteA, voteB) => voteB.count - voteA.count); }); + useEffect(() => { + return () => { + sessionStorage.removeItem(SESSION_STORAGE_KEY.currentReviewCollectionSectionId); + }; + }, []); + const renderContent = (review: GroupedReview) => { if (review.question.type === 'CHECKBOX') { const hasNoCheckboxAnswer = review.votes?.every((vote) => vote.count === 0); diff --git a/frontend/src/pages/ReviewCollectionPage/hooks/useGetGroupedReviews.ts b/frontend/src/pages/ReviewCollectionPage/hooks/useGetGroupedReviews.ts index be16a1427..27b2d687f 100644 --- a/frontend/src/pages/ReviewCollectionPage/hooks/useGetGroupedReviews.ts +++ b/frontend/src/pages/ReviewCollectionPage/hooks/useGetGroupedReviews.ts @@ -1,7 +1,7 @@ import { useSuspenseQuery } from '@tanstack/react-query'; import { getGroupedReviews } from '@/apis/review'; -import { REVIEW_QUERY_KEY } from '@/constants'; +import { REVIEW_QUERY_KEY, SESSION_STORAGE_KEY } from '@/constants'; import { GroupedReviews } from '@/types'; interface UseGetGroupedReviewsProps { @@ -11,6 +11,7 @@ interface UseGetGroupedReviewsProps { const useGetGroupedReviews = ({ sectionId }: UseGetGroupedReviewsProps) => { const fetchGroupedReviews = async () => { const result = await getGroupedReviews({ sectionId }); + sessionStorage.setItem(SESSION_STORAGE_KEY.currentReviewCollectionSectionId, sectionId.toString()); return result; }; diff --git a/frontend/src/pages/ReviewCollectionPage/index.tsx b/frontend/src/pages/ReviewCollectionPage/index.tsx index 9b838b0d0..c582d30e6 100644 --- a/frontend/src/pages/ReviewCollectionPage/index.tsx +++ b/frontend/src/pages/ReviewCollectionPage/index.tsx @@ -1,30 +1,9 @@ -import { useEffect } from 'react'; - import { AuthAndServerErrorFallback, ErrorSuspenseContainer, TopButton } from '@/components'; import ReviewDisplayLayout from '@/components/layouts/ReviewDisplayLayout'; -import { SESSION_STORAGE_KEY } from '@/constants'; import ReviewCollectionPageContents from './components/ReviewCollectionPageContents'; const ReviewCollectionPage = () => { - const clearEditorAnswerMapStorage = () => { - for (let i = 0; i < localStorage.length; i++) { - const key = localStorage.key(i); - - // ํ‚ค์— ํŠน์ • ๋ฌธ์ž์—ด์ด ํฌํ•จ๋˜์–ด ์žˆ๋Š”์ง€ ํ™•์ธ - if (key?.includes(SESSION_STORAGE_KEY.editorAnswerMap)) { - localStorage.removeItem(key); // ํ•ด๋‹น ํ‚ค ์‚ญ์ œ - i--; // removeItem ํ›„์— ์ธ๋ฑ์Šค๊ฐ€ ๋ณ€๊ฒฝ๋˜๋ฏ€๋กœ i๋ฅผ ๊ฐ์†Œ์‹œ์ผœ์•ผ ํ•จ - } - } - }; - - useEffect(() => { - return () => { - clearEditorAnswerMapStorage(); - }; - }, []); - return (