diff --git a/animory/src/main/java/com/daggle/animory/domain/account/dto/request/ShelterAddressSignUpDto.java b/animory/src/main/java/com/daggle/animory/domain/account/dto/request/ShelterAddressSignUpDto.java index b0515110..30121335 100644 --- a/animory/src/main/java/com/daggle/animory/domain/account/dto/request/ShelterAddressSignUpDto.java +++ b/animory/src/main/java/com/daggle/animory/domain/account/dto/request/ShelterAddressSignUpDto.java @@ -11,7 +11,7 @@ public record ShelterAddressSignUpDto( @NotNull(message = "광역시/도를 입력해주세요.") Province province, @NotNull(message = "시/군/구를 입력해주세요.") String city, @NotNull(message = "도로명을 입력해주세요.") String roadName, - @NotNull(message = "상세 주소를 입력해주세요.") String detail) { + String detail) { public ShelterAddress getShelterAddress() { return ShelterAddress.builder() .province(province) diff --git a/animory/src/main/java/com/daggle/animory/domain/pet/entity/Pet.java b/animory/src/main/java/com/daggle/animory/domain/pet/entity/Pet.java index b25499a1..daba6e96 100644 --- a/animory/src/main/java/com/daggle/animory/domain/pet/entity/Pet.java +++ b/animory/src/main/java/com/daggle/animory/domain/pet/entity/Pet.java @@ -67,11 +67,6 @@ public class Pet extends BaseEntity { @JoinColumn(name = "shelter_id") private Shelter shelter; - @OneToOne(mappedBy = "pet") - @JoinColumn(name = "pet_polygon_profile_id") - private PetPolygonProfile petPolygonProfile; - - public void updateImage(final String imageUrl) { this.profileImageUrl = imageUrl; } diff --git a/animory/src/main/java/com/daggle/animory/domain/pet/entity/PetPolygonProfile.java b/animory/src/main/java/com/daggle/animory/domain/pet/entity/PetPolygonProfile.java index cdd22a5b..9cbeec5b 100644 --- a/animory/src/main/java/com/daggle/animory/domain/pet/entity/PetPolygonProfile.java +++ b/animory/src/main/java/com/daggle/animory/domain/pet/entity/PetPolygonProfile.java @@ -14,7 +14,6 @@ public class PetPolygonProfile { @Id - @GeneratedValue(strategy = GenerationType.IDENTITY) private Integer id; @MapsId @@ -24,7 +23,6 @@ public class PetPolygonProfile { private int intelligence; - private int affinity; private int athletic; diff --git a/animory/src/test/java/com/daggle/animory/acceptance/AccountTest.java b/animory/src/test/java/com/daggle/animory/acceptance/AccountTest.java new file mode 100644 index 00000000..8e7cd46a --- /dev/null +++ b/animory/src/test/java/com/daggle/animory/acceptance/AccountTest.java @@ -0,0 +1,120 @@ +package com.daggle.animory.acceptance; + +import com.daggle.animory.domain.account.dto.request.AccountLoginDto; +import com.daggle.animory.domain.account.dto.request.EmailValidateDto; +import com.daggle.animory.domain.account.dto.request.ShelterAddressSignUpDto; +import com.daggle.animory.domain.account.dto.request.ShelterSignUpDto; +import com.daggle.animory.domain.shelter.entity.Province; +import com.daggle.animory.testutil.AcceptanceTest; +import com.daggle.animory.testutil.fixture.AccountFixture; +import org.junit.jupiter.api.Test; +import org.springframework.http.MediaType; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + + +class AccountTest extends AcceptanceTest { + + private final String EMAIL = AccountFixture.EMAIL; + private final String PASSWORD = AccountFixture.PASSWORD; + + @Test + void 이메일_중복_검사() throws Exception { + final EmailValidateDto emailValidateDto = new EmailValidateDto(EMAIL + "1"); + + result = mvc.perform(post("/account/email") + .contentType(MediaType.APPLICATION_JSON) + .content(om.writeValueAsString(emailValidateDto))); + + assertSuccess(); + } + + @Test + void 보호소_회원가입() throws Exception { + final ShelterSignUpDto shelterSignUpDto = ShelterSignUpDto.builder() + .email(EMAIL + "1") + .password(PASSWORD) + .name("테스트 보호소") + .address( + ShelterAddressSignUpDto.builder() + .province(Province.광주) + .city("무슨무슨구") + .roadName("무슨무슨로") + .detail("상세주소 1234-56") + .build() + ) + .contact("010-1234-5678") + .build(); + + + result = mvc.perform(post("/account/shelter") + .contentType(MediaType.APPLICATION_JSON) + .content(om.writeValueAsString(shelterSignUpDto))); + + assertSuccess(); + } + + @Test + void 중복된_이메일로_회원가입_불가() throws Exception { + final ShelterSignUpDto shelterSignUpDto = ShelterSignUpDto.builder() + .email(EMAIL) + .password(PASSWORD) + .name("테스트 보호소") + .address( + ShelterAddressSignUpDto.builder() + .province(Province.광주) + .city("무슨무슨구") + .roadName("무슨무슨로") + .detail("상세주소 1234-56") + .build() + ) + .contact("010-1234-5678") + .build(); + + + result = mvc.perform(post("/account/shelter") + .contentType(MediaType.APPLICATION_JSON) + .content(om.writeValueAsString(shelterSignUpDto))) + .andExpect(status().isBadRequest()) + .andExpect(jsonPath("$.success").value(false)); + } + + @Test + void 보호소_로그인() throws Exception { + final AccountLoginDto accountLoginDto = AccountLoginDto.builder() + .email(EMAIL) + .password(PASSWORD) + .build(); + + result = mvc.perform(post("/account/login") + .contentType(MediaType.APPLICATION_JSON) + .content(om.writeValueAsString(accountLoginDto))); + + assertSuccess(); + + // header authorization field exists + assertThat( result.andReturn() + .getResponse() + .getHeader("Authorization") ).isNotNull(); + } + + @Test + void 존재하지_않는_계정으로_로그인_실패와_안내문구() throws Exception { + final AccountLoginDto accountLoginDto = AccountLoginDto.builder() + .email(EMAIL + "1") + .password(PASSWORD) + .build(); + + result = mvc.perform(post("/account/login") + .contentType(MediaType.APPLICATION_JSON) + .content(om.writeValueAsString(accountLoginDto))) + .andExpect(status().isBadRequest()) + .andExpect(jsonPath("$.success").value(false)) + .andExpect(jsonPath("$.error.message").value("이메일 또는 비밀번호를 확인해주세요.")); + + } + +} diff --git a/animory/src/test/java/com/daggle/animory/acceptance/AnimoryAcceptanceTest.java b/animory/src/test/java/com/daggle/animory/acceptance/AnimoryAcceptanceTest.java deleted file mode 100644 index 2aa08018..00000000 --- a/animory/src/test/java/com/daggle/animory/acceptance/AnimoryAcceptanceTest.java +++ /dev/null @@ -1,206 +0,0 @@ -package com.daggle.animory.acceptance; - -import com.daggle.animory.domain.account.dto.request.AccountLoginDto; -import com.daggle.animory.domain.account.dto.request.EmailValidateDto; -import com.daggle.animory.domain.account.dto.request.ShelterAddressSignUpDto; -import com.daggle.animory.domain.account.dto.request.ShelterSignUpDto; -import com.daggle.animory.domain.pet.dto.PetPolygonProfileDto; -import com.daggle.animory.domain.pet.dto.request.PetRegisterRequestDto; -import com.daggle.animory.domain.pet.entity.AdoptionStatus; -import com.daggle.animory.domain.pet.entity.NeutralizationStatus; -import com.daggle.animory.domain.pet.entity.PetType; -import com.daggle.animory.domain.pet.entity.Sex; -import com.daggle.animory.domain.shelter.entity.Province; -import com.daggle.animory.testutil.AcceptanceTest; -import lombok.extern.slf4j.Slf4j; -import org.json.JSONObject; -import org.junit.jupiter.api.Test; -import org.springframework.http.MediaType; -import org.springframework.mock.web.MockMultipartFile; -import org.springframework.mock.web.MockPart; -import org.springframework.transaction.annotation.Transactional; - -import java.nio.charset.StandardCharsets; -import java.time.LocalDate; -import java.util.HashMap; -import java.util.Map; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.springframework.http.HttpMethod.POST; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; - -/** - *
- * - * A. 보호소 계정 회원가입, 로그인 - * - * B. 펫 등록, 수정 - * - * - * - * - * - *- */ -@Slf4j -@Transactional -class AnimoryAcceptanceTest extends AcceptanceTest { - - private final Map
+ * 상세정보 + * 동물 상세 정보 조회 API에서는 + * 1. 보호중인 보호소의 정보를 알 수 있다. + * 2. 오각형으로 이뤄진 동물 특성을 알 수 있다. + * 3. 해당 동물의 프로필 사진 한 개를 볼 수 있다.+ */ + @Test + void 펫_상세정보_조회() throws Exception { + result = mvc.perform(get("/pet/{petId}", 1)) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.response.shelterInfo.id").isNotEmpty()) + .andExpect(jsonPath("$.response.shelterInfo.name").isNotEmpty()) + .andExpect(jsonPath("$.response.shelterInfo.contact").isNotEmpty()) + .andExpect(jsonPath("$.response.petPolygonProfileDto").isNotEmpty()) + .andExpect(jsonPath("$.response.petPolygonProfileDto.intelligence").value(3)) + .andExpect(jsonPath("$.response.profileImageUrl").isNotEmpty()); + } + + /** + * 유기동물 프로필 리스트 + * 동물 기본 정보(식별자, 프로필 사진, 이름, 나이, 소속 보호소, 입양상태, 안락사 예정여부)를 확인할 수 있다. + * 조회 기준은 둥록일 최신순 또는 보호만료일이 가까운 순으로 확인할 수 있다. + * 더보기 버튼을 통해 최신순 또는 안락사 기간 기준으로 각각 전체 리스트를 확인할 수 있다. + * 페이지 당 프로필을 각각 8개 단위로 확인할 수 있다. + */ + @Test + void 유기동물_프로필_리스트() throws Exception { + result = mvc.perform(get("/pet/profiles")) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.response.sosList").isNotEmpty()) + .andExpect(jsonPath("$.response.newList").isNotEmpty()) + // TODO: + .andDo(print()); + } + + +} diff --git a/animory/src/test/java/com/daggle/animory/acceptance/ShelterTest.java b/animory/src/test/java/com/daggle/animory/acceptance/ShelterTest.java new file mode 100644 index 00000000..9a1a722f --- /dev/null +++ b/animory/src/test/java/com/daggle/animory/acceptance/ShelterTest.java @@ -0,0 +1,41 @@ +package com.daggle.animory.acceptance; + +import com.daggle.animory.testutil.AcceptanceTest; +import org.junit.jupiter.api.Test; + +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; +import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +class ShelterTest extends AcceptanceTest { + + /** + 근처 동물 보호소 보기 (지도 페이지) + 입력받은 주소(kakao id)들 중 DB에 존재하는 주소(kakao id)들을 찾아서 필터링하여 응답한다. + */ + @Test + void 근처_동물_보호소_보기() throws Exception { + mvc.perform(post("/shelter/filter") + .contentType("application/json") + .content("[14569757, 14569758, 14569759]")) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.response").isArray()) + .andExpect(jsonPath("$.response[0].kakaoLocationId").value(14569757)); + } + + /** + 보호소 상세 페이지(프로필) + 보호소 기본 정보(이름, 주소, 연락처)를 확인할 수 있다. + 해당 보호소가 보호중인 동물들을 확인할 수 있다. (유기동물 프로필 리스트 페이지와 동일하게 보여진다) + 앱에서 전화걸기를 클릭하면 전화번호가 뜬다. + */ + @Test + void 보호소_상세_페이지() throws Exception { + mvc.perform(get("/shelter/{shelterId}", 1) + .param("page", "0")) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.response.shelter.name").value("광주광역시동물보호소")) + .andDo(print()); + } +} diff --git a/animory/src/test/java/com/daggle/animory/acceptance/ShortFormTest.java b/animory/src/test/java/com/daggle/animory/acceptance/ShortFormTest.java new file mode 100644 index 00000000..fd53001b --- /dev/null +++ b/animory/src/test/java/com/daggle/animory/acceptance/ShortFormTest.java @@ -0,0 +1,65 @@ +package com.daggle.animory.acceptance; + +import com.daggle.animory.testutil.AcceptanceTest; +import org.junit.jupiter.api.Test; + +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +public class ShortFormTest extends AcceptanceTest { + + /** + * 홈 + * 숏폼 비디오 API는 회원 권한을 요구하지 않는다. + * 숏폼 비디오 응답에는 각각 Pet 식별자가 포함되어 있다. + * 숏폼 비디오 응답에는 해당 보호소 식별자, 보호소 이름도 포함되어 있다. + * 숏폼 비디오 응답에서 해당 동물의 입양여부를 알 수 있다. + */ + @Test + void 홈_화면_숏폼API() throws Exception { + mvc.perform(get("/short-forms/home") + .param("page", "0")) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.success").value(true)) + .andExpect(jsonPath("$.response.shortForms[0].petId").value(1)) + .andExpect(jsonPath("$.response.shortForms[0].name").value("멍멍이")) + .andExpect(jsonPath("$.response.shortForms[0].age").value("0년6개월")) + .andExpect(jsonPath("$.response.shortForms[0].shelterId").value(1)) + .andExpect(jsonPath("$.response.shortForms[0].shelterName").value("광주광역시동물보호소")) + .andExpect(jsonPath("$.response.shortForms[0].profileShortFormUrl").value("http://amazon.server/api/petVideo/20231001104521_test1.mp4")) + .andExpect(jsonPath("$.response.shortForms[0].adoptionStatus").value("NO")) + .andExpect(jsonPath("$.response.hasNext").value(true)) + .andDo(print()); + } + + + + + /** + * 카테고리 + * 숏폼 영상 검색 조건에서 동물 타입을 선택할 수 있다. + * 지역 카테고리도 검색할 수 있다. + * 숏폼 영상 응답에 동물 정보가 포함되어 있다. + */ + @Test + void 카테고리_숏폼API() throws Exception { + mvc.perform(get("/short-forms") + .param("page", "0") + .param("type", "DOG") + .param("area", "광주")) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.success").value(true)) + .andExpect(jsonPath("$.response.categoryTitle").value("광주광역시 기준 강아지 친구들")) + .andExpect(jsonPath("$.response.shortForms[0].petId").value(1)) + .andExpect(jsonPath("$.response.shortForms[0].name").value("멍멍이")) + .andExpect(jsonPath("$.response.shortForms[0].age").value("0년6개월")) + .andExpect(jsonPath("$.response.shortForms[0].shelterId").value(1)) + .andExpect(jsonPath("$.response.shortForms[0].shelterName").value("광주광역시동물보호소")) + .andExpect(jsonPath("$.response.shortForms[0].profileShortFormUrl").value("http://amazon.server/api/petVideo/20231001104521_test1.mp4")) + .andExpect(jsonPath("$.response.shortForms[0].adoptionStatus").value("NO")) + .andExpect(jsonPath("$.response.hasNext").value(true)) + .andDo(print()); + } +} diff --git a/animory/src/test/java/com/daggle/animory/testutil/AcceptanceTest.java b/animory/src/test/java/com/daggle/animory/testutil/AcceptanceTest.java index 55002f01..c93f6890 100644 --- a/animory/src/test/java/com/daggle/animory/testutil/AcceptanceTest.java +++ b/animory/src/test/java/com/daggle/animory/testutil/AcceptanceTest.java @@ -1,17 +1,38 @@ package com.daggle.animory.testutil; +import com.daggle.animory.common.security.TokenProvider; +import com.daggle.animory.domain.account.AccountRepository; +import com.daggle.animory.domain.account.entity.Account; +import com.daggle.animory.domain.account.entity.AccountRole; +import com.daggle.animory.domain.pet.entity.Pet; +import com.daggle.animory.domain.pet.entity.PetPolygonProfile; +import com.daggle.animory.domain.pet.entity.PetType; +import com.daggle.animory.domain.pet.repository.PetPolygonRepository; +import com.daggle.animory.domain.pet.repository.PetRepository; +import com.daggle.animory.domain.shelter.ShelterRepository; +import com.daggle.animory.domain.shelter.entity.Shelter; +import com.daggle.animory.testutil.fixture.AccountFixture; +import com.daggle.animory.testutil.fixture.PetFixture; +import com.daggle.animory.testutil.fixture.PetPolygonProfileFixture; +import com.daggle.animory.testutil.fixture.ShelterFixture; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; +import org.junit.jupiter.api.BeforeEach; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.ResultActions; +import org.springframework.transaction.annotation.Transactional; + +import javax.persistence.EntityManager; +import java.util.List; import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; +@Transactional @AutoConfigureMockMvc @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.MOCK) public abstract class AcceptanceTest { @@ -30,4 +51,57 @@ protected void assertSuccess() throws Exception { .andDo(print()); } + // token + + @Autowired + protected TokenProvider tokenProvider; + + protected String getShelterToken() { + return tokenProvider.create(AccountFixture.EMAIL, AccountRole.SHELTER); + } + + // dummy data setting + + @Autowired + protected AccountRepository accountRepository; + @Autowired + protected ShelterRepository shelterRepository; + @Autowired + protected PetRepository petRepository; + @Autowired + protected PetPolygonRepository petPolygonRepository; + + @Autowired + private EntityManager em; + + @BeforeEach + void setUpDummyData() { + resetDB(); + + // 보호소 계정 생성 + final Account shelterAccount = accountRepository.save(AccountFixture.getShelter()); + + // Shelter 등록 + final Shelter shelter = shelterRepository.save(ShelterFixture.getOne(shelterAccount)); // ShelterId = 1 + + // Pet 1마리 등록 + final Pet firstPet = petRepository.save(PetFixture.getOne(shelter)); // PetId = 1 + final PetPolygonProfile firstPetPolygonProfile = petPolygonRepository.save(PetPolygonProfileFixture.getOne(firstPet)); + + // Pet 10마리 등록 + final List