diff --git a/backend/build.gradle b/backend/build.gradle index 346de5c3..35c13751 100644 --- a/backend/build.gradle +++ b/backend/build.gradle @@ -78,7 +78,7 @@ subprojects { '**/CentralVaccinationInformationApplication*', '**/DummyData*', '**/CVIControllerAdvice*', - // cvi-publicdata-parser + // domain-cvi-publicdata-parser '**/Parser*', // domain-cvi '**/Sort*', @@ -103,7 +103,7 @@ subprojects { "**/*Test*.*, **/Q*.java, **/*Doc*.java, " + // api-cvi-api "**/CentralVaccinationInformationApplication.java, **/DataLoader.java, **/DummyData.java, **/CVIControllerAdvice.java, " + - // cvi-publicdata-parser + // domain-cvi-publicdata-parser "**/Parser.java, " + // domain-cvi "**/Sort.java, **/Filter.java, **/ImageType.java, " + diff --git a/backend/domain-cvi-publicdata-service/build.gradle b/backend/domain-cvi-publicdata-service/build.gradle index 4169e62a..965a2603 100644 --- a/backend/domain-cvi-publicdata-service/build.gradle +++ b/backend/domain-cvi-publicdata-service/build.gradle @@ -17,12 +17,12 @@ jacocoTestCoverageVerification { // 코드 커버리지 측정항목 시행 violationRules { // 위반 규칙 rule { enabled = true - element = 'GROUP' + element = 'BUNDLE' limit { counter = 'METHOD' value = 'COVEREDRATIO' - minimum = 0.90 + minimum = 1.0 } } } diff --git a/backend/domain-cvi-publicdata-service/src/test/java/com/cvi/PublicDataFactory.java b/backend/domain-cvi-publicdata-service/src/test/java/com/cvi/PublicDataFactory.java index 7219b323..7753bc24 100644 --- a/backend/domain-cvi-publicdata-service/src/test/java/com/cvi/PublicDataFactory.java +++ b/backend/domain-cvi-publicdata-service/src/test/java/com/cvi/PublicDataFactory.java @@ -58,47 +58,6 @@ public static KoreaVaccineParserResponse toVaccineParserResponse(LocalDate targe ), 18, 1, 20, 2634); } - public static List toVaccinationStatisticResponse(LocalDate targetDate) { - return Arrays.asList( - new VaccinationStatisticResponse(19473657, 7146602, targetDate, - 473850, 35955, "전국", 19947507, 7182557, BigDecimal.valueOf(39.2), BigDecimal.valueOf(14.3)), - new VaccinationStatisticResponse(3646765, 1329982, targetDate, - 77877, 7123, "서울특별시", 3724642, 1337105, BigDecimal.valueOf(39.5), BigDecimal.valueOf(14.4)), - new VaccinationStatisticResponse(1352394, 477845, targetDate, - 31252, 2628, "부산광역시", 1383646, 480473, BigDecimal.valueOf(41.8), BigDecimal.valueOf(14.6)), - new VaccinationStatisticResponse(848397, 309317, targetDate, - 22726, 2688, "대구광역시", 871123, 312005, BigDecimal.valueOf(37.0), BigDecimal.valueOf(13.4)), - new VaccinationStatisticResponse(1032052, 360923, targetDate, - 27394, 1760, "인천광역시", 1059446, 362683, BigDecimal.valueOf(39.8), BigDecimal.valueOf(14.7)), - new VaccinationStatisticResponse(549706, 204415, targetDate, - 13700, 830, "광주광역시", 563406, 205245, BigDecimal.valueOf(37.6), BigDecimal.valueOf(14.7)), - new VaccinationStatisticResponse(396793, 124839, targetDate, - 11275, 471, "울산광역시", 408068, 125310, BigDecimal.valueOf(37.6), BigDecimal.valueOf(14.0)), - new VaccinationStatisticResponse(523814, 197608, targetDate, - 12990, 959, "대전광역시", 536804, 198567, BigDecimal.valueOf(36.8), BigDecimal.valueOf(12.7)), - new VaccinationStatisticResponse(4636237, 1636357, targetDate, - 118717, 7895, "경기도", 4754954, 1644252, BigDecimal.valueOf(31.6), BigDecimal.valueOf(10.9)), - new VaccinationStatisticResponse(668422, 273253, targetDate, - 14908, 1010, "강원도", 683330, 274263, BigDecimal.valueOf(36.9), BigDecimal.valueOf(11.5)), - new VaccinationStatisticResponse(109202, 37624, targetDate, - 3028, 179, "세종특별자치시", 112230, 37803, BigDecimal.valueOf(42.7), BigDecimal.valueOf(15.8)), - new VaccinationStatisticResponse(639514, 240704, targetDate, - 15886, 1324, "충청북도", 655400, 242028, BigDecimal.valueOf(42.1), BigDecimal.valueOf(16.1)), - new VaccinationStatisticResponse(849914, 330591, targetDate, - 22167, 2054, "충청남도", 872081, 332645, BigDecimal.valueOf(45.6), BigDecimal.valueOf(17.8)), - new VaccinationStatisticResponse(789017, 311961, targetDate, - 17331, 1270, "전라북도", 806348, 313231, BigDecimal.valueOf(48.4), BigDecimal.valueOf(19.1)), - new VaccinationStatisticResponse(859228, 344275, targetDate, - 19083, 1378, "전라남도", 878311, 345653, BigDecimal.valueOf(42.7), BigDecimal.valueOf(16.0)), - new VaccinationStatisticResponse(1070878, 409752, targetDate, - 27263, 2016, "경상북도", 1098141, 411768, BigDecimal.valueOf(40.4), BigDecimal.valueOf(14.8)), - new VaccinationStatisticResponse(1249910, 464110, targetDate, - 31098, 1943, "경상남도", 1281008, 466053, BigDecimal.valueOf(39.2), BigDecimal.valueOf(14.3)), - new VaccinationStatisticResponse(251414, 93046, targetDate, - 7155, 427, "제주특별자치도", 258569, 93473, BigDecimal.valueOf(42.7), BigDecimal.valueOf(17.8)) - ); - } - public static WorldVaccinationParserResponse toWorldVaccinationParserResponse(LocalDate targetDate) { return new WorldVaccinationParserResponse("World", "OWID_WRL", Arrays.asList(new WorldVaccinationData(targetDate.minusDays(2).toString(), 4327424315L, 2293196690L, 1175939230L, @@ -110,18 +69,4 @@ public static WorldVaccinationParserResponse toWorldVaccinationParserResponse(Lo ) ); } - - public static List toVaccinationStatisticResponseOnlyWorldRegion(LocalDate targetDate) { - return Arrays.asList( - new VaccinationStatisticResponse(0, 0, targetDate, - 0, 0, "World", 2303769251L, 1191535085L, BigDecimal.valueOf(29.3), BigDecimal.valueOf(15.0)), - new VaccinationStatisticResponse(0, 0, targetDate.minusDays(1), - 0, 0, "World", 2293196690L, 1175939230L, BigDecimal.valueOf(28.9), BigDecimal.valueOf(14.7)) - ); - } - - public static VaccinationStatisticResponse toSingleWorldVaccinationStatisticResponse(LocalDate targetDate) { - return new VaccinationStatisticResponse(0, 0, targetDate, - 0, 0, "World", 2303769251L, 1191535085L, BigDecimal.valueOf(29.3), BigDecimal.valueOf(15.0)); - } } diff --git a/backend/domain-cvi-publicdata-service/src/test/java/com/cvi/service/CacheEventLoggerTest.java b/backend/domain-cvi-publicdata-service/src/test/java/com/cvi/service/CacheEventLoggerTest.java new file mode 100644 index 00000000..11b03c6e --- /dev/null +++ b/backend/domain-cvi-publicdata-service/src/test/java/com/cvi/service/CacheEventLoggerTest.java @@ -0,0 +1,29 @@ +package com.cvi.service; + +import org.ehcache.event.CacheEvent; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import static org.mockito.BDDMockito.willReturn; +import static org.mockito.Mockito.*; + +@DisplayName("CacheEventLogger 기능 테스트") +class CacheEventLoggerTest { + + @DisplayName("이벤트 호출 확인 - 성공") + @Test + void onEvent() { + //given + CacheEventLogger cacheEventLogger = new CacheEventLogger(); + final CacheEvent cacheEvent = mock(CacheEvent.class); + //when + willReturn(1L).given(cacheEvent).getKey(); + willReturn("이전 캐시").given(cacheEvent).getOldValue(); + willReturn("새로운 캐시").given(cacheEvent).getNewValue(); + cacheEventLogger.onEvent(cacheEvent); + //then + verify(cacheEvent, times(1)).getKey(); + verify(cacheEvent, times(1)).getOldValue(); + verify(cacheEvent, times(1)).getNewValue(); + } +} diff --git a/backend/domain-cvi-publicdata-service/src/test/java/com/cvi/service/PublicDataServiceTest.java b/backend/domain-cvi-publicdata-service/src/test/java/com/cvi/service/PublicDataServiceTest.java index db994744..8135c4ae 100644 --- a/backend/domain-cvi-publicdata-service/src/test/java/com/cvi/service/PublicDataServiceTest.java +++ b/backend/domain-cvi-publicdata-service/src/test/java/com/cvi/service/PublicDataServiceTest.java @@ -22,7 +22,6 @@ import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; import org.springframework.beans.factory.annotation.Autowired; @@ -43,7 +42,7 @@ class PublicDataServiceTest { private VaccinationParser vaccinationParser; - public static Stream targetDate() { + public static Stream koreaVaccinationTargetDate() { return Stream.of( Arguments.of(LocalDate.now()), Arguments.of(LocalDate.now().minusDays(1)), @@ -51,6 +50,14 @@ public static Stream targetDate() { ); } + public static Stream worldVaccinationTargetDate() { + return Stream.of( + Arguments.of(LocalDate.now()), + Arguments.of(LocalDate.now().minusDays(1)), + Arguments.of(LocalDate.now().minusDays(2)) + ); + } + @BeforeEach void init() { vaccinationParser = mock(VaccinationParser.class); @@ -64,7 +71,7 @@ void clear() { @DisplayName("백신 정종률 데이터 저장 - 성공") @CustomParameterizedTest - @MethodSource("targetDate") + @MethodSource("koreaVaccinationTargetDate") void saveVaccinationStatistics(LocalDate targetDate) { //given //when @@ -77,7 +84,7 @@ void saveVaccinationStatistics(LocalDate targetDate) { @DisplayName("백신 정종률 데이터 조회 - 성공") @CustomParameterizedTest - @MethodSource("targetDate") + @MethodSource("koreaVaccinationTargetDate") void findVaccinationStatistics(LocalDate targetDate) { //given //when @@ -105,22 +112,37 @@ void findVaccinationStatistics(LocalDate targetDate) { .isNotEmpty(); assertThat(vaccinationStatistics).extracting(VaccinationStatisticResponse::getTotalFirstRate) .isNotEmpty(); + assertThat(vaccinationStatistics).extracting(VaccinationStatisticResponse::getTotalSecondRate) + .isNotEmpty(); } @DisplayName("세계 백신 정좁률 데이터 - 저장 - 성공 ") - @Test - void saveWorldVaccinationStatistics() { + @CustomParameterizedTest + @MethodSource("worldVaccinationTargetDate") + void saveWorldVaccinationStatistics(LocalDate targetDate) { //given - LocalDate targetDate = LocalDate.now(); //when - 세계_백신_접종률_저장되어_있음(targetDate); - List vaccinationStatistics = - vaccinationStatisticRepository.findByRegionPopulation(RegionPopulation.WORLD); + List vaccinationStatisticResponses = 세계_백신_접종률_저장되어_있음(targetDate); //then - assertThat(vaccinationStatistics).extracting(VaccinationStatistic::getBaseDate) + assertThat(vaccinationStatisticResponses).extracting(VaccinationStatisticResponse::getBaseDate) .contains(targetDate); - assertThat(vaccinationStatistics).extracting(VaccinationStatistic::getRegionPopulation) - .contains(RegionPopulation.WORLD); + assertThat(vaccinationStatisticResponses).extracting(VaccinationStatisticResponse::getSido) + .contains(RegionPopulation.WORLD.getRegion()); + } + + @DisplayName("세계 백신 접종률 데이터 - 조회 - 성공") + @CustomParameterizedTest + @MethodSource("worldVaccinationTargetDate") + void findWorldVaccinationStatistics(LocalDate targetDate) { + //given + //when + 세계_백신_접종률_저장되어_있음(targetDate); + final List vaccinationStatisticResponses = publicDataService.findWorldVaccinationStatistics(targetDate); + //then + assertThat(vaccinationStatisticResponses).extracting(VaccinationStatisticResponse::getBaseDate) + .contains(targetDate); + assertThat(vaccinationStatisticResponses).extracting(VaccinationStatisticResponse::getSido) + .contains(RegionPopulation.WORLD.getRegion()); } private void 백신_접종률_저장되어_있음(LocalDate targetDate) { @@ -129,8 +151,8 @@ void saveWorldVaccinationStatistics() { publicDataService.saveVaccinationStatistics(targetDate); } - private void 세계_백신_접종률_저장되어_있음(LocalDate targetDate) { + private List 세계_백신_접종률_저장되어_있음(LocalDate targetDate) { willReturn(toWorldVaccinationParserResponse(targetDate)).given(vaccinationParser).parseToWorldPublicData(); - publicDataService.saveWorldVaccinationStatistics(targetDate); + return publicDataService.saveWorldVaccinationStatistics(targetDate); } } diff --git a/frontend/cypress.json b/frontend/cypress.json index f2eb178e..f134c7d9 100644 --- a/frontend/cypress.json +++ b/frontend/cypress.json @@ -1,6 +1,5 @@ { "baseUrl": "http://localhost:9000", - "integrationFolder": "cypress/pages", "env": { "cypress-react-selector": { "root": "#root" diff --git a/frontend/cypress/fixtures/astrazenecaReviewList.json b/frontend/cypress/fixtures/astrazenecaReviewList.json new file mode 100644 index 00000000..ab41a3e4 --- /dev/null +++ b/frontend/cypress/fixtures/astrazenecaReviewList.json @@ -0,0 +1,46 @@ +[ + { + "content": "test1", + "createdAt": "2021-07-27T14:56:43.633", + "id": 1, + "vaccinationType": "ASTRAZENECA", + "viewCount": 0, + "likeCount": 3, + "commentCount": 4, + "writer": { + "accessToken": null, + "ageRange": { + "maxAge": 20, + "meaning": "10대", + "minAge": 10 + }, + "id": 1, + "nickname": "검프", + "socialId": null, + "socialProfileUrl": null, + "socialProvider": null + } + }, + { + "content": "test7", + "createdAt": "2021-07-27T14:56:43.633", + "id": 7, + "vaccinationType": "ASTRAZENECA", + "viewCount": 0, + "likeCount": 35, + "commentCount": 40, + "writer": { + "accessToken": null, + "ageRange": { + "maxAge": 20, + "meaning": "10대", + "minAge": 10 + }, + "id": 1, + "nickname": "검프", + "socialId": null, + "socialProfileUrl": null, + "socialProvider": null + } + } +] diff --git a/frontend/cypress/fixtures/commentList.json b/frontend/cypress/fixtures/commentList.json new file mode 100644 index 00000000..fe51488c --- /dev/null +++ b/frontend/cypress/fixtures/commentList.json @@ -0,0 +1 @@ +[] diff --git a/frontend/cypress/fixtures/editReview.json b/frontend/cypress/fixtures/editReview.json deleted file mode 100644 index ede9821a..00000000 --- a/frontend/cypress/fixtures/editReview.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "content": "다음날 되니 좀 아픈것 같아요 ㅠ ㅠ", - "createdAt": "2021-07-27T14:56:43.633", - "id": 8, - "vaccinationType": "MODERNA", - "viewCount": 0, - "likeCount": 310, - "commentCount": 20, - "writer": { - "accessToken": null, - "ageRange": { - "maxAge": 20, - "meaning": "10대", - "minAge": 10 - }, - "id": 1, - "nickname": "검프", - "shotVerified": true, - "socialId": null, - "socialProfileUrl": null, - "socialProvider": null - } -} diff --git a/frontend/cypress/fixtures/editedReview.json b/frontend/cypress/fixtures/editedReview.json new file mode 100644 index 00000000..d39916d0 --- /dev/null +++ b/frontend/cypress/fixtures/editedReview.json @@ -0,0 +1,22 @@ +{ + "content": "다음날 되니 좀 아픈것 같아요 ㅠ ㅠ", + "createdAt": "2021-07-28T14:56:43.633", + "id": 8, + "vaccinationType": "MODERNA", + "viewCount": 0, + "likeCount": 310, + "commentCount": 20, + "writer": { + "accessToken": "accessToken", + "ageRange": { + "maxAge": 30, + "meaning": "20대", + "minAge": 20 + }, + "id": 8, + "nickname": "nickname", + "socialId": "socialId", + "socialProfileUrl": "http://k.kakaocdn.net/dn/xGvcl/btranGk6QWP/uvRGXQeokXgIhPRD0wTPgk/img_640x640.jpg", + "socialProvider": "KAKAO" + } +} diff --git a/frontend/cypress/fixtures/janssenReviewList.json b/frontend/cypress/fixtures/janssenReviewList.json new file mode 100644 index 00000000..fe48ded9 --- /dev/null +++ b/frontend/cypress/fixtures/janssenReviewList.json @@ -0,0 +1,46 @@ +[ + { + "content": "test5", + "createdAt": "2021-07-27T14:56:43.633", + "id": 5, + "vaccinationType": "JANSSEN", + "viewCount": 0, + "likeCount": 36, + "commentCount": 24, + "writer": { + "accessToken": null, + "ageRange": { + "maxAge": 20, + "meaning": "10대", + "minAge": 10 + }, + "id": 1, + "nickname": "검프", + "socialId": null, + "socialProfileUrl": null, + "socialProvider": null + } + }, + { + "content": "test6", + "createdAt": "2021-07-27T14:56:43.633", + "id": 6, + "vaccinationType": "JANSSEN", + "viewCount": 0, + "likeCount": 13, + "commentCount": 43, + "writer": { + "accessToken": null, + "ageRange": { + "maxAge": 20, + "meaning": "10대", + "minAge": 10 + }, + "id": 1, + "nickname": "검프", + "socialId": null, + "socialProfileUrl": null, + "socialProvider": null + } + } +] diff --git a/frontend/cypress/fixtures/modernaReviewList.json b/frontend/cypress/fixtures/modernaReviewList.json new file mode 100644 index 00000000..d834248f --- /dev/null +++ b/frontend/cypress/fixtures/modernaReviewList.json @@ -0,0 +1,46 @@ +[ + { + "content": "모더나를 맞았어요. 별로 안 아프더라구요.", + "createdAt": "2021-07-27T14:56:43.633", + "id": 8, + "vaccinationType": "MODERNA", + "viewCount": 0, + "likeCount": 310, + "commentCount": 20, + "writer": { + "accessToken": "accessToken", + "ageRange": { + "maxAge": 30, + "meaning": "20대", + "minAge": 20 + }, + "id": 8, + "nickname": "nickname", + "socialId": "socialId", + "socialProfileUrl": "http://k.kakaocdn.net/dn/xGvcl/btranGk6QWP/uvRGXQeokXgIhPRD0wTPgk/img_640x640.jpg", + "socialProvider": "KAKAO" + } + }, + { + "content": "test2", + "createdAt": "2021-07-27T14:56:43.633", + "id": 2, + "vaccinationType": "MODERNA", + "viewCount": 0, + "likeCount": 3, + "commentCount": 4, + "writer": { + "accessToken": null, + "ageRange": { + "maxAge": 20, + "meaning": "10대", + "minAge": 10 + }, + "id": 1, + "nickname": "검프", + "socialId": null, + "socialProfileUrl": null, + "socialProvider": null + } + } +] diff --git a/frontend/cypress/fixtures/newReview.json b/frontend/cypress/fixtures/newReview.json index fcbbf84b..a823b607 100644 --- a/frontend/cypress/fixtures/newReview.json +++ b/frontend/cypress/fixtures/newReview.json @@ -1,5 +1,5 @@ { - "content": "test8", + "content": "모더나를 맞았어요. 별로 안 아프더라구요.", "createdAt": "2021-07-27T14:56:43.633", "id": 8, "vaccinationType": "MODERNA", @@ -7,17 +7,16 @@ "likeCount": 310, "commentCount": 20, "writer": { - "accessToken": null, + "accessToken": "accessToken", "ageRange": { - "maxAge": 20, - "meaning": "10대", - "minAge": 10 + "maxAge": 30, + "meaning": "20대", + "minAge": 20 }, - "id": 1, - "nickname": "검프", - "shotVerified": true, - "socialId": null, - "socialProfileUrl": null, - "socialProvider": null + "id": 8, + "nickname": "nickname", + "socialId": "socialId", + "socialProfileUrl": "http://k.kakaocdn.net/dn/xGvcl/btranGk6QWP/uvRGXQeokXgIhPRD0wTPgk/img_640x640.jpg", + "socialProvider": "KAKAO" } } diff --git a/frontend/cypress/fixtures/pfizerReviewList.json b/frontend/cypress/fixtures/pfizerReviewList.json new file mode 100644 index 00000000..7cbaf5db --- /dev/null +++ b/frontend/cypress/fixtures/pfizerReviewList.json @@ -0,0 +1,46 @@ +[ + { + "content": "test3", + "createdAt": "2021-07-27T14:56:43.633", + "id": 3, + "vaccinationType": "PFIZER", + "viewCount": 0, + "likeCount": 8, + "commentCount": 17, + "writer": { + "accessToken": null, + "ageRange": { + "maxAge": 20, + "meaning": "10대", + "minAge": 10 + }, + "id": 1, + "nickname": "검프", + "socialId": null, + "socialProfileUrl": null, + "socialProvider": null + } + }, + { + "content": "test4", + "createdAt": "2021-07-27T14:56:43.633", + "id": 4, + "vaccinationType": "PFIZER", + "viewCount": 0, + "likeCount": 23, + "commentCount": 4, + "writer": { + "accessToken": null, + "ageRange": { + "maxAge": 20, + "meaning": "10대", + "minAge": 10 + }, + "id": 1, + "nickname": "검프", + "socialId": null, + "socialProfileUrl": null, + "socialProvider": null + } + } +] diff --git a/frontend/cypress/fixtures/publicVaccinations.json b/frontend/cypress/fixtures/publicVaccinations.json new file mode 100644 index 00000000..7a2dde66 --- /dev/null +++ b/frontend/cypress/fixtures/publicVaccinations.json @@ -0,0 +1,14 @@ +[ + { + "accumulatedFirstCnt": 40850783, + "accumulatedSecondCnt": 36431541, + "baseDate": "2021-10-27", + "firstCnt": 40305, + "secondCnt": 278236, + "sido": "전국", + "totalFirstCnt": 40891088, + "totalFirstRate": 99.9, + "totalSecondCnt": 36709777, + "totalSecondRate": 99.9 + } +] diff --git a/frontend/cypress/fixtures/publicVaccinationsWorld.json b/frontend/cypress/fixtures/publicVaccinationsWorld.json new file mode 100644 index 00000000..238b470c --- /dev/null +++ b/frontend/cypress/fixtures/publicVaccinationsWorld.json @@ -0,0 +1,14 @@ +[ + { + "accumulatedFirstCnt": 0, + "accumulatedSecondCnt": 0, + "baseDate": "2021-10-26", + "firstCnt": 0, + "secondCnt": 0, + "sido": "World", + "totalFirstCnt": 3847412475, + "totalFirstRate": 48.8, + "totalSecondCnt": 2974157922, + "totalSecondRate": 99.9 + } +] diff --git a/frontend/cypress/fixtures/reviewList.json b/frontend/cypress/fixtures/reviewList.json index 37aebaa8..ee6ee8d2 100644 --- a/frontend/cypress/fixtures/reviewList.json +++ b/frontend/cypress/fixtures/reviewList.json @@ -3,7 +3,7 @@ "content": "test1", "createdAt": "2021-07-27T14:56:43.633", "id": 1, - "vaccinationType": "MODERNA", + "vaccinationType": "ASTRAZENECA", "viewCount": 0, "likeCount": 3, "commentCount": 4, @@ -16,7 +16,6 @@ }, "id": 1, "nickname": "검프", - "shotVerified": true, "socialId": null, "socialProfileUrl": null, "socialProvider": null @@ -39,7 +38,6 @@ }, "id": 1, "nickname": "검프", - "shotVerified": true, "socialId": null, "socialProfileUrl": null, "socialProvider": null @@ -49,7 +47,7 @@ "content": "test3", "createdAt": "2021-07-27T14:56:43.633", "id": 3, - "vaccinationType": "MODERNA", + "vaccinationType": "PFIZER", "viewCount": 0, "likeCount": 8, "commentCount": 17, @@ -62,7 +60,6 @@ }, "id": 1, "nickname": "검프", - "shotVerified": true, "socialId": null, "socialProfileUrl": null, "socialProvider": null @@ -72,7 +69,7 @@ "content": "test4", "createdAt": "2021-07-27T14:56:43.633", "id": 4, - "vaccinationType": "MODERNA", + "vaccinationType": "PFIZER", "viewCount": 0, "likeCount": 23, "commentCount": 4, @@ -85,7 +82,6 @@ }, "id": 1, "nickname": "검프", - "shotVerified": true, "socialId": null, "socialProfileUrl": null, "socialProvider": null @@ -95,7 +91,7 @@ "content": "test5", "createdAt": "2021-07-27T14:56:43.633", "id": 5, - "vaccinationType": "MODERNA", + "vaccinationType": "JANSSEN", "viewCount": 0, "likeCount": 36, "commentCount": 24, @@ -108,7 +104,6 @@ }, "id": 1, "nickname": "검프", - "shotVerified": true, "socialId": null, "socialProfileUrl": null, "socialProvider": null @@ -118,7 +113,7 @@ "content": "test6", "createdAt": "2021-07-27T14:56:43.633", "id": 6, - "vaccinationType": "MODERNA", + "vaccinationType": "JANSSEN", "viewCount": 0, "likeCount": 13, "commentCount": 43, @@ -131,17 +126,16 @@ }, "id": 1, "nickname": "검프", - "shotVerified": true, "socialId": null, "socialProfileUrl": null, "socialProvider": null } }, { - "content": "test", + "content": "test7", "createdAt": "2021-07-27T14:56:43.633", "id": 7, - "vaccinationType": "MODERNA", + "vaccinationType": "ASTRAZENECA", "viewCount": 0, "likeCount": 35, "commentCount": 40, @@ -154,7 +148,6 @@ }, "id": 1, "nickname": "검프", - "shotVerified": true, "socialId": null, "socialProfileUrl": null, "socialProvider": null diff --git a/frontend/cypress/fixtures/theLatestPreview.json b/frontend/cypress/fixtures/theLatestPreview.json new file mode 100644 index 00000000..04005fcb --- /dev/null +++ b/frontend/cypress/fixtures/theLatestPreview.json @@ -0,0 +1,22 @@ +{ + "id": 10, + "writer": { + "id": 10, + "nickname": "nickname", + "ageRange": { "meaning": "20대", "minAge": 20, "maxAge": 30 }, + "accessToken": null, + "socialProvider": "KAKAO", + "socialId": "1817338555", + "socialProfileUrl": "http://k.kakaocdn.net/dn/Kd2tL/btqUMFAlQga/pfDHcqt4SOQzqudn5mflFk/img_640x640.jpg" + }, + "content": "theLatestPreviewList-10", + "viewCount": 47, + "likeCount": 0, + "commentCount": 0, + "hasLiked": false, + "vaccinationType": "MODERNA", + "createdAt": "2021-10-27T12:58:10", + "images": [ + "https://d2c5b1goqlbzjy.cloudfront.net/posts/images/post-image_2021-10-27_18-24-14_e6bdc8e6-dde8-45fb-a52f-3e45060b4541.jpeg" + ] +} diff --git a/frontend/cypress/fixtures/theLatestPreviewList.json b/frontend/cypress/fixtures/theLatestPreviewList.json new file mode 100644 index 00000000..f8a5d3d8 --- /dev/null +++ b/frontend/cypress/fixtures/theLatestPreviewList.json @@ -0,0 +1,90 @@ +[ + { + "id": 10, + "writer": { + "id": 10, + "nickname": "nickname", + "ageRange": { "meaning": "20대", "minAge": 20, "maxAge": 30 }, + "accessToken": null, + "socialProvider": "KAKAO", + "socialId": "1817338555", + "socialProfileUrl": "http://k.kakaocdn.net/dn/Kd2tL/btqUMFAlQga/pfDHcqt4SOQzqudn5mflFk/img_640x640.jpg" + }, + "content": "theLatestPreviewList-10", + "viewCount": 47, + "likeCount": 0, + "commentCount": 0, + "hasLiked": false, + "vaccinationType": "MODERNA", + "createdAt": "2021-10-27T12:58:10", + "images": [ + "https://d2c5b1goqlbzjy.cloudfront.net/posts/images/post-image_2021-10-27_18-24-14_e6bdc8e6-dde8-45fb-a52f-3e45060b4541.jpeg" + ] + }, + { + "id": 11, + "writer": { + "id": 10, + "nickname": "nickname", + "ageRange": { "meaning": "20대", "minAge": 20, "maxAge": 30 }, + "accessToken": null, + "socialProvider": "KAKAO", + "socialId": "1817338555", + "socialProfileUrl": "http://k.kakaocdn.net/dn/Kd2tL/btqUMFAlQga/pfDHcqt4SOQzqudn5mflFk/img_640x640.jpg" + }, + "content": "theLatestPreviewList-11", + "viewCount": 47, + "likeCount": 0, + "commentCount": 0, + "hasLiked": false, + "vaccinationType": "PFIZER", + "createdAt": "2021-10-27T12:58:10", + "images": [ + "https://d2c5b1goqlbzjy.cloudfront.net/posts/images/post-image_2021-10-27_18-24-14_e6bdc8e6-dde8-45fb-a52f-3e45060b4541.jpeg" + ] + }, + { + "id": 12, + "writer": { + "id": 10, + "nickname": "nickname", + "ageRange": { "meaning": "20대", "minAge": 20, "maxAge": 30 }, + "accessToken": null, + "socialProvider": "KAKAO", + "socialId": "1817338555", + "socialProfileUrl": "http://k.kakaocdn.net/dn/Kd2tL/btqUMFAlQga/pfDHcqt4SOQzqudn5mflFk/img_640x640.jpg" + }, + "content": "theLatestPreviewList-12", + "viewCount": 47, + "likeCount": 0, + "commentCount": 0, + "hasLiked": false, + "vaccinationType": "JANSSEN", + "createdAt": "2021-10-27T12:58:10", + "images": [ + "https://d2c5b1goqlbzjy.cloudfront.net/posts/images/post-image_2021-10-27_18-24-14_e6bdc8e6-dde8-45fb-a52f-3e45060b4541.jpeg" + ] + }, + { + "id": 13, + "writer": { + "id": 10, + "nickname": "nickname", + "ageRange": { "meaning": "20대", "minAge": 20, "maxAge": 30 }, + "accessToken": null, + "socialProvider": "KAKAO", + "socialId": "1817338555", + "socialProfileUrl": "http://k.kakaocdn.net/dn/Kd2tL/btqUMFAlQga/pfDHcqt4SOQzqudn5mflFk/img_640x640.jpg" + }, + "content": "theLatestPreviewList-13", + "viewCount": 47, + "likeCount": 0, + "commentCount": 0, + "hasLiked": false, + "vaccinationType": "ASTRAZENECA", + "createdAt": "2021-10-27T12:58:10", + "images": [ + "https://d2c5b1goqlbzjy.cloudfront.net/posts/images/post-image_2021-10-27_18-24-14_e6bdc8e6-dde8-45fb-a52f-3e45060b4541.jpeg" + ] + } +] diff --git a/frontend/cypress/fixtures/theMostFamousPreview.json b/frontend/cypress/fixtures/theMostFamousPreview.json new file mode 100644 index 00000000..45bc2b2e --- /dev/null +++ b/frontend/cypress/fixtures/theMostFamousPreview.json @@ -0,0 +1,22 @@ +{ + "id": 14, + "writer": { + "id": 10, + "nickname": "nickname", + "ageRange": { "meaning": "20대", "minAge": 20, "maxAge": 30 }, + "accessToken": null, + "socialProvider": "KAKAO", + "socialId": "1817338555", + "socialProfileUrl": "http://k.kakaocdn.net/dn/Kd2tL/btqUMFAlQga/pfDHcqt4SOQzqudn5mflFk/img_640x640.jpg" + }, + "content": "theMostFamousPreviewList-14", + "viewCount": 47, + "likeCount": 0, + "commentCount": 0, + "hasLiked": false, + "vaccinationType": "MODERNA", + "createdAt": "2021-10-27T12:58:10", + "images": [ + "https://d2c5b1goqlbzjy.cloudfront.net/posts/images/post-image_2021-10-27_18-24-14_e6bdc8e6-dde8-45fb-a52f-3e45060b4541.jpeg" + ] +} diff --git a/frontend/cypress/fixtures/theMostFamousPreviewList.json b/frontend/cypress/fixtures/theMostFamousPreviewList.json new file mode 100644 index 00000000..3d630fdc --- /dev/null +++ b/frontend/cypress/fixtures/theMostFamousPreviewList.json @@ -0,0 +1,90 @@ +[ + { + "id": 14, + "writer": { + "id": 10, + "nickname": "nickname", + "ageRange": { "meaning": "20대", "minAge": 20, "maxAge": 30 }, + "accessToken": null, + "socialProvider": "KAKAO", + "socialId": "1817338555", + "socialProfileUrl": "http://k.kakaocdn.net/dn/Kd2tL/btqUMFAlQga/pfDHcqt4SOQzqudn5mflFk/img_640x640.jpg" + }, + "content": "theMostFamousPreviewList-14", + "viewCount": 47, + "likeCount": 0, + "commentCount": 0, + "hasLiked": false, + "vaccinationType": "MODERNA", + "createdAt": "2021-10-27T12:58:10", + "images": [ + "https://d2c5b1goqlbzjy.cloudfront.net/posts/images/post-image_2021-10-27_18-24-14_e6bdc8e6-dde8-45fb-a52f-3e45060b4541.jpeg" + ] + }, + { + "id": 15, + "writer": { + "id": 10, + "nickname": "nickname", + "ageRange": { "meaning": "20대", "minAge": 20, "maxAge": 30 }, + "accessToken": null, + "socialProvider": "KAKAO", + "socialId": "1817338555", + "socialProfileUrl": "http://k.kakaocdn.net/dn/Kd2tL/btqUMFAlQga/pfDHcqt4SOQzqudn5mflFk/img_640x640.jpg" + }, + "content": "theMostFamousPreviewList-15", + "viewCount": 47, + "likeCount": 0, + "commentCount": 0, + "hasLiked": false, + "vaccinationType": "PFIZER", + "createdAt": "2021-10-27T12:58:10", + "images": [ + "https://d2c5b1goqlbzjy.cloudfront.net/posts/images/post-image_2021-10-27_18-24-14_e6bdc8e6-dde8-45fb-a52f-3e45060b4541.jpeg" + ] + }, + { + "id": 16, + "writer": { + "id": 10, + "nickname": "nickname", + "ageRange": { "meaning": "20대", "minAge": 20, "maxAge": 30 }, + "accessToken": null, + "socialProvider": "KAKAO", + "socialId": "1817338555", + "socialProfileUrl": "http://k.kakaocdn.net/dn/Kd2tL/btqUMFAlQga/pfDHcqt4SOQzqudn5mflFk/img_640x640.jpg" + }, + "content": "theMostFamousPreviewList-16", + "viewCount": 47, + "likeCount": 0, + "commentCount": 0, + "hasLiked": false, + "vaccinationType": "JANSSEN", + "createdAt": "2021-10-27T12:58:10", + "images": [ + "https://d2c5b1goqlbzjy.cloudfront.net/posts/images/post-image_2021-10-27_18-24-14_e6bdc8e6-dde8-45fb-a52f-3e45060b4541.jpeg" + ] + }, + { + "id": 17, + "writer": { + "id": 10, + "nickname": "nickname", + "ageRange": { "meaning": "20대", "minAge": 20, "maxAge": 30 }, + "accessToken": null, + "socialProvider": "KAKAO", + "socialId": "1817338555", + "socialProfileUrl": "http://k.kakaocdn.net/dn/Kd2tL/btqUMFAlQga/pfDHcqt4SOQzqudn5mflFk/img_640x640.jpg" + }, + "content": "theMostFamousPreviewList-17", + "viewCount": 47, + "likeCount": 0, + "commentCount": 0, + "hasLiked": false, + "vaccinationType": "ASTRAZENECA", + "createdAt": "2021-10-27T12:58:10", + "images": [ + "https://d2c5b1goqlbzjy.cloudfront.net/posts/images/post-image_2021-10-27_18-24-14_e6bdc8e6-dde8-45fb-a52f-3e45060b4541.jpeg" + ] + } +] diff --git a/frontend/cypress/fixtures/newReviewList.json b/frontend/cypress/fixtures/updatedReviewList.json similarity index 82% rename from frontend/cypress/fixtures/newReviewList.json rename to frontend/cypress/fixtures/updatedReviewList.json index 57c5e1f7..b1373426 100644 --- a/frontend/cypress/fixtures/newReviewList.json +++ b/frontend/cypress/fixtures/updatedReviewList.json @@ -1,9 +1,31 @@ [ + { + "content": "모더나를 맞았어요. 별로 안 아프더라구요.", + "createdAt": "2021-07-27T14:56:43.633", + "id": 8, + "vaccinationType": "MODERNA", + "viewCount": 0, + "likeCount": 310, + "commentCount": 20, + "writer": { + "accessToken": "accessToken", + "ageRange": { + "maxAge": 30, + "meaning": "20대", + "minAge": 20 + }, + "id": 8, + "nickname": "nickname", + "socialId": "socialId", + "socialProfileUrl": "http://k.kakaocdn.net/dn/xGvcl/btranGk6QWP/uvRGXQeokXgIhPRD0wTPgk/img_640x640.jpg", + "socialProvider": "KAKAO" + } + }, { "content": "test1", "createdAt": "2021-07-27T14:56:43.633", "id": 1, - "vaccinationType": "MODERNA", + "vaccinationType": "ASTRAZENECA", "viewCount": 0, "likeCount": 3, "commentCount": 4, @@ -16,7 +38,6 @@ }, "id": 1, "nickname": "검프", - "shotVerified": true, "socialId": null, "socialProfileUrl": null, "socialProvider": null @@ -39,7 +60,6 @@ }, "id": 1, "nickname": "검프", - "shotVerified": true, "socialId": null, "socialProfileUrl": null, "socialProvider": null @@ -49,7 +69,7 @@ "content": "test3", "createdAt": "2021-07-27T14:56:43.633", "id": 3, - "vaccinationType": "MODERNA", + "vaccinationType": "PFIZER", "viewCount": 0, "likeCount": 8, "commentCount": 17, @@ -62,7 +82,6 @@ }, "id": 1, "nickname": "검프", - "shotVerified": true, "socialId": null, "socialProfileUrl": null, "socialProvider": null @@ -72,7 +91,7 @@ "content": "test4", "createdAt": "2021-07-27T14:56:43.633", "id": 4, - "vaccinationType": "MODERNA", + "vaccinationType": "PFIZER", "viewCount": 0, "likeCount": 23, "commentCount": 4, @@ -85,7 +104,6 @@ }, "id": 1, "nickname": "검프", - "shotVerified": true, "socialId": null, "socialProfileUrl": null, "socialProvider": null @@ -95,7 +113,7 @@ "content": "test5", "createdAt": "2021-07-27T14:56:43.633", "id": 5, - "vaccinationType": "MODERNA", + "vaccinationType": "JANSSEN", "viewCount": 0, "likeCount": 36, "commentCount": 24, @@ -108,7 +126,6 @@ }, "id": 1, "nickname": "검프", - "shotVerified": true, "socialId": null, "socialProfileUrl": null, "socialProvider": null @@ -118,7 +135,7 @@ "content": "test6", "createdAt": "2021-07-27T14:56:43.633", "id": 6, - "vaccinationType": "MODERNA", + "vaccinationType": "JANSSEN", "viewCount": 0, "likeCount": 13, "commentCount": 43, @@ -131,17 +148,16 @@ }, "id": 1, "nickname": "검프", - "shotVerified": true, "socialId": null, "socialProfileUrl": null, "socialProvider": null } }, { - "content": "test", + "content": "test7", "createdAt": "2021-07-27T14:56:43.633", "id": 7, - "vaccinationType": "MODERNA", + "vaccinationType": "ASTRAZENECA", "viewCount": 0, "likeCount": 35, "commentCount": 40, @@ -154,30 +170,6 @@ }, "id": 1, "nickname": "검프", - "shotVerified": true, - "socialId": null, - "socialProfileUrl": null, - "socialProvider": null - } - }, - { - "content": "test8", - "createdAt": "2021-07-27T14:56:43.633", - "id": 8, - "vaccinationType": "MODERNA", - "viewCount": 0, - "likeCount": 310, - "commentCount": 20, - "writer": { - "accessToken": null, - "ageRange": { - "maxAge": 20, - "meaning": "10대", - "minAge": 10 - }, - "id": 1, - "nickname": "검프", - "shotVerified": true, "socialId": null, "socialProfileUrl": null, "socialProvider": null diff --git a/frontend/cypress/integration/afterLogin.test.js b/frontend/cypress/integration/afterLogin.test.js new file mode 100644 index 00000000..fa237a9a --- /dev/null +++ b/frontend/cypress/integration/afterLogin.test.js @@ -0,0 +1,112 @@ +import { CONFIRM_MESSAGE } from '../../src/constants'; + +const BASE_URL = 'https://dev.cvi-korea.r-e.kr/api/v1'; + +describe('After Login Test', () => { + const login = () => { + cy.window() + .its('store') + .invoke('dispatch', { + type: 'auth/myInfo/fulfilled', + payload: { + accessToken: 'accessToken', + user: { + id: 8, + nickname: 'nickname', + ageRange: { meaning: '20대', minAge: 20, maxAge: 30 }, + socialProvider: 'KAKAO', + socialId: 'socialId', + socialProfileUrl: + 'http://k.kakaocdn.net/dn/xGvcl/btranGk6QWP/uvRGXQeokXgIhPRD0wTPgk/img_640x640.jpg', + }, + }, + }); + }; + + const getReviewList = () => + cy + .intercept('GET', `${BASE_URL}/posts/paging?offset=0&size=10&sort=CREATED_AT_DESC`, { + fixture: 'reviewList', + }) + .as('getReviewList'); + + const getCommentList = () => + cy + .intercept('GET', `${BASE_URL}/posts/8/comments/paging?offset=0&size=10`, { + fixture: 'reviewList', + }) + .as('getCommentList'); + + before(() => { + getReviewList(); + + cy.visit('/review'); + cy.wait('@getReviewList'); + cy.waitForReact(); + }); + + it('로그인 후 접종 후기 화면으로 간다.', () => { + login(); + }); + + it('후기 작성 버튼을 클릭해서, 후기를 작성한다.', () => { + cy.intercept('POST', `${BASE_URL}/posts`, { + state: 'SUCCESS', + }).as('createReview'); + cy.intercept('GET', `${BASE_URL}/posts/paging?offset=0&size=10&sort=CREATED_AT_DESC`, { + fixture: 'updatedReviewList', + }).as('getUpdatedReviewList'); + + cy.react('Button').contains('후기 작성').click(); + + cy.get('textarea').eq(0).type('모더나를 맞았어요. 별로 안 아프더라구요.'); + cy.react('Button').contains('제출하기').click(); + cy.wait('@createReview'); + cy.wait('@getUpdatedReviewList'); + }); + + it('내가 쓴 후기에 들어가서 수정한다.', () => { + cy.intercept('PUT', `${BASE_URL}/posts/8`, { state: 'SUCCESS' }).as('editReview'); + cy.intercept('GET', `${BASE_URL}/posts/8`, { fixture: 'newReview' }).as('getNewReview'); + getCommentList(); + + cy.react('ReviewItem').eq(0).click(); + cy.url().should('include', '/review/8'); + cy.wait('@getNewReview'); + cy.wait('@getCommentList'); + + cy.contains('button', '수정').click(); + cy.wait('@getNewReview'); + cy.url().should('include', '/review/8/edit'); + + cy.get('textarea').type('다음날 되니 좀 아픈것 같아요 ㅠ ㅠ'); + cy.react('Button').contains('수정하기').click(); + cy.wait('@editReview'); + }); + + it('내가 쓴 후기를 삭제한다.', () => { + cy.intercept('DELETE', `${BASE_URL}/posts/8`, { state: 'SUCCESS' }).as('deleteReview'); + cy.intercept('GET', `${BASE_URL}/posts/8`, { fixture: 'editedReview' }).as('getUpdatedReview'); + getReviewList(); + getCommentList(); + + cy.visit('/review/8'); + cy.wait('@getUpdatedReview'); + cy.wait('@getCommentList'); + login(); + cy.waitForReact(); + + cy.contains('button', '삭제').eq(0).click(); + cy.on('window:confirm', (text) => { + expect(text).to.equal(CONFIRM_MESSAGE.DELETE_REVIEW); + }); + cy.on('window:confirm', () => true); + + cy.wait('@deleteReview'); + + cy.url().should('include', '/review'); + cy.wait('@getReviewList'); + + cy.react('ReviewItem').its('length').should('eq', 7); + }); +}); diff --git a/frontend/cypress/integration/beforeLogin.test.js b/frontend/cypress/integration/beforeLogin.test.js new file mode 100644 index 00000000..b1e63161 --- /dev/null +++ b/frontend/cypress/integration/beforeLogin.test.js @@ -0,0 +1,212 @@ +import { ALERT_MESSAGE } from '../../src/constants'; + +const BASE_URL = 'https://dev.cvi-korea.r-e.kr/api/v1'; + +describe('Before Login Test', () => { + const getPublicVaccinations = () => { + cy.intercept('GET', `${BASE_URL}/publicdata/vaccinations`, { + fixture: 'publicVaccinations', + }).as('getPublicVaccinations'); + }; + + const getPublicVaccinationsWorld = () => { + cy.intercept('GET', `${BASE_URL}/publicdata/vaccinations/world`, { + fixture: 'publicVaccinationsWorld', + }).as('getPublicVaccinationsWorld'); + }; + + const getTheLatestPreviewList = () => { + cy.intercept('GET', `${BASE_URL}/posts/paging?offset=0&size=10&sort=CREATED_AT_DESC`, { + fixture: 'theLatestPreviewList', + }).as('getTheLatestPreviewList'); + }; + + const getTheMostFamousPreviewList = () => { + cy.intercept('GET', `${BASE_URL}/posts/paging?offset=0&size=10&sort=LIKE_COUNT_DESC`, { + fixture: 'theMostFamousPreviewList', + }).as('getTheMostFamousPreviewList'); + }; + + const getCommentList = (id) => + cy + .intercept('GET', `${BASE_URL}/posts/${id}/comments/paging?offset=0&size=10`, { + fixture: 'commentList', + }) + .as('getCommentList'); + + before(() => { + getPublicVaccinations(); + getPublicVaccinationsWorld(); + getTheLatestPreviewList(); + getTheMostFamousPreviewList(); + + cy.visit(''); + cy.wait('@getPublicVaccinations'); + cy.wait('@getPublicVaccinationsWorld'); + cy.wait('@getTheLatestPreviewList'); + cy.wait('@getTheMostFamousPreviewList'); + cy.waitForReact(); + }); + + it('홈페이지에 접속하여 접종 현황을 본다.', () => { + cy.react('VaccinationState', { props: { title: '접종 현황' } }).should('exist'); + }); + + it('홈페이지에 접속하여 최신 글을 본다.', () => { + cy.react('Preview', { props: { title: '최신 글' } }).should('exist'); + }); + + it('홈페이지에 접속하여 실시간 인기 글을 본다.', () => { + cy.react('Preview', { props: { title: '실시간 인기 글' } }).should('exist'); + }); + + it('홈페이지에 접속하여 접종 예약 하러가기 버튼을 본다', () => { + cy.contains('a', '접종 예약 하러가기').should('exist'); + }); + + it('홈페이지에 접속하여 접종 후기 쓰러가기 버튼을 본다', () => { + cy.react('Button').contains('접종 후기 쓰러가기').should('exist'); + }); + + it('홈페이지에 접속하여 잔여 백신 보러가기 버튼을 본다', () => { + cy.contains('a', '잔여 백신 보러가기').should('exist'); + }); + + it('홈페이지에 있는 최신 글의 첫 번째 후기를 클릭하면, 최신 글 첫 번째 후기의 상세 페이지가 보인다.', () => { + const reviewId = 10; + + getPublicVaccinations(); + getPublicVaccinationsWorld(); + getTheLatestPreviewList(); + getTheMostFamousPreviewList(); + cy.intercept('GET', `${BASE_URL}/posts/${reviewId}`, { fixture: 'theLatestPreview' }).as( + 'getTheLatestPreview', + ); + getCommentList(reviewId); + + cy.react('Preview', { props: { title: '최신 글' } }) + .find('ul li:first') + .click(); + + cy.wait('@getTheLatestPreview'); + cy.wait('@getCommentList'); + cy.url().should('include', `review/${reviewId}`); + + cy.contains('a', '홈').click(); + + cy.wait('@getTheLatestPreviewList'); + cy.wait('@getTheMostFamousPreviewList'); + }); + + it('홈페이지에 있는 실시간 인기 글의 첫 번째 후기를 클릭하면, 실시간 인기 글 첫 번째 후기의 상세 페이지가 보인다.', () => { + const reviewId = 14; + + cy.intercept('GET', `${BASE_URL}/posts/${reviewId}`, { fixture: 'theMostFamousPreview' }).as( + 'getTheMostFamousPreview', + ); + getCommentList(reviewId); + + cy.react('Preview', { props: { title: '실시간 인기 글' } }) + .find('ul li:first') + .click(); + + cy.url().should('include', `review/${reviewId}`); + cy.wait('@getTheMostFamousPreview'); + cy.wait('@getCommentList'); + }); + + it('목록 보기 버튼을 클릭하면, 접종 후기 페이지가 보인다.', () => { + cy.intercept('GET', `${BASE_URL}/posts/paging?offset=0&size=10&sort=CREATED_AT_DESC`, { + fixture: 'updatedReviewList', + }).as('getReviewList'); + + cy.contains('div', '목록 보기').click(); + + cy.wait('@getReviewList'); + cy.location('pathname').should('equal', '/review'); + }); + + it('모더나 탭을 클릭하면, 모더나 접종 후기만 보인다.', () => { + cy.intercept( + 'GET', + `${BASE_URL}/posts/paging?vaccinationType=MODERNA&offset=0&size=10&sort=CREATED_AT_DESC`, + { fixture: 'modernaReviewList' }, + ).as('getModernaReviewList'); + + cy.react('Button').contains('모더나').click(); + + cy.wait('@getModernaReviewList'); + cy.react('Label').contains('화이자').should('not.exist'); + cy.react('Label').contains('얀센').should('not.exist'); + cy.react('Label').contains('아스트라제네카').should('not.exist'); + }); + + it('화이자 탭을 클릭하면, 화이자 접종 후기만 보인다.', () => { + cy.intercept( + 'GET', + `${BASE_URL}/posts/paging?vaccinationType=PFIZER&offset=0&size=10&sort=CREATED_AT_DESC`, + { fixture: 'pfizerReviewList' }, + ).as('getPfizerReviewList'); + + cy.react('Button').contains('화이자').click(); + + cy.wait('@getPfizerReviewList'); + cy.react('Label').contains('모더나').should('not.exist'); + cy.react('Label').contains('얀센').should('not.exist'); + cy.react('Label').contains('아스트라제네카').should('not.exist'); + }); + + it('얀센 탭을 클릭하면, 얀센 접종 후기만 보인다.', () => { + cy.intercept( + 'GET', + `${BASE_URL}/posts/paging?vaccinationType=JANSSEN&offset=0&size=10&sort=CREATED_AT_DESC`, + { fixture: 'janssenReviewList' }, + ).as('getJanssenReviewList'); + + cy.react('Button').contains('얀센').click(); + + cy.wait('@getJanssenReviewList'); + cy.react('Label').contains('화이자').should('not.exist'); + cy.react('Label').contains('모더나').should('not.exist'); + cy.react('Label').contains('아스트라제네카').should('not.exist'); + }); + + it('아스트라제네카 탭을 클릭하면, 아스트라제네카 접종 후기만 보인다.', () => { + cy.intercept( + 'GET', + `${BASE_URL}/posts/paging?vaccinationType=ASTRAZENECA&offset=0&size=10&sort=CREATED_AT_DESC`, + { fixture: 'astrazenecaReviewList' }, + ).as('getAstrazenecaReviewList'); + + cy.react('Button').contains('아스트라제네카').click(); + + cy.wait('@getAstrazenecaReviewList'); + cy.react('Label').contains('화이자').should('not.exist'); + cy.react('Label').contains('모더나').should('not.exist'); + cy.react('Label').contains('얀센').should('not.exist'); + expect(); + }); + + it('후기 작성 버튼을 누르면 로그인을 안내하는 alert가 보이고, 취소 버튼을 클릭한다.', () => { + cy.react('Button').contains('후기 작성').click(); + + cy.on('window:confirm', (text) => { + expect(text).to.equal(ALERT_MESSAGE.NEED_LOGIN); + }); + cy.on('window:confirm', () => false); + }); + + it('접종 후기 페이지가 보인다', () => { + cy.location('pathname').should('equal', '/review'); + }); + + it('후기 작성 버튼을 누르고 확인을 누르면, 로그인 페이지가 보인다', () => { + cy.react('Button').contains('후기 작성').click(); + + cy.on('window:confirm', () => true); + }); + + it('로그인 페이지가 보인다.', () => { + cy.location('pathname').should('equal', '/login'); + }); +}); diff --git a/frontend/cypress/pages/afterLogin.test.js b/frontend/cypress/pages/afterLogin.test.js deleted file mode 100644 index c048373a..00000000 --- a/frontend/cypress/pages/afterLogin.test.js +++ /dev/null @@ -1,173 +0,0 @@ -import { PAGING_SIZE } from '../../src/constants'; - -const BASE_URL = 'https://dev.cvi-korea.kro.kr/api/v1'; - -describe('After Login Test', () => { - const getCreatedAtReviewList = () => { - cy.intercept( - 'GET', - `${BASE_URL}/paging?offset=0&size=${PAGING_SIZE}&sort=CREATED_AT_DESC`, - (req) => { - req.headers['Content-Type'] = 'application/json; charset=UTF-8'; - req.headers['Authorization'] = 'Bearer '; - req.reply({ - fixture: 'reviewList', - }); - }, - ).as('requestCreatedAtReviewData'); - }; - - before(() => { - // const asd = getCreatedAtReviewList(); - // console.log(asd); - // getCreatedAtReviewList(); - cy.visit(''); - // login(); - // cy.setLocalStorage('accessToken', JSON.stringify('accessToken')); - // cy.wait('@requestCreatedAtReviewData', { resquestTimeout: 10000 }); - }); - - const login = () => { - cy.window() - .its('store') - .invoke('dispatch', { - type: 'auth/myInfo/fulfilled', - payload: { - accessToken: 'accessToken', - user: { - id: 8, - nickname: 'nickname', - ageRange: { meaning: '20대', minAge: 20, maxAge: 30 }, - shotVerified: false, - socialProvider: 'KAKAO', - socialId: 'socialId', - socialProfileUrl: - 'http://k.kakaocdn.net/dn/xGvcl/btranGk6QWP/uvRGXQeokXgIhPRD0wTPgk/img_640x640.jpg', - }, - }, - }); - }; - - it.skip('로그인 후 홈화면으로 온다.', () => { - login(); - // cy.waitForReact(); - - // cy.visit(''); - // getCreatedAtReviewList(); - - // cy.wait('@requestCreatedAtReviewData'); - - // cy.window() - // .its('store') - // .invoke('getState') - // .should('deep.equal', { - // authReducer: { - // accessToken: 'accessToken', - // user: { - // id: 8, - // nickname: 'nickname', - // ageRange: { meaning: '20대', minAge: 20, maxAge: 30 }, - // shotVerified: false, - // socialProvider: 'KAKAO', - // socialId: 'socialId', - // socialProfileUrl: - // 'http://k.kakaocdn.net/dn/xGvcl/btranGk6QWP/uvRGXQeokXgIhPRD0wTPgk/img_640x640.jpg', - // }, - // }, - // }); - cy.setLocalStorage('accessToken', JSON.stringify('accessToken')); - }); - - it.skip('접종 후기 메뉴를 클릭하면, 접종 후기 페이지가 보인다.', () => { - login(); - cy.waitForReact(); - cy.contains('a', '접종후기').click(); - - cy.url().should('include', '/review'); - }); - - const createReview = () => { - cy.intercept('POST', `${BASE_URL}/posts`, { - state: 'SUCCESS', - }).as('requestCreateReview'); - }; - - const editReview = () => { - cy.intercept('POST', `${BASE_URL}/posts/7`, { state: 'SUCCESS' }).as('requestEditReview'); - }; - - const getNewReviewList = () => { - cy.intercept( - 'GET', - `${BASE_URL}/paging?offset=0&size=${PAGING_SIZE}&sort=CREATED_AT_DESC`, - (req) => { - req.headers['Content-Type'] = 'application/json; charset=UTF-8'; - req.headers['Authorization'] = 'Bearer '; - req.reply({ - fixture: 'newReviewList', - }); - }, - ).as('requestNewReviewData'); - }; - - const getNewReview = () => { - cy.intercept('GET', `${BASE_URL}/posts/7`, { fixture: 'newReview' }).as('requestGetNewReview'); - }; - - const getEditedReview = () => { - cy.intercept('GET', `${BASE_URL}/posts/7`, { fixture: 'editReview' }).as( - 'requestGetEditReview', - ); - }; - - it.skip('후기 작성 버튼을 클릭해서, 후기를 작성한다.', () => { - login(); - - getCreatedAtReviewList(); - - cy.waitForReact(); - - cy.contains('button', '후기 작성').click(); - - cy.on('window:confirm', () => false); - createReview(); - cy.get('textarea').eq(0).type('모더나를 맞았어요. 별로 안 아프더라구요.'); - cy.contains('button', '제출하기').click(); - - login(); - getNewReviewList(); - cy.visit('/review'); - cy.wait('@requestNewReviewData'); - }); - - it.skip('접종 후기에 페이지에서 내가 쓴 후기에 들어가서 수정한다.', () => { - cy.waitForReact(); - - getNewReview(); - editReview(); - - cy.react('ReviewItem').eq(0).click(); - cy.url().should('include', '/review/7'); - - cy.contains('button', '수정').click(); - cy.url().should('include', '/review/7/edit'); - - cy.get('textarea').type('다음날 되니 좀 아픈것 같아요 ㅠ ㅠ'); - cy.contains('button', '수정하기').click(); - - getEditedReview(); - cy.visit('/review/7'); - login(); - }); - - it.skip('내가 쓴 후기를 삭제한다.', () => { - cy.waitForReact(); - - cy.contains('button', '삭제').click(); - getCreatedAtReviewList(); - - cy.visit('/review'); - login(); - cy.wait('@requestReviewData'); - }); -}); diff --git a/frontend/cypress/pages/beforeLogin.test.js b/frontend/cypress/pages/beforeLogin.test.js deleted file mode 100644 index 54995d59..00000000 --- a/frontend/cypress/pages/beforeLogin.test.js +++ /dev/null @@ -1,108 +0,0 @@ -import { BASE_URL } from '../../src/constants'; - -describe('Before Login Test', () => { - const getReviewList = () => { - cy.intercept('GET', `${BASE_URL}/posts`, { fixture: 'reviewList' }).as('requestReviewData'); - }; - - before(() => { - getReviewList(); - - cy.visit(''); - // cy.wait('@requestReviewData'); - }); - - it.skip('홈페이지에 접속하여 접종 현황을 본다.', () => { - cy.waitForReact(); - // cy.react('VaccinationState', { props: { title: '접종 현황' }, exact: true }).contains( - // '접종 현황', - // ); - }); - - it.skip('홈페이지에 접속하여 접종 후기를 본다.', () => { - getReviewList(); - - cy.visit(''); - cy.wait('@requestReviewData'); - }); - - it.skip('홈페이지에 있는 첫 번째 접종 후기를 클릭하면, 첫 번째 접종 후기의 접종 상세 페이지가 보인다.', () => { - cy.get('ul li:first').click(); - - cy.location().should((loc) => { - expect(loc.pathname).contains('/review/'); - }); - }); - - it.skip('목록 보기 버튼을 클릭하면, 전체 접종 후기 페이지가 보인다.', () => { - cy.contains('div', '목록 보기').click(); - - cy.location().should((loc) => { - expect(loc.pathname).contains('/review'); - }); - }); - - it.skip('모더나 탭을 클릭하면, 모더나 접종 후기만 보인다.', () => { - cy.contains('button', '모더나').click(); - - cy.waitForReact(); - cy.react('Label').contains('화이자').should('have.length', '0'); - cy.react('Label').contains('얀센').should('have.length', '0'); - cy.react('Label').contains('아스트라제네카').should('have.length', '0'); - }); - - it.skip('화이자 탭을 클릭하면, 화이자 접종 후기만 보인다.', () => { - cy.contains('button', '화이자').click(); - - cy.waitForReact(); - cy.react('Label').contains('모더나').should('have.length', '0'); - cy.react('Label').contains('얀센').should('have.length', '0'); - cy.react('Label').contains('아스트라제네카').should('have.length', '0'); - }); - - it.skip('얀센 탭을 클릭하면, 얀센 접종 후기만 보인다.', () => { - cy.contains('button', '얀센').click(); - - cy.waitForReact(); - cy.react('Label').contains('화이자').should('have.length', '0'); - cy.react('Label').contains('모더나').should('have.length', '0'); - cy.react('Label').contains('아스트라제네카').should('have.length', '0'); - }); - - it.skip('아스트라제네카 탭을 클릭하면, 아스트라제네카 접종 후기만 보인다.', () => { - cy.contains('button', '아스트라제네카').click(); - - cy.waitForReact(); - cy.react('Label').contains('화이자').should('have.length', '0'); - cy.react('Label').contains('모더나').should('have.length', '0'); - cy.react('Label').contains('얀센').should('have.length', '0'); - expect(); - }); - - it.skip('후기 작성 버튼을 클릭하면, 로그인을 안내하는 alert가 보인다.', () => { - cy.contains('button', '후기 작성').click(); - - cy.on('window:confirm', (text) => { - expect(text).to.equal('로그인이 필요한 서비스입니다.'); - }); - cy.on('window:confirm', () => false); - }); - - it.skip('취소 버튼을 클릭한다.', () => { - cy.contains('button', '후기 작성').click(); - - cy.on('window:confirm', () => false); - }); - - it.skip('다시 후기 작성 버튼을 누르고, alert에서 확인 버튼을 클릭한다.', () => { - cy.contains('button', '후기 작성').click(); - - cy.on('window:confirm', () => true); - }); - - it.skip('로그인 페이지가 보인다.', () => { - cy.location().should((loc) => { - expect(loc.pathname).contains('/login'); - }); - }); -}); diff --git a/frontend/package.json b/frontend/package.json index 821a0d59..ac9f9597 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -31,13 +31,16 @@ "react-intersection-observer": "^8.32.0", "react-lottie": "^1.2.3", "react-redux": "^7.2.4", - "react-router-dom": "^5.2.0" + "react-router-dom": "^5.2.0", + "react-spring": "^9.3.0" }, "devDependencies": { "@babel/core": "^7.14.6", "@babel/plugin-transform-runtime": "^7.14.5", "@babel/preset-env": "^7.14.7", "@babel/preset-react": "^7.14.5", + "@cypress/react": "^5.10.1", + "@cypress/webpack-dev-server": "^1.7.0", "@storybook/addon-actions": "^6.3.3", "@storybook/addon-essentials": "^6.3.3", "@storybook/addon-links": "^6.3.3", @@ -46,9 +49,9 @@ "@webpack-cli/generators": "^2.2.0", "babel-loader": "^8.2.2", "babel-plugin-react-require": "^3.1.3", - "cypress": "^8.0.0", + "cypress": "^8.7.0", "cypress-localstorage-commands": "^1.5.0", - "cypress-react-selector": "^2.3.11", + "cypress-react-selector": "^2.3.12", "eslint": "^7.30.0", "eslint-config-prettier": "^8.3.0", "eslint-plugin-cypress": "^2.11.3", diff --git a/frontend/src/components/@common/DonutChart/DonutChart.js b/frontend/src/components/@common/DonutChart/DonutChart.js index ed74e9bd..bcb22370 100644 --- a/frontend/src/components/@common/DonutChart/DonutChart.js +++ b/frontend/src/components/@common/DonutChart/DonutChart.js @@ -1,7 +1,7 @@ -import { useEffect, useState } from 'react'; +import { animated, useSpring } from 'react-spring'; import PropTypes from 'prop-types'; import { THEME_COLOR } from '../../../constants'; -import { Container, Span, Percent } from './DonutChart.styles'; +import { AnimatedCircle } from './DonutChart.styles'; const DonutChart = ({ target, @@ -13,32 +13,51 @@ const DonutChart = ({ radius, thickness, }) => { - const [currentNumber, setCurrentNumber] = useState(0); + const { number } = useSpring({ + from: { number: 0 }, + number: target, + config: { duration: 3000 }, + }); - useEffect(() => { - if (!target) return; + const totalCircleLength = 2 * Math.PI * radius; + const circleOffset = (totalCircleLength / 4).toString(); - const intervalId = setInterval(() => { - if (currentNumber < target) setCurrentNumber((currentNumber) => currentNumber + 1); + const getStrokeDasharray = (target) => { + const targetPathLength = (totalCircleLength / 100) * target; - clearInterval(intervalId); - }, 10); - - return () => clearInterval(intervalId); - }, [currentNumber, target]); + return `${targetPathLength} ${totalCircleLength - targetPathLength}`; + }; return ( - - - {target} - % - - + <> + + + {target && ( + + )} + + {number.to((n) => n.toFixed(1))} + + + % + + + ); }; @@ -57,9 +76,9 @@ DonutChart.defaultProps = { filledColor: THEME_COLOR.PRIMARY, emptyColor: '#EFF5F5', fontColor: THEME_COLOR.PRIMARY, - fontSize: '2.4rem', + fontSize: '2.2rem', percentSize: '1.2rem', - radius: 50, + radius: 42, thickness: 16, }; diff --git a/frontend/src/components/@common/DonutChart/DonutChart.styles.js b/frontend/src/components/@common/DonutChart/DonutChart.styles.js index 62f013c3..368432bf 100644 --- a/frontend/src/components/@common/DonutChart/DonutChart.styles.js +++ b/frontend/src/components/@common/DonutChart/DonutChart.styles.js @@ -1,38 +1,15 @@ import styled from '@emotion/styled'; -import { THEME_COLOR } from '../../../constants'; -const Container = styled.div` - position: relative; - /* display: inline-block; */ - border-radius: 50%; - transition: 0.3s; +const AnimatedCircle = styled.circle` + -webkit-animation: circle-fill-animation 3s; + -moz-animation: circle-fill-animation 3s; + animation: circle-fill-animation 3s; - width: ${({ radius }) => radius * 2}px; - height: ${({ radius }) => radius * 2}px; - background: ${({ currentNumber, filledColor, emptyColor }) => - `conic-gradient(${filledColor} 0% ${currentNumber}%, ${emptyColor} ${currentNumber}% 100%)`}; + @keyframes circle-fill-animation { + 0% { + stroke-dasharray: 0, ${({ totalCircleLength }) => totalCircleLength && totalCircleLength}; + } + } `; -const Span = styled.span` - background-color: ${THEME_COLOR.WHITE}; - /* display: block; */ - position: absolute; - top: 50%; - left: 50%; - transform: translate(-50%, -50%); - border-radius: 50%; - text-align: center; - font-weight: 600; - - font-size: ${({ fontSize }) => fontSize && fontSize}; - color: ${({ fontColor }) => fontColor && fontColor}; - width: ${({ radius }) => radius * 2}px; - height: ${({ radius }) => radius * 2}px; - line-height: ${({ radius }) => radius * 2}px; -`; - -const Percent = styled.span` - font-size: ${({ percentSize }) => percentSize && percentSize}; -`; - -export { Container, Span, Percent }; +export { AnimatedCircle }; diff --git a/frontend/src/components/@common/MapChartSvg/MapChartSvg.js b/frontend/src/components/@common/MapChartSvg/MapChartSvg.js index c4e232b1..fc4130b1 100644 --- a/frontend/src/components/@common/MapChartSvg/MapChartSvg.js +++ b/frontend/src/components/@common/MapChartSvg/MapChartSvg.js @@ -18,12 +18,7 @@ const MapChartSvg = ({ dataList, hoveredRegion, setHoveredRegion }) => { return ( <> - + diff --git a/frontend/src/components/@common/Snackbar/Snackbar.styles.js b/frontend/src/components/@common/Snackbar/Snackbar.styles.js index a6b4da1b..5d1a2bf4 100644 --- a/frontend/src/components/@common/Snackbar/Snackbar.styles.js +++ b/frontend/src/components/@common/Snackbar/Snackbar.styles.js @@ -13,20 +13,19 @@ const Container = styled.div` color: ${FONT_COLOR.WHITE}; box-shadow: rgba(17, 17, 26, 0.05) 0px 4px 16px, rgba(17, 17, 26, 0.05) 0px 8px 32px; z-index: 100; - position: absolute; + position: fixed; bottom: 1.6rem; left: 50%; transform: translateX(-50%); + animation: fade 3s; + -webkit-animation: fade 3s; + animation-fill-mode: forwards; @keyframes fade { 0% { opacity: 0; bottom: 0; } - 25% { - opacity: 1; - bottom: 1.6rem; - } 50% { opacity: 1; bottom: 1.6rem; @@ -41,10 +40,6 @@ const Container = styled.div` opacity: 0; bottom: 0; } - 25% { - opacity: 1; - bottom: 1.6rem; - } 50% { opacity: 1; bottom: 1.6rem; @@ -54,9 +49,6 @@ const Container = styled.div` bottom: 0; } } - - animation: fade 3s; - -webkit-animation: fade 3s; `; export { Container }; diff --git a/frontend/yarn.lock b/frontend/yarn.lock index 876e7463..7e8438cd 100644 --- a/frontend/yarn.lock +++ b/frontend/yarn.lock @@ -1119,6 +1119,21 @@ exec-sh "^0.3.2" minimist "^1.2.0" +"@cypress/mount-utils@1.0.2": + version "1.0.2" + resolved "https://registry.yarnpkg.com/@cypress/mount-utils/-/mount-utils-1.0.2.tgz#afbc4f8c350b7cd86edc5ad0db0cbe1e0181edc8" + integrity sha512-Fn3fdTiyayHoy8Ol0RSu4MlBH2maQ2ZEXeEVKl/zHHXEQpld5HX3vdNLhK5YLij8cLynA4DxOT/nO9iEnIiOXw== + +"@cypress/react@^5.10.1": + version "5.10.1" + resolved "https://registry.yarnpkg.com/@cypress/react/-/react-5.10.1.tgz#3ce539d4f14660cd51caebc1b3c97e1b5dc5b8fb" + integrity sha512-/q9dJTAGRQv68PxK6ab0xTKICMA/ulLNB+1lrghavScOwhVdk4v/GAVRRAdBg7eFuFp3ZhPOJME9INudxBnjqg== + dependencies: + "@cypress/mount-utils" "1.0.2" + debug "4.3.2" + find-webpack "2.2.1" + find-yarn-workspace-root "2.0.0" + "@cypress/request@^2.88.6": version "2.88.6" resolved "https://registry.yarnpkg.com/@cypress/request/-/request-2.88.6.tgz#a970dd675befc6bdf8a8921576c01f51cc5798e9" @@ -1144,6 +1159,15 @@ tunnel-agent "^0.6.0" uuid "^8.3.2" +"@cypress/webpack-dev-server@^1.7.0": + version "1.7.0" + resolved "https://registry.yarnpkg.com/@cypress/webpack-dev-server/-/webpack-dev-server-1.7.0.tgz#00b2040f4e58aca815240ab310f7f5198cc98cbf" + integrity sha512-kolBDmgTaSTKgsJC4QsYw6GVy8Rg4d3c3Ck6MuAu3XQDjkIqGuRNtlxaJEIhhxZWa/ZyQWOqVMeeNASPRS2Kzw== + dependencies: + debug "4.3.2" + semver "^7.3.4" + webpack-merge "^5.4.0" + "@cypress/xvfb@^1.2.4": version "1.2.4" resolved "https://registry.yarnpkg.com/@cypress/xvfb/-/xvfb-1.2.4.tgz#2daf42e8275b39f4aa53c14214e557bd14e7748a" @@ -1567,6 +1591,91 @@ prop-types "^15.6.1" react-lifecycles-compat "^3.0.4" +"@react-spring/animated@~9.3.0": + version "9.3.0" + resolved "https://registry.yarnpkg.com/@react-spring/animated/-/animated-9.3.0.tgz#294f7696e450c4ae3abd2b59a6dd08bf70b53d3f" + integrity sha512-QvuyW77eDvLhdJyO6FFldlWlvnuKK2cpOx4+Zr962RyT/0IO1tbNDRO6G1vM8va6mbv6tmfYmRGKmKYePN3kVg== + dependencies: + "@react-spring/shared" "~9.3.0" + "@react-spring/types" "~9.3.0" + +"@react-spring/core@~9.3.0": + version "9.3.0" + resolved "https://registry.yarnpkg.com/@react-spring/core/-/core-9.3.0.tgz#2d0534c5b53c7e39b8e9ed3d996502828c90f4d4" + integrity sha512-SZQOIX7wkIagmucAi7zxqGGIb9A60o9n5922UrWo8Kl3FdG7FgrNwqr0kOI43/pMFeL70/PXwFhBatB03N5ctw== + dependencies: + "@react-spring/animated" "~9.3.0" + "@react-spring/shared" "~9.3.0" + "@react-spring/types" "~9.3.0" + +"@react-spring/konva@~9.3.0": + version "9.3.0" + resolved "https://registry.yarnpkg.com/@react-spring/konva/-/konva-9.3.0.tgz#97b23b2f235a9805d39279a0a1027c7d9646d6fb" + integrity sha512-lyUWxzEateE6Qxpc81oxJb5yiNDdj36Q9R9euJAgjl2dvUDaX85rVGqaB25+72yA1iQg5I4Kymj3UZVvPthRlA== + dependencies: + "@react-spring/animated" "~9.3.0" + "@react-spring/core" "~9.3.0" + "@react-spring/shared" "~9.3.0" + "@react-spring/types" "~9.3.0" + +"@react-spring/native@~9.3.0": + version "9.3.0" + resolved "https://registry.yarnpkg.com/@react-spring/native/-/native-9.3.0.tgz#6fee1ccaa8d70a19c239b27e95bcc050776f1725" + integrity sha512-lvKV5qxqnE5AMtTHv8xwAocGED4+VRxpljwBl1lbtileq3WnvOn7CpMLZNGc5TXjLWAE3zfoNJui69/jE/3uSw== + dependencies: + "@react-spring/animated" "~9.3.0" + "@react-spring/core" "~9.3.0" + "@react-spring/shared" "~9.3.0" + "@react-spring/types" "~9.3.0" + +"@react-spring/rafz@~9.3.0": + version "9.3.0" + resolved "https://registry.yarnpkg.com/@react-spring/rafz/-/rafz-9.3.0.tgz#e791c0ae854f7c1a512ae87f34fff36934d82d29" + integrity sha512-FD04d2TNb3xOZ6+04qwDmC3d0H4X6gvhsxU71/nSm4PPYRqFzZEolcVPmrHlbGzco3bvXKI+Kp2pIrpXLPUJFA== + +"@react-spring/shared@~9.3.0": + version "9.3.0" + resolved "https://registry.yarnpkg.com/@react-spring/shared/-/shared-9.3.0.tgz#7b4393094a97a1384f74fd8088e0b896e8f0c411" + integrity sha512-7ZFY2Blu/wxbLGcYvQavyLUVi9bK/is1bsn11qZ9AaZb4iucRyIf2jgjBfKZFCq4qgi7S/7QmDQG7sucUyLELg== + dependencies: + "@react-spring/rafz" "~9.3.0" + "@react-spring/types" "~9.3.0" + +"@react-spring/three@~9.3.0": + version "9.3.0" + resolved "https://registry.yarnpkg.com/@react-spring/three/-/three-9.3.0.tgz#e3fc49de1411eb1a7aa937fec8db33252f11d294" + integrity sha512-RKMXXdcNK0nbwLbmle/0KT/idGGpOxvI5lT1KtN8R3cgJWQBKYWVtzg+B/RgmQVNxO/QNlsKGWTjURockTRSVQ== + dependencies: + "@react-spring/animated" "~9.3.0" + "@react-spring/core" "~9.3.0" + "@react-spring/shared" "~9.3.0" + "@react-spring/types" "~9.3.0" + +"@react-spring/types@~9.3.0": + version "9.3.0" + resolved "https://registry.yarnpkg.com/@react-spring/types/-/types-9.3.0.tgz#54ec58ca40414984209c8baa75fddd394f9e2949" + integrity sha512-q4cDr2RSPblXMD3Rxvk6qcC7nmhhfV2izEBP06hb8ZCXznA6qJirG3RMpi29kBtEQiw1lWR59hAXKhauaPtbOA== + +"@react-spring/web@~9.3.0": + version "9.3.0" + resolved "https://registry.yarnpkg.com/@react-spring/web/-/web-9.3.0.tgz#48d1ebdd1d484065e0a943dbbb343af259496427" + integrity sha512-OTAGKRdyz6fLRR1tABFyw9KMpytyATIndQrj0O6RG47GfjiInpf4+WZKxo763vpS7z1OlnkI81WLUm/sqOqAnA== + dependencies: + "@react-spring/animated" "~9.3.0" + "@react-spring/core" "~9.3.0" + "@react-spring/shared" "~9.3.0" + "@react-spring/types" "~9.3.0" + +"@react-spring/zdog@~9.3.0": + version "9.3.0" + resolved "https://registry.yarnpkg.com/@react-spring/zdog/-/zdog-9.3.0.tgz#d84b69375017d864514ebcf59511731c5cc0280f" + integrity sha512-JOQwtg/MQ6sWwmKNY4w/R1TVXohIUkrbSgDfgUEK45ERTDwZGZzIo9QbqHv4dwEBK4Wa2Hfrcdf8cnEaNNzdAQ== + dependencies: + "@react-spring/animated" "~9.3.0" + "@react-spring/core" "~9.3.0" + "@react-spring/shared" "~9.3.0" + "@react-spring/types" "~9.3.0" + "@reduxjs/toolkit@^1.6.0": version "1.6.1" resolved "https://registry.yarnpkg.com/@reduxjs/toolkit/-/toolkit-1.6.1.tgz#7bc83b47352a663bf28db01e79d17ba54b98ade9" @@ -4154,7 +4263,7 @@ chardet@^0.7.0: resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.7.0.tgz#90094849f0937f2eedc2425d0d28a9e5f0cbad9e" integrity sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA== -check-more-types@^2.24.0: +check-more-types@2.24.0, check-more-types@^2.24.0: version "2.24.0" resolved "https://registry.yarnpkg.com/check-more-types/-/check-more-types-2.24.0.tgz#1420ffb10fd444dcfc79b43891bbfffd32a84600" integrity sha1-FCD/sQ/URNz8ebQ4kbv//TKoRgA= @@ -4851,17 +4960,17 @@ cypress-localstorage-commands@^1.5.0: resolved "https://registry.yarnpkg.com/cypress-localstorage-commands/-/cypress-localstorage-commands-1.5.0.tgz#53d67c1ce491dcbe39794151749b943227e65cd7" integrity sha512-gl1uKeviYdyJG4dLcZ9hfoUjLciwkkfbaQ3gvRtmipsPxC612ZBJhSjbunnJcUGwkryaM+82VrY9ij0tLSg7LA== -cypress-react-selector@^2.3.11: - version "2.3.11" - resolved "https://registry.yarnpkg.com/cypress-react-selector/-/cypress-react-selector-2.3.11.tgz#0b732c327f7b329ae67ea4efbe727436c9e0f2e3" - integrity sha512-oWdVkBiXKpf4oHCcSBs2FGf8egJu7l8Rfi5Y9sbSk7kfq4cQRnQVnvmjWER1FkJRd/4tcwAO/Ku+Qw9XJsyxIw== +cypress-react-selector@^2.3.12: + version "2.3.12" + resolved "https://registry.yarnpkg.com/cypress-react-selector/-/cypress-react-selector-2.3.12.tgz#8071b5350545cf3484c147a9fc7f9bcb4e68707c" + integrity sha512-sCiKIeSidtLM2sku/wKkQaijTVFnhnd58pU+6FUrUg8SWs71wDvyaEwFsYhrwvzFMiNnfMKRBPJdSACMIwjLCw== dependencies: resq "1.10.1" -cypress@^8.0.0: - version "8.5.0" - resolved "https://registry.yarnpkg.com/cypress/-/cypress-8.5.0.tgz#5712ca170913f8344bf167301205c4217c1eb9bd" - integrity sha512-MMkXIS+Ro2KETn4gAlG3tIc/7FiljuuCZP0zpd9QsRG6MZSyZW/l1J3D4iQM6WHsVxuX4rFChn5jPFlC2tNSvQ== +cypress@^8.7.0: + version "8.7.0" + resolved "https://registry.yarnpkg.com/cypress/-/cypress-8.7.0.tgz#2ee371f383d8f233d3425b6cc26ddeec2668b6da" + integrity sha512-b1bMC3VQydC6sXzBMFnSqcvwc9dTZMgcaOzT0vpSD+Gq1yFc+72JDWi55sfUK5eIeNLAtWOGy1NNb6UlhMvB+Q== dependencies: "@cypress/request" "^2.88.6" "@cypress/xvfb" "^1.2.4" @@ -4935,20 +5044,27 @@ debug@2.6.9, debug@^2.2.0, debug@^2.3.3, debug@^2.6.0: dependencies: ms "2.0.0" -debug@^3.0.0, debug@^3.1.0, debug@^3.1.1, debug@^3.2.6: - version "3.2.7" - resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.7.tgz#72580b7e9145fb39b6676f9c5e5fb100b934179a" - integrity sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ== +debug@4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.1.1.tgz#3b72260255109c6b589cee050f1d516139664791" + integrity sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw== dependencies: ms "^2.1.1" -debug@^4.0.1, debug@^4.1.0, debug@^4.1.1, debug@^4.3.2: +debug@4.3.2, debug@^4.0.1, debug@^4.1.0, debug@^4.1.1, debug@^4.3.2: version "4.3.2" resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.2.tgz#f0a49c18ac8779e31d4a0c6029dfb76873c7428b" integrity sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw== dependencies: ms "2.1.2" +debug@^3.0.0, debug@^3.1.0, debug@^3.1.1, debug@^3.2.6: + version "3.2.7" + resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.7.tgz#72580b7e9145fb39b6676f9c5e5fb100b934179a" + integrity sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ== + dependencies: + ms "^2.1.1" + decamelize@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" @@ -6198,6 +6314,30 @@ find-up@^5.0.0: locate-path "^6.0.0" path-exists "^4.0.0" +find-webpack@2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/find-webpack/-/find-webpack-2.2.1.tgz#96e7b701a2d37c3500cae30d4dc59e14923ba460" + integrity sha512-OdDtn2AzQvu3l9U1TS5ALc7uTVcLK/yv3fhjo+Pz7yuv4hG3ANKnbkKnPIPZ5ofd9mpYe6wRf5g5H4X9Lx48vQ== + dependencies: + debug "4.1.1" + find-yarn-workspace-root "1.2.1" + mocked-env "1.3.2" + +find-yarn-workspace-root@1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/find-yarn-workspace-root/-/find-yarn-workspace-root-1.2.1.tgz#40eb8e6e7c2502ddfaa2577c176f221422f860db" + integrity sha512-dVtfb0WuQG+8Ag2uWkbG79hOUzEsRrhBzgfn86g2sJPkzmcpGdghbNTfUKGTxymFrY/tLIodDzLoW9nOJ4FY8Q== + dependencies: + fs-extra "^4.0.3" + micromatch "^3.1.4" + +find-yarn-workspace-root@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/find-yarn-workspace-root/-/find-yarn-workspace-root-2.0.0.tgz#f47fb8d239c900eb78179aa81b66673eac88f7bd" + integrity sha512-1IMnbjt4KzsQfnhnzNd8wUEgXZ44IzZaZmnLYx7D5FZlaHt2gW20Cri8Q+E/t5tIj4+epTBub+2Zxu/vNILzqQ== + dependencies: + micromatch "^4.0.2" + first-chunk-stream@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/first-chunk-stream/-/first-chunk-stream-2.0.0.tgz#1bdecdb8e083c0664b91945581577a43a9f31d70" @@ -6340,6 +6480,15 @@ fs-extra@^0.30.0: path-is-absolute "^1.0.0" rimraf "^2.2.8" +fs-extra@^4.0.3: + version "4.0.3" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-4.0.3.tgz#0d852122e5bc5beb453fb028e9c0c9bf36340c94" + integrity sha512-q6rbdDd1o2mAnQreO7YADIxf/Whx4AHBiRf6d+/cVT8h44ss+lHgxf1FemcqDnQt9X3ct4McHr+JMGlYSsK7Cg== + dependencies: + graceful-fs "^4.1.2" + jsonfile "^4.0.0" + universalify "^0.1.0" + fs-extra@^9.0.0, fs-extra@^9.0.1, fs-extra@^9.1.0: version "9.1.0" resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-9.1.0.tgz#5954460c764a8da2094ba3554bf839e6b9a7c86d" @@ -8052,6 +8201,13 @@ jsonfile@^2.1.0: optionalDependencies: graceful-fs "^4.1.6" +jsonfile@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-4.0.0.tgz#8771aae0799b64076b76640fca058f9c10e33ecb" + integrity sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss= + optionalDependencies: + graceful-fs "^4.1.6" + jsonfile@^6.0.1: version "6.1.0" resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-6.1.0.tgz#bc55b2634793c679ec6403094eb13698a6ec0aae" @@ -8135,7 +8291,7 @@ klona@^2.0.4: resolved "https://registry.yarnpkg.com/klona/-/klona-2.0.4.tgz#7bb1e3affb0cb8624547ef7e8f6708ea2e39dfc0" integrity sha512-ZRbnvdg/NxqzC7L9Uyqzf4psi1OM4Cuc+sJAkQPjO6XkQIJTNbfK2Rsmbw8fx1p2mkZdp2FZYo2+LwXYY/uwIA== -lazy-ass@^1.6.0: +lazy-ass@1.6.0, lazy-ass@^1.6.0: version "1.6.0" resolved "https://registry.yarnpkg.com/lazy-ass/-/lazy-ass-1.6.0.tgz#7999655e8646c17f089fdd187d150d3324d54513" integrity sha1-eZllXoZGwX8In90YfRUNMyTVRRM= @@ -8751,6 +8907,16 @@ mkdirp@^1.0.0, mkdirp@^1.0.3, mkdirp@^1.0.4: resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e" integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw== +mocked-env@1.3.2: + version "1.3.2" + resolved "https://registry.yarnpkg.com/mocked-env/-/mocked-env-1.3.2.tgz#548eb2fde141d083de70dc6b231cd9f3210d8731" + integrity sha512-jwm3ziowCjpbLNhUNYwn2G0tawV/ZGRuWeEGt6PItrkQT74Nk3pDldL2pmwm9sQZw6a/x+ZBGeBVYq54acTauQ== + dependencies: + check-more-types "2.24.0" + debug "4.1.1" + lazy-ass "1.6.0" + ramda "0.26.1" + moment@^2.15.1, moment@^2.24.0: version "2.29.1" resolved "https://registry.yarnpkg.com/moment/-/moment-2.29.1.tgz#b2be769fa31940be9eeea6469c075e35006fa3d3" @@ -9953,6 +10119,11 @@ queue-microtask@^1.2.2: resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243" integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A== +ramda@0.26.1: + version "0.26.1" + resolved "https://registry.yarnpkg.com/ramda/-/ramda-0.26.1.tgz#8d41351eb8111c55353617fc3bbffad8e4d35d06" + integrity sha512-hLWjpy7EnsDBb0p+Z3B7rPi3GDeRG5ZtiI33kJhTt+ORCd38AbAIjB/9zRIUoeTbE/AVX5ZkU7m6bznsvrf8eQ== + ramda@^0.21.0: version "0.21.0" resolved "https://registry.yarnpkg.com/ramda/-/ramda-0.21.0.tgz#a001abedb3ff61077d4ff1d577d44de77e8d0a35" @@ -10226,6 +10397,18 @@ react-sizeme@^3.0.1: shallowequal "^1.1.0" throttle-debounce "^3.0.1" +react-spring@^9.3.0: + version "9.3.0" + resolved "https://registry.yarnpkg.com/react-spring/-/react-spring-9.3.0.tgz#4d71eecbfd4f0823bf67e5943d2b0fb77f3e26ad" + integrity sha512-zxhMUCM4ha22724q1CshmbzKUfqdUp2HyA4P72+A0xVF/9bgaFuMukI8C8/Rjfdqw6sGg3hZNvmY9Z8n4cqWmg== + dependencies: + "@react-spring/core" "~9.3.0" + "@react-spring/konva" "~9.3.0" + "@react-spring/native" "~9.3.0" + "@react-spring/three" "~9.3.0" + "@react-spring/web" "~9.3.0" + "@react-spring/zdog" "~9.3.0" + react-syntax-highlighter@^13.5.3: version "13.5.3" resolved "https://registry.yarnpkg.com/react-syntax-highlighter/-/react-syntax-highlighter-13.5.3.tgz#9712850f883a3e19eb858cf93fad7bb357eea9c6" @@ -12145,6 +12328,11 @@ unist-util-visit@2.0.3, unist-util-visit@^2.0.0: unist-util-is "^4.0.0" unist-util-visit-parents "^3.0.0" +universalify@^0.1.0: + version "0.1.2" + resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66" + integrity sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg== + universalify@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/universalify/-/universalify-2.0.0.tgz#75a4984efedc4b08975c5aeb73f530d02df25717" @@ -12574,7 +12762,7 @@ webpack-log@^2.0.0: ansi-colors "^3.0.0" uuid "^3.3.2" -webpack-merge@^5.7.3: +webpack-merge@^5.4.0, webpack-merge@^5.7.3: version "5.8.0" resolved "https://registry.yarnpkg.com/webpack-merge/-/webpack-merge-5.8.0.tgz#2b39dbf22af87776ad744c390223731d30a68f61" integrity sha512-/SaI7xY0831XwP6kzuwhKWVKDP9t1QY1h65lAFLbZqMPIuYcD9QAW4u9STIbU9kaJbPBB/geU/gLr1wDjOhQ+Q==