import Foundation import TeleTuiIOSCore @main struct TeleTuiIOSSmokeTests { static func main() async throws { try await authFlowMatchesAllInteractiveStates() try await chatListLoadsDeterministicFakeDataAndFilters() try await chatDetailLoadsAndSendsMessage() try await messageActionsCoverEditReplyForwardReactDeleteSearchAndCopy() try await profileLoadsFromSelectedChat() appStorageUsesApplicationSupportStyleAccountPaths() print("TeleTuiIOS smoke tests passed") } @MainActor private static func authFlowMatchesAllInteractiveStates() async throws { let account = Account(id: "fake", displayName: "Fake", databasePath: URL(fileURLWithPath: "/tmp/fake")) let store = SessionStore(account: account, bridge: FakeSessionBridge()) let viewModel = AuthViewModel(store: store) await store.refreshAuthState() precondition(store.authState == .waitPhoneNumber) viewModel.phone = "+10000000000" await viewModel.submitCurrentStep() precondition(store.authState == .waitCode) viewModel.code = "12345" await viewModel.submitCurrentStep() precondition(store.authState == .waitPassword) viewModel.password = "secret" await viewModel.submitCurrentStep() precondition(store.authState == .ready) } @MainActor private static func chatListLoadsDeterministicFakeDataAndFilters() async throws { let bridge = FakeSessionBridge(auth: .ready) let viewModel = ChatListViewModel(bridge: bridge) await viewModel.load() precondition(viewModel.chats.map(\.title) == ["Saved Messages", "iOS Team"]) viewModel.searchText = "team" precondition(viewModel.filteredChats.map(\.title) == ["iOS Team"]) } @MainActor private static func chatDetailLoadsAndSendsMessage() async throws { let bridge = FakeSessionBridge(auth: .ready) let chat = try await bridge.loadChats(folderId: nil)[0] let viewModel = ChatViewModel(chat: chat, bridge: bridge) await viewModel.load() precondition(viewModel.messages.count == 1) viewModel.composeText = "Hi from SwiftUI" await viewModel.send() precondition(viewModel.messages.last?.text == "Hi from SwiftUI") precondition(viewModel.composeText.isEmpty) } @MainActor private static func messageActionsCoverEditReplyForwardReactDeleteSearchAndCopy() async throws { let bridge = FakeSessionBridge(auth: .ready) let chat = try await bridge.loadChats(folderId: nil)[0] let viewModel = ChatViewModel(chat: chat, bridge: bridge) await viewModel.load() guard let first = viewModel.messages.first else { preconditionFailure("fake chat should contain a message") } await viewModel.edit(message: first, text: "Edited text") precondition(viewModel.messages.first?.text == "Edited text") precondition(viewModel.messages.first?.editDate != nil) viewModel.beginReply(to: viewModel.messages[0]) viewModel.composeText = "Reply text" await viewModel.send() precondition(viewModel.messages.last?.replyText == "Reply to #1") await viewModel.react(message: viewModel.messages[0], reaction: "👍") precondition(viewModel.messages[0].reactions.first?.emoji == "👍") viewModel.searchText = "reply" await viewModel.search() precondition(viewModel.searchResults.count == 1) await viewModel.copyPayload(for: viewModel.messages[0]) precondition(viewModel.copiedPayload == "Edited text") await viewModel.forward(message: viewModel.messages[0], to: 2) let forwarded = try await bridge.loadHistory(chatId: 2) precondition(forwarded.contains { $0.forwardSenderName == "Alice" && $0.text == "Edited text" }) await viewModel.delete(message: viewModel.messages[0]) precondition(!viewModel.messages.contains { $0.id == 1 }) } @MainActor private static func profileLoadsFromSelectedChat() async throws { let bridge = FakeSessionBridge(auth: .ready) let viewModel = ProfileViewModel(bridge: bridge) await viewModel.load(chatId: 1) precondition(viewModel.profile?.title == "Saved Messages") precondition(viewModel.profile?.username == "saved") } private static func appStorageUsesApplicationSupportStyleAccountPaths() { let root = URL(fileURLWithPath: "/tmp/TeleTuiIOS") let paths = AppStoragePaths(root: root) precondition(paths.databasePath(for: "work").path == "/tmp/TeleTuiIOS/Accounts/work/tdlib") } }