import Foundation import AppKit import WebKit import Testing @testable import MikeMail @MainActor struct MailPresentationTests { @Test func htmlAlternativeAndAttachmentsSurviveArchive() throws { let root = FileManager.default.temporaryDirectory.appending(path: UUID().uuidString) defer { try? FileManager.default.removeItem(at: root) } let html = "
Grüße Welt
" let bytes = Data([0, 1, 254, 255]) let raw = try MIME.compose(from: "from@example.com", to: ["to@example.com"], subject: "HTML", body: "Grüße Welt", attachments: [MailAttachment(name: "Probe.bin", mimeType: "application/octet-stream", data: bytes)], htmlBody: html) let archive = try MailArchive(root: root) try archive.store(raw: raw, folderID: "inbox", validity: "1", uid: "1", flags: []) let message = try #require(archive.messages(folderID: "inbox").first) #expect(message.body == "Grüße Welt") #expect(message.htmlBody == html) #expect(message.attachments.first?.data == bytes) let htmlOnly = MIME.parse(Data("Content-Type: text/html; charset=utf-8\r\n\r\nHallo Welt
".utf8), id: "html") #expect(htmlOnly.htmlBody?.contains("Hallo") == true) #expect(htmlOnly.body.contains("Hallo Welt")) } @Test func selectedFormattingExportsHTMLWithoutChangingOtherText() throws { let editor = MailEditorModel() let view = NSTextView() view.string = "Hallo Welt" view.font = NSFont(name: "Helvetica", size: 14) editor.textView = view view.setSelectedRange(NSRange(location: 0, length: 5)) editor.toggleTrait(.boldFontMask, enabled: true) editor.setAttribute(.foregroundColor, value: NSColor(srgbRed: 1, green: 0, blue: 0, alpha: 1)) editor.setFont(size: 24) let selected = try #require(view.textStorage?.attribute(.font, at: 0, effectiveRange: nil) as? NSFont) let remaining = try #require(view.textStorage?.attribute(.font, at: 6, effectiveRange: nil) as? NSFont) #expect(NSFontManager.shared.traits(of: selected).contains(.boldFontMask)) #expect(selected.pointSize == 24) #expect(remaining.pointSize == 14) let html = try editor.html() #expect(html.contains("24")) // Cocoa's HTML writer converts color profiles, so compare the exported color with tolerance. let colorRange = try #require(html.range(of: "#[0-9a-fA-F]{6}", options: .regularExpression)) let rgb = try #require(UInt32(html[colorRange].dropFirst(), radix: 16)) #expect((rgb >> 16) > 230 && ((rgb >> 8) & 255) < 25 && (rgb & 255) < 25) #expect(editor.plainText == "Hallo Welt") } @Test func accountOrderPersistsInBothDirections() throws { let root = FileManager.default.temporaryDirectory.appending(path: UUID().uuidString) defer { try? FileManager.default.removeItem(at: root) } let archive = try MailArchive(root: root) let accounts = ["A", "B", "C"].map { MailAccount(name: $0) } try archive.saveConfiguration(ArchiveConfiguration(accounts: accounts, folders: [:], recipients: [])) let store = MailStore(archive: archive) store.moveAccounts(from: IndexSet(integer: 0), to: 3) #expect(store.accounts.map(\.name) == ["B", "C", "A"]) #expect(try MailArchive(root: root).configuration()?.accounts.map(\.name) == ["B", "C", "A"]) store.moveAccounts(from: IndexSet(integer: 2), to: 0) #expect(store.accounts == accounts) #expect(try archive.configuration()?.accounts == accounts) } @Test func senderAndDatePresentation() throws { #expect(MailDisplay.sender("\"Max Muster\"HTML