diff --git a/tooling-core/src/main/java/org/opentest4j/reporting/tooling/core/htmlreport/CoreContributor.java b/tooling-core/src/main/java/org/opentest4j/reporting/tooling/core/htmlreport/CoreContributor.java index 4c99c88..8ec6f94 100644 --- a/tooling-core/src/main/java/org/opentest4j/reporting/tooling/core/htmlreport/CoreContributor.java +++ b/tooling-core/src/main/java/org/opentest4j/reporting/tooling/core/htmlreport/CoreContributor.java @@ -189,65 +189,13 @@ private static Optional
createAttachmentsSection(Context context) { var type = child.getLocalName(); var section = Section.builder().title(capitalize(type)); if (matches(File.ELEMENT, child)) { - var attributes = KeyValuePairs.builder(); - getAttributeValue(child, File.TIME).ifPresent(section::metaInfo); - var mediaType = getAttributeValue(child, File.MEDIA_TYPE); - getAttributeValue(child, File.PATH).ifPresent(rawPath -> { - var originalPath = context.sourceXmlFile().getParent().resolve(rawPath).toAbsolutePath(); - var path = tryRelativize(context.targetHtmlFile().getParent(), originalPath); - var filename = path.getFileName().toString(); - filename = filename.substring(Math.max(filename.lastIndexOf('/'), filename.lastIndexOf('\\')) + 1); - attributes.putContent("Filename", filename); - attributes.putContent("Path", "link:" + path); - if (Files.isRegularFile(originalPath)) { - var resolvedMediaType = mediaType.or(() -> { - try { - return Optional.ofNullable(Files.probeContentType(path)); - } - catch (IOException e) { - return Optional.empty(); - } - }).orElse(null); - if (resolvedMediaType != null) { - if (SUPPORTED_IMAGE_MEDIA_TYPES.contains(resolvedMediaType)) { - section.addBlock(Image.builder().content(path.toString()).altText(filename).build()); - } - else if (SUPPORTED_TEXT_MEDIA_TYPES.stream().anyMatch(resolvedMediaType::startsWith)) { - try { - var charset = parseCharset(resolvedMediaType); - var content = Files.readString(originalPath, charset); - section.addBlock(PreFormattedOutput.builder().content(content).build()); - } - catch (IOException ignore) { - } - } - } - } - }); - mediaType.ifPresent(it -> attributes.putContent("Media type", it)); - section.addBlock(attributes.build()); + addFileAttachment(context, child, section); } else if (matches(Data.ELEMENT, child)) { - var attributes = KeyValuePairs.builder(); - getAttributeValue(child, Data.TIME).ifPresent(section::metaInfo); - findChildren(child, Data.Entry.ELEMENT).forEach(entry -> { - getAttributeValue(entry, Data.Entry.KEY).ifPresent(key -> { - var value = entry.getTextContent(); - attributes.putContent(key, value); - }); - }); - section.addBlock(attributes.build()); + addDataAttachment(child, section); } else if (matches(Output.ELEMENT, child)) { - getAttributeValue(child, Output.SOURCE) // - .map(source -> switch (source) { - case "stdout" -> "Standard output"; - case "stderr" -> "Standard error"; - default -> "%s (%s)".formatted("Output", source); - }) // - .ifPresent(section::title); - getAttributeValue(child, Output.TIME).ifPresent(section::metaInfo); - section.addBlock(PreFormattedOutput.builder().content(child.getTextContent()).build()); + addOutputAttachment(child, section); } return section.build(); }).forEach(subsections::addContent); @@ -255,6 +203,75 @@ else if (matches(Output.ELEMENT, child)) { return Optional.of(Section.builder().title("Attachments").order(30).addBlock(subsections.build()).build()); } + private static void addFileAttachment(Context context, Node child, Section.Builder section) { + var attributes = KeyValuePairs.builder(); + getAttributeValue(child, File.TIME).ifPresent(section::metaInfo); + var mediaType = getAttributeValue(child, File.MEDIA_TYPE); + getAttributeValue(child, File.PATH).ifPresent(rawPath -> { + var originalPath = context.sourceXmlFile().getParent().resolve(rawPath).toAbsolutePath(); + var path = tryRelativize(context.targetHtmlFile().getParent(), originalPath); + var filename = path.getFileName().toString(); + filename = filename.substring(Math.max(filename.lastIndexOf('/'), filename.lastIndexOf('\\')) + 1); + attributes.putContent("Filename", filename); + attributes.putContent("Path", "link:" + path); + if (Files.isRegularFile(originalPath)) { + var resolvedMediaType = mediaType.or(() -> { + try { + return Optional.ofNullable(Files.probeContentType(path)); + } + catch (IOException e) { + return Optional.empty(); + } + }).orElse(null); + if (resolvedMediaType != null) { + addInlineFileBlock(section, resolvedMediaType, path, filename, originalPath); + } + } + }); + mediaType.ifPresent(it -> attributes.putContent("Media type", it)); + section.addBlock(attributes.build()); + } + + private static void addInlineFileBlock(Section.Builder section, String resolvedMediaType, Path path, + String filename, Path originalPath) { + if (SUPPORTED_IMAGE_MEDIA_TYPES.contains(resolvedMediaType)) { + section.addBlock(Image.builder().content(path.toString()).altText(filename).build()); + } + else if (SUPPORTED_TEXT_MEDIA_TYPES.stream().anyMatch(resolvedMediaType::startsWith)) { + try { + var charset = parseCharset(resolvedMediaType); + var content = Files.readString(originalPath, charset); + section.addBlock(PreFormattedOutput.builder().content(content).build()); + } + catch (IOException ignore) { + } + } + } + + private static void addDataAttachment(Node child, Section.Builder section) { + var attributes = KeyValuePairs.builder(); + getAttributeValue(child, Data.TIME).ifPresent(section::metaInfo); + findChildren(child, Data.Entry.ELEMENT).forEach(entry -> { + getAttributeValue(entry, Data.Entry.KEY).ifPresent(key -> { + var value = entry.getTextContent(); + attributes.putContent(key, value); + }); + }); + section.addBlock(attributes.build()); + } + + private static void addOutputAttachment(Node child, Section.Builder section) { + getAttributeValue(child, Output.SOURCE) // + .map(source -> switch (source) { + case "stdout" -> "Standard output"; + case "stderr" -> "Standard error"; + default -> "%s (%s)".formatted("Output", source); + }) // + .ifPresent(section::title); + getAttributeValue(child, Output.TIME).ifPresent(section::metaInfo); + section.addBlock(PreFormattedOutput.builder().content(child.getTextContent()).build()); + } + private static Charset parseCharset(String resolvedMediaType) { var mediaTypeParts = resolvedMediaType.split(";"); for (var part : mediaTypeParts) {