Running Jasmine Tests from Grunt on JavaScript that uses Require - javascript

I am writing some extensions to lodash. The code related to this question can be download from here. The structure is that code is located in /shared/modules/myExtensions.js. Currently, my code is very basic and looks like this:
'use strict';
var _ = require('lodash');
_.mixin({
'myFunction' : function(s) {
return 'Hello ' + s;
}
});
module.exports = _;
My code will grow in complexity. For that reason, I want to setup unit tests from the start on this. Right now, my tests are located at /shared/tests/myExtensions.tests.js. That file looks like this:
'use strict';
describe('myModule', function() {
it('should work', function() {
expect(true).toBe(true);
});
});
This test always asserts to true. I'm trying to execute this Jasmine test via grunt. When I execute the this via Grunt, I get an error. The error confuses me because the grunt-jasmine-node module is defined in my package.json file. I've also checked that it got downloaded when I ran npm install. Either way, here is the error:
>> Local Npm module "grunt-jasmine-node" not found. Is it installed?
Running "jasmine:testShared" (jasmine) task
Testing jasmine specs via PhantomJS
>> Error: notloaded: Module name "../" has not been loaded yet for context: _. Use require([])
>> http://requirejs.org/docs/errors.html#notloaded at
>> ..\..\C:\Tests\jasmine\_SpecRunner.html:21
>> ..\..\C:\Tests\jasmine\.grunt\grunt-contrib-jasmine\require.js:12 v
>> ..\..\C:\Tests\jasmine\.grunt\grunt-contrib-jasmine\require.js:26 h
>> ..\..\C:\Tests\jasmine\.grunt\grunt-contrib-jasmine\require.js:31
>> ..\..\C:\Tests\jasmine\node_modules\glob\examples\g.js:1
>> Error: notloaded: Module name "../" has not been loaded yet for context: _. Use require([])
>> http://requirejs.org/docs/errors.html#notloaded at
>> ..\..\C:\Tests\jasmine\_SpecRunner.html:21
>> ..\..\C:\Tests\jasmine\.grunt\grunt-contrib-jasmine\require.js:12 v
>> ..\..\C:\Tests\jasmine\.grunt\grunt-contrib-jasmine\require.js:26 h
>> ..\..\C:\Tests\jasmine\.grunt\grunt-contrib-jasmine\require.js:31
>> ..\..\C:\Tests\jasmine\node_modules\glob\examples\usr-local.js:1
>> ReferenceError: Can't find variable: module at
>> ..\..\C:\Tests\jasmine\node_modules\glob\glob.js:37
>> Error caught from PhantomJS. More info can be found by opening the Spec Runner in a browser.
Warning: SyntaxError: Parse error Use --force to continue.
Aborted due to warnings.
This is so frustrating. My code can be downloaded from here. I've been working on this for 2 days now. If I don't get it done today, I'll have to go back to .NET. Can someone please help me get this resolved? I really want to keep moving in this direction. I believe this is just something really small.

grunt-jasmine-node is not defined in your package.json as Andy pointed out.
You can define and install it using the command npm-install --save grunt-jasmine-node that will fix that error.
This issue might be related https://github.com/gruntjs/grunt/issues/232.
Also you might want to seperate your dev dependencies and normal dependencies.
npm install --save-dev module includes the module in 'devDependencies' config, and
npm install --save module includes the module in dependencies config, in package.json.
I hope this will fix your problem, i am looking for that 500 bounty.
Edit
Edit:
Also it appears to me that you are mixing your client libraries with the server sides.
Namely you include vendor path like this:
File: tasks/options/jasmine.js
options: {
specs: "shared/tests/unit/**.tests.js",
// server libs
vendor: "node_modules/**/*.js",
// should be browser libs
// vendor: "shared/libs/lodash/dist/lodash.js",
}
All your node_modules folder gets included inside the browser.
Really what you should be doing is define your libraries in shared/libs
and use that path for the vendor option.
You can use bower to automatically install them.
And finally your actual code,
var _ = require('lodash');
_.mixin({
'myFunction' : function(s) {
return 'Hello ' + s;
}
});
module.exports = _;
This is again server side code, that gets loaded into the browser.
You should write this for the browser.

Related

webpack require with dynamic path

My colleague put something like this in our code:
const information = require('../relative/path/' + tag + '.json');
The funny thing is that it works, and I don't really see how.
I have created this minimal project:
$ head *.json main.js
==> 1.json <==
["message #1"]
==> 2.json <==
["message two"]
==> 3.json <==
["message III"]
==> package.json <==
{
"dependencies": {
"webpack": "^5.38.1"
"webpack-cli": "^4.7.2"
}
}
==> package-lock.json <==
...
==> main.js <==
const arg = process.argv[2] ? process.argv[2] : 1;
console.log(require(`./${arg}.json`)[0]);
when I run the original program, I get this:
$ node main.js 1
message #1
$ node main.js 2
message two
$ node main.js 3
message III
so now I compile with webpack
$ node_modules/.bin/webpack ./main.js
and it creates a dist directory with a single file it in, and that new bundled program works too:
$ node dist/main.js 1
message #1
$ node dist/main.js 2
message two
$ node dist/main.js 3
message III
and when I look inside the bundle, all the info is bundled:
When I remove the require from the program, and just print the arg, the bundled program is a single line.
So how does it do it?
somehow calculate every possible file?
just include everything from the current directory down?
Funny thing is in my simple example, package.json ended up in there too, but in the real one that gave me the idea, it didn't.
Does anybody know how this works?
I mean the simple practical answer for me is, never put variables in require... but I am still curious.
PS the real one is a web project. just used node and args for the example
Webpack always bundles all require'd files into the final output file (by default called bundle.js). You cannot require anything that was not bundled.
If you require something that is not a constant, as you pointed out, it might lead to some trouble. That is why eslint has a no-dynamic-require rule for that. But if you know what you are doing, everything is just fine.
Webpack uses some heuristics to support non-build-time-constant values (i.e. expressions) for require. The exact behavior is documented in webpack's documentation on dependency management.
As explained in that link, your require('../relative/path/' + tag + '.json') will lead webpack to determine:
Directory: ../relative/path
Regular expression: /^.*\.json$/
And will bundle all files matching that criterion.
When your require call is executed, it will provide that file that matches it exactly, or throw an error if that file was not bundled.
Important: This means, of course, that you cannot add files after bundling. You must have files in the right place, before bundling, so they can be found, added and ultimately resolved by webpack.
Also note that often times, you don't need to write your own webpack experiments. Webpack has plenty of official samples. E.g. your case is illustrated exactly by this official webpack sample.

mocha "describe" is not defined

I read all the related mocha "describe" is not defined posts but none of them seem to be suitable for my situation.
I use meteor and installed the "mocha": "^3.5.0" package by npm
I have created a /testfolder in my meteor root directory.
and a sample test mochatest.js
var assert = require("assert"); // node.js core module
describe('Array', function(){
describe('#indexOf()', function(){
it('should return -1 when the value is not present', function(){
assert.equal(-1, [1,2,3].indexOf(4)); // 4 is not present in this array so indexOf returns -1
})
})
});
When i run mocha the test passes.
But when i start my normal server i get: ReferenceError: describe is not defined
.meteor/packages/meteor-tool/.1.3.5_1.1wj76e8++os.linux.x86_64+web.browser+web.cordova/mt-os.linux.x86_64/dev_bundle/server-lib/node_modules/fibers/future.js:280
throw(ex);
^
ReferenceError: describe is not defined
at meteorInstall.test.mochatest.js (test/mochatest.js:3:1)
at fileEvaluate (packages/modules-runtime/.npm/package/node_modules/install/install.js:153:1)
at require (packages/modules-runtime/.npm/package/node_modules/install/install.js:82:1)
at project-i18n.js:6:1
at .meteor/local/build/programs/server/boot.js:297:10
at Array.forEach (native)
at Function._.each._.forEach (.meteor/packages/meteor-tool/.1.3.5_1.1wj76e8++os.linux.x86_64+web.browser+web.cordova/mt-os.linux.x86_64/dev_bundle/server-lib/node_modules/underscore/underscore.js:79:11)
at .meteor/local/build/programs/server/boot.js:133:5
I have a feeling that meteor wants to run the test on startup but can't find mocha stuff.
So what to do?
You need to rename the /test folder to /tests.
From the official Meteor Testing Guide:
The Meteor build tool and the meteor test command ignore any files
located in any tests/ directory. This allows you to put tests in this
directory that you can run using a test runner outside of Meteor’s
built-in test tools and still not have those files loaded in your
application.
You could also consider renaming your test files with extensions like:
*.test[s].*, or *.spec[s].* -- So your file could be named mocha.test.js.
Such files are ignored by Meteor build tool as well.
Looks like the test file is somehow invoked when the server runs. It should not be included anywhere in the server code.
If you can't figure out what's happening, you can try to debug the server and put a breakpoint at the "describe" line - try to see how you got there.

requiring angular modules in browserify

I have written a module called loginModule found in loginModule.js file.
var loginModule = angular.module('loginModule', []);
loginModule.controller('loginController', function ($scope) {
$scope.userName = "Stack Overflow";
});
});
And I have another module called root module which depends on loginModule, so as browserify suggests, I have required it in rootModule.js file.
require('./modules/loginModule.js');
var rootModule = angular.module('rootModule', ['ngRoute','loginModule']);
rootModule.controller('loginController', function ($scope, $window) {
$scope.sample = "Hello angular";
});
Directory Structure
| app
| - modules
| | - loginModule.js
| - rootModule.js
| gulpfile.js
But when I my gulp task tries to bundle them, I keep getting this error message.
If what I have understood is correct, bundling just concats the JavaScript files to make one huge JS file (usually referred to as bundle.js), and the files to be concatenated and the dependencies are resolved by going through the require('*.js') statements found in the entry point file. (Here rootModule.js).
So am I doing everything correctly here? Any suggestions guys? I know I am missing something very basic...
Just found an issue for your same problem on github, here.
The issue is still open. Still, the last post says:
I was able to get it to work after installing a fresh node and npm, and reinstalling all my node_modules again.
So, if your're using nodejs 4.1, npm#3, you could try to upgrade, too... :-)

Fixing Module Not Found with Browserify for Local Relative Requires

I have a demo NPM framework structured as the following:
./src/child.coffee
module.exports = class Child
./src/parent.coffee
Child = require "./child"
module.exports = class Parent
./gulp.js
require('coffee-script/register');
require('./gulpfile.coffee');
./gulp.coffee
gulp = require "gulp"
util = require "gulp-util"
coffee = require "gulp-coffee"
browserify = require "gulp-browserify"
gulp.task "build", ->
gulp.src("./src/**/*.coffee")
.pipe(coffee().on("error", util.log))
.pipe(gulp.dest("./lib/"))
Everything works great if I run gulp build. However, I'm trying to introduce Browserify by adding the following to the build task:
gulp.task "build", ->
gulp.src("./src/**/*.coffee")
.pipe(coffee().on("error", util.log))
.pipe(browserify())
.pipe(gulp.dest("./lib/"))
With that in place the relative requires within the framework fail:
events.js:85
throw er; // Unhandled 'error' event
^ Error: module "./child" not found from "/Users/kevin/Desktop/demo/src/fake_d1543b04.js" at notFound
(/Users/kevin/Desktop/demo/node_modules/gulp-browserify/node_modules/browserify/index.js:803:15)
at
/Users/kevin/Desktop/demo/node_modules/gulp-browserify/node_modules/browserify/index.js:754:23
at
/Users/kevin/Desktop/demo/node_modules/gulp-browserify/node_modules/browserify/node_modules/browser-resolve/index.js:185:24
at
/Users/kevin/Desktop/demo/node_modules/gulp-browserify/node_modules/browserify/node_modules/resolve/lib/async.js:36:22
at load
(/Users/kevin/Desktop/demo/node_modules/gulp-browserify/node_modules/browserify/node_modules/resolve/lib/async.js:54:43)
at
/Users/kevin/Desktop/demo/node_modules/gulp-browserify/node_modules/browserify/node_modules/resolve/lib/async.js:60:22
at
/Users/kevin/Desktop/demo/node_modules/gulp-browserify/node_modules/browserify/node_modules/resolve/lib/async.js:16:47
at FSReqWrap.oncomplete (fs.js:95:15)
How does one properly setup relative requires within a framework and have it work with gulp and coffeescript? Changing the require to be for a dependency from the package.json (i.e. Lodash = require "lodash") allows gulp to build. Furthermore changing from coffeescript to regular javascript also fixes the problem.
The problem is likely the .coffee extension. You need to instruct browserify to look for that extension. See opts.extensions. I don't know how you'd do that with gulp-browserify, but you're better off not using it anyway (it's blacklisted by gulp, if that matters to you, and I believe it's unmaintained).

Module not found when using rekuire, requirish, or rfr to solve nodejs require relative issue

I'd like to avoid the complex relative path issue described here by using one of the recommended solutions. I've come across three similar libraries:
rekuire
node-rfr aka Require from Root
requirish
I've tried all three and all are failing with "module not found" or a similar error which makes me believe I'm doing something fundamentally wrong. I'm relatively inexperienced with npm/node. I'm only using node in the browser using browserify to bundle my app into a single JS file.
Here's my extremely simple hello world example:
Structure:
lib/Bob.js
app.js
Bob.js
function Bob() {
return "I am bob";
}
module.exports = Bob;
app.js
var Bob = require('./lib/Bob.js');
console.log(Bob());
Bundling into a single JS:
browserify app.js -o bundle.js
Chrome's console successfully outputs "I am Bob".
Now if I try and of the libraries, let's say requirish:
REQUIRISH:
npm install requirish
app.js changes
'use strict';
require('requirish')._(module);
var Bob = require('lib/Bob');
console.log(Bob());
Bundling changes
browserify -t requirish app.js > bundle.js
I get the following error:
Error: Cannot find module '/lib/Bob' from '/Users/ngb/projects/MyApp/src/main/resources/public/js/hello'
at /Users/ngb/.nvm/v0.10.30/lib/node_modules/browserify/node_modules/resolve/lib/async.js:42:25
RFR:
'use strict';
var rfr = require('rfr');
var Bob = rfr('lib/Bob');
console.log(Bob());
Building
browserify app.js -o bundle.js -d
Chrome's console outputs the following error:
Uncaught Error: Cannot find module 'lib/Bob'
The Browserify can find module by parse string "require".
If you want to use both side client and server, use rfr for server side and browserify-rfr for browserify's transform.
In my opinion, the "rfr" is the best because this module does not override original require.
------- Notice! Additional Information,
As today browserify-rfr version leaves my local file path to bundle.js. This may cause another problem, so I chose requirish. Since the requirish changes behavior of original require by pushing a new path to module.paths, you always notice that and alert your coworker!
thanks!
https://www.npmjs.com/package/requirish

Categories

Resources