RadrootsDocumentInterchangeTests.swift (6251B)
1 import Foundation 2 import Testing 3 @testable import RadrootsKit 4 5 @Test func documentImportRequestNormalizesContentKinds() throws { 6 let request = try RadrootsDocumentImportRequest( 7 allowedContentKinds: [.json, .json, .plainText], 8 allowsMultipleSelection: true, 9 destinationScope: .cache 10 ) 11 12 #expect(request.allowedContentKinds == [.json, .plainText]) 13 #expect(request.allowsMultipleSelection) 14 #expect(request.destinationScope == .cache) 15 16 #expect(throws: RadrootsDocumentInterchangeError.self) { 17 _ = try RadrootsDocumentImportRequest(allowedContentKinds: []) 18 } 19 } 20 21 @Test func documentImportResultRejectsEmptyResultsAndUnsafeMetadata() throws { 22 let file = RadrootsFileReference(scope: .temporary, relativePath: "imports/config.json") 23 let document = try RadrootsImportedDocument( 24 file: file, 25 originalURL: URL(fileURLWithPath: "/tmp/config.json"), 26 suggestedFilename: " config.json ", 27 mediaType: " Application/JSON ", 28 sizeBytes: 12 29 ) 30 31 #expect(document.originalURL == URL(fileURLWithPath: "/tmp/config.json")) 32 #expect(document.suggestedFilename == "config.json") 33 #expect(document.mediaType == "application/json") 34 #expect(try RadrootsDocumentImportResult(documents: [document]).documents == [document]) 35 36 #expect(throws: RadrootsDocumentInterchangeError.self) { 37 _ = try RadrootsDocumentImportResult(documents: []) 38 } 39 #expect(throws: RadrootsDocumentInterchangeError.self) { 40 _ = try RadrootsImportedDocument( 41 file: file, 42 originalURL: URL(string: "https://radroots.org/config.json"), 43 suggestedFilename: "config.json", 44 mediaType: "application/json", 45 sizeBytes: 1 46 ) 47 } 48 #expect(throws: RadrootsDocumentInterchangeError.self) { 49 _ = try RadrootsImportedDocument( 50 file: file, 51 originalURL: nil, 52 suggestedFilename: "../config.json", 53 mediaType: "application/json", 54 sizeBytes: 1 55 ) 56 } 57 } 58 59 @Test func shareRequestValidatesPublicItems() throws { 60 let file = RadrootsFileReference(scope: .cache, relativePath: "exports/diagnostics.json") 61 let stagedBlob = try RadrootsStagedBlobReference( 62 blobID: "diagnostics", 63 sizeBytes: 24, 64 mediaType: "application/json", 65 filenameHint: "diagnostics.json" 66 ) 67 let request = try RadrootsShareRequest( 68 items: [ 69 .text(" public post "), 70 .url(URL(string: "https://radroots.org/posts/1")!), 71 .file(file, suggestedFilename: " diagnostics.json ", mediaType: " Application/JSON ", sizeBytes: 24), 72 .stagedBlob(stagedBlob, suggestedFilename: " staged.json ") 73 ], 74 subject: " Radroots " 75 ) 76 77 #expect(request.subject == "Radroots") 78 #expect(request.items.count == 4) 79 #expect(request.items[0] == .text("public post")) 80 #expect(request.items[1] == .url(URL(string: "https://radroots.org/posts/1")!)) 81 #expect(request.items[2] == .file(file, suggestedFilename: "diagnostics.json", mediaType: "application/json", sizeBytes: 24)) 82 #expect(request.items[3] == .stagedBlob(stagedBlob, suggestedFilename: "staged.json")) 83 84 #expect(throws: RadrootsDocumentInterchangeError.self) { 85 _ = try RadrootsShareRequest(items: []) 86 } 87 #expect(throws: RadrootsDocumentInterchangeError.self) { 88 _ = try RadrootsShareRequest(items: [.text(" ")]) 89 } 90 #expect(throws: RadrootsDocumentInterchangeError.self) { 91 _ = try RadrootsShareRequest(items: [.url(URL(string: "file:///tmp/private.txt")!)]) 92 } 93 } 94 95 @Test func exportDocumentRequestValidatesFilenameMediaTypeAndByteCounts() throws { 96 let inlineData = Data(#"{"relay":"wss://radroots.org"}"#.utf8) 97 let inlineRequest = try RadrootsExportDocumentRequest( 98 source: .inlineData(inlineData), 99 suggestedFilename: " relays.json ", 100 mediaType: " Application/JSON " 101 ) 102 103 #expect(inlineRequest.suggestedFilename == "relays.json") 104 #expect(inlineRequest.mediaType == "application/json") 105 #expect(inlineRequest.sizeBytes == UInt64(inlineData.count)) 106 107 let stagedBlob = try RadrootsStagedBlobReference(blobID: "relay-export", sizeBytes: 64) 108 let stagedRequest = try RadrootsExportDocumentRequest( 109 source: .stagedBlob(stagedBlob), 110 suggestedFilename: "relay-export.json", 111 mediaType: "application/json", 112 sizeBytes: 64 113 ) 114 #expect(stagedRequest.sizeBytes == 64) 115 116 #expect(throws: RadrootsDocumentInterchangeError.self) { 117 _ = try RadrootsExportDocumentRequest( 118 source: .inlineData(inlineData), 119 suggestedFilename: "/tmp/relays.json", 120 mediaType: "application/json" 121 ) 122 } 123 #expect(throws: RadrootsDocumentInterchangeError.self) { 124 _ = try RadrootsExportDocumentRequest( 125 source: .inlineData(inlineData), 126 suggestedFilename: "relays.json", 127 mediaType: "application json" 128 ) 129 } 130 #expect(throws: RadrootsDocumentInterchangeError.self) { 131 _ = try RadrootsExportDocumentRequest( 132 source: .inlineData(inlineData), 133 suggestedFilename: "relays.json", 134 mediaType: "application/json", 135 sizeBytes: 1 136 ) 137 } 138 #expect(throws: RadrootsDocumentInterchangeError.self) { 139 _ = try RadrootsExportDocumentRequest( 140 source: .stagedBlob(stagedBlob), 141 suggestedFilename: "relay-export.json", 142 mediaType: "application/json", 143 sizeBytes: 1 144 ) 145 } 146 } 147 148 @Test func exportDocumentResultNormalizesPublicMetadata() throws { 149 let result = try RadrootsExportDocumentResult( 150 exportedFilename: " diagnostics.json ", 151 mediaType: " Application/JSON ", 152 sizeBytes: 99 153 ) 154 155 #expect(result.exportedFilename == "diagnostics.json") 156 #expect(result.mediaType == "application/json") 157 #expect(result.sizeBytes == 99) 158 159 #expect(throws: RadrootsDocumentInterchangeError.self) { 160 _ = try RadrootsExportDocumentResult( 161 exportedFilename: "bad/name.json", 162 mediaType: "application/json", 163 sizeBytes: nil 164 ) 165 } 166 }