Issue a unit test on a Gulp file using Karma & Jasmine - javascript

I wrote a unit test for a Gulp file. The test runs through karma using Jasmine Framework (safari/chrome).
Knowing that Karma runs the test file, specified in the json config file, in the browser, it should have a way to run Node's modules in the browser.
After researching, I found that by using Browserify I'll be able to require modules in the browser.
When I write this command
browserify ./Test/GulpTest.js -o ./Test/TEST.js -d
The new TEST.js seems to be big
and I run the following command to start the test on the new TEST.js
karma start karma.conf.js
I get this error:
gulp input stream
✗ should compile from ts to js TypeError: Cannot read property 'isTTY' of undefined
at Object. (/Users/Snap/Desktop/Demo App/Test/TEST.js:75226:20)
at Object.252._process (/Users/Snap/Desktop/Demo App/Test/TEST.js:75284:4)
at s (/Users/Snap/Desktop/Demo App/Test/TEST.js:1:254)
at /Users/Snap/Desktop/Demo App/Test/TEST.js:1:305
at Object.31../lib/PluginError (/Users/Snap/Desktop/Demo App/Test/TEST.js:3530:9)
at Object.239../lib/PluginError (/Users/Snap/Desktop/Demo App/Test/TEST.js:75113:21)
at s (/Users/Snap/Desktop/Demo App/Test/TEST.js:1:254)
at /Users/Snap/Desktop/Demo App/Test/TEST.js:1:305
at Object.229.deprecated (/Users/Snap/Desktop/Demo App/Test/TEST.js:74824:13)
at s (/Users/Snap/Desktop/Demo App/Test/TEST.js:1:254)
Chrome 44.0.2403 (Mac OS X 10.10.4): Executed 1 of 1 (1 FAILED) ERROR
(0.037 secs / 0.03 secs)
it("should compile from ts to js", function () {
var gulp = require("gulp");
var ts = require("gulp-typescript");
var lazy = require("gulp-load-plugins");
var fs = require('graceful-fs');
var should = require('should');
var join = require('path').join;
/*
* * * Compile Typescript to JavaScript
*/
gulp.task("ts-compiler", function () {
return gulp.src("./Test/lib/file.ts")
.pipe(lazy.typescript({
// Generates corresponding .map file.
sourceMap : false,
// Generates corresponding .d.ts file.
declaration : true,
// Do not emit comments to output.
removeComments : false,
// Warn on expressions and declarations with an implied 'any' type.
noImplicitAny : false,
// Skip resolution and preprocessing.
noResolve : false,
// Specify module code generation: 'commonjs' or 'amd'
module : "amd",
// Specify ECMAScript target version: 'ES3' (default), or 'ES5'
target : "ES5"
}))
.pipe(gulp.dest("./Test/lib/dest"));
});
gulp.start("ts-compiler", function () {
console.log("compiling...");
should.exist("./Test/lib/dest/file.js");
});
});

You can't run Gulp inside karma and jasmine—you're running it as if it is a front-end library, and it is not.
You need to use a back-end testing library. You can still use jasmine, you just have to use it through nodejs, which is how gulp runs: https://www.npmjs.com/package/jasmine
You might be interested to see how I wrote unit tests for my gulp tasks where I work: https://github.com/Lostmyname/lmn-gulp-tasks/tree/master/test

Related

Mocha not recognizing CoffeeScript/JS test when adding programatically

I am trying to add mocha to an existing project. I have the following test just for putting things together...
assert = require('assert');
describe 'Array', ->
describe '#indexOf()', ->
it 'should return -1 when the value is not present', ->
assert.equal(-1, [1,2,3].indexOf(4));
Options...
--compilers coffee:coffee-script/register
Then I run mocha --opts ./mocha.opts src/test/coffee/test/test.coffee and I see
1 passing (6ms)
Now I try to create a runner file to handle
globFlat = require('glob-flat');
Mocha = require('mocha');
mocha = new Mocha();
files = globFlat.sync([
'src/test/coffee/test/test.coffee'
]);
mocha.addFile file for file in files
mocha.run();
And run mocha --opts ./mocha.opts src/test/mocha/mocha-runner.coffee I get
0 passing (0ms)
So why is it not finding the test?
Update
I have also converted everything over to JS to ensure it wasn't an issue with CS and I am getting the same thing...
require('coffee-script');
var globFlat = require('glob-flat');
var Mocha = require('mocha');
var mocha = new Mocha();
mocha.addFile('src/test/coffee/test/test.js');
runner = mocha.run();
console.log("Done");
It runs like this...
mocha src/test/mocha/mocha-runner.js
Done
0 passing (0ms)
Update 2
Ok so it appears I should be using node and not mocha for running it. This presents a problem as the .js version works but the .coffee version throws an error...
(function (exports, require, module, __filename, __dirname) { require 'coffee-script';
^^^^^^^^^^^^^^^
SyntaxError: Unexpected string
Because node cannot recognize the coffeescript
I am going to post this up here as an answer, although I don't like it...
mocha-wrapper.js
require('coffee-script/register');
require('./mocha-runner.coffee');
mocha-runner.coffee
globFlat = require 'glob-flat';
Mocha = require 'mocha';
mocha = new Mocha();
files = globFlat.sync([
'src/test/coffee/test/test.coffee'
]);
mocha.addFile file for file in files
mocha.run();
I would like to avoid the multiple files but for now it looks like I am stuck :-/. That is why I am going to wait to accept my answer.

Integrating javascripts unit tests code coverage in MSBuild

I am using Jasmine and Karma for writing unit tests and code coverage. I have created the tasks using Gulp and running them through task runner explorer in VS 2015 update 3.
var gulp = require("gulp");
var Server = require('karma').Server;
var remapIstanbul = require('remap-istanbul/lib/gulpRemapIstanbul');
gulp.task('unit-tests', function (done) {
new Server({
configFile: __dirname + '/karma.conf.js'
}, done).start();
});
gulp.task('code-coverage', function () {
return gulp.src('_reports/coverage-javascript.json')
.pipe(remapIstanbul({
reports: {
'json': '_reports/coverage-typescript.json',
'html': '_reports/html-report'
}
}));
});
I want to read the generated html results file, i.e. from _reports/html-report/index.html file during Gated Builds or Nightly builds. I want to use this code coverage to perform certain actions like stopping the build if code coverage is below 80% or when a test failed.
How can I do that?
I have implemented one solution which fails MSBuild whenever any Unit Test failed. Basically I wrote a Custom Target in my project.csproj file which runs after 'CompileTypeScript' target.
<PropertyGroup>
<CompileDependsOn>
$(CompileDependsOn);
GulpBuild;
</CompileDependsOn>
</PropertyGroup>
<Target Name="GulpBuild" DependsOnTargets="CompileTypeScript">
<Exec Command="./node_modules/.bin/gulp task-name" />
</Target>
This task will run after Visual studio compiles TS to JS. In build server 'Path' variable is not set for 'gulp', that's why passing the command through node_modules .bin folder.

UNKOWN error thrown when compiling typescript using Gulp in VS2015

I have installed Visual Studio 2015 (with no other previous versions) on a new laptop and have pulled down the source for our MVC web app. We have a gulp file with tasks to compile our less and typescript.
When running this task ...
cmd.exe /c gulp -b "C:\Code\Trunk\MyProj\MyProj.Web" --color --gulpfile "C:\Code\Trunk\MyProj\MyProj.Web\Gulpfile.js" typescript
... I get the following error:
[09:43:16] Using gulpfile C:\Code\Trunk\MyProj\MyProj.Web\Gulpfile.js
[09:43:16] Starting 'typescript'...
[09:43:34] Plumber found unhandled error:
Error: UNKNOWN, open 'C:\Code\Trunk\MyProj\MyProj.Web\app\allergy\main.js'
Process terminated with code 0.
Here is the task in the gulp file (with other parts removed for brevity):
var gulp = require("gulp");
var plumber = require("gulp-plumber");
var sourcemaps = require("gulp-sourcemaps");
var typescript = require("gulp-typescript");
var merge = require("merge2");
var paths = {
typescript: {
globpatterns: {
all: "./Scripts/**/*.ts",
excludedefinitions: "!./Scripts/**/*.d.ts"
}
}
};
gulp.task("typescript", function () {
var result = gulp.src([
paths.typescript.globpatterns.all,
paths.typescript.globpatterns.excludedefinitions
])
.pipe(plumber())
.pipe(sourcemaps.init())
.pipe(typescript({
removeComments: true,
declarationFiles: false,
noImplicitAny: false,
noEmitOnError: true,
module: "amd",
target: "ES5"
}));
return merge([
result.js.pipe(gulp.dest("./")),
result.pipe(sourcemaps.write()).pipe(gulp.dest("./"))
]);
});
My colleague has the same set-up as me and gets no error.
Typescript is set to version 1.0 in the project file (<TypeScriptToolsVersion>1.0</TypeScriptToolsVersion>) and I can't change this just now. I wondered if the reason was beacuse I don't have this version installed on my machine but my colleague doesn't either. C:\Program Files (x86)\Microsoft SDKs\TypeScript only has a folder for 1.7
I noticed that the task completes successfully if I remove either of the 2 lines with in the merge block.
It's a different .js file in the error message each time
I searched the web to see what the UNKNOWN error even means but couldn't find anything obvious / helpful. Anyone know how to fix this error? Or how I go about finding out why it's being thrown?
EDIT 20-Jan-2016
So, I was getting this error consistently for about a week ... and now it has stopped happening. I haven't made any changes to my development environment either. I'd like to leave this question open since I'm curious as to why this happened.

testing code transpiled for es6

I'm preparing to write some tests with Qunit for a Backbone app that is written for ES6 with babel.js applied to it so that it can run in contemporary browsers. To ensure that I have qunit set up properly and all the paths properly specified, I first tested an Backbone model written in ES5 and everything worked as expected. However, I then included bundle.js (which contains the results of my ES6 code with babel.js applied to it) into my tests/index.html, and wrote
test ( "Code transformed by babel.js contained in bundle.js can be tested", function(){
expect(1);
var es6model = new ES6Model();
equal( es6model.get("defaultproperty"), "defaultstring", "defaultproperty should be defaultstring");
})
and it's telling me ES6Model is not defined.
Question: is there something about code transformed by babeljs that would make it more challenging to be tested using Qunit?
In addition to all the complex js that babel writes at the top of the file, the code in bundle.js looks like this
var Model = Backbone.Model;
var View = Backbone.View;
var Collection = Backbone.Collection;
var Router = Backbone.Router;
var LocalStorage = Backbone.LocalStorage;
var ES6Model = (function (Model) {
function ES6Model() {
_classCallCheck(this, ES6Model);
if (Model != null) {
Model.apply(this, arguments);
}
}
_inherits(ES6Model, Model);
_prototypeProperties(Gopher, null, {
defaults: {
value: function defaults() {
return {
defaultproperty: "defaultstring"
};
},
writable: true,
configurable: true
}
});
return ES6Model;
})(Model);
Update
I include all the code created by babel.js in a file called bundle.js and include that in my index.html like I would any other js file, and it runs without issue, which is why I assumed I could test it like any other js code. However, it should be noted (as the commenter pointed out) that the code created by babel.js is contained in a module..this is how bundle.js begins with the model I'm trying to test coming after
(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
"use strict";
Update
I am using browserify to apply babel to the various files of my ES6 code which creates a bundle. To run the tests, I do npm run test and to compile the bundle, I try both of these (one of them uses modules --ignore) but neither of them work
"scripts": {
"test": "./node_modules/karma/bin/karma start --log-level debug",
"build-js": "browserify app/app.js app/views.js app/models.js app/d3charts.js -t babelify > app/bundle.js",
"t-build": "browserify app/app.js app/views.js app/models.js app/d3charts.js -t [babelify --modules ignore] > app/test/test-bundle.js"
},
(The application is a Backbone.js app).
This is my karma config file. I don't have any further configuration (so I'm guessing my inclusion of karma-require is a waste but maybe necessary...)
module.exports = function(config) {
config.set({
basePath: '',
frameworks: ['qunit'],
plugins: ['karma-qunit', 'karma-phantomjs-launcher', 'karma-requirejs'],
files : [
'app/test/jquery.js',
'app/test/d3.js',
'app/test/json2.js',
'app/test/underscore.js',
'app/test/backbone.js',
'app/backbone.localStorage.js',
'app/test/test-bundle.js',
'app/test/tests.js'
],
reporters: ['progress'],
// web server port
port: 8080,
// enable / disable colors in the output (reporters and logs)
colors: true,
// level of logging
// possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG
logLevel: config.LOG_INFO,
// enable / disable watching file and executing tests whenever any file changes
autoWatch: false,
// start these browsers
// available browser launchers: https://npmjs.org/browse/keyword/karma-launcher
browsers: ['PhantomJS'],
// Continuous Integration mode
// if true, Karma captures browsers, runs the tests and exits
singleRun: true,
// See http://stackoverflow.com/a/27873086/1517919
customLaunchers: {
Chrome_sandbox: {
base: 'Chrome',
flags: ['--no-sandbox']
}
}
});
};
For reference they way to do this with traceur is to compile the traceur-runtime.js file into the code (see https://github.com/google/traceur-compiler/issues/777 - a similar variable not defined error).
E.g.
traceur --out out/src/yourcode.js --script lib/traceur-runtime.js --script test/yourcode.js
(see Compiling Offline https://github.com/google/traceur-compiler/wiki/Compiling-Offline).
Import the Babel-generated module into your test before executing (recommended)
You'll need to include a module loader (e.g. SystemJS) to handle the imports. Babel has excellent documentation for its module system.
It looks something like this:
System.import( 'path/to/ES6Module' )
.then( function( ES6Module ) {
// … Run your tests on ES6Module here
});
Note: System.import() returns a Promise, so your test suite will need to support asynchronous operations.
Tell Babel to skip module generation (simpler)
You can tell Babel not to wrap your code in a module using the --modules ignore flag. This allows your code to set up global variables, immediately available to your unit tests. Global variables are not recommended (especially in production systems), but they are simpler to apply.

Gulp with browserify, tsify, and reactify?

I'm using gulp with browserify and tsify in a TypeScript project. The following is an extract from my gulpfile.js:
var browserified = function (filename, debug) {
var b = browserify({
entries: filename,
debug: debug || false
});
b.plugin('tsify', {
noImplicitAny: true,
target: 'ES5'
});
b.transform('debowerify');
return b.bundle();
};
gulp.task('rebuild', ['lint', 'less'], function() {
var b = browserified ('./src/ts/main.ts', true);
return buildSourceMaps (b);
});
This works so far. I want to extend this so I can require React JSX files. First I tried (from one of my TypeScript files):
import Test = require ('../jsx/Test.jsx');
This doesn't work, though, because tsify would complain as it looks for a TypeScript file ../jsx/Test.jsx.ts. So I use the following hack:
declare var require: any;
var Test = require ('../jsx/Test.jsx');
If Test.jsx is plain vanilla JavaScript, this works. If Test.jsx contains TypeScript, it would fail, which is what I expect. So far, so clear.
Now I want to add reactify to my gulp tasks so I can use JSX in these files. Here I am stuck! I tried adding the following to the function browserified in my gulpfile.js:
b.plugin ('reactify', {
extension: 'jsx'
});
I still get the following error when I call gulp rebuild when Test.jsx contains actual JSX:
Unexpected token <
Obviously, gulp chokes on the first JSX-specific term. I think gulp is trying to pass the JSX through the TypeScript compiler. Which isn't a surprise, since I can't think of a way how to tell tsify to ignore my .jsx files. I'm new to gulp, so I am a bit at a loss. Any ideas how to set up gulp to allow for TypeScript with all .ts files and JSX with all .jsx files?
This is the gulp task I use for development. It uses watchify along with browserify and reactify to build your code, provide source mapping, and rebundle any changes you make on the fly. The path.ENTRY_POINT variable is the main component for your react app (often app.js or main.js).
gulp.task('watch', function() {
gulp.watch(path.HTML, ['copy']);
var watcher = watchify(browserify({
entries: [path.ENTRY_POINT],
transform: [reactify],
debug: true,
cache: {}, packageCache: {}, fullPaths: true
}));
return watcher.on('update', function () {
watcher.bundle()
.pipe(source(path.OUT))
.pipe(gulp.dest(path.DEST_SRC))
console.log('Updated');
})
.bundle()
.pipe(source(path.OUT))
.pipe(gulp.dest(path.DEST_SRC));
});
I used this tutorial to set up my gulpfile.js and it provides a good explanation for every gulp task:
http://tylermcginnis.com/reactjs-tutorial-pt-2-building-react-applications-with-gulp-and-browserify/

Categories

Resources