Skip to content
This repository has been archived by the owner on Nov 16, 2020. It is now read-only.

Commit

Permalink
Merge pull request #31 from baarde/betterRangeErrorMessages
Browse files Browse the repository at this point in the history
Use better error messages for RangeValidator and CountValidator
  • Loading branch information
tanner0101 authored Oct 30, 2018
2 parents 156f8ad + 870fe99 commit 4de213c
Show file tree
Hide file tree
Showing 3 changed files with 49 additions and 19 deletions.
25 changes: 13 additions & 12 deletions Sources/Validation/Validators/CountValidator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -38,19 +38,12 @@ extension Validator where T: Collection {
fileprivate struct CountValidator<T>: ValidatorType where T: Collection {
/// See `ValidatorType`.
var validatorReadable: String {
let x: String
if T.self is String.Type {
x = "characters"
} else {
x = "items"
}

if let min = self.min, let max = self.max {
return "between \(min) and \(max) \(x)"
return "between \(min) and \(elementDescription(count: max))"
} else if let min = self.min {
return "at least \(min) \(x)"
return "at least \(elementDescription(count: min))"
} else if let max = self.max {
return "at most \(max) \(x)"
return "at most \(elementDescription(count: max))"
} else {
return "valid"
}
Expand All @@ -75,14 +68,22 @@ fileprivate struct CountValidator<T>: ValidatorType where T: Collection {
func validate(_ data: T) throws {
if let min = self.min {
guard data.count >= min else {
throw BasicValidationError("is not larger than \(min)")
throw BasicValidationError("is less than required minimum of \(elementDescription(count: min))")
}
}

if let max = self.max {
guard data.count <= max else {
throw BasicValidationError("is larger than \(max)")
throw BasicValidationError("is greater than required maximum of \(elementDescription(count: max))")
}
}
}

private func elementDescription(count: Int) -> String {
if T.Element.self is Character.Type {
return count == 1 ? "1 character" : "\(count) characters"
} else {
return count == 1 ? "1 item" : "\(count) items"
}
}
}
4 changes: 2 additions & 2 deletions Sources/Validation/Validators/RangeValidator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -70,13 +70,13 @@ fileprivate struct RangeValidator<T>: ValidatorType where T: Comparable {
func validate(_ data: T) throws {
if let min = self.min {
guard data >= min else {
throw BasicValidationError("is not larger than \(min)")
throw BasicValidationError("is less than \(min)")
}
}

if let max = self.max {
guard data <= max else {
throw BasicValidationError("is larger than \(max)")
throw BasicValidationError("is greater than \(max)")
}
}
}
Expand Down
39 changes: 34 additions & 5 deletions Tests/ValidationTests/ValidationTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -50,21 +50,48 @@ class ValidationTests: XCTestCase {
try Validator<Int>.range(-5...5).validate(4)
try Validator<Int>.range(-5...5).validate(5)
try Validator<Int>.range(-5...5).validate(-5)
XCTAssertThrowsError(try Validator<Int>.range(-5...5).validate(6))
XCTAssertThrowsError(try Validator<Int>.range(-5...5).validate(-6))
XCTAssertThrowsError(try Validator<Int>.range(-5...5).validate(6)) { error in
XCTAssertEqual((error as? ValidationError)?.reason, "data is greater than 5")
}
XCTAssertThrowsError(try Validator<Int>.range(-5...5).validate(-6)) { error in
XCTAssertEqual((error as? ValidationError)?.reason, "data is less than -5")
}

try Validator<Int>.range(5...).validate(.max)

try Validator<Int>.range(-5...5).validate(4)
XCTAssertThrowsError(try Validator<Int>.range(-5...5).validate(6))

try Validator<Int>.range(-5..<6).validate(-5)
try Validator<Int>.range(-5..<6).validate(-4)
try Validator<Int>.range(-5..<6).validate(5)
XCTAssertThrowsError(try Validator<Int>.range(-5..<6).validate(-6))
XCTAssertThrowsError(try Validator<Int>.range(-5..<6).validate(6))
}

func testCountCharacters() throws {
let validator = Validator<String>.count(1...6)
try validator.validate("1")
try validator.validate("123")
try validator.validate("123456")
XCTAssertThrowsError(try validator.validate("")) { error in
XCTAssertEqual((error as? ValidationError)?.reason, "data is less than required minimum of 1 character")
}
XCTAssertThrowsError(try validator.validate("1234567")) { error in
XCTAssertEqual((error as? ValidationError)?.reason, "data is greater than required maximum of 6 characters")
}
}

func testCountItems() throws {
let validator = Validator<[Int]>.count(1...6)
try validator.validate([1])
try validator.validate([1, 2, 3])
try validator.validate([1, 2, 3, 4, 5, 6])
XCTAssertThrowsError(try validator.validate([])) { error in
XCTAssertEqual((error as? ValidationError)?.reason, "data is less than required minimum of 1 item")
}
XCTAssertThrowsError(try validator.validate([1, 2, 3, 4, 5, 6, 7])) { error in
XCTAssertEqual((error as? ValidationError)?.reason, "data is greater than required maximum of 6 items")
}
}

func testURL() throws {
try Validator<String>.url.validate("https://www.somedomain.com/somepath.png")
try Validator<String>.url.validate("https://www.somedomain.com/")
Expand All @@ -80,6 +107,8 @@ class ValidationTests: XCTestCase {
("testEmpty", testEmpty),
("testEmail", testEmail),
("testRange", testRange),
("testCountCharacters", testCountCharacters),
("testCountItems", testCountItems),
("testURL", testURL),
]
}
Expand Down

0 comments on commit 4de213c

Please sign in to comment.