diff --git a/packages/vitest/src/node/reporters/junit.ts b/packages/vitest/src/node/reporters/junit.ts
index 9643e341781a..681b4dfef12a 100644
--- a/packages/vitest/src/node/reporters/junit.ts
+++ b/packages/vitest/src/node/reporters/junit.ts
@@ -23,13 +23,39 @@ function flattenTasks(task: Task, baseName = ''): Task[] {
}
}
+// https://gist.github.com/john-doherty/b9195065884cdbfd2017a4756e6409cc
+function removeInvalidXMLCharacters(value: any, removeDiscouragedChars: boolean): string {
+ // eslint-disable-next-line no-control-regex
+ let regex = /((?:[\0-\x08\x0B\f\x0E-\x1F\uFFFD\uFFFE\uFFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF]))/g
+ value = String(value || '').replace(regex, '')
+
+ if (removeDiscouragedChars) {
+ // remove everything discouraged by XML 1.0 specifications
+ regex = new RegExp(
+ '([\\x7F-\\x84]|[\\x86-\\x9F]|[\\uFDD0-\\uFDEF]|(?:\\uD83F[\\uDFFE\\uDFFF])|(?:\\uD87F[\\uDF'
+ + 'FE\\uDFFF])|(?:\\uD8BF[\\uDFFE\\uDFFF])|(?:\\uD8FF[\\uDFFE\\uDFFF])|(?:\\uD93F[\\uDFFE\\uD'
+ + 'FFF])|(?:\\uD97F[\\uDFFE\\uDFFF])|(?:\\uD9BF[\\uDFFE\\uDFFF])|(?:\\uD9FF[\\uDFFE\\uDFFF])'
+ + '|(?:\\uDA3F[\\uDFFE\\uDFFF])|(?:\\uDA7F[\\uDFFE\\uDFFF])|(?:\\uDABF[\\uDFFE\\uDFFF])|(?:\\'
+ + 'uDAFF[\\uDFFE\\uDFFF])|(?:\\uDB3F[\\uDFFE\\uDFFF])|(?:\\uDB7F[\\uDFFE\\uDFFF])|(?:\\uDBBF'
+ + '[\\uDFFE\\uDFFF])|(?:\\uDBFF[\\uDFFE\\uDFFF])(?:[\\0-\\t\\x0B\\f\\x0E-\\u2027\\u202A-\\uD7FF\\'
+ + 'uE000-\\uFFFF]|[\\uD800-\\uDBFF][\\uDC00-\\uDFFF]|[\\uD800-\\uDBFF](?![\\uDC00-\\uDFFF])|'
+ + '(?:[^\\uD800-\\uDBFF]|^)[\\uDC00-\\uDFFF]))', 'g')
+
+ value = value.replace(regex, '')
+ }
+
+ return value
+}
+
function escapeXML(value: any): string {
- return String(value)
- .replace(/&/g, '&')
- .replace(/"/g, '"')
- .replace(/'/g, ''')
- .replace(//g, '>')
+ return removeInvalidXMLCharacters(
+ String(value)
+ .replace(/&/g, '&')
+ .replace(/"/g, '"')
+ .replace(/'/g, ''')
+ .replace(//g, '>'),
+ true)
}
function getDuration(task: Task): string | undefined {
diff --git a/test/reporters/src/data.ts b/test/reporters/src/data.ts
index a5003c07197b..03f9e0451c1c 100644
--- a/test/reporters/src/data.ts
+++ b/test/reporters/src/data.ts
@@ -142,6 +142,14 @@ const tasks: Task[] = [
fails: undefined,
file,
result: { state: 'pass', duration: 0.1923508644104004 },
+ logs: [
+ {
+ content: '[33merror[39m',
+ type: 'stderr',
+ time: 1642587001759,
+ size: 15,
+ },
+ ],
},
]
diff --git a/test/reporters/tests/__snapshots__/reporters.spec.ts.snap b/test/reporters/tests/__snapshots__/reporters.spec.ts.snap
index 5e31568012c8..6083083da594 100644
--- a/test/reporters/tests/__snapshots__/reporters.spec.ts.snap
+++ b/test/reporters/tests/__snapshots__/reporters.spec.ts.snap
@@ -24,6 +24,9 @@ AssertionError: expected 2.23606797749979 to equal 2
+
+[33merror[39m
+
@@ -54,6 +57,9 @@ AssertionError: expected 2.23606797749979 to equal 2
+
+[33merror[39m
+
@@ -89,6 +95,9 @@ AssertionError: expected 2.23606797749979 to equal 2
+
+[33merror[39m
+
@@ -124,6 +133,9 @@ AssertionError: expected 2.23606797749979 to equal 2
+
+[33merror[39m
+
@@ -159,6 +171,9 @@ AssertionError: expected 2.23606797749979 to equal 2
+
+[33merror[39m
+
@@ -194,6 +209,9 @@ AssertionError: expected 2.23606797749979 to equal 2
+
+[33merror[39m
+