Skip to content

Commit 8eac8a6

Browse files
committed
feat: add contains substring validation rule
1 parent 78cc5d9 commit 8eac8a6

File tree

4 files changed

+118
-0
lines changed

4 files changed

+118
-0
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -309,6 +309,7 @@ struct RegistrationView: View {
309309
| `EmailValidationRule` | Validates email format | `EmailValidationRule(error: "Please enter a valid email")` |
310310
| `CharactersValidationRule` | Validates that a string contains only characters from the allowed CharacterSet | `CharactersValidationRule(characterSet: .letters, error: "Invalid characters")` |
311311
| `NilValidationRule` | Validates that value is nil | `NilValidationRule(error: "Value must be nil")`
312+
| `ContainsValidationRule` | Validates that a string contains a specific substring | `ContainsValidationRule(substring: "@", error: "Must contain @")`
312313

313314
## Custom Validators
314315

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
//
2+
// Validator
3+
// Copyright © 2025 Space Code. All rights reserved.
4+
//
5+
6+
/// Validates that a string contains a specific substring.
7+
///
8+
/// # Example:
9+
/// ```swift
10+
/// let rule = ContainsValidationRule(substring: "@", error: "Must contain @")
11+
/// rule.validate(input: "user@example.com") // true
12+
/// ```
13+
public struct ContainsValidationRule: IValidationRule {
14+
// MARK: Types
15+
16+
public typealias Input = String
17+
18+
// MARK: Properties
19+
20+
/// The substring that the input must contain.
21+
public let substring: String
22+
23+
/// The validation error.
24+
public let error: IValidationError
25+
26+
// MARK: Initialization
27+
28+
/// Creates a validation rule that checks whether the input contains a required substring.
29+
///
30+
/// - Parameters:
31+
/// - substring: The string the input must contain.
32+
/// - error: The validation error associated with failed validation.
33+
public init(substring: String, error: IValidationError) {
34+
self.substring = substring
35+
self.error = error
36+
}
37+
38+
// MARK: IValidationRule
39+
40+
public func validate(input: String) -> Bool {
41+
input.contains(substring)
42+
}
43+
}

Sources/ValidatorCore/Validator.docc/Overview.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ ValidatorCore contains all core validation rules, utilities, and mechanisms for
3131
- ``RegexValidationRule``
3232
- ``SuffixValidationRule``
3333
- ``URLValidationRule``
34+
- ``ContainsValidationRule``
3435

3536
### Articles
3637

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
//
2+
// Validator
3+
// Copyright © 2025 Space Code. All rights reserved.
4+
//
5+
6+
@testable import ValidatorCore
7+
import XCTest
8+
9+
// MARK: - ContainsValidationRuleTests
10+
11+
final class ContainsValidationRuleTests: XCTestCase {
12+
// MARK: Properties
13+
14+
private var sut: ContainsValidationRule!
15+
16+
// MARK: XCTestCase
17+
18+
override func setUp() {
19+
super.setUp()
20+
sut = ContainsValidationRule(substring: "@", error: String.error)
21+
}
22+
23+
override func tearDown() {
24+
sut = nil
25+
super.tearDown()
26+
}
27+
28+
// MARK: Tests
29+
30+
func test_thatContainsValidationRuleSetsProperties() {
31+
// then
32+
XCTAssertEqual(sut.substring, "@")
33+
XCTAssertEqual(sut.error.message, .error)
34+
}
35+
36+
func test_thatRuleReturnsTrue_whenInputContainsSubstring() {
37+
// when
38+
let result = sut.validate(input: "user@example.com")
39+
40+
// then
41+
XCTAssertTrue(result)
42+
}
43+
44+
func test_thatRuleReturnsFalse_whenInputDoesNotContainSubstring() {
45+
// when
46+
let result = sut.validate(input: "userexample.com")
47+
48+
// then
49+
XCTAssertFalse(result)
50+
}
51+
52+
func test_thatRuleReturnsFalse_whenInputIsEmpty() {
53+
// when
54+
let result = sut.validate(input: "")
55+
56+
// then
57+
XCTAssertFalse(result)
58+
}
59+
60+
func test_thatRuleReturnsTrue_whenSubstringAppearsMultipleTimes() {
61+
// when
62+
let result = sut.validate(input: "@user@domain.com")
63+
64+
// then
65+
XCTAssertTrue(result)
66+
}
67+
}
68+
69+
// MARK: - Constants
70+
71+
private extension String {
72+
static let error = "Must contain @"
73+
}

0 commit comments

Comments
 (0)