krz/domain-dig
an ios app for DNS & SSL analysis
clone: git clone https://gitbay.org/krz/domain-dig.git
v5.0.2: DomainDigTests/DomainReportBuilderTests.swift · raw
1import XCTest
2@testable import DomainDig
3
4/// Characterization tests for the snapshot → report projection. These lock the
5/// field-mapping and derivation rules the export/diff contracts depend on.
6final class DomainReportBuilderTests: XCTestCase {
7 private let builder = DomainReportBuilder()
8
9 func testCoreIdentityFieldsPassThrough() {
10 let report = builder.build(
11 from: SnapshotFixture.snapshot(
12 domain: "mapped.example",
13 resolverURLString: "https://r.example/dns-query"
14 ),
15 deriveChangeSummary: false
16 )
17
18 XCTAssertEqual(report.domain, "mapped.example")
19 XCTAssertEqual(report.timestamp, SnapshotFixture.referenceDate)
20 XCTAssertEqual(report.resolverURLString, "https://r.example/dns-query")
21 XCTAssertFalse(report.metadata.schemaVersion.isEmpty)
22 }
23
24 func testAvailabilityDefaultsToUnknownWhenAbsent() {
25 let unknown = builder.build(from: SnapshotFixture.snapshot(availability: nil), deriveChangeSummary: false)
26 XCTAssertEqual(unknown.availability, .unknown)
27
28 let registered = builder.build(from: SnapshotFixture.snapshot(availability: .registered), deriveChangeSummary: false)
29 XCTAssertEqual(registered.availability, .registered)
30 }
31
32 func testPrimaryIPComesFromFirstARecord() {
33 let report = builder.build(
34 from: SnapshotFixture.snapshot(
35 dnsSections: [
36 SnapshotFixture.dnsSection(type: .A, values: ["198.51.100.7", "198.51.100.8"]),
37 SnapshotFixture.dnsSection(type: .AAAA, values: ["2001:db8::1"])
38 ]
39 ),
40 deriveChangeSummary: false
41 )
42
43 XCTAssertEqual(report.dns.primaryIP, "198.51.100.7")
44 XCTAssertEqual(report.network.primaryIP, "198.51.100.7")
45 }
46
47 func testPrimaryIPNilWithoutARecord() {
48 let report = builder.build(
49 from: SnapshotFixture.snapshot(
50 dnsSections: [SnapshotFixture.dnsSection(type: .MX, values: ["mail.example.com"])]
51 ),
52 deriveChangeSummary: false
53 )
54 XCTAssertNil(report.dns.primaryIP)
55 }
56
57 func testDNSSECDerivedFromSections() {
58 let signed = builder.build(
59 from: SnapshotFixture.snapshot(
60 dnsSections: [SnapshotFixture.dnsSection(type: .A, values: ["203.0.113.1"], dnssecSigned: true)]
61 ),
62 deriveChangeSummary: false
63 )
64 XCTAssertEqual(signed.dns.dnssecSigned, true)
65
66 let unknown = builder.build(
67 from: SnapshotFixture.snapshot(
68 dnsSections: [SnapshotFixture.dnsSection(type: .A, values: ["203.0.113.1"])]
69 ),
70 deriveChangeSummary: false
71 )
72 XCTAssertNil(unknown.dns.dnssecSigned)
73 }
74
75 func testTLSStatusReflectsCertificatePresence() {
76 let valid = builder.build(
77 from: SnapshotFixture.snapshot(sslInfo: SnapshotFixture.certificate()),
78 deriveChangeSummary: false
79 )
80 XCTAssertEqual(valid.web.tlsStatus, "valid")
81
82 let missing = builder.build(from: SnapshotFixture.snapshot(sslInfo: nil), deriveChangeSummary: false)
83 XCTAssertEqual(missing.web.tlsStatus, "unavailable")
84 }
85
86 func testWebHeaderCountAndFinalURL() {
87 let report = builder.build(
88 from: SnapshotFixture.snapshot(
89 httpHeaders: [
90 HTTPHeader(name: "Content-Type", value: "text/html"),
91 HTTPHeader(name: "Strict-Transport-Security", value: "max-age=63072000")
92 ],
93 httpStatusCode: 200
94 ),
95 deriveChangeSummary: false
96 )
97
98 XCTAssertEqual(report.web.headerCount, 2)
99 XCTAssertEqual(report.web.statusCode, 200)
100 XCTAssertNil(report.web.finalURL, "no redirect chain means no final URL")
101 }
102
103 func testPartialSnapshotAndValidationIssuesPropagate() {
104 let report = builder.build(
105 from: SnapshotFixture.snapshot(
106 isPartialSnapshot: true,
107 validationIssues: ["missing DNS", "stale WHOIS"]
108 ),
109 deriveChangeSummary: false
110 )
111
112 XCTAssertTrue(report.isPartialSnapshot)
113 XCTAssertEqual(report.validationIssues, ["missing DNS", "stale WHOIS"])
114 XCTAssertTrue(report.metadata.isPartialSnapshot)
115 XCTAssertEqual(report.metadata.validationIssues, ["missing DNS", "stale WHOIS"])
116 }
117
118 func testRecordSectionsArePreserved() {
119 let sections = [
120 SnapshotFixture.dnsSection(type: .A, values: ["203.0.113.1"]),
121 SnapshotFixture.dnsSection(type: .MX, values: ["mail.example.com"])
122 ]
123 let report = builder.build(
124 from: SnapshotFixture.snapshot(dnsSections: sections),
125 deriveChangeSummary: false
126 )
127
128 XCTAssertEqual(Set(report.dns.recordSections.map(\.recordType)), [.A, .MX])
129 }
130}