diff --git a/src/main/kotlin/picklab/backend/common/model/SuccessCode.kt b/src/main/kotlin/picklab/backend/common/model/SuccessCode.kt index 3ef636c9..83adf1d4 100644 --- a/src/main/kotlin/picklab/backend/common/model/SuccessCode.kt +++ b/src/main/kotlin/picklab/backend/common/model/SuccessCode.kt @@ -21,6 +21,7 @@ enum class SuccessCode( UPDATE_EMAIL_AGREEMENT(HttpStatus.OK, "이메일 마케팅 수신 동의 정보를 수정했습니다."), GET_MEMBER_SOCIAL_LOGINS(HttpStatus.OK, "소셜 로그인 연동 정보 조회에 성공했습니다."), GET_MEMBER_ME(HttpStatus.OK, "내 정보 조회에 성공했습니다."), + CHECK_NICKNAME_AVAILABILITY(HttpStatus.OK, "닉네임 사용 가능 여부 조회에 성공했습니다."), MEMBER_WITHDRAW(HttpStatus.OK, "회원 탈퇴에 성공했습니다."), SUBMIT_SURVEY(HttpStatus.OK, "탈퇴 설문 제출에 성공했습니다."), MEMBER_NOTIFICATION_UPDATED(HttpStatus.OK, "알림 변경에 성공했습니다."), diff --git a/src/main/kotlin/picklab/backend/member/application/MemberUseCase.kt b/src/main/kotlin/picklab/backend/member/application/MemberUseCase.kt index 4bbd8f8e..b47272ae 100644 --- a/src/main/kotlin/picklab/backend/member/application/MemberUseCase.kt +++ b/src/main/kotlin/picklab/backend/member/application/MemberUseCase.kt @@ -130,11 +130,19 @@ class MemberUseCase( fun getSocialLogins(memberId: Long) = memberService.getSocialLogins(memberId) + fun isNicknameAvailable(nickname: String): Boolean = !memberService.existByNickname(nickname) + @Transactional(readOnly = true) fun getMemberMe(memberId: Long): MemberMeResult { val member = memberService.findActiveMember(memberId) val interestedJobCategories = memberService.findInterestedJobCategories(memberId) - return member.toMemberMeResult(interestedJobCategories) + val emailAgreement = memberService.findEmailAgreement(memberId) + val notificationPreference = memberService.findNotificationPreference(memberId) + return member.toMemberMeResult( + interestedJobCategories = interestedJobCategories, + emailAgreement = emailAgreement, + notificationPreference = notificationPreference, + ) } fun withdrawMember(memberId: Long) { diff --git a/src/main/kotlin/picklab/backend/member/application/mapper/MemberMeMapper.kt b/src/main/kotlin/picklab/backend/member/application/mapper/MemberMeMapper.kt index 8c1a7c66..f4ca2f8f 100644 --- a/src/main/kotlin/picklab/backend/member/application/mapper/MemberMeMapper.kt +++ b/src/main/kotlin/picklab/backend/member/application/mapper/MemberMeMapper.kt @@ -3,8 +3,13 @@ package picklab.backend.member.application.mapper import picklab.backend.member.application.model.MemberMeResult import picklab.backend.member.domain.entity.InterestedJobCategory import picklab.backend.member.domain.entity.Member +import picklab.backend.member.domain.entity.NotificationPreference -fun Member.toMemberMeResult(interestedJobCategories: List): MemberMeResult = +fun Member.toMemberMeResult( + interestedJobCategories: List, + emailAgreement: Boolean, + notificationPreference: NotificationPreference, +): MemberMeResult = MemberMeResult( name = this.name, nickname = this.nickname, @@ -14,4 +19,7 @@ fun Member.toMemberMeResult(interestedJobCategories: List jobFields = interestedJobCategories.map { it.jobCategory.jobGroup }.distinct(), employmentStatus = this.employmentStatus, company = this.company, + emailAgreement = emailAgreement, + notifyPopularActivity = notificationPreference.notifyPopularActivity, + notifyBookmarkedActivity = notificationPreference.notifyBookmarkedActivity, ) diff --git a/src/main/kotlin/picklab/backend/member/application/model/MemberMeResult.kt b/src/main/kotlin/picklab/backend/member/application/model/MemberMeResult.kt index 95bb876d..1d553a83 100644 --- a/src/main/kotlin/picklab/backend/member/application/model/MemberMeResult.kt +++ b/src/main/kotlin/picklab/backend/member/application/model/MemberMeResult.kt @@ -13,4 +13,7 @@ data class MemberMeResult( val jobFields: List, val employmentStatus: String, val company: String, + val emailAgreement: Boolean, + val notifyPopularActivity: Boolean, + val notifyBookmarkedActivity: Boolean, ) diff --git a/src/main/kotlin/picklab/backend/member/domain/MemberService.kt b/src/main/kotlin/picklab/backend/member/domain/MemberService.kt index d6f70e8c..b5b3227a 100644 --- a/src/main/kotlin/picklab/backend/member/domain/MemberService.kt +++ b/src/main/kotlin/picklab/backend/member/domain/MemberService.kt @@ -239,6 +239,12 @@ class MemberService( fun findInterestedJobCategories(memberId: Long): List = interestedJobCategoryRepository.findAllByMemberIdWithJobCategory(memberId) + @Transactional(readOnly = true) + fun findEmailAgreement(memberId: Long): Boolean = memberAgreementRepository.findByMemberId(memberId)?.emailAgreement ?: false + + fun findNotificationPreference(memberId: Long): NotificationPreference = + notificationPreferenceService.getNotificationPreference(memberId) + @Transactional fun withdrawMember(memberId: Long) { val member = findActiveMember(memberId) diff --git a/src/main/kotlin/picklab/backend/member/entrypoint/MemberApi.kt b/src/main/kotlin/picklab/backend/member/entrypoint/MemberApi.kt index 1195b673..40bd4140 100644 --- a/src/main/kotlin/picklab/backend/member/entrypoint/MemberApi.kt +++ b/src/main/kotlin/picklab/backend/member/entrypoint/MemberApi.kt @@ -5,6 +5,7 @@ import io.swagger.v3.oas.annotations.responses.ApiResponse import io.swagger.v3.oas.annotations.responses.ApiResponses import io.swagger.v3.oas.annotations.tags.Tag import jakarta.validation.Valid +import org.springdoc.core.annotations.ParameterObject import org.springframework.http.ResponseEntity import org.springframework.security.core.annotation.AuthenticationPrincipal import org.springframework.web.bind.annotation.RequestBody @@ -12,6 +13,7 @@ import picklab.backend.common.model.MemberPrincipal import picklab.backend.common.model.ResponseWrapper import picklab.backend.member.entrypoint.request.AdditionalInfoRequest import picklab.backend.member.entrypoint.request.MemberWithdrawalRequest +import picklab.backend.member.entrypoint.request.NicknameAvailabilityRequest import picklab.backend.member.entrypoint.request.SendEmailRequest import picklab.backend.member.entrypoint.request.ToggleMemberNotificationRequest import picklab.backend.member.entrypoint.request.UpdateEmailAgreementRequest @@ -22,6 +24,7 @@ import picklab.backend.member.entrypoint.request.UpdateProfileImageRequest import picklab.backend.member.entrypoint.request.VerifyEmailCodeRequest import picklab.backend.member.entrypoint.response.GetMemberMeResponse import picklab.backend.member.entrypoint.response.GetSocialLoginsResponse +import picklab.backend.member.entrypoint.response.NicknameAvailabilityResponse @Tag(name = "회원 API", description = "회원 관련 작업을 하는 API") interface MemberApi { @@ -42,6 +45,21 @@ interface MemberApi { @Valid @RequestBody request: AdditionalInfoRequest, ): ResponseEntity> + @Operation( + summary = "닉네임 사용 가능 여부 조회", + description = "회원가입에 사용할 닉네임의 중복 여부를 확인합니다.", + ) + @ApiResponses( + value = [ + ApiResponse(responseCode = "200", description = "닉네임 사용 가능 여부 조회에 성공했습니다."), + ApiResponse(responseCode = "400", description = "닉네임 형식이 올바르지 않습니다."), + ApiResponse(responseCode = "401", description = "인증되지 않은 사용자입니다."), + ], + ) + fun checkNicknameAvailability( + @Valid @ParameterObject request: NicknameAvailabilityRequest, + ): ResponseEntity> + @Operation( summary = "사용자 정보 수정", description = "사용자의 정보를 수정한다", diff --git a/src/main/kotlin/picklab/backend/member/entrypoint/MemberController.kt b/src/main/kotlin/picklab/backend/member/entrypoint/MemberController.kt index 00e9b208..7f412e12 100644 --- a/src/main/kotlin/picklab/backend/member/entrypoint/MemberController.kt +++ b/src/main/kotlin/picklab/backend/member/entrypoint/MemberController.kt @@ -6,6 +6,7 @@ import org.springframework.http.ResponseEntity import org.springframework.security.core.annotation.AuthenticationPrincipal import org.springframework.web.bind.annotation.DeleteMapping import org.springframework.web.bind.annotation.GetMapping +import org.springframework.web.bind.annotation.ModelAttribute import org.springframework.web.bind.annotation.PatchMapping import org.springframework.web.bind.annotation.PostMapping import org.springframework.web.bind.annotation.PutMapping @@ -19,6 +20,7 @@ import picklab.backend.member.application.MemberUseCase import picklab.backend.member.entrypoint.mapper.toResponse import picklab.backend.member.entrypoint.request.AdditionalInfoRequest import picklab.backend.member.entrypoint.request.MemberWithdrawalRequest +import picklab.backend.member.entrypoint.request.NicknameAvailabilityRequest import picklab.backend.member.entrypoint.request.SendEmailRequest import picklab.backend.member.entrypoint.request.ToggleMemberNotificationRequest import picklab.backend.member.entrypoint.request.UpdateEmailAgreementRequest @@ -29,6 +31,7 @@ import picklab.backend.member.entrypoint.request.UpdateProfileImageRequest import picklab.backend.member.entrypoint.request.VerifyEmailCodeRequest import picklab.backend.member.entrypoint.response.GetMemberMeResponse import picklab.backend.member.entrypoint.response.GetSocialLoginsResponse +import picklab.backend.member.entrypoint.response.NicknameAvailabilityResponse @RestController @RequestMapping("/v1/members") @@ -50,6 +53,15 @@ class MemberController( .body(ResponseWrapper.success(SuccessCode.SIGNUP_SUCCESS, Unit)) } + @GetMapping("/nickname-availability") + override fun checkNicknameAvailability( + @Valid @ModelAttribute request: NicknameAvailabilityRequest, + ): ResponseEntity> = + NicknameAvailabilityResponse( + available = memberUseCase.isNicknameAvailable(request.nickname), + ).let { ResponseWrapper.success(SuccessCode.CHECK_NICKNAME_AVAILABILITY, it) } + .let { ResponseEntity.ok(it) } + @PutMapping("/info") override fun updateMemberInfo( @AuthenticationPrincipal member: MemberPrincipal, diff --git a/src/main/kotlin/picklab/backend/member/entrypoint/mapper/MemberMeMapper.kt b/src/main/kotlin/picklab/backend/member/entrypoint/mapper/MemberMeMapper.kt index 371d2eb9..1a9329f3 100644 --- a/src/main/kotlin/picklab/backend/member/entrypoint/mapper/MemberMeMapper.kt +++ b/src/main/kotlin/picklab/backend/member/entrypoint/mapper/MemberMeMapper.kt @@ -3,6 +3,7 @@ package picklab.backend.member.entrypoint.mapper import picklab.backend.member.application.model.MemberMeResult import picklab.backend.member.entrypoint.response.EmploymentInfoResponse import picklab.backend.member.entrypoint.response.GetMemberMeResponse +import picklab.backend.member.entrypoint.response.NotificationPreferencesResponse fun MemberMeResult.toResponse(): GetMemberMeResponse = GetMemberMeResponse( @@ -17,4 +18,10 @@ fun MemberMeResult.toResponse(): GetMemberMeResponse = employmentStatus = this.employmentStatus, company = this.company, ), + emailAgreement = this.emailAgreement, + notificationPreferences = + NotificationPreferencesResponse( + popular = this.notifyPopularActivity, + bookmarked = this.notifyBookmarkedActivity, + ), ) diff --git a/src/main/kotlin/picklab/backend/member/entrypoint/request/NicknameAvailabilityRequest.kt b/src/main/kotlin/picklab/backend/member/entrypoint/request/NicknameAvailabilityRequest.kt new file mode 100644 index 00000000..e838c644 --- /dev/null +++ b/src/main/kotlin/picklab/backend/member/entrypoint/request/NicknameAvailabilityRequest.kt @@ -0,0 +1,15 @@ +package picklab.backend.member.entrypoint.request + +import io.swagger.v3.oas.annotations.media.Schema +import jakarta.validation.constraints.NotBlank +import jakarta.validation.constraints.Pattern + +data class NicknameAvailabilityRequest( + @field:NotBlank(message = "닉네임은 필수 입력값입니다.") + @field:Pattern( + regexp = "^[a-zA-Z0-9가-힣_.-]{1,20}$", + message = "닉네임은 영문, 숫자, 한글, _, -, .만 사용 가능하며 최대 20자까지 입력 가능합니다.", + ) + @field:Schema(description = "중복 확인할 닉네임", example = "picklab멤버", maxLength = 20) + val nickname: String, +) diff --git a/src/main/kotlin/picklab/backend/member/entrypoint/response/GetMemberMeResponse.kt b/src/main/kotlin/picklab/backend/member/entrypoint/response/GetMemberMeResponse.kt index 1053bf6d..8cf6d237 100644 --- a/src/main/kotlin/picklab/backend/member/entrypoint/response/GetMemberMeResponse.kt +++ b/src/main/kotlin/picklab/backend/member/entrypoint/response/GetMemberMeResponse.kt @@ -20,6 +20,10 @@ data class GetMemberMeResponse( val jobFields: List, @field:Schema(description = "재직 상태") val employment: EmploymentInfoResponse, + @field:Schema(description = "이메일 마케팅 수신 동의 여부") + val emailAgreement: Boolean, + @field:Schema(description = "알림 수신 설정") + val notificationPreferences: NotificationPreferencesResponse, ) data class EmploymentInfoResponse( @@ -28,3 +32,10 @@ data class EmploymentInfoResponse( @field:Schema(description = "회사") val company: String, ) + +data class NotificationPreferencesResponse( + @field:Schema(description = "인기 공고 알림 수신 여부") + val popular: Boolean, + @field:Schema(description = "저장한 공고 알림 수신 여부") + val bookmarked: Boolean, +) diff --git a/src/main/kotlin/picklab/backend/member/entrypoint/response/NicknameAvailabilityResponse.kt b/src/main/kotlin/picklab/backend/member/entrypoint/response/NicknameAvailabilityResponse.kt new file mode 100644 index 00000000..728e4f9b --- /dev/null +++ b/src/main/kotlin/picklab/backend/member/entrypoint/response/NicknameAvailabilityResponse.kt @@ -0,0 +1,8 @@ +package picklab.backend.member.entrypoint.response + +import io.swagger.v3.oas.annotations.media.Schema + +data class NicknameAvailabilityResponse( + @field:Schema(description = "닉네임 사용 가능 여부") + val available: Boolean, +) diff --git a/src/main/kotlin/picklab/backend/participation/entrypoint/ActivityParticipationApi.kt b/src/main/kotlin/picklab/backend/participation/entrypoint/ActivityParticipationApi.kt index 0b9e9180..5a8311c8 100644 --- a/src/main/kotlin/picklab/backend/participation/entrypoint/ActivityParticipationApi.kt +++ b/src/main/kotlin/picklab/backend/participation/entrypoint/ActivityParticipationApi.kt @@ -3,6 +3,9 @@ package picklab.backend.participation.entrypoint import io.swagger.v3.oas.annotations.Operation import io.swagger.v3.oas.annotations.responses.ApiResponse import io.swagger.v3.oas.annotations.tags.Tag +import jakarta.validation.Valid +import jakarta.validation.constraints.Max +import jakarta.validation.constraints.Min import org.springframework.http.ResponseEntity import picklab.backend.common.model.MemberPrincipal import picklab.backend.common.model.PageResponse @@ -42,7 +45,7 @@ interface ActivityParticipationApi { fun updateApplicationStatus( member: MemberPrincipal, participationId: Long, - request: UpdateApplicationStatusRequest, + @Valid request: UpdateApplicationStatusRequest, ): ResponseEntity> @Operation( @@ -52,7 +55,7 @@ interface ActivityParticipationApi { fun updateProgressStatus( member: MemberPrincipal, participationId: Long, - request: UpdateProgressStatusRequest, + @Valid request: UpdateProgressStatusRequest, ): ResponseEntity> @Operation( @@ -62,8 +65,8 @@ interface ActivityParticipationApi { fun getResults( member: MemberPrincipal, applicationStatus: List?, - page: Int, - size: Int, + @Min(1) page: Int, + @Min(1) @Max(100) size: Int, ): ResponseEntity>> @Operation( diff --git a/src/main/kotlin/picklab/backend/participation/entrypoint/ActivityParticipationController.kt b/src/main/kotlin/picklab/backend/participation/entrypoint/ActivityParticipationController.kt index dab30c96..fe3c3a8d 100644 --- a/src/main/kotlin/picklab/backend/participation/entrypoint/ActivityParticipationController.kt +++ b/src/main/kotlin/picklab/backend/participation/entrypoint/ActivityParticipationController.kt @@ -1,8 +1,5 @@ package picklab.backend.participation.entrypoint -import jakarta.validation.Valid -import jakarta.validation.constraints.Max -import jakarta.validation.constraints.Min import org.springframework.http.HttpStatus import org.springframework.http.ResponseEntity import org.springframework.security.core.annotation.AuthenticationPrincipal @@ -53,7 +50,7 @@ class ActivityParticipationController( override fun updateApplicationStatus( @AuthenticationPrincipal member: MemberPrincipal, @PathVariable participationId: Long, - @Valid @RequestBody request: UpdateApplicationStatusRequest, + @RequestBody request: UpdateApplicationStatusRequest, ): ResponseEntity> { activityParticipationUseCase.updateApplicationStatus( memberId = member.memberId, @@ -67,7 +64,7 @@ class ActivityParticipationController( override fun updateProgressStatus( @AuthenticationPrincipal member: MemberPrincipal, @PathVariable participationId: Long, - @Valid @RequestBody request: UpdateProgressStatusRequest, + @RequestBody request: UpdateProgressStatusRequest, ): ResponseEntity> { activityParticipationUseCase.updateProgressStatus( memberId = member.memberId, @@ -81,8 +78,8 @@ class ActivityParticipationController( override fun getResults( @AuthenticationPrincipal member: MemberPrincipal, @RequestParam(required = false) applicationStatus: List?, - @RequestParam(defaultValue = "1") @Min(1) page: Int, - @RequestParam(defaultValue = "10") @Min(1) @Max(100) size: Int, + @RequestParam(defaultValue = "1") page: Int, + @RequestParam(defaultValue = "10") size: Int, ): ResponseEntity>> { val response = activityParticipationUseCase.getResults( diff --git a/src/main/kotlin/picklab/backend/review/application/mapper/ReviewViewMapperDetail.kt b/src/main/kotlin/picklab/backend/review/application/mapper/ReviewViewMapperDetail.kt index f6f39bb8..533eb574 100644 --- a/src/main/kotlin/picklab/backend/review/application/mapper/ReviewViewMapperDetail.kt +++ b/src/main/kotlin/picklab/backend/review/application/mapper/ReviewViewMapperDetail.kt @@ -12,6 +12,7 @@ import picklab.backend.review.domain.entity.Review */ fun Review.toDetailView(): MyReviewDetailView = MyReviewDetailView( + activityId = this.activity.id, jobGroup = this.jobCategory.jobGroup, jobDetail = this.jobCategory.jobDetail, overallScore = this.overallScore, diff --git a/src/main/kotlin/picklab/backend/review/application/query/model/MyReviewDetailView.kt b/src/main/kotlin/picklab/backend/review/application/query/model/MyReviewDetailView.kt index 524b6642..479ecb8d 100644 --- a/src/main/kotlin/picklab/backend/review/application/query/model/MyReviewDetailView.kt +++ b/src/main/kotlin/picklab/backend/review/application/query/model/MyReviewDetailView.kt @@ -4,6 +4,7 @@ import picklab.backend.job.domain.enums.JobDetail import picklab.backend.job.domain.enums.JobGroup data class MyReviewDetailView( + val activityId: Long, val jobGroup: JobGroup, val jobDetail: JobDetail?, val overallScore: Int, diff --git a/src/main/kotlin/picklab/backend/review/entrypoint/mapper/ReviewDetailMapper.kt b/src/main/kotlin/picklab/backend/review/entrypoint/mapper/ReviewDetailMapper.kt index b7b639f3..537e635d 100644 --- a/src/main/kotlin/picklab/backend/review/entrypoint/mapper/ReviewDetailMapper.kt +++ b/src/main/kotlin/picklab/backend/review/entrypoint/mapper/ReviewDetailMapper.kt @@ -5,6 +5,7 @@ import picklab.backend.review.entrypoint.response.MyReviewResponse fun MyReviewDetailView.toResponse(): MyReviewResponse = MyReviewResponse( + activityId = this.activityId, jobGroup = this.jobGroup, jobDetail = this.jobDetail, overallScore = this.overallScore, diff --git a/src/main/kotlin/picklab/backend/review/entrypoint/response/MyReviewResponse.kt b/src/main/kotlin/picklab/backend/review/entrypoint/response/MyReviewResponse.kt index caac1eb8..c4e06152 100644 --- a/src/main/kotlin/picklab/backend/review/entrypoint/response/MyReviewResponse.kt +++ b/src/main/kotlin/picklab/backend/review/entrypoint/response/MyReviewResponse.kt @@ -6,6 +6,8 @@ import picklab.backend.job.domain.enums.JobGroup @Schema(description = "내 리뷰 단건 조회 응답") data class MyReviewResponse( + @field:Schema(description = "활동 ID") + val activityId: Long, @field:Schema(description = "직무") val jobGroup: JobGroup, @field:Schema(description = "상세 직무 (null = 전체)") diff --git a/src/test/kotlin/picklab/backend/member/entrypoint/MemberControllerTest.kt b/src/test/kotlin/picklab/backend/member/entrypoint/MemberControllerTest.kt index 36576a1f..e1d384a9 100644 --- a/src/test/kotlin/picklab/backend/member/entrypoint/MemberControllerTest.kt +++ b/src/test/kotlin/picklab/backend/member/entrypoint/MemberControllerTest.kt @@ -5,6 +5,7 @@ import org.junit.jupiter.api.Assertions.assertTrue import org.junit.jupiter.api.DisplayName import org.junit.jupiter.api.Nested import org.junit.jupiter.api.Test +import org.mockito.BDDMockito.given import org.springframework.beans.factory.annotation.Autowired import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest import org.springframework.http.MediaType @@ -169,6 +170,46 @@ class MemberControllerTest { } } + @Nested + @WithMockUser + @DisplayName("닉네임 사용 가능 여부 조회") + inner class CheckNicknameAvailability { + @Test + @DisplayName("[성공] 사용 가능한 닉네임이면 true를 반환한다.") + fun available() { + given(memberUseCase.isNicknameAvailable("newNickname")).willReturn(true) + + mockMvc + .get("/v1/members/nickname-availability") { + param("nickname", "newNickname") + }.andExpect { status { isOk() } } + .andExpect { jsonPath("$.code") { value(SuccessCode.CHECK_NICKNAME_AVAILABILITY.status.value()) } } + .andExpect { jsonPath("$.message") { value(SuccessCode.CHECK_NICKNAME_AVAILABILITY.message) } } + .andExpect { jsonPath("$.data.available") { value(true) } } + } + + @Test + @DisplayName("[성공] 중복된 닉네임이면 false를 반환한다.") + fun unavailable() { + given(memberUseCase.isNicknameAvailable("usedNickname")).willReturn(false) + + mockMvc + .get("/v1/members/nickname-availability") { + param("nickname", "usedNickname") + }.andExpect { status { isOk() } } + .andExpect { jsonPath("$.data.available") { value(false) } } + } + + @Test + @DisplayName("[실패] 닉네임 형식이 올바르지 않으면 400을 반환한다.") + fun invalidNickname() { + mockMvc + .get("/v1/members/nickname-availability") { + param("nickname", "invalid nickname") + }.andExpect { status { isBadRequest() } } + } + } + @Nested @WithMockUser @DisplayName("회원 정보 수정") diff --git a/src/test/kotlin/picklab/backend/member/entrypoint/MemberMeControllerTest.kt b/src/test/kotlin/picklab/backend/member/entrypoint/MemberMeControllerTest.kt index fcf0b934..81813f1d 100644 --- a/src/test/kotlin/picklab/backend/member/entrypoint/MemberMeControllerTest.kt +++ b/src/test/kotlin/picklab/backend/member/entrypoint/MemberMeControllerTest.kt @@ -39,6 +39,9 @@ class MemberMeControllerTest { jobFields = listOf(JobGroup.DEVELOPMENT), employmentStatus = "재직 중", company = "Picklab", + emailAgreement = true, + notifyPopularActivity = true, + notifyBookmarkedActivity = false, ), ) @@ -57,5 +60,8 @@ class MemberMeControllerTest { .andExpect { jsonPath("$.data.job_fields[0]") { value("DEVELOPMENT") } } .andExpect { jsonPath("$.data.employment.employment_status") { value("재직 중") } } .andExpect { jsonPath("$.data.employment.company") { value("Picklab") } } + .andExpect { jsonPath("$.data.email_agreement") { value(true) } } + .andExpect { jsonPath("$.data.notification_preferences.popular") { value(true) } } + .andExpect { jsonPath("$.data.notification_preferences.bookmarked") { value(false) } } } } diff --git a/src/test/kotlin/picklab/backend/member/service/MemberMeServiceTest.kt b/src/test/kotlin/picklab/backend/member/service/MemberMeServiceTest.kt index 18e440f3..50ea065e 100644 --- a/src/test/kotlin/picklab/backend/member/service/MemberMeServiceTest.kt +++ b/src/test/kotlin/picklab/backend/member/service/MemberMeServiceTest.kt @@ -12,8 +12,12 @@ import picklab.backend.job.domain.enums.JobGroup import picklab.backend.member.application.MemberUseCase import picklab.backend.member.domain.entity.InterestedJobCategory import picklab.backend.member.domain.entity.Member +import picklab.backend.member.domain.entity.MemberAgreement +import picklab.backend.member.domain.entity.NotificationPreference import picklab.backend.member.domain.repository.InterestedJobCategoryRepository +import picklab.backend.member.domain.repository.MemberAgreementRepository import picklab.backend.member.domain.repository.MemberRepository +import picklab.backend.member.domain.repository.NotificationPreferenceRepository import picklab.backend.template.IntegrationTest import java.time.LocalDate @@ -27,6 +31,12 @@ class MemberMeServiceTest : IntegrationTest() { @Autowired lateinit var interestedJobCategoryRepository: InterestedJobCategoryRepository + @Autowired + lateinit var memberAgreementRepository: MemberAgreementRepository + + @Autowired + lateinit var notificationPreferenceRepository: NotificationPreferenceRepository + @Autowired lateinit var jobCategoryRepository: JobCategoryRepository @@ -51,6 +61,21 @@ class MemberMeServiceTest : IntegrationTest() { ), ) + memberAgreementRepository.save( + MemberAgreement( + member = member, + emailAgreement = true, + privacyAgreement = true, + ), + ) + notificationPreferenceRepository.save( + NotificationPreference( + member = member, + notifyPopularActivity = true, + notifyBookmarkedActivity = false, + ), + ) + val backend = jobCategoryRepository.save( JobCategory( @@ -83,5 +108,12 @@ class MemberMeServiceTest : IntegrationTest() { assertThat(result.jobFields).containsExactly(JobGroup.DEVELOPMENT) assertThat(result.employmentStatus).isEqualTo("재직 중") assertThat(result.company).isEqualTo("Picklab") + assertThat(result.emailAgreement).isTrue() + assertThat(result.notifyPopularActivity).isTrue() + assertThat(result.notifyBookmarkedActivity).isFalse() + + memberAgreementRepository.deleteAll() + + assertThat(memberUseCase.getMemberMe(member.id).emailAgreement).isFalse() } } diff --git a/src/test/kotlin/picklab/backend/participation/ActivityParticipationIntegrationTest.kt b/src/test/kotlin/picklab/backend/participation/ActivityParticipationIntegrationTest.kt index 86d03f0f..5839b2b6 100644 --- a/src/test/kotlin/picklab/backend/participation/ActivityParticipationIntegrationTest.kt +++ b/src/test/kotlin/picklab/backend/participation/ActivityParticipationIntegrationTest.kt @@ -179,6 +179,47 @@ class ActivityParticipationIntegrationTest : IntegrationTest() { .andExpect { jsonPath("$.data.completed_count") { value(1) } } } + @Test + @DisplayName("[성공] 활동 결과 목록을 조회한다") + fun getResults() { + val participation = + participationRepository.save( + ActivityParticipation( + applicationStatus = ApplicationStatus.APPLIED, + progressStatus = ProgressStatus.NOT_SELECTED, + member = member, + activity = activity, + ), + ) + + mockMvc + .get("/v1/activity-participations/results") { + param("page", "1") + param("size", "10") + }.andExpect { status { isOk() } } + .andExpect { jsonPath("$.data.items[0].participation_id") { value(participation.id) } } + .andExpect { jsonPath("$.data.items[0].activity_id") { value(activity.id) } } + .andExpect { jsonPath("$.data.items[0].title") { value("테스트 대외활동") } } + .andExpect { jsonPath("$.data.page") { value(1) } } + .andExpect { jsonPath("$.data.size") { value(10) } } + .andExpect { jsonPath("$.data.total_elements") { value(1) } } + + mockMvc + .get("/v1/activity-participations/results") + .andExpect { status { isOk() } } + + mockMvc + .get("/v1/activity-participations/results") { + param("size", "1") + }.andExpect { status { isOk() } } + .andExpect { jsonPath("$.data.size") { value(1) } } + + mockMvc + .get("/v1/activity-participations/results") { + param("page", "0") + }.andExpect { status { isBadRequest() } } + } + @Test @DisplayName("[실패] 최종 합격 상태가 아니면 수료 여부를 수정할 수 없다") fun cannotUpdateProgressStatusWithoutAccepted() {