From ca29de43bf35fec22ec88a9606f49a92c039583f Mon Sep 17 00:00:00 2001 From: Nikita Vasilev Date: Mon, 17 Nov 2025 19:54:46 +0400 Subject: [PATCH 1/4] Add `URLValidationRule` implementation --- .../Classes/Rules/URLValidationRule.swift | 31 +++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 Sources/ValidatorCore/Classes/Rules/URLValidationRule.swift diff --git a/Sources/ValidatorCore/Classes/Rules/URLValidationRule.swift b/Sources/ValidatorCore/Classes/Rules/URLValidationRule.swift new file mode 100644 index 0000000..c52f6ae --- /dev/null +++ b/Sources/ValidatorCore/Classes/Rules/URLValidationRule.swift @@ -0,0 +1,31 @@ +// +// Validator +// Copyright © 2025 Space Code. All rights reserved. +// + +import Foundation + +/// A url validation rule. +public struct URLValidationRule: IValidationRule { + // MARK: Types + + public typealias Input = String + + // MARK: Properties + + /// The validation error. + public let error: IValidationError + + // MARK: Initialization + + public init(error: IValidationError) { + self.error = error + } + + // MARK: IValidationRule + + public func validate(input: String) -> Bool { + guard let url = URL(string: input) else { return false } + return url.isFileURL || (url.host != nil && url.scheme != nil) + } +} From 01257b587a9bd1b70f71c93b8c73eaa706007f78 Mon Sep 17 00:00:00 2001 From: Nikita Vasilev Date: Mon, 17 Nov 2025 19:54:55 +0400 Subject: [PATCH 2/4] Write unit tests for `URLValidationRule` --- .../Rules/URLValidationRuleTests.swift | 123 ++++++++++++++++++ 1 file changed, 123 insertions(+) create mode 100644 Tests/ValidatorCoreTests/UnitTests/Rules/URLValidationRuleTests.swift diff --git a/Tests/ValidatorCoreTests/UnitTests/Rules/URLValidationRuleTests.swift b/Tests/ValidatorCoreTests/UnitTests/Rules/URLValidationRuleTests.swift new file mode 100644 index 0000000..b95358e --- /dev/null +++ b/Tests/ValidatorCoreTests/UnitTests/Rules/URLValidationRuleTests.swift @@ -0,0 +1,123 @@ +// +// Validator +// Copyright © 2025 Space Code. All rights reserved. +// + +import ValidatorCore +import XCTest + +// MARK: - URLValidationRuleTests + +final class URLValidationRuleTests: XCTestCase { + // MARK: - Properties + + private var sut: URLValidationRule! + + // MARK: - Setup + + override func setUp() { + super.setUp() + sut = URLValidationRule(error: String.error) + } + + override func tearDown() { + sut = nil + super.tearDown() + } + + // MARK: - Tests + + func test_validate_validURL_shouldReturnTrue() { + // given + let url = "https://google.com" + + // when + let result = sut.validate(input: url) + + // then + XCTAssertTrue(result) + } + + func test_validate_missingScheme_shouldReturnFalse() { + // given + let url = "google.com" + + // when + let result = sut.validate(input: url) + + // then + XCTAssertFalse(result) + } + + func test_validate_missingHost_shouldReturnFalse() { + // given + let url = "https://" + + // when + let result = sut.validate(input: url) + + // then + XCTAssertFalse(result) + } + + func test_validate_emptyString_shouldReturnFalse() { + // given + let url = "" + + // when + let result = sut.validate(input: url) + + // then + XCTAssertFalse(result) + } + + func test_validate_whitespaceString_shouldReturnFalse() { + // given + let url = " " + + // when + let result = sut.validate(input: url) + + // then + XCTAssertFalse(result) + } + + func test_validate_ipAddressURL_shouldReturnTrue() { + // given + let url = "http://192.168.0.1" + + // when + let result = sut.validate(input: url) + + // then + XCTAssertTrue(result) + } + + func test_validate_urlWithPort_shouldReturnTrue() { + // given + let url = "https://localhost:8080" + + // when + let result = sut.validate(input: url) + + // then + XCTAssertTrue(result) + } + + func test_validate_ftpScheme_shouldReturnTrue() { + // given + let url = "ftp://example.com" + + // when + let result = sut.validate(input: url) + + // then + XCTAssertTrue(result) + } +} + +// MARK: Constants + +private extension String { + static let error = "URL is invalid" +} From cc6dd3aa7328e1100f8ab2bf9d56199aafabb04a Mon Sep 17 00:00:00 2001 From: Nikita Vasilev Date: Mon, 17 Nov 2025 20:01:37 +0400 Subject: [PATCH 3/4] Update `README.md` --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index a5c8f11..cc1e0cb 100644 --- a/README.md +++ b/README.md @@ -199,6 +199,7 @@ struct ContentView: View { | **PrefixValidationRule** | To validate whether a string contains a prefix | | **SuffixValidationRule** | To validate whether a string contains a suffix | | **RegexValidationRule** | To validate if a pattern is matched | +| **URLValidationRule** | To validate whether a string contains a URL | ## Custom Validation Rules From ec09b284007d75bb74b84ceaacf2d312caff43da Mon Sep 17 00:00:00 2001 From: Nikita Vasilev Date: Tue, 18 Nov 2025 09:14:55 +0400 Subject: [PATCH 4/4] Update `CHANGELOG.md` --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8c586f3..2db31e8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,8 @@ All notable changes to this project will be documented in this file. #### Added - Add `dependabot.yml` - Added in Pull Request [#21](https://github.com/space-code/validator/pull/21). +- Add `URLValidationRule`. + - Added in Pull Request [#25](https://github.com/space-code/validator/pull/25). #### Updated - Update `Mintfile`