Grunt-Karma-Jasmine: can not find module - angularjs

I am trying to set up tests for my Angular.js project and I keep getting "$injector:nomod, Module 'result' is not available! You either misspelled..." error. I am sure that I am including "result" module in the "files" array inside "karma.config.js", basically it looks like this:
files: [
'../javascripts/jquery-2.1.4.min.js',
'../jquery-ui/jquery-ui.min.js',
'../D3/d3.js',
'libs/angular.min.js',
'libs/angular-route.min.js',
'libs/angular-animate.min.js',
'libs/selectize.js',
'libs/angular-selectize.js',
'libs/angular-mocks.js',
'simulator.js',
'*.js',
'services/**/*.js',
'qa/tests-*.js'
],
...
I thought initially that the ordering of the main module: 'simulator' (defined inside 'simulator.js' file) is wrong, so I specifically moved it upwards, before
the other modules, like the following stackoverflow thread recommends:
Angular module not available in Karma Jasmine test run
It did not help. Then I tried to make sure that the files are imported in the same order as in my angular apps' main entry file (except for angular-mocks.js and qa/tests-*.js), importing each single file, instead of using wildcards, but no success.
Jasmine definitely goes inside the test files but stumbles upon the line where I am trying to import the module "result":
describe('simulator.chartService', function() {
var chartService;
var graphConfig;
console.log("instantiating module result");
beforeEach(module('result'));
console.log("finished instantiating");
beforeEach(inject(function($injector) {
graphConfig = $injector.get('graphConfig');
chartService = $injector.get('chartService');
}));
it('should be created', function() {
expect(chartService.calcColors(10)).not.toBeNull();
});
});
So, I see that the error happens in-between two console.log() statements.
I suspect that still something can be wrong with the ordering of my files inside the array "files" in "karma.config.js". I have main module "simulator" which is dependent on other modules:
angular.module('simulator', ['ngRoute','ngAnimate','selectize','newexp2','newexp','login','edit','exps', 'result','templates','commons'])
Modules 'newexp2', 'newexp', 'login', 'edit', 'exps', 'result', 'templates' are all dependent on the module 'commons'.
How to correctly import interdependent modules inside the "files" array?
Is it just enough to place "simulator.js", main module, above all others,
or I also need to place all other modules before "commons.js"?
Another my suspicion is that angular.js library version that I downloaded from the official angular website, "angular-mocks.js", can be incompatible with other modules that I am using. I had such an issue with "angular-animate.js" file before.
As long as I surround my test code with $(function(){...}) (and all other my modules ARE surrounded with it) it does not generate the error while importing the result module, so I start seeing two console.log() statements without an error in-between, however, this generates some unknown error which prevents me from invoking the it part at all, whereas when I do not surround it with $(function(){...}), the it test is invoked, but the module result import fails.
So far I am pretty much stuck and do not know where to move and what to try. Any suggestion would be greatly appreciated.

OK, I figured it out. The issue was that ALL of my angular code was enclosed inside $(function(){...}). The solution is to remove all of the $function(){...}), then reorder javascript imports inside the main entry .html file, and then all of the testing starts working good.
The question might be better to mark as duplicate with:
Angular document.ready() issue

Related

Require.js fails when including socket.io [duplicate]

I'm getting this error when I browse my webapp for the first time (usually in a browser with disabled cache).
Error: Mismatched anonymous define() module: function (require) {
HTML:
<html>
.
.
.
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.8.0/jquery.min.js"></script>
<script> var require = { urlArgs: "v=0.4.1.32" }; </script>
<script data-main="assets/js/main" src="assets/js/libs/require.js"></script>
<script src="assets/js/ace/ace.js?v=0.4.1.32"></script>
</body>
</html>
JS:
$(function () {
define(function (require) {
// do something
});
});
Anyone know exactly what this error means and why its happening?
source file, a short discussion about it in the github issues page
Like AlienWebguy said, per the docs, require.js can blow up if
You have an anonymous define ("modules that call define() with no string ID") in its own script tag (I assume actually they mean anywhere in global scope)
You have modules that have conflicting names
You use loader plugins or anonymous modules but don't use require.js's optimizer to bundle them
I had this problem while including bundles built with browserify alongside require.js modules. The solution was to either:
A. load the non-require.js standalone bundles in script tags before require.js is loaded, or
B. load them using require.js (instead of a script tag)
In getting started with require.js I ran into the issue and as a beginner the docs may as well been written in greek.
The issue I ran into was that most of the beginner examples use "anonymous defines" when you should be using a "string id".
anonymous defines
define(function() {
return { helloWorld: function() { console.log('hello world!') } };
})
define(function() {
return { helloWorld2: function() { console.log('hello world again!') } };
})
define with string id
define('moduleOne',function() {
return { helloWorld: function() { console.log('hello world!') } };
})
define('moduleTwo', function() {
return { helloWorld2: function() { console.log('hello world again!') } };
})
When you use define with a string id then you will avoid this error when you try to use the modules like so:
require([ "moduleOne", "moduleTwo" ], function(moduleOne, moduleTwo) {
moduleOne.helloWorld();
moduleTwo.helloWorld2();
});
I had this error because I included the requirejs file along with other librairies included directly in a script tag. Those librairies (like lodash) used a define function that was conflicting with require's define. The requirejs file was loading asynchronously so I suspect that the require's define was defined after the other libraries define, hence the conflict.
To get rid of the error, include all your other js files by using requirejs.
Per the docs:
If you manually code a script tag in HTML to load a script with an
anonymous define() call, this error can occur.
Also seen if you
manually code a script tag in HTML to load a script that has a few
named modules, but then try to load an anonymous module that ends up
having the same name as one of the named modules in the script loaded
by the manually coded script tag.
Finally, if you use the loader
plugins or anonymous modules (modules that call define() with no
string ID) but do not use the RequireJS optimizer to combine files
together, this error can occur. The optimizer knows how to name
anonymous modules correctly so that they can be combined with other
modules in an optimized file.
To avoid the error:
Be sure to load all scripts that call define() via the RequireJS API.
Do not manually code script tags in HTML to load scripts that have
define() calls in them.
If you manually code an HTML script tag, be
sure it only includes named modules, and that an anonymous module that
will have the same name as one of the modules in that file is not
loaded.
If the problem is the use of loader plugins or anonymous
modules but the RequireJS optimizer is not used for file bundling, use
the RequireJS optimizer.
The existing answers explain the problem well but if including your script files using or before requireJS is not an easy option due to legacy code a slightly hacky workaround is to remove require from the window scope before your script tag and then reinstate it afterwords. In our project this is wrapped behind a server-side function call but effectively the browser sees the following:
<script>
window.__define = window.define;
window.__require = window.require;
window.define = undefined;
window.require = undefined;
</script>
<script src="your-script-file.js"></script>
<script>
window.define = window.__define;
window.require = window.__require;
window.__define = undefined;
window.__require = undefined;
</script>
Not the neatest but seems to work and has saved a lot of refractoring.
Be aware that some browser extensions can add code to the pages.
In my case I had an "Emmet in all textareas" plugin that messed up with my requireJs.
Make sure that no extra code is beign added to your document by inspecting it in the browser.
Or you can use this approach.
Add require.js in your code base
then load your script through that code
<script data-main="js/app.js" src="js/require.js"></script>
What it will do it will load your script after loading require.js.
I was also seeing the same error on browser console for a project based out of require.js. As stated under MISMATCHED ANONYMOUS DEFINE() MODULES at https://requirejs.org/docs/errors.html, this error has multiple causes, the interesting one in my case being: If the problem is the use of loader plugins or anonymous modules but the RequireJS optimizer is not used for file bundling, use the RequireJS optimizer. As it turns out, Google Closure compiler was getting used to merge/minify the Javascript code during build. Solution was to remove the Google closure compiler, and instead use require.js's optimizer (r.js) to merge the js files.

Blueimp jquery-file-upload with Browserify and Angular

Has anybody had any luck with using blueimp jquery-file-upload with browserify? I have the following requires in my javascript ...
require("jquery");
require("blueimp-file-upload/js/jquery.iframe-transport.js");
require("blueimp-file-upload");
require("blueimp-file-upload/js/jquery.fileupload-angular.js");
and I get the following error when I use the resulting browserified code...
TypeError: $element.fileupload is not a function
... at the line ...
$element.fileupload(angular.extend(
... inside of jquery.fileupload-angular.js. Without browserify this was working fine. I can't figure out where the fileupload() function is being added to the prototype of the $element.
By request I'm posting what I did here to get around the issue. So technically speaking not an answer but a "work around". As I indicated in my comment above I used gulp-concat along with gulp-uglify to do the minimizing "manually". I say manually because I have to list all of the source files here rather than relying on the requires.
gulp.src([src1, src2, ..., srcN])
.pipe(concat('bundle.js'))
.pipe(uglify())
.pipe(gulp.dest(outputdir));

#section syntax instead of requirejs or browserify for angularjs application

I understand that requirejs and browserify can load my files dependent on its current context, and that it is amazing. I would really prefer to use the #section sections syntax that the razor engine uses. Was just wondering if there is a way to implement this into a typescript / angularjs application.
for example
index.html
#renderSection scripts;
// which could turn into something like
<script data-render="scripts"></scripts>
// the app.run() could declare all the scripts that will be needed on every
// page view
view.html
<script ng-section-repeat="injected in injection"></script>
// the ng-section-repeat is basically taking all the items in the
// typescript constructor and then finding out which ones are needed for
// that view.
I like the idea injecting application file dependencies in the view , without a configuration file and all the added extras that comes with the loaders.
I just want to easily define what files are needed in the actual view and get them loaded, with angular's dependency injection handling the dependency itself.
If you are handling all your dependencies with $inject then , as far as i can tell, dependency is technically already setup in the controllers, all one would need, is to load this as it is called. Which could even eliminate the need for the #section scripts completely
Update:
What i have done to sort of replicate the module loaders is to just use gulp-concat and define the file order in my gulp.config.js and then pass it to the gulp-src before running $.concat .this allows me to have the files in the gulp steam , in dependent order . They are however loaded on the first load. With gulp-uglify the files are tiny ( its now at 566Kb with 16 external libraries loading in 69ms . To put that into perspective it takes 209ms to load one google font ).
I dont know maybe i am not understanding browserify correctly but i honestly struggle to see the need for it, its seems extremely convoluted for something so simple
It is possible using external modules and an injector to do what you asked for:
I just want to easily define what files are needed in the actual view
import {UserFactory} from 'models/userFactory';
import {UserValidator} from 'models/userValidator';
import {Inject} from 'angular2/di';
and get them loaded, with angular's dependency injection handling the dependency itself.
Note: My example uses angular 2.x because I less familiar with angular 1.x and I'm sure you can do something really similar...
class SomeComponent {
userName: string;
userRating: number;
rating: number;
constructor(
#Inject(UserFactory) UserFactory
#Inject(UserValidator) UserValidator
)
{
this.UserFactory = UserFactory;
this.UserValidator = UserValidator;
}
}
Then you can use Browserify to create a bundle.js file that can be executed in a web browser.

Angular karma test failing due to unknown provider of injected value recipe

Before posting this question, I have researched a lot regarding the "unknown provider" error but I could not find anything like my scenario.
Basically in my app.js were I have defined my main app module, called - "bookingsApp", I am adding a value recipe to it, called - "connectionWithServerErrorMessage".
Then, I am accessing this value recipe, in a service, called - "httpPostingExampleService". Till now no issues. Note that the test for this service passes correctly.
The problem comes, when I call the method that there is in this service in another service. For example, in this case the service, called - "bookingElementExampleService". Please see plunkr for a better understanding: http://plnkr.co/edit/0Z3ZiQXPGdkD08r9Akci
The problem is that when I come to test this other service (bookingElementExampleService), it fails because of the following error:
Error: Unknown provider: connectionWithServerErrorMessageProvider <- connectionWithServerErrorMessage <- httpPostingService
Note: The application works just fine, no errors are outputted, the problem is just with that test failing.
Honestly I could not understand, I think I have all the module dependencies set correctly, so can't really pin point what is the issue. Any help please?
Update
Here is my karma config files:
// list of files / patterns to load in the browser
files: [
//First include all dependencies
'app/lib/jquery/jquery-1.8.3.min.js',
'bower_components/qtip2/jquery.qtip.js',
'app/lib/angular/angular.js',
'app/lib/angular/angular-mocks.js',
'bower_components/angular-debounce/dist/angular-debounce.min.js',
'app/lib/ui-bootstrap/ui-bootstrap-custom-tpls-0.12.0.min.js',
//Then include application and any module definitions which are required to be loaded first
'app/app.js',
'app/components/http-posting/http-posting.js',
'app/components/booking-element/booking-element.js',
'app/components/bookings/bookings-ui.js',
'app/components/date-and-stats/date-and-stats.js',
'app/components/timeline/timeline.js',
//Then include all other files required
'app/*.js',
'app/components/**/*.js',
//Then include all partial files
'app/components/**/*.html' //html files (partials)
],

unit testing angular directives templateUrl (include requirejs and ng-html2js

I am working on a not-yet-huge angular app. I have got a problem with karma unit testing. To make a long story short, I am using angular with requirej. My tests run well if I keep my template embedded in my directive. But as this app will be huge, it will not scale. But when I move the template and load it in my directive with templateUrl, I can not get rid of one of the following errors (depending on how I modify the conf):
(initial error) "Unexpected request: GET path/to/mytpl.html"
"ReferenceError: Can't find variable: angular". This error occurs with different config:
when I put {pattern: 'path/to/mytpl.html', included: false} in my karma.conf and add a requirejs's define path/to/mytpl.html in my test file (this is the way I would like that to work).
when I put path/to/mytpl.html in my karma.conf then all my template return this error (whether I am using ng-html2-js preprocessor or not).
"Error: [$injector:modulerr] Failed to instantiate module templates due to:
Error: [$injector:nomod] Module 'templates' is not available!". I saw that karma-ng-html2js-preprocessor could be use to create a module that will contains all templates, but it never worked.
NB: I do not use FQN in karma.conf, I use it here to be consistent. I do not think that matters, but I prefer to precise it
I saw someone putting each 'path/to/mytpl.html': {deps: ['angular']} in the shim section of their test-main.js. But it does not work for me and that solution will not scale.
I had the same problem and found solution in the following article.
I guess your problem is in wrong karma or requireJS config, in particular base path setup.
In case your directive templateUrl is relative and that url can't be resolved correctly against karma base path or requireJS base path, then you need to work out this issue.
Let's assume your directive has 'app/directive/myDirective.html' value for templateUrl. Then:
Check if your html file is properly included into files section of karma config, pay attention to included:false setting:
files: [
//...
{ pattern: 'path_to_directive/myDirective.html', included: false },
//...
],
of course you can use a wild card chars like * or **, but for troubleshooting purposes I would start with a full path value. According to the value of basePath in karma config, 'path_to_directive' will or won't be the same as path in your app.
Ex: if karma base path is one level up from you app root, then your 'path_to_directive' = 'some-folder/app/directive/myDirective.html'
Make sure you can get your file from the browser. Go to http://localhost:karma_port/base/path_to_directive/myDirective.html.js
While doing this test pay attention to:
base prefix in the url (karma serves all files from that virtual path and adds this prefix to all urls)
'.js' at the end of your url
Once you get file in step 2, you'll see the actual module code, created by html2js preprocessor. It should look something like this:
angular.module('module_path/myDirective.html', []).run(function($templateCache) {
$templateCache.put('module_path/myDirective.html',
//...
Make sure module_path is 'app/directive/'. If not then you have 2 options:
module_path has some prefix => simply remove it by adding the following to karma config:
ngHtml2JsPreprocessor: { stripPrefix: 'modulePrefix' }
module_path is shorter => add missing part:
ngHtml2JsPreprocessor: { prependPrefix: 'missingPart' }
Restart karma and make sure 'module_path' in step 3 is 'app/directive/'
Make sure you have added angular dependency for your template module (check test-main.js which is basically config file for requireJS). Also keep in mind, that value in shim section will be resolved according to baseUrl value in your test-main.js file. For simplicity, I'll assume that requireJS can get the file from 'requirejs_path/myDirective.html' path.
shim: {
//..
'requirejs_path/myDirective.html': { deps: ['angular'] },
//..
}
Make sure you have included your template as a dependency to your test and also don't forget to load the module:
define(['requirejs_path/myDirective.html', 'angular-mocks', '...'], function () {
describe('test suite', function() {
//...
beforeEach(module('app/directive/myDirective.html'));
//...
});
});
I hope by completing these 6 step you'll get a working test. Good luck.
After having set aside this problem for a while and use this time to improve my knowledge and to widen my app, I found a solution.
Brief methodology recap: as karma-ng-html2js-preprocessor or karma-html2js-preprocessor seems to work on some other projects and as they are referenced in the official doc, I tried many (almost all, I think) possible configuration combinations to run one of them in my test environment. With no success, I came the clue : I have to drop them and find another way.
The solution came from grunt-html2js. By simply adding to grunt configuration the basic set-up and run grunt, it generate a module containing all my templates - maybe, I will split it later in more meaningful modules. But from here, work is almost done. Then I just had to :
tell karma to serve the file has other external tools file: [ {pattern: 'path/to/mytplmodule.js', included: false}, ...]
register the path in my require conf for tests path: [ 'templates' : 'path/to/mytplmodule', ...]
shim it, still in require conf for tests, to be sure it won't be loaded before angular shim: [ 'templates' : 'angular', ...]
load this module in my test file define(['templates',...], function(){...});
retrieve the tested directive's template beforeEach(module('path/to/mytpl.html'));
add a step in your grunt configuration to make it automatically generated before running tests.
That's all !
There is a drawback with this approach, it requires to retrieve or mock all other directives' templates used in the tested directive. It could be boring as number of directives grows. But I prefer that for now as it is not invasive for the application's code. Maybe later, especially when I will include javascript's compilation in my process, I will move it from test to app too.

Resources