diff --git a/pom.xml b/pom.xml
index bfacb6a..2ca2b60 100644
--- a/pom.xml
+++ b/pom.xml
@@ -4,7 +4,7 @@
com.testrail
testrail-junit-extensions
jar
- 0.1.1
+ 0.1.2
testrail-junit-extensions
Improvements for JUnit that allow you to take better advantage of JUnit 5 (jupiter engine)
https://github.com/gurock/testrail-junit-extensions
diff --git a/src/main/java/com/testrail/junit/customjunitxml/XmlReportWriter.java b/src/main/java/com/testrail/junit/customjunitxml/XmlReportWriter.java
index 0b27f50..aac8781 100644
--- a/src/main/java/com/testrail/junit/customjunitxml/XmlReportWriter.java
+++ b/src/main/java/com/testrail/junit/customjunitxml/XmlReportWriter.java
@@ -126,6 +126,7 @@ private void writeXmlReport(TestIdentifier testIdentifier, Map entries = this.reportData.getReportEntries(testIdentifier);
Map testrunProperties = getTestRunProperties(entries);
for (Map.Entry property : testrunProperties.entrySet()) {
- addProperty(writer, property.getKey(), property.getValue());
+ addPropertyAndEscapeValue(writer, property.getKey(), property.getValue());
}
writer.writeEndElement(); // properties
@@ -316,6 +317,12 @@ private void addProperty(XMLStreamWriter writer, String name, String value) thro
newLine(writer);
}
+
+ private void addPropertyAndEscapeValue(XMLStreamWriter writer, String name, String value) throws XMLStreamException {
+ writer.writeCharacters(String.format("", name, escapeIllegalCharsForAttributes(value)));
+ newLine(writer);
+ }
+
private void addPropertyWithInnerContent(XMLStreamWriter writer, String name, String value)
throws XMLStreamException {
writer.writeStartElement("property");
@@ -502,6 +509,11 @@ private void writeAttributeSafely(XMLStreamWriter writer, String name, String va
writer.writeAttribute(name, escapeIllegalChars(value));
}
+
+ private void writeAttributeSafelyEncodingSomeChars(XMLStreamWriter writer, String name, String value) throws XMLStreamException {
+ writer.writeAttribute(name, escapeIllegalCharsForAttributes(value));
+ }
+
private void writeCDataSafely(XMLStreamWriter writer, String data) throws XMLStreamException {
for (String safeDataPart : CDATA_SPLIT_PATTERN.split(escapeIllegalChars(data))) {
writer.writeCData(safeDataPart);
@@ -533,6 +545,28 @@ private static boolean isAllowedXmlCharacter(int codePoint) {
|| (codePoint >= 0x10000 && codePoint <= 0x10FFFF);
}
+ static String escapeIllegalCharsForAttributes(String text) {
+ if (text.codePoints().allMatch(XmlReportWriter::isAllowedXmlCharacterForAttributes)) {
+ return text;
+ }
+ StringBuilder result = new StringBuilder(text.length() * 2);
+ text.codePoints().forEach(codePoint -> {
+ if (isAllowedXmlCharacterForAttributes(codePoint)) {
+ result.appendCodePoint(codePoint);
+ } else { // use a Character Reference (cf. https://www.w3.org/TR/xml/#NT-CharRef)
+ result.append("").append(codePoint).append(';');
+ }
+ });
+ return result.toString();
+ }
+
+ private static boolean isAllowedXmlCharacterForAttributes(int codePoint) {
+ // source: https://www.w3.org/TR/xml/#charsets with a workaround for enconding some characters, such as tab, newline, carriage return
+ return (codePoint >= 0x20 && codePoint <= 0xD7FF) //
+ || (codePoint >= 0xE000 && codePoint <= 0xFFFD) //
+ || (codePoint >= 0x10000 && codePoint <= 0x10FFFF);
+ }
+
private void newLine(XMLStreamWriter xmlWriter) throws XMLStreamException {
xmlWriter.writeCharacters("\n");
}
diff --git a/src/test/java/com/testrail/junit/customjunitxml/EnhancedLegacyXmlTest.java b/src/test/java/com/testrail/junit/customjunitxml/EnhancedLegacyXmlTest.java
index 84f23b0..a0cbdea 100644
--- a/src/test/java/com/testrail/junit/customjunitxml/EnhancedLegacyXmlTest.java
+++ b/src/test/java/com/testrail/junit/customjunitxml/EnhancedLegacyXmlTest.java
@@ -14,6 +14,7 @@
import static org.assertj.core.api.Assertions.assertThat;
import static org.joox.JOOX.$;
+import static org.joox.JOOX.attr;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.junit.jupiter.api.Assertions.fail;
import static org.junit.platform.engine.discovery.DiscoverySelectors.selectMethod;
@@ -378,6 +379,16 @@ public void shouldStoreTestRunPropertiesMultiple() throws Exception {
assertThat(testcase.child("properties").children("property").matchAttr("name", "my_property2").attr("value")).isEqualTo("world");
}
+ @Test
+ public void shouldStoreMultilineTestRunProperties() throws Exception {
+ String testMethodName = "testWithTestRunPropertyMultiline";
+ executeTestMethodWithParams(TEST_EXAMPLES_CLASS, testMethodName, "com.testrail.junit.customjunitxml.TestRailTestReporter");
+ Match testsuite = readValidXmlFile(tempDirectory.resolve(REPORT_NAME));
+ Match testcase = testsuite.child("testcase");
+ assertThat(testcase.attr("name", String.class)).isEqualTo(testMethodName);
+ assertThat(testcase.child("properties").children("property").matchAttr("name", "testrail_case_field").attr("value")).isEqualTo("custom_steps:1. First step\n2. Second step\n3. Third step");
+ }
+
private Match readValidXmlFile(Path xmlFile) throws Exception {
assertTrue(Files.exists(xmlFile), () -> "File does not exist: " + xmlFile);
try (BufferedReader reader = Files.newBufferedReader(xmlFile)) {
@@ -398,6 +409,15 @@ static void assertValidAccordingToJenkinsSchema(Document document) throws Except
}
}
+ private void dumpJunitXMLReport(Path reportPath) {
+ System.out.println("Junit XML report: " + reportPath);
+ try {
+ Files.lines(reportPath).forEach(System.out::println);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
private enum CachedSchema {
JENKINS("/enhanced-jenkins-junit.xsd");
diff --git a/src/test/java/com/testrail/junit/customjunitxml/ExamplesTestRailEnabledTestExamples.java b/src/test/java/com/testrail/junit/customjunitxml/ExamplesTestRailEnabledTestExamples.java
index f87e1f9..247bcd4 100644
--- a/src/test/java/com/testrail/junit/customjunitxml/ExamplesTestRailEnabledTestExamples.java
+++ b/src/test/java/com/testrail/junit/customjunitxml/ExamplesTestRailEnabledTestExamples.java
@@ -39,6 +39,12 @@ public void testWithMultipleTestRunProperties(TestRailTestReporter customReporte
customReporter.setProperty("my_property2", "world");
}
+ @Test
+ public void testWithTestRunPropertyMultiline(TestRailTestReporter customReporter) {
+ customReporter.setProperty("testrail_case_field", "custom_steps:1. First step\n2. Second step\n3. Third step");
+ }
+
+
@Test
@TestRail(id = "myCustomId")
public void annotatedTestWithCustomId() {