Skip to content

Commit ea5d5e7

Browse files
committed
feat: add equality validation rule
1 parent 2313d93 commit ea5d5e7

File tree

4 files changed

+141
-0
lines changed

4 files changed

+141
-0
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -312,6 +312,7 @@ struct RegistrationView: View {
312312
| `PositiveNumberValidationRule` | Validates that value is positive | `PositiveNumberValidationRule(error: "Value must be positive")`
313313
| `NoWhitespaceValidationRule` | Validates that a string does not contain any whitespace characters | `NoWhitespaceValidationRule(error: "Spaces are not allowed")`
314314
| `ContainsValidationRule` | Validates that a string contains a specific substring | `ContainsValidationRule(substring: "@", error: "Must contain @")`
315+
| `EqualityValidationRule`| Validates that the input is equal to a given reference value | `EqualityValidationRule(compareTo: password, error: "Passwords do not match")`
315316

316317
## Custom Validators
317318

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
//
2+
// Validator
3+
// Copyright © 2025 Space Code. All rights reserved.
4+
//
5+
6+
/// Validates that the input is equal to a given reference value.
7+
///
8+
/// This rule compares the provided `input` against a predefined value using `Equatable`.
9+
/// Validation passes only if both values are equal.
10+
///
11+
/// # Example:
12+
/// ```swift
13+
/// let rule = EqualityValidationRule(compareTo: 42, error: SomeError())
14+
/// rule.validate(input: 42) // true
15+
/// rule.validate(input: 41) // false
16+
/// ```
17+
///
18+
/// - Note: This rule works with any `Equatable` type.
19+
public struct EqualityValidationRule<T: Equatable>: IValidationRule {
20+
// MARK: Types
21+
22+
public typealias Input = T
23+
24+
// MARK: Properties
25+
26+
public let value: T
27+
28+
/// The validation error.
29+
public let error: IValidationError
30+
31+
// MARK: Initialization
32+
33+
/// Creates a validation rule that checks whether the input equals a specific value.
34+
///
35+
/// - Parameters:
36+
/// - value: The value to compare the input against.
37+
/// - error: The validation error to return if validation fails.
38+
public init(compareTo value: T, error: IValidationError) {
39+
self.value = value
40+
self.error = error
41+
}
42+
43+
// MARK: IValidationRule
44+
45+
public func validate(input: T) -> Bool {
46+
value == input
47+
}
48+
}

Sources/ValidatorCore/Validator.docc/Overview.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ ValidatorCore contains all core validation rules, utilities, and mechanisms for
3535
- ``PositiveNumberValidationRule``
3636
- ``NoWhitespaceValidationRuleTests``
3737
- ``ContainsValidationRule``
38+
- ``EqualityValidationRule``
3839

3940
### Articles
4041

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
//
2+
// Validator
3+
// Copyright © 2025 Space Code. All rights reserved.
4+
//
5+
6+
@testable import ValidatorCore
7+
import XCTest
8+
9+
// MARK: - EqualityValidationRuleTests
10+
11+
final class EqualityValidationRuleTests: XCTestCase {
12+
// MARK: Properties
13+
14+
private var sut: EqualityValidationRule<Int>!
15+
16+
// MARK: XCTestCase
17+
18+
override func setUp() {
19+
super.setUp()
20+
sut = EqualityValidationRule(compareTo: 10, error: String.error)
21+
}
22+
23+
override func tearDown() {
24+
sut = nil
25+
super.tearDown()
26+
}
27+
28+
// MARK: Tests
29+
30+
func test_thatValidationRuleSetsProperties() {
31+
// then
32+
XCTAssertEqual(sut.value, 10)
33+
XCTAssertEqual(sut.error.message, .error)
34+
}
35+
36+
func test_thatRuleValidatesCorrectValue() {
37+
// when
38+
let result = sut.validate(input: 10)
39+
40+
// then
41+
XCTAssertTrue(result)
42+
}
43+
44+
func test_thatRuleFailsForIncorrectValue() {
45+
// when
46+
let result = sut.validate(input: 5)
47+
48+
// then
49+
XCTAssertFalse(result)
50+
}
51+
52+
func test_thatRuleWorksWithStringInput() {
53+
// given
54+
let rule = EqualityValidationRule(compareTo: "abc", error: String.error)
55+
56+
// when
57+
let resultPass = rule.validate(input: "abc")
58+
let resultFail = rule.validate(input: "abcd")
59+
60+
// then
61+
XCTAssertTrue(resultPass)
62+
XCTAssertFalse(resultFail)
63+
}
64+
65+
func test_thatRuleWorksWithCustomEquatableType() {
66+
// given
67+
struct User: Equatable {
68+
let id: Int
69+
let name: String
70+
}
71+
72+
let matchUser = User(id: 1, name: "Nikita")
73+
let anotherUser = User(id: 2, name: "Alex")
74+
75+
let rule = EqualityValidationRule(compareTo: matchUser, error: String.error)
76+
77+
// when
78+
let resultPass = rule.validate(input: matchUser)
79+
let resultFail = rule.validate(input: anotherUser)
80+
81+
// then
82+
XCTAssertTrue(resultPass)
83+
XCTAssertFalse(resultFail)
84+
}
85+
}
86+
87+
// MARK: Constants
88+
89+
private extension String {
90+
static let error = "Values must be equal"
91+
}

0 commit comments

Comments
 (0)