krz/domain-dig

an ios app for DNS & SSL analysis

clone: git clone https://gitbay.org/krz/domain-dig.git

v5.0.2: DomainDigTests/DomainReportExporterTests.swift · raw

  1import XCTest
  2@testable import DomainDig
  3
  4/// Characterization tests for the export surface. These pin the format dispatch,
  5/// the JSON round-trip (the canonical machine contract), and the structural
  6/// invariants of the human-readable formats.
  7final class DomainReportExporterTests: XCTestCase {
  8
  9    private let decoder: JSONDecoder = {
 10        let decoder = JSONDecoder()
 11        decoder.dateDecodingStrategy = .iso8601
 12        return decoder
 13    }()
 14
 15    func testEveryFormatProducesNonEmptyData() throws {
 16        let report = SnapshotFixture.report(availability: .registered)
 17        for format in DomainExportFormat.allCases {
 18            let data = try DomainReportExporter.data(for: report, format: format)
 19            XCTAssertFalse(data.isEmpty, "\(format.rawValue) export was empty")
 20        }
 21    }
 22
 23    func testJSONExportRoundTripsToReport() throws {
 24        let report = SnapshotFixture.report(domain: "roundtrip.example", availability: .registered)
 25
 26        let data = try DomainReportExporter.data(for: report, format: .json)
 27        let decoded = try decoder.decode(DomainReport.self, from: data)
 28
 29        XCTAssertEqual(decoded.domain, "roundtrip.example")
 30        XCTAssertEqual(decoded.availability, .registered)
 31        XCTAssertEqual(decoded.timestamp, report.timestamp)
 32    }
 33
 34    func testBatchJSONExportRoundTripsToReportArray() throws {
 35        let reports = [
 36            SnapshotFixture.report(domain: "one.example"),
 37            SnapshotFixture.report(domain: "two.example")
 38        ]
 39
 40        let data = try DomainReportExporter.data(for: reports, format: .json, title: "Batch")
 41        let decoded = try decoder.decode([DomainReport].self, from: data)
 42
 43        XCTAssertEqual(decoded.map(\.domain), ["one.example", "two.example"])
 44    }
 45
 46    func testCSVHasHeaderAndOneRowPerReport() {
 47        let reports = [
 48            SnapshotFixture.report(domain: "alpha.example"),
 49            SnapshotFixture.report(domain: "beta.example")
 50        ]
 51
 52        let csv = DomainReportExporter.csv(for: reports)
 53        let lines = csv.split(separator: "\n", omittingEmptySubsequences: false)
 54
 55        XCTAssertEqual(lines.count, 3, "one header line plus one row per report")
 56        XCTAssertTrue(lines[0].contains("\"domain\""))
 57        XCTAssertTrue(csv.contains("\"alpha.example\""))
 58        XCTAssertTrue(csv.contains("\"beta.example\""))
 59    }
 60
 61    func testMarkdownIsHeadedAndNamesTheDomain() {
 62        let markdown = DomainReportExporter.markdown(for: SnapshotFixture.report(domain: "md.example"))
 63
 64        XCTAssertTrue(markdown.hasPrefix("# "), "markdown export should open with an H1")
 65        XCTAssertTrue(markdown.contains("md.example"))
 66    }
 67
 68    func testTextExportNamesTheDomain() {
 69        let text = DomainReportExporter.text(for: SnapshotFixture.report(domain: "txt.example"))
 70        XCTAssertTrue(text.contains("txt.example"))
 71    }
 72
 73    func testBatchExportsCarryTitleAndEveryDomain() {
 74        let reports = [
 75            SnapshotFixture.report(domain: "first.example"),
 76            SnapshotFixture.report(domain: "second.example")
 77        ]
 78
 79        let markdown = DomainReportExporter.batchMarkdown(for: reports, title: "Portfolio Sweep")
 80        XCTAssertTrue(markdown.contains("Portfolio Sweep"))
 81        XCTAssertTrue(markdown.contains("first.example"))
 82        XCTAssertTrue(markdown.contains("second.example"))
 83
 84        let text = DomainReportExporter.batchText(for: reports, title: "Portfolio Sweep")
 85        XCTAssertTrue(text.contains("Portfolio Sweep"))
 86        XCTAssertTrue(text.contains("first.example"))
 87        XCTAssertTrue(text.contains("second.example"))
 88    }
 89
 90    func testPDFExportHasPDFSignature() throws {
 91        let data = try DomainReportExporter.data(for: SnapshotFixture.report(), format: .pdf)
 92        XCTAssertTrue(data.starts(with: Array("%PDF".utf8)), "PDF export should begin with the %PDF signature")
 93    }
 94
 95    func testTimelineTextNamesTheDomain() {
 96        let reports = [
 97            SnapshotFixture.report(domain: "timeline.example", timestamp: SnapshotFixture.referenceDate),
 98            SnapshotFixture.report(
 99                domain: "timeline.example",
100                timestamp: SnapshotFixture.referenceDate.addingTimeInterval(86_400)
101            )
102        ]
103
104        let text = DomainReportExporter.timelineText(for: reports, domain: "timeline.example", includeDiffSummary: false)
105        XCTAssertTrue(text.contains("timeline.example"))
106    }
107}