init local code
This commit is contained in:
@@ -0,0 +1,96 @@
|
||||
package com.yunhai.cms.portal;
|
||||
|
||||
import com.yunhai.cms.entity.CmsSite;
|
||||
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.MvcResult;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
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.status;
|
||||
|
||||
/**
|
||||
* 主题微调参数渲染注入(方案 §8.3 C 组 T13-T15,§5.3):
|
||||
* 站点 config_json.theme_params 经快照装配 → head 内联 :root 覆盖串(位于皮肤 CSS 之后)。
|
||||
*/
|
||||
@DisplayName("ThemeRender - 微调参数 CSS 注入(方案 §5.3)")
|
||||
class ThemeRenderIT extends CmsIntegrationTestBase {
|
||||
|
||||
@Autowired
|
||||
private MockMvc mockMvc;
|
||||
|
||||
@BeforeEach
|
||||
void seed() {
|
||||
purgeTables();
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
void clean() {
|
||||
purgeTables();
|
||||
}
|
||||
|
||||
private void persistSiteWithConfig(String code, String configJson) {
|
||||
CmsSite site = new CmsSite();
|
||||
site.setCode(code);
|
||||
site.setSchId(1);
|
||||
site.setSchName("学校-1");
|
||||
site.setName("注入测试门户");
|
||||
site.setTheme("default");
|
||||
site.setConfigJson(configJson);
|
||||
site.setStatus(1);
|
||||
siteRepository.saveAndFlush(site);
|
||||
}
|
||||
|
||||
private String homeHtml(String siteCode) throws Exception {
|
||||
MvcResult result = mockMvc.perform(get("/portal/{code}/", siteCode))
|
||||
.andExpect(status().isOk())
|
||||
.andReturn();
|
||||
return result.getResponse().getContentAsString(StandardCharsets.UTF_8);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("T13: 微调参数注入 CSS 变量且位于皮肤 CSS link 之后")
|
||||
void themeParamsInjectedAfterSkinCss() throws Exception {
|
||||
persistSiteWithConfig("inj1", "{\"theme_params\":{\"primary\":\"#b01a2e\"}}");
|
||||
|
||||
String html = homeHtml("inj1");
|
||||
assertThat(html).as("合法色值应注入").contains("--primary:#b01a2e");
|
||||
int cssLinkIndex = html.indexOf("css/main.css");
|
||||
int varIndex = html.indexOf("--primary:#b01a2e");
|
||||
assertThat(cssLinkIndex).as("皮肤 CSS link 应存在").isGreaterThan(-1);
|
||||
assertThat(varIndex).as("内联覆盖串必须在皮肤 CSS link 之后(层叠后写覆盖)")
|
||||
.isGreaterThan(cssLinkIndex);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("T14: 非法色值不注入(red;} / javascript:alert(1) 防注入)")
|
||||
void illegalColorValuesNotInjected() throws Exception {
|
||||
persistSiteWithConfig("inj2", "{\"theme_params\":{\"primary\":\"red;}}\"}}");
|
||||
|
||||
String html = homeHtml("inj2");
|
||||
assertThat(html).doesNotContain("red;}}").doesNotContain("red;}");
|
||||
assertThat(html).doesNotContain("--primary:red");
|
||||
|
||||
purgeTables();
|
||||
persistSiteWithConfig("inj3", "{\"theme_params\":{\"primary\":\"javascript:alert(1)\"}}");
|
||||
String html3 = homeHtml("inj3");
|
||||
assertThat(html3).doesNotContain("javascript:alert(1)");
|
||||
assertThat(html3).doesNotContain("--primary:javascript");
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("T15: 未声明 key 不注入(按主题 schema 过滤)")
|
||||
void undeclaredKeysNotInjected() throws Exception {
|
||||
persistSiteWithConfig("inj4", "{\"theme_params\":{\"zzhack\":\"zzvalue\"}}");
|
||||
|
||||
String html = homeHtml("inj4");
|
||||
assertThat(html).doesNotContain("zzhack").doesNotContain("zzvalue");
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user