diff --git a/Gruntfile.js b/Gruntfile.js
index 377eb50..40aa9d2 100644
--- a/Gruntfile.js
+++ b/Gruntfile.js
@@ -213,6 +213,20 @@ module.exports = function(grunt) {
}
},
+ manifest: {
+ generate: {
+ options: {
+ basePath: 'dist/',
+ timestamp: true,
+ hash: true,
+ cache: ['socket.io/socket.io.js'],
+ master: ['index.html']
+ },
+ src: ['**/*.*'],
+ dest: 'dist/appcache.manifest'
+ }
+ },
+
nodewebkit: {
options: {
version: '0.9.2', // node-webkit version
@@ -238,12 +252,13 @@ module.exports = function(grunt) {
grunt.loadNpmTasks('grunt-contrib-copy');
grunt.loadNpmTasks('grunt-contrib-compress');
grunt.loadNpmTasks('grunt-node-webkit-builder');
+ grunt.loadNpmTasks('grunt-manifest');
// Build tasks
grunt.registerTask('dist-npm', ['copy:npm', 'copy:npmDev', 'copy:cryptoLib']);
grunt.registerTask('dist-css', ['sass', 'autoprefixer', 'csso']);
grunt.registerTask('dist-copy', ['copy']);
- grunt.registerTask('dist', ['clean', 'dist-npm', 'dist-css', 'dist-copy']);
+ grunt.registerTask('dist', ['clean', 'dist-npm', 'dist-css', 'dist-copy', 'manifest']);
// Test/Dev tasks
grunt.registerTask('dev', ['connect:dev']);
diff --git a/README.md b/README.md
index ea96681..826f347 100644
--- a/README.md
+++ b/README.md
@@ -50,11 +50,21 @@ Then visit [http://localhost:8580/dist/#/desktop?dev=true](http://localhost:8580
grunt watch
-## Releasing
+## Releasing Chrome App
grunt release-test --release=0.0.0.x
grunt release-stable --release=0.x.0
+## Deploying Web App
+
+First build and generate the `dist/` directory:
+
+ grunt
+
+Then deploy that directoy by adding it to a local git branch. Push that branch to your node.js server and then start the server:
+
+ npm start
+
## License
Copyright © 2014, Whiteout Networks GmbH. All rights reserved.
diff --git a/config/default.js b/config/default.js
new file mode 100644
index 0000000..5a7447f
--- /dev/null
+++ b/config/default.js
@@ -0,0 +1,12 @@
+'use strict';
+
+module.exports = {
+ server: {
+ port: process.env.PORT || 8889,
+ host: "0.0.0.0"
+ },
+ log: {
+ level: "silly",
+ http: ':remote-addr [:date] ":method :url HTTP/:http-version" :status :res[content-length] ":referrer"'
+ }
+};
\ No newline at end of file
diff --git a/config/integration.js b/config/integration.js
new file mode 100644
index 0000000..2833006
--- /dev/null
+++ b/config/integration.js
@@ -0,0 +1,10 @@
+'use strict';
+
+module.exports = {
+ server: {
+ port: 8889
+ },
+ log: {
+ level: "error"
+ }
+};
\ No newline at end of file
diff --git a/package.json b/package.json
index 35c72ff..ca7da8f 100644
--- a/package.json
+++ b/package.json
@@ -23,7 +23,6 @@
"node": ">=0.10"
},
"scripts": {
- "postinstall": "grunt",
"test": "grunt && grunt test",
"start": "node server.js"
},
@@ -39,26 +38,31 @@
"ng-infinite-scroll": "~1.1.2",
"pgpbuilder": "~0.4.0",
"pgpmailer": "~0.4.0",
- "requirejs": "~2.1.14"
+ "requirejs": "~2.1.14",
+ "config": "^1.0.2",
+ "morgan": "^1.2.3",
+ "npmlog": "^0.1.1",
+ "socket.io": "^1.0.6"
},
"devDependencies": {
"angularjs": "https://github.com/whiteout-io/angular.js/tarball/npm-version",
"browsercrow": "https://github.com/whiteout-io/browsercrow/tarball/master",
"browsersmtp": "https://github.com/whiteout-io/browsersmtp/tarball/master",
- "grunt": "~0.4.1",
- "mocha": "~1.13.0",
"chai": "~1.7.2",
- "sinon": "~1.7.3",
+ "grunt": "~0.4.1",
+ "grunt-contrib-clean": "~0.5.0",
+ "grunt-contrib-copy": "~0.4.1",
+ "grunt-manifest": "^0.4.0",
+ "grunt-autoprefixer": "~0.7.2",
+ "grunt-contrib-compress": "~0.5.2",
"grunt-contrib-connect": "~0.5.0",
"grunt-contrib-jshint": "~0.6.4",
- "grunt-mocha": "~0.4.1",
- "grunt-contrib-clean": "~0.5.0",
- "grunt-csso": "~0.6.1",
"grunt-contrib-sass": "~0.7.3",
- "grunt-autoprefixer": "~0.7.2",
"grunt-contrib-watch": "~0.5.3",
- "grunt-contrib-copy": "~0.4.1",
- "grunt-contrib-compress": "~0.5.2",
- "grunt-node-webkit-builder": "~0.1.17"
+ "grunt-csso": "~0.6.1",
+ "grunt-mocha": "~0.4.1",
+ "grunt-node-webkit-builder": "~0.1.17",
+ "mocha": "~1.13.0",
+ "sinon": "~1.7.3"
}
}
\ No newline at end of file
diff --git a/server.js b/server.js
index e949b62..23c12c2 100644
--- a/server.js
+++ b/server.js
@@ -1,8 +1,70 @@
'use strict';
-var express = require('express'),
- compression = require('compression'),
- app = express();
+process.chdir(__dirname);
+
+var cluster = require('cluster');
+var config = require('config');
+var log = require('npmlog');
+
+log.level = config.log.level;
+
+// Handle error conditions
+process.on('SIGTERM', function() {
+ log.warn('exit', 'Exited on SIGTERM');
+ process.exit(0);
+});
+
+process.on('SIGINT', function() {
+ log.warn('exit', 'Exited on SIGINT');
+ process.exit(0);
+});
+
+process.on('uncaughtException', function(err) {
+ log.error('uncaughtException ', err);
+ process.exit(1);
+});
+
+if (cluster.isMaster) {
+ // MASTER process
+
+ cluster.on('fork', function(worker) {
+ log.info('cluster', 'Forked worker #%s [pid:%s]', worker.id, worker.process.pid);
+ });
+
+ cluster.on('exit', function(worker) {
+ log.warn('cluster', 'Worker #%s [pid:%s] died', worker.id, worker.process.pid);
+ setTimeout(function() {
+ cluster.fork();
+ }, 1000);
+ });
+
+ // Fork a single worker
+ cluster.fork();
+ return;
+}
+
+// WORKER process
+
+var express = require('express');
+var compression = require('compression');
+var app = express();
+var server = require('http').Server(app);
+var io = require('socket.io')(server);
+var net = require('net');
+
+// Setup logger. Stream all http logs to general logger
+app.use(require('morgan')(config.log.http, {
+ 'stream': {
+ 'write': function(line) {
+ if ((line = (line || '').trim())) {
+ log.http('express', line);
+ }
+ }
+ }
+}));
+
+// Do not advertise Express
+app.disable('x-powered-by');
//
// web server config
@@ -17,7 +79,8 @@ app.use(function(req, res, next) {
// HSTS
res.set('Strict-Transport-Security', 'max-age=16070400; includeSubDomains');
// CSP
- res.set('Content-Security-Policy', "default-src 'self'; object-src 'none'; connect-src *; style-src 'self' 'unsafe-inline'; img-src 'self' data:");
+ var iframe = development ? "http://" + req.hostname + ":" + port : "https://" + req.hostname; // allow iframe to load assets
+ res.set('Content-Security-Policy', "default-src 'self' " + iframe + "; object-src 'none'; connect-src *; style-src 'self' 'unsafe-inline' " + iframe + "; img-src 'self' data:");
return next();
});
@@ -38,11 +101,84 @@ app.use(express.static(__dirname + '/dist', {
maxAge: oneDay
}));
+//
+// Socket.io proxy
+//
+
+io.on('connection', function(socket) {
+
+ log.info('io', 'New connection [%s]', socket.conn.id);
+
+ var idCounter = 0;
+
+ socket.on('open', function(data, fn) {
+ var socketId = ++idCounter;
+ var tcp;
+
+ log.verbose('io', 'Open request to %s:%s [%s:%s]', data.host, data.port, socket.conn.id, socketId);
+
+ tcp = net.connect(data.port, data.host, function() {
+ log.verbose('io', 'Opened tcp connection to %s:%s [%s:%s]', data.host, data.port, socket.conn.id, socketId);
+
+ tcp.on('data', function(chunk) {
+ log.silly('io', 'Received %s bytes from %s:%s [%s:%s]', chunk.length, data.host, data.port, socket.conn.id, socketId);
+ socket.emit('data-' + socketId, chunk);
+ });
+
+ tcp.on('error', function(err) {
+ log.verbose('io', 'Error for %s:%s [%s:%s]: %s', data.host, data.port, socket.conn.id, socketId, err.message);
+ socket.emit('error-' + socketId, err.message);
+ });
+
+ tcp.on('end', function() {
+ socket.emit('end-' + socketId);
+ });
+
+ tcp.on('close', function() {
+ log.verbose('io', 'Closed tcp connection to %s:%s [%s:%s]', data.host, data.port, socket.conn.id, socketId);
+ socket.emit('close-' + socketId);
+
+ socket.removeAllListeners('data-' + socketId);
+ socket.removeAllListeners('end-' + socketId);
+ });
+
+ socket.on('data-' + socketId, function(chunk, fn) {
+ if (!chunk || !chunk.length) {
+ if (typeof fn === 'function') {
+ fn();
+ }
+ return;
+ }
+ log.silly('io', 'Sending %s bytes to %s:%s [%s:%s]', chunk.length, data.host, data.port, socket.conn.id, socketId);
+ tcp.write(chunk, function() {
+ if (typeof fn === 'function') {
+ fn();
+ }
+ });
+ });
+
+ socket.on('end-' + socketId, function() {
+ log.verbose('io', 'Received request to close connection to %s:%s [%s:%s]', data.host, data.port, socket.conn.id, socketId);
+ tcp.end();
+ });
+
+ if (typeof fn === 'function') {
+ fn(socketId);
+ }
+ });
+ });
+
+ socket.on('disconnect', function() {
+ log.info('io', 'Closed connection [%s]', socket.conn.id);
+ socket.removeAllListeners();
+ });
+});
+
//
// start server
//
-app.listen(port);
+server.listen(port);
if (development) {
console.log(' > starting in development mode');
}
diff --git a/src/index.html b/src/index.html
index c43d2fa..74de1ae 100644
--- a/src/index.html
+++ b/src/index.html
@@ -1,5 +1,5 @@
-
+
Whiteout Mail
@@ -29,6 +29,7 @@
+
diff --git a/src/js/controller/add-account.js b/src/js/controller/add-account.js
index 6732271..2530a41 100644
--- a/src/js/controller/add-account.js
+++ b/src/js/controller/add-account.js
@@ -3,7 +3,12 @@ define(function(require) {
var appCtrl = require('js/app-controller');
- var AddAccountCtrl = function($scope, $location) {
+ var AddAccountCtrl = function($scope, $location, $routeParams) {
+ if (!appCtrl._auth && !$routeParams.dev) {
+ $location.path('/'); // init app
+ return;
+ }
+
$scope.connectToGoogle = function() {
// test for oauth support
if (appCtrl._auth._oauth.isSupported()) {
diff --git a/src/js/controller/login-existing.js b/src/js/controller/login-existing.js
index 20858c6..35aa6bd 100644
--- a/src/js/controller/login-existing.js
+++ b/src/js/controller/login-existing.js
@@ -3,7 +3,12 @@ define(function(require) {
var appController = require('js/app-controller');
- var LoginExistingCtrl = function($scope, $location) {
+ var LoginExistingCtrl = function($scope, $location, $routeParams) {
+ if (!appController._emailDao && !$routeParams.dev) {
+ $location.path('/'); // init app
+ return;
+ }
+
var emailDao = appController._emailDao;
$scope.buttonEnabled = true;
diff --git a/src/js/controller/login-initial.js b/src/js/controller/login-initial.js
index f2e2246..8c04c7d 100644
--- a/src/js/controller/login-initial.js
+++ b/src/js/controller/login-initial.js
@@ -3,7 +3,12 @@ define(function(require) {
var appController = require('js/app-controller');
- var LoginInitialCtrl = function($scope, $location) {
+ var LoginInitialCtrl = function($scope, $location, $routeParams) {
+ if (!appController._emailDao && !$routeParams.dev) {
+ $location.path('/'); // init app
+ return;
+ }
+
var emailDao = appController._emailDao,
states, termsMsg = 'You must accept the Terms of Service to continue.';
diff --git a/src/js/controller/login-new-device.js b/src/js/controller/login-new-device.js
index 60d8897..b39091a 100644
--- a/src/js/controller/login-new-device.js
+++ b/src/js/controller/login-new-device.js
@@ -4,7 +4,12 @@ define(function(require) {
var angular = require('angular'),
appController = require('js/app-controller');
- var LoginExistingCtrl = function($scope, $location) {
+ var LoginExistingCtrl = function($scope, $location, $routeParams) {
+ if (!appController._emailDao && !$routeParams.dev) {
+ $location.path('/'); // init app
+ return;
+ }
+
var emailDao = appController._emailDao,
pgp = appController._pgp;
diff --git a/src/js/controller/login-privatekey-download.js b/src/js/controller/login-privatekey-download.js
index 481d093..18256b8 100644
--- a/src/js/controller/login-privatekey-download.js
+++ b/src/js/controller/login-privatekey-download.js
@@ -3,7 +3,12 @@ define(function(require) {
var appController = require('js/app-controller');
- var LoginPrivateKeyDownloadCtrl = function($scope, $location) {
+ var LoginPrivateKeyDownloadCtrl = function($scope, $location, $routeParams) {
+ if (!appController._emailDao && !$routeParams.dev) {
+ $location.path('/'); // init app
+ return;
+ }
+
var keychain = appController._keychain,
emailDao = appController._emailDao,
userId = emailDao._account.emailAddress;
diff --git a/src/js/controller/login-set-credentials.js b/src/js/controller/login-set-credentials.js
index 25fdb32..81efbde 100644
--- a/src/js/controller/login-set-credentials.js
+++ b/src/js/controller/login-set-credentials.js
@@ -10,7 +10,12 @@ define(function(require) {
ImapClient = require('imap-client'),
SmtpClient = require('smtpclient');
- var SetCredentialsCtrl = function($scope, $location) {
+ var SetCredentialsCtrl = function($scope, $location, $routeParams) {
+ if (!appCtrl._emailDao && !$routeParams.dev) {
+ $location.path('/'); // init app
+ return;
+ }
+
var auth = appCtrl._auth;
var provider;
diff --git a/src/js/controller/navigation.js b/src/js/controller/navigation.js
index 7d7ccb8..54aae00 100644
--- a/src/js/controller/navigation.js
+++ b/src/js/controller/navigation.js
@@ -13,7 +13,12 @@ define(function(require) {
// Controller
//
- var NavigationCtrl = function($scope, $routeParams) {
+ var NavigationCtrl = function($scope, $routeParams, $location) {
+ if (!appController._emailDao && !$routeParams.dev) {
+ $location.path('/'); // init app
+ return;
+ }
+
emailDao = appController._emailDao;
outboxBo = appController._outboxBo;
diff --git a/test/unit/add-account-ctrl-test.js b/test/unit/add-account-ctrl-test.js
index 8b6410b..00fe15f 100644
--- a/test/unit/add-account-ctrl-test.js
+++ b/test/unit/add-account-ctrl-test.js
@@ -9,39 +9,44 @@ define(function(require) {
appController = require('js/app-controller');
describe('Add Account Controller unit test', function() {
- var scope, location, ctrl, authStub;
+ var scope, location, ctrl, authStub, origAuth;
+
+ beforeEach(function() {
+ // remember original module to restore later, then replace it
+ origAuth = appController._auth;
+ appController._auth = authStub = sinon.createStubInstance(Auth);
+
+ angular.module('addaccounttest', []);
+ mocks.module('addaccounttest');
+ mocks.inject(function($controller, $rootScope, $location) {
+ location = $location;
+ scope = $rootScope.$new();
+ scope.state = {};
+
+ sinon.stub(location, 'path').returns(location);
+ sinon.stub(location, 'search').returns(location);
+ sinon.stub(scope, '$apply', function() {});
+
+ ctrl = $controller(AddAccountCtrl, {
+ $location: location,
+ $scope: scope,
+ $routeParams: {}
+ });
+ });
+ });
+
+ afterEach(function() {
+ // restore the app controller module
+ appController._auth = origAuth;
+
+ location.path.restore();
+ location.search.restore();
+ scope.$apply.restore();
+ });
describe('connectToGoogle', function() {
- var origAuth;
- beforeEach(function() {
- // remember original module to restore later, then replace it
- origAuth = appController._auth;
- appController._auth = authStub = sinon.createStubInstance(Auth);
- });
-
- afterEach(function() {
- // restore the app controller module
- appController._auth = origAuth;
- });
it('should forward to login', function() {
- angular.module('addaccounttest', []);
- mocks.module('addaccounttest');
- mocks.inject(function($controller, $rootScope, $location) {
- location = $location;
- scope = $rootScope.$new();
- scope.state = {};
-
- sinon.stub(location, 'path').returns(location);
- sinon.stub(location, 'search').returns(location);
- sinon.stub(scope, '$apply', function() {});
-
- ctrl = $controller(AddAccountCtrl, {
- $location: location,
- $scope: scope
- });
- });
-
authStub._oauth = {
isSupported: function() {
return true;
@@ -57,30 +62,9 @@ define(function(require) {
provider: 'gmail'
})).to.be.true;
expect(authStub.getOAuthToken.calledOnce).to.be.true;
-
- location.path.restore();
- location.search.restore();
- scope.$apply.restore();
});
it('should not use oauth for gmail', function() {
- angular.module('addaccounttest', []);
- mocks.module('addaccounttest');
- mocks.inject(function($controller, $rootScope, $location) {
- location = $location;
- scope = $rootScope.$new();
- scope.state = {};
-
- sinon.stub(location, 'path').returns(location);
- sinon.stub(location, 'search').returns(location);
- sinon.stub(scope, '$apply', function() {});
-
- ctrl = $controller(AddAccountCtrl, {
- $location: location,
- $scope: scope
- });
- });
-
authStub._oauth = {
isSupported: function() {
return false;
@@ -94,30 +78,9 @@ define(function(require) {
provider: 'gmail'
})).to.be.true;
expect(authStub.getOAuthToken.called).to.be.false;
-
- location.path.restore();
- location.search.restore();
- scope.$apply.restore();
});
it('should not forward to login when oauth fails', function(done) {
- angular.module('addaccounttest', []);
- mocks.module('addaccounttest');
- mocks.inject(function($controller, $rootScope, $location) {
- location = $location;
- scope = $rootScope.$new();
- scope.state = {};
-
- sinon.stub(location, 'path').returns(location);
- sinon.stub(location, 'search').returns(location);
- sinon.stub(scope, '$apply', function() {});
-
- ctrl = $controller(AddAccountCtrl, {
- $location: location,
- $scope: scope
- });
- });
-
authStub._oauth = {
isSupported: function() {
return true;
@@ -131,10 +94,6 @@ define(function(require) {
expect(location.path.called).to.be.false;
expect(location.search.called).to.be.false;
- location.path.restore();
- location.search.restore();
- scope.$apply.restore();
-
done();
};
@@ -144,193 +103,67 @@ define(function(require) {
describe('connectToYahoo', function() {
it('should forward to login', function() {
- angular.module('addaccounttest', []);
- mocks.module('addaccounttest');
- mocks.inject(function($controller, $rootScope, $location) {
- location = $location;
- scope = $rootScope.$new();
- scope.state = {};
-
- sinon.stub(location, 'path').returns(location);
- sinon.stub(location, 'search').returns(location);
- sinon.stub(scope, '$apply', function() {});
-
- ctrl = $controller(AddAccountCtrl, {
- $location: location,
- $scope: scope
- });
- });
-
scope.connectToYahoo();
expect(location.path.calledWith('/login-set-credentials')).to.be.true;
expect(location.search.calledWith({
provider: 'yahoo'
})).to.be.true;
-
- location.path.restore();
- location.search.restore();
- scope.$apply.restore();
});
});
describe('connectToTonline', function() {
it('should forward to login', function() {
- angular.module('addaccounttest', []);
- mocks.module('addaccounttest');
- mocks.inject(function($controller, $rootScope, $location) {
- location = $location;
- scope = $rootScope.$new();
- scope.state = {};
-
- sinon.stub(location, 'path').returns(location);
- sinon.stub(location, 'search').returns(location);
- sinon.stub(scope, '$apply', function() {});
-
- ctrl = $controller(AddAccountCtrl, {
- $location: location,
- $scope: scope
- });
- });
-
scope.connectToTonline();
expect(location.path.calledWith('/login-set-credentials')).to.be.true;
expect(location.search.calledWith({
provider: 'tonline'
})).to.be.true;
-
- location.path.restore();
- location.search.restore();
- scope.$apply.restore();
});
});
describe('connectToOutlook', function() {
it('should forward to login', function() {
- angular.module('addaccounttest', []);
- mocks.module('addaccounttest');
- mocks.inject(function($controller, $rootScope, $location) {
- location = $location;
- scope = $rootScope.$new();
- scope.state = {};
-
- sinon.stub(location, 'path').returns(location);
- sinon.stub(location, 'search').returns(location);
- sinon.stub(scope, '$apply', function() {});
-
- ctrl = $controller(AddAccountCtrl, {
- $location: location,
- $scope: scope
- });
- });
-
scope.connectToOutlook();
expect(location.path.calledWith('/login-set-credentials')).to.be.true;
expect(location.search.calledWith({
provider: 'outlook'
})).to.be.true;
-
- location.path.restore();
- location.search.restore();
- scope.$apply.restore();
});
});
describe('connectToGmx', function() {
it('should forward to login', function() {
- angular.module('addaccounttest', []);
- mocks.module('addaccounttest');
- mocks.inject(function($controller, $rootScope, $location) {
- location = $location;
- scope = $rootScope.$new();
- scope.state = {};
-
- sinon.stub(location, 'path').returns(location);
- sinon.stub(location, 'search').returns(location);
- sinon.stub(scope, '$apply', function() {});
-
- ctrl = $controller(AddAccountCtrl, {
- $location: location,
- $scope: scope
- });
- });
-
scope.connectToGmx();
expect(location.path.calledWith('/login-set-credentials')).to.be.true;
expect(location.search.calledWith({
provider: 'gmx'
})).to.be.true;
-
- location.path.restore();
- location.search.restore();
- scope.$apply.restore();
});
});
describe('connectToWebde', function() {
it('should forward to login', function() {
- angular.module('addaccounttest', []);
- mocks.module('addaccounttest');
- mocks.inject(function($controller, $rootScope, $location) {
- location = $location;
- scope = $rootScope.$new();
- scope.state = {};
-
- sinon.stub(location, 'path').returns(location);
- sinon.stub(location, 'search').returns(location);
- sinon.stub(scope, '$apply', function() {});
-
- ctrl = $controller(AddAccountCtrl, {
- $location: location,
- $scope: scope
- });
- });
-
scope.connectToWebde();
expect(location.path.calledWith('/login-set-credentials')).to.be.true;
expect(location.search.calledWith({
provider: 'webde'
})).to.be.true;
-
- location.path.restore();
- location.search.restore();
- scope.$apply.restore();
});
});
describe('connectOther', function() {
it('should forward to login', function() {
- angular.module('addaccounttest', []);
- mocks.module('addaccounttest');
- mocks.inject(function($controller, $rootScope, $location) {
- location = $location;
- scope = $rootScope.$new();
- scope.state = {};
-
- sinon.stub(location, 'path').returns(location);
- sinon.stub(location, 'search').returns(location);
- sinon.stub(scope, '$apply', function() {});
-
- ctrl = $controller(AddAccountCtrl, {
- $location: location,
- $scope: scope
- });
- });
-
scope.connectOther();
expect(location.path.calledWith('/login-set-credentials')).to.be.true;
expect(location.search.calledWith({
provider: 'custom'
})).to.be.true;
-
- location.path.restore();
- location.search.restore();
- scope.$apply.restore();
});
});
});
diff --git a/test/unit/login-existing-ctrl-test.js b/test/unit/login-existing-ctrl-test.js
index 15b223b..baa16e0 100644
--- a/test/unit/login-existing-ctrl-test.js
+++ b/test/unit/login-existing-ctrl-test.js
@@ -39,7 +39,8 @@ define(function(require) {
scope = $rootScope.$new();
scope.state = {};
ctrl = $controller(LoginExistingCtrl, {
- $scope: scope
+ $scope: scope,
+ $routeParams: {}
});
});
});
diff --git a/test/unit/login-initial-ctrl-test.js b/test/unit/login-initial-ctrl-test.js
index b6c6a87..533a1f4 100644
--- a/test/unit/login-initial-ctrl-test.js
+++ b/test/unit/login-initial-ctrl-test.js
@@ -43,7 +43,8 @@ define(function(require) {
ui: {}
};
ctrl = $controller(LoginInitialCtrl, {
- $scope: scope
+ $scope: scope,
+ $routeParams: {}
});
});
});
diff --git a/test/unit/login-new-device-ctrl-test.js b/test/unit/login-new-device-ctrl-test.js
index 3d9b48e..977bedd 100644
--- a/test/unit/login-new-device-ctrl-test.js
+++ b/test/unit/login-new-device-ctrl-test.js
@@ -41,7 +41,8 @@ define(function(require) {
ui: {}
};
ctrl = $controller(LoginNewDeviceCtrl, {
- $scope: scope
+ $scope: scope,
+ $routeParams: {}
});
});
});
diff --git a/test/unit/login-privatekey-download-ctrl-test.js b/test/unit/login-privatekey-download-ctrl-test.js
index 78a8463..532dbf1 100644
--- a/test/unit/login-privatekey-download-ctrl-test.js
+++ b/test/unit/login-privatekey-download-ctrl-test.js
@@ -38,7 +38,8 @@ define(function(require) {
scope.state = {};
ctrl = $controller(LoginPrivateKeyDownloadCtrl, {
$location: location,
- $scope: scope
+ $scope: scope,
+ $routeParams: {}
});
done();
});
@@ -251,7 +252,8 @@ define(function(require) {
scope.state = {};
ctrl = $controller(LoginPrivateKeyDownloadCtrl, {
$location: location,
- $scope: scope
+ $scope: scope,
+ $routeParams: {}
});
});
diff --git a/test/unit/login-set-credentials-ctrl-test.js b/test/unit/login-set-credentials-ctrl-test.js
index 3dd48a3..e39d248 100644
--- a/test/unit/login-set-credentials-ctrl-test.js
+++ b/test/unit/login-set-credentials-ctrl-test.js
@@ -33,7 +33,8 @@ define(function(require) {
scope.state = {};
setCredentialsCtrl = $controller(SetCredentialsCtrl, {
- $scope: scope
+ $scope: scope,
+ $routeParams: {}
});
});
});