为旅拍 OTG 上传增加 client_photo_id,并按服务端已登记 ID 同步本地上传状态。
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@ -90,6 +90,78 @@ final class TravelAlbumOTGStorageTests: XCTestCase {
|
||||
XCTAssertFalse(FileManager.default.fileExists(atPath: another.deletingLastPathComponent().deletingLastPathComponent().path))
|
||||
}
|
||||
|
||||
func testLegacyRecordGetsStableClientPhotoIdOnLoad() throws {
|
||||
let root = try makeTempDirectory()
|
||||
defer { try? FileManager.default.removeItem(at: root) }
|
||||
let store = makeStore(root: root)
|
||||
let legacyJSON = """
|
||||
{"id":"legacy","sourceId":"legacy","fileName":"A.JPG","localPath":"",\
|
||||
"thumbnailPath":"","capturedAt":"2026-07-16 12:00:00","fileSizeBytes":1,\
|
||||
"status":"UPLOADED","progress":100,"albumId":33,"userId":"u1",\
|
||||
"remoteUrl":"https://cdn/a.jpg","updatedAt":1}
|
||||
""".data(using: .utf8)!
|
||||
let legacy = try JSONDecoder().decode(TravelAlbumOTGPhotoRecord.self, from: legacyJSON)
|
||||
XCTAssertTrue(legacy.clientPhotoId.isEmpty)
|
||||
store.save([legacy], albumId: 33)
|
||||
|
||||
let first = try XCTUnwrap(store.load(albumId: 33).first?.clientPhotoId)
|
||||
let second = try XCTUnwrap(store.load(albumId: 33).first?.clientPhotoId)
|
||||
|
||||
XCTAssertNotNil(UUID(uuidString: first))
|
||||
XCTAssertEqual(first, first.lowercased())
|
||||
XCTAssertEqual(first, second)
|
||||
}
|
||||
|
||||
func testServerStatusPolicyPromotesDemotesAndPreservesActiveOrChangedRecords() {
|
||||
let matched = makeStatusRecord(id: "matched", clientPhotoId: "server-id", status: .failed)
|
||||
let missing = makeStatusRecord(id: "missing", clientPhotoId: "missing-id", status: .uploaded)
|
||||
let active = makeStatusRecord(id: "active", clientPhotoId: "active-id", status: .uploaded)
|
||||
let changedBaseline = makeStatusRecord(id: "changed", clientPhotoId: "changed-id", status: .uploaded)
|
||||
var changed = changedBaseline
|
||||
changed.progress = 37
|
||||
|
||||
let result = TravelAlbumOTGServerStatusPolicy.reconcile(
|
||||
records: [matched, missing, active, changed],
|
||||
baselineRecordsById: [
|
||||
"matched": matched,
|
||||
"missing": missing,
|
||||
"active": active,
|
||||
"changed": changedBaseline,
|
||||
],
|
||||
activePhotoIds: ["active"],
|
||||
serverClientPhotoIds: [" SERVER-ID "],
|
||||
now: 9
|
||||
)
|
||||
let byId = Dictionary(uniqueKeysWithValues: result.map { ($0.id, $0) })
|
||||
|
||||
XCTAssertEqual(byId["matched"]?.status, .uploaded)
|
||||
XCTAssertEqual(byId["matched"]?.progress, 100)
|
||||
XCTAssertEqual(byId["missing"]?.status, .pending)
|
||||
XCTAssertEqual(byId["active"]?.status, .uploaded)
|
||||
XCTAssertEqual(byId["changed"]?.status, .uploaded)
|
||||
}
|
||||
|
||||
private func makeStatusRecord(
|
||||
id: String,
|
||||
clientPhotoId: String,
|
||||
status: TravelAlbumOTGUploadStatus
|
||||
) -> TravelAlbumOTGPhotoRecord {
|
||||
TravelAlbumOTGPhotoRecord(
|
||||
id: id,
|
||||
clientPhotoId: clientPhotoId,
|
||||
fileName: "\(id).JPG",
|
||||
localPath: "",
|
||||
capturedAt: "2026-07-16 12:00:00",
|
||||
fileSizeBytes: 1,
|
||||
status: status,
|
||||
progress: status == .uploaded ? 100 : 0,
|
||||
albumId: 33,
|
||||
userId: "u1",
|
||||
remoteUrl: "https://cdn/\(id).jpg",
|
||||
updatedAt: 1
|
||||
)
|
||||
}
|
||||
|
||||
private func makeStore(root: URL) -> TravelAlbumOTGPhotoStore {
|
||||
TravelAlbumOTGPhotoStore(
|
||||
context: TravelAlbumOTGStorageContext(
|
||||
|
||||
Reference in New Issue
Block a user