macsync/@packages/inotes/Tests/INoteSyncTests/SenderDispatchTests.swift

135 lines
4.7 KiB
Swift

import Foundation
import MacSyncShared
import Testing
@testable import INoteSync
final class FakeNoteApplier: NoteApplying, @unchecked Sendable {
enum Call: Equatable {
case create(NoteSendPayload)
case update(NoteSendPayload)
case delete(NoteSendPayload)
}
private(set) var calls: [Call] = []
var nextResult: SendQueueApplyResult = .sent
func create(_ payload: NoteSendPayload) async -> SendQueueApplyResult {
calls.append(.create(payload))
return nextResult
}
func update(_ payload: NoteSendPayload) async -> SendQueueApplyResult {
calls.append(.update(payload))
return nextResult
}
func delete(_ payload: NoteSendPayload) async -> SendQueueApplyResult {
calls.append(.delete(payload))
return nextResult
}
}
@Suite("NoteSender dispatch")
@MainActor
struct SenderDispatchTests {
private func item(_ action: String, _ payload: NoteSendPayload = NoteSendPayload()) -> PendingNoteSend {
PendingNoteSend(id: "i-1", action: action, payload: payload, createdAt: "2026-05-13T00:00:00Z")
}
@Test("create_note dispatches to create")
func dispatchCreate() async {
let fake = FakeNoteApplier()
let sender = NoteSender(applier: fake)
let p = NoteSendPayload(folder: "Notes", name: "Hi", body: "<p>x</p>")
let result = await sender.apply(item("create_note", p))
guard case .sent = result else { Issue.record("expected .sent"); return }
#expect(fake.calls == [.create(p)])
}
@Test("update_note dispatches to update")
func dispatchUpdate() async {
let fake = FakeNoteApplier()
let sender = NoteSender(applier: fake)
let p = NoteSendPayload(noteIdentifier: "id-1", body: "<p>new</p>")
_ = await sender.apply(item("update_note", p))
#expect(fake.calls == [.update(p)])
}
@Test("delete_note dispatches to delete")
func dispatchDelete() async {
let fake = FakeNoteApplier()
let sender = NoteSender(applier: fake)
let p = NoteSendPayload(noteIdentifier: "id-1")
_ = await sender.apply(item("delete_note", p))
#expect(fake.calls == [.delete(p)])
}
@Test("unknown action returns .failed without invoking applier")
func unknownAction() async {
let fake = FakeNoteApplier()
let sender = NoteSender(applier: fake)
let result = await sender.apply(item("frobnicate"))
guard case .failed(let reason) = result else {
Issue.record("expected .failed")
return
}
#expect(reason.contains("unknown action"))
#expect(fake.calls.isEmpty)
}
@Test("propagates .failed from applier")
func propagatesFailure() async {
let fake = FakeNoteApplier()
fake.nextResult = .failed(reason: "boom")
let sender = NoteSender(applier: fake)
let result = await sender.apply(item("create_note", NoteSendPayload(name: "n")))
guard case .failed(let reason) = result else {
Issue.record("expected .failed")
return
}
#expect(reason == "boom")
}
}
@Suite("AppleScriptNoteApplier missing-field guards")
struct AppleScriptNoteApplierGuards {
@Test("create without name returns .failed")
func createMissingName() async {
let applier = AppleScriptNoteApplier()
let result = await applier.create(NoteSendPayload(body: "x"))
guard case .failed(let reason) = result else {
Issue.record("expected .failed"); return
}
#expect(reason.contains("name"))
}
@Test("update without noteIdentifier returns .failed")
func updateMissingId() async {
let applier = AppleScriptNoteApplier()
let result = await applier.update(NoteSendPayload(body: "x"))
guard case .failed(let reason) = result else {
Issue.record("expected .failed"); return
}
#expect(reason.contains("noteIdentifier"))
}
@Test("update with id but no fields returns .failed")
func updateNoFields() async {
let applier = AppleScriptNoteApplier()
let result = await applier.update(NoteSendPayload(noteIdentifier: "id-1"))
guard case .failed(let reason) = result else {
Issue.record("expected .failed"); return
}
#expect(reason.contains("no fields"))
}
@Test("delete without noteIdentifier returns .failed")
func deleteMissingId() async {
let applier = AppleScriptNoteApplier()
let result = await applier.delete(NoteSendPayload())
guard case .failed(let reason) = result else {
Issue.record("expected .failed"); return
}
#expect(reason.contains("noteIdentifier"))
}
}