How can I unit test event listener in input field?

In the simplest testing, I try to test the following function:

addPercentSign: function (oEvent, control) { var inputVal = oEvent.getParameters().value; var inputNumber = parseFloat(inputVal); if (inputNumber) { if (inputNumber < 50 || inputNumber > 100) { //see learningCurveFormatCheck return null; } else { var finalVal = inputNumber.toFixed(1); var finalOutput = finalVal + "%"; control.learningCurve.setValue(finalOutput); return finalOutput; }; } } 

The above function is an event listener in the input field (id = "learningCurveInput"). When the user enters a value in the field and then fires the send event (via "ENTER"), the addPercentSign function is called.

I understand that with unit tests, the idea is to "isolate" the test as much as possible from any dependencies. Therefore, to test against DOM manipulation, you can attach an element to test.html under a div like this:

 $('<input id="learningCurveInput" type="text"/>').appendTo('#qunit-fixture'); 

Can someone explain what to do next? The function uses an Event object that is passed to retrieve the input value. I'm not sure how to recreate this in a test. I attached my unit test below, but this is just to show my thinking:

 ..., function (formatter, viewControls) { "use strict"; QUnit.module("Formatter Object Exists") QUnit.test("Learning Curve Input Value", function (assert) { $('<input id="learningCurveInput" type="text"/>').appendTo('#qunit-fixture'); $("#learningCurveInput").val("55"); var result = '55'; equals(result, $('#learningCurveInput').val(), "testing input value"); }); QUnit.test("addPecentSign Function", function (assert) { //how to test this dom-dependent function? }); } ); 

Consolidated Question

How can I unit test use the function "addPercentSign" which is called in the 'submit' input field?

+5
source share
1 answer

I suggest splitting this in these parts:

  • Check the conversion from input to output, i.e.: "51" -> "51.0%"
  • Check if your way of changing input value works
  • Check if the event listener you called is called when it is needed.

If all of these tests are successful, you can assume that combining them together will work.

To test the conversion method, I would suggest translating its logic into a separate, clean function. I pasted your format logic below and removed the side effect of setValue . I have included some tests (you should check them and see if you need more / they meet your requirements). As an example, I cited two failed tests.

String formation test:

 function addPercentSign(val) { var inputNumber = parseFloat(val); if (inputNumber) { if (inputNumber < 50 || inputNumber > 100) { //see learningCurveFormatCheck return null; } else { var finalVal = inputNumber.toFixed(1); var finalOutput = finalVal + "%"; return finalOutput; }; }; }; module("String formatting"); test("Returns undefined for unparseable strings", function() { ["foo", null, NaN, "0.0.0"] .forEach(function(result, i, arr) { var result = addPercentSign(result); strictEqual(result, undefined, arr[i] + " produces " + result); }); }); test("Returns null for values below 50 and above 100", function() { ["0", "0.0", "25", "49.99999", "100.00000001", "10300", Infinity] .forEach(function(result, i, arr) { var result = addPercentSign(result); strictEqual(result, null, arr[i] + " produces " + result); }); }); test("Appends a % sign for values between 50 and 100", function() { strictEqual(addPercentSign("51.0"), "51.0%"); // ... }); test("Appends a digit for values without one", function() { strictEqual(addPercentSign("51"), "51.0%"); // ... }); test("Removes and rounds digits for values with more than one", function() { strictEqual(addPercentSign("51.999"), "52.0%"); strictEqual(addPercentSign("51.06"), "51.1%"); // ... }); 
 <link href="https://code.jquery.com/qunit/qunit-1.12.0.css" rel="stylesheet"/> <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <script src="https://code.jquery.com/qunit/qunit-1.12.0.js"></script> <div id="qunit"></div> <div id="qunit-fixture"></div> 

Now that you have received this method, you need to find out if you can get the values โ€‹โ€‹from and enter the values โ€‹โ€‹in the input field. They are similar to the ones you already wrote:

Getting and setting value input

 function createInput() { return $('<input id="learningCurveInput" type="text" value="hello world"/>') .appendTo('#qunit-fixture'); } module("Writing and reading to input", {}) test("writes to value", function(assert) { var $input = createInput(); var result = "55"; // Whatever you're using to set: // in your code, I read `control.learningCurve.setValue` // if that what you're using, that the method you should test $input.val(result); strictEqual($input.val(), result); }); test("reads from value", function(assert) { var $input = createInput(); // Whatever you're using to get the value $input.val(); strictEqual($input.val(), "hello world"); }); 
 <link href="https://code.jquery.com/qunit/qunit-1.12.0.css" rel="stylesheet"/> <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <script src="https://code.jquery.com/qunit/qunit-1.12.0.js"></script> <div id="qunit"></div> <div id="qunit-fixture"></div> 

Now that you know that you can (a) correctly convert the values โ€‹โ€‹and (b) read and write the values โ€‹โ€‹correctly, you will need to check if the value of your variable value โ†’ transform value โ†’ set value is called correctly. For instance:

Testing event listeners

jQuery has several convenient methods for hooking up and running event listeners. You can use .change or submit without an argument to simulate user interface input. Alternatively, you can click on the submit button.

 function createForm() { return $("<form></form>") .append(createInput()); } function createInput() { return $('<input id="learningCurveInput" type="text" value="hello world"/>') .appendTo('#qunit-fixture'); } module("Form event listeners", {}) test("input executes method on change", function(assert) { var called = false; var onChange = function() { called = true; }; var $input = createInput(); $input.change(onChange); $input.val("test"); strictEqual(called, false); $input.change(); strictEqual(called, true); }); test("form executes method on submit", function(assert) { var called = false; var onSubmit = function() { called = true; }; var $form = createForm(); var $input = $form.find("input"); $form.submit(onSubmit); strictEqual(called, false); $form.submit(); strictEqual(called, true); }); 
 <link href="https://code.jquery.com/qunit/qunit-1.12.0.css" rel="stylesheet"/> <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <script src="https://code.jquery.com/qunit/qunit-1.12.0.js"></script> <div id="qunit"></div> <div id="qunit-fixture"></div> 

Conclusion

Now you can determine if your code execution extends to your tests:

 $("form").submit(function() { // Tested in test 3 var $input = $(this).find("input"); var originalValue = $input.val(); // Tested in test 2 var newValue = addPercentSign(originalValue); // Tested in test 1 $input.val(newValue); // Tested in test 2 }); 

Note that this is basically the first test module that has user logic and requirements. If you use jQuery, which is already heavily tested, you will not need to re-test the tests for methods such as .val() : check their public repo to see the coverage for them. If you use special methods to interact with the DOM, you need to test them.

So, in a word: rewrite addPercentageSign will be a pure function that takes a string and returns a string; make sure it is thoroughly tested. Interact with the DOM through the test library or write tests for editing the DOM as well as for listening to events.

+10
source

Source: https://habr.com/ru/post/1261069/


All Articles