Skip to contentSkip to conversation

Use Jquery's Qunit tests to create some unit tests for javascript

PATCH In review brian avery 3 participants 6 messages Aug 20, 2015 – Sep 10, 2015

lore
Share & tools
lore
#0 lore raw

cover Use Jquery's Qunit tests to create some unit tests for javascript

Use Jquery's Qunit tests to create some unit tests for javascript.

The following changes since commit c348fa50186fb0796bc7b793c4b8d710419f2a0d:

bitbake: toaster: move code from setup_lv_tests to setUp (2015-08-17 14:41:45 +0100)

are available in the git repository at:

git://git.yoctoproject.org/poky-contrib bavery/submit/michaelw/20150817_qunit-tests
http://git.yoctoproject.org/cgit.cgi/poky-contrib/log/?h=bavery/submit/michaelw/20150817_qunit-tests

Michael Wood (1):
toastergui: Add frontend javascript unit tests

 lib/toaster/toastergui/static/js/tests/test.js     | 175 +++++++++++++++++++++
 .../toastergui/templates/js-unit-tests.html        |  39 +++++
 lib/toaster/toastergui/urls.py                     |   3 +
 lib/toaster/toastergui/views.py                    |  16 ++
 4 files changed, 233 insertions(+)
 create mode 100644 bitbake/lib/toaster/toastergui/static/js/tests/test.js
 create mode 100644 bitbake/lib/toaster/toastergui/templates/js-unit-tests.html
Signature · 1 line
1.9.1
#1 lore raw

PATCH 1/1 toastergui: Add frontend javascript unit tests

From: Michael Wood <[email protected]>

Use Jquery's Qunit tests to create some unit tests for javascript components used in toaster.

---
 lib/toaster/toastergui/static/js/tests/test.js     | 175 +++++++++++++++++++++
 .../toastergui/templates/js-unit-tests.html        |  39 +++++
 lib/toaster/toastergui/urls.py                     |   3 +
 lib/toaster/toastergui/views.py                    |  16 ++
 4 files changed, 233 insertions(+)
 create mode 100644 bitbake/lib/toaster/toastergui/static/js/tests/test.js
 create mode 100644 bitbake/lib/toaster/toastergui/templates/js-unit-tests.html
lib/toaster/toastergui/static/js/tests/test.js new file +175 -0
new file mode 100644
index 0000000..d610113
@@ -0,0 +1,175 @@
+"use strict";
+/* Unit tests for Toaster's JS */
+
+/* libtoaster tests */
+
+QUnit.test("Layer alert notification", function(assert) {
+  var layer = {
+    "layerdetailurl":"/toastergui/project/1/layer/22",
+    "vcs_url":"git://example.com/example.git",
+    "detail":"[ git://example.com/example.git | master ]",
+    "vcs_reference":"master",
+    "id": 22,
+    "name":"meta-example"
+  };
+
+  var correctResponse = "You have added <strong>3</strong> layers to your project: <a id=\"layer-affected-name\" href=\"/toastergui/project/1/layer/22\">meta-example</a> and its dependencies <a href=\"/toastergui/project/1/layer/9\" data-original-title=\"\" title=\"\">meta-example-two</a>, <a href=\"/toastergui/project/1/layer/9\" data-original-title=\"\" title=\"\">meta-example-three</a>";
+
+  var layerDepsList = [
+    {
+    "layerdetailurl":"/toastergui/project/1/layer/9",
+    "vcs_url":"git://example.com/example.git",
+    "detail":"[ git://example.com/example.git | master ]",
+    "vcs_reference":"master",
+    "id": 9,
+    "name":"meta-example-two"
+    },
+    {
+    "layerdetailurl":"/toastergui/project/1/layer/9",
+    "vcs_url":"git://example.com/example.git",
+    "detail":"[ git://example.com/example.git | master ]",
+    "vcs_reference":"master",
+    "id": 10,
+    "name":"meta-example-three"
+    },
+  ];
+
+  var msg = libtoaster.makeLayerAddRmAlertMsg(layer, layerDepsList, true);
+  var test = $("<div></div>");
+
+  test.html(msg);
+
+  assert.equal(test.children("strong").text(), "3");
+  assert.equal(test.children("a").length, 3);
+});
+
+QUnit.test("Project info", function(assert){
+  var done = assert.async();
+  libtoaster.getProjectInfo(libtoaster.ctx.projectPageUrl, function(prjInfo){
+    assert.ok(prjInfo.machine.name);
+    assert.ok(prjInfo.releases.length > 0);
+    assert.ok(prjInfo.layers.length > 0);
+    assert.ok(prjInfo.freqtargets);
+    assert.ok(prjInfo.release);
+    done();
+  });
+});
+
+QUnit.test("Show notification", function(assert){
+  var msg = "Testing";
+  var element = $("#change-notification-msg");
+
+  libtoaster.showChangeNotification(msg);
+
+  assert.equal(element.text(), msg);
+  assert.ok(element.is(":visible"));
+
+  $("#change-notification").hide();
+});
+
+var layer = {
+  "id": 91,
+  "name":  "meta-crystalforest",
+  "layerdetailurl": "/toastergui/project/4/layer/91"
+};
+
+QUnit.test("Add layer", function(assert){
+  var done = assert.async();
+
+  /* Wait for the modal to be added to the dom */
+  var checkModal = setInterval(function(){
+    if ($("#dependencies-modal").length > 0) {
+      $("#dependencies-modal .btn-primary").click();
+      clearInterval(checkModal);
+    }
+  }, 200);
+
+  libtoaster.addRmLayer(layer, true, function(deps){
+    assert.equal(deps.length, 1);
+    done();
+  });
+
+});
+
+QUnit.test("Rm layer", function(assert){
+  var done = assert.async();
+
+  libtoaster.addRmLayer(layer, false, function(deps){
+    assert.equal(deps.length, 0);
+    done();
+  });
+
+});
+
+QUnit.test("Parse url params", function(assert){
+  var params = libtoaster.parseUrlParams();
+  assert.ok(params);
+});
+
+QUnit.test("Dump url params", function(assert){
+  var params = libtoaster.dumpsUrlParams();
+  assert.ok(params);
+});
+
+QUnit.test("Make typeaheads", function(assert){
+  var layersT = $("#layers");
+  var machinesT = $("#machines");
+  var projectsT = $("#projects");
+  var recipesT = $("#recipes");
+
+  libtoaster.makeTypeahead(layersT,
+    libtoaster.ctx.layersTypeAheadUrl, {}, function(){});
+
+  libtoaster.makeTypeahead(machinesT,
+    libtoaster.ctx.machinesTypeAheadUrl, {}, function(){});
+
+  libtoaster.makeTypeahead(projectsT,
+    libtoaster.ctx.projectsTypeAheadUrl, {}, function(){});
+
+  libtoaster.makeTypeahead(recipesT,
+    libtoaster.ctx.recipesTypeAheadUrl, {}, function(){});
+
+  assert.ok(recipesT.data('typeahead'));
+  assert.ok(layersT.data('typeahead'));
+  assert.ok(projectsT.data('typeahead'));
+  assert.ok(recipesT.data('typeahead'));
+});
+
+
+
+/* Page init functions */
+
+QUnit.test("Import layer page init", function(assert){
+  assert.throws(importLayerPageInit());
+});
+
+QUnit.test("Project page init", function(assert){
+  assert.throws(projectPageInit());
+});
+
+QUnit.test("Layer details page init", function(assert){
+  assert.throws(layerDetailsPageInit());
+});
+
+QUnit.test("Layer btns init", function(assert){
+  assert.throws(layerBtnsInit({ projectLayers : [] }));
+});
+
+QUnit.test("Table init", function(assert){
+  assert.throws(tableInit({ url : tableUrl }));
+});
+
+$(document).ajaxError(function(event, jqxhr, settings, errMsg){
+  if (errMsg === 'abort')
+    return;
+
+  QUnit.test("Ajax error", function(assert){
+    assert.notOk(jqxhr.responseText);
+  });
+});
+
+
+
+
+
+
lib/toaster/toastergui/templates/js-unit-tests.html new file +39 -0
new file mode 100644
index 0000000..5b8fd84
@@ -0,0 +1,39 @@
+{% extends "base.html" %}
+{% load projecttags %}
+{% load humanize %}
+{% load static %}
+{% block pagecontent %}
+
+<link rel="stylesheet" href="//code.jquery.com/qunit/qunit-1.18.0.css" />
+
+<script src="//code.jquery.com/qunit/qunit-1.18.0.js"></script>
+
+<script src="{% static 'js/layerDepsModal.js' %}"></script>
+<script src="{% static 'js/projectpage.js' %}"></script>
+
+<script src="{% static 'js/bootstrap.min.js' %}"></script>
+<script src="{% static 'js/filtersnippet.js' %}"></script>
+<script src="{% static 'js/importlayer.js' %}"></script>
+<script src="{% static 'js/prettify.js' %}"></script>
+<script src="{% static 'js/layerBtn.js' %}"></script>
+<script src="{% static 'js/layerDepsModal.js' %}"></script>
+<script src="{% static 'js/projectpage.js' %}"></script>
+<script src="{% static 'js/layerdetails.js' %}"></script>
+<script src="{% static 'js/table.js' %}"></script>
+
+<script>
+  var tableUrl = '{% url 'projectlayers' project.pk %}';
+</script>
+
+<script src="{% static 'js/tests/test.js' %}"></script>
+
+<div id="qunit"></div>
+
+<input type="text" id="layers" placeholder="layers" ></input>
+<input type="text" id="recipes" placeholder="recipes"></input>
+<input type="text" id="projects" placeholder="projects"></input>
+<input type="text" id="machines" placeholder="machines"></input>
+
+{% endblock %}
+
+
lib/toaster/toastergui/urls.py +3 -0
index f74090b..46e5761 100644
@@ -145,6 +145,9 @@ urlpatterns = patterns('toastergui.views',
         url(r'^xhr_importlayer/$', 'xhr_importlayer', name='xhr_importlayer'),
         url(r'^xhr_updatelayer/$', 'xhr_updatelayer', name='xhr_updatelayer'),
 
+        # JS Unit tests
+        url(r'^js-unit-tests/$', 'jsunittests', name='js-unit-tests'),
+
         # default redirection
         url(r'^$', RedirectView.as_view( url= 'landing')),
 )
lib/toaster/toastergui/views.py +16 -0
index 889b6c6..e39baad 100755
@@ -27,6 +27,7 @@ from django.shortcuts import render, redirect
 from orm.models import Build, Target, Task, Layer, Layer_Version, Recipe, LogMessage, Variable
 from orm.models import Task_Dependency, Recipe_Dependency, Package, Package_File, Package_Dependency
 from orm.models import Target_Installed_Package, Target_File, Target_Image_File, BuildArtifact
+from orm.models import BitbakeVersion
 from bldcontrol import bbcontroller
 from django.views.decorators.cache import cache_control
 from django.core.urlresolvers import reverse
@@ -2255,6 +2256,21 @@ if True:
 
         return context
 
+    def jsunittests(request):
+      """ Provides a page for the js unit tests """
+      bbv = BitbakeVersion.objects.filter(branch="master").first()
+      release = Release.objects.filter(bitbake_version=bbv).first()
+
+      name = "_js_unit_test_prj_"
+
+      # If there is an existing project by this name delete it. We don't want
+      # Lots of duplicates cluttering up the projects.
+      Project.objects.filter(name=name).delete()
+
+      new_project = Project.objects.create_project(name=name, release=release)
+
+      context = { 'project' : new_project }
+      return render(request, "js-unit-tests.html", context)
 
     from django.views.decorators.csrf import csrf_exempt
     @csrf_exempt
Signature · 1 line
1.9.1
#2 lore raw

Re: [PATCH 1/1] toastergui: Add frontend javascript unit tests

Quoted 280 lines · brian avery

From: Michael Wood <[email protected]>

Use Jquery's Qunit tests to create some unit tests for javascript components used in toaster.

---
  lib/toaster/toastergui/static/js/tests/test.js     | 175 +++++++++++++++++++++
  .../toastergui/templates/js-unit-tests.html        |  39 +++++
  lib/toaster/toastergui/urls.py                     |   3 +
  lib/toaster/toastergui/views.py                    |  16 ++
  4 files changed, 233 insertions(+)

create mode 100644 bitbake/lib/toaster/toastergui/static/js/tests/test.js create mode 100644 bitbake/lib/toaster/toastergui/templates/js-unit-tests.html

lib/toaster/toastergui/static/js/tests/test.js new file +175 -0
new file mode 100644
index 0000000..d610113
@@ -0,0 +1,175 @@
+"use strict";
+/* Unit tests for Toaster's JS */
+
+/* libtoaster tests */
+
+QUnit.test("Layer alert notification", function(assert) {
+  var layer = {
+    "layerdetailurl":"/toastergui/project/1/layer/22",
+    "vcs_url":"git://example.com/example.git",
+    "detail":"[ git://example.com/example.git | master ]",
+    "vcs_reference":"master",
+    "id": 22,
+    "name":"meta-example"
+  };
+
+  var correctResponse = "You have added <strong>3</strong> layers to your project: <a id=\"layer-affected-name\" href=\"/toastergui/project/1/layer/22\">meta-example</a> and its dependencies <a href=\"/toastergui/project/1/layer/9\" data-original-title=\"\" title=\"\">meta-example-two</a>, <a href=\"/toastergui/project/1/layer/9\" data-original-title=\"\" title=\"\">meta-example-three</a>";
+
+  var layerDepsList = [
+    {
+    "layerdetailurl":"/toastergui/project/1/layer/9",
+    "vcs_url":"git://example.com/example.git",
+    "detail":"[ git://example.com/example.git | master ]",
+    "vcs_reference":"master",
+    "id": 9,
+    "name":"meta-example-two"
+    },
+    {
+    "layerdetailurl":"/toastergui/project/1/layer/9",
+    "vcs_url":"git://example.com/example.git",
+    "detail":"[ git://example.com/example.git | master ]",
+    "vcs_reference":"master",
+    "id": 10,
+    "name":"meta-example-three"
+    },
+  ];
+
+  var msg = libtoaster.makeLayerAddRmAlertMsg(layer, layerDepsList, true);
+  var test = $("<div></div>");
+
+  test.html(msg);
+
+  assert.equal(test.children("strong").text(), "3");
+  assert.equal(test.children("a").length, 3);
+});
+
+QUnit.test("Project info", function(assert){
+  var done = assert.async();
+  libtoaster.getProjectInfo(libtoaster.ctx.projectPageUrl, function(prjInfo){
+    assert.ok(prjInfo.machine.name);
+    assert.ok(prjInfo.releases.length > 0);
+    assert.ok(prjInfo.layers.length > 0);
+    assert.ok(prjInfo.freqtargets);
+    assert.ok(prjInfo.release);
+    done();
+  });
+});
+
+QUnit.test("Show notification", function(assert){
+  var msg = "Testing";
+  var element = $("#change-notification-msg");
+
+  libtoaster.showChangeNotification(msg);
+
+  assert.equal(element.text(), msg);
+  assert.ok(element.is(":visible"));
+
+  $("#change-notification").hide();
+});
+
+var layer = {
+  "id": 91,
+  "name":  "meta-crystalforest",
+  "layerdetailurl": "/toastergui/project/4/layer/91"
+};
+
+QUnit.test("Add layer", function(assert){
+  var done = assert.async();
+
+  /* Wait for the modal to be added to the dom */
+  var checkModal = setInterval(function(){
+    if ($("#dependencies-modal").length > 0) {
+      $("#dependencies-modal .btn-primary").click();
+      clearInterval(checkModal);
+    }
+  }, 200);
+
+  libtoaster.addRmLayer(layer, true, function(deps){
+    assert.equal(deps.length, 1);
+    done();
+  });
+
+});
+
+QUnit.test("Rm layer", function(assert){
+  var done = assert.async();
+
+  libtoaster.addRmLayer(layer, false, function(deps){
+    assert.equal(deps.length, 0);
+    done();
+  });
+
+});
+
+QUnit.test("Parse url params", function(assert){
+  var params = libtoaster.parseUrlParams();
+  assert.ok(params);
+});
+
+QUnit.test("Dump url params", function(assert){
+  var params = libtoaster.dumpsUrlParams();
+  assert.ok(params);
+});
+
+QUnit.test("Make typeaheads", function(assert){
+  var layersT = $("#layers");
+  var machinesT = $("#machines");
+  var projectsT = $("#projects");
+  var recipesT = $("#recipes");
+
+  libtoaster.makeTypeahead(layersT,
+    libtoaster.ctx.layersTypeAheadUrl, {}, function(){});
+
+  libtoaster.makeTypeahead(machinesT,
+    libtoaster.ctx.machinesTypeAheadUrl, {}, function(){});
+
+  libtoaster.makeTypeahead(projectsT,
+    libtoaster.ctx.projectsTypeAheadUrl, {}, function(){});
+
+  libtoaster.makeTypeahead(recipesT,
+    libtoaster.ctx.recipesTypeAheadUrl, {}, function(){});
+
+  assert.ok(recipesT.data('typeahead'));
+  assert.ok(layersT.data('typeahead'));
+  assert.ok(projectsT.data('typeahead'));
+  assert.ok(recipesT.data('typeahead'));
+});
+
+
+
+/* Page init functions */
+
+QUnit.test("Import layer page init", function(assert){
+  assert.throws(importLayerPageInit());
+});
+
+QUnit.test("Project page init", function(assert){
+  assert.throws(projectPageInit());
+});
+
+QUnit.test("Layer details page init", function(assert){
+  assert.throws(layerDetailsPageInit());
+});
+
+QUnit.test("Layer btns init", function(assert){
+  assert.throws(layerBtnsInit({ projectLayers : [] }));
+});
+
+QUnit.test("Table init", function(assert){
+  assert.throws(tableInit({ url : tableUrl }));
+});
+
+$(document).ajaxError(function(event, jqxhr, settings, errMsg){
+  if (errMsg === 'abort')
+    return;
+
+  QUnit.test("Ajax error", function(assert){
+    assert.notOk(jqxhr.responseText);
+  });
+});
+
+
+
+
+
+
lib/toaster/toastergui/templates/js-unit-tests.html new file +39 -0
new file mode 100644
index 0000000..5b8fd84
@@ -0,0 +1,39 @@
+{% extends "base.html" %}
+{% load projecttags %}
+{% load humanize %}
+{% load static %}
+{% block pagecontent %}
+
+<link rel="stylesheet" href="//code.jquery.com/qunit/qunit-1.18.0.css" />
+
+<script src="//code.jquery.com/qunit/qunit-1.18.0.js"></script>
+
+<script src="{% static 'js/layerDepsModal.js' %}"></script>
+<script src="{% static 'js/projectpage.js' %}"></script>
+
+<script src="{% static 'js/bootstrap.min.js' %}"></script>
+<script src="{% static 'js/filtersnippet.js' %}"></script>
+<script src="{% static 'js/importlayer.js' %}"></script>
+<script src="{% static 'js/prettify.js' %}"></script>
+<script src="{% static 'js/layerBtn.js' %}"></script>
+<script src="{% static 'js/layerDepsModal.js' %}"></script>
+<script src="{% static 'js/projectpage.js' %}"></script>
+<script src="{% static 'js/layerdetails.js' %}"></script>
+<script src="{% static 'js/table.js' %}"></script>
+
+<script>
+  var tableUrl = '{% url 'projectlayers' project.pk %}';
+</script>
+
+<script src="{% static 'js/tests/test.js' %}"></script>
+
+<div id="qunit"></div>
+
+<input type="text" id="layers" placeholder="layers" ></input>
+<input type="text" id="recipes" placeholder="recipes"></input>
+<input type="text" id="projects" placeholder="projects"></input>
+<input type="text" id="machines" placeholder="machines"></input>
+
+{% endblock %}
+
+
lib/toaster/toastergui/urls.py +3 -0
index f74090b..46e5761 100644
@@ -145,6 +145,9 @@ urlpatterns = patterns('toastergui.views',
          url(r'^xhr_importlayer/$', 'xhr_importlayer', name='xhr_importlayer'),
          url(r'^xhr_updatelayer/$', 'xhr_updatelayer', name='xhr_updatelayer'),
 
+        # JS Unit tests
+        url(r'^js-unit-tests/$', 'jsunittests', name='js-unit-tests'),
+
          # default redirection
          url(r'^$', RedirectView.as_view( url= 'landing')),
  )
lib/toaster/toastergui/views.py +9 -0
index 889b6c6..e39baad 100755
@@ -27,6 +27,7 @@ from django.shortcuts import render, redirect
  from orm.models import Build, Target, Task, Layer, Layer_Version, Recipe, LogMessage, Variable
  from orm.models import Task_Dependency, Recipe_Dependency, Package, Package_File, Package_Dependency
  from orm.models import Target_Installed_Package, Target_File, Target_Image_File, BuildArtifact
+from orm.models import BitbakeVersion
  from bldcontrol import bbcontroller
  from django.views.decorators.cache import cache_control
  from django.core.urlresolvers import reverse
@@ -2255,6 +2256,21 @@ if True:
 
          return context
 
+    def jsunittests(request):
+      """ Provides a page for the js unit tests """
+      bbv = BitbakeVersion.objects.filter(branch="master").first()
+      release = Release.objects.filter(bitbake_version=bbv).first()
+
+      name = "_js_unit_test_prj_"
+
+      # If there is an existing project by this name delete it. We don't want

lib/toaster/toastergui/views.py if True: · line 2276

Quoted 10 lines
lib/toaster/toastergui/views.py +7 -0
+      # Lots of duplicates cluttering up the projects.
+      Project.objects.filter(name=name).delete()
+
+      new_project = Project.objects.create_project(name=name, release=release)
+
+      context = { 'project' : new_project }
+      return render(request, "js-unit-tests.html", context)
 
      from django.views.decorators.csrf import csrf_exempt
      @csrf_exempt

This patch seems to have landed without the new files
http://cgit.openembedded.org/bitbake/commit/?id=1c2f6b9b7b9e700146944b9d6d2114e0d014ee81

-rw-r--r-- lib/toaster/toastergui/urls.py 3
-rwxr-xr-x lib/toaster/toastergui/views.py 16

2 files changed, 19 insertions, 0 deletions
#3 lore raw

Re: [PATCH 1/1] toastergui: Add frontend javascript unit tests

yes, the following files were new in the patch and were not created:
lib/toaster/toastergui/static/js/tests/test.js b/lib/toaster/toastergui/static/js/tests/test.js lib/toaster/toastergui/templates/js-unit-tests.html b/lib/toaster/toastergui/templates/js-unit-tests.html

-bavery

Quoted 320 lines · Michael Wood
Quoted 304 lines · brian avery

From: Michael Wood <[email protected]>

Use Jquery's Qunit tests to create some unit tests for javascript components used in toaster.

---
  lib/toaster/toastergui/static/js/tests/test.js     | 175
+++++++++++++++++++++
  .../toastergui/templates/js-unit-tests.html        |  39 +++++
  lib/toaster/toastergui/urls.py                     |   3 +
  lib/toaster/toastergui/views.py                    |  16 ++
  4 files changed, 233 insertions(+)

create mode 100644
bitbake/lib/toaster/toastergui/static/js/tests/test.js
create mode 100644
bitbake/lib/toaster/toastergui/templates/js-unit-tests.html

lib/toaster/toastergui/static/js/tests/test.js new file +16 -0
new file mode 100644
index 0000000..d610113
@@ -0,0 +1,175 @@
+"use strict";
+/* Unit tests for Toaster's JS */
+
+/* libtoaster tests */
+
+QUnit.test("Layer alert notification", function(assert) {
+  var layer = {
+    "layerdetailurl":"/toastergui/project/1/layer/22",
+    "vcs_url":"git://example.com/example.git",
+    "detail":"[ git://example.com/example.git | master ]",
+    "vcs_reference":"master",
+    "id": 22,
+    "name":"meta-example"
+  };
+
+  var correctResponse = "You have added <strong>3</strong> layers to your

project: <a id=\"layer-affected-name\" href=\"/toastergui/project/1/layer/22\">meta-example</a> and its dependencies <a href=\"/toastergui/project/1/layer/9\" data-original-title=\"\" title=\"\">meta-example-two</a>, <a href=\"/toastergui/project/1/layer/9\" data-original-title=\"\" title=\"\">meta-example-three</a>";

lib/toaster/toastergui/static/js/tests/test.js new file +21 -0
+
+  var layerDepsList = [
+    {
+    "layerdetailurl":"/toastergui/project/1/layer/9",
+    "vcs_url":"git://example.com/example.git",
+    "detail":"[ git://example.com/example.git | master ]",
+    "vcs_reference":"master",
+    "id": 9,
+    "name":"meta-example-two"
+    },
+    {
+    "layerdetailurl":"/toastergui/project/1/layer/9",
+    "vcs_url":"git://example.com/example.git",
+    "detail":"[ git://example.com/example.git | master ]",
+    "vcs_reference":"master",
+    "id": 10,
+    "name":"meta-example-three"
+    },
+  ];
+
+  var msg = libtoaster.makeLayerAddRmAlertMsg(layer, layerDepsList,

true);

lib/toaster/toastergui/static/js/tests/test.js new file +11 -0
+  var test = $("<div></div>");
+
+  test.html(msg);
+
+  assert.equal(test.children("strong").text(), "3");
+  assert.equal(test.children("a").length, 3);
+});
+
+QUnit.test("Project info", function(assert){
+  var done = assert.async();
+  libtoaster.getProjectInfo(libtoaster.ctx.projectPageUrl,

function(prjInfo){

lib/toaster/toastergui/static/js/tests/test.js new file +127 -0
+    assert.ok(prjInfo.machine.name);
+    assert.ok(prjInfo.releases.length > 0);
+    assert.ok(prjInfo.layers.length > 0);
+    assert.ok(prjInfo.freqtargets);
+    assert.ok(prjInfo.release);
+    done();
+  });
+});
+
+QUnit.test("Show notification", function(assert){
+  var msg = "Testing";
+  var element = $("#change-notification-msg");
+
+  libtoaster.showChangeNotification(msg);
+
+  assert.equal(element.text(), msg);
+  assert.ok(element.is(":visible"));
+
+  $("#change-notification").hide();
+});
+
+var layer = {
+  "id": 91,
+  "name":  "meta-crystalforest",
+  "layerdetailurl": "/toastergui/project/4/layer/91"
+};
+
+QUnit.test("Add layer", function(assert){
+  var done = assert.async();
+
+  /* Wait for the modal to be added to the dom */
+  var checkModal = setInterval(function(){
+    if ($("#dependencies-modal").length > 0) {
+      $("#dependencies-modal .btn-primary").click();
+      clearInterval(checkModal);
+    }
+  }, 200);
+
+  libtoaster.addRmLayer(layer, true, function(deps){
+    assert.equal(deps.length, 1);
+    done();
+  });
+
+});
+
+QUnit.test("Rm layer", function(assert){
+  var done = assert.async();
+
+  libtoaster.addRmLayer(layer, false, function(deps){
+    assert.equal(deps.length, 0);
+    done();
+  });
+
+});
+
+QUnit.test("Parse url params", function(assert){
+  var params = libtoaster.parseUrlParams();
+  assert.ok(params);
+});
+
+QUnit.test("Dump url params", function(assert){
+  var params = libtoaster.dumpsUrlParams();
+  assert.ok(params);
+});
+
+QUnit.test("Make typeaheads", function(assert){
+  var layersT = $("#layers");
+  var machinesT = $("#machines");
+  var projectsT = $("#projects");
+  var recipesT = $("#recipes");
+
+  libtoaster.makeTypeahead(layersT,
+    libtoaster.ctx.layersTypeAheadUrl, {}, function(){});
+
+  libtoaster.makeTypeahead(machinesT,
+    libtoaster.ctx.machinesTypeAheadUrl, {}, function(){});
+
+  libtoaster.makeTypeahead(projectsT,
+    libtoaster.ctx.projectsTypeAheadUrl, {}, function(){});
+
+  libtoaster.makeTypeahead(recipesT,
+    libtoaster.ctx.recipesTypeAheadUrl, {}, function(){});
+
+  assert.ok(recipesT.data('typeahead'));
+  assert.ok(layersT.data('typeahead'));
+  assert.ok(projectsT.data('typeahead'));
+  assert.ok(recipesT.data('typeahead'));
+});
+
+
+
+/* Page init functions */
+
+QUnit.test("Import layer page init", function(assert){
+  assert.throws(importLayerPageInit());
+});
+
+QUnit.test("Project page init", function(assert){
+  assert.throws(projectPageInit());
+});
+
+QUnit.test("Layer details page init", function(assert){
+  assert.throws(layerDetailsPageInit());
+});
+
+QUnit.test("Layer btns init", function(assert){
+  assert.throws(layerBtnsInit({ projectLayers : [] }));
+});
+
+QUnit.test("Table init", function(assert){
+  assert.throws(tableInit({ url : tableUrl }));
+});
+
+$(document).ajaxError(function(event, jqxhr, settings, errMsg){
+  if (errMsg === 'abort')
+    return;
+
+  QUnit.test("Ajax error", function(assert){
+    assert.notOk(jqxhr.responseText);
+  });
+});
+
+
+
+
+
+
lib/toaster/toastergui/templates/js-unit-tests.html new file +39 -0
new file mode 100644
index 0000000..5b8fd84
@@ -0,0 +1,39 @@
+{% extends "base.html" %}
+{% load projecttags %}
+{% load humanize %}
+{% load static %}
+{% block pagecontent %}
+
+<link rel="stylesheet" href="//code.jquery.com/qunit/qunit-1.18.0.css" />
+
+<script src="//code.jquery.com/qunit/qunit-1.18.0.js"></script>
+
+<script src="{% static 'js/layerDepsModal.js' %}"></script>
+<script src="{% static 'js/projectpage.js' %}"></script>
+
+<script src="{% static 'js/bootstrap.min.js' %}"></script>
+<script src="{% static 'js/filtersnippet.js' %}"></script>
+<script src="{% static 'js/importlayer.js' %}"></script>
+<script src="{% static 'js/prettify.js' %}"></script>
+<script src="{% static 'js/layerBtn.js' %}"></script>
+<script src="{% static 'js/layerDepsModal.js' %}"></script>
+<script src="{% static 'js/projectpage.js' %}"></script>
+<script src="{% static 'js/layerdetails.js' %}"></script>
+<script src="{% static 'js/table.js' %}"></script>
+
+<script>
+  var tableUrl = '{% url 'projectlayers' project.pk %}';
+</script>
+
+<script src="{% static 'js/tests/test.js' %}"></script>
+
+<div id="qunit"></div>
+
+<input type="text" id="layers" placeholder="layers" ></input>
+<input type="text" id="recipes" placeholder="recipes"></input>
+<input type="text" id="projects" placeholder="projects"></input>
+<input type="text" id="machines" placeholder="machines"></input>
+
+{% endblock %}
+
+
lib/toaster/toastergui/urls.py +2 -0
index f74090b..46e5761 100644
@@ -145,6 +145,9 @@ urlpatterns = patterns('toastergui.views',
          url(r'^xhr_importlayer/$', 'xhr_importlayer',
 name='xhr_importlayer'),
          url(r'^xhr_updatelayer/$', 'xhr_updatelayer',
 name='xhr_updatelayer'),
  +        # JS Unit tests
+        url(r'^js-unit-tests/$', 'jsunittests', name='js-unit-tests'),
+
          # default redirection
          url(r'^$', RedirectView.as_view( url= 'landing')),
  )
lib/toaster/toastergui/views.py +0 -0
index 889b6c6..e39baad 100755
@@ -27,6 +27,7 @@ from django.shortcuts import render, redirect
  from orm.models import Build, Target, Task, Layer, Layer_Version,

Recipe, LogMessage, Variable
from orm.models import Task_Dependency, Recipe_Dependency, Package,
Package_File, Package_Dependency
from orm.models import Target_Installed_Package, Target_File,
Target_Image_File, BuildArtifact

lib/toaster/toastergui/views.py +8 -0
+from orm.models import BitbakeVersion
  from bldcontrol import bbcontroller
  from django.views.decorators.cache import cache_control
  from django.core.urlresolvers import reverse
@@ -2255,6 +2256,21 @@ if True:
            return context
  +    def jsunittests(request):
+      """ Provides a page for the js unit tests """
+      bbv = BitbakeVersion.objects.filter(branch="master").first()
+      release = Release.objects.filter(bitbake_version=bbv).first()
+
+      name = "_js_unit_test_prj_"
+
+      # If there is an existing project by this name delete it. We don't

want

lib/toaster/toastergui/views.py +4 -0
+      # Lots of duplicates cluttering up the projects.
+      Project.objects.filter(name=name).delete()
+
+      new_project = Project.objects.create_project(name=name,

release=release)

lib/toaster/toastergui/views.py if True: · line 2276

Quoted 5 lines
lib/toaster/toastergui/views.py +3 -0
+
+      context = { 'project' : new_project }
+      return render(request, "js-unit-tests.html", context)
        from django.views.decorators.csrf import csrf_exempt
      @csrf_exempt

This patch seems to have landed without the new files
http://cgit.openembedded.org/bitbake/commit/?id=1c2f6b9b7b9e700146944b9d6d2114e0d014ee81

(quoted diff) +0 -2
-rw-r--r--    lib/toaster/toastergui/urls.py    3
-rwxr-xr-x    lib/toaster/toastergui/views.py    16
2 files changed, 19 insertions, 0 deletions
#4 lore raw

Re: [PATCH 1/1] toastergui: Add frontend javascript unit tests

should I resubmit this to get the js and html file merged? -b

Quoted 329 lines · Brian Avery

yes, the following files were new in the patch and were not created:
lib/toaster/toastergui/static/js/tests/test.js b/lib/toaster/toastergui/static/js/tests/test.js lib/toaster/toastergui/templates/js-unit-tests.html b/lib/toaster/toastergui/templates/js-unit-tests.html

-bavery

Quoted 320 lines · Michael Wood
Quoted 304 lines · brian avery

From: Michael Wood <[email protected]>

Use Jquery's Qunit tests to create some unit tests for javascript components used in toaster.

---
  lib/toaster/toastergui/static/js/tests/test.js     | 175
+++++++++++++++++++++
  .../toastergui/templates/js-unit-tests.html        |  39 +++++
  lib/toaster/toastergui/urls.py                     |   3 +
  lib/toaster/toastergui/views.py                    |  16 ++
  4 files changed, 233 insertions(+)

create mode 100644
bitbake/lib/toaster/toastergui/static/js/tests/test.js
create mode 100644
bitbake/lib/toaster/toastergui/templates/js-unit-tests.html

lib/toaster/toastergui/static/js/tests/test.js new file +16 -0
new file mode 100644
index 0000000..d610113
@@ -0,0 +1,175 @@
+"use strict";
+/* Unit tests for Toaster's JS */
+
+/* libtoaster tests */
+
+QUnit.test("Layer alert notification", function(assert) {
+  var layer = {
+    "layerdetailurl":"/toastergui/project/1/layer/22",
+    "vcs_url":"git://example.com/example.git",
+    "detail":"[ git://example.com/example.git | master ]",
+    "vcs_reference":"master",
+    "id": 22,
+    "name":"meta-example"
+  };
+
+  var correctResponse = "You have added <strong>3</strong> layers to your

project: <a id=\"layer-affected-name\" href=\"/toastergui/project/1/layer/22\">meta-example</a> and its dependencies <a href=\"/toastergui/project/1/layer/9\" data-original-title=\"\" title=\"\">meta-example-two</a>, <a href=\"/toastergui/project/1/layer/9\" data-original-title=\"\" title=\"\">meta-example-three</a>";

lib/toaster/toastergui/static/js/tests/test.js new file +21 -0
+
+  var layerDepsList = [
+    {
+    "layerdetailurl":"/toastergui/project/1/layer/9",
+    "vcs_url":"git://example.com/example.git",
+    "detail":"[ git://example.com/example.git | master ]",
+    "vcs_reference":"master",
+    "id": 9,
+    "name":"meta-example-two"
+    },
+    {
+    "layerdetailurl":"/toastergui/project/1/layer/9",
+    "vcs_url":"git://example.com/example.git",
+    "detail":"[ git://example.com/example.git | master ]",
+    "vcs_reference":"master",
+    "id": 10,
+    "name":"meta-example-three"
+    },
+  ];
+
+  var msg = libtoaster.makeLayerAddRmAlertMsg(layer, layerDepsList,

true);

lib/toaster/toastergui/static/js/tests/test.js new file +11 -0
+  var test = $("<div></div>");
+
+  test.html(msg);
+
+  assert.equal(test.children("strong").text(), "3");
+  assert.equal(test.children("a").length, 3);
+});
+
+QUnit.test("Project info", function(assert){
+  var done = assert.async();
+  libtoaster.getProjectInfo(libtoaster.ctx.projectPageUrl,

function(prjInfo){

lib/toaster/toastergui/static/js/tests/test.js new file +127 -0
+    assert.ok(prjInfo.machine.name);
+    assert.ok(prjInfo.releases.length > 0);
+    assert.ok(prjInfo.layers.length > 0);
+    assert.ok(prjInfo.freqtargets);
+    assert.ok(prjInfo.release);
+    done();
+  });
+});
+
+QUnit.test("Show notification", function(assert){
+  var msg = "Testing";
+  var element = $("#change-notification-msg");
+
+  libtoaster.showChangeNotification(msg);
+
+  assert.equal(element.text(), msg);
+  assert.ok(element.is(":visible"));
+
+  $("#change-notification").hide();
+});
+
+var layer = {
+  "id": 91,
+  "name":  "meta-crystalforest",
+  "layerdetailurl": "/toastergui/project/4/layer/91"
+};
+
+QUnit.test("Add layer", function(assert){
+  var done = assert.async();
+
+  /* Wait for the modal to be added to the dom */
+  var checkModal = setInterval(function(){
+    if ($("#dependencies-modal").length > 0) {
+      $("#dependencies-modal .btn-primary").click();
+      clearInterval(checkModal);
+    }
+  }, 200);
+
+  libtoaster.addRmLayer(layer, true, function(deps){
+    assert.equal(deps.length, 1);
+    done();
+  });
+
+});
+
+QUnit.test("Rm layer", function(assert){
+  var done = assert.async();
+
+  libtoaster.addRmLayer(layer, false, function(deps){
+    assert.equal(deps.length, 0);
+    done();
+  });
+
+});
+
+QUnit.test("Parse url params", function(assert){
+  var params = libtoaster.parseUrlParams();
+  assert.ok(params);
+});
+
+QUnit.test("Dump url params", function(assert){
+  var params = libtoaster.dumpsUrlParams();
+  assert.ok(params);
+});
+
+QUnit.test("Make typeaheads", function(assert){
+  var layersT = $("#layers");
+  var machinesT = $("#machines");
+  var projectsT = $("#projects");
+  var recipesT = $("#recipes");
+
+  libtoaster.makeTypeahead(layersT,
+    libtoaster.ctx.layersTypeAheadUrl, {}, function(){});
+
+  libtoaster.makeTypeahead(machinesT,
+    libtoaster.ctx.machinesTypeAheadUrl, {}, function(){});
+
+  libtoaster.makeTypeahead(projectsT,
+    libtoaster.ctx.projectsTypeAheadUrl, {}, function(){});
+
+  libtoaster.makeTypeahead(recipesT,
+    libtoaster.ctx.recipesTypeAheadUrl, {}, function(){});
+
+  assert.ok(recipesT.data('typeahead'));
+  assert.ok(layersT.data('typeahead'));
+  assert.ok(projectsT.data('typeahead'));
+  assert.ok(recipesT.data('typeahead'));
+});
+
+
+
+/* Page init functions */
+
+QUnit.test("Import layer page init", function(assert){
+  assert.throws(importLayerPageInit());
+});
+
+QUnit.test("Project page init", function(assert){
+  assert.throws(projectPageInit());
+});
+
+QUnit.test("Layer details page init", function(assert){
+  assert.throws(layerDetailsPageInit());
+});
+
+QUnit.test("Layer btns init", function(assert){
+  assert.throws(layerBtnsInit({ projectLayers : [] }));
+});
+
+QUnit.test("Table init", function(assert){
+  assert.throws(tableInit({ url : tableUrl }));
+});
+
+$(document).ajaxError(function(event, jqxhr, settings, errMsg){
+  if (errMsg === 'abort')
+    return;
+
+  QUnit.test("Ajax error", function(assert){
+    assert.notOk(jqxhr.responseText);
+  });
+});
+
+
+
+
+
+
lib/toaster/toastergui/templates/js-unit-tests.html new file +39 -0
new file mode 100644
index 0000000..5b8fd84
@@ -0,0 +1,39 @@
+{% extends "base.html" %}
+{% load projecttags %}
+{% load humanize %}
+{% load static %}
+{% block pagecontent %}
+
+<link rel="stylesheet" href="//code.jquery.com/qunit/qunit-1.18.0.css" />
+
+<script src="//code.jquery.com/qunit/qunit-1.18.0.js"></script>
+
+<script src="{% static 'js/layerDepsModal.js' %}"></script>
+<script src="{% static 'js/projectpage.js' %}"></script>
+
+<script src="{% static 'js/bootstrap.min.js' %}"></script>
+<script src="{% static 'js/filtersnippet.js' %}"></script>
+<script src="{% static 'js/importlayer.js' %}"></script>
+<script src="{% static 'js/prettify.js' %}"></script>
+<script src="{% static 'js/layerBtn.js' %}"></script>
+<script src="{% static 'js/layerDepsModal.js' %}"></script>
+<script src="{% static 'js/projectpage.js' %}"></script>
+<script src="{% static 'js/layerdetails.js' %}"></script>
+<script src="{% static 'js/table.js' %}"></script>
+
+<script>
+  var tableUrl = '{% url 'projectlayers' project.pk %}';
+</script>
+
+<script src="{% static 'js/tests/test.js' %}"></script>
+
+<div id="qunit"></div>
+
+<input type="text" id="layers" placeholder="layers" ></input>
+<input type="text" id="recipes" placeholder="recipes"></input>
+<input type="text" id="projects" placeholder="projects"></input>
+<input type="text" id="machines" placeholder="machines"></input>
+
+{% endblock %}
+
+
lib/toaster/toastergui/urls.py +2 -0
index f74090b..46e5761 100644
@@ -145,6 +145,9 @@ urlpatterns = patterns('toastergui.views',
          url(r'^xhr_importlayer/$', 'xhr_importlayer',
 name='xhr_importlayer'),
          url(r'^xhr_updatelayer/$', 'xhr_updatelayer',
 name='xhr_updatelayer'),
  +        # JS Unit tests
+        url(r'^js-unit-tests/$', 'jsunittests', name='js-unit-tests'),
+
          # default redirection
          url(r'^$', RedirectView.as_view( url= 'landing')),
  )
lib/toaster/toastergui/views.py +0 -0
index 889b6c6..e39baad 100755
@@ -27,6 +27,7 @@ from django.shortcuts import render, redirect
  from orm.models import Build, Target, Task, Layer, Layer_Version,

Recipe, LogMessage, Variable
from orm.models import Task_Dependency, Recipe_Dependency, Package,
Package_File, Package_Dependency
from orm.models import Target_Installed_Package, Target_File,
Target_Image_File, BuildArtifact

lib/toaster/toastergui/views.py +8 -0
+from orm.models import BitbakeVersion
  from bldcontrol import bbcontroller
  from django.views.decorators.cache import cache_control
  from django.core.urlresolvers import reverse
@@ -2255,6 +2256,21 @@ if True:
            return context
  +    def jsunittests(request):
+      """ Provides a page for the js unit tests """
+      bbv = BitbakeVersion.objects.filter(branch="master").first()
+      release = Release.objects.filter(bitbake_version=bbv).first()
+
+      name = "_js_unit_test_prj_"
+
+      # If there is an existing project by this name delete it. We don't

want

lib/toaster/toastergui/views.py +4 -0
+      # Lots of duplicates cluttering up the projects.
+      Project.objects.filter(name=name).delete()
+
+      new_project = Project.objects.create_project(name=name,

release=release)

lib/toaster/toastergui/views.py if True: · line 2276

Quoted 5 lines
lib/toaster/toastergui/views.py +3 -0
+
+      context = { 'project' : new_project }
+      return render(request, "js-unit-tests.html", context)
        from django.views.decorators.csrf import csrf_exempt
      @csrf_exempt

This patch seems to have landed without the new files
http://cgit.openembedded.org/bitbake/commit/?id=1c2f6b9b7b9e700146944b9d6d2114e0d014ee81

(quoted diff) +0 -2
-rw-r--r--    lib/toaster/toastergui/urls.py    3
-rwxr-xr-x    lib/toaster/toastergui/views.py    16
2 files changed, 19 insertions, 0 deletions
#5 lore raw

Re: [PATCH 1/1] toastergui: Add frontend javascript unit tests

Quoted 10 lines · Brian Avery

should I resubmit this to get the js and html file merged? -b

Quoted 6 lines · Brian Avery

yes, the following files were new in the patch and were not created:
lib/toaster/toastergui/static/js/tests/test.js b/lib/toaster/toastergui/static/js/tests/test.js lib/toaster/toastergui/templates/js-unit-tests.html b/lib/toaster/toastergui/templates/js-unit-tests.html

I believe this was fixed yesterday. Let me know if not.

Cheers,

Richard