init local code
This commit is contained in:
@@ -0,0 +1,112 @@
|
||||
package com.yunhai.cms.theme;
|
||||
|
||||
import com.yunhai.cms.controller.api.ThemeController;
|
||||
import com.yunhai.cms.service.impl.ThemeService;
|
||||
import com.yunhai.cms.support.CmsIntegrationTestBase;
|
||||
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.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.header;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||
|
||||
/**
|
||||
* 主题管理接口契约(方案 §8.3 E 组 T18-T21,§5.2)。
|
||||
* 测试分层(§8.6):T18 全上下文 MockMvc(匿名 CAS 302 契约,现有唯一先例模式);
|
||||
* T19 服务级直调;T20/T21 standalone MockMvc(不走 CAS 过滤器链的控制器薄契约)。
|
||||
*/
|
||||
@DisplayName("ThemeApi - /api/theme 接口契约(方案 §5.2)")
|
||||
class ThemeApiIT extends CmsIntegrationTestBase {
|
||||
|
||||
@Autowired
|
||||
private MockMvc mockMvc;
|
||||
@Autowired
|
||||
private ThemeService themeService;
|
||||
@Autowired
|
||||
private ThemeRegistry themeRegistry;
|
||||
|
||||
private MockMvc standalone;
|
||||
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
purgeTables();
|
||||
standalone = MockMvcBuilders
|
||||
.standaloneSetup(new ThemeController(themeService, themeRegistry)).build();
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
void clean() {
|
||||
purgeTables();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("T18: /api/theme/list 匿名 302 至 SSO(CAS 契约,同 /api/site 先例)")
|
||||
void themeList_anonymousRedirectsToSso() throws Exception {
|
||||
mockMvc.perform(get("/api/theme/list"))
|
||||
.andExpect(status().is3xxRedirection())
|
||||
.andExpect(result -> assertThat(result.getResponse().getRedirectedUrl())
|
||||
.contains("sso."));
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("T19: 主题列表返回 schema(含 default:name/title/params/bannerSize/screenshotUrl)")
|
||||
void themeList_containsDefaultWithSchema() {
|
||||
List<com.yunhai.cms.model.vo.ThemeVo> list = themeService.list();
|
||||
assertThat(list).as("至少包含 default(Registry 已注册)")
|
||||
.extracting(vo -> vo.getName()).contains("default");
|
||||
|
||||
com.yunhai.cms.model.vo.ThemeVo def = list.stream()
|
||||
.filter(v -> "default".equals(v.getName()))
|
||||
.findFirst().orElseThrow(IllegalStateException::new);
|
||||
assertThat(def.getTitle()).isNotBlank();
|
||||
assertThat(def.getBannerSize()).isNotBlank();
|
||||
assertThat(def.getScreenshotUrl()).isEqualTo("/api/theme/default/asset/screenshot.png");
|
||||
assertThat(def.getParams()).isNotEmpty();
|
||||
com.yunhai.cms.model.vo.ThemeVo.ThemeParamVo primary = def.getParams().stream()
|
||||
.filter(p -> "primary".equals(p.getKey()))
|
||||
.findFirst().orElseThrow(IllegalStateException::new);
|
||||
assertThat(primary.getType()).isEqualTo("color");
|
||||
assertThat(primary.getCssVar()).isEqualTo("--primary");
|
||||
assertThat(primary.getDefaultValue()).isNotBlank();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("T20: 资产代理防穿越(..%2f 拒绝 400/404)")
|
||||
void assetTraversalRejected() throws Exception {
|
||||
standalone.perform(get("/api/theme/t-demo-red/asset/..%2F..%2Fapplication.yml"))
|
||||
.andExpect(result -> assertThat(result.getResponse().getStatus()).isIn(400, 404));
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("T21: 未注册主题资产 404(不落目录拼接)")
|
||||
void unregisteredThemeAsset404() throws Exception {
|
||||
standalone.perform(get("/api/theme/no-such-theme/asset/screenshot.png"))
|
||||
.andExpect(status().isNotFound());
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("T21 补充: 夹具主题 screenshot 经代理可取且带缓存头")
|
||||
void fixtureScreenshotServed() throws Exception {
|
||||
standalone.perform(get("/api/theme/t-demo-red/asset/screenshot.png"))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(header().string("Cache-Control", "max-age=3600, public"));
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("P2-T32: 三新包 screenshot 经资产代理可取(registry 校验存在 + 接口冒烟)")
|
||||
void newPackageScreenshotsServed() throws Exception {
|
||||
for (String name : new String[] {"classic-red", "blue-white", "warm-kinder"}) {
|
||||
standalone.perform(get("/api/theme/{name}/asset/screenshot.png", name))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(header().string("Cache-Control", "max-age=3600, public"));
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user