Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

πŸ”€ :: Validator λͺ¨λ“ˆ λ°‘μž‘μ—… #90

Merged
merged 3 commits into from
May 22, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,10 @@ public extension TargetDependency.Core {
}

public extension TargetDependency.Shared {
static let Validator = TargetDependency.project(
target: ModulePaths.Shared.Validator.targetName(type: .sources),
path: .relativeToShared(ModulePaths.Shared.Validator.rawValue)
)
static let FoundationUtil = TargetDependency.project(
target: ModulePaths.Shared.FoundationUtil.targetName(type: .sources),
path: .relativeToShared(ModulePaths.Shared.FoundationUtil.rawValue)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ public extension ModulePaths {

public extension ModulePaths {
enum Shared: String {
case Validator
case FoundationUtil
case ViewUtil
case DateUtil
Expand Down
2 changes: 1 addition & 1 deletion Projects/App/Sources/Application/NeedleGenerated.swift
Original file line number Diff line number Diff line change
Expand Up @@ -299,7 +299,7 @@ private func registerProviderFactory(_ componentPath: String, _ factory: @escapi

#if !NEEDLE_DYNAMIC

private func register1() {
@inline(never) private func register1() {
registerProviderFactory("^->AppComponent->JwtStoreComponent", factoryb27d5aae1eb7e73575a6f47b58f8f304c97af4d5)
registerProviderFactory("^->AppComponent", factoryEmptyDependencyProvider)
registerProviderFactory("^->AppComponent->KeychainComponent", factoryEmptyDependencyProvider)
Expand Down
1 change: 1 addition & 0 deletions Projects/Feature/BaseFeature/Project.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ let project = Project.makeModule(
.Shared.DateUtil,
.Shared.FoundationUtil,
.Shared.GlobalThirdPartyLibrary,
.Shared.Validator,
.Shared.UtilityModule
]
)
10 changes: 10 additions & 0 deletions Projects/Shared/Validator/Project.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import ProjectDescription
import ProjectDescriptionHelpers
import DependencyPlugin

let project = Project.makeModule(
name: ModulePaths.Shared.Validator.rawValue,
product: .staticLibrary,
targets: [.unitTest],
internalDependencies: []
)
13 changes: 13 additions & 0 deletions Projects/Shared/Validator/Sources/EmailValidator.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import Foundation

public struct EmailValidator: Validator {
private let regexValidator = RegexValidator(
pattern: "^[a-zA-Z0-9+-_.]+@[a-zA-Z0-9-]+\\.[a-zA-Z0-9-.]+$"
)

public init() {}

public func validate(_ value: String) -> Bool {
regexValidator.validate(value)
}
}
26 changes: 26 additions & 0 deletions Projects/Shared/Validator/Sources/RegexValidator.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import Foundation

public struct RegexValidator: Validator {
private let regexPattern: String
private let regexOptions: NSRegularExpression.Options
private let matchingOptions: NSRegularExpression.MatchingOptions

public init(
pattern: String,
regexOptions: NSRegularExpression.Options = [],
matchingOptions: NSRegularExpression.MatchingOptions = []
) {
self.regexPattern = pattern
self.regexOptions = regexOptions
self.matchingOptions = matchingOptions
}

public func validate(_ value: String) -> Bool {
guard let regex = try? NSRegularExpression(
pattern: regexPattern,
options: regexOptions
) else { return false }
let regexNSRange = (value as NSString).range(of: value)
return regex.firstMatch(in: value, options: matchingOptions, range: regexNSRange) != nil
}
}
15 changes: 15 additions & 0 deletions Projects/Shared/Validator/Sources/StringSizeValidator.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import Foundation

public struct StringSizeValidator: Validator {
private let min: Int
private let max: Int

public init(min: Int = .zero, max: Int = .max) {
self.min = min
self.max = max
}

public func validate(_ value: String) -> Bool {
value.count >= min && value.count <= max
}
}
14 changes: 14 additions & 0 deletions Projects/Shared/Validator/Sources/URLValidator.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import Foundation

public struct URLValidator: Validator {
private let regexValidator = RegexValidator(
pattern: "https?:\\/\\/(www\\.)?[-a-zA-Z0-9@:%._\\+~#=]{2,256}\\.[a-z]{2,6}\\b([-a-zA-Z0-9@:%_\\+.~#()?&//=]*)"
)

public init() {}

public func validate(_ value: String) -> Bool {
regexValidator.validate(value)
}

}
5 changes: 5 additions & 0 deletions Projects/Shared/Validator/Sources/Validator.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
public protocol Validator {
associatedtype WrappedType

func validate(_ value: WrappedType) -> Bool
}
26 changes: 26 additions & 0 deletions Projects/Shared/Validator/Tests/EmailValidatorTests.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import XCTest
@testable import Validator

final class EmailValidatorTests: XCTestCase {
var sut: EmailValidator!

override func setUp() {
sut = EmailValidator()
}

func test_validate_valid_email() {
let validResult1 = sut.validate("test@gmail.com")
XCTAssertTrue(validResult1)

let validResult2 = sut.validate("test@gsm.hs.kr")
XCTAssertTrue(validResult2)
}

func test_validate_invalid_email() {
let invalidResult1 = sut.validate("testgmailcoom")
XCTAssertFalse(invalidResult1)

let invalidResult2 = sut.validate("test@gmailcoom")
XCTAssertFalse(invalidResult2)
}
}
24 changes: 24 additions & 0 deletions Projects/Shared/Validator/Tests/RegexValidatorTests.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import Validator
import XCTest

final class RegexValidatorTests: XCTestCase {
func test_only_string_or_number_validate() {
let validator = RegexValidator(pattern: "^[a-zA-Z0-9]+$")
XCTAssertTrue(validator.validate("abc"))
XCTAssertFalse(validator.validate("abc!"))
}

func test_only_special_characters_validate() {
let validator = RegexValidator(pattern: "^[^a-zA-Z0-9]+$")
XCTAssertTrue(validator.validate("!@#$%^&*()"))
XCTAssertFalse(validator.validate("abc"))
}

func test_email_validate() {
let validator = RegexValidator(pattern: "^[a-zA-Z0-9+-_.]+@[a-zA-Z0-9-]+\\.[a-zA-Z0-9-.]+$")
XCTAssertTrue(validator.validate("test@gmail.com"))
XCTAssertTrue(validator.validate("test@gsm.hs.kr"))
XCTAssertFalse(validator.validate("testgmail.com"))
XCTAssertFalse(validator.validate("test@gmailcom"))
}
}
18 changes: 18 additions & 0 deletions Projects/Shared/Validator/Tests/StringSizeValidatorTests.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import Validator
import XCTest

final class StringSizeValidatorTests: XCTestCase {
func test_validate_valid_string() {
let validator = StringSizeValidator(min: 1, max: 10)
XCTAssertTrue(validator.validate("a"))
XCTAssertTrue(validator.validate("abc"))
XCTAssertTrue(validator.validate("abcde"))
XCTAssertTrue(validator.validate("abcdefghij"))
}

func test_validate_invalid_string() {
let validator = StringSizeValidator(min: 1, max: 10)
XCTAssertFalse(validator.validate(""))
XCTAssertFalse(validator.validate("abcdeABCDEa"))
}
}
28 changes: 28 additions & 0 deletions Projects/Shared/Validator/Tests/URLValidatorTests.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import Validator
import XCTest

final class URLValidatorTests: XCTestCase {
var sut: URLValidator!

override func setUp() {
super.setUp()
sut = URLValidator()
}

func test_validate_valid_url() {
XCTAssertTrue(sut.validate("https://www.google.com"))
XCTAssertTrue(sut.validate("http://www.google.com"))
XCTAssertTrue(sut.validate("http://google.com"))
XCTAssertTrue(sut.validate("https://google.com"))
XCTAssertTrue(sut.validate("https://www.naver.com"))
XCTAssertTrue(sut.validate("https://github.com"))
XCTAssertTrue(sut.validate("http://github.com"))
XCTAssertTrue(sut.validate("https://www.apple.com"))
}

func test_validate_invalid_url() {
XCTAssertFalse(sut.validate("www.google"))
XCTAssertFalse(sut.validate("www.naver.com"))
XCTAssertFalse(sut.validate("github.com"))
}
}