|
|
@@ -355,6 +355,44 @@ class ClasspathOutlookExamSprintReportRendererTest {
|
|
|
.doesNotContain("class='donut-unmastered-arc'");
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * 覆盖考纲圆环中心文案渲染时,应将百分比与“掌握率”包进围绕圆心(110,110)定位的标签组,而不是继续输出两个绝对 baseline 文本。
|
|
|
+ */
|
|
|
+ @Test
|
|
|
+ void renderSyllabusDonutAnchorsCenterCopyAsCircleCenteredLabelGroup() throws Exception {
|
|
|
+ ClasspathOutlookExamSprintReportRenderer renderer = new ClasspathOutlookExamSprintReportRenderer(OBJECT_MAPPER);
|
|
|
+
|
|
|
+ String html = renderer.render(unmodeledOutlookContent(callerVocabularyPayload()), Instant.parse("2026-01-03T08:00:00Z"));
|
|
|
+
|
|
|
+ String syllabusSvg = extractSvgByClass(html, "syllabus-donut-chart");
|
|
|
+
|
|
|
+ assertThat(syllabusSvg)
|
|
|
+ .contains("<g class='donut-center-label' transform='translate(110 110)'>")
|
|
|
+ .contains("<text class='chart-percent' x='0' y='-6' text-anchor='middle' fill='#2b4c8a' font-size='28' font-weight='700'>40.00%</text>")
|
|
|
+ .contains("<text class='chart-caption' x='0' y='19' text-anchor='middle' fill='#5f6b7a' font-size='14'>掌握率</text>")
|
|
|
+ .doesNotContain("class='chart-percent' x='110' y='106'")
|
|
|
+ .doesNotContain("class='chart-caption' x='110' y='131'");
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 覆盖学员案例命中率圆环中心文案渲染时,应将百分比与“命中率”包进围绕圆心(130,130)定位的标签组。
|
|
|
+ */
|
|
|
+ @Test
|
|
|
+ void renderCaseStudyRingAnchorsCenterCopyAsCircleCenteredLabelGroup() throws Exception {
|
|
|
+ ClasspathOutlookExamSprintReportRenderer renderer = new ClasspathOutlookExamSprintReportRenderer(OBJECT_MAPPER);
|
|
|
+
|
|
|
+ String html = renderer.render(unmodeledOutlookContent(callerVocabularyPayload()), Instant.parse("2026-01-03T08:00:00Z"));
|
|
|
+
|
|
|
+ String caseStudySvg = extractSvgByAriaLabel(html, "上届学员提分案例图示");
|
|
|
+
|
|
|
+ assertThat(caseStudySvg)
|
|
|
+ .contains("<g class='case-center-label' transform='translate(130 130)'>")
|
|
|
+ .contains("<text x='0' y='-6' text-anchor='middle' fill='#8a5d36' font-size='26' font-weight='700'>33.8%</text>")
|
|
|
+ .contains("<text x='0' y='20' text-anchor='middle' fill='#8a5d36' font-size='12'>命中率</text>")
|
|
|
+ .doesNotContain("<text x='130' y='124'")
|
|
|
+ .doesNotContain("<text x='130' y='152'");
|
|
|
+ }
|
|
|
+
|
|
|
private static final class TrackingObjectMapper extends ObjectMapper {
|
|
|
private boolean treeToValueCalled;
|
|
|
|
|
|
@@ -471,6 +509,15 @@ class ClasspathOutlookExamSprintReportRendererTest {
|
|
|
throw new AssertionError("svg should exist for class '" + cssClass + "' in HTML fragment:\n" + html);
|
|
|
}
|
|
|
|
|
|
+ private String extractSvgByAriaLabel(String html, String ariaLabel) {
|
|
|
+ Pattern svgPattern = Pattern.compile("<svg\\b(?=[^>]*aria-label='" + Pattern.quote(ariaLabel) + "')[\\s\\S]*?</svg>");
|
|
|
+ Matcher matcher = svgPattern.matcher(html);
|
|
|
+ if (matcher.find()) {
|
|
|
+ return matcher.group();
|
|
|
+ }
|
|
|
+ throw new AssertionError("svg should exist for aria-label '" + ariaLabel + "' in HTML fragment:\n" + html);
|
|
|
+ }
|
|
|
+
|
|
|
private List<String> gridLineElements(String svg) {
|
|
|
Pattern gridLinePattern = Pattern.compile("<line class='chart-grid-line chart-grid-line-y'[^>]*/>");
|
|
|
Matcher matcher = gridLinePattern.matcher(svg);
|