How to check jquery and ajax calls using JsTestDriver?

I have a dynamic page built using jQuery. Html parts are loaded from mustache templates. These templates are loaded from the URL, and I would like to unit test the general html construct:

JsTestDriver Test:

AppTest = TestCase("AppTest") AppTest.prototype.test = function() { var actualHtml = ""; getHtml({ "title": "title", "header": "header", "text": "text", "authors": [ {"firstname": "firstname", "lastname": "lastname"} ] }, function(html) { actualHtml = html; }); assertEquals("expected html", actualHtml); }; 

And the code:

 function getHtml(json, resultFunc) { jQuery.ajax({ url: "url/to/mustache/template", success: function(view) { resultFunc(mergeArticleModelAndView(json, view)); }, error: function(jqXHR, textStatus, errorThrown) { resultFunc(textStatus + " errorThrown: " + errorThrown); }, dataType: 'text', async: false }); } 

Then I run the tests, and the result:

 $ java -jar JsTestDriver-1.3.2.jar --port 9876 --browser /usr/bin/firefox --tests all F Total 1 tests (Passed: 0; Fails: 1; Errors: 0) (8,00 ms) Firefox 5.0 Linux: Run 1 tests (Passed: 0; Fails: 1; Errors 0) (8,00 ms) AppTest.test failed (8,00 ms): AssertError: expected "expected html" but was "error errorThrown: [Exception... \"Component returned failure code: 0x80004005 (NS_ERROR_FAILURE)\" nsresult: \"0x80004005 (NS_ERROR_FAILURE)\" location: \"JS frame :: http://localhost:9876/test/main/js/jquery.min.js :: <TOP_LEVEL> :: line 16\" data: no]" ()@http://localhost:9876/test/test/js/app_test.js:25 

So, the error callback was called, and I don’t understand why it breaks with JsTestDriver, and the code works when calling the application manually using the browser

Last thing, jsTestDriver.conf:

 server: http://localhost:9876 load: - test/js/app_test.js - main/js/jquery.min.js - main/js/jquery.mustache.js - main/js/app.js 

Thanks for your advice. More generally, what unit test frameworks do you use to test javascript and command line using DOM and jQuery?

+6
source share
4 answers

Yes, you can do the same with jquery:

Test code (only test setup is the same):

 TestCase("AppTest", { setUp: function() { this.xhr = Object.create(fakeXMLHttpRequest); this.xhr.send=function () { this.readyState = 4; }; this.xhr.getAllResponseHeaders=stubFn({}); this.xhr.responseText="<expected data>"; jQuery.ajaxSettings.isLocal=stubFn(true); jQuery.ajaxSettings.xhr=stubFn(this.xhr); }, // same test method 

And production code:

 function getHtml(model, resultFunc) { $.get("/url/to/template", function(view) { resultFunc(mergeArticleModelAndView(model, view)); }); } 

This is the solution we have chosen.

+3
source

An alternative would be to force JsTestDriver to serve your template and some JSON test data. In the configuration below, you can put static JSON test data (e.g. my_data.json) in src / test / webapp / json and Mustache templates in src / main / webapp / templates. You can change this around to fit the original layout if it is too Maven-y for your tastes.

Note that JsTestDriver serves resources with / test / pre -pended to the URIs specified in the serve attribute, therefore src / test / webapp / json / my_data.json is actually served with http: // localhost: 9876 / test / src / test /webapp/json/my_data.json.

 server: http://localhost:9876 serve: - src/main/webapp/templates/*.html - src/test/webapp/json/*.json load: - src/main/webapp/js/*.js - src/main/webapp/js/libs/*.js test: - src/test/webapp/js/*.js 

Then in the test case, you can easily load the template data and JSON.

  testLoadTemplateAndData : function () { // Variables var onComplete, template, data, expected, actual, templateLoaded, dataLoaded; dataLoaded = false; templateLoaded = false; expected = "<h2>Your expected markup</h2>"; // Completion action onComplete = function () { if (dataLoaded && templateLoaded) { // Render the template and data actual = Mustache.to_html(template, data); // Compare with expected assertEquals('Markup should match', expected, actual); } }; // Load data with jQuery $.ajax({ url : '/test/src/test/webapp/json/demo.json', success : function (result) { data = result; dataLoaded = true; }, error : function () { fail("Data did not load."); }, complete : function () { onComplete(); } } ); // Load the template with jQuery $.get('/test/src/main/webapp/templates/demo.html', function(result) { template = result; templateLoaded = true; } ) .error(function() { fail("Template did not load."); }) .complete(function() { onComplete(); }); } 

When both jQuery callbacks are complete, Mustache should parse the template with JSON data and display the expected result.

+5
source

I found a way to do this: mock ajax calls. There is an example at http://tddjs.com/ that can be done in chapter 12, and the git repository is here: http://tddjs.com/code/12-abstracting-browser-differences-ajax.git

So the test code is:

 TestCase("AppTest", { setUp: function() { tddjs.isLocal = stubFn(true); var ajax = tddjs.ajax; this.xhr = Object.create(fakeXMLHttpRequest); this.xhr.send=function () { this.readyState = 4; this.onreadystatechange(); }; this.xhr.responseText="<expected data>"; ajax.create = stubFn(this.xhr); }, "test article html ok": function () { var actualHtml = ""; getHtml({ "title": "title", "header": "header", "text": "text", "authors": [ {"firstname": "firstname", "lastname": "lastname"} ] }, function(html) { actualHtml = html; }); assertEquals("<expected html>", actualHtml); } }); 

And production code:

 function getHtml(model, resultFunc) { tddjs.ajax.get("http://url/to/template", { success: function (xhr) { resultFunc(mergeArticleModelAndView(model, xhr.responseText)); } }); } 

After reading jQuery code, I think you can make fun of jQuery ajax request. Cf also jquery 1.5 mock ajax

+4
source

With sinon.js, this is even simpler:

 TestCase("AppTest", { setUp: function() { this.server = sinon.fakeServer.create(); }, tearDown: function() { this.server.restore(); }, "test article html ok": function () { this.server.respondWith("mustache template"); this.server.respond(); var actualHtml = ""; getHtml({ "title": "title", "header": "header", "text": "text", "authors": [ {"firstname": "firstname", "lastname": "lastname"} ] }, function(html) { actualHtml = html; }); assertEquals("<expected html>", actualHtml); } 
0
source

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


All Articles