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` 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 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) + } +} 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" +}