import Foundation import ManaCore import Testing @testable import ManaAuthUI @Suite("Account-ViewModels (ChangeEmail/ChangePW/Delete)") @MainActor struct AccountViewModelTests { /// Simuliert eingeloggten User über den echten `signIn`-Pfad /// mit Mock-URL, weil `persistSession` internal in ManaCore ist. private func signedInAuth() async -> MockedAuth { let mocked = makeMockedAuth() let access = "eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJ1MSIsImV4cCI6MjAwMDAwMDAwMH0.sig" mocked.setHandler { _ in (200, Data(#"{"accessToken":"\#(access)","refreshToken":"r"}"#.utf8)) } await mocked.auth.signIn(email: "u@x.de", password: "pw") return mocked } // MARK: - ChangeEmail @Test("changeEmail erfolgreich → .done") func changeEmailSuccess() async { let mocked = await signedInAuth() let model = ChangeEmailViewModel(auth: mocked.auth, callbackUniversalLink: nil) model.newEmail = "neu@x.de" mocked.setHandler { _ in (200, Data(#"{"success":true}"#.utf8)) } await model.submit() #expect(model.status == .done) } @Test("changeEmail ohne Session → .error mit notSignedIn") func changeEmailNoSession() async { let model = ChangeEmailViewModel(auth: makeMockedAuth().auth, callbackUniversalLink: nil) model.newEmail = "neu@x.de" await model.submit() if case let .error(message) = model.status { #expect(message == "Nicht angemeldet") } else { Issue.record("Expected .error, got \(model.status)") } } // MARK: - ChangePassword @Test("changePassword erfolgreich → .done und cleared Felder") func changePasswordSuccess() async { let mocked = await signedInAuth() let model = ChangePasswordViewModel(auth: mocked.auth) model.currentPassword = "alt-lang-genug" model.newPassword = "neu-lang-genug" model.confirmPassword = "neu-lang-genug" mocked.setHandler { _ in (200, Data(#"{"success":true}"#.utf8)) } await model.submit() #expect(model.status == .done) #expect(model.currentPassword == "") #expect(model.newPassword == "") #expect(model.confirmPassword == "") } @Test("changePassword Mismatch → canSubmit false") func changePasswordMismatch() { let model = ChangePasswordViewModel(auth: makeMockedAuth().auth) model.currentPassword = "alt" model.newPassword = "neu-lang-genug" model.confirmPassword = "anders-lang-genug" #expect(model.canSubmit == false) } // MARK: - DeleteAccount @Test("deleteAccount mit korrektem Bestätigungswort → .done") func deleteAccountSuccess() async { let mocked = await signedInAuth() let model = DeleteAccountViewModel(auth: mocked.auth) model.confirmationText = "LÖSCHEN" model.password = "pw" mocked.setHandler { request in #expect(request.httpMethod == "DELETE") return (200, Data(#"{"success":true}"#.utf8)) } await model.submit() #expect(model.status == .done) #expect(mocked.auth.status == .signedOut) } @Test("deleteAccount mit falschem Bestätigungswort → canSubmit false") func deleteAccountWrongConfirmation() { let model = DeleteAccountViewModel(auth: makeMockedAuth().auth) model.confirmationText = "delete" model.password = "pw" #expect(model.canSubmit == false) model.confirmationText = "LÖSCHEN" #expect(model.canSubmit == true) // Case-insensitive model.confirmationText = "löschen" #expect(model.canSubmit == true) } }