feat(ios): add cross-instance message center
This commit is contained in:
@@ -0,0 +1,78 @@
|
||||
import XCTest
|
||||
|
||||
@testable import MultiSimAdmin
|
||||
|
||||
final class MessageServiceTests: XCTestCase {
|
||||
func testParsesUpstreamEnvelopeAndNormalizesMessages() async throws {
|
||||
let store = InstanceSessionStore()
|
||||
let client = MessageTestClient()
|
||||
let service = MessageService(client: client, sessions: store)
|
||||
let instance = Self.instance()
|
||||
await store.set(instance.id, origin: instance.origin, cookie: "simadmin_session=token")
|
||||
|
||||
let page = try await service.messages([instance], limit: 2)
|
||||
|
||||
XCTAssertEqual(client.routes.first, .smsList(limit: 2, offset: 0, direction: nil))
|
||||
XCTAssertEqual(page.messages.count, 1)
|
||||
let message = try XCTUnwrap(page.messages.first)
|
||||
XCTAssertEqual(message.id, "42")
|
||||
XCTAssertEqual(message.instanceID, instance.id)
|
||||
XCTAssertEqual(message.instanceName, "Message Node")
|
||||
XCTAssertEqual(message.phoneNumber, "13800138000")
|
||||
XCTAssertEqual(message.content, "device ready")
|
||||
XCTAssertEqual(message.direction, .outgoing)
|
||||
XCTAssertEqual(message.status, "sent")
|
||||
}
|
||||
|
||||
func testSendUsesStoredSessionAndRejectsInvalidInput() async throws {
|
||||
let store = InstanceSessionStore()
|
||||
let client = MessageTestClient()
|
||||
let service = MessageService(client: client, sessions: store)
|
||||
let instance = Self.instance()
|
||||
await store.set(instance.id, origin: instance.origin, cookie: "simadmin_session=token")
|
||||
|
||||
try await service.send(instance, phoneNumber: "13800138000", content: "hello")
|
||||
XCTAssertEqual(client.routes.last, .smsSend(phoneNumber: "13800138000", content: "hello"))
|
||||
|
||||
do {
|
||||
try await service.send(instance, phoneNumber: "", content: "hello")
|
||||
XCTFail("Empty phone number should fail.")
|
||||
} catch {
|
||||
XCTAssertEqual(error as? MessageServiceError, .invalidInput)
|
||||
}
|
||||
}
|
||||
|
||||
private static func instance() -> Instance {
|
||||
Instance(
|
||||
id: UUID(),
|
||||
name: "Message Node",
|
||||
origin: URL(string: "http://192.168.1.20:3000")!,
|
||||
configRevision: 1,
|
||||
createdAt: Date(),
|
||||
updatedAt: Date()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private final class MessageTestClient: SimAdminClientProtocol, @unchecked Sendable {
|
||||
var routes: [UpstreamRoute] = []
|
||||
|
||||
func send(_ route: UpstreamRoute, baseURL: URL, cookie: String?) async throws -> UpstreamResponse {
|
||||
routes.append(route)
|
||||
guard cookie == "simadmin_session=token" else {
|
||||
throw UpstreamError.unauthorized
|
||||
}
|
||||
switch route {
|
||||
case .smsList:
|
||||
let json = """
|
||||
{"status":"ok","data":{"total":1,"messages":[{"id":42,"phone_number":"13800138000",
|
||||
"content":"device ready","direction":"outgoing","status":"sent","timestamp":"2026-09-08T10:00:00Z"}]}}
|
||||
"""
|
||||
return UpstreamResponse(status: 200, data: Data(json.utf8))
|
||||
case .smsSend:
|
||||
return UpstreamResponse(status: 200, data: Data(#"{"status":"ok"}"#.utf8))
|
||||
default:
|
||||
return UpstreamResponse(status: 200, data: Data("{}".utf8))
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user