added tests for remote-validation methods and a little refactoring

This commit is contained in:
David Patterson 2016-03-03 23:20:52 -06:00
parent d359bf0683
commit f9fad02c3d
4 changed files with 88 additions and 22 deletions

View File

@ -61,13 +61,13 @@ public class Validator {
have undergone validation attempt.
- parameter completion: Bool that is set to true when all fields have experienced validation attempt.
- returns: No return value.
*/
*/
private func validateAllFields(completion: (finished: Bool) -> Void) {
errors = [:]
for (textField, rule) in validations {
if rule.remoteInfo != nil {
validateRemoteField(textField, completion: { status -> Void in
validateRemoteField(textField, callback: { error -> Void in
self.completedValidationsCount = self.completedValidationsCount + 1
if self.completedValidationsCount == self.validations.count {
// Sends validation back to validate()
@ -91,16 +91,17 @@ public class Validator {
- parameter completion: Closure that holds the status of textField's validation. Is set to true
after remote validation has ended, regardless of whether the validation was a success or failure.
- returns: No return value.
*/
private func validateRemoteField(textField: UITextField, completion: (status: Bool) -> Void) {
*/
public func validateRemoteField(textField: UITextField, callback: (error: ValidationError?) -> Void) {
if let fieldRule = validations[textField] {
// Carry on with validation as regular validation passed
// Carry on with validation only if regular validation passed
if self.validateRegularField(fieldRule.textField) {
delegate!.remoteValidationRequest!(textField.text!, urlString: fieldRule.remoteInfo!.urlString, completion: { result -> Void in
delegate!.remoteValidationRequest?(textField.text!, urlString: fieldRule.remoteInfo!.urlString, completion: { result -> Void in
if result {
if let transform = self.successStyleTransform {
transform(validationRule: fieldRule)
}
callback(error: nil)
} else {
// Stop validation because remote validation failed
// Validation Failed on remote call
@ -109,15 +110,10 @@ public class Validator {
if let transform = self.errorStyleTransform {
transform(validationError: error)
}
callback(error: error)
}
// Validation is over, so let validateAllFields(completion: (status: Bool)) know
completion(status: true)
})
} else {
// Validation is over, so let validateAllFields(completion: (status: Bool)) know
completion(status: true)
}
}
}
@ -133,15 +129,15 @@ public class Validator {
errors[textField] = error
if let transform = self.errorStyleTransform {
transform(validationError: error)
return false
}
return false
} else {
if let transform = self.successStyleTransform {
if fieldRule.remoteInfo == nil {
transform(validationRule: fieldRule)
}
return true
}
return true
}
}
return false

View File

@ -30,14 +30,8 @@ public class ValidationRule {
- parameter rules: array of Rule objects, which text field will be validated against.
- returns: An initialized `ValidationRule` object, or nil if an object could not be created for some reason that would not result in an exception.
*/
public init(textField: UITextField, rules:[Rule], errorLabel:UILabel?, remoteURLString: String? = nil){
self.textField = textField
self.errorLabel = errorLabel
self.rules = rules
//self.remoteURLString = remoteURLString
}
public init(textField: UITextField, rules:[Rule], errorLabel:UILabel?, remoteInfo: (String, String)? = nil){
public init(textField: UITextField, rules:[Rule], errorLabel:UILabel? = nil, remoteInfo: (String, String)? = nil){
self.textField = textField
self.errorLabel = errorLabel
self.rules = rules

View File

@ -37,6 +37,7 @@ class SwiftValidatorTests: XCTestCase {
let REGISTER_TXT_FIELD = UITextField()
let REGISTER_VALIDATOR = Validator()
let REGISTER_VALIDATOR2 = Validator()
let REGISTER_RULES = [Rule]()
let UNREGISTER_TXT_FIELD = UITextField()
@ -48,6 +49,40 @@ class SwiftValidatorTests: XCTestCase {
let ERROR_LABEL = UILabel()
let URL_STRING = "http://localhost:8000/emails/"
let EMAIL_TAKEN_MESSAGE = "Email already taken"
class FailureRemoteValidationViewController: UIViewController, ValidationDelegate {
func validationSuccessful() {
}
func validationFailed(errors: [UITextField : ValidationError]) {
}
func remoteValidationRequest(text: String, urlString: String, completion: (result: Bool) -> Void) {
completion(result: false)
}
}
class SuccessRemoteValidationViewController: UIViewController, ValidationDelegate {
func validationSuccessful() {
}
func validationFailed(errors: [UITextField : ValidationError]) {
}
func remoteValidationRequest(text: String, urlString: String, completion: (result: Bool) -> Void) {
completion(result: true)
}
}
let REGISTER_FAILURE_REMOTE_VALIDATION_DELEGATE = FailureRemoteValidationViewController()
let REGISTER_SUCCESS_REMOTE_VALIDATION_DELEGATE = SuccessRemoteValidationViewController()
override func setUp() {
super.setUp()
// Put setup code here. This method is called before the invocation of each test method in the class.
@ -370,6 +405,43 @@ class SwiftValidatorTests: XCTestCase {
}
}
/// Used to test validation on a single field that has remote validation
func testValidateSuccessSingleRemoteField() {
REGISTER_TXT_FIELD.text = VALID_EMAIL
REGISTER_VALIDATOR.registerField(REGISTER_TXT_FIELD, errorLabel: ERROR_LABEL, rules: [EmailRule()], remoteInfo: (urlString: URL_STRING, error: EMAIL_TAKEN_MESSAGE))
REGISTER_VALIDATOR.delegate = REGISTER_SUCCESS_REMOTE_VALIDATION_DELEGATE
REGISTER_VALIDATOR.validateRemoteField(REGISTER_TXT_FIELD) { error -> Void in
XCTAssertNil(error)
}
}
func testValidateFailureSingleRemoteField() {
REGISTER_TXT_FIELD.text = VALID_EMAIL
REGISTER_VALIDATOR.registerField(REGISTER_TXT_FIELD, errorLabel: ERROR_LABEL, rules: [EmailRule()], remoteInfo: (urlString: URL_STRING, error: EMAIL_TAKEN_MESSAGE))
REGISTER_VALIDATOR.delegate = REGISTER_FAILURE_REMOTE_VALIDATION_DELEGATE
REGISTER_VALIDATOR.validateRemoteField(REGISTER_TXT_FIELD) { error -> Void in
XCTAssertNotNil(error)
}
}
/// Used to test remote validation success
func testValidationSuccessOnRemoteSuccess() {
REGISTER_TXT_FIELD.text = VALID_EMAIL
REGISTER_VALIDATOR.registerField(REGISTER_TXT_FIELD, errorLabel: ERROR_LABEL, rules: [EmailRule()], remoteInfo: (urlString: URL_STRING, error: EMAIL_TAKEN_MESSAGE))
REGISTER_VALIDATOR.delegate = REGISTER_SUCCESS_REMOTE_VALIDATION_DELEGATE
REGISTER_VALIDATOR.validate()
XCTAssert(REGISTER_VALIDATOR.errors.count == 0)
}
/// Used to test remote validation failure
func testValidationFailOnRemoteFailure() {
REGISTER_TXT_FIELD.text = VALID_EMAIL
REGISTER_VALIDATOR.registerField(REGISTER_TXT_FIELD, errorLabel: ERROR_LABEL, rules: [EmailRule()], remoteInfo: (urlString: URL_STRING, error: EMAIL_TAKEN_MESSAGE))
REGISTER_VALIDATOR.delegate = REGISTER_FAILURE_REMOTE_VALIDATION_DELEGATE
REGISTER_VALIDATOR.validate()
XCTAssert(REGISTER_VALIDATOR.errors.count == 1, "There is at least one error")
}
// MARK: Validate error field gets it's text set to the error, if supplied
func testNoErrorMessageSet() {

View File

@ -59,6 +59,10 @@ class ViewController: UIViewController , ValidationDelegate, UITextFieldDelegate
@IBAction func submitTapped(sender: AnyObject) {
print("Validating...")
validator.validateField(UITextField()) { error -> Void in
}
validator.validate()
}
@ -93,7 +97,7 @@ class ViewController: UIViewController , ValidationDelegate, UITextFieldDelegate
}
func validationFailed(errors:[UITextField:ValidationError]) {
print("Validation FAILED!")
print("Validation FAILED!", validator.errors.count)
}
func remoteValidationRequest(text: String, urlString: String, completion: (result: Bool) -> Void) {