Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
689ca2c
chore: opencode 사용을 위해서 AGENTS.md 파일은 gitignore 처리
Dimo-2562 Mar 23, 2026
3f61a07
test: ExerciseQuery getExerciseDetail 테스트 정리
Dimo-2562 Mar 24, 2026
ba43ab5
test: 운동 수정용 상세 조회 테스트 코드 작성
Dimo-2562 Mar 25, 2026
c309736
test: 내가 초대한 게스트 조회 API 테스트 코드 작성
Dimo-2562 Mar 25, 2026
5f06806
test: 모임 운동 캘린더 조회 API 테스트 코드 작성
Dimo-2562 Mar 25, 2026
6a0a3f5
test: 모임 운동 캘린더 조회 API에서 기본 기간 테스트도 추가
Dimo-2562 Mar 25, 2026
402e072
test: 내 운동 캘린더 조회 API 테스트 코드 작성
Dimo-2562 Mar 25, 2026
f4165af
chore: 테스트 환경의 시간 존을 Asia로 설정
Dimo-2562 Mar 25, 2026
a8b23e4
test: 내 모임 운동 조회 API 테스트 코드 작성
Dimo-2562 Mar 25, 2026
81f5a92
chore: claude code와 omc 사용을 위해 깃 이그노어 처리
Dimo-2562 Mar 26, 2026
76a8e25
test: 내 모임 운동 캘린더 조회 API 테스트 코드 작성
Dimo-2562 Mar 26, 2026
524a759
test: 사용자 추천 운동 조회 API 테스트 코드 작성
Dimo-2562 Mar 27, 2026
80f3cd7
test: ExerciseFixture에서 오버로딩 호출 방식으로 구조 변경
Dimo-2562 Mar 27, 2026
78ebb30
fix: 기존 모임 운동 캘린더 조회 통합 테스트에서 날짜가 같아 깨지던 테스트를 수정
Dimo-2562 Mar 27, 2026
1657d73
test: 내 참여 운동 조회 API 테스트 코드 작성
Dimo-2562 Mar 27, 2026
eda73ce
test: 건물 운동 상세 조회 API 테스트 코드 작성
Dimo-2562 Mar 27, 2026
080385e
test: 월간 운동 건물 지도 데이터 조회 API 테스트 코드 작성
Dimo-2562 Mar 27, 2026
0ad152a
test: 추천 운동 캘린더 조회 API 테스트 코드 작성
Dimo-2562 Mar 27, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -50,4 +50,8 @@ terraform/terraform.tfstate.backup
terraform/terraform.tfvars

### firebase ###
src/main/resources/firebase/*.json
src/main/resources/firebase/*.json

### Claude / OMC ###
.claude/
.omc/
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;

class ExerciseIntegrationTest extends IntegrationTestBase {
class ExerciseCommandIntegrationTest extends IntegrationTestBase {

@Autowired MockMvc mockMvc;
@Autowired ObjectMapper objectMapper;
Expand Down Expand Up @@ -1096,205 +1096,4 @@ void guestNotInvitedByMember() throws Exception {
}
}

@Nested
@DisplayName("GET /api/exercises/{exerciseId} - 운동 상세 조회")
class GetExerciseDetail {

private Exercise exercise;

@BeforeEach
void setUp() {
exercise = exerciseRepository.save(
ExerciseFixture.createExerciseWithAddr(party, LocalDate.now().minusDays(1)));
}

@Nested
@DisplayName("성공 케이스")
class Success {

@Test
@DisplayName("응답의 모든 주요 필드가 올바르게 반환된다")
void 응답의_모든_주요_필드가_올바르게_반환된다() throws Exception {
SecurityContextHelper.setAuthentication(manager.getId(), manager.getNickname());

memberExerciseRepository.save(MemberFixture.createMemberExercise(normalMember, exercise));

mockMvc.perform(get("/api/exercises/{exerciseId}", exercise.getId()))
.andExpect(status().isOk())
.andExpect(jsonPath("$.data.isManager").value(true))
.andExpect(jsonPath("$.data.info.buildingName").value("테스트 체육관"))
.andExpect(jsonPath("$.data.info.location").value("서울특별시 강남구 테헤란로 1"))
.andExpect(jsonPath("$.data.participants.currentParticipantCount").value(1))
.andExpect(jsonPath("$.data.participants.totalCount").value(10))
.andExpect(jsonPath("$.data.participants.manCount").value(1))
.andExpect(jsonPath("$.data.participants.womenCount").value(0))
.andExpect(jsonPath("$.data.participants.list[0].participantNumber").value(1))
.andExpect(jsonPath("$.data.participants.list[0].name").isString())
.andExpect(jsonPath("$.data.participants.list[0].gender").value("MALE"))
.andExpect(jsonPath("$.data.participants.list[0].level").isString())
.andExpect(jsonPath("$.data.participants.list[0].participantType").isString())
.andExpect(jsonPath("$.data.participants.list[0].isWithdrawn").value(false))
.andExpect(jsonPath("$.data.waiting.currentWaitingCount").value(0));
}

@Test
@DisplayName("활성 회원 참가자는 isWithdrawn false로 반환된다")
void 활성_회원_참가자는_isWithdrawn_false로_반환된다() throws Exception {
SecurityContextHelper.setAuthentication(manager.getId(), manager.getNickname());

memberExerciseRepository.save(MemberFixture.createMemberExercise(normalMember, exercise));

mockMvc.perform(get("/api/exercises/{exerciseId}", exercise.getId()))
.andExpect(status().isOk())
.andExpect(jsonPath("$.data.participants.list[0].isWithdrawn").value(false));
}

@Test
@DisplayName("탈퇴 회원 참가자는 isWithdrawn true로 반환된다")
void 탈퇴_회원_참가자는_isWithdrawn_true로_반환된다() throws Exception {
SecurityContextHelper.setAuthentication(manager.getId(), manager.getNickname());

Member withdrawnMember = memberRepository.save(
MemberFixture.createWithdrawnMember("탈퇴회원", "탈퇴닉네임", 8888L));

memberExerciseRepository.save(MemberFixture.createMemberExercise(withdrawnMember, exercise));

mockMvc.perform(get("/api/exercises/{exerciseId}", exercise.getId()))
.andExpect(status().isOk())
.andExpect(jsonPath("$.data.participants.list[0].isWithdrawn").value(true));
}

@Test
@DisplayName("모임장이 조회하면 isManager true로 반환된다")
void 모임장이_조회하면_isManager_true로_반환된다() throws Exception {
SecurityContextHelper.setAuthentication(manager.getId(), manager.getNickname());

mockMvc.perform(get("/api/exercises/{exerciseId}", exercise.getId()))
.andExpect(status().isOk())
.andExpect(jsonPath("$.data.isManager").value(true));
}

@Test
@DisplayName("일반 멤버가 조회하면 isManager false로 반환된다")
void 일반_멤버가_조회하면_isManager_false로_반환된다() throws Exception {
SecurityContextHelper.setAuthentication(normalMember.getId(), normalMember.getNickname());

mockMvc.perform(get("/api/exercises/{exerciseId}", exercise.getId()))
.andExpect(status().isOk())
.andExpect(jsonPath("$.data.isManager").value(false));
}

@Test
@DisplayName("정원 초과 참가자는 대기자로 반환된다")
void 정원_초과_참가자는_대기자로_반환된다() throws Exception {
SecurityContextHelper.setAuthentication(manager.getId(), manager.getNickname());

Exercise smallExercise = exerciseRepository.save(
ExerciseFixture.createExerciseWithAddr(party, LocalDate.now().minusDays(1), 1));

memberExerciseRepository.save(MemberFixture.createMemberExercise(normalMember, smallExercise));
memberExerciseRepository.save(MemberFixture.createMemberExercise(subManager, smallExercise));

mockMvc.perform(get("/api/exercises/{exerciseId}", smallExercise.getId()))
.andExpect(status().isOk())
.andExpect(jsonPath("$.data.participants.currentParticipantCount").value(1))
.andExpect(jsonPath("$.data.waiting.currentWaitingCount").value(1));
}

@Test
@DisplayName("게스트 참가자는 inviterName이 반환된다")
void 게스트_참가자는_inviterName이_반환된다() throws Exception {
SecurityContextHelper.setAuthentication(manager.getId(), manager.getNickname());

guestRepository.save(GuestFixture.createGuest(exercise, manager.getId()));

mockMvc.perform(get("/api/exercises/{exerciseId}", exercise.getId()))
.andExpect(status().isOk())
.andExpect(jsonPath("$.data.participants.list[0].participantType").value("GUEST"))
.andExpect(jsonPath("$.data.participants.list[0].inviterName").isString());
}

@Test
@DisplayName("먼저 가입한 참가자가 더 낮은 participantNumber를 받는다")
void 먼저_가입한_참가자가_더_낮은_participantNumber를_받는다() throws Exception {
SecurityContextHelper.setAuthentication(manager.getId(), manager.getNickname());

memberExerciseRepository.save(MemberFixture.createMemberExercise(normalMember, exercise));
memberExerciseRepository.save(MemberFixture.createMemberExercise(subManager, exercise));

mockMvc.perform(get("/api/exercises/{exerciseId}", exercise.getId()))
.andExpect(status().isOk())
.andExpect(jsonPath("$.data.participants.currentParticipantCount").value(2))
.andExpect(jsonPath("$.data.participants.list[0].participantNumber").value(1))
.andExpect(jsonPath("$.data.participants.list[1].participantNumber").value(2))
.andExpect(jsonPath("$.data.participants.list[0].name").value(normalMember.getMemberName()))
.andExpect(jsonPath("$.data.participants.list[1].name").value(subManager.getMemberName()));
}

@Test
@DisplayName("대기자의 성별 카운트가 올바르게 반환된다")
void 대기자의_성별_카운트가_올바르게_반환된다() throws Exception {
SecurityContextHelper.setAuthentication(manager.getId(), manager.getNickname());

// 정원 1명짜리 운동: normalMember(MALE) 참가, subManager(FEMALE) 대기
Exercise smallExercise = exerciseRepository.save(
ExerciseFixture.createExerciseWithAddr(party, LocalDate.now().minusDays(1), 1));

memberExerciseRepository.save(MemberFixture.createMemberExercise(normalMember, smallExercise));
memberExerciseRepository.save(MemberFixture.createMemberExercise(subManager, smallExercise));

mockMvc.perform(get("/api/exercises/{exerciseId}", smallExercise.getId()))
.andExpect(status().isOk())
.andExpect(jsonPath("$.data.participants.currentParticipantCount").value(1))
.andExpect(jsonPath("$.data.participants.manCount").value(1))
.andExpect(jsonPath("$.data.participants.womenCount").value(0))
.andExpect(jsonPath("$.data.waiting.currentWaitingCount").value(1))
.andExpect(jsonPath("$.data.waiting.manCount").value(0))
.andExpect(jsonPath("$.data.waiting.womenCount").value(1));
}

@Test
@DisplayName("남성과 여성 참가자가 있을 때 성별 카운트가 올바르게 반환된다")
void 남성과_여성_참가자가_있을_때_성별_카운트가_올바르게_반환된다() throws Exception {
SecurityContextHelper.setAuthentication(manager.getId(), manager.getNickname());

// normalMember: MALE, subManager: FEMALE
memberExerciseRepository.save(MemberFixture.createMemberExercise(normalMember, exercise));
memberExerciseRepository.save(MemberFixture.createMemberExercise(subManager, exercise));

mockMvc.perform(get("/api/exercises/{exerciseId}", exercise.getId()))
.andExpect(status().isOk())
.andExpect(jsonPath("$.data.participants.currentParticipantCount").value(2))
.andExpect(jsonPath("$.data.participants.manCount").value(1))
.andExpect(jsonPath("$.data.participants.womenCount").value(1));
}
}

@Nested
@DisplayName("실패 케이스")
class Failure {

@Test
@DisplayName("존재하지 않는 운동이면 에러를 반환한다")
void 존재하지_않는_운동이면_에러를_반환한다() throws Exception {
SecurityContextHelper.setAuthentication(manager.getId(), manager.getNickname());

mockMvc.perform(get("/api/exercises/{exerciseId}", 999L))
.andExpect(status().isNotFound())
.andExpect(jsonPath("$.code").value(ExerciseErrorCode.EXERCISE_NOT_FOUND.getCode()))
.andExpect(jsonPath("$.message").value(ExerciseErrorCode.EXERCISE_NOT_FOUND.getMessage()));
}

@Test
@DisplayName("존재하지 않는 멤버면 에러를 반환한다")
void 존재하지_않는_멤버면_에러를_반환한다() throws Exception {
SecurityContextHelper.setAuthentication(999L, "없는멤버");

mockMvc.perform(get("/api/exercises/{exerciseId}", exercise.getId()))
.andExpect(status().isNotFound())
.andExpect(jsonPath("$.code").value(ExerciseErrorCode.MEMBER_NOT_FOUND.getCode()))
.andExpect(jsonPath("$.message").value(ExerciseErrorCode.MEMBER_NOT_FOUND.getMessage()));
}
}
}
}
Loading