Uploaded image for project: 'Commons Validator'
  1. Commons Validator
  2. VALIDATOR-168

[validator] Extension to provide test cases for client-side validation

    XMLWordPrintableJSON

Details

    • Improvement
    • Status: Closed
    • Minor
    • Resolution: Won't Fix
    • None
    • None
    • JavaScript
    • None
    • Operating System: All
      Platform: All

    • 32873

    Description

      ABSTRACT: There is a general problem with client side validation in validator.
      It is almost impossible to provide test cases for functions working on forms.
      Instead, if the validator functions focused on what they (should) do best:
      validation, then it would be much simpler to provide tests for all validators. I
      propose making two functions in between forms and validator. One would act as a
      sort of controller (validateField) and another would grab all values from the
      field (grabValuesFromSingleField). Most validators would have the same
      signature: a single parameter of type Array. The most obviest enhancements would
      be easier maintainability, greater clarity and reusability. Another enhancement
      this would provide is conforming to the nature of http: being able to send
      multiple values for any type of single field.

      NOTE: Some discussion about this went on in #32343 with Niall's Javascript
      Rendering Extension. I beleive it would help stop bugs like #32351 and many others.

      PROPOSAL: First of all I want to look at a couple of transformed validator
      functions so we can inmediately get a grasp of the benefits we'll encounter
      (note that the parameter is an array of values and that isAllDigits and trim are
      omitted for clarity):

      function validateRequired(values) {
      var isValid = values.length > 0;
      for (i=0; i<values.length; i++) {
      if (trim(values[i]).length == 0)

      { isValid = false; break; }

      }
      return isValid;
      }

      function validateInteger(values) {
      var isValid = true;
      for (i=0; i<values.length; i++) {
      if (!isAllDigits(values[i]))

      { isValid = false; break; }

      else {
      var iValue = parseInt(values[i]);
      if (isNaN(iValue) || !(iValue >= -2147483648 && iValue <= 2147483647))

      { isValid = false; break; }

      }

      }
      return isValid;
      }

      function testInteger() {
      assertFalse("validateInteger(new Array(\"1\", \"a\", \"b\"))");
      assertTrue("validateInteger(new Array(\"1\", \"-2\", \"44\"))");
      }

      function assertTrue(evalMe) {
      if (eval(evalMe))

      { log("[assertTrue] Test ok for: " + evalMe); }

      else

      { log("[assertTrue] Test failed for: " + evalMe, true); }

      }

      function assertFalse(evalMe) {
      if (eval(evalMe))

      { log("[assertFalse] Test failed for: " + evalMe, true); }

      else

      { log("[assertFalse] Test ok for: " + evalMe); }

      }

              • So to the point now. The "controller" would be:

      function validateField(oField, validatorFunction) {
      if (!oField.type && oField.length && oField[0])

      { //if it has no type it means there are multiple fields with the same name. We shall put the type //for the field for easier handling oField.type = oField[0].type; oField.name = oField[0].name }

      var bValid = true;
      var focusField = oField;
      if (oField.type == 'radio' || oField.type == 'checkbox') {
      var virtualField = oField;
      if (!oField.length)

      { virtualField = new Array(); virtualField.type = oField.type; virtualField.name = oField.name; virtualField[0] = oField; }

      eval("bValid = " + validatorFunction +
      "(grabValuesFromSingleField(virtualField))");
      //no need to focus on these
      focusField = null;
      } else if (oField.length && !oField.options) {
      for (n=oField.length - 1; n>=0; n--) {//reverse so we can focus on the first
      eval("var auxValid = " + validatorFunction +
      "(grabValuesFromSingleField(oField[n]))");
      if (!auxValid)

      { //if it's not valid for a single element it won't be valid bValid = auxValid; focusField = oField[n]; }

      }
      } else

      { eval("bValid = " + validatorFunction + "(grabValuesFromSingleField(oField))"); }

      if (!bValid && focusField && focusField.focus && focusField.style.visibility !=
      'hidden'
      && focusField.disabled == false && focusField.type != 'hidden')

      { focusField.focus(); }

      }

              • and the "grabber":

      function grabValuesFromSingleField(oSingleField) {
      var singleValues = new Array();
      if (oSingleField.type == 'select-multiple') {
      for (s=0; s<oSingleField.options.length; s++) {
      if (oSingleField.options[s].selected)

      { singleValues[singleValues.length] = oSingleField.options[s].value; }

      }
      } else if (oSingleField.type == 'select-one')

      { singleValues[0] = oSingleField.options[oSingleField.selectedIndex].value; }

      else if (oSingleField.type == 'radio' || oSingleField.type == 'checkbox') {
      for (s=0; s<oSingleField.length; s++) {
      if (oSingleField[s].checked)

      { singleValues[singleValues.length] = oSingleField[s].value; }

      }
      } else

      { singleValues[0] = oSingleField.value; }

      return singleValues;
      }

      A html page with this use of the "grabber" can be found at:
      http://www.visual-ma.com/validator/grab.html

      Feedback would be very appreciated. I don't know if this is the way to go but
      IMHO, this should be the direction. We need a way to provide test cases for
      client side validation or we could never assure validator is production ready
      (at least for client-side validation).

      Nacho G. Mac Dowell

      Attachments

        Activity

          People

            Unassigned Unassigned
            mac@apache.org Nacho G. Mac Dowell
            Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

            Dates

              Created:
              Updated:
              Resolved: