mana-swift-event-sync/Tests/ManaEventSyncTests/CoreTests.swift
Till JS 630e4254c7 0.9.0: 402-Handling (kein aktives Cloud-Sync-Abo)
EventSyncError.subscriptionRequired (402-Mapping in SyncHTTPClient),
onSyncRequired-Hook + isSyncRequired. Push/Pull: Events bleiben in der
Outbox (kein Verlust, kein Attempt-Increment), event-getriggerte
Push/Pull unterdrückt, Poll prüft weiter (force) → Auto-Recovery.
Wire-Parität zu @mana/event-sync 0.9.0. swift build + tests grün.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-17 15:26:20 +02:00

83 lines
3.2 KiB
Swift

import XCTest
@testable import ManaEventSync
final class CoreTests: XCTestCase {
func testULIDFormat() {
let id = ULID.generate()
XCTAssertEqual(id.count, 26)
let alphabet = Set("0123456789ABCDEFGHJKMNPQRSTVWXYZ")
XCTAssertTrue(id.allSatisfy { alphabet.contains($0) })
}
func testULIDsAreUnique() {
let ids = (0 ..< 100).map { _ in ULID.generate() }
XCTAssertEqual(Set(ids).count, ids.count)
}
func testJWTSubjectExtraction() {
// payload = base64url({"sub":"user_42"})
let token = "h.eyJzdWIiOiJ1c2VyXzQyIn0.s"
XCTAssertEqual(JWTSubject.subject(of: token), "user_42")
}
func testJWTSubjectRejectsMalformed() {
XCTAssertNil(JWTSubject.subject(of: "not-a-jwt"))
XCTAssertNil(JWTSubject.subject(of: "a.b"))
}
func testJSONValueRoundTrip() throws {
struct Sample: Codable, Equatable {
let name: String
let count: Int
let tags: [String]
let nested: [String: Double]
}
let sample = Sample(name: "pasta", count: 3, tags: ["a", "b"], nested: ["kcal": 600])
let value = try JSONValue.from(sample)
let back: Sample = try value.decode()
XCTAssertEqual(sample, back)
XCTAssertEqual(value.get("name"), .string("pasta"))
}
func testEventEnvelopeCodableRoundTrip() throws {
let envelope = EventEnvelope(
eventId: ULID.generate(),
aggregateId: "highlight:01HX",
appId: "pageta",
eventType: "HighlightCreated",
eventVersion: 1,
occurredAt: "2026-05-25T10:00:00.000Z",
actor: .user(principalId: "user_42"),
attributedToUserId: "user_42",
origin: "user",
idempotencyKey: "idem-1",
payload: .object(["text": .string("hallo")])
)
let data = try JSONEncoder().encode(envelope)
let decoded = try JSONDecoder().decode(EventEnvelope.self, from: data)
XCTAssertEqual(envelope, decoded)
}
func testEnvelopeAttributedRewrite() {
let envelope = EventEnvelope(
eventId: "e1", aggregateId: "a:1", appId: "pageta", eventType: "X",
eventVersion: 1, occurredAt: "t", actor: .user(principalId: "anon:guest-1"),
attributedToUserId: "anon:guest-1", origin: "user", idempotencyKey: "k", payload: .null
)
let claimed = envelope.attributed(to: "user_42")
XCTAssertEqual(claimed.attributedToUserId, "user_42")
XCTAssertEqual(claimed.eventId, "e1")
}
func testSubscriptionRequiredErrorIsDistinct() {
// 402-Mapping: eigener, von schemaOutdated/transport unterscheidbarer
// Fall mit nutzbarer Beschreibung (Banner-Text der App).
XCTAssertEqual(EventSyncError.subscriptionRequired, EventSyncError.subscriptionRequired)
XCTAssertNotEqual(EventSyncError.subscriptionRequired, EventSyncError.schemaOutdated)
XCTAssertNotEqual(
EventSyncError.subscriptionRequired,
EventSyncError.transport(status: 402, body: nil)
)
XCTAssertNotNil(EventSyncError.subscriptionRequired.errorDescription)
}
}