test(apple): CoreGateway seam, XCTest suite, and CI

- Introduce a CoreGateway protocol so feature models depend on a seam
  (CoreRepository conforms); enables faking the core in tests
- Add a VniDropTests target with 42 tests mirroring the KMP suites:
  approval coordinator, send/receive/settings/app models, preferences,
  file previews, invitation decode, message queue, error mapping
- Add a fake gateway/file-system/device-info and fixtures
- Add .github/workflows/apple.yml: build the Rust core, generate the
  project, and run the tests on an iOS Simulator
This commit is contained in:
2026-07-19 23:48:11 +02:00
parent e35c8c840a
commit 17099d32f2
23 changed files with 771 additions and 20 deletions

View File

@@ -0,0 +1,43 @@
import XCTest
@testable import VniDrop
/// Ports `feature/receive/ExternalInvitationControllerTest.kt` + the `.vnd`
/// decode/filename helpers.
@MainActor
final class InvitationTests: XCTestCase {
func testValidateInvitationAcceptsValid() {
guard case .success(let raw) = validateInvitation("some-ticket") else { return XCTFail("expected success") }
XCTAssertEqual(raw, "some-ticket")
}
func testValidateRejectsEmpty() {
guard case .failure(let error) = validateInvitation(" \n ") else { return XCTFail("expected failure") }
XCTAssertTrue((error as? InvitationError) != nil)
}
func testValidateRejectsTooLarge() {
let big = String(repeating: "a", count: maxVniDropInvitationBytes + 1)
guard case .failure = validateInvitation(big) else { return XCTFail("expected failure") }
}
func testDecodeInvitationBytesRoundTrip() throws {
let text = "vnidrop://ticket-abc"
let decoded = try decodeInvitationBytes(Data(text.utf8))
XCTAssertEqual(decoded, text)
}
func testDecodeRejectsEmptyData() {
XCTAssertThrowsError(try decodeInvitationBytes(Data()))
}
func testDecodeRejectsInvalidUtf8() {
XCTAssertThrowsError(try decodeInvitationBytes(Data([0xFF, 0xFE, 0xFD])))
}
func testInvitationFileNameSanitizes() {
XCTAssertEqual(invitationFileName("My Photos"), "My-Photos.vnd")
XCTAssertEqual(invitationFileName(" "), "invitation.vnd")
XCTAssertTrue(invitationFileName("a/b:c*d").hasSuffix(".vnd"))
}
}