Closed Integralist closed 11 years ago
Ah, OK it looks like this works...
describe('x', function(){
beforeEach(function(){
$('body').append('<div id="js-injected"></div>');
this.news = require('module/bootstrap');
});
afterEach(function(){
$('#js-injected').remove();
});
it('should x', function(){
console.log('this.news.$', this.news.$);
});
});
I'm going to keep testing to see if there is any other issue that crops up!
One question though, is this a good idea? Is there not a better way?
The current issue I'm having is getting jQuery (which is loaded by the time the tests run) to successfully run its ajax method.
For some reason it doesn't run the success callback or the error callback, and I'm not sure why that would be?
If I run console.log(this.news.$.ajax)
I can see in the Terminal response the content of the ajax method. But the more bare bones usage doesn't work...
describe('AJAX Form', function(){
beforeEach(function(){
$('body').append('<div id="js-injected"></div>');
this.news = require('module/bootstrap');
});
afterEach(function(){
$('#js-injected').remove();
});
it('should run the error handler', function(){
this.news.$.ajax({
url: 'file-that-doesnt-exist.js',
success: function(response) {
console.log(response);
},
error: function() {
console.log('error occurred');
}
});
});
});
It's a big issue that I noticed first when I tried to use Sinon to mock the AJAX functionality (which doesn't work either). I removed the Sinon code and tested the bare bones ajax functionality to find it still didn't work.
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>Jasmine Spec Runner</title>
<link rel="stylesheet" type="text/css" href=".grunt/grunt-contrib-jasmine/jasmine.css">
<script src="./.grunt/grunt-contrib-jasmine/jasmine.js"></script>
<script src="./.grunt/grunt-contrib-jasmine/jasmine-html.js"></script>
<script src="./tabloid/webapp/static/js/specs/helpers/SpecHelper.js"></script>
<script src="./tabloid/webapp/static/js/specs/helpers/sinon.js"></script>
<script>
var require = {
"baseUrl": "./tabloid/webapp/static/js/",
"paths": {
"jquery-1": "vendor/jquery-1/jquery.min",
"jquery": "vendor/jquery-2/jquery.min",
"domReady": "vendor/require/domReady",
"translation": "module/translations/news"
},
"name": "define"
};
</script>
<script>
function launchTest() {
require([
'bootstrap-ui' ,
'config' ,
'define' ,
'deviceInspector' ,
'locator/autoCompleteView' ,
'locator/autoCompleteView.js ' ,
'locator/bootstrap' ,
'locator/locatorView' ,
'locator/main' ,
'locator/stats' ,
'module/ajaxForm/ajaxForm' ,
'module/ajaxForm/ajaxFormView' ,
'module/analytics/analytics_client' ,
'module/base' ,
'module/bootstrap-desktop' ,
'module/bootstrap' ,
'module/components/featuresAndAnalysis' ,
'module/components/mostPopular' ,
'module/components/topStoriesPromo' ,
'module/deviceInspector' ,
'module/featureDetector' ,
'module/fontface' ,
'module/history/hashed' ,
'module/history/history' ,
'module/history/native' ,
'module/hyperpuff/hyperpuff' ,
'module/hyperpuff/minihyper' ,
'module/imageenhancer' ,
'module/index' ,
'module/live-event-component' ,
'module/live-event' ,
'module/liveEvent/timeline' ,
'module/liveEvent/timelineView' ,
'module/local/local' ,
'module/local/localView' ,
'module/localnewsandweather' ,
'module/media/empFacade' ,
'module/media/mediaHandler' ,
'module/media/mediaLoader' ,
'module/media/mediaRegistry' ,
'module/media/piratePlayer' ,
'module/media/piratePlayerView' ,
'module/mediaAssetPage/api' ,
'module/mediaAssetPage/assetView' ,
'module/mediaAssetPage/listView' ,
'module/mediaAssetPage/map' ,
'module/mediaAssetPage/mediaAssetPage' ,
'module/mediaAssetPage/pinningView' ,
'module/nav/nav' ,
'module/nav/navManager' ,
'module/poller' ,
'module/readabilityCheck' ,
'module/rollingNews' ,
'module/stats/siteCatalyst' ,
'module/stats/statsConfig' ,
'module/stats/statsSubscriber' ,
'module/story' ,
'module/stylesheetloader' ,
'module/tabbed/panel' ,
'module/tabbed/tab' ,
'module/tabbed/tabbed' ,
'module/timestamp' ,
'module/transclude' ,
'module/translations/afrique' ,
'module/translations/arabic' ,
'module/translations/hausa' ,
'module/translations/hindi' ,
'module/translations/indonesia' ,
'module/translations/mundo' ,
'module/translations/news' ,
'module/translations/russian' ,
'module/translator' ,
'module/travel/travel' ,
'module/travel/travelView' ,
'module/urlShrinker' ,
'module/weather/weather' ,
'module/weather/weatherLocation' ,
'module/weather/weatherLocationView' ,
'module/weather/weatherView' ,
'specs/helpers/SpecHelper' ,
'specs/helpers/sinon' ,
'translator'
],
function(){
require(['./tabloid/webapp/static/js/specs/AjaxFormSpec.js','./.grunt/grunt-contrib-jasmine/reporter.js'], function(){
require(['./.grunt/grunt-contrib-jasmine/jasmine-helper.js'], function(){
// good to go! Our tests should already be running.
})
})
}
)
}
</script>
<script src=".grunt/grunt-contrib-jasmine/require.js"></script>
<script>
require.onError = function(error) {
var message = error.requireType + ': ';
if (error.requireType === 'scripterror' || error.requireType === 'notloaded' && error.requireModules) {
message += 'Illegal path or script error: ' + '[\'' + error.requireModules.join("', '") + '\']';
} else {
message += error.message;
}
throw Error(message);
};
</script>
<script>
launchTest();
</script>
</head>
<body>
</body>
</html>
console.log()
invocations in your spec or source code won't be shown in grunt jasmine
task
Use console.info()
instead, it makes sense to ignore those debugging information in order to filtering annoying output.
Ultimately I think the primary issue here is that the modules are loaded fine but there is no 'good' way to access the return value from the module. Do you or @jsoverson have any ideas to achieve that? Because it seems most of my issues stem from that primary issue :-(
Sorry, I don't understand your ultimate needs. In general, module definition should be treated as static object, so it should return same thing when access it every time, just like import
directive does in other languages, such as python.
We use require('module/A')
or ['module/A']
by define()
to explicitly get it in AMD style.
What's meaning of
there is no 'good' way to access the return value from the module
@cloudchen I'm going to look into this more to see if I can find the issue with jQuery not running properly within the context of the unit test.
But just to clarify, as far as you're concerned, doing the following is fine and should be the way to go (and by that I'm specifically referring to the use of this.news = require('module/bootstrap');
to access the module that has been loaded by the spec runner)...
describe('AJAX Form', function(){
beforeEach(function(){
$('body').append('<div id="js-injected"></div>');
this.news = require('module/bootstrap');
});
afterEach(function(){
$('#js-injected').remove();
});
it('should run the error handler', function(){
this.news.$.ajax({
url: 'file-that-doesnt-exist.js',
success: function(response) {
console.log(response);
},
error: function() {
console.log('error occurred');
}
});
});
});
@Integralist var foo = require('foo')
is the recommended way.
Also, a disclaimer, this template is just a way not the way to test requirejs/amd modules. It follows some accepted practices but anyone is able to make their own template to accomodate different testing styles. The template is minimal and can easily be changed to accomodate different styles.
@jsoverson thanks for the feedback. I'm trying to figure out why jQuery isn't working within the context of the test when loaded like so...
describe('AJAX Form', function(){
beforeEach(function(){
$('body').append('<div id="js-injected"></div>');
this.news = require('module/bootstrap');
});
afterEach(function(){
$('#js-injected').remove();
});
it('should run the error handler', function(){
console.info(this.news.$.ajax);
this.news.$.ajax({
url: 'file-that-doesnt-exist.js',
success: function(response) {
console.info(response);
},
error: function() {
console.info('error occurred');
}
});
});
});
The 'module/bootstrap'
looks like this...
define([
'jquery',
'config'
], function(
jquery,
config
) {
var news = {
$: jquery,
config: config
};
return news;
});
So there is nothing complicated going on there.
When I run a console.info
on this.news.$.ajax
I can see the content of the AJAX method but yet running a basic test where the method tries to get a file that doesn't exist, the error callback isn't invoked (no content is displayed in the terminal to suggest that it has been run).
Any ideas?
Finally, I see what you concerned.
Because you are testing async method rather than sync ones.
You should use wait()
or waitFor()
methods of jasmine to test async
method.
Or use sinon.js to mock ajax result and manually respond it before
expect()
invocation.
Take a look at associated documentations of jasmine.
On Wednesday, May 1, 2013, Mark McDonnell wrote:
@jsoverson https://github.com/jsoverson thanks for the feedback. I'm trying to figure out why jQuery isn't working within the context of the test when loaded like so...
describe('AJAX Form', function(){ beforeEach(function(){ $('body').append('
'); this.news = require('module/bootstrap'); });afterEach(function(){ $('#js-injected').remove(); }); it('should run the error handler', function(){ console.info(this.news.$.ajax); this.news.$.ajax({ url: 'file-that-doesnt-exist.js', success: function(response) { console.info(response); }, error: function() { console.info('error occurred'); } }); });});
The 'module/bootstrap' looks like this...
define([ 'jquery', 'config'], function( jquery, config) { var news = { $: jquery, config: config };
return news;});
So there is nothing complicated going on there.
When I run a console.info on this.news.$.ajax I can see the content of the AJAX method but yet running a basic test where the method tries to get a file that doesn't exist, the error callback isn't invoked (no content is displayed in the terminal to suggest that it has been run).
Any ideas?
— Reply to this email directly or view it on GitHubhttps://github.com/jsoverson/grunt-template-jasmine-requirejs/issues/23#issuecomment-17272373 .
@cloudchen I was mocking the ajax with sinon but the results weren't working as expected (seemed like nothing was being mocked) so I reverted to using real ajax call. I'll double check my code.
@cloudchen @jsoverson I updated my example code this morning and found that it fails still even though I'm sure it shouldn't...
describe('AJAX Form', function(){
beforeEach(function(){
$('body').append('<div id="js-injected"></div>');
this.news = require('module/bootstrap');
// Sinon set-up
this.server = sinon.fakeServer.create();
});
afterEach(function(){
$('#js-injected').remove();
});
it('should run the error handler', function(){
var spy_success = sinon.spy(),
spy_error = sinon.spy();
this.server.respondWith([200, {}, JSON.stringify({reply: 'success', body: 'test'})]);
// this.server.respondWith([404, {}, JSON.stringify({reply: 'lulz', body: 'test'})]);
this.news.$.ajax({
url: 'file-that-doesnt-exist.js',
success: spy_success,
error: spy_error
});
this.server.respond();
expect(spy_success.called).toBeTruthy();
});
});
I don't know what happened with your environment. I copied above code and passed in my env. Check you environment first.
Hi,
Here is my latest Gruntfile...
This generates the following SpecRunner file...
The issue I have is that the AMD modules that are loaded before the tests are run aren't available within the tests.
I'm not sure how I access the loaded AMD modules within each test file?
For example, here is one test file...