feat(theme): S5 学院蓝主题改造——home-blocks/service/guide页+区块CSS+ThemeRegistry增强
build / build-push (push) Successful in 53s
build / build-push (push) Successful in 53s
This commit is contained in:
@@ -208,6 +208,32 @@ class ThemeRegistryTest {
|
||||
.doesNotContainKey("heroImage");
|
||||
}
|
||||
|
||||
// ===== P-T1 参数迁包级(工作项 T):.meta 覆盖层承载 paramValues =====
|
||||
|
||||
@Test
|
||||
@DisplayName("T-T-01: .meta 覆盖层的 paramValues 被注册表读取并经 paramValuesOf 暴露")
|
||||
void metaOverlayParamValuesExposed() throws Exception {
|
||||
java.nio.file.Path dir = java.nio.file.Files.createTempDirectory("pt1-themes");
|
||||
writeExternalPackage(dir, "t-ext-params", null);
|
||||
java.nio.file.Files.createDirectories(dir.resolve(".meta"));
|
||||
java.nio.file.Files.write(dir.resolve(".meta").resolve("t-ext-params.json"),
|
||||
"{\"paramValues\":{\"primary\":\"#0a5c36\"}}".getBytes(java.nio.charset.StandardCharsets.UTF_8));
|
||||
|
||||
ThemeRegistry r = new ThemeRegistry();
|
||||
r.setThemeDir(dir.toString());
|
||||
r.load();
|
||||
|
||||
assertThat(r.get("t-ext-params").getParamValues())
|
||||
.as("覆盖层 paramValues 必须进入注册表(包级参数值的唯一来源)")
|
||||
.containsEntry("primary", "#0a5c36");
|
||||
assertThat(r.paramValuesOf("t-ext-params")).containsEntry("primary", "#0a5c36");
|
||||
assertThat(r.paramValuesOf("t-demo-red"))
|
||||
.as("无覆盖层的包返回空 Map(值回落 theme.json defaultValue)").isEmpty();
|
||||
assertThat(r.paramValuesOf("no-such-theme"))
|
||||
.as("未注册主题返回空 Map,调用方免判空").isEmpty();
|
||||
deleteRecursively(dir);
|
||||
}
|
||||
|
||||
// ===== W1 外部主题目录(方案 §5.3 T-W1-01..04)=====
|
||||
|
||||
/** 在临时目录构造一个合规外部包(基于 classpath 夹具 t-demo-red 文件拷贝改名) */
|
||||
@@ -308,6 +334,65 @@ class ThemeRegistryTest {
|
||||
deleteRecursively(dir);
|
||||
}
|
||||
|
||||
// ===== v2 工作项 B:首页区块门禁补强(手册 §2.5 坑⑤:引用一致而非 8 形态强制)=====
|
||||
|
||||
@Test
|
||||
@DisplayName("T-B-10 坑⑤回归:home.html 未引用本包 home-blocks 且无该文件的外部包必须照常注册")
|
||||
void packageWithoutOwnHomeBlocksIsNotEvicted() throws Exception {
|
||||
java.nio.file.Path dir = java.nio.file.Files.createTempDirectory("gate-themes");
|
||||
java.nio.file.Path pkg = writeExternalPackage(dir, "t-ext-nohb", null);
|
||||
assertThat(java.nio.file.Files.exists(pkg.resolve("home.html"))).isTrue();
|
||||
assertThat(java.nio.file.Files.exists(pkg.resolve("fragments").resolve("home-blocks.html")))
|
||||
.as("夹具包本就没有 home-blocks(B 档包同构)").isFalse();
|
||||
|
||||
ThemeRegistry r = new ThemeRegistry();
|
||||
r.setThemeDir(dir.toString());
|
||||
r.load();
|
||||
assertThat(r.contains("t-ext-nohb"))
|
||||
.as("缺 home-blocks 不得成为剔除理由,否则 7 套 B 档包静默回落 default").isTrue();
|
||||
deleteRecursively(dir);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("T-B-11 home.html 把未定义的形态分发给本包 home-blocks → 该包剔除,同目录健康包不受影响")
|
||||
void danglingHomeBlockReferenceEvictsOnlyThatPackage() throws Exception {
|
||||
java.nio.file.Path dir = java.nio.file.Files.createTempDirectory("gate-themes");
|
||||
java.nio.file.Path pkg = writeExternalPackage(dir, "t-ext-dangling", null);
|
||||
// compact 有定义、image_wall 无定义(模拟派生包补形态时漏写一个)
|
||||
java.nio.file.Files.write(pkg.resolve("fragments").resolve("home-blocks.html"),
|
||||
"<section th:fragment=\"compact(block)\">c</section>".getBytes(java.nio.charset.StandardCharsets.UTF_8));
|
||||
String home = new String(java.nio.file.Files.readAllBytes(pkg.resolve("home.html")),
|
||||
java.nio.charset.StandardCharsets.UTF_8);
|
||||
java.nio.file.Files.write(pkg.resolve("home.html"),
|
||||
(home + dispatchToOwnHomeBlocks("compact") + dispatchToOwnHomeBlocks("image_wall"))
|
||||
.getBytes(java.nio.charset.StandardCharsets.UTF_8));
|
||||
writeExternalPackage(dir, "t-ext-neighbour", null);
|
||||
|
||||
ThemeRegistry r = new ThemeRegistry();
|
||||
r.setThemeDir(dir.toString());
|
||||
r.load();
|
||||
assertThat(r.contains("t-ext-dangling"))
|
||||
.as("引用了本包不存在的 fragment → 首页必 500,必须剔除").isFalse();
|
||||
assertThat(r.contains("t-ext-neighbour"))
|
||||
.as("剔除范围仅限坏包,不得连带误杀").isTrue();
|
||||
deleteRecursively(dir);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("T-B-12 门禁补强后 13 套内置包零剔除(含只做 5 形态的 campus-glow)")
|
||||
void allBuiltinPackagesSurviveTheGate() {
|
||||
assertThat(registry.list()).extracting(ThemeInfo::getName).contains(
|
||||
"default", "classic-red", "blue-white", "warm-kinder", "fresh-mint", "mint-breeze",
|
||||
"scholar-blue", "campus-glow", "academic-navy", "campus-azure", "poly-blue",
|
||||
"agri-forest", "jade-normal");
|
||||
}
|
||||
|
||||
/** 与 poly-blue/home.html 同构的分发写法:~{${themeBase} + '/fragments/home-blocks' :: 形态(${block})} */
|
||||
private static String dispatchToOwnHomeBlocks(String form) {
|
||||
return "<th:block th:case=\"'" + form + "'\"><th:block th:replace=\"~{${themeBase} + "
|
||||
+ "'/fragments/home-blocks' :: " + form + "(${block})}\" /></th:block>";
|
||||
}
|
||||
|
||||
/** JDK8 递归删除(测试临时目录专用) */
|
||||
private static void deleteRecursively(java.nio.file.Path path) {
|
||||
if (!java.nio.file.Files.exists(path)) {
|
||||
|
||||
Reference in New Issue
Block a user