native macOS codings agent orchestrator prowl.onev.cat
Something went wrong. Try again.
7.5 kB · 197 lines
Swift
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198import Foundationimport Testing
@testable import supacode
/// RAII helper: creates a unique scratch directory under `$TMPDIR` and/// removes it on deinit so test runs don't accumulate orphan folders/// between invocations (we ship to `make test` repeatedly during dev).private final class ScratchDirectory { let url: URL
init(prefix: String) { url = URL(fileURLWithPath: NSTemporaryDirectory()) .appending(path: "\(prefix)-\(UUID().uuidString)", directoryHint: .isDirectory) try? FileManager.default.createDirectory(at: url, withIntermediateDirectories: true) }
deinit { try? FileManager.default.removeItem(at: url) }}
@MainActorstruct RepositoryIconAssetStoreTests { // MARK: - Helpers
private struct StoreFixture { let store: RepositoryIconAssetStore let repoRoot: ScratchDirectory let iconStoreRoot: ScratchDirectory
func iconsDirectory() -> URL { iconStoreRoot.url .appending(path: repoRoot.url.lastPathComponent, directoryHint: .isDirectory) .appending(path: "icons", directoryHint: .isDirectory) } }
private func makeRepoRootScratch() -> ScratchDirectory { ScratchDirectory(prefix: "prowl-icon-store") }
private func makeStoreFixture() -> StoreFixture { let repoRoot = makeRepoRootScratch() let iconStoreRoot = ScratchDirectory(prefix: "prowl-icon-store-home") let store = RepositoryIconAssetStore.fileSystemValue { rootURL in iconStoreRoot.url .appending(path: rootURL.lastPathComponent, directoryHint: .isDirectory) .appending(path: "icons", directoryHint: .isDirectory) } return StoreFixture(store: store, repoRoot: repoRoot, iconStoreRoot: iconStoreRoot) }
private func writeSourceFile( in scratch: ScratchDirectory, extension ext: String, contents: Data = Data([0xDE, 0xAD]) ) throws -> URL { let url = scratch.url.appending(path: "icon.\(ext)", directoryHint: .notDirectory) try contents.write(to: url) return url }
// MARK: - importImage
@Test func importImageCopiesFileWithUUIDName() throws { let fixture = makeStoreFixture() let source = ScratchDirectory(prefix: "prowl-icon-source") let sourceFile = try writeSourceFile( in: source, extension: "png", contents: Data([0x01, 0x02, 0x03]) )
let filename = try fixture.store.importImage(sourceFile, fixture.repoRoot.url)
#expect(filename.hasSuffix(".png")) #expect(UUID(uuidString: String(filename.dropLast(4))) != nil)
let resolved = fixture.iconsDirectory().appending(path: filename, directoryHint: .notDirectory) let copied = try Data(contentsOf: resolved) #expect(copied == Data([0x01, 0x02, 0x03]))
let productionURL = SupacodePaths.repositoryIconFileURL( filename: filename, repositoryRootURL: fixture.repoRoot.url ) #expect(!FileManager.default.fileExists(atPath: productionURL.path(percentEncoded: false))) }
@Test func importImageNormalizesUppercaseExtension() throws { let fixture = makeStoreFixture() let source = ScratchDirectory(prefix: "prowl-icon-source") let sourceFile = try writeSourceFile(in: source, extension: "PNG")
let filename = try fixture.store.importImage(sourceFile, fixture.repoRoot.url) #expect(filename.hasSuffix(".png")) }
@Test func importImageAcceptsSVG() throws { let fixture = makeStoreFixture() let source = ScratchDirectory(prefix: "prowl-icon-source") let sourceFile = try writeSourceFile(in: source, extension: "svg")
let filename = try fixture.store.importImage(sourceFile, fixture.repoRoot.url) #expect(filename.hasSuffix(".svg")) }
@Test func importImageAcceptsArbitraryImageExtensions() throws { // The store no longer enforces a PNG/SVG whitelist — the file // picker filters down to image UTTypes already, and anything // that NSImage can't decode falls back to a placeholder at // render time. JPG / WebP / HEIC / GIF / TIFF / etc. all flow // through the same byte-copy path and round-trip through // `repositoryIconFileURL` like PNG does. let fixture = makeStoreFixture()
for ext in ["jpg", "jpeg", "webp", "heic", "gif", "tiff", "bmp"] { let source = ScratchDirectory(prefix: "prowl-icon-source") let sourceFile = try writeSourceFile(in: source, extension: ext) let filename = try fixture.store.importImage(sourceFile, fixture.repoRoot.url) #expect(filename.hasSuffix(".\(ext)")) } }
@Test func importImageHandlesFileWithNoExtension() throws { // Defensive: a dragged-in file without an extension shouldn't // crash the importer. The destination filename gets a generic // fallback so the round-trip still works. let fixture = makeStoreFixture() let source = ScratchDirectory(prefix: "prowl-icon-source") let sourceFile = source.url.appending(path: "icon", directoryHint: .notDirectory) try Data([0xDE, 0xAD]).write(to: sourceFile)
let filename = try fixture.store.importImage(sourceFile, fixture.repoRoot.url) #expect(!filename.isEmpty) }
@Test func importImageCreatesIconsDirectoryWhenMissing() throws { let fixture = makeStoreFixture() // Don't pre-create the icons directory — importImage should make // it itself, otherwise first-time imports would fail. let source = ScratchDirectory(prefix: "prowl-icon-source") let sourceFile = try writeSourceFile(in: source, extension: "png")
_ = try fixture.store.importImage(sourceFile, fixture.repoRoot.url)
let iconsDir = fixture.iconsDirectory() var isDirectory: ObjCBool = false let exists = FileManager.default.fileExists( atPath: iconsDir.path(percentEncoded: false), isDirectory: &isDirectory ) #expect(exists) #expect(isDirectory.boolValue) }
@Test func importImageGeneratesUniqueFilenamePerCall() throws { let fixture = makeStoreFixture() let source = ScratchDirectory(prefix: "prowl-icon-source") let sourceFile = try writeSourceFile(in: source, extension: "png")
let first = try fixture.store.importImage(sourceFile, fixture.repoRoot.url) let second = try fixture.store.importImage(sourceFile, fixture.repoRoot.url) #expect(first != second) }
// MARK: - exists
@Test func existsReportsFalseWhenMissing() { let fixture = makeStoreFixture() #expect(!fixture.store.exists("nonexistent.png", fixture.repoRoot.url)) }
@Test func existsReportsTrueAfterImport() throws { let fixture = makeStoreFixture() let source = ScratchDirectory(prefix: "prowl-icon-source") let sourceFile = try writeSourceFile(in: source, extension: "png") let filename = try fixture.store.importImage(sourceFile, fixture.repoRoot.url) #expect(fixture.store.exists(filename, fixture.repoRoot.url)) }
// MARK: - remove
@Test func removeDeletesImportedFile() throws { let fixture = makeStoreFixture() let source = ScratchDirectory(prefix: "prowl-icon-source") let sourceFile = try writeSourceFile(in: source, extension: "png") let filename = try fixture.store.importImage(sourceFile, fixture.repoRoot.url)
try fixture.store.remove(filename, fixture.repoRoot.url) #expect(!fixture.store.exists(filename, fixture.repoRoot.url)) }
@Test func removeIsIdempotent() throws { // Reset / replace flows can call remove repeatedly; missing files // shouldn't throw or the reducer would have to track existence. let fixture = makeStoreFixture() try fixture.store.remove("never-existed.png", fixture.repoRoot.url) }}