I would like to programatically inject the html to test into the qunit-fixture. I have tried with $.load but the JS dealing with the HTML gets executed before the html is loaded.
The HTML:
<div id="qunit"></div>
<div id="qunit-fixture"></div>
<script src="../components/bower/qunit/qunit/qunit.js"></script>
<script>
QUnit.config.autostart = false;
</script>
<script data-main="tests" src="../components/bower/requirejs/require.js"></script>
The JS manipulating the html is the module I want to test:
define(['jquery'], function($) {
'use strict';
var Foo = {
_init: function() {
this._addClass();
},
_addClass: function() {
console.log('adding class testit');
$('.foo').addClass('testit');
},
greet: function() {
return "Hello";
}
};
Foo._init();
return {
greet : Foo.greet
};
});
And my test:
define(['foo'], function(foo) {
'use strict';
var Test = {
test: function() {
module( "module Foo");
asyncTest("foo class test", function() {
expect(1);
// foo() is executed before load is done :(
$('#qunit-fixture').load('../components/app/foo/foo.html', function(data) {
ok($('.foo').hasClass('testit'), ".foo should have class 'testit'");
QUnit.start();
});
});
}
};
return {
test: Test.test
};
});
Since the loading of the content is asynchronous you'll need to tell QUnit to wait before running. Note that this is just a guess at what your test harness might look like, it will likely need to be updated for your use case.
<!-- in your test HTML document -->
<script>
QUnit.config.autostart = false;
// your code to load the HTML dynamically in the fixture
// your test definitions
require(
[ "src/yourSourceCode", "tests/theTests" ],
function() {
QUnit.start(); // this starts the main QUnit code
}
);
</script>
UPDATE
Looks like the OP is, in fact, already stopping QUnit from running immediately, the problem (see the comment below) is that the module code runs before the HTML is loaded dynamically. I think this is because the _init() method is called inside the module. Instead, return the _init method as a property of the module and call it from the test:
define(['jquery'], function($) {
'use strict';
var Foo = {
_init: function() {
...
},
...
};
// Foo._init(); // don't do this here...
return {
greet : Foo.greet,
init : Foo._init // add the init method to your exports
};
});
Now, in your test you can do:
define(['foo'], function(foo) {
'use strict';
var Test = {
test: function() {
module( "module Foo");
asyncTest("foo class test", function() {
expect(1);
$('#qunit-fixture').load('../components/app/foo/foo.html', function(data) {
foo.init(); // we've moved the initialization to here...
ok($('.foo').hasClass('testit'), ".foo should have class 'testit'");
QUnit.start();
});
});
}
};
return {
test: Test.test
};
});
Related
I am trying to show current time with running seconds on a page under adminhtml. I wrote the code for js in Namespace_Module/view/adminhtml/web/js/timejs.js And the code is
define(
['jquery', 'uiComponent', 'ko']
,function ($, Component, ko) {
'use strict';
return Component.extend({
defaults: {
template: 'Pixelnet_Blog/time'
},
initialize: function () {
this._super();
this.currentTime();
},
currentTime: ko.computed(function () {
setInterval(function(){
var currentTime = new Date().toLocaleTimeString();
// console.log(currentTime);
}, 1000);
return currentTime;
})
});
}
);
To render the js function I created a PHTML in the place of Namespace_Module/view/adminhtml/templates/js_time.phtml and the code is
<div id="time_show" data-bind="scope:'time_show'">
<!-- ko template: getTemplate() --><!-- /ko -->
<script type="text/x-magento-init">
{
"*": {
"Magento_Ui/js/core/app": {
"components": {
"time_show": {
"component": "Pixelnet_Blog/js/timejs"
}
}
}
}
}
</script>
</div>
I called the template in the phtml and put the template in the position of Namespace_Module/view/adminhtml/web/template/time.html. And HTML code is
<div>
<h4>Current Time is:</h4><span id="time_show" data-bind="text: currentTime()"></span>
</div>
lastly, I put a require js file in the location of Namespace_Module/view/adminhtml/requirejs-config.js and the code snippet is
var config = {
map: {
'*': {
timejs: 'Pixelnet_Blog/js/timejs'
}
}
};
But when I render the page it does not show the time with running seconds. In console, it shows an error named Failed to load the "Pixelnet_Blog/js/timejs" component. I cannot figure out the problem.
I have a JS file named ui.js and a function within it does something. This file looks something like this
define(function (require) {
function someName(param1, param2, param3) {
......
};
}
In another JS file, I call all of my JS files like so:
define(function (require) {
var $ = require('jquery');
var functionName = require('ui');
$(function() {
function one() {
.....
someName(value1, value2, value3);
}
});
});
function one works without mistake, but when i call function someName within it, then i get an error someFunction is not defined. I must be out of the scope, but I don't know how to get this working. I tried to console.log outside and inside the someName function, and I get the log from outside but not the log from inside. Any ideas?
///// EDIT
I just mistyped it here, I have the closing brackets in my code
I guess you're looking for this:
ui.js
define(function() {
return function(param1, param2, param3) {
...
};
}
someOtherModule.js
define(["jquery", "ui"], function($, ui) {
$(function() {
...
ui(v1, v2, v3);
});
});
If ui.js should propose several methods:
ui.js
define(function() {
return {
f1: function() {
...
},
f2: function() {
...
}
};
}
someOtherModule.js
define(["jquery", "ui"], function($, ui) {
$(function() {
...
ui.f1();
ui.f2();
});
});
I have a variable that contains my angular app
(was instantiated with:)
var app = angular.module('app', [...]);
And I want to get the $timeout service.
How can I get this service from the it?
I want something like:
var timeout = app.getService('$timeout');
or
app.something('$imeout', function($timeout) {
...
} // like controller() does
Where I want to use it:
define([], function () { // I can import my angular module 'app', or 'angular'
return {
'some_function': function () {
$timeout(function() { ... do something ... }, 1000);
}
}
}
This is a service (with requirejs), and my controllers will require it.
What you should do is:
app.controller("myCtrl",["$timeout", "otherService" ,function($timeout, otherService){
$timeout(function() {
otherService.updateService('Hi');
}, 3000);
}]);
despite i found already some answers i could not figure it out where i made the mistake in loading the module with require js, i always get the error Uncaught
TypeError: undefined is not a function
at the line where i try to call the function in the zoom.js file
myZoomingFunctions.minSize();
here my code:
main.js
require.config({
baseUrl: 'js/libs',
paths: {
'jquery': 'jquery-1.9.1',
'myDraw': '../draw',
'myZoomingFunctions': '../zoom'
}
});
require(['jquery', 'myDraw'], function ($, myDraw_ref) {
var myDraw = new myDraw_ref();
});
draw.js
define(['myZoomingFunctions'], function (myZoomingFunctions_ref) {
var myZoomingFunctions = new myZoomingFunctions_ref();
return draw = function() {
myZoomingFunctions.minSize();
}
});
zoom.js
define([], function () {
return zoom = function() {
function minSize(){
alert("minSize called");
}
}
});
thanks!
i figured out, maybe if someone else have the same problem, here is the solution:
main.js
require.config({
baseUrl: 'js/libs',
paths: {
'jquery': 'jquery-1.9.1',
'myDraw': '../draw',
'myZoomingFunctions': '../zoom'
}
});
require(['jquery', 'myDraw'], function ($, myDraw_ref) {
var myDraw = new myDraw_ref();
});
draw.js
define(['myZoomingFunctions'], function (myZoomingFunctions) {
return draw = function() {
myZoomingFunctions.minSize();
myZoomingFunctions.maxSize();
}
});
zoom.js
define([], function () {
return {
minSize: function() {
alert("min Size called");
},
maxSize: function() {
alert("max Size Called");
}
}
});
I can see that the mustache.js file has been loaded, (code 200 in Firebug Net tab) so why do I get an error saying "ReferenceError: Mustache is not defined"?
I've looked at several related SO posts on this subject, but none seem to shed light on the issue. Any help is appreciated.
Relevant HTML
<div class="contact"></div>
<script data-main="js/modules/app.js" src="js/lib/require.min.js"></script>
app.js
var KBCOM = KBCOM || {};
(function (kbcom) {
kbcom.app = {
data: {
kboucher: "{ \"firstName\": \"Kevin\", \"lastName\": \"Boucher\", \"dob\": \"1970-05-01T05:00:00.000Z\", \"emailAddress\": \"example#mail.com\", \"telephone\": \"512-555-1212\" }"
},
init: function () {
kbcom.templates.loadTemplate(
kbcom.templates.vcard,
JSON.parse(this.data.kboucher),
document.querySelector('.contact'));
}
};
}(KBCOM));
require.config({
baseUrl: '/js/modules',
paths: {
Mustache: '/js/lib/mustache',
domReady: '/js/lib/domReady'
}
});
require(['domReady', 'templates', 'Mustache'], function (domReady) {
domReady(function () {
KBCOM.app.init();
});
});
templates.js
var KBCOM = KBCOM || {};
(function (kbcom) {
kbcom.templates = {
vcard: '<ul>\
<li class="fn">{{fisrtName}} {{lastName}}</li>\
<li class="email">{{emailAddress}}</li>\
<li class="tel">{{telephone}}</li>\
<li class="bday">{{dob}}</li>\
</ul>',
loadTemplate: function (template, data, element) {
element.innerHTML = Mustache.render(template, data);
}
};
}(KBCOM));
templates.js "requires" Mustache, therefore you need to define that dependency in templates.js. It also needs to be defined as a module, so you need to use define to properly create a module.
app.js
require(['domReady', 'templates'], function (domReady, templates) {
//append templates to namespace
KBCOM.templates = templates;
domReady(function () {
KBCOM.app.init();
});
});
templates.js
define([
//dependencies
'Mustache'
], function( Mustache ){
//module code
return {
vcard: '...',
loadTemplate: function ( template, data, element ) {
element.innerHTML = Mustache.render( template, data );
}
};
});
Require will bind the variables of the libraries to the parameters of the function given in the second parameter, so to use templates and Mustache in your code you should do the following:
require( [ 'domReady', 'templates', 'Mustache' ],
function( domReady, templates, Mustache ) {
domReady( function () {
KBCOM.app.init();
} );
}
);