mirror of
https://github.com/moparisthebest/mail
synced 2024-12-21 06:48:50 -05:00
[WO-592] implement webmail using socket.io
* Relax CSP to allow iframe assets to load * Integrate socket.io proxy * go to /# when controllers not initiated * Add offline caching using AppCache manifest
This commit is contained in:
parent
e29f083c60
commit
487bb31d45
17
Gruntfile.js
17
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']);
|
||||
|
12
README.md
12
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.
|
||||
|
12
config/default.js
Normal file
12
config/default.js
Normal file
@ -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"'
|
||||
}
|
||||
};
|
10
config/integration.js
Normal file
10
config/integration.js
Normal file
@ -0,0 +1,10 @@
|
||||
'use strict';
|
||||
|
||||
module.exports = {
|
||||
server: {
|
||||
port: 8889
|
||||
},
|
||||
log: {
|
||||
level: "error"
|
||||
}
|
||||
};
|
28
package.json
28
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"
|
||||
}
|
||||
}
|
146
server.js
146
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');
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
<!DOCTYPE html>
|
||||
<html ng-app="mail" ng-csp>
|
||||
<html ng-app="mail" ng-csp manifest="appcache.manifest">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Whiteout Mail</title>
|
||||
@ -29,6 +29,7 @@
|
||||
<link rel="stylesheet" media="all" href="css/all.min.css" type="text/css">
|
||||
|
||||
<!-- The Scripts -->
|
||||
<script src="socket.io/socket.io.js"></script>
|
||||
<script src="lib/require.js"></script>
|
||||
<script src="require-config.js"></script>
|
||||
<script src="js/app.js"></script>
|
||||
|
@ -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()) {
|
||||
|
@ -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;
|
||||
|
@ -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.';
|
||||
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
||||
|
@ -9,22 +9,13 @@ 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;
|
||||
|
||||
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) {
|
||||
@ -38,10 +29,24 @@ define(function(require) {
|
||||
|
||||
ctrl = $controller(AddAccountCtrl, {
|
||||
$location: location,
|
||||
$scope: scope
|
||||
$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() {
|
||||
|
||||
it('should forward to login', function() {
|
||||
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();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -39,7 +39,8 @@ define(function(require) {
|
||||
scope = $rootScope.$new();
|
||||
scope.state = {};
|
||||
ctrl = $controller(LoginExistingCtrl, {
|
||||
$scope: scope
|
||||
$scope: scope,
|
||||
$routeParams: {}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -43,7 +43,8 @@ define(function(require) {
|
||||
ui: {}
|
||||
};
|
||||
ctrl = $controller(LoginInitialCtrl, {
|
||||
$scope: scope
|
||||
$scope: scope,
|
||||
$routeParams: {}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -41,7 +41,8 @@ define(function(require) {
|
||||
ui: {}
|
||||
};
|
||||
ctrl = $controller(LoginNewDeviceCtrl, {
|
||||
$scope: scope
|
||||
$scope: scope,
|
||||
$routeParams: {}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -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: {}
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -33,7 +33,8 @@ define(function(require) {
|
||||
|
||||
scope.state = {};
|
||||
setCredentialsCtrl = $controller(SetCredentialsCtrl, {
|
||||
$scope: scope
|
||||
$scope: scope,
|
||||
$routeParams: {}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
Loading…
Reference in New Issue
Block a user