apple_kit

Apple-native services for Radroots iOS and macOS apps
git clone https://radroots.dev/git/apple_kit.git
Log | Files | Refs | README

RadrootsCaptureIntakeTests.swift (5933B)


      1 import Foundation
      2 import Testing
      3 @testable import RadrootsKit
      4 
      5 @Test func mediaImportRequestNormalizesKindsAndSelectionLimit() throws {
      6     let request = try RadrootsMediaImportRequest(
      7         allowedMediaKinds: [.image, .image],
      8         selectionLimit: 2,
      9         destinationScope: .data
     10     )
     11 
     12     #expect(request.allowedMediaKinds == [.image])
     13     #expect(request.selectionLimit == 2)
     14     #expect(request.destinationScope == .data)
     15 }
     16 
     17 @Test func mediaImportRequestRejectsInvalidSelectionLimits() {
     18     #expect(throws: RadrootsCaptureIntakeError.invalidRequest("media import selection limit must be positive")) {
     19         _ = try RadrootsMediaImportRequest(selectionLimit: 0)
     20     }
     21     #expect(throws: RadrootsCaptureIntakeError.invalidRequest("media import selection limit cannot exceed 100")) {
     22         _ = try RadrootsMediaImportRequest(selectionLimit: 101)
     23     }
     24 }
     25 
     26 @Test func mediaPickerSupportOmitsKindsWhenUnavailable() throws {
     27     let support = try RadrootsMediaPickerSupport(
     28         importAvailable: false,
     29         cameraCaptureAvailable: false,
     30         supportedImportKinds: [.image],
     31         supportedCaptureKinds: [.image],
     32         multipleSelectionSupported: true
     33     )
     34 
     35     #expect(!support.importAvailable)
     36     #expect(!support.cameraCaptureAvailable)
     37     #expect(support.supportedImportKinds.isEmpty)
     38     #expect(support.supportedCaptureKinds.isEmpty)
     39     #expect(support.multipleSelectionSupported)
     40 }
     41 
     42 @Test func mediaAssetNormalizesMetadata() throws {
     43     let asset = try RadrootsMediaAsset(
     44         source: .libraryImport,
     45         kind: .image,
     46         file: RadrootsFileReference(scope: .temporary, relativePath: "capture/photo.jpg"),
     47         mediaType: " Image/JPEG ",
     48         suggestedFilename: " photo.jpg ",
     49         sizeBytes: 12,
     50         pixelWidth: 640,
     51         pixelHeight: 480,
     52         capturedAt: Date(timeIntervalSince1970: 10)
     53     )
     54 
     55     #expect(asset.mediaType == "image/jpeg")
     56     #expect(asset.suggestedFilename == "photo.jpg")
     57     #expect(asset.pixelWidth == 640)
     58     #expect(asset.pixelHeight == 480)
     59     #expect(asset.capturedAt == Date(timeIntervalSince1970: 10))
     60 }
     61 
     62 @Test func mediaAssetRejectsUnsafeMetadata() {
     63     #expect(throws: RadrootsCaptureIntakeError.invalidRequest("capture filename cannot contain path separators")) {
     64         _ = try RadrootsMediaAsset(
     65             source: .libraryImport,
     66             kind: .image,
     67             file: RadrootsFileReference(scope: .temporary, relativePath: "capture/photo.jpg"),
     68             mediaType: "image/jpeg",
     69             suggestedFilename: "../photo.jpg",
     70             sizeBytes: 12,
     71             capturedAt: Date(timeIntervalSince1970: 10)
     72         )
     73     }
     74     #expect(throws: RadrootsCaptureIntakeError.invalidRequest("capture media type must be type/subtype")) {
     75         _ = try RadrootsMediaAsset(
     76             source: .libraryImport,
     77             kind: .image,
     78             file: RadrootsFileReference(scope: .temporary, relativePath: "capture/photo.jpg"),
     79             mediaType: "image",
     80             suggestedFilename: "photo.jpg",
     81             sizeBytes: 12,
     82             capturedAt: Date(timeIntervalSince1970: 10)
     83         )
     84     }
     85     #expect(throws: RadrootsCaptureIntakeError.invalidRequest("image dimensions must include width and height together")) {
     86         _ = try RadrootsMediaAsset(
     87             source: .libraryImport,
     88             kind: .image,
     89             file: RadrootsFileReference(scope: .temporary, relativePath: "capture/photo.jpg"),
     90             mediaType: "image/jpeg",
     91             suggestedFilename: "photo.jpg",
     92             sizeBytes: 12,
     93             pixelWidth: 640,
     94             capturedAt: Date(timeIntervalSince1970: 10)
     95         )
     96     }
     97 }
     98 
     99 @Test func mediaImportResultRequiresAtLeastOneItem() throws {
    100     let asset = try testMediaAsset()
    101     let result = try RadrootsMediaImportResult(items: [asset])
    102 
    103     #expect(result.items == [asset])
    104     #expect(throws: RadrootsCaptureIntakeError.invalidRequest("media import result cannot be empty")) {
    105         _ = try RadrootsMediaImportResult(items: [])
    106     }
    107 }
    108 
    109 @Test func scannerSupportOmitsOutputKindsWhenUnavailable() throws {
    110     let support = try RadrootsDocumentScannerSupport(
    111         interactiveScanAvailable: false,
    112         multiPageSupported: true,
    113         supportedOutputKinds: [.pdf]
    114     )
    115 
    116     #expect(!support.interactiveScanAvailable)
    117     #expect(!support.multiPageSupported)
    118     #expect(support.supportedOutputKinds.isEmpty)
    119 }
    120 
    121 @Test func scannedDocumentNormalizesPdfMetadata() throws {
    122     let document = try RadrootsScannedDocument(
    123         file: RadrootsFileReference(scope: .temporary, relativePath: "capture/scan.pdf"),
    124         outputKind: .pdf,
    125         suggestedFilename: " scan.pdf ",
    126         mediaType: " Application/PDF ",
    127         pageCount: 2,
    128         sizeBytes: 2048,
    129         capturedAt: Date(timeIntervalSince1970: 11)
    130     )
    131 
    132     #expect(document.suggestedFilename == "scan.pdf")
    133     #expect(document.mediaType == "application/pdf")
    134     #expect(document.pageCount == 2)
    135     #expect(document.sizeBytes == 2048)
    136 }
    137 
    138 @Test func scannedDocumentRejectsEmptyPageCount() {
    139     #expect(throws: RadrootsCaptureIntakeError.invalidRequest("scanned document page count must be positive")) {
    140         _ = try RadrootsScannedDocument(
    141             file: RadrootsFileReference(scope: .temporary, relativePath: "capture/scan.pdf"),
    142             outputKind: .pdf,
    143             suggestedFilename: "scan.pdf",
    144             mediaType: "application/pdf",
    145             pageCount: 0,
    146             sizeBytes: 2048,
    147             capturedAt: Date(timeIntervalSince1970: 11)
    148         )
    149     }
    150 }
    151 
    152 private func testMediaAsset() throws -> RadrootsMediaAsset {
    153     try RadrootsMediaAsset(
    154         source: .libraryImport,
    155         kind: .image,
    156         file: RadrootsFileReference(scope: .temporary, relativePath: "capture/photo.jpg"),
    157         mediaType: "image/jpeg",
    158         suggestedFilename: "photo.jpg",
    159         sizeBytes: 12,
    160         capturedAt: Date(timeIntervalSince1970: 10)
    161     )
    162 }