package com.trafficaudit.holiday.service;
|
|
import org.junit.jupiter.api.Test;
|
|
import java.io.ByteArrayInputStream;
|
import java.nio.file.Files;
|
import java.nio.file.Path;
|
import java.nio.file.Paths;
|
import java.util.ArrayList;
|
import java.util.Arrays;
|
import java.util.List;
|
import java.util.zip.ZipEntry;
|
import java.util.zip.ZipInputStream;
|
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
import static org.junit.jupiter.api.Assertions.assertTrue;
|
|
class HolidayTrendWordServiceTest {
|
|
@Test
|
void rebuildsTemplateWithSectionsChartsAndAppendix() throws Exception {
|
Path template = resolveTemplate();
|
byte[] templateBytes = Files.readAllBytes(template);
|
HolidayTrendWordService service = new HolidayTrendWordService();
|
|
List<HolidayTrendWordService.DocumentBlock> blocks = new ArrayList<>();
|
blocks.add(new HolidayTrendWordService.SectionBlock("一、总体情况"));
|
blocks.add(new HolidayTrendWordService.ChartBlock("客流总量", png(1),
|
new HolidayTrendWordService.ImageSize(5000000L, 3000000L)));
|
blocks.add(new HolidayTrendWordService.ChartBlock("客流占比", png(2), true,
|
new HolidayTrendWordService.ImageSize(4000000L, 2500000L)));
|
blocks.add(new HolidayTrendWordService.PageBreakBlock());
|
blocks.add(new HolidayTrendWordService.SectionBlock("附录一 每日客流构成变化"));
|
blocks.add(new HolidayTrendWordService.ChartBlock("每日构成", png(3), true));
|
|
byte[] result = service.generate(templateBytes, 2026, blocks);
|
List<String> entries = entries(result);
|
assertTrue(entries.contains("word/media/image1.png"));
|
assertTrue(entries.contains("word/media/image2.png"));
|
assertTrue(entries.contains("word/media/image3.png"));
|
assertEquals(3, entries.stream().filter(name -> name.endsWith(".png")).count());
|
|
String documentXml = readEntry(result, "word/document.xml");
|
assertTrue(documentXml.contains("一、总体情况"));
|
assertTrue(documentXml.contains("附录一 每日客流构成变化"));
|
assertTrue(documentXml.contains("客流总量"));
|
assertTrue(documentXml.contains("每日构成"));
|
assertTrue(!paragraphHasNumbering(documentXml, "一、总体情况"));
|
assertTrue(!paragraphHasNumbering(documentXml, "附录一 每日客流构成变化"));
|
assertTrue(documentXml.contains("cx=\"5000000\" cy=\"3000000\""));
|
assertTrue(documentXml.contains("cx=\"4000000\" cy=\"2500000\""));
|
assertEquals(2, pageBreakCount(documentXml));
|
|
String rels = readEntry(result, "word/_rels/document.xml.rels");
|
assertTrue(rels.contains("rId100"));
|
assertTrue(rels.contains("rId102"));
|
}
|
|
private Path resolveTemplate() {
|
Path direct = Paths.get("docs/专项统计/重要节假日/2026年十一假期全省综合运输客流量走势图.docx");
|
if (Files.exists(direct)) return direct;
|
return Paths.get("..", "docs", "专项统计", "重要节假日", "2026年十一假期全省综合运输客流量走势图.docx");
|
}
|
|
private boolean paragraphHasNumbering(String documentXml, String text) throws Exception {
|
javax.xml.parsers.DocumentBuilderFactory factory =
|
javax.xml.parsers.DocumentBuilderFactory.newInstance();
|
factory.setNamespaceAware(true);
|
org.w3c.dom.Document document = factory.newDocumentBuilder().parse(
|
new java.io.ByteArrayInputStream(documentXml.getBytes("UTF-8")));
|
org.w3c.dom.NodeList paragraphs = document.getElementsByTagNameNS(
|
"http://schemas.openxmlformats.org/wordprocessingml/2006/main", "p");
|
for (int i = 0; i < paragraphs.getLength(); i++) {
|
org.w3c.dom.Element paragraph = (org.w3c.dom.Element) paragraphs.item(i);
|
StringBuilder builder = new StringBuilder();
|
org.w3c.dom.NodeList texts = paragraph.getElementsByTagNameNS(
|
"http://schemas.openxmlformats.org/wordprocessingml/2006/main", "t");
|
for (int j = 0; j < texts.getLength(); j++) {
|
builder.append(texts.item(j).getTextContent());
|
}
|
if (text.equals(builder.toString())) {
|
return paragraph.getElementsByTagNameNS(
|
"http://schemas.openxmlformats.org/wordprocessingml/2006/main", "numPr")
|
.getLength() > 0;
|
}
|
}
|
throw new AssertionError("Paragraph not found: " + text);
|
}
|
|
private int pageBreakCount(String documentXml) throws Exception {
|
javax.xml.parsers.DocumentBuilderFactory factory =
|
javax.xml.parsers.DocumentBuilderFactory.newInstance();
|
factory.setNamespaceAware(true);
|
org.w3c.dom.Document document = factory.newDocumentBuilder().parse(
|
new java.io.ByteArrayInputStream(documentXml.getBytes("UTF-8")));
|
org.w3c.dom.NodeList breaks = document.getElementsByTagNameNS(
|
"http://schemas.openxmlformats.org/wordprocessingml/2006/main", "br");
|
int count = 0;
|
for (int i = 0; i < breaks.getLength(); i++) {
|
org.w3c.dom.Element br = (org.w3c.dom.Element) breaks.item(i);
|
if ("page".equals(br.getAttributeNS(
|
"http://schemas.openxmlformats.org/wordprocessingml/2006/main", "type"))) {
|
count++;
|
}
|
}
|
return count;
|
}
|
|
private byte[] png(int seed) {
|
byte[] bytes = new byte[256];
|
Arrays.fill(bytes, (byte) seed);
|
bytes[0] = (byte) 0x89;
|
bytes[1] = 0x50;
|
bytes[2] = 0x4e;
|
bytes[3] = 0x47;
|
return bytes;
|
}
|
|
private List<String> entries(byte[] zipBytes) throws Exception {
|
List<String> result = new ArrayList<>();
|
try (ZipInputStream input = new ZipInputStream(new ByteArrayInputStream(zipBytes))) {
|
ZipEntry entry;
|
while ((entry = input.getNextEntry()) != null) result.add(entry.getName());
|
}
|
return result;
|
}
|
|
private String readEntry(byte[] zipBytes, String name) throws Exception {
|
try (ZipInputStream input = new ZipInputStream(new ByteArrayInputStream(zipBytes))) {
|
ZipEntry entry;
|
while ((entry = input.getNextEntry()) != null) {
|
if (name.equals(entry.getName())) {
|
java.io.ByteArrayOutputStream out = new java.io.ByteArrayOutputStream();
|
byte[] buffer = new byte[1024];
|
int length;
|
while ((length = input.read(buffer)) > 0) out.write(buffer, 0, length);
|
return out.toString("UTF-8");
|
}
|
}
|
}
|
return "";
|
}
|
}
|