From c34cc2e0920b58aa5b13186c1a1f6efd255732c7 Mon Sep 17 00:00:00 2001 From: Nikita Vasilev Date: Mon, 24 Nov 2025 18:41:22 +0400 Subject: [PATCH 1/3] feat: add characters validation rule --- .../Rules/CharactersValidationRule.swift | 33 +++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 Sources/ValidatorCore/Classes/Rules/CharactersValidationRule.swift diff --git a/Sources/ValidatorCore/Classes/Rules/CharactersValidationRule.swift b/Sources/ValidatorCore/Classes/Rules/CharactersValidationRule.swift new file mode 100644 index 0000000..dd3f8f1 --- /dev/null +++ b/Sources/ValidatorCore/Classes/Rules/CharactersValidationRule.swift @@ -0,0 +1,33 @@ +// +// Validator +// Copyright © 2025 Space Code. All rights reserved. +// + +import Foundation + +/// A characters validation rule. +public struct CharactersValidationRule: IValidationRule { + // MARK: Types + + public typealias Input = String + + // MARK: Properties + + public let characterSet: CharacterSet + + /// The validation error. + public let error: IValidationError + + // MARK: Initialization + + public init(characterSet: CharacterSet, error: IValidationError) { + self.characterSet = characterSet + self.error = error + } + + // MARK: IValidationRule + + public func validate(input: String) -> Bool { + input.rangeOfCharacter(from: characterSet.inverted) == .none + } +} From f2807c7d0c4d623072dbe476b9f6089498f61301 Mon Sep 17 00:00:00 2001 From: Nikita Vasilev Date: Mon, 24 Nov 2025 18:41:39 +0400 Subject: [PATCH 2/3] test: add unit tests for the characters validation rule --- .../Rules/CharactersValidationRuleTests.swift | 100 ++++++++++++++++++ 1 file changed, 100 insertions(+) create mode 100644 Tests/ValidatorCoreTests/UnitTests/Rules/CharactersValidationRuleTests.swift diff --git a/Tests/ValidatorCoreTests/UnitTests/Rules/CharactersValidationRuleTests.swift b/Tests/ValidatorCoreTests/UnitTests/Rules/CharactersValidationRuleTests.swift new file mode 100644 index 0000000..8461f21 --- /dev/null +++ b/Tests/ValidatorCoreTests/UnitTests/Rules/CharactersValidationRuleTests.swift @@ -0,0 +1,100 @@ +// +// Validator +// Copyright © 2025 Space Code. All rights reserved. +// + +@testable import ValidatorCore +import XCTest + +// MARK: - CharactersValidationRuleTests + +final class CharactersValidationRuleTests: XCTestCase { + // MARK: - Properties + + private var sut: CharactersValidationRule! + + // MARK: - Setup / Teardown + + override func setUp() { + super.setUp() + sut = CharactersValidationRule(characterSet: .letters, error: String.error) + } + + override func tearDown() { + sut = nil + super.tearDown() + } + + // MARK: - Valid Input Tests + + func testValidate_WithOnlyAllowedCharacters_ReturnsTrue() { + // Given + let input = "HelloWorld" + + // When + let result = sut.validate(input: input) + + // Then + XCTAssertTrue(result) + } + + // MARK: - Invalid Input Tests + + func testValidate_WithDisallowedCharacters_ReturnsFalse() { + // Given + let input = "Hello123" + + // When + let result = sut.validate(input: input) + + // Then + XCTAssertFalse(result) + } + + func testValidate_WithSpecialCharacters_ReturnsFalse() { + // Given + let input = "Hi!" + + // When + let result = sut.validate(input: input) + + // Then + XCTAssertFalse(result) + } + + // MARK: - Edge Cases + + func testValidate_EmptyString_ReturnsTrue() { + // Given + let input = "" + + // When + let result = sut.validate(input: input) + + // Then + XCTAssertTrue(result) + } + + func testValidate_UnicodeCharacters_WhenNotAllowed_ReturnsTrue() { + // Given + let input = "Привет" + + // When + let result = sut.validate(input: input) + + // Then + XCTAssertTrue(result) + } + + // MARK: - Error Property + + func testErrorProperty_ReturnsProvidedError() { + XCTAssertEqual(sut.error as? String, String.error) + } +} + +// MARK: Constants + +private extension String { + static let error = "Invalid characters" +} From 0b2fc865979f2f0d97329e5a7d2c6ac51aa0dfb4 Mon Sep 17 00:00:00 2001 From: Nikita Vasilev Date: Mon, 24 Nov 2025 18:42:56 +0400 Subject: [PATCH 3/3] docs: update `README.md` --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 5e86ed1..53c480b 100644 --- a/README.md +++ b/README.md @@ -303,6 +303,7 @@ struct RegistrationView: View { | `URLValidationRule` | Validates URL format | `URLValidationRule(error: "Please enter a valid URL")` | | `CreditCardValidationRule` | Validates credit card numbers (Luhn algorithm) | `CreditCardValidationRule(error: "Invalid card number")` | | `EmailValidationRule` | Validates email format | `EmailValidationRule(error: "Please enter a valid email")` | +| `CharactersValidationRule` | Validates that a string contains only characters from the allowed CharacterSet | `CharactersValidationRule(characterSet: .letters, error: "Invalid characters")` | ## Custom Validators