summaryrefslogtreecommitdiff
path: root/DomainDigTests/DomainReportExporterTests.swift
diff options
context:
space:
mode:
Diffstat (limited to 'DomainDigTests/DomainReportExporterTests.swift')
-rw-r--r--DomainDigTests/DomainReportExporterTests.swift107
1 files changed, 107 insertions, 0 deletions
diff --git a/DomainDigTests/DomainReportExporterTests.swift b/DomainDigTests/DomainReportExporterTests.swift
new file mode 100644
index 0000000..ddecabf
--- /dev/null
+++ b/DomainDigTests/DomainReportExporterTests.swift
@@ -0,0 +1,107 @@
+import XCTest
+@testable import DomainDig
+
+/// Characterization tests for the export surface. These pin the format dispatch,
+/// the JSON round-trip (the canonical machine contract), and the structural
+/// invariants of the human-readable formats.
+final class DomainReportExporterTests: XCTestCase {
+
+ private let decoder: JSONDecoder = {
+ let decoder = JSONDecoder()
+ decoder.dateDecodingStrategy = .iso8601
+ return decoder
+ }()
+
+ func testEveryFormatProducesNonEmptyData() throws {
+ let report = SnapshotFixture.report(availability: .registered)
+ for format in DomainExportFormat.allCases {
+ let data = try DomainReportExporter.data(for: report, format: format)
+ XCTAssertFalse(data.isEmpty, "\(format.rawValue) export was empty")
+ }
+ }
+
+ func testJSONExportRoundTripsToReport() throws {
+ let report = SnapshotFixture.report(domain: "roundtrip.example", availability: .registered)
+
+ let data = try DomainReportExporter.data(for: report, format: .json)
+ let decoded = try decoder.decode(DomainReport.self, from: data)
+
+ XCTAssertEqual(decoded.domain, "roundtrip.example")
+ XCTAssertEqual(decoded.availability, .registered)
+ XCTAssertEqual(decoded.timestamp, report.timestamp)
+ }
+
+ func testBatchJSONExportRoundTripsToReportArray() throws {
+ let reports = [
+ SnapshotFixture.report(domain: "one.example"),
+ SnapshotFixture.report(domain: "two.example")
+ ]
+
+ let data = try DomainReportExporter.data(for: reports, format: .json, title: "Batch")
+ let decoded = try decoder.decode([DomainReport].self, from: data)
+
+ XCTAssertEqual(decoded.map(\.domain), ["one.example", "two.example"])
+ }
+
+ func testCSVHasHeaderAndOneRowPerReport() {
+ let reports = [
+ SnapshotFixture.report(domain: "alpha.example"),
+ SnapshotFixture.report(domain: "beta.example")
+ ]
+
+ let csv = DomainReportExporter.csv(for: reports)
+ let lines = csv.split(separator: "\n", omittingEmptySubsequences: false)
+
+ XCTAssertEqual(lines.count, 3, "one header line plus one row per report")
+ XCTAssertTrue(lines[0].contains("\"domain\""))
+ XCTAssertTrue(csv.contains("\"alpha.example\""))
+ XCTAssertTrue(csv.contains("\"beta.example\""))
+ }
+
+ func testMarkdownIsHeadedAndNamesTheDomain() {
+ let markdown = DomainReportExporter.markdown(for: SnapshotFixture.report(domain: "md.example"))
+
+ XCTAssertTrue(markdown.hasPrefix("# "), "markdown export should open with an H1")
+ XCTAssertTrue(markdown.contains("md.example"))
+ }
+
+ func testTextExportNamesTheDomain() {
+ let text = DomainReportExporter.text(for: SnapshotFixture.report(domain: "txt.example"))
+ XCTAssertTrue(text.contains("txt.example"))
+ }
+
+ func testBatchExportsCarryTitleAndEveryDomain() {
+ let reports = [
+ SnapshotFixture.report(domain: "first.example"),
+ SnapshotFixture.report(domain: "second.example")
+ ]
+
+ let markdown = DomainReportExporter.batchMarkdown(for: reports, title: "Portfolio Sweep")
+ XCTAssertTrue(markdown.contains("Portfolio Sweep"))
+ XCTAssertTrue(markdown.contains("first.example"))
+ XCTAssertTrue(markdown.contains("second.example"))
+
+ let text = DomainReportExporter.batchText(for: reports, title: "Portfolio Sweep")
+ XCTAssertTrue(text.contains("Portfolio Sweep"))
+ XCTAssertTrue(text.contains("first.example"))
+ XCTAssertTrue(text.contains("second.example"))
+ }
+
+ func testPDFExportHasPDFSignature() throws {
+ let data = try DomainReportExporter.data(for: SnapshotFixture.report(), format: .pdf)
+ XCTAssertTrue(data.starts(with: Array("%PDF".utf8)), "PDF export should begin with the %PDF signature")
+ }
+
+ func testTimelineTextNamesTheDomain() {
+ let reports = [
+ SnapshotFixture.report(domain: "timeline.example", timestamp: SnapshotFixture.referenceDate),
+ SnapshotFixture.report(
+ domain: "timeline.example",
+ timestamp: SnapshotFixture.referenceDate.addingTimeInterval(86_400)
+ )
+ ]
+
+ let text = DomainReportExporter.timelineText(for: reports, domain: "timeline.example", includeDiffSummary: false)
+ XCTAssertTrue(text.contains("timeline.example"))
+ }
+}