import Foundation import Testing @testable import Photochk @Suite("選択ルール") @MainActor struct SelectionTests { private func asset( _ name: String, width: Int, height: Int, size: Int64, days: Double ) -> PhotoAsset { PhotoAsset( url: URL(fileURLWithPath: "/tmp/photochk/\(name)"), fileSize: size, modificationDate: Date(timeIntervalSince1970: days * 86_400), captureDate: Date(timeIntervalSince1970: days * 86_400), pixelWidth: width, pixelHeight: height ) } private func makeGroup() -> SimilarityGroup { let big = asset("big.jpg", width: 4000, height: 3000, size: 5_000_000, days: 10) let mid = asset("mid.jpg", width: 2000, height: 1500, size: 2_000_000, days: 20) let small = asset("small.jpg", width: 1000, height: 750, size: 500_000, days: 1) return SimilarityGroup( members: [ .init(asset: big, relation: .exact), .init(asset: mid, relation: .similar(distance: 0.1)), .init(asset: small, relation: .similar(distance: 0.2)), ], representativeID: big.url ) } private func makeModel() -> ScanViewModel { let model = ScanViewModel() model.setGroupsForTesting([makeGroup()]) return model } @Test("最後の1枚は選択できない") func keepsAtLeastOne() { let model = makeModel() let group = model.groups[0] let ids = group.members.map(\.id) model.toggleMark(ids[0], in: group) model.toggleMark(ids[1], in: group) #expect(model.markedCount == 2) // 3枚目を選ぶと全滅するので拒否される #expect(model.canMark(ids[2], in: group) == false) model.toggleMark(ids[2], in: group) #expect(model.markedCount == 2) // すでに選んでいるものは解除できる #expect(model.canMark(ids[0], in: group) == true) } @Test("解像度が最も高い1枚を残す") func keepHighestResolution() { let model = makeModel() model.applyKeepRule(.highestResolution) let kept = model.groups[0].members.filter { !model.markedForDeletion.contains($0.id) } #expect(kept.count == 1) #expect(kept[0].asset.fileName == "big.jpg") } @Test("最も新しい1枚 / 最も古い1枚を残す") func keepNewestAndOldest() { let model = makeModel() model.applyKeepRule(.newest) var kept = model.groups[0].members.filter { !model.markedForDeletion.contains($0.id) } #expect(kept.map(\.asset.fileName) == ["mid.jpg"]) model.applyKeepRule(.oldest) kept = model.groups[0].members.filter { !model.markedForDeletion.contains($0.id) } #expect(kept.map(\.asset.fileName) == ["small.jpg"]) } @Test("選択解除ですべての印が消える") func clearMarks() { let model = makeModel() model.applyKeepRule(.highestResolution) #expect(model.markedCount == 2) model.clearMarks() #expect(model.markedCount == 0) #expect(model.markedBytes == 0) } @Test("選択した容量の合計が集計される") func markedBytes() { let model = makeModel() model.applyKeepRule(.highestResolution) #expect(model.markedBytes == 2_500_000) } }