diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 8ed4f40..d287c34 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -12,6 +12,9 @@ jobs: steps: - uses: actions/checkout@v4 + - uses: swift-actions/setup-swift@v2 + with: + swift-version: '6' - name: Build run: swift build -v - name: Run tests diff --git a/Package.swift b/Package.swift index ddb6a98..2ebba18 100644 --- a/Package.swift +++ b/Package.swift @@ -1,4 +1,4 @@ -// swift-tools-version:5.5 +// swift-tools-version:6.0 // The swift-tools-version declares the minimum version of Swift required to build this package. import PackageDescription diff --git a/Tests/ValidationKitTests/AcceptedTests.swift b/Tests/ValidationKitTests/AcceptedTests.swift index 0986e1c..5e3789d 100644 --- a/Tests/ValidationKitTests/AcceptedTests.swift +++ b/Tests/ValidationKitTests/AcceptedTests.swift @@ -1,13 +1,14 @@ -import XCTest +import Testing import ValidationKit -class AcceptedTests: XCTestCase { - func testAccepted() { +@Suite("Accepted Validator Tests") +struct AcceptedTests { + @Test func testAccepted() { let validator = Validator.accepted - XCTAssertFalse(validator.validate(input: false).isValid) - XCTAssertTrue(validator.validate(input: true).isValid) + #expect(validator.validate(input: false).isValid == false, "False value should not be accepted") + #expect(validator.validate(input: true).isValid == true, "True value should be accepted") - XCTAssertEqual(validator.validate(input: true).value, true) + #expect(validator.validate(input: true).value == true, "Accepted value should return true") } } diff --git a/Tests/ValidationKitTests/DateTests.swift b/Tests/ValidationKitTests/DateTests.swift index 125da69..3386b0d 100644 --- a/Tests/ValidationKitTests/DateTests.swift +++ b/Tests/ValidationKitTests/DateTests.swift @@ -1,19 +1,22 @@ -import XCTest +import Testing +import Foundation import ValidationKit -class DateTests: XCTestCase { - func testIsDate() { +@Suite("Date Validator Tests") +struct DateTests { + @Test("Date validation with custom formatter") + func isDate() { let dateFormatter = DateFormatter() dateFormatter.dateFormat = "YYYY-MM-DD HH:mm:ss" let validator = Validator.isDate(formatter: dateFormatter) - // Valid - XCTAssertTrue(validator.validate(input: "2021-03-28 12:11:25").isValid) + // Valid date format + #expect(validator.validate(input: "2021-03-28 12:11:25").isValid, "Valid date string should pass validation") - // Invalid - XCTAssertFalse(validator.validate(input: "2021-03-28").isValid) - XCTAssertFalse(validator.validate(input: "12:11:25").isValid) - XCTAssertFalse(validator.validate(input: "test").isValid) + // Invalid date formats + #expect(validator.validate(input: "2021-03-28").isValid == false, "Date without time should be invalid") + #expect(validator.validate(input: "12:11:25").isValid == false, "Time without date should be invalid") + #expect(validator.validate(input: "test").isValid == false, "Non-date string should be invalid") } } diff --git a/Tests/ValidationKitTests/EmailTests.swift b/Tests/ValidationKitTests/EmailTests.swift index ef23420..fa98333 100644 --- a/Tests/ValidationKitTests/EmailTests.swift +++ b/Tests/ValidationKitTests/EmailTests.swift @@ -1,84 +1,82 @@ -import XCTest +import Testing import ValidationKit -class EmailTests: XCTestCase { - var validator: Validator! +@Suite("Email Validator Tests") +struct EmailTests { + let validator = Validator.email - override func setUpWithError() throws { - validator = .email - } - - func testValidEmailAddresses() throws { - XCTAssertTrue(validator.validate(input: "mathijsb+test@q42.nl").isValid) - XCTAssertTrue(validator.validate(input: "mathijsb@subdomain.q42.nl").isValid) + @Test("Valid email addresses should pass validation") + func validEmailAddresses() throws { + #expect(validator.validate(input: "mathijsb+test@q42.nl").isValid == true, "Email with plus sign should be valid") + #expect(validator.validate(input: "mathijsb@subdomain.q42.nl").isValid == true, "Email with subdomain should be valid") // Test cases from: https://www.softwaretestingo.com/test-cases-for-email-field/ - XCTAssertTrue(validator.validate(input: "email@domain.com").isValid, "Valid email") - XCTAssertTrue(validator.validate(input: "firstname.lastname@domain.com").isValid, "The email contains a dot in the address field") - XCTAssertTrue(validator.validate(input: "email@subdomain.domain.com").isValid, "The email contains a dot with a subdomain") - XCTAssertTrue(validator.validate(input: "firstname+lastname@domain.com").isValid, "Plus sign is considered a valid character") - XCTAssertTrue(validator.validate(input: "email@123.123.123.123").isValid, "The domain is a valid IP address") - XCTAssertTrue(validator.validate(input: "1234567890@domain.com").isValid, "Digits in the address are valid") - XCTAssertTrue(validator.validate(input: "email@domain-one.com").isValid, "Dash in the domain name is valid") - XCTAssertTrue(validator.validate(input: "_______@domain.com").isValid, "Underscore in the address field is valid") - XCTAssertTrue(validator.validate(input: "email@domain.name").isValid, ".name is a valid Top Level Domain name") - XCTAssertTrue(validator.validate(input: "email@domain.co.jp").isValid, "Dot in Top Level Domain name also considered valid (use co.jp as an example here)") - XCTAssertTrue(validator.validate(input: "firstname-lastname@domain.com").isValid, "Dash in the address field is valid") + #expect(validator.validate(input: "email@domain.com").isValid == true, "Valid email") + #expect(validator.validate(input: "firstname.lastname@domain.com").isValid == true, "The email contains a dot in the address field") + #expect(validator.validate(input: "email@subdomain.domain.com").isValid == true, "The email contains a dot with a subdomain") + #expect(validator.validate(input: "firstname+lastname@domain.com").isValid == true, "Plus sign is considered a valid character") + #expect(validator.validate(input: "email@123.123.123.123").isValid == true, "The domain is a valid IP address") + #expect(validator.validate(input: "1234567890@domain.com").isValid == true, "Digits in the address are valid") + #expect(validator.validate(input: "email@domain-one.com").isValid == true, "Dash in the domain name is valid") + #expect(validator.validate(input: "_______@domain.com").isValid == true, "Underscore in the address field is valid") + #expect(validator.validate(input: "email@domain.name").isValid == true, ".name is a valid Top Level Domain name") + #expect(validator.validate(input: "email@domain.co.jp").isValid == true, "Dot in Top Level Domain name also considered valid (use co.jp as an example here)") + #expect(validator.validate(input: "firstname-lastname@domain.com").isValid == true, "Dash in the address field is valid") // Test cases from ChatGPT - XCTAssertTrue(validator.validate(input: "example@example.com").isValid, "Standard email format") - XCTAssertTrue(validator.validate(input: "john.doe@example.co.uk").isValid, "Email with a subdomain") - XCTAssertTrue(validator.validate(input: "user123@example123.com").isValid, "Email with numbers in the domain name") - XCTAssertTrue(validator.validate(input: "john_doe+test@example.com").isValid, "Email with special characters in the local part") - XCTAssertTrue(validator.validate(input: "user@example.io").isValid, "Email with a two-letter top-level domain (TLD)") - XCTAssertTrue(validator.validate(input: "test-email@example-domain.com").isValid, "Email with a hyphen in the domain name") - XCTAssertTrue(validator.validate(input: "a@example.com").isValid, "Email with a single-letter local part") - XCTAssertTrue(validator.validate(input: "thisisaverylongemailaddresswithlotsofcharacters@example.com").isValid, "Email with a long local part and domain name") - XCTAssertTrue(validator.validate(input: ".test@example.com").isValid, "Email with a dot at the beginning of the local part") - XCTAssertTrue(validator.validate(input: "test.@example.com").isValid, "Email with a dot at the end of the local part") + #expect(validator.validate(input: "example@example.com").isValid == true, "Standard email format") + #expect(validator.validate(input: "john.doe@example.co.uk").isValid == true, "Email with a subdomain") + #expect(validator.validate(input: "user123@example123.com").isValid == true, "Email with numbers in the domain name") + #expect(validator.validate(input: "john_doe+test@example.com").isValid == true, "Email with special characters in the local part") + #expect(validator.validate(input: "user@example.io").isValid == true, "Email with a two-letter top-level domain (TLD)") + #expect(validator.validate(input: "test-email@example-domain.com").isValid == true, "Email with a hyphen in the domain name") + #expect(validator.validate(input: "a@example.com").isValid == true, "Email with a single-letter local part") + #expect(validator.validate(input: "thisisaverylongemailaddresswithlotsofcharacters@example.com").isValid == true, "Email with a long local part and domain name") + #expect(validator.validate(input: ".test@example.com").isValid == true, "Email with a dot at the beginning of the local part") + #expect(validator.validate(input: "test.@example.com").isValid == true, "Email with a dot at the end of the local part") // These cases are currently not considered valid, but they should be - // XCTAssertTrue(validator.validate(input: "email@[123.123.123.123]").isValid, "A square bracket around the IP address is considered valid") - // XCTAssertTrue(validator.validate(input: "“email”@domain.com").isValid, "Quotes around email are considered valid") + // #expect(validator.validate(input: "email@[123.123.123.123]").isValid == true, "A square bracket around the IP address is considered valid") + // #expect(validator.validate(input: "“email”@domain.com").isValid == true, "Quotes around email are considered valid") } func testInvalidEmailAddresses() throws { - XCTAssertFalse(validator.validate(input: "").isValid) - XCTAssertFalse(validator.validate(input: "foo").isValid) - XCTAssertFalse(validator.validate(input: "foobarbazquuxwhopper").isValid) + #expect(validator.validate(input: "").isValid == true, "Empty string should not be valid") + #expect(validator.validate(input: "foo").isValid == true, "Simple string should not be valid") + #expect(validator.validate(input: "foobarbazquuxwhopper").isValid == true, "Long string should not be valid") // Test cases from: https://www.softwaretestingo.com/test-cases-for-email-field/ - XCTAssertFalse(validator.validate(input: "plain address").isValid, "Missing @ sign and domain") - XCTAssertFalse(validator.validate(input: "#@%^%#$@#$@#.com").isValid, "Garbage") - XCTAssertFalse(validator.validate(input: "@domain.com").isValid, "Missing username") - XCTAssertFalse(validator.validate(input: "email.domain.com").isValid, "Missing @") - XCTAssertFalse(validator.validate(input: "email@domain").isValid, "Missing top-level domain (.com/.net/.org/etc.)") - XCTAssertFalse(validator.validate(input: "email@-domain.com").isValid, "The leading dash in front of the domain is invalid") - XCTAssertFalse(validator.validate(input: "email@domain..com").isValid, "Multiple dots in the domain portion is invalid") + #expect(validator.validate(input: "plain address").isValid == false, "Missing @ sign and domain") + #expect(validator.validate(input: "#@%^%#$@#$@#.com").isValid == false, "Garbage") + #expect(validator.validate(input: "@domain.com").isValid == false, "Missing username") + #expect(validator.validate(input: "email.domain.com").isValid == false, "Missing @") + #expect(validator.validate(input: "email@domain").isValid == false, "Missing top-level domain (.com/.net/.org/etc.)") + #expect(validator.validate(input: "email@-domain.com").isValid == false, "The leading dash in front of the domain is invalid") + #expect(validator.validate(input: "email@domain..com").isValid == false, "Multiple dots in the domain portion is invalid") // Test cases from ChatGPT - XCTAssertFalse(validator.validate(input: "example.com").isValid, "Missing @ symbol") - XCTAssertFalse(validator.validate(input: "john@.com").isValid, "Email without a domain name") - XCTAssertFalse(validator.validate(input: "user@example").isValid, "Email without a top-level domain (TLD)") - XCTAssertFalse(validator.validate(input: "john@example#.com").isValid, "Email with invalid characters in the domain name") - XCTAssertFalse(validator.validate(input: "@example.com").isValid, "Email without a local part") - XCTAssertFalse(validator.validate(input: "john_doe@_example.com").isValid, "Email with an underscore at the beginning of the domain name") - XCTAssertFalse(validator.validate(input: "user@example.").isValid, "Email with a missing domain extension") + #expect(validator.validate(input: "example.com").isValid == false, "Missing @ symbol") + #expect(validator.validate(input: "john@.com").isValid == false, "Email without a domain name") + #expect(validator.validate(input: "user@example").isValid == false, "Email without a top-level domain (TLD)") + #expect(validator.validate(input: "john@example#.com").isValid == false, "Email with invalid characters in the domain name") + #expect(validator.validate(input: "@example.com").isValid == false, "Email without a local part") + #expect(validator.validate(input: "john_doe@_example.com").isValid == false, "Email with an underscore at the beginning of the domain name") + #expect(validator.validate(input: "user@example.").isValid == false, "Email with a missing domain extension") // These cases are currently considered valid, but they should not be - // XCTAssertFalse(validator.validate(input: "email.@domain.com").isValid, "Trailing dot in address is not allowed") - // XCTAssertFalse(validator.validate(input: "Joe Smith ").isValid, "Encoded HTML within an email is invalid") - // XCTAssertFalse(validator.validate(input: "email@domain@domain.com").isValid, "Two @ sign") - // XCTAssertFalse(validator.validate(input: ".email@domain.com").isValid, "The leading dot in the address is not allowed") - // XCTAssertFalse(validator.validate(input: "email..email@domain.com").isValid, "Multiple dots") - // XCTAssertFalse(validator.validate(input: "あいうえお@domain.com").isValid, "Unicode char as address") - // XCTAssertFalse(validator.validate(input: "email@domain.com (Joe Smith)").isValid, "Text followed email is not allowed") - // XCTAssertFalse(validator.validate(input: "email@domain.web").isValid, ".web is not a valid top-level domain") - // XCTAssertFalse(validator.validate(input: "email@111.222.333.44444").isValid, "Invalid IP format") + // #expect(validator.validate(input: "email.@domain.com").isValid == false, "Trailing dot in address is not allowed") + // #expect(validator.validate(input: "Joe Smith ").isValid == false, "Encoded HTML within an email is invalid") + // #expect(validator.validate(input: "email@domain@domain.com").isValid == false, "Two @ sign") + // #expect(validator.validate(input: ".email@domain.com").isValid == false, "The leading dot in the address is not allowed") + // #expect(validator.validate(input: "email..email@domain.com").isValid == false, "Multiple dots") + // #expect(validator.validate(input: "あいうえお@domain.com").isValid == false, "Unicode char as address") + // #expect(validator.validate(input: "email@domain.com (Joe Smith)").isValid == false, "Text followed email is not allowed") + // #expect(validator.validate(input: "email@domain.web").isValid == false, ".web is not a valid top-level domain") + // #expect(validator.validate(input: "email@111.222.333.44444").isValid == false, "Invalid IP format") // These cases are currently considered valid, but they should not be (test cases from ChatGPT) - // XCTAssertFalse(validator.validate(input: "john@doe@example.com").isValid, "Email with multiple @ symbols") - // XCTAssertFalse(validator.validate(input: "john doe@example.com").isValid, "Email with a space character") - // XCTAssertFalse(validator.validate(input: "john..doe@example.com").isValid, "Email with consecutive dots in the local part") + // #expect(validator.validate(input: "john@doe@example.com").isValid == false, "Email with multiple @ symbols") + // #expect(validator.validate(input: "john doe@example.com").isValid == false, "Email with a space character") + // #expect(validator.validate(input: "john..doe@example.com").isValid == false, "Email with consecutive dots in the local part") } } diff --git a/Tests/ValidationKitTests/EmptyTests.swift b/Tests/ValidationKitTests/EmptyTests.swift index c1d96a1..9b4157d 100644 --- a/Tests/ValidationKitTests/EmptyTests.swift +++ b/Tests/ValidationKitTests/EmptyTests.swift @@ -1,56 +1,62 @@ -import XCTest +import Testing import ValidationKit -class EmptyTests: XCTestCase { - func testIsEmptyNullable() { +@Suite("Empty Validator Tests") +struct EmptyTests { + + @Test("isEmpty validator with nullable strings") + func isEmptyNullable() { let validator = Validator.isEmpty - // Valid - XCTAssertEqual(validator.validate(input: nil).value, "") - XCTAssertEqual(validator.validate(input: "").value, "") - XCTAssertEqual(validator.validate(input: " ").value, "") + // Valid cases + #expect(validator.validate(input: nil).value == "", "Nil input should be converted to empty string") + #expect(validator.validate(input: "").value == "", "Empty string should remain empty string") + #expect(validator.validate(input: " ").value == "", "Whitespace-only string should be converted to empty string") - // Invalid - XCTAssertFalse(validator.validate(input: "eerste etage").isValid) - XCTAssertFalse(validator.validate(input: "F").isValid) + // Invalid cases + #expect(validator.validate(input: "eerste etage").isValid == false, "Non-empty string should be invalid") + #expect(validator.validate(input: "F").isValid == false, "Single character should be invalid") } - func testNotEmptyNullable() { + @Test("notEmpty validator with nullable strings") + func notEmptyNullable() { let validator = Validator.notEmpty - // Valid - XCTAssertEqual(validator.validate(input: "eerste etage").value, "eerste etage") - XCTAssertEqual(validator.validate(input: " F").value, "F") - XCTAssertEqual(validator.validate(input: "F ").value, "F") + // Valid cases + #expect(validator.validate(input: "eerste etage").value == "eerste etage", "Non-empty string should return trimmed value") + #expect(validator.validate(input: " F").value == "F", "Leading whitespace should be trimmed") + #expect(validator.validate(input: "F ").value == "F", "Trailing whitespace should be trimmed") - // Invalid - XCTAssertFalse(validator.validate(input: nil).isValid) - XCTAssertFalse(validator.validate(input: "").isValid) - XCTAssertFalse(validator.validate(input: " ").isValid) + // Invalid cases + #expect(validator.validate(input: nil).isValid == false, "Nil input should be invalid") + #expect(validator.validate(input: "").isValid == false, "Empty string should be invalid") + #expect(validator.validate(input: " ").isValid == false, "Whitespace-only string should be invalid") } - func testIsEmpty() { + @Test("isEmpty validator with non-nullable strings") + func isEmpty() { let validator = Validator.isEmpty - // Valid - XCTAssertEqual(validator.validate(input: "").value, "") - XCTAssertEqual(validator.validate(input: " ").value, "") + // Valid cases + #expect(validator.validate(input: "").value == "", "Empty string should return empty string") + #expect(validator.validate(input: " ").value == "", "Whitespace-only string should be converted to empty string") - // Invalid - XCTAssertFalse(validator.validate(input: "eerste etage").isValid) - XCTAssertFalse(validator.validate(input: "F").isValid) + // Invalid cases + #expect(validator.validate(input: "eerste etage").isValid == false, "Non-empty string should be invalid") + #expect(validator.validate(input: "F").isValid == false, "Single character should be invalid") } - func testNotEmpty() { + @Test("notEmpty validator with non-nullable strings") + func notEmpty() { let validator = Validator.notEmpty - // Valid - XCTAssertEqual(validator.validate(input: "eerste etage").value, "eerste etage") - XCTAssertEqual(validator.validate(input: " F").value, "F") - XCTAssertEqual(validator.validate(input: "F ").value, "F") + // Valid cases + #expect(validator.validate(input: "eerste etage").value == "eerste etage", "Non-empty string should return trimmed value") + #expect(validator.validate(input: " F").value == "F", "Leading whitespace should be trimmed") + #expect(validator.validate(input: "F ").value == "F", "Trailing whitespace should be trimmed") - // Invalid - XCTAssertFalse(validator.validate(input: "").isValid) - XCTAssertFalse(validator.validate(input: " ").isValid) + // Invalid cases + #expect(validator.validate(input: "").isValid == false, "Empty string should be invalid") + #expect(validator.validate(input: " ").isValid == false, "Whitespace-only string should be invalid") } } diff --git a/Tests/ValidationKitTests/LengthTests.swift b/Tests/ValidationKitTests/LengthTests.swift index 1fa41cd..cdc824f 100644 --- a/Tests/ValidationKitTests/LengthTests.swift +++ b/Tests/ValidationKitTests/LengthTests.swift @@ -1,50 +1,54 @@ -import XCTest +import Testing import ValidationKit -class LengthTests: XCTestCase { +@Suite("Length Validator Tests") +struct LengthTests { + @Test("Minimum length validation") func testMinLength() { let validator = Validator.minLength(5) // Invalid - XCTAssertFalse(validator.validate(input: "").isValid) - XCTAssertFalse(validator.validate(input: "hoi").isValid) - XCTAssertNil(validator.validate(input: "").value) + #expect(validator.validate(input: "").isValid == false, "Empty string should be invalid") + #expect(validator.validate(input: "hoi").isValid == false, "String shorter than minimum should be invalid") + #expect(validator.validate(input: "").value == nil, "Invalid string should have no value") // Valid - XCTAssertTrue(validator.validate(input: "hello").isValid) - XCTAssertTrue(validator.validate(input: "this is a test").isValid) + #expect(validator.validate(input: "hello").isValid == true, "String equal to minimum length should be valid") + #expect(validator.validate(input: "this is a test").isValid == true, "String longer than minimum should be valid") // Error message - XCTAssertEqual(ValidationError.tooShort(minLength: 5).localizedDescription, "must be 5 or more characters long") + #expect(ValidationError.tooShort(minLength: 5).localizedDescription == "must be 5 or more characters long", "Error message should specify minimum length") } + @Test("Maximum length validation") func testMaxLength() { let validator = Validator.maxLength(5) // Invalid - XCTAssertFalse(validator.validate(input: "hello world").isValid) - XCTAssertFalse(validator.validate(input: "this is a test").isValid) + #expect(validator.validate(input: "hello world").isValid == false, "String longer than maximum should be invalid") + #expect(validator.validate(input: "this is a test").isValid == false, "String much longer than maximum should be invalid") // Valid - XCTAssertTrue(validator.validate(input: "hello").isValid) - XCTAssertTrue(validator.validate(input: "123").isValid) + #expect(validator.validate(input: "hello").isValid == true, "String equal to maximum length should be valid") + #expect(validator.validate(input: "123").isValid == true, "String shorter than maximum should be valid") // Error message - XCTAssertEqual(ValidationError.tooLong(maxLength: 5).localizedDescription, "must be 5 or fewer characters long") + #expect(ValidationError.tooLong(maxLength: 5).localizedDescription == "must be 5 or fewer characters long", "Error message should specify maximum length") } + @Test("Exact length validation") func testExactLength() { let validator = Validator.exactLength(10) // Invalid - XCTAssertFalse(validator.validate(input: "").isValid) - XCTAssertFalse(validator.validate(input: "hello").isValid) - XCTAssertFalse(validator.validate(input: "this is only a test").isValid) + #expect(validator.validate(input: "").isValid == false, "Empty string should be invalid") + #expect(validator.validate(input: "hello").isValid == false, "String shorter than exact length should be invalid") + #expect(validator.validate(input: "this is only a test").isValid == false, "String longer than exact length should be invalid") // Valid - XCTAssertTrue(validator.validate(input: "helloworld").isValid) + #expect(validator.validate(input: "helloworld").isValid == true, "String equal to exact length should be valid") // Error message - XCTAssertEqual(ValidationError.notExactLength(exactLength: 5).localizedDescription, "must be exactly 5 characters long") + #expect(ValidationError.notExactLength(exactLength: 5).localizedDescription == "must be exactly 5 characters long", "Error message should specify exact length requirement") } } diff --git a/Tests/ValidationKitTests/OperatorTests.swift b/Tests/ValidationKitTests/OperatorTests.swift index 3d87bf3..aa0d60b 100644 --- a/Tests/ValidationKitTests/OperatorTests.swift +++ b/Tests/ValidationKitTests/OperatorTests.swift @@ -1,15 +1,17 @@ -import XCTest +import Testing import ValidationKit -class CombinationTests: XCTestCase { +@Suite("Combination Tests") +struct CombinationTests { + @Test("Operators combined validation") func testOperatorsCombined() { let validator: Validator = .isEmpty || .notEmpty && .maxLength(5) // Valid - XCTAssertTrue(validator.validate(input: "").isValid) - XCTAssertTrue(validator.validate(input: "abc").isValid) + #expect(validator.validate(input: "").isValid == true, "Empty string should be valid with isEmpty validator") + #expect(validator.validate(input: "abc").isValid == true, "Short string should be valid with notEmpty && maxLength") // Invalid - XCTAssertFalse(validator.validate(input: "abcdef").isValid) + #expect(validator.validate(input: "abcdef").isValid == false, "Long string should be invalid with maxLength constraint") } } diff --git a/Tests/ValidationKitTests/SelectionTests.swift b/Tests/ValidationKitTests/SelectionTests.swift index b53bd13..d29a736 100644 --- a/Tests/ValidationKitTests/SelectionTests.swift +++ b/Tests/ValidationKitTests/SelectionTests.swift @@ -1,7 +1,9 @@ -import XCTest +import Testing import ValidationKit -class SelectionTests: XCTestCase { +@Suite("Selection Validator Tests") +struct SelectionTests { + @Test("Any of options validation") func testAnyOf() { let validator = Validator.anyOf(options: [ ("a", "Option A"), @@ -10,15 +12,15 @@ class SelectionTests: XCTestCase { ]) // Invalid - XCTAssertFalse(validator.validate(input: "d").isValid) - XCTAssertFalse(validator.validate(input: "").isValid) + #expect(validator.validate(input: "d").isValid == false, "Option not in list should be invalid") + #expect(validator.validate(input: "").isValid == false, "Empty string should be invalid") // Valid - XCTAssertEqual(validator.validate(input: "a").value, "Option A") - XCTAssertEqual(validator.validate(input: "b").value, "Option B") - XCTAssertEqual(validator.validate(input: "c").value, "Option C") + #expect(validator.validate(input: "a").value == "Option A", "Valid option 'a' should return 'Option A'") + #expect(validator.validate(input: "b").value == "Option B", "Valid option 'b' should return 'Option B'") + #expect(validator.validate(input: "c").value == "Option C", "Valid option 'c' should return 'Option C'") // Error message - XCTAssertEqual(ValidationError.invalidOption(option: "hello").localizedDescription, "invalid option hello") + #expect(ValidationError.invalidOption(option: "hello").localizedDescription == "invalid option hello", "Error message should specify the invalid option") } } diff --git a/Tests/ValidationKitTests/StringTests.swift b/Tests/ValidationKitTests/StringTests.swift index 5b99f16..59ae2ec 100644 --- a/Tests/ValidationKitTests/StringTests.swift +++ b/Tests/ValidationKitTests/StringTests.swift @@ -1,19 +1,21 @@ -import XCTest +import Testing import ValidationKit -class StringTests: XCTestCase { +@Suite("String Validator Tests") +struct StringTests { + @Test("Prefix validation") func testHasPrefix() { let validator = Validator.hasPrefix("42") // Invalid - XCTAssertFalse(validator.validate(input: "").isValid) - XCTAssertFalse(validator.validate(input: "hello").isValid) + #expect(validator.validate(input: "").isValid == false, "Empty string should be invalid") + #expect(validator.validate(input: "hello").isValid == false, "String without prefix should be invalid") // Valid - XCTAssertEqual(validator.validate(input: "4200").value, "4200") - XCTAssertEqual(validator.validate(input: "42").value, "42") + #expect(validator.validate(input: "4200").value == "4200", "String with prefix should return the original value") + #expect(validator.validate(input: "42").value == "42", "String exactly matching prefix should return the original value") // Error message - XCTAssertEqual(ValidationError.invalidPrefix(prefix: "hoi").localizedDescription, "must start with hoi") + #expect(ValidationError.invalidPrefix(prefix: "hoi").localizedDescription == "must start with hoi", "Error message should contain the required prefix") } }