Proper use of karma-commonjs with Jasmine 2 - node.js

I've spent a fair amount of time trying to debug this, and figured I would ask. I even created a GitHub repository but won't rely on it, so here goes. I'm trying to take advantage of CommonJS syntax within the Karma test runner using PhantomJS. For my module I created the simplest thing I could think of:
exports.returnYes = function() {
return "Yes";
};
The Jasmine test is:
var returnYes = require("../js/returnYes").returnYes;
describe("returnYes", function() {
it("should return Yes", function() {
expect(returnYes()).toBe("Yes");
});
});
And, if I do a jasmine init I can run it from the command line thanks to jasmine-npm by simply typing jasmine with output:
$ jasmine
Started
.
1 spec, 0 failures
Finished in 0.003 seconds
Now to try and get it to work inside karma:
I create my karma.conf.js with frameworks: jasmine,commonjs. And, I add commonjs as preprocessor.
I try to do a karma run and I find that it can't find global which is part of getJasmineRequireObj in jasmine.js where it declares jasmineGlobal = global;
The command line output is a little hard to read, but here it is:
$ karma run
[2015-06-27 17:41:35.266] [DEBUG] config - Loading config /Users/zen/Projects/karma-commonjs-test/karma.conf.js
##teamcity[enteredTheMatrix]
##teamcity[testSuiteStarted nodeId='1' parentNodeId='0' name='karma.conf.js' nodeType='config' locationHint='config:///Users/zen/Projects/karma-commonjs-test/karma.conf.js']
##teamcity[testSuiteStarted nodeId='2' parentNodeId='1' name='PhantomJS 1.9.8 (Mac OS X 0.0.0)' nodeType='browser']
##teamcity[testStarted nodeId='3' parentNodeId='2' name='Error' nodeType='browserError']
##teamcity[testFailed nodeId='3' error='yes' message='ReferenceError: Can|'t find variable: global|nat http://localhost:9876/base/node_modules/jasmine-core/lib/jasmine-core/jasmine.js?68f13ab3f93af5a219b9fe8409f8763b31998bba:27']
##teamcity[testSuiteFinished nodeId='2']
##teamcity[testSuiteFinished nodeId='1']
For good measure here are the devDependencies in my packages.json:
"devDependencies": {
"jasmine-core": "^2.3.4",
"karma": "^0.12.37",
"karma-commonjs": "0.0.13",
"karma-jasmine": "^0.3.5",
"karma-phantomjs-launcher": "^0.2.0",
"phantomjs": "^1.9.17"
}
I'm not sure why I can't find global. Any help would be greatly appreciated!!! :)

It seems like my whole problem came down to the line in karma.conf.js (not shown in my original question:
preprocessors: {
'**/*.js': ['commonjs']
},
For some reason, jasmine.js is not happy being pre-processed by commonjs, and "**/*.js" says to go through all subdirectories (which is probably overkill), including node_modules which has jasmine-core/jasmine.js
So I can either make my pre-processor more specific (best practice):
preprocessors: {
'spec/*.js': ['commonjs'],
'js/*.js': ['commonjs']
},
but as a test to see if any other files would give me a problem, I tried:
preprocessors: {
'**/!(jasmine).js': ['commonjs'],
},
And, everything worked as well. Bottom line. Do not process jasmine.js through commonjs preprocessor!

Related

webpack import error with node-postgres ('pg'.Client)

Trying to bundle the following file with Webpack fails with
ERROR in ./~/pg/lib/native/index.js Module not found: Error: Cannot
resolve module 'pg-native' in
.../node_modules/pg/lib/native
# ./~/pg/lib/native/index.js 9:13-33
I tried several ignore statements in the .babelrc but didnt get it running...
The test-file i want to bundle: handler.js
const Client = require('pg').Client;
console.log("done");
webpack.config.js
module.exports = {
entry: './handler.js',
target: 'node',
module: {
loaders: [{
test: /\.js$/,
loaders: ['babel'],
include: __dirname,
exclude: /node_modules/,
}]
}
};
.babelrc
{
"plugins": ["transform-runtime"],
"presets": ["es2015", "stage-1"]
}
package.json
"dependencies": {
"postgraphql": "^2.4.0",
"babel-runtime": "6.11.6"
},
"devDependencies": {
"babel-core": "^6.13.2",
"babel-loader": "^6.2.4",
"babel-plugin-transform-runtime": "^6.12.0",
"babel-preset-es2015": "^6.13.2",
"babel-preset-stage-0": "^6.5.0",
"babel-polyfill": "6.13.0",
"serverless-webpack": "^1.0.0-rc.3",
"webpack": "^1.13.1"
}
Somewhat related github-issues:
https://github.com/brianc/node-postgres/issues/1187
https://github.com/serverless/serverless-runtime-babel/issues/8
This is indeed an old thread, but one that helped me nonetheless.
The solution provided by Steve Schafer 1 is good, but not the simplest.
Instead, the one provided by Marco Lüthy 2 in the linked issue is probably the easiest to set up because it is pure configuration, without even the need for a dummy file to be created.
It consists of modifying your Webpack config plugins array as follows:
const webpack = require('webpack');
const webpackConfig = {
...
resolve: { ... },
plugins: [
new webpack.IgnorePlugin(/^pg-native$/)
// Or, for WebPack 4+:
new webpack.IgnorePlugin({ resourceRegExp: /^pg-native$/ })
],
output: { ... },
...
}
Updated to include a change suggested in the comments.
This is an old thread but the problem still exists, so for anyone experiencing it, there is a workaround. The problem is an interaction between the way that node-postgres is written and how babel rewrites the code, which forces pg-native to be loaded even when you don't explicitly import/require it.
The simplest workaround is to add a couple of aliases to your webpack.config.js to cause it to link in a dummy do-nothing file instead:
{
...
resolve: {
alias: {
...
'pg-native': path-to-dummy-js-file,
'dns': path-to-dummy-js-file
}
}
...
}
where the dummy file contains a single line:
export default null
See https://github.com/brianc/node-postgres/issues/838 for further discussion and alternative workarounds.
I know that this is an old topic but I'm compelled to share how I solved it. It was maddening to deal with.
So, here is the readers digest version as based on the recollection from the last brain cell that I have.
Error:
Webpack Compilation Error ./node_modules/pg/lib/native/client.js Module not found: Error: Can't resolve 'pg-native'
The error above was thrown when attempting to run a Cypress test that required the npm package 'pg'.
Attempting to install the pg-native package was not successful and resulted in another error; namely ->
Call to 'pg_config --libdir' returned exit status 1 while in binding.gyp. while trying to load binding.gyp
I found that executing pg_config --libdir in the VSCode cmd prompt resulted in that command failing.
However, I knew that it should work since running that command from the system command prompt resulted in this -> C:/PROGRA~1/POSTGR~1/9.3/lib
That is the path that contains a required dll.
So, instead of running npm install from the VSCode command prompt, I ran it from the command prompt as launched from windows.
The result...success!!! pg-native was installed successfully.
After, the Cypress test was able to run as well.
Errors in now way helped me to arrive at this solution. It was more just checking that things were installed that were required, etc.
You may have pg-native globally installed locally. Hence the packet manager does not include the pg-native in the lock file. That was a issue i experienced where it did run fine locally but every time i build in the cloud webpack complained about pg-native missing. I solved it by removing the lockfile in the files pushed to the cloud (In this case seed.run).

shimming linkurious - how to configure?

I'm trying to use the linkurious library (a sigma fork), which provides a "main": "dist/sigma.require.js" (in the package.json). this allows me to do:
var sigma = require('linkurious');
however, the plugins are not included so I have to require them separately. the problem is that the plugins rely on the sigma variable being available in the global scope. so I've shimmed things as follows (from the package.json):
"browser": {
"sigma": "./node_modules/linkurious/dist/sigma.js",
"linkurious/plugins": "./node_modules/linkurious/dist/plugins.js"
},
"browserify-shim": {
"sigma": {"exports": "sigma"},
"linkurious/plugins": { "depends": [ "sigma" ] }
},
"browserify": {
"transform": [ "browserify-shim" ]
},
which, when run in a browser doesn't generate errors during inclusion of the plugins (I gather this means the global variable is available) but references to the plugins fail (as if they failed to attach themselves, or attached themselves to a non-global variable).
I'm using grunt-browserify to run the process where I have it configured like this (from the Gruntfile.js):
grunt.initConfig({
browserify: {
libs: {
files: { 'inc.js': ['index.js'] },
},
}
});
I've attached a little project to this issue with the minimal required code to demonstrate the problem in the hopes that someone else can replicate/figure out. unpack, type npm install; npm start and run a browser against http://localhost:8002/ to see the issue.
thanks in advance,
ekkis
sigma.zip
- edit I -
incidentally, bendrucker at the git repo (see: https://github.com/thlorenz/browserify-shim/issues/215) suggests I need to do a global transform. It's been explained to me that shimming doesn't work on node_modules files and for those I need a global transform. this doesn't make much sense to me as the whole point of shimming is that you don't own the code you're shimming. in any case, bendrucker pointed me to this other SO post where the question is posed but no answers are provided.
help?

getting browserify-shim to work as expected

I am trying to get browserify-shim to work, but I can't seem to get it to create the globals I expect to see.
(note, my end goal is to get this working from gulp, but after having many problems, I figured I would eliminate one variable and try to get this working in browserify alone)
In this case, I expect "horses" to be created as a global variable pointing to the jQuery library.
// package.json
{
"version": "0.0.1",
"browser": {
"jquery": "./lib/js/vendor/jquery-2.0.2.js"
},
"browserify": {
"transform": [
"browserify-shim"
]
},
"browserify-shim": {
"jquery": "global:horses"
},
"devDependencies": {
// my dev dependencies
},
"dependencies": {
// my production dependencies
}
}
With this configuration, from the command line I run:
browserify common.js > mycoolfile.js
I then include mycoolfile.js into my application and run it in the browser:
<script src="mycoolfile.js"></script>
The browserified file is included fine, but when I go to chrome dev tools console and type "horses" I get an undefined error. Any thoughts on what I may be doing wrong? Thank you
I think that you want to get at jquery via exports and you are also assuming that global lets you take a global a module creates and make an alias for it, but I don't think it does that. The above might work if jquery really did have a global called horses it creates, but it won't if you just make up that name arbitrarily. I think you are trying to do something more like this:
"browserify-shim": {
"jquery": {"exports": "jQuery"}
},

npm + Mocha + RequireJS

I'm having quite the time trying to set up node/npm with Mocha and RequireJS. Here's what I've done.
I've created a testing/ directory, with this structure:
testing/
|
+-- package.json
|
+-- README.md
|
+-- test/
|
+-- mocha.opts
|
+-- widgets/
|
+--mywidget/
|
+-- test.js
Here is what each relevant file contains:
package.json:
{
"name":"testing-project",
"version":"2.5.0",
"description":"Testing Project",
"keywords":["test"],
"engines": { "node": ">= 0.7.0 < 0.11.0" },
"scripts" : {
"test": "./node_modules/.bin/mocha"
},
"devDependencies": {
"mocha": ">= 1.18.2",
"requirejs": ">= 2.1.11",
"should": ">= 3.2.0",
"expect.js": ">= 0.3.1"
}
}
test/mocha.opts:
--require expect.js
--require should
--require requirejs
--require mocha
--reporter spec
--ui tdd
--recursive
--growl
test/widgets/mywidget/test.js
'use strict';
var requirejs = require('requirejs');
// Also tried with: require('../../../r.js') which I downloaded from RequireJS' site
requirejs.config({
baseUrl: '../../../../',
nodeRequire: require
});
console.log('before require');
requirejs(['mywidget/trunk/src/mywidgetfile.js'], function(myObj){
console.log('after require');
var expect = require('expect.js');
// Instead of the above "requirejs['mywidget..." line, I've also tried:
// var myObj = requirejs('mywidget/trunk/src/mywidgetfile.js'); AND:
// var myObj = requirejs('../../../../mywidget/trunk/src/mywidgetfile.js');
describe('My Widget', function(){
describe('my-widget#getInfo', function(){
it('should pass this test', function(done){
expect( myObj.returnString('test') ).to.equal( 'test' );
done();
})
})
});
});
console.log('done');
It will output the console lines "before require" and "done", but as long as I have the requirejs(['mywidget... line in, it will not hit the after require. If I remove the requirejs line (and the corresponding closing brace/paren line), and instead use the direct "var myObj =" line, I get "cannot find module", and if I use the second "var myObj" line, I get "Reference Error: define is not defined".
I'm trying to package this all, for convenience for other developers, with npm, such that I'm running the command "npm test" from within the top "testing/" directory.
I've been scouring for answers and trying so many things, but I can't seem to require a file using RequireJS and have "define()" defined. I can execute tests, that's not a problem... it's just trying to insert RequireJS into the mix that is when I start having the issues.
Any help would be tremendous!
Thank you!
There are multiple problems going on in what you are showing us. You are incorrectly using both RequireJS and Mocha.
RequireJS
I am pretty sure your baseUrl is incorrect. You seem to think that Mocha's current working directory will be set to test/widgets/mywidget/ when it executes the tests in test/widgets/mywidget/test.js. That's not the case. The working directory is wherever you happen to be when you run npm test. According to your description you are in testing/ when you run it. It is not clear to me what value your baseUrl should be because you do not provide enough information in your question but I trust that from the explanation I just gave you can figure it out.
Now you may think "surely, my baseUrl is correct because when I execute requirejs(['mywidget/trunk/src/mywidgetfile.js'], function(myObj){ I don't get an error". This would be an incorrect inference. While this requirejs invocation schedules the loading of your module, RequireJS does not get the opportunity to try loading it because Mocha exits before RequireJS tries to load it. You can check this by replacing your module path with complete garbage and you won't get an error.
Once you fix this baseUrl issue, using var myObj = requirejs('mywidget/trunk/src/mywidgetfile.js') will work as you expect. So you'll be able to avoid using the asynchronous form of require (this is the form that uses an array of dependencies as the first argument). (The requirejs function you use is just an alias for the function normally called require in RequireJS' documentation.)
Mocha
Your tests are not running because Mocha does not see them. The way Mocha works is by reading all of the test files it finds and then executing them. The callbacks to each describe calls are executed right away, and the callbacks to each it calls are recorded as tests to be run. Once Mocha is done figuring out what tests exist, it runs them.
What happens with your test file is that Mocha executes it, as usual. However, there is no call to describe or it in the top scope of your test file. There are calls in your callback to requirejs but remember what I said above: RequireJS does not get the opportunity to load the module so it does not get the opportunity to run the callback. (And even if it did run it, it would be too late.) So Mocha does not see any tests and exits right away.
The Way Forward
Figure out the baseUrl you need, and then this should work:
'use strict';
var requirejs = require('requirejs');
requirejs.config({
baseUrl: <whatever value is needed here>,
nodeRequire: require
});
var myObj = requirejs('mywidget/trunk/src/mywidgetfile.js');
describe('My Widget', function() {
// etc...
You might also consider dropping RequireJS entirely from your test suite. I've written a library that works just as well in Node as in the browser. It is composed of AMD modules and is loaded by RequireJS in the browser, but I don't use RequireJS in the test suite. This is the loader I use to load my modules in Node. There's also amdefine which I've not used but should give similar capabilities.

Less won't compile as nodejs middleware

I setup less-middleware for compiling less on the fly, it worked great for quite some time now, but I was changing some packages, doing npm update and so on, but nothing really less-related...
And it stopped working. When I'm requesting for example main.css (it should compile main.less and serve it as css), I get weird error in console:
LESS Syntax error : Object function (deleteValue) {
for (var i = 0; i < this.length; i++) {
if (this[i] == deleteValue) {
this.splice(i, 1);
i--;
}
}
return this;
} has no method 'charAt'
LESS File : /srv/sicy-node/public/css/main.less null:-1
TypeError: Object function (deleteValue) {
for (var i = 0; i < this.length; i++) {
if (this[i] == deleteValue) {
this.splice(i, 1);
i--;
}
}
return this;
} has no method 'charAt'
at Object.Parser.parser.parsers.parsers.ruleProperty (/srv/sicy-node/node_modules/less-middleware/node_modules/less/lib/less/parser.js:1938:37)
at Object.Parser.parser.parsers.parsers.rule (/srv/sicy-node/node_modules/less-middleware/node_modules/less/lib/less/parser.js:1479:48)
at Object.Parser.parser.parsers.parsers.primary (/srv/sicy-node/node_modules/less-middleware/node_modules/less/lib/less/parser.js:721:76)
at Object.Parser.parser.parsers.parsers.block (/srv/sicy-node/node_modules/less-middleware/node_modules/less/lib/less/parser.js:1427:51)
at Object.Parser.parser.parsers.parsers.ruleset (/srv/sicy-node/node_modules/less-middleware/node_modules/less/lib/less/parser.js:1461:48)
at Object.Parser.parser.parsers.parsers.primary (/srv/sicy-node/node_modules/less-middleware/node_modules/less/lib/less/parser.js:721:91)
at Object.Parser.parser.parsers.parsers.block (/srv/sicy-node/node_modules/less-middleware/node_modules/less/lib/less/parser.js:1427:51)
at Object.Parser.parser.parsers.parsers.directive (/srv/sicy-node/node_modules/less-middleware/node_modules/less/lib/less/parser.js:1715:34)
at Object.Parser.parser.parsers.parsers.primary (/srv/sicy-node/node_modules/less-middleware/node_modules/less/lib/less/parser.js:722:64)
at Object.Parser.parser.parse [as parse] (/srv/sicy-node/node_modules/less-middleware/node_modules/less/lib/less/parser.js:498:61)
This is how middleware is set:
app.use(require('less-middleware')({ src: __dirname + '/public' }));
It looks like this is a result of that bug in Less 1.6.1 (basically, Less fails if some other module extends Array.prototype). Updating less-middleware to more recent Less version should help (you can update your installation by changing the version in this file to ~1.6.3 if it does not update automatically).
I might not be solving your exact problem but this is how i do the less compilation using grunt, infact not just i but most of the people do, and i find it very convenient.
grunt provides a great way to automate the process of transmuting LESS into CSS. Initially you'll have to set up a few tools, but once you're done with that, you can easily use the system with all your projects.
Grunt is a JavaScript-based task runner that can be configured to keep an eye on changes made to your LESS files. When the contents change, it automatically compiles the files into a minified CSS file.
Step 1: Install Node.js
Get the installation package from Nodejs.com, and install it. Binaries are available for Mac OS X, Windows, Linux, and SunOS. You can also compile it from source code.
Step 2: Install Grunt
Install Grunt using the Node package manager:
sudo npm install -g grunt
sudo npm install -g grunt-cli
Step 3: Write your Grunt configuration file
Create a Gruntfile.js file in your project directory. Then copy and paste the contents below. You'll just need to change the (commented) lines that define which files you want Grunt to watch, and where to place the compiled CSS file.
module.exports = function(grunt) {
grunt.initConfig({
less: {
development: {
options: {
compress: true,
yuicompress: true,
optimization: 2
},
files: {
// target.css file: source.less file
"sites/all/themes/jiandan/css/main.css": "sites/all/themes /jiandan/less/main.less"
}
}
},
watch: {
styles: {
// Which files to watch (all .less files recursively in the less directory)
files: ['sites/all/themes/jiandan/less/**/*.less'],
tasks: ['less'],
options: {
nospawn: true
}
}
}
});
grunt.loadNpmTasks('grunt-contrib-less');
grunt.loadNpmTasks('grunt-contrib-watch');
grunt.registerTask('default', ['watch']);
};
Step 4: Configure the package
cd YOUR_PROJECT_DIRECTORY
npm init
The above will prompt you to supply additional information about your project.
When you're done, open the package.json file located in your project directory, and add the following lines of code:
"devDependencies": {
"grunt": "~0.4.1",
"grunt-contrib-less": "~0.5.0",
"grunt-contrib-watch": "~0.4.0"
},
Then issue the following command to install the package dependencies:
npm install
Step 5: Start Grunt
grunt
Well that's it and you can compile all your less in one shot.
I agree that initially it looks complicated but once you get used to it, you are going to find it very simple. All you need to do is create a configuration file for each project, and Grunt will take care of the rest.
It seems as it was problem with permissions. I've just set new permissions and everything works fine again. So if anyone have same problem be sure that less can create new file and that original less is readable by your app.
Sorry for wasting your time.
Edit: Problem can also occur if you are using #import url("something.less"), try dropping url part: #impurt "something.less"

Resources