gulp-jasmine Window is not defined error - angularjs

I am using gulp / gulp-jasmine / angular to run my unit tests. However, I encounter the following error when running my Gulp target:
C:\Projects\website2>gulp test
[01:53:10] Using gulpfile C:\Projects\website2\gulpfile.js
[01:53:10] Starting 'test'...
[01:53:11] Version: webpack 1.4.13
Asset Size Chunks Chunk Names
test.bundle.js 1051728 0 [emitted] test
F
Failures:
1) Exception loading: C:\Projects\website2\scripts\dist\test.bundle.js Error
1.1) ReferenceError: window is not defined
1 spec, 1 failure
Finished in 0.015 seconds
[01:53:11] 'test' errored after 916 ms
[01:53:11] Error in plugin 'gulp-jasmine'
Message:
Tests failed
I believe gulp-jasmine uses PhantomJS (no browser window is triggered). Can someone help me with what I'm doing wrong? Is there a configuration setting I'm missing?
Here is my gulpfile.js:
var gulp = require('gulp');
var path = require('path');
var webpack = require('gulp-webpack');
var webpackConfig = require('./webpack.config');
var testWebpackConfig = require('./test.webpack.config');
var jasmine = require('gulp-jasmine');
gulp.task('default', ['build'], function() {
});
gulp.task('build', function() {
return gulp.src(['scripts/app/**/*.js', '!scripts/app/**/*.tests.js'])
.pipe(webpack(webpackConfig))
.pipe(gulp.dest('scripts/dist'));
});
gulp.task('test', function() {
return gulp.src(['scripts/app/**/*.tests.js'])
.pipe(webpack(testWebpackConfig))
.pipe(gulp.dest('scripts/dist'))
.pipe(jasmine());
});

gulp-jasmine runs the tests through Node.js and thus is not suitable for client side testing, see https://github.com/sindresorhus/gulp-jasmine/issues/46
For client side tests, if you want to use Jasmine (instead of Karma or in parallel), you can write a SpecRunner.html file (the name does not matter) and run it in your browser:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Jasmine Spec Runner</title>
<!-- You need to specify package 'jasmine-core' in your Node.js package.json -->
<link rel="shortcut icon" href="node_modules/jasmine-core/images/jasmine_favicon.png">
<link rel="stylesheet" href="node_modules/jasmine-core/lib/jasmine-core/jasmine.css">
<script src="node_modules/jasmine-core/lib/jasmine-core/jasmine.js"></script>
<script src="node_modules/jasmine-core/lib/jasmine-core/jasmine-html.js"></script>
<script src="node_modules/jasmine-core/lib/jasmine-core/boot.js"></script>
<!-- Source and Spec dependencies -->
<script src="node_modules/underscore/underscore.js"></script>
<script src="node_modules/angular/angular.js"></script>
<script src="node_modules/angular-mocks/angular-mocks.js"></script>
<!-- Source files -->
<script src="app/MySourceCode1.js"></script>
<script src="app/MySourceCode2.js"></script>
<!-- Spec files -->
<script src="test/MySourceCode1.spec.js"></script>
<script src="test/MySourceCode2.spec.js"></script>
</head>
<body>
</body>
</html>
Or use gulp-jasmine-browser:
var gulp = require('gulp');
var $ = require('gulp-load-plugins')();
// You need to specify packages 'jasmine-core' and 'gulp-jasmine-browser'
// in your Node.js package.json
gulp.task('jasmine', function() {
return gulp.src([
'node_modules/underscore/underscore.js',
'node_modules/angular/angular.js',
'node_modules/angular-mocks/angular-mocks.js',
'app/MySourceCode1.js',
'app/MySourceCode2.js',
'test/MySourceCode1.spec.js',
'test/MySourceCode2.spec.js',
])
.pipe($.jasmineBrowser.specRunner())
.pipe($.jasmineBrowser.server());
});
Or use Karma :)

I was able to solve this another way using PhantomJS for the headless browser, karma for the command-line test runner, jasmine for the test framework, and gulp for the task runner.
karma.conf.js
module.exports = function(config) {
config.set({
basePath: './',
files: [
'node_modules/angular/angular.js',
'node_modules/angular-mocks/angular-mocks.js',
'index-controller.js',
'index-controller.tests.js'
],
exclude: [
],
autoWatch: true,
frameworks: ['jasmine'],
browsers: ['PhantomJS'],
plugins: [
'karma-jasmine',
'karma-junit-reporter',
'karma-chrome-launcher',
'karma-firefox-launcher',
'karma-phantomjs-launcher'
],
junitReporter: {
outputFile: 'unit.xml',
suite: 'unit'
}
})
}
Install the necessary npm modules:
npm install angular
npm install angular-mocks
npm install -g gulp
npm install gulp
npm install karma
npm install -g karma-cli
npm install karma-jasmine
npm install karma-junit-reporter
npm install karma-chrome-launcher
npm install karma-firefox-launcher
npm install karma-phantomjs-launcher
npm install phantomjs
Update your gulpfile.js and provide two tasks: the default task to run the unit tests once, a TDD task to watch the file system and run the tests when any file changes:
gulpfile.js
var gulp = require('gulp');
var karma = require('karma').server;
gulp.task('default', function(done) {
karma.start({
configFile: __dirname + '/karma.conf.js',
singleRun: true
}, done);
});
gulp.task('tdd', function (done) {
karma.start({
configFile: __dirname + '/karma.conf.js'
}, done);
});
To trigger:
gulp default
gulp tdd
For completeness, here is my index-controller, and associated test:
index-controller.js
var app = angular.module('app', []);
app.controller('ctrl', function($scope) {
$scope.name = 'mickey mouse';
});
index-controller.tests.js
describe('index-controller', function() {
beforeEach(module('app'));
var $controller;
beforeEach(inject(function(_$controller_){
// The injector unwraps the underscores (_) from around the
// parameter names when matching
$controller = _$controller_;
}));
describe('$scope.name', function() {
it('should be mickey mouse', function() {
var $scope = {};
var controller = $controller('ctrl', { $scope: $scope });
expect($scope.name).toEqual('mickey mouse');
});
});
});

Related

Gulp and React require is not defined and browserify not working

I have app structure:
-- dist
- index.html
-- js
- index.js
- package.json
- package-lock.json
- gulpfile.js
In index.html I have this:
<!DOCTYPE html>
<html>
<head>
<title>Title</title>
<link rel="stylesheet" type="text/css" href="/css/main.css">
</head>
<body>
<div id='root'></div>
<script type="text/javascript" src="/js/index.js"></script>
</body>
</html>
In index.js I have this simple React app:
import React from 'react';
import ReactDOM from 'react-dom';
ReactDOM.render((
<h1>Hello world</h1>),
document.getElementById('root')
);
And this script in Gulp with appropriate imports and packages:
gulp.task('js', () =>
gulp.src('js/*.js')
.pipe(babel({
presets: ['env', 'react', 'es2015']
}))
.pipe(gulp.dest('dist/js'))
);
gulp.task('webserver', function() {
gulp.src('dist')
.pipe(webserver({
livereload: true,
directoryListing: true,
open: 'http://localhost:8000/index.html'
}));
});
gulp.task('watch', function() {
gulp.watch('styles/**/*.less', ['less']);
gulp.watch('js/**/*.js', ['js']);
gulp.src('dist')
.pipe(webserver({
open: 'http://localhost:8000/index.html'
}));
});
// + less
gulp.task('default', [ 'less', 'watch', 'js']);
It correctly creates copy of js files and add them to the dist/js folder and the server start running. The first load throw error in console Failed to load resource: the server responded with a status of 404 (Not Found) index.js:1 but on second load it works fine but throw error Uncaught ReferenceError: require is not defined index:3.
I found on the internet similar cases and the advice was to use browserify or webpack. I tried this script to bundle everything instead of the above code:
gulp.task('js', function () {
var b = browserify({
entry: './js/*.js',
debug: true,
transform: [babelify.configure({
presets: ['env', 'react', 'es2015']
})]
});
return b.bundle()
.pipe(source('index.js'))
.pipe(buffer())
.pipe(sourcemaps.init({loadMaps: true}))
// Add transformation tasks to the pipeline here.
.pipe(uglify())
.on('error', log.error)
.pipe(sourcemaps.write('./'))
.pipe(gulp.dest('./dist/js/'));
});
The application loads but the React is not there. it creates accordingly index.js and index.map but the DOM is not updated from the React.
It's the first time using Gulp so I am not sure what I am doing wrong.

HTML href not finding resource in project

I've been trying to learn angularJS, specifically 1.5 using components. My IDE is c9 so the server uses port: process.env.PORT which when I start will show the project at https://projectName-username.c9users.io (with angular-ui-router it has '/#!' on the end). This ide doesn't seem to compile es6 without using something like gulp. So I copy pasted much of the gulp code from the tutorial into my own project so that I could continue using the es6 syntax to build my own project.Everything is working pretty well except I am trying to link bootstrap 4 and my own css files from inside the project rather than a cdn and I can't seem to get the file path correct. When running the gulp file it says serving files from ./build so I tried writing the path from there but it has 404 on the resource.The closest I've come to was no errors thrown trying <link rel="stylesheet" src="#!/src/bower_components/bootstrap/dist/css/bootstrap.min.css"> but checking the network it says it's loading https://billardsWebsite-rawlejuglal.c9users.io/ with type stylesheet but nothing is actually there. Below is my file structure, the index.html file and then the gulpfile. If anyone can enlighten me on how to structure my links to find these resources I would appreciate it.
billardsWebsite
-.c9
-.git
-build
-index.html
-main.js
-node_modules
-src
-bower_components
-boostrap
-dist
-css
-bootstrap.min.css
-js
-css
-styles.css
-index.html
-.bowerrc
-.bower.json
-gulpfile.js
-package.json
-Procfile
Index.html (src/index.html)
<!DOCTYPE html>
<html lang="en">
<head>
<!-- Required meta tags -->
<meta charset="utf-8">
<title ng-bind="pageTitle"></title>
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<link rel="stylesheet" href="#!/src/bower_components/bootstrap/dist/css/bootstrap.min.css">
</head>
<body>
<div ui-view></div>
<!-- jQuery first, then Tether, then Bootstrap JS. -->
<script src="https://code.jquery.com/jquery-3.1.1.slim.min.js" integrity="sha384-A7FZj7v+d/sdmMqp/nOQwliLvUsJfDHW+k9Omg/a/EheAdgtzNs3hpfag6Ed950n" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/tether/1.4.0/js/tether.min.js" integrity="sha384-DztdAPBWPRXSA/3eYEEUWrWCy7G5KFbe8fFjk5JAIxUYHKkDx6Qin1DkWx51bBrb" crossorigin="anonymous"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha.6/js/bootstrap.min.js" integrity="sha384-vBWWzlZJ8ea9aCX4pEW3rVHjgjt7zpkNpZk+02D9phzyeVkE+jo0ieGizqPLForn" crossorigin="anonymous"></script>
<script src="main.js"></script>
</body>
</html>
gulpfile.js
var gulp = require('gulp');
var notify = require('gulp-notify');
var source = require('vinyl-source-stream');
var browserify = require('browserify');
var babelify = require('babelify');
var ngAnnotate = require('browserify-ngannotate');
var browserSync = require('browser-sync').create();
var rename = require('gulp-rename');
var templateCache = require('gulp-angular-templatecache');
var uglify = require('gulp-uglify');
var merge = require('merge-stream');
// Where our files are located
var jsFiles = "src/js/**/*.js";
var viewFiles = "src/js/**/*.html";
var interceptErrors = function(error) {
var args = Array.prototype.slice.call(arguments);
// Send error to notification center with gulp-notify
notify.onError({
title: 'Compile Error',
message: '<%= error.message %>'
}).apply(this, args);
// Keep gulp from hanging on this task
this.emit('end');
};
gulp.task('browserify', ['views'], function() {
return browserify('./src/js/app.js')
.transform(babelify, {presets: ["es2015"]})
.transform(ngAnnotate)
.bundle()
.on('error', interceptErrors)
//Pass desired output filename to vinyl-source-stream
.pipe(source('main.js'))
// Start piping stream to tasks!
.pipe(gulp.dest('./build/'));
});
gulp.task('html', function() {
return gulp.src("src/index.html")
.on('error', interceptErrors)
.pipe(gulp.dest('./build/'));
});
gulp.task('views', function() {
return gulp.src(viewFiles)
.pipe(templateCache({
standalone: true
}))
.on('error', interceptErrors)
.pipe(rename("app.templates.js"))
.pipe(gulp.dest('./src/js/config/'));
});
// This task is used for building production ready
// minified JS/CSS files into the dist/ folder
gulp.task('build', ['html', 'browserify'], function() {
var html = gulp.src("build/index.html")
.pipe(gulp.dest('./dist/'));
var js = gulp.src("build/main.js")
.pipe(uglify())
.pipe(gulp.dest('./dist/'));
return merge(html,js);
});
gulp.task('default', ['html', 'browserify'], function() {
browserSync.init(['./build/**/**.**'], {
server: "./build",
port: process.env.PORT || '3000',
notify: false,
ui: {
port: 3001
}
});
gulp.watch("src/index.html", ['html']);
gulp.watch(viewFiles, ['views']);
gulp.watch(jsFiles, ['browserify']);
});

Reactjs file size: script-file vs npm-version

I am using reactjs and gulp for the build-process. Currently I use react from npm with browserify. When I want to minify my App in production-mode the react code ends up with about 180kb.
This is the gulp code I use:
gulp.task('production', function () {
var bundler = browserify('./public/dev/js/main.js').transform(babelify, { presets: ['react'] });
return bundler.bundle()
.on('error', map_error)
.pipe(source('bundle.js'))
.pipe(buffer())
.pipe(rename('bundle-build.min.js'))
.pipe(envify({'_': 'purge', NODE_ENV: 'production'}))
.pipe(uglify())
.pipe(gulp.dest('./public/dist/js/'));
});
However, if I download the minified script files from the react-website and load the script files like this:
<script type="text/javascript" src="./react.min.js"></script>
<script type="text/javascript" src="./react-dom.min.js"></script>
it ends up with about 150kb.
Why is the with gulp minified version bigger? How can I bring it to the same size? Also, is there a difference in the development / production of the app between loading the provided script files or using it from npm?
Thanks in advance
Cheers

Gulp - How to collect used files only and convert them as single files in `dest`

I am using the gulp for run my angular app. But I am facing a problem here.
all bower_components files are copied in dest ans bower_components folder
my js files ( say 2 ) I am getting 2 js files in dest folder
same things happening for html and css files too.
What i requires is :
dest file should have only one html and js and css all or minified with source map included.( if necessary )
Basically, the gulp need to collect the files, what just i have used in the app instead of collecting from the folder as .js.
How to do this?
here is my current gulp code :
// gulp
var gulp = require('gulp');
// plugins
var connect = require('gulp-connect');
var jshint = require('gulp-jshint');
var uglify = require('gulp-uglify');
var minifyCSS = require('gulp-minify-css');
var clean = require('gulp-clean');
var runSequence = require('run-sequence');
// tasks
gulp.task('lint', function() {
gulp.src(['./app/**/*.js', '!./app/bower_components/**'])
.pipe(jshint())
.pipe(jshint.reporter('default'))
.pipe(jshint.reporter('fail'));
});
gulp.task('clean', function() {
gulp.src('./dist/*')
.pipe(clean({force: true}));
});
gulp.task('minify-css', function() {
var opts = {comments:true,spare:true};
gulp.src(['./app/**/*.css', '!./app/bower_components/**'])
.pipe(minifyCSS(opts))
.pipe(gulp.dest('./dist/'))
});
gulp.task('minify-js', function() {
gulp.src(['./app/**/*.js', '!./app/bower_components/**'])
.pipe(uglify({
// inSourceMap:
// outSourceMap: "app.js.map"
}))
.pipe(gulp.dest('./dist/'))
});
gulp.task('copy-bower-components', function () {
gulp.src('./app/bower_components/**')
.pipe(gulp.dest('dist/bower_components'));
});
gulp.task('copy-html-files', function () {
gulp.src('./app/**/*.html')
.pipe(gulp.dest('dist/'));
});
gulp.task('connect', function () {
connect.server({
root: 'app/',
port: 8888
});
});
gulp.task('connectDist', function () {
connect.server({
root: 'dist/',
port: 9999
});
});
// default task
gulp.task('default',
['lint', 'connect']
);
gulp.task('build', function() {
runSequence(
['clean'],
['lint', 'minify-css', 'minify-js', 'copy-html-files', 'copy-bower-components', 'connectDist']
);
});
You should make use of the gulp-useref module, which parses the build blocks in the HTML, replace them and pass those files through.
Here the example setup:
index.html:
<!doctype html>
<html ng-app="app">
<head>
<!-- build:js app.js -->
<script src="bower_components/angular/angular.js"></script>
<script src="bower_components/angular-route/angular-route.js"></script>
<script src="myscript.js"></script>
<!-- endbuild -->
</head>
<body>
Hello world!
</body>
</html>
gulpfile.js:
var gulp = require('gulp');
var useref = require('gulp-useref');
gulp.task('default', function () {
return gulp.src('app/index.html')
.pipe(useref())
.pipe(gulp.dest('dist'));
});
Running the gulp now will result in having the two files in the dist folder:
index.html - having the build block replaced by the only script tag, <script src="app.js"></script>
app.js - the concatenation of the files listed in the build block of the original index.html file
The same can be done with the css files as well.
This way you will have no extra files in your dest folder, just what you have used in your app.
var concat = require("gulp-concat");
gulp.task('minify-js', function() {
gulp.src(['./app/**/*.js', '!./app/bower_components/**'])
.pipe(uglify({
output: {
beautify: false
},
outSourceMap: true,
properties : true,
mangle:false
}))
.pipe(concat('bundle.js'))
.pipe(gulp.dest('./dist/'))
});
this will concatenate all files in one bundle.js file.

How to test an Angular app?

For simple application such as just a "Hello World" where do I write tests.
I have created a plnkr.
http://plnkr.co/edit/M0GAIE837G3s1vNwTyK8?p=info
Now this is a very simple plnkr, which does nothing but display Hello World.
Now if I want to write a test for this Application i.e for MainCtrl.. where do I plug it in ?
To run test with Angular-Karma-Jasmine:
You need to install nodejs, karma runs on top of node
You need to install karma from Node Packaged Modules from your command window execute: npm install -g karma
If you plan to run this with Chrome and Firefox and you are running this on windows you need to add 2 environment variables:
CHROME_BIN = [Crome installation path/chrome.exe]
FIREFOX_BIN =[Firefox installation path/firefox.exe]
4. Go back to your project folder using the command window once there you can execute:karma init
Just hit enter until it finishes; bottom line this will create a file named: karma.config.js
In my project this file looks like this, yours probably will include some helpful comments on the different settings:
module.exports = function(config) {
config.set({
basePath: '',
frameworks: ['jasmine'],
files: [
'../app/*.js',
'../app/lib/angular.js',
'../app/lib/angular-route.min.js',
'../app/lib/angular-mocks.js',
'../app/app.js',
'controllers/*.js',
'services/*.js',
],
exclude: [
],
reporters: ['progress'],
port: 9876,
colors: true,
logLevel: config.LOG_INFO,
autoWatch: true,
browsers: ['Chrome','Firefox'],
captureTimeout: 60000,
singleRun: false
});
};
Important: make sure you included angular-mocks in your configuration, the inject function is on that module.
5. Go back to your command window, navigate where your karma.config.js file is and and execute: karma start
At this point you will be good to go to start writing tests with jasmine.
a simple jasmine test for your controller will be:
describe('MainCtrl', function() {
var $scope, $rootScope, createController;
beforeEach(inject(function($injector) {
$rootScope = $injector.get('$rootScope');
$scope = $rootScope.$new();
var $controller = $injector.get('$controller');
createController = function() {
return $controller('MainCtrl', {
'$scope': $scope
});
};
}));
it('should have a...', function() {
var controller = createController();
// do your testing here...
});
});

Resources