mirror of
https://github.com/Cocoanetics/SwiftMail.git
synced 2026-03-17 20:02:25 +00:00
Modernized unit tests
This commit is contained in:
@@ -2,6 +2,18 @@ import Foundation
|
||||
import Testing
|
||||
@testable import SwiftMail
|
||||
|
||||
// Use existing tag definitions and add new ones
|
||||
extension Tag {
|
||||
@Tag static var encoding: Self
|
||||
@Tag static var decoding: Self
|
||||
@Tag static var imap: Self
|
||||
@Tag static var performance: Self
|
||||
@Tag static var mime: Self
|
||||
@Tag static var fileHandling: Self
|
||||
@Tag static var security: Self
|
||||
}
|
||||
|
||||
@Suite("Quoted-Printable Encoding Tests", .tags(.imap, .encoding, .decoding))
|
||||
struct QuotedPrintableTests {
|
||||
|
||||
// MARK: - Test Resources
|
||||
@@ -24,8 +36,8 @@ struct QuotedPrintableTests {
|
||||
|
||||
// MARK: - Basic Decoding Tests
|
||||
|
||||
@Test
|
||||
func testBasicQuotedPrintableDecoding() {
|
||||
@Test("Basic quoted-printable decoding", .tags(.decoding))
|
||||
func basicQuotedPrintableDecoding() {
|
||||
// Test basic quoted-printable decoding
|
||||
let encoded = "Hello=20World"
|
||||
#expect(encoded.decodeQuotedPrintable() == "Hello World")
|
||||
@@ -43,8 +55,8 @@ struct QuotedPrintableTests {
|
||||
#expect(equalsSign.decodeQuotedPrintable() == "3=2+1")
|
||||
}
|
||||
|
||||
@Test
|
||||
func testEncodingDetection() {
|
||||
@Test("Encoding detection", .tags(.encoding))
|
||||
func encodingDetection() {
|
||||
// Test ISO-8859-1 encoding detection
|
||||
let isoContent = "Content-Type: text/plain; charset=iso-8859-1\r\n\r\nThis has special chars: =E4=F6=FC=DF"
|
||||
#expect(isoContent.detectCharsetEncoding() == .isoLatin1)
|
||||
@@ -62,9 +74,8 @@ struct QuotedPrintableTests {
|
||||
#expect(noCharset.detectCharsetEncoding() == .utf8)
|
||||
}
|
||||
|
||||
// Skip this test for now as the implementation might be different
|
||||
@Test
|
||||
func testAutoDetectionDecoding() {
|
||||
@Test("Auto-detection decoding", .tags(.decoding))
|
||||
func autoDetectionDecoding() {
|
||||
// Simple test with basic content
|
||||
let basicContent = "Hello=20World"
|
||||
#expect(basicContent.decodeQuotedPrintable() == "Hello World")
|
||||
@@ -72,8 +83,8 @@ struct QuotedPrintableTests {
|
||||
|
||||
// MARK: - MIME Header Tests
|
||||
|
||||
@Test
|
||||
func testMIMEHeaderDecoding() {
|
||||
@Test("MIME header decoding", .tags(.decoding, .mime))
|
||||
func mimeHeaderDecoding() {
|
||||
// Test Q-encoded header
|
||||
let qEncoded = "=?UTF-8?Q?Hello=20World?="
|
||||
#expect(qEncoded.decodeMIMEHeader() == "Hello World")
|
||||
@@ -94,8 +105,8 @@ struct QuotedPrintableTests {
|
||||
|
||||
// MARK: - HTML File Tests
|
||||
|
||||
@Test
|
||||
func testISO8859HTMLFile() throws {
|
||||
@Test("ISO-8859-1 HTML file processing", .tags(.fileHandling))
|
||||
func iso8859HTMLFile() throws {
|
||||
let content = try loadResourceContent(name: "sample_quoted_printable", withExtension: "html")
|
||||
|
||||
// Test that the content was loaded
|
||||
@@ -109,8 +120,8 @@ struct QuotedPrintableTests {
|
||||
#expect(simpleTest.decodeQuotedPrintable() == "Hello World")
|
||||
}
|
||||
|
||||
@Test
|
||||
func testUTF8HTMLFile() throws {
|
||||
@Test("UTF-8 HTML file processing", .tags(.fileHandling))
|
||||
func utf8HTMLFile() throws {
|
||||
let content = try loadResourceContent(name: "sample_quoted_printable_utf8", withExtension: "html")
|
||||
|
||||
// Test that the content was loaded
|
||||
@@ -124,8 +135,8 @@ struct QuotedPrintableTests {
|
||||
#expect(simpleTest.decodeQuotedPrintable() == "Hello World")
|
||||
}
|
||||
|
||||
@Test
|
||||
func testMIMEHeaderFile() throws {
|
||||
@Test("MIME header file processing", .tags(.fileHandling, .mime))
|
||||
func mimeHeaderFile() throws {
|
||||
let content = try loadResourceContent(name: "sample_mime_header", withExtension: "txt")
|
||||
|
||||
// Split the content into lines
|
||||
@@ -155,6 +166,39 @@ struct QuotedPrintableTests {
|
||||
throw TestFailure("Subject header not found")
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Additional Edge Cases
|
||||
|
||||
@Test("Edge cases and malformed input", .tags(.decoding, .security))
|
||||
func edgeCasesAndMalformedInput() {
|
||||
// Test empty string
|
||||
#expect("".decodeQuotedPrintable() == "")
|
||||
|
||||
// Test string without encoding
|
||||
#expect("Plain text".decodeQuotedPrintable() == "Plain text")
|
||||
|
||||
// Test malformed encoding (incomplete hex) - should return nil for invalid input
|
||||
let malformed = "Hello=2World" // Missing second hex digit
|
||||
let result = malformed.decodeQuotedPrintable()
|
||||
#expect(result == nil, "Should return nil for malformed input")
|
||||
|
||||
// Test with invalid hex characters - should return nil for invalid input
|
||||
let invalidHex = "Hello=ZZ"
|
||||
let invalidResult = invalidHex.decodeQuotedPrintable()
|
||||
#expect(invalidResult == nil, "Should return nil for invalid hex")
|
||||
}
|
||||
|
||||
@Test("Performance with large content", .tags(.performance, .decoding))
|
||||
func performanceWithLargeContent() {
|
||||
// Create a large quoted-printable encoded string
|
||||
let baseString = "This=20is=20a=20test=20string=20with=20spaces=0D=0A"
|
||||
let largeContent = String(repeating: baseString, count: 1000)
|
||||
|
||||
// Test that decoding completes without hanging
|
||||
let decoded = largeContent.decodeQuotedPrintable()
|
||||
#expect(decoded != nil, "Should decode large content successfully")
|
||||
#expect(decoded?.contains("This is a test string with spaces") ?? false, "Should contain expected decoded content")
|
||||
}
|
||||
}
|
||||
|
||||
// Custom error type for test failures
|
||||
|
||||
@@ -1,51 +1,152 @@
|
||||
// String+EmailTests.swift
|
||||
// Tests for email validation String extension
|
||||
|
||||
import XCTest
|
||||
import Testing
|
||||
@testable import SwiftMail
|
||||
|
||||
final class StringEmailTests: XCTestCase {
|
||||
func testValidEmails() {
|
||||
// Test basic valid formats
|
||||
XCTAssertTrue("user@example.com".isValidEmail())
|
||||
XCTAssertTrue("user.name@example.com".isValidEmail())
|
||||
XCTAssertTrue("user+tag@example.com".isValidEmail())
|
||||
XCTAssertTrue("user@subdomain.example.com".isValidEmail())
|
||||
XCTAssertTrue("123@example.com".isValidEmail())
|
||||
XCTAssertTrue("user@example.co.uk".isValidEmail())
|
||||
|
||||
// Test edge cases that should be valid
|
||||
XCTAssertTrue("a@b.cc".isValidEmail()) // Minimal length
|
||||
XCTAssertTrue("disposable.style.email.with+symbol@example.com".isValidEmail())
|
||||
XCTAssertTrue("other.email-with-hyphen@example.com".isValidEmail())
|
||||
XCTAssertTrue("fully-qualified-domain@example.com".isValidEmail())
|
||||
XCTAssertTrue("user.name+tag+sorting@example.com".isValidEmail())
|
||||
XCTAssertTrue("x@example.com".isValidEmail()) // One-letter local-part
|
||||
XCTAssertTrue("example-indeed@strange-example.com".isValidEmail())
|
||||
XCTAssertTrue("example@s.example".isValidEmail()) // Short but valid domain
|
||||
// Use existing tag definitions
|
||||
extension Tag {
|
||||
@Tag static var validation: Self
|
||||
@Tag static var security: Self
|
||||
}
|
||||
|
||||
@Suite("String Email Validation Tests", .tags(.core, .validation))
|
||||
struct StringEmailTests {
|
||||
|
||||
@Test("Valid email addresses should pass validation", .tags(.validation),
|
||||
arguments: [
|
||||
"user@example.com",
|
||||
"user.name@example.com",
|
||||
"user+tag@example.com",
|
||||
"user@subdomain.example.com",
|
||||
"123@example.com",
|
||||
"user@example.co.uk",
|
||||
"a@b.cc", // Minimal length
|
||||
"disposable.style.email.with+symbol@example.com",
|
||||
"other.email-with-hyphen@example.com",
|
||||
"fully-qualified-domain@example.com",
|
||||
"user.name+tag+sorting@example.com",
|
||||
"x@example.com", // One-letter local-part
|
||||
"example-indeed@strange-example.com",
|
||||
"example@s.example", // Short but valid domain
|
||||
"test.email.with+symbol@example.com",
|
||||
"user123@test-domain.org"
|
||||
])
|
||||
func validEmails(email: String) {
|
||||
#expect(email.isValidEmail(), "'\(email)' should be a valid email address")
|
||||
}
|
||||
|
||||
func testInvalidEmails() {
|
||||
// Test basic invalid formats
|
||||
XCTAssertFalse("".isValidEmail())
|
||||
XCTAssertFalse("@example.com".isValidEmail())
|
||||
XCTAssertFalse("user@".isValidEmail())
|
||||
XCTAssertFalse("user@.com".isValidEmail())
|
||||
XCTAssertFalse("user@example".isValidEmail())
|
||||
XCTAssertFalse("user.example.com".isValidEmail())
|
||||
@Test("Invalid email addresses should fail validation", .tags(.validation, .security),
|
||||
arguments: [
|
||||
"",
|
||||
"@example.com",
|
||||
"user@",
|
||||
"user@.com",
|
||||
"user@example",
|
||||
"user.example.com",
|
||||
"user@exam ple.com", // Space in domain
|
||||
"user@@example.com", // Double @
|
||||
".user@example.com", // Leading dot
|
||||
"user.@example.com", // Trailing dot
|
||||
"user@example..com", // Double dot
|
||||
"user@-example.com", // Leading hyphen in domain
|
||||
"user@example-.com", // Trailing hyphen in domain
|
||||
"user@.example.com", // Leading dot in domain
|
||||
"user@example.", // Trailing dot in domain
|
||||
"user@ex*ample.com", // Invalid character
|
||||
"user@example.c", // TLD too short
|
||||
"user name@example.com", // Space in local part
|
||||
"user<script>@example.com", // Security: HTML injection attempt
|
||||
"user@example.com; DROP TABLE users;", // Security: SQL injection attempt
|
||||
"user@192.168.1.1", // IP addresses without proper format
|
||||
"user@[192.168.1.1", // Malformed IP bracket
|
||||
"user@192.168.1.1]" // Malformed IP bracket
|
||||
])
|
||||
func invalidEmails(email: String) {
|
||||
#expect(!email.isValidEmail(), "'\(email)' should be an invalid email address")
|
||||
}
|
||||
|
||||
@Test("Edge cases for email validation")
|
||||
func emailEdgeCases() {
|
||||
// Test specific edge cases individually for better diagnostics
|
||||
#expect("a@b.cc".isValidEmail(), "Minimal valid email should pass")
|
||||
#expect(!"".isValidEmail(), "Empty string should be invalid")
|
||||
#expect(!"@".isValidEmail(), "Single @ symbol should be invalid")
|
||||
#expect(!"user@@example.com".isValidEmail(), "Double @ should be invalid")
|
||||
#expect(!"user@example..com".isValidEmail(), "Double dots in domain should be invalid")
|
||||
}
|
||||
|
||||
@Test("International domain names", .tags(.validation))
|
||||
func internationalDomains() {
|
||||
// These might be valid depending on implementation
|
||||
let internationalEmails = [
|
||||
"user@münchen.de",
|
||||
"test@café.com",
|
||||
"email@測試.com"
|
||||
]
|
||||
|
||||
// Test invalid characters and formats
|
||||
XCTAssertFalse("user@exam ple.com".isValidEmail()) // Space in domain
|
||||
XCTAssertFalse("user@@example.com".isValidEmail()) // Double @
|
||||
XCTAssertFalse(".user@example.com".isValidEmail()) // Leading dot
|
||||
XCTAssertFalse("user.@example.com".isValidEmail()) // Trailing dot
|
||||
XCTAssertFalse("user@example..com".isValidEmail()) // Double dot
|
||||
XCTAssertFalse("user@-example.com".isValidEmail()) // Leading hyphen in domain
|
||||
XCTAssertFalse("user@example-.com".isValidEmail()) // Trailing hyphen in domain
|
||||
XCTAssertFalse("user@.example.com".isValidEmail()) // Leading dot in domain
|
||||
XCTAssertFalse("user@example.".isValidEmail()) // Trailing dot in domain
|
||||
XCTAssertFalse("user@ex*ample.com".isValidEmail()) // Invalid character
|
||||
XCTAssertFalse("user@example.c".isValidEmail()) // TLD too short
|
||||
XCTAssertFalse("user name@example.com".isValidEmail()) // Space in local part
|
||||
for email in internationalEmails {
|
||||
let result = email.isValidEmail()
|
||||
// Implementation might vary on international domain support
|
||||
// Just verify that the function doesn't crash and returns a boolean
|
||||
#expect(result is Bool, "Email validation should return a boolean for '\(email)'")
|
||||
}
|
||||
}
|
||||
|
||||
@Test("Security and injection protection", .tags(.security))
|
||||
func securityTests() {
|
||||
let maliciousInputs = [
|
||||
"user<script>alert('xss')</script>@example.com",
|
||||
"user'; DROP TABLE users; --@example.com",
|
||||
"user@example.com\\r\\nBCC: evil@hacker.com",
|
||||
"user@example.com\\nSubject: Spam",
|
||||
"user\\u{0000}@example.com", // Null byte injection
|
||||
"user@exam\\u{0000}ple.com"
|
||||
]
|
||||
|
||||
for maliciousEmail in maliciousInputs {
|
||||
#expect(!maliciousEmail.isValidEmail(),
|
||||
"Malicious input '\(maliciousEmail)' should be rejected")
|
||||
}
|
||||
}
|
||||
|
||||
@Test("Performance with long inputs", .tags(.validation))
|
||||
func performanceLongInputs() {
|
||||
// Test very long email addresses
|
||||
let longLocalPart = String(repeating: "a", count: 1000)
|
||||
let longEmail = "\(longLocalPart)@example.com"
|
||||
|
||||
// Should handle long inputs gracefully (likely invalid due to length)
|
||||
let result = longEmail.isValidEmail()
|
||||
#expect(!result, "Extremely long email should be invalid")
|
||||
|
||||
// Test long domain
|
||||
let longDomain = String(repeating: "test.", count: 50) + "com"
|
||||
let longDomainEmail = "user@\(longDomain)"
|
||||
let domainResult = longDomainEmail.isValidEmail()
|
||||
// Just verify it handles the input without crashing
|
||||
#expect(domainResult is Bool, "Email validation should handle long domains gracefully")
|
||||
}
|
||||
|
||||
@Test("Unicode and special character handling", .tags(.validation))
|
||||
func unicodeHandling() {
|
||||
let unicodeEmails = [
|
||||
"用户@example.com", // Chinese characters in local part
|
||||
"user@раздел.com", // Cyrillic in domain
|
||||
"tëst@example.com", // Accented characters
|
||||
"user+tag@example.com", // Plus sign (should be valid)
|
||||
"user=tag@example.com", // Equals sign
|
||||
"user%tag@example.com" // Percent sign
|
||||
]
|
||||
|
||||
for email in unicodeEmails {
|
||||
let result = email.isValidEmail()
|
||||
// Implementation may vary on unicode support
|
||||
// Just verify that the function doesn't crash and returns a boolean
|
||||
#expect(result is Bool, "Email validation should return a boolean for '\(email)'")
|
||||
}
|
||||
|
||||
// Test that plus sign is typically allowed (common use case)
|
||||
#expect("user+tag@example.com".isValidEmail(), "Plus sign should typically be allowed in email addresses")
|
||||
}
|
||||
}
|
||||
@@ -1,38 +1,43 @@
|
||||
// String+HostnameTests.swift
|
||||
// Tests for hostname-related String extensions
|
||||
|
||||
import XCTest
|
||||
import Testing
|
||||
import Foundation
|
||||
@testable import SwiftMail
|
||||
|
||||
final class StringHostnameTests: XCTestCase {
|
||||
func testLocalHostname() {
|
||||
@Suite("String Hostname Extensions Tests")
|
||||
struct StringHostnameTests {
|
||||
|
||||
@Test("Local hostname resolution returns valid hostname")
|
||||
func localHostname() {
|
||||
let hostname = String.localHostname
|
||||
|
||||
// Test that hostname is not empty
|
||||
XCTAssertFalse(hostname.isEmpty)
|
||||
#expect(!hostname.isEmpty, "Hostname should not be empty")
|
||||
|
||||
// Test that hostname is not the fallback value unless all other methods fail
|
||||
if !hostname.hasPrefix("[") && !hostname.hasSuffix("]") {
|
||||
// If it's not an IP address format, it should be a valid hostname
|
||||
XCTAssertNotEqual(hostname, "localhost")
|
||||
XCTAssertNotEqual(hostname, "swift-mail-client.local")
|
||||
#expect(hostname != "localhost", "Should not default to localhost unless necessary")
|
||||
#expect(hostname != "swift-mail-client.local", "Should not default to fallback unless necessary")
|
||||
}
|
||||
|
||||
// Test hostname format
|
||||
if hostname.hasPrefix("[") && hostname.hasSuffix("]") {
|
||||
// IP address format
|
||||
let ip = String(hostname.dropFirst().dropLast())
|
||||
XCTAssertTrue(isValidIP(ip), "Invalid IP address format: \(ip)")
|
||||
#expect(isValidIP(ip), "Invalid IP address format: \(ip)")
|
||||
} else {
|
||||
// Hostname format
|
||||
XCTAssertTrue(isValidHostname(hostname), "Invalid hostname format: \(hostname)")
|
||||
#expect(isValidHostname(hostname), "Invalid hostname format: \(hostname)")
|
||||
}
|
||||
}
|
||||
|
||||
func testLocalIPAddress() {
|
||||
@Test("Local IP address resolution returns valid IP when available")
|
||||
func localIPAddress() {
|
||||
if let ipAddress = String.localIPAddress {
|
||||
// Test that we got a valid IP address
|
||||
XCTAssertTrue(isValidIP(ipAddress), "Invalid IP address format: \(ipAddress)")
|
||||
#expect(isValidIP(ipAddress), "Invalid IP address format: \(ipAddress)")
|
||||
}
|
||||
// Note: We don't fail if no IP is found, as this might be legitimate in some environments
|
||||
}
|
||||
|
||||
@@ -1,57 +1,118 @@
|
||||
// String+MIMETests.swift
|
||||
// Tests for MIME-related String extensions
|
||||
|
||||
import XCTest
|
||||
import Testing
|
||||
@testable import SwiftMail
|
||||
|
||||
final class StringMIMETests: XCTestCase {
|
||||
func testFileExtensionForMIMEType() {
|
||||
// MARK: - Tag Definitions
|
||||
extension Tag {
|
||||
@Tag static var core: Self
|
||||
@Tag static var mime: Self
|
||||
@Tag static var fileHandling: Self
|
||||
@Tag static var crossPlatform: Self
|
||||
}
|
||||
|
||||
@Suite("String MIME Extensions Tests", .tags(.core, .mime, .fileHandling))
|
||||
struct StringMIMETests {
|
||||
|
||||
@Test("File extension for MIME type resolution", .tags(.crossPlatform))
|
||||
func fileExtensionForMIMEType() {
|
||||
#if os(macOS)
|
||||
// On macOS, we use UTType which might return different extensions
|
||||
// We only test that we get a valid extension back
|
||||
if let jpegExt = String.fileExtension(for: "image/jpeg") {
|
||||
XCTAssertTrue(["jpg", "jpeg"].contains(jpegExt))
|
||||
#expect(["jpg", "jpeg"].contains(jpegExt))
|
||||
} else {
|
||||
XCTFail("Failed to get extension for image/jpeg")
|
||||
Issue.record("Failed to get extension for image/jpeg")
|
||||
}
|
||||
#else
|
||||
// Test common MIME types
|
||||
XCTAssertEqual(String.fileExtension(for: "image/jpeg"), "jpg")
|
||||
XCTAssertEqual(String.fileExtension(for: "image/png"), "png")
|
||||
XCTAssertEqual(String.fileExtension(for: "application/pdf"), "pdf")
|
||||
XCTAssertEqual(String.fileExtension(for: "text/plain"), "txt")
|
||||
XCTAssertEqual(String.fileExtension(for: "text/html"), "html")
|
||||
#expect(String.fileExtension(for: "image/jpeg") == "jpg")
|
||||
#expect(String.fileExtension(for: "image/png") == "png")
|
||||
#expect(String.fileExtension(for: "application/pdf") == "pdf")
|
||||
#expect(String.fileExtension(for: "text/plain") == "txt")
|
||||
#expect(String.fileExtension(for: "text/html") == "html")
|
||||
|
||||
// Test Office document types
|
||||
XCTAssertEqual(String.fileExtension(for: "application/msword"), "doc")
|
||||
XCTAssertEqual(String.fileExtension(for: "application/vnd.openxmlformats-officedocument.wordprocessingml.document"), "docx")
|
||||
XCTAssertEqual(String.fileExtension(for: "application/vnd.ms-excel"), "xls")
|
||||
#expect(String.fileExtension(for: "application/msword") == "doc")
|
||||
#expect(String.fileExtension(for: "application/vnd.openxmlformats-officedocument.wordprocessingml.document") == "docx")
|
||||
#expect(String.fileExtension(for: "application/vnd.ms-excel") == "xls")
|
||||
#endif
|
||||
|
||||
// Test unknown MIME type (should work the same on all platforms)
|
||||
XCTAssertNil(String.fileExtension(for: "application/unknown"))
|
||||
#expect(String.fileExtension(for: "application/unknown") == nil)
|
||||
}
|
||||
|
||||
func testMIMETypeForFileExtension() {
|
||||
@Test("MIME type for file extension resolution", .tags(.crossPlatform))
|
||||
func mimeTypeForFileExtension() {
|
||||
// Test common file extensions (should work the same on all platforms)
|
||||
XCTAssertEqual(String.mimeType(for: "jpg"), "image/jpeg")
|
||||
XCTAssertEqual(String.mimeType(for: "jpeg"), "image/jpeg")
|
||||
XCTAssertEqual(String.mimeType(for: "png"), "image/png")
|
||||
XCTAssertEqual(String.mimeType(for: "pdf"), "application/pdf")
|
||||
XCTAssertEqual(String.mimeType(for: "txt"), "text/plain")
|
||||
XCTAssertEqual(String.mimeType(for: "html"), "text/html")
|
||||
XCTAssertEqual(String.mimeType(for: "htm"), "text/html")
|
||||
#expect(String.mimeType(for: "jpg") == "image/jpeg")
|
||||
#expect(String.mimeType(for: "jpeg") == "image/jpeg")
|
||||
#expect(String.mimeType(for: "png") == "image/png")
|
||||
#expect(String.mimeType(for: "pdf") == "application/pdf")
|
||||
#expect(String.mimeType(for: "txt") == "text/plain")
|
||||
#expect(String.mimeType(for: "html") == "text/html")
|
||||
#expect(String.mimeType(for: "htm") == "text/html")
|
||||
|
||||
// Test Office file extensions
|
||||
XCTAssertEqual(String.mimeType(for: "doc"), "application/msword")
|
||||
XCTAssertEqual(String.mimeType(for: "docx"), "application/vnd.openxmlformats-officedocument.wordprocessingml.document")
|
||||
XCTAssertEqual(String.mimeType(for: "xls"), "application/vnd.ms-excel")
|
||||
#expect(String.mimeType(for: "doc") == "application/msword")
|
||||
#expect(String.mimeType(for: "docx") == "application/vnd.openxmlformats-officedocument.wordprocessingml.document")
|
||||
#expect(String.mimeType(for: "xls") == "application/vnd.ms-excel")
|
||||
|
||||
// Test case insensitivity
|
||||
XCTAssertEqual(String.mimeType(for: "JPG"), "image/jpeg")
|
||||
XCTAssertEqual(String.mimeType(for: "PDF"), "application/pdf")
|
||||
#expect(String.mimeType(for: "JPG") == "image/jpeg")
|
||||
#expect(String.mimeType(for: "PDF") == "application/pdf")
|
||||
|
||||
// Test unknown extension
|
||||
XCTAssertEqual(String.mimeType(for: "unknown"), "application/octet-stream")
|
||||
#expect(String.mimeType(for: "unknown") == "application/octet-stream")
|
||||
}
|
||||
|
||||
@Test("Extended MIME type support", .tags(.fileHandling))
|
||||
func extendedMIMETypes() {
|
||||
// Test additional multimedia types - verify they return appropriate types
|
||||
let mp4Type = String.mimeType(for: "mp4")
|
||||
#expect(mp4Type.hasPrefix("video/"), "MP4 should be a video type, got: \(mp4Type)")
|
||||
|
||||
let mp3Type = String.mimeType(for: "mp3")
|
||||
#expect(mp3Type.hasPrefix("audio/"), "MP3 should be an audio type, got: \(mp3Type)")
|
||||
|
||||
let wavType = String.mimeType(for: "wav")
|
||||
#expect(wavType.hasPrefix("audio/"), "WAV should be an audio type, got: \(wavType)")
|
||||
|
||||
let gifType = String.mimeType(for: "gif")
|
||||
#expect(gifType.hasPrefix("image/"), "GIF should be an image type, got: \(gifType)")
|
||||
|
||||
let bmpType = String.mimeType(for: "bmp")
|
||||
#expect(bmpType.hasPrefix("image/"), "BMP should be an image type, got: \(bmpType)")
|
||||
|
||||
// Test archive types
|
||||
let zipType = String.mimeType(for: "zip")
|
||||
#expect(zipType.hasPrefix("application/"), "ZIP should be an application type, got: \(zipType)")
|
||||
|
||||
// Test development file types
|
||||
let jsonType = String.mimeType(for: "json")
|
||||
#expect(jsonType.hasPrefix("application/") || jsonType.hasPrefix("text/"),
|
||||
"JSON should be application or text type, got: \(jsonType)")
|
||||
|
||||
let cssType = String.mimeType(for: "css")
|
||||
#expect(cssType.hasPrefix("text/"), "CSS should be a text type, got: \(cssType)")
|
||||
|
||||
let jsType = String.mimeType(for: "js")
|
||||
#expect(jsType.hasPrefix("application/") || jsType.hasPrefix("text/"),
|
||||
"JavaScript should be application or text type, got: \(jsType)")
|
||||
}
|
||||
|
||||
@Test("Edge cases for MIME type resolution")
|
||||
func edgeCases() {
|
||||
// Test empty string
|
||||
#expect(String.mimeType(for: "") == "application/octet-stream")
|
||||
|
||||
// Test very long extension
|
||||
let longExtension = String(repeating: "a", count: 100)
|
||||
#expect(String.mimeType(for: longExtension) == "application/octet-stream")
|
||||
|
||||
// Test extension with special characters
|
||||
#expect(String.mimeType(for: "file.exe") == "application/octet-stream")
|
||||
#expect(String.mimeType(for: "test@test") == "application/octet-stream")
|
||||
}
|
||||
}
|
||||
@@ -1,24 +1,27 @@
|
||||
// String+UtilitiesTests.swift
|
||||
// Tests for general String utilities
|
||||
|
||||
import XCTest
|
||||
import Testing
|
||||
@testable import SwiftMail
|
||||
|
||||
final class StringUtilitiesTests: XCTestCase {
|
||||
func testSanitizedFileName() {
|
||||
@Suite("String Utilities Tests")
|
||||
struct StringUtilitiesTests {
|
||||
|
||||
@Test("Sanitized file name validation")
|
||||
func sanitizedFileName() {
|
||||
// Test valid filenames remain unchanged
|
||||
XCTAssertEqual("document.txt".sanitizedFileName(), "document.txt")
|
||||
XCTAssertEqual("image.jpg".sanitizedFileName(), "image.jpg")
|
||||
#expect("document.txt".sanitizedFileName() == "document.txt")
|
||||
#expect("image.jpg".sanitizedFileName() == "image.jpg")
|
||||
|
||||
// Test invalid characters are replaced
|
||||
XCTAssertEqual("file:with/invalid\\chars?.txt".sanitizedFileName(), "file_with_invalid_chars_.txt")
|
||||
XCTAssertEqual("doc*with|special<chars>.pdf".sanitizedFileName(), "doc_with_special_chars_.pdf")
|
||||
#expect("file:with/invalid\\chars?.txt".sanitizedFileName() == "file_with_invalid_chars_.txt")
|
||||
#expect("doc*with|special<chars>.pdf".sanitizedFileName() == "doc_with_special_chars_.pdf")
|
||||
|
||||
// Test spaces are replaced with underscores
|
||||
XCTAssertEqual("my document.pdf".sanitizedFileName(), "my_document.pdf")
|
||||
XCTAssertEqual("file with spaces.txt".sanitizedFileName(), "file_with_spaces.txt")
|
||||
#expect("my document.pdf".sanitizedFileName() == "my_document.pdf")
|
||||
#expect("file with spaces.txt".sanitizedFileName() == "file_with_spaces.txt")
|
||||
|
||||
// Test empty string
|
||||
XCTAssertEqual("".sanitizedFileName(), "")
|
||||
#expect("".sanitizedFileName() == "")
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user