feat(favorites): 支持设备批量取消收藏

This commit is contained in:
Zhou Weidong committed 2026-10-27 10:33:59 +08:00
1 parent 5d44ac239b
commit 23321a0b0c
8 files changed
+147 -6

No files matched your search

@@ -47,6 +47,7 @@ import java.util.List;
import static org.mockito.BDDMockito.given;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyList;
import static org.mockito.Mockito.mock;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
@@ -90,6 +91,8 @@ class AppCommentCountAnonymousSecurityTest {
given(episodeStatsService.get(11L, null, "device-a")).willReturn(stats);
given(favoriteService.page(any(InteractionIdentity.class), any(Integer.class), any(Integer.class)))
.willReturn(new PageResult<>(0L, List.of()));
given(favoriteService.removeBatch(any(InteractionIdentity.class), anyList()))
.willReturn(1);
given(catalogService.toCards(List.of())).willReturn(List.of());
given(watchProgressService.recentPage(
any(InteractionIdentity.class), any(Integer.class), any(Integer.class)))
@@ -177,6 +180,18 @@ class AppCommentCountAnonymousSecurityTest {
.andExpect(jsonPath("$.code").value(0));
}
@Test
void should_allow_anonymous_favorite_batch_removal_through_security_chain()
throws Exception {
mockMvc.perform(post("/app/favorites/remove")
.header("X-Device-Id", "device-a")
.contentType("application/json")
.content("{\"dramaIds\":[\"7\"]}"))
.andExpect(status().isOk())
.andExpect(jsonPath("$.code").value(0))
.andExpect(jsonPath("$.data").value(1));
}
@Test
void should_keep_paid_and_entitlement_operations_login_required() throws Exception {
mockMvc.perform(post("/app/episodes/11/unlock"))
@@ -22,6 +22,7 @@ import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.test.web.servlet.MockMvc;
import java.time.LocalDateTime;
import java.util.Collections;
import java.util.List;
import static org.mockito.BDDMockito.given;
@@ -30,6 +31,7 @@ import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
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;
@@ -136,6 +138,43 @@ class AppLibraryPagingContractTest {
verify(progressService).recentPage(any(InteractionIdentity.class), eq(2), eq(20));
}
@Test
void should_remove_favorite_batch_for_signed_in_user() throws Exception {
given(favoriteService.removeBatch(any(InteractionIdentity.class), eq(List.of(7L, 8L))))
.willReturn(2);
favoriteMvc.perform(post("/app/favorites/remove")
.contentType("application/json")
.content("{\"dramaIds\":[\"7\",\"8\"]}"))
.andExpect(status().isOk())
.andExpect(jsonPath("$.code").value(0))
.andExpect(jsonPath("$.data").value(2));
verify(favoriteService).removeBatch(any(InteractionIdentity.class), eq(List.of(7L, 8L)));
}
@Test
void should_reject_empty_favorite_batch() throws Exception {
favoriteMvc.perform(post("/app/favorites/remove")
.contentType("application/json")
.content("{\"dramaIds\":[]}"))
.andExpect(status().isOk())
.andExpect(jsonPath("$.code").value(400))
.andExpect(jsonPath("$.message").value("dramaIds 不能为空"));
}
@Test
void should_reject_favorite_batch_over_limit() throws Exception {
String dramaIds = String.join(",", Collections.nCopies(201, "\"7\""));
favoriteMvc.perform(post("/app/favorites/remove")
.contentType("application/json")
.content("{\"dramaIds\":[" + dramaIds + "]}"))
.andExpect(status().isOk())
.andExpect(jsonPath("$.code").value(400))
.andExpect(jsonPath("$.message").value("dramaIds 最多 200 条"));
}
@Test
void should_keep_total_and_return_empty_list_when_watch_page_is_out_of_range()
throws Exception {