mirror of
https://github.com/moparisthebest/mail
synced 2024-11-22 08:52:15 -05:00
[WO-36] add minimally invasive controller unit tests
This commit is contained in:
parent
6ea15083d5
commit
8fb822bdea
@ -148,7 +148,7 @@ module.exports = function(grunt) {
|
||||
expand: true,
|
||||
flatten: true,
|
||||
cwd: 'node_modules/',
|
||||
src: ['requirejs/require.js', 'mocha/mocha.css', 'mocha/mocha.js', 'chai/chai.js', 'sinon/pkg/sinon.js'],
|
||||
src: ['requirejs/require.js', 'mocha/mocha.css', 'mocha/mocha.js', 'chai/chai.js', 'sinon/pkg/sinon.js', 'angularjs/src/ngMock/angular-mocks.js'],
|
||||
dest: 'test/lib/'
|
||||
},
|
||||
cryptoLib: {
|
||||
|
@ -16,6 +16,7 @@
|
||||
"requirejs": "2.1.8"
|
||||
},
|
||||
"devDependencies": {
|
||||
"angular": "https://github.com/angular/angular.js/tarball/v1.2.0",
|
||||
"grunt": "0.4.1",
|
||||
"mocha": "1.13.0",
|
||||
"phantomjs": "1.9.1-9",
|
||||
|
@ -37,7 +37,7 @@ define(function(require) {
|
||||
$scope.exportKeyFile = function() {
|
||||
emailDao._crypto.exportKeys(function(err, keys) {
|
||||
if (err) {
|
||||
console.error(err);
|
||||
$scope.onError(err);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -46,16 +46,14 @@ define(function(require) {
|
||||
content: keys.publicKeyArmored + keys.privateKeyArmored,
|
||||
filename: id + '.asc',
|
||||
contentType: 'text/plain'
|
||||
}, onSave);
|
||||
}, function onSave(err) {
|
||||
if (err) {
|
||||
$scope.onError(err);
|
||||
return;
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
function onSave(err) {
|
||||
if (err) {
|
||||
console.error(err);
|
||||
return;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
return AccountCtrl;
|
||||
|
@ -31,16 +31,16 @@ define(function(require) {
|
||||
return;
|
||||
}
|
||||
|
||||
setState(states.PROCESSING);
|
||||
$scope.setState(states.PROCESSING);
|
||||
setTimeout(function() {
|
||||
emailDao.unlock({}, passphrase, function(err) {
|
||||
if (err) {
|
||||
console.error(err);
|
||||
setState(states.IDLE, true);
|
||||
$scope.setState(states.IDLE, true);
|
||||
return;
|
||||
}
|
||||
|
||||
setState(states.DONE, true);
|
||||
$scope.setState(states.DONE, true);
|
||||
});
|
||||
}, 500);
|
||||
};
|
||||
@ -75,13 +75,13 @@ define(function(require) {
|
||||
$location.path('/desktop');
|
||||
};
|
||||
|
||||
function setState(state, async) {
|
||||
$scope.setState = function(state, async) {
|
||||
$scope.state.ui = state;
|
||||
|
||||
if (async) {
|
||||
$scope.$apply();
|
||||
}
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
return LoginInitialCtrl;
|
||||
|
@ -27,12 +27,6 @@
|
||||
angular: {
|
||||
exports: 'angular'
|
||||
},
|
||||
openpgp: {
|
||||
exports: 'window'
|
||||
},
|
||||
iscroll: {
|
||||
exports: 'IScroll'
|
||||
},
|
||||
angularRoute: {
|
||||
exports: 'angular',
|
||||
deps: ['angular']
|
||||
@ -41,6 +35,12 @@
|
||||
exports: 'angular',
|
||||
deps: ['angular']
|
||||
},
|
||||
openpgp: {
|
||||
exports: 'window'
|
||||
},
|
||||
iscroll: {
|
||||
exports: 'IScroll'
|
||||
},
|
||||
lawnchair: {
|
||||
exports: 'Lawnchair'
|
||||
},
|
||||
|
@ -29,7 +29,7 @@
|
||||
<h1>Keypair generated</h1>
|
||||
<p>Your personal keypair has been generated. You can export it (e.g. to a USB flash drive) to setup whiteout on another computer or as a backup.</p>
|
||||
<button ng-click="exportKeypair()" class="btn" tabindex="4">Export now</button>
|
||||
<button ng-click="proceed()" class="btn" tabindex="5">Do it later</button>
|
||||
<button ng-click="forward()" class="btn" tabindex="5">Do it later</button>
|
||||
</div>
|
||||
|
||||
</div><!--/content-->
|
||||
|
115
test/new-unit/account-ctrl-test.js
Normal file
115
test/new-unit/account-ctrl-test.js
Normal file
@ -0,0 +1,115 @@
|
||||
define(function(require) {
|
||||
'use strict';
|
||||
|
||||
var expect = chai.expect,
|
||||
angular = require('angular'),
|
||||
mocks = require('angularMocks'),
|
||||
AccountCtrl = require('js/controller/account'),
|
||||
EmailDAO = require('js/dao/email-dao'),
|
||||
PGP = require('js/crypto/pgp'),
|
||||
dl = require('js/util/download'),
|
||||
appController = require('js/app-controller');
|
||||
|
||||
describe('Account Controller unit test', function() {
|
||||
var scope, accountCtrl, origEmailDao, emailDaoMock,
|
||||
dummyFingerprint, expectedFingerprint,
|
||||
dummyKeyId, expectedKeyId,
|
||||
emailAddress,
|
||||
keySize,
|
||||
cryptoMock;
|
||||
|
||||
beforeEach(function() {
|
||||
origEmailDao = appController._emailDao;
|
||||
cryptoMock = sinon.createStubInstance(PGP);
|
||||
emailDaoMock = sinon.createStubInstance(EmailDAO);
|
||||
emailDaoMock._crypto = cryptoMock;
|
||||
appController._emailDao = emailDaoMock;
|
||||
|
||||
dummyFingerprint = '3A2D39B4E1404190B8B949DE7D7E99036E712926';
|
||||
expectedFingerprint = '3A2D 39B4 E140 4190 B8B9 49DE 7D7E 9903 6E71 2926';
|
||||
dummyKeyId = '9FEB47936E712926';
|
||||
expectedKeyId = '6E712926';
|
||||
cryptoMock.getFingerprint.returns(dummyFingerprint);
|
||||
cryptoMock.getKeyId.returns(dummyKeyId);
|
||||
emailAddress = 'fred@foo.com';
|
||||
keySize = 1234;
|
||||
emailDaoMock._account = {
|
||||
emailAddress: emailAddress,
|
||||
asymKeySize: keySize
|
||||
};
|
||||
|
||||
angular.module('accounttest', []);
|
||||
mocks.module('accounttest');
|
||||
mocks.inject(function($rootScope, $controller) {
|
||||
scope = $rootScope.$new();
|
||||
scope.state = {};
|
||||
accountCtrl = $controller(AccountCtrl, {
|
||||
$scope: scope
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
afterEach(function() {
|
||||
// restore the module
|
||||
appController._emailDao = origEmailDao;
|
||||
});
|
||||
|
||||
describe('scope variables', function() {
|
||||
it('should be set correctly', function() {
|
||||
expect(scope.eMail).to.equal(emailAddress);
|
||||
expect(scope.keyId).to.equal(expectedKeyId);
|
||||
expect(scope.fingerprint).to.equal(expectedFingerprint);
|
||||
expect(scope.keysize).to.equal(keySize);
|
||||
});
|
||||
});
|
||||
describe('export to key file', function() {
|
||||
it('should work', function() {
|
||||
var createDownloadMock = sinon.stub(dl, 'createDownload');
|
||||
cryptoMock.exportKeys.yields(null, {
|
||||
publicKeyArmored: 'a',
|
||||
privateKeyArmored: 'b',
|
||||
keyId: dummyKeyId
|
||||
});
|
||||
createDownloadMock.withArgs(sinon.match(function(arg) {
|
||||
return arg.content === 'ab' && arg.filename === expectedKeyId + '.asc' && arg.contentType === 'text/plain';
|
||||
})).yields();
|
||||
|
||||
scope.exportKeyFile();
|
||||
|
||||
expect(cryptoMock.exportKeys.calledOnce).to.be.true;
|
||||
expect(dl.createDownload.calledOnce).to.be.true;
|
||||
dl.createDownload.restore();
|
||||
});
|
||||
|
||||
it('should not work when key export failed', function(done) {
|
||||
cryptoMock.exportKeys.yields(new Error('asdasd'));
|
||||
scope.onError = function() {
|
||||
expect(cryptoMock.exportKeys.calledOnce).to.be.true;
|
||||
done();
|
||||
};
|
||||
|
||||
scope.exportKeyFile();
|
||||
});
|
||||
|
||||
it('should not work when create download failed', function(done) {
|
||||
var createDownloadMock = sinon.stub(dl, 'createDownload');
|
||||
cryptoMock.exportKeys.yields(null, {
|
||||
publicKeyArmored: 'a',
|
||||
privateKeyArmored: 'b',
|
||||
keyId: dummyKeyId
|
||||
});
|
||||
createDownloadMock.withArgs(sinon.match(function(arg) {
|
||||
return arg.content === 'ab' && arg.filename === expectedKeyId + '.asc' && arg.contentType === 'text/plain';
|
||||
})).yields(new Error('asdasd'));
|
||||
scope.onError = function() {
|
||||
expect(cryptoMock.exportKeys.calledOnce).to.be.true;
|
||||
expect(dl.createDownload.calledOnce).to.be.true;
|
||||
dl.createDownload.restore();
|
||||
done();
|
||||
};
|
||||
|
||||
scope.exportKeyFile();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
50
test/new-unit/dialog-ctrl-test.js
Normal file
50
test/new-unit/dialog-ctrl-test.js
Normal file
@ -0,0 +1,50 @@
|
||||
define(function(require) {
|
||||
'use strict';
|
||||
|
||||
var expect = chai.expect,
|
||||
angular = require('angular'),
|
||||
mocks = require('angularMocks'),
|
||||
DialogCtrl = require('js/controller/dialog');
|
||||
|
||||
describe('Dialog Controller unit test', function() {
|
||||
var scope, dialogCtrl;
|
||||
|
||||
beforeEach(function() {
|
||||
angular.module('dialogtest', []);
|
||||
mocks.module('dialogtest');
|
||||
mocks.inject(function($rootScope, $controller) {
|
||||
scope = $rootScope.$new();
|
||||
scope.state = {
|
||||
dialog: {}
|
||||
};
|
||||
dialogCtrl = $controller(DialogCtrl, {
|
||||
$scope: scope
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
afterEach(function() {});
|
||||
|
||||
describe('confirm', function() {
|
||||
it('should work', function(done) {
|
||||
scope.state.dialog.callback = function(confirmed) {
|
||||
expect(confirmed).to.be.true;
|
||||
expect(scope.state.dialog.open).to.be.false;
|
||||
done();
|
||||
};
|
||||
scope.confirm(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('cancel', function() {
|
||||
it('should work', function(done) {
|
||||
scope.state.dialog.callback = function(confirmed) {
|
||||
expect(confirmed).to.be.false;
|
||||
expect(scope.state.dialog.open).to.be.false;
|
||||
done();
|
||||
};
|
||||
scope.confirm(false);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
192
test/new-unit/login-ctrl-test.js
Normal file
192
test/new-unit/login-ctrl-test.js
Normal file
@ -0,0 +1,192 @@
|
||||
define(function(require) {
|
||||
'use strict';
|
||||
|
||||
var expect = chai.expect,
|
||||
angular = require('angular'),
|
||||
mocks = require('angularMocks'),
|
||||
LoginCtrl = require('js/controller/login'),
|
||||
EmailDAO = require('js/dao/email-dao'),
|
||||
appController = require('js/app-controller');
|
||||
|
||||
describe('Login Controller unit test', function() {
|
||||
var scope, location, ctrl, origEmailDao, emailDaoMock,
|
||||
emailAddress = 'fred@foo.com',
|
||||
oauthToken = 'foobarfoobar',
|
||||
startAppStub,
|
||||
checkForUpdateStub,
|
||||
fetchOAuthStub,
|
||||
initStub;
|
||||
|
||||
describe('initialization', function() {
|
||||
var hasChrome, hasIdentity;
|
||||
|
||||
beforeEach(function() {
|
||||
hasChrome = !!window.chrome;
|
||||
hasIdentity = !!window.chrome.identity;
|
||||
window.chrome = window.chrome || {};
|
||||
window.chrome.identity = window.chrome.identity || {};
|
||||
|
||||
// remember original module to restore later, then replace it
|
||||
origEmailDao = appController._emailDao;
|
||||
emailDaoMock = sinon.createStubInstance(EmailDAO);
|
||||
appController._emailDao = emailDaoMock;
|
||||
});
|
||||
|
||||
afterEach(function() {
|
||||
// restore the browser
|
||||
if (!hasIdentity) {
|
||||
delete window.chrome.identity;
|
||||
}
|
||||
|
||||
if (!hasChrome) {
|
||||
delete window.chrome;
|
||||
}
|
||||
|
||||
// restore the app controller module
|
||||
appController._emailDao = origEmailDao;
|
||||
appController.start.restore && appController.start.restore();
|
||||
appController.checkForUpdate.restore && appController.checkForUpdate.restore();
|
||||
appController.fetchOAuthToken.restore && appController.fetchOAuthToken.restore();
|
||||
appController.init.restore && appController.init.restore();
|
||||
location.path.restore && location.path.restore();
|
||||
});
|
||||
|
||||
it('should forward to existing user login', function(done) {
|
||||
startAppStub = sinon.stub(appController, 'start');
|
||||
startAppStub.yields();
|
||||
checkForUpdateStub = sinon.stub(appController, 'checkForUpdate');
|
||||
fetchOAuthStub = sinon.stub(appController, 'fetchOAuthToken');
|
||||
fetchOAuthStub.yields(null, {
|
||||
emailAddress: emailAddress,
|
||||
token: oauthToken
|
||||
});
|
||||
initStub = sinon.stub(appController, 'init');
|
||||
initStub.yields(null, {
|
||||
privateKey: 'a',
|
||||
publicKey: 'b'
|
||||
});
|
||||
|
||||
emailDaoMock.imapLogin.yields();
|
||||
|
||||
angular.module('logintest', []);
|
||||
mocks.module('logintest');
|
||||
mocks.inject(function($controller, $rootScope, $location) {
|
||||
location = $location;
|
||||
sinon.stub(location, 'path', function(path) {
|
||||
expect(path).to.equal('/login-existing');
|
||||
expect(emailDaoMock.imapLogin.calledOnce).to.be.true;
|
||||
expect(startAppStub.calledOnce).to.be.true;
|
||||
expect(checkForUpdateStub.calledOnce).to.be.true;
|
||||
expect(fetchOAuthStub.calledOnce).to.be.true;
|
||||
done();
|
||||
});
|
||||
scope = $rootScope.$new();
|
||||
scope.state = {};
|
||||
ctrl = $controller(LoginCtrl, {
|
||||
$location: location,
|
||||
$scope: scope
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('should forward to new device login', function(done) {
|
||||
startAppStub = sinon.stub(appController, 'start');
|
||||
startAppStub.yields();
|
||||
checkForUpdateStub = sinon.stub(appController, 'checkForUpdate');
|
||||
fetchOAuthStub = sinon.stub(appController, 'fetchOAuthToken');
|
||||
fetchOAuthStub.yields(null, {
|
||||
emailAddress: emailAddress,
|
||||
token: oauthToken
|
||||
});
|
||||
initStub = sinon.stub(appController, 'init');
|
||||
initStub.yields(null, {
|
||||
publicKey: 'b'
|
||||
});
|
||||
|
||||
emailDaoMock.imapLogin.yields();
|
||||
|
||||
angular.module('logintest', []);
|
||||
mocks.module('logintest');
|
||||
mocks.inject(function($controller, $rootScope, $location) {
|
||||
location = $location;
|
||||
sinon.stub(location, 'path', function(path) {
|
||||
expect(path).to.equal('/login-new-device');
|
||||
expect(emailDaoMock.imapLogin.calledOnce).to.be.true;
|
||||
expect(startAppStub.calledOnce).to.be.true;
|
||||
expect(checkForUpdateStub.calledOnce).to.be.true;
|
||||
expect(fetchOAuthStub.calledOnce).to.be.true;
|
||||
done();
|
||||
});
|
||||
scope = $rootScope.$new();
|
||||
scope.state = {};
|
||||
ctrl = $controller(LoginCtrl, {
|
||||
$location: location,
|
||||
$scope: scope
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('should forward to initial login', function(done) {
|
||||
startAppStub = sinon.stub(appController, 'start');
|
||||
startAppStub.yields();
|
||||
checkForUpdateStub = sinon.stub(appController, 'checkForUpdate');
|
||||
fetchOAuthStub = sinon.stub(appController, 'fetchOAuthToken');
|
||||
fetchOAuthStub.yields(null, {
|
||||
emailAddress: emailAddress,
|
||||
token: oauthToken
|
||||
});
|
||||
initStub = sinon.stub(appController, 'init');
|
||||
initStub.yields();
|
||||
|
||||
emailDaoMock.imapLogin.yields();
|
||||
|
||||
angular.module('logintest', []);
|
||||
mocks.module('logintest');
|
||||
mocks.inject(function($controller, $rootScope, $location) {
|
||||
location = $location;
|
||||
sinon.stub(location, 'path', function(path) {
|
||||
expect(path).to.equal('/login-initial');
|
||||
expect(emailDaoMock.imapLogin.calledOnce).to.be.true;
|
||||
expect(startAppStub.calledOnce).to.be.true;
|
||||
expect(checkForUpdateStub.calledOnce).to.be.true;
|
||||
expect(fetchOAuthStub.calledOnce).to.be.true;
|
||||
done();
|
||||
});
|
||||
scope = $rootScope.$new();
|
||||
scope.state = {};
|
||||
ctrl = $controller(LoginCtrl, {
|
||||
$location: location,
|
||||
$scope: scope
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('should fall back to dev mode', function(done) {
|
||||
var chromeIdentity;
|
||||
|
||||
chromeIdentity = window.chrome.identity;
|
||||
delete window.chrome.identity;
|
||||
|
||||
startAppStub = sinon.stub(appController, 'start');
|
||||
startAppStub.yields();
|
||||
|
||||
angular.module('logintest', []);
|
||||
mocks.module('logintest');
|
||||
mocks.inject(function($controller, $rootScope, $location) {
|
||||
location = $location;
|
||||
sinon.stub(location, 'path', function(path) {
|
||||
expect(path).to.equal('/desktop');
|
||||
window.chrome.identity = chromeIdentity;
|
||||
done();
|
||||
});
|
||||
scope = $rootScope.$new();
|
||||
scope.state = {};
|
||||
ctrl = $controller(LoginCtrl, {
|
||||
$location: location,
|
||||
$scope: scope
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
105
test/new-unit/login-existing-ctrl-test.js
Normal file
105
test/new-unit/login-existing-ctrl-test.js
Normal file
@ -0,0 +1,105 @@
|
||||
define(function(require) {
|
||||
'use strict';
|
||||
|
||||
var expect = chai.expect,
|
||||
angular = require('angular'),
|
||||
mocks = require('angularMocks'),
|
||||
LoginExistingCtrl = require('js/controller/login-existing'),
|
||||
EmailDAO = require('js/dao/email-dao'),
|
||||
KeychainDAO = require('js/dao/keychain-dao'),
|
||||
appController = require('js/app-controller');
|
||||
|
||||
describe('Login (existing user) Controller unit test', function() {
|
||||
var scope, location, ctrl, origEmailDao, emailDaoMock,
|
||||
emailAddress = 'fred@foo.com',
|
||||
passphrase = 'asd',
|
||||
keychainMock;
|
||||
|
||||
beforeEach(function() {
|
||||
// remember original module to restore later
|
||||
origEmailDao = appController._emailDao;
|
||||
|
||||
emailDaoMock = sinon.createStubInstance(EmailDAO);
|
||||
appController._emailDao = emailDaoMock;
|
||||
|
||||
keychainMock = sinon.createStubInstance(KeychainDAO);
|
||||
emailDaoMock._keychain = keychainMock;
|
||||
|
||||
emailDaoMock._account = {
|
||||
emailAddress: emailAddress,
|
||||
};
|
||||
|
||||
angular.module('loginexistingtest', []);
|
||||
mocks.module('loginexistingtest');
|
||||
mocks.inject(function($rootScope, $controller, $location) {
|
||||
location = $location;
|
||||
scope = $rootScope.$new();
|
||||
scope.state = {};
|
||||
ctrl = $controller(LoginExistingCtrl, {
|
||||
$scope: scope
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
afterEach(function() {
|
||||
// restore the module
|
||||
appController._emailDao = origEmailDao;
|
||||
});
|
||||
|
||||
describe('initial state', function() {
|
||||
it('should be well defined', function() {
|
||||
expect(scope.buttonEnabled).to.be.true;
|
||||
expect(scope.incorrect).to.be.false;
|
||||
expect(scope.change).to.exist;
|
||||
expect(scope.confirmPassphrase).to.exist;
|
||||
});
|
||||
});
|
||||
|
||||
describe('functionality', function() {
|
||||
describe('change', function() {
|
||||
it('should set incorrect to false', function() {
|
||||
scope.incorrect = true;
|
||||
|
||||
scope.change();
|
||||
expect(scope.incorrect).to.be.false;
|
||||
});
|
||||
});
|
||||
|
||||
describe('confirm passphrase', function() {
|
||||
it('should unlock crypto and start', function() {
|
||||
var keypair = {},
|
||||
pathSpy = sinon.spy(location, 'path');
|
||||
scope.passphrase = passphrase;
|
||||
keychainMock.getUserKeyPair.withArgs(emailAddress).yields(null, keypair);
|
||||
emailDaoMock.unlock.withArgs(keypair, passphrase).yields(null);
|
||||
|
||||
|
||||
scope.confirmPassphrase();
|
||||
|
||||
expect(keychainMock.getUserKeyPair.calledOnce).to.be.true;
|
||||
expect(emailDaoMock.unlock.calledOnce).to.be.true;
|
||||
expect(pathSpy.calledOnce).to.be.true;
|
||||
expect(pathSpy.calledWith('/desktop')).to.be.true;
|
||||
});
|
||||
|
||||
it('should not do anything without passphrase', function() {
|
||||
var pathSpy = sinon.spy(location, 'path');
|
||||
scope.passphrase = '';
|
||||
|
||||
scope.confirmPassphrase();
|
||||
expect(pathSpy.callCount).to.equal(0);
|
||||
});
|
||||
|
||||
it('should not work when keypair unavailable', function(done) {
|
||||
scope.passphrase = passphrase;
|
||||
keychainMock.getUserKeyPair.withArgs(emailAddress).yields(new Error('asd'));
|
||||
|
||||
scope.confirmPassphrase();
|
||||
|
||||
expect(keychainMock.getUserKeyPair.calledOnce).to.be.true;
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
171
test/new-unit/login-initial-ctrl-test.js
Normal file
171
test/new-unit/login-initial-ctrl-test.js
Normal file
@ -0,0 +1,171 @@
|
||||
define(function(require) {
|
||||
'use strict';
|
||||
|
||||
var expect = chai.expect,
|
||||
angular = require('angular'),
|
||||
mocks = require('angularMocks'),
|
||||
LoginInitialCtrl = require('js/controller/login-initial'),
|
||||
dl = require('js/util/download'),
|
||||
PGP = require('js/crypto/pgp'),
|
||||
EmailDAO = require('js/dao/email-dao'),
|
||||
appController = require('js/app-controller');
|
||||
|
||||
describe('Login (initial user) Controller unit test', function() {
|
||||
var scope, ctrl, location, origEmailDao, emailDaoMock,
|
||||
emailAddress = 'fred@foo.com',
|
||||
passphrase = 'asd',
|
||||
keyId, expectedKeyId,
|
||||
cryptoMock;
|
||||
|
||||
beforeEach(function() {
|
||||
// remember original module to restore later
|
||||
origEmailDao = appController._emailDao;
|
||||
|
||||
emailDaoMock = sinon.createStubInstance(EmailDAO);
|
||||
appController._emailDao = emailDaoMock;
|
||||
|
||||
keyId = '9FEB47936E712926';
|
||||
expectedKeyId = '6E712926';
|
||||
cryptoMock = sinon.createStubInstance(PGP);
|
||||
emailDaoMock._crypto = cryptoMock;
|
||||
|
||||
emailDaoMock._account = {
|
||||
emailAddress: emailAddress,
|
||||
};
|
||||
|
||||
angular.module('logininitialtest', []);
|
||||
mocks.module('logininitialtest');
|
||||
mocks.inject(function($rootScope, $controller, $location) {
|
||||
scope = $rootScope.$new();
|
||||
location = $location;
|
||||
scope.state = {
|
||||
ui: {}
|
||||
};
|
||||
ctrl = $controller(LoginInitialCtrl, {
|
||||
$scope: scope
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
afterEach(function() {
|
||||
// restore the module
|
||||
appController._emailDao = origEmailDao;
|
||||
});
|
||||
|
||||
describe('initial state', function() {
|
||||
it('should be well defined', function() {
|
||||
expect(scope.proceed).to.exist;
|
||||
expect(scope.exportKeypair).to.exist;
|
||||
expect(scope.confirmPassphrase).to.exist;
|
||||
expect(scope.state.ui).to.equal(1);
|
||||
});
|
||||
});
|
||||
|
||||
describe('confirm passphrase', function() {
|
||||
var setStateStub;
|
||||
|
||||
it('should unlock crypto', function(done) {
|
||||
scope.state.passphrase = passphrase;
|
||||
scope.state.confirmation = passphrase;
|
||||
emailDaoMock.unlock.withArgs({}, passphrase).yields();
|
||||
setStateStub = sinon.stub(scope, 'setState', function(state) {
|
||||
if (setStateStub.calledOnce) {
|
||||
expect(state).to.equal(2);
|
||||
} else if (setStateStub.calledTwice) {
|
||||
expect(state).to.equal(4);
|
||||
expect(emailDaoMock.unlock.calledOnce).to.be.true;
|
||||
scope.setState.restore();
|
||||
done();
|
||||
}
|
||||
});
|
||||
|
||||
scope.confirmPassphrase();
|
||||
});
|
||||
|
||||
it('should not do anything matching passphrases', function() {
|
||||
scope.state.passphrase = 'a';
|
||||
scope.state.confirmation = 'b';
|
||||
|
||||
scope.confirmPassphrase();
|
||||
});
|
||||
|
||||
it('should not work when keypair generation fails', function(done) {
|
||||
scope.state.passphrase = passphrase;
|
||||
scope.state.confirmation = passphrase;
|
||||
emailDaoMock.unlock.withArgs({}, passphrase).yields(new Error('asd'));
|
||||
setStateStub = sinon.stub(scope, 'setState', function(state) {
|
||||
if (setStateStub.calledOnce) {
|
||||
expect(state).to.equal(2);
|
||||
} else if (setStateStub.calledTwice) {
|
||||
expect(state).to.equal(1);
|
||||
expect(emailDaoMock.unlock.calledOnce).to.be.true;
|
||||
scope.setState.restore();
|
||||
done();
|
||||
}
|
||||
});
|
||||
|
||||
scope.confirmPassphrase();
|
||||
});
|
||||
});
|
||||
|
||||
describe('proceed', function() {
|
||||
it('should forward', function() {
|
||||
var locationSpy = sinon.spy(location, 'path');
|
||||
|
||||
scope.proceed();
|
||||
|
||||
expect(locationSpy.calledWith('/desktop')).to.be.true;
|
||||
});
|
||||
});
|
||||
|
||||
describe('export keypair', function() {
|
||||
it('should work', function() {
|
||||
var locationSpy, createDownloadMock;
|
||||
|
||||
createDownloadMock = sinon.stub(dl, 'createDownload');
|
||||
cryptoMock.exportKeys.yields(null, {
|
||||
publicKeyArmored: 'a',
|
||||
privateKeyArmored: 'b',
|
||||
keyId: keyId
|
||||
});
|
||||
createDownloadMock.withArgs(sinon.match(function(arg) {
|
||||
return arg.content === 'ab' && arg.filename === expectedKeyId + '.asc' && arg.contentType === 'text/plain';
|
||||
})).yields();
|
||||
|
||||
locationSpy = sinon.spy(location, 'path');
|
||||
|
||||
scope.exportKeypair();
|
||||
|
||||
expect(cryptoMock.exportKeys.calledOnce).to.be.true;
|
||||
expect(createDownloadMock.calledOnce).to.be.true;
|
||||
expect(locationSpy.calledWith('/desktop')).to.be.true;
|
||||
dl.createDownload.restore();
|
||||
});
|
||||
|
||||
it('should not work when download fails', function() {
|
||||
var createDownloadMock = sinon.stub(dl, 'createDownload');
|
||||
cryptoMock.exportKeys.yields(null, {
|
||||
publicKeyArmored: 'a',
|
||||
privateKeyArmored: 'b',
|
||||
keyId: keyId
|
||||
});
|
||||
createDownloadMock.yields({
|
||||
errMsg: 'snafu.'
|
||||
});
|
||||
scope.exportKeypair();
|
||||
|
||||
expect(cryptoMock.exportKeys.calledOnce).to.be.true;
|
||||
expect(createDownloadMock.calledOnce).to.be.true;
|
||||
dl.createDownload.restore();
|
||||
});
|
||||
|
||||
it('should not work when export fails', function() {
|
||||
cryptoMock.exportKeys.yields(new Error('snafu.'));
|
||||
|
||||
scope.exportKeypair();
|
||||
|
||||
expect(cryptoMock.exportKeys.calledOnce).to.be.true;
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
142
test/new-unit/login-new-device-ctrl-test.js
Normal file
142
test/new-unit/login-new-device-ctrl-test.js
Normal file
@ -0,0 +1,142 @@
|
||||
define(function(require) {
|
||||
'use strict';
|
||||
|
||||
var expect = chai.expect,
|
||||
angular = require('angular'),
|
||||
mocks = require('angularMocks'),
|
||||
LoginNewDeviceCtrl = require('js/controller/login-new-device'),
|
||||
KeychainDAO = require('js/dao/keychain-dao'),
|
||||
EmailDAO = require('js/dao/email-dao'),
|
||||
appController = require('js/app-controller');
|
||||
|
||||
describe('Login (new device) Controller unit test', function() {
|
||||
var scope, ctrl, origEmailDao, emailDaoMock,
|
||||
emailAddress = 'fred@foo.com',
|
||||
passphrase = 'asd',
|
||||
keyId,
|
||||
keychainMock;
|
||||
|
||||
beforeEach(function() {
|
||||
// remember original module to restore later
|
||||
origEmailDao = appController._emailDao;
|
||||
|
||||
emailDaoMock = sinon.createStubInstance(EmailDAO);
|
||||
appController._emailDao = emailDaoMock;
|
||||
|
||||
keyId = '9FEB47936E712926';
|
||||
keychainMock = sinon.createStubInstance(KeychainDAO);
|
||||
emailDaoMock._keychain = keychainMock;
|
||||
|
||||
emailDaoMock._account = {
|
||||
emailAddress: emailAddress,
|
||||
};
|
||||
|
||||
angular.module('loginnewdevicetest', []);
|
||||
mocks.module('loginnewdevicetest');
|
||||
mocks.inject(function($rootScope, $controller) {
|
||||
scope = $rootScope.$new();
|
||||
scope.state = {
|
||||
ui: {}
|
||||
};
|
||||
ctrl = $controller(LoginNewDeviceCtrl, {
|
||||
$scope: scope
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
afterEach(function() {
|
||||
// restore the module
|
||||
appController._emailDao = origEmailDao;
|
||||
});
|
||||
|
||||
describe('initial state', function() {
|
||||
it('should be well defined', function() {
|
||||
expect(scope.incorrect).to.be.false;
|
||||
expect(scope.confirmPassphrase).to.exist;
|
||||
});
|
||||
});
|
||||
|
||||
describe('confirm passphrase', function() {
|
||||
it('should unlock crypto', function() {
|
||||
scope.passphrase = passphrase;
|
||||
scope.key = {
|
||||
privateKeyArmored: 'b'
|
||||
};
|
||||
keychainMock.getUserKeyPair.withArgs(emailAddress).yields(null, {
|
||||
_id: keyId,
|
||||
publicKey: 'a'
|
||||
});
|
||||
emailDaoMock.unlock.withArgs(sinon.match.any, passphrase).yields();
|
||||
keychainMock.putUserKeyPair.yields();
|
||||
|
||||
scope.confirmPassphrase();
|
||||
|
||||
expect(emailDaoMock.unlock.calledOnce).to.be.true;
|
||||
expect(keychainMock.getUserKeyPair.calledOnce).to.be.true;
|
||||
});
|
||||
|
||||
it('should not do anything without passphrase', function() {
|
||||
scope.state.passphrase = '';
|
||||
|
||||
scope.confirmPassphrase();
|
||||
|
||||
expect(scope.incorrect).to.be.true;
|
||||
});
|
||||
|
||||
it('should not work when keypair upload fails', function() {
|
||||
scope.passphrase = passphrase;
|
||||
scope.key = {
|
||||
privateKeyArmored: 'b'
|
||||
};
|
||||
|
||||
keychainMock.getUserKeyPair.withArgs(emailAddress).yields(null, {
|
||||
_id: keyId,
|
||||
publicKey: 'a'
|
||||
});
|
||||
emailDaoMock.unlock.withArgs(sinon.match.any, passphrase).yields();
|
||||
keychainMock.putUserKeyPair.yields({
|
||||
errMsg: 'yo mamma.'
|
||||
});
|
||||
|
||||
scope.confirmPassphrase();
|
||||
|
||||
expect(keychainMock.getUserKeyPair.calledOnce).to.be.true;
|
||||
expect(emailDaoMock.unlock.calledOnce).to.be.true;
|
||||
expect(keychainMock.putUserKeyPair.calledOnce).to.be.true;
|
||||
});
|
||||
|
||||
it('should not work when unlock fails', function() {
|
||||
scope.passphrase = passphrase;
|
||||
scope.key = {
|
||||
privateKeyArmored: 'b'
|
||||
};
|
||||
|
||||
keychainMock.getUserKeyPair.withArgs(emailAddress).yields(null, {
|
||||
_id: keyId,
|
||||
publicKey: 'a'
|
||||
});
|
||||
emailDaoMock.unlock.withArgs(sinon.match.any, passphrase).yields({
|
||||
errMsg: 'yo mamma.'
|
||||
});
|
||||
|
||||
scope.confirmPassphrase();
|
||||
|
||||
expect(scope.incorrect).to.be.true;
|
||||
expect(keychainMock.getUserKeyPair.calledOnce).to.be.true;
|
||||
expect(emailDaoMock.unlock.calledOnce).to.be.true;
|
||||
});
|
||||
|
||||
it('should not work when keypair retrieval', function() {
|
||||
scope.passphrase = passphrase;
|
||||
|
||||
keychainMock.getUserKeyPair.withArgs(emailAddress).yields({
|
||||
errMsg: 'yo mamma.'
|
||||
});
|
||||
|
||||
scope.confirmPassphrase();
|
||||
|
||||
expect(keychainMock.getUserKeyPair.calledOnce).to.be.true;
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
253
test/new-unit/mail-list-ctrl-test.js
Normal file
253
test/new-unit/mail-list-ctrl-test.js
Normal file
@ -0,0 +1,253 @@
|
||||
define(function(require) {
|
||||
'use strict';
|
||||
|
||||
var expect = chai.expect,
|
||||
angular = require('angular'),
|
||||
mocks = require('angularMocks'),
|
||||
MailListCtrl = require('js/controller/mail-list'),
|
||||
EmailDAO = require('js/dao/email-dao'),
|
||||
DeviceStorageDAO = require('js/dao/devicestorage-dao'),
|
||||
KeychainDAO = require('js/dao/keychain-dao'),
|
||||
appController = require('js/app-controller');
|
||||
|
||||
describe('Mail List controller unit test', function() {
|
||||
var scope, ctrl, origEmailDao, emailDaoMock, keychainMock, deviceStorageMock,
|
||||
emailAddress, notificationClickedHandler,
|
||||
hasChrome, hasNotifications, hasSocket, hasRuntime, hasIdentity;
|
||||
|
||||
beforeEach(function() {
|
||||
hasChrome = !! window.chrome;
|
||||
hasNotifications = !! window.chrome.notifications;
|
||||
hasSocket = !! window.chrome.socket;
|
||||
hasIdentity = !! window.chrome.identity;
|
||||
if (!hasChrome) {
|
||||
window.chrome = {};
|
||||
}
|
||||
if (!hasNotifications) {
|
||||
window.chrome.notifications = {
|
||||
onClicked: {
|
||||
addListener: function(handler) {
|
||||
notificationClickedHandler = handler;
|
||||
}
|
||||
},
|
||||
create: function() {}
|
||||
};
|
||||
}
|
||||
if (!hasSocket) {
|
||||
window.chrome.socket = {};
|
||||
}
|
||||
if (!hasRuntime) {
|
||||
window.chrome.runtime = {
|
||||
getURL: function() {}
|
||||
};
|
||||
}
|
||||
if (!hasIdentity) {
|
||||
window.chrome.identity = {};
|
||||
}
|
||||
origEmailDao = appController._emailDao;
|
||||
emailDaoMock = sinon.createStubInstance(EmailDAO);
|
||||
appController._emailDao = emailDaoMock;
|
||||
emailAddress = 'fred@foo.com';
|
||||
emailDaoMock._account = {
|
||||
emailAddress: emailAddress,
|
||||
};
|
||||
|
||||
|
||||
keychainMock = sinon.createStubInstance(KeychainDAO);
|
||||
emailDaoMock._keychain = keychainMock;
|
||||
|
||||
deviceStorageMock = sinon.createStubInstance(DeviceStorageDAO);
|
||||
emailDaoMock._devicestorage = deviceStorageMock;
|
||||
|
||||
angular.module('maillisttest', []);
|
||||
mocks.module('maillisttest');
|
||||
mocks.inject(function($rootScope, $controller) {
|
||||
scope = $rootScope.$new();
|
||||
scope.state = {};
|
||||
ctrl = $controller(MailListCtrl, {
|
||||
$scope: scope
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
afterEach(function() {
|
||||
if (!hasNotifications) {
|
||||
delete window.chrome.notifications;
|
||||
}
|
||||
if (!hasSocket) {
|
||||
delete window.chrome.socket;
|
||||
}
|
||||
if (!hasRuntime) {
|
||||
delete window.chrome.runtime;
|
||||
}
|
||||
if (!hasChrome) {
|
||||
delete window.chrome;
|
||||
}
|
||||
if (!hasIdentity) {
|
||||
delete window.chrome.identity;
|
||||
}
|
||||
|
||||
// restore the module
|
||||
appController._emailDao = origEmailDao;
|
||||
});
|
||||
|
||||
describe('scope variables', function() {
|
||||
it('should be set correctly', function() {
|
||||
expect(scope.select).to.exist;
|
||||
expect(scope.synchronize).to.exist;
|
||||
expect(scope.remove).to.exist;
|
||||
expect(scope.state.mailList).to.exist;
|
||||
expect(emailDaoMock.onIncomingMessage).to.exist;
|
||||
});
|
||||
});
|
||||
|
||||
describe('push notification', function() {
|
||||
it('should focus mail and not mark it read', function(done) {
|
||||
var uid, mail, currentFolder;
|
||||
|
||||
uid = 123;
|
||||
mail = {
|
||||
uid: uid,
|
||||
from: [{
|
||||
address: 'asd'
|
||||
}],
|
||||
subject: '[whiteout] asdasd',
|
||||
unread: true
|
||||
};
|
||||
currentFolder = 'asd';
|
||||
scope.state.nav = {
|
||||
currentFolder: currentFolder
|
||||
};
|
||||
scope.state.read = {
|
||||
toggle: function() {}
|
||||
};
|
||||
scope.emails = [mail];
|
||||
emailDaoMock.imapMarkMessageRead.withArgs({
|
||||
folder: currentFolder,
|
||||
uid: uid
|
||||
}).yields();
|
||||
emailDaoMock.unreadMessages.yieldsAsync(null, 10);
|
||||
emailDaoMock.imapSync.yieldsAsync();
|
||||
emailDaoMock.listMessages.yieldsAsync(null, [mail]);
|
||||
window.chrome.notifications.create = function(id, opts) {
|
||||
expect(id).to.equal('123');
|
||||
expect(opts.type).to.equal('basic');
|
||||
expect(opts.message).to.equal('asdasd');
|
||||
expect(opts.title).to.equal('asd');
|
||||
expect(scope.state.mailList.selected).to.deep.equal(mail);
|
||||
expect(emailDaoMock.imapMarkMessageRead.callCount).to.equal(0);
|
||||
done();
|
||||
};
|
||||
|
||||
emailDaoMock.onIncomingMessage(mail);
|
||||
});
|
||||
});
|
||||
|
||||
describe('clicking push notification', function() {
|
||||
it('should focus mail and mark it read', function() {
|
||||
var uid, mail, currentFolder;
|
||||
|
||||
uid = 123;
|
||||
mail = {
|
||||
uid: uid,
|
||||
from: [{
|
||||
address: 'asd'
|
||||
}],
|
||||
subject: '[whiteout] asdasd',
|
||||
unread: true
|
||||
};
|
||||
currentFolder = 'asd';
|
||||
scope.state.nav = {
|
||||
currentFolder: currentFolder
|
||||
};
|
||||
scope.state.read = {
|
||||
toggle: function() {}
|
||||
};
|
||||
scope.emails = [mail];
|
||||
emailDaoMock.imapMarkMessageRead.withArgs({
|
||||
folder: currentFolder,
|
||||
uid: uid
|
||||
}).yields();
|
||||
|
||||
notificationClickedHandler('123'); // first select, irrelevant
|
||||
notificationClickedHandler('123');
|
||||
|
||||
expect(scope.state.mailList.selected).to.deep.equal(mail);
|
||||
expect(emailDaoMock.imapMarkMessageRead.callCount).to.be.at.least(1);
|
||||
});
|
||||
});
|
||||
describe('remove', function() {
|
||||
it('should not delete without a selected mail', function() {
|
||||
scope.remove();
|
||||
|
||||
expect(emailDaoMock.imapDeleteMessage.called).to.be.false;
|
||||
});
|
||||
|
||||
it('should delete the selected mail from trash folder after clicking ok', function() {
|
||||
var uid, mail, currentFolder;
|
||||
|
||||
uid = 123;
|
||||
mail = {
|
||||
uid: uid,
|
||||
from: [{
|
||||
address: 'asd'
|
||||
}],
|
||||
subject: '[whiteout] asdasd',
|
||||
unread: true
|
||||
};
|
||||
scope.emails = [mail];
|
||||
currentFolder = {
|
||||
type: 'Trash'
|
||||
};
|
||||
scope.folders = [currentFolder];
|
||||
scope.state.nav = {
|
||||
currentFolder: currentFolder
|
||||
};
|
||||
emailDaoMock.imapDeleteMessage.yields();
|
||||
|
||||
scope.remove(mail);
|
||||
scope.state.dialog.callback(true);
|
||||
|
||||
expect(emailDaoMock.imapDeleteMessage.calledOnce).to.be.true;
|
||||
expect(scope.state.mailList.selected).to.not.exist;
|
||||
});
|
||||
|
||||
it('should move the selected mail to the trash folder', function() {
|
||||
var uid, mail, currentFolder, trashFolder;
|
||||
|
||||
uid = 123;
|
||||
mail = {
|
||||
uid: uid,
|
||||
from: [{
|
||||
address: 'asd'
|
||||
}],
|
||||
subject: '[whiteout] asdasd',
|
||||
unread: true
|
||||
};
|
||||
scope.emails = [mail];
|
||||
currentFolder = {
|
||||
type: 'Inbox',
|
||||
path: 'INBOX'
|
||||
};
|
||||
trashFolder = {
|
||||
type: 'Trash',
|
||||
path: 'TRASH'
|
||||
};
|
||||
scope.folders = [currentFolder, trashFolder];
|
||||
scope.state.nav = {
|
||||
currentFolder: currentFolder
|
||||
};
|
||||
emailDaoMock.imapMoveMessage.withArgs({
|
||||
folder: currentFolder,
|
||||
uid: uid,
|
||||
destination: trashFolder.path
|
||||
}).yields();
|
||||
|
||||
scope.remove(mail);
|
||||
|
||||
expect(emailDaoMock.imapMoveMessage.calledOnce).to.be.true;
|
||||
expect(scope.state.mailList.selected).to.not.exist;
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
@ -2,9 +2,19 @@
|
||||
|
||||
require(['../../src/require-config'], function() {
|
||||
require.config({
|
||||
baseUrl: '../../src/lib'
|
||||
baseUrl: '../../src/lib',
|
||||
paths: {
|
||||
angularMocks: '../../test/lib/angular-mocks'
|
||||
},
|
||||
shim: {
|
||||
angularMocks: {
|
||||
exports: 'angular.mock',
|
||||
deps: ['angular']
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
// Start the main app logic.
|
||||
require(['js/app-config', 'cordova'], function(app) {
|
||||
window.Worker = undefined; // disable web workers since mocha doesn't support them
|
||||
@ -27,7 +37,17 @@ function startTests() {
|
||||
'test/new-unit/publickey-dao-test',
|
||||
'test/new-unit/lawnchair-dao-test',
|
||||
'test/new-unit/keychain-dao-test',
|
||||
'test/new-unit/devicestorage-dao-test'
|
||||
'test/new-unit/devicestorage-dao-test',
|
||||
'test/new-unit/dialog-ctrl-test',
|
||||
'test/new-unit/account-ctrl-test',
|
||||
'test/new-unit/login-existing-ctrl-test',
|
||||
'test/new-unit/login-initial-ctrl-test',
|
||||
'test/new-unit/login-new-device-ctrl-test',
|
||||
'test/new-unit/login-ctrl-test',
|
||||
'test/new-unit/read-ctrl-test',
|
||||
'test/new-unit/navigation-ctrl-test',
|
||||
'test/new-unit/mail-list-ctrl-test',
|
||||
'test/new-unit/write-ctrl-test'
|
||||
], function() {
|
||||
//Tests loaded, run tests
|
||||
mocha.run();
|
||||
|
120
test/new-unit/navigation-ctrl-test.js
Normal file
120
test/new-unit/navigation-ctrl-test.js
Normal file
@ -0,0 +1,120 @@
|
||||
define(function(require) {
|
||||
'use strict';
|
||||
|
||||
var expect = chai.expect,
|
||||
angular = require('angular'),
|
||||
mocks = require('angularMocks'),
|
||||
NavigationCtrl = require('js/controller/navigation'),
|
||||
EmailDAO = require('js/dao/email-dao'),
|
||||
DeviceStorageDAO = require('js/dao/devicestorage-dao'),
|
||||
appController = require('js/app-controller');
|
||||
|
||||
describe('Navigation Controller unit test', function() {
|
||||
var scope, ctrl, origEmailDao, emailDaoMock, deviceStorageMock, tempChrome;
|
||||
|
||||
beforeEach(function() {
|
||||
if (window.chrome.identity) {
|
||||
tempChrome = window.chrome.identity;
|
||||
delete window.chrome.identity;
|
||||
}
|
||||
// remember original module to restore later
|
||||
origEmailDao = appController._emailDao;
|
||||
|
||||
emailDaoMock = sinon.createStubInstance(EmailDAO);
|
||||
appController._emailDao = emailDaoMock;
|
||||
|
||||
deviceStorageMock = sinon.createStubInstance(DeviceStorageDAO);
|
||||
appController._emailDao._devicestorage = deviceStorageMock;
|
||||
|
||||
angular.module('navigationtest', []);
|
||||
mocks.module('navigationtest');
|
||||
mocks.inject(function($rootScope, $controller) {
|
||||
scope = $rootScope.$new();
|
||||
scope.state = {};
|
||||
ctrl = $controller(NavigationCtrl, {
|
||||
$scope: scope
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
afterEach(function() {
|
||||
// restore the module
|
||||
appController._emailDao = origEmailDao;
|
||||
if (tempChrome) {
|
||||
window.chrome.identity = tempChrome;
|
||||
}
|
||||
});
|
||||
|
||||
describe('initial state', function() {
|
||||
it('should be well defined', function() {
|
||||
expect(scope.state).to.exist;
|
||||
expect(scope.state.nav.open).to.be.false;
|
||||
expect(scope.folders).to.not.be.empty;
|
||||
|
||||
expect(scope.onError).to.exist;
|
||||
expect(scope.openFolder).to.exist;
|
||||
expect(scope.emptyOutbox).to.exist;
|
||||
});
|
||||
});
|
||||
|
||||
describe('open/close nav view', function() {
|
||||
it('should open/close', function() {
|
||||
expect(scope.state.nav.open).to.be.false;
|
||||
scope.state.nav.toggle(true);
|
||||
expect(scope.state.nav.open).to.be.true;
|
||||
scope.state.nav.toggle(false);
|
||||
expect(scope.state.nav.open).to.be.false;
|
||||
});
|
||||
});
|
||||
|
||||
describe('open folder', function() {
|
||||
it('should work', function() {
|
||||
scope.state.nav.open = true;
|
||||
|
||||
scope.openFolder('asd');
|
||||
expect(scope.state.nav.currentFolder).to.equal('asd');
|
||||
expect(scope.state.nav.open).to.be.false;
|
||||
});
|
||||
});
|
||||
|
||||
describe('empty outbox', function() {
|
||||
it('should work', function() {
|
||||
deviceStorageMock.listItems.yields(null, [{
|
||||
id: 1
|
||||
}, {
|
||||
id: 2
|
||||
}, {
|
||||
id: 3
|
||||
}]);
|
||||
emailDaoMock.smtpSend.yields();
|
||||
deviceStorageMock.removeList.yields();
|
||||
|
||||
scope.emptyOutbox();
|
||||
|
||||
expect(deviceStorageMock.listItems.calledOnce).to.be.true;
|
||||
expect(emailDaoMock.smtpSend.calledThrice).to.be.true;
|
||||
expect(deviceStorageMock.removeList.calledThrice).to.be.true;
|
||||
});
|
||||
|
||||
it('should not work when device storage errors', function() {
|
||||
deviceStorageMock.listItems.yields({errMsg: 'error'});
|
||||
|
||||
scope.emptyOutbox();
|
||||
|
||||
expect(deviceStorageMock.listItems.calledOnce).to.be.true;
|
||||
});
|
||||
|
||||
it('should not work when smtp send fails', function() {
|
||||
deviceStorageMock.listItems.yields(null, [{
|
||||
id: 1
|
||||
}]);
|
||||
emailDaoMock.smtpSend.yields({errMsg: 'error'});
|
||||
|
||||
scope.emptyOutbox();
|
||||
|
||||
expect(deviceStorageMock.listItems.calledOnce).to.be.true;
|
||||
expect(emailDaoMock.smtpSend.calledOnce).to.be.true;
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
44
test/new-unit/read-ctrl-test.js
Normal file
44
test/new-unit/read-ctrl-test.js
Normal file
@ -0,0 +1,44 @@
|
||||
define(function(require) {
|
||||
'use strict';
|
||||
|
||||
var expect = chai.expect,
|
||||
angular = require('angular'),
|
||||
mocks = require('angularMocks'),
|
||||
ReadCtrl = require('js/controller/read');
|
||||
|
||||
describe('Read Controller unit test', function() {
|
||||
var scope, ctrl;
|
||||
|
||||
beforeEach(function() {
|
||||
angular.module('readtest', []);
|
||||
mocks.module('readtest');
|
||||
mocks.inject(function($rootScope, $controller) {
|
||||
scope = $rootScope.$new();
|
||||
scope.state = {};
|
||||
ctrl = $controller(ReadCtrl, {
|
||||
$scope: scope
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
afterEach(function() {});
|
||||
|
||||
describe('scope variables', function() {
|
||||
it('should be set correctly', function() {
|
||||
expect(scope.state.read).to.exist;
|
||||
expect(scope.state.read.open).to.be.false;
|
||||
expect(scope.state.read.toggle).to.exist;
|
||||
});
|
||||
});
|
||||
|
||||
describe('open/close read view', function() {
|
||||
it('should open/close', function() {
|
||||
expect(scope.state.read.open).to.be.false;
|
||||
scope.state.read.toggle(true);
|
||||
expect(scope.state.read.open).to.be.true;
|
||||
scope.state.read.toggle(false);
|
||||
expect(scope.state.read.open).to.be.false;
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
205
test/new-unit/write-ctrl-test.js
Normal file
205
test/new-unit/write-ctrl-test.js
Normal file
@ -0,0 +1,205 @@
|
||||
define(function(require) {
|
||||
'use strict';
|
||||
|
||||
var expect = chai.expect,
|
||||
angular = require('angular'),
|
||||
mocks = require('angularMocks'),
|
||||
WriteCtrl = require('js/controller/write'),
|
||||
EmailDAO = require('js/dao/email-dao'),
|
||||
DeviceStorageDAO = require('js/dao/devicestorage-dao'),
|
||||
KeychainDAO = require('js/dao/keychain-dao'),
|
||||
appController = require('js/app-controller');
|
||||
|
||||
describe('Write controller unit test', function() {
|
||||
var ctrl, scope, origEmailDao, emailDaoMock, keychainMock, deviceStorageMock, emailAddress;
|
||||
|
||||
beforeEach(function() {
|
||||
origEmailDao = appController._emailDao;
|
||||
emailDaoMock = sinon.createStubInstance(EmailDAO);
|
||||
appController._emailDao = emailDaoMock;
|
||||
emailAddress = 'fred@foo.com';
|
||||
emailDaoMock._account = {
|
||||
emailAddress: emailAddress,
|
||||
};
|
||||
|
||||
keychainMock = sinon.createStubInstance(KeychainDAO);
|
||||
emailDaoMock._keychain = keychainMock;
|
||||
|
||||
deviceStorageMock = sinon.createStubInstance(DeviceStorageDAO);
|
||||
emailDaoMock._devicestorage = deviceStorageMock;
|
||||
|
||||
angular.module('writetest', []);
|
||||
mocks.module('writetest');
|
||||
mocks.inject(function($rootScope, $controller) {
|
||||
scope = $rootScope.$new();
|
||||
scope.state = {};
|
||||
ctrl = $controller(WriteCtrl, {
|
||||
$scope: scope
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
afterEach(function() {
|
||||
// restore the module
|
||||
appController._emailDao = origEmailDao;
|
||||
});
|
||||
|
||||
describe('scope variables', function() {
|
||||
it('should be set correctly', function() {
|
||||
expect(scope.state.writer).to.exist;
|
||||
expect(scope.state.writer.open).to.be.false;
|
||||
expect(scope.state.writer.write).to.exist;
|
||||
expect(scope.state.writer.close).to.exist;
|
||||
expect(scope.verifyTo).to.exist;
|
||||
expect(scope.updatePreview).to.exist;
|
||||
expect(scope.sendToOutbox).to.exist;
|
||||
});
|
||||
});
|
||||
|
||||
describe('close', function() {
|
||||
it('should close the writer', function() {
|
||||
scope.state.writer.open = true;
|
||||
|
||||
scope.state.writer.close();
|
||||
|
||||
expect(scope.state.writer.open).to.be.false;
|
||||
});
|
||||
});
|
||||
|
||||
describe('write', function() {
|
||||
it('should prepare write view', function() {
|
||||
var verifyToMock = sinon.stub(scope, 'verifyTo');
|
||||
|
||||
scope.state.writer.write();
|
||||
|
||||
expect(scope.writerTitle).to.equal('New email');
|
||||
expect(scope.to).to.equal('');
|
||||
expect(scope.subject).to.equal('');
|
||||
expect(scope.body).to.equal('');
|
||||
expect(scope.ciphertextPreview).to.equal('');
|
||||
expect(verifyToMock.calledOnce).to.be.true;
|
||||
|
||||
scope.verifyTo.restore();
|
||||
});
|
||||
|
||||
it('should prefill write view for response', function() {
|
||||
var verifyToMock = sinon.stub(scope, 'verifyTo'),
|
||||
address = 'pity@dafool',
|
||||
subject = 'Ermahgerd!',
|
||||
body = 'so much body!',
|
||||
re = {
|
||||
from: [{
|
||||
address: address
|
||||
}],
|
||||
subject: subject,
|
||||
sentDate: new Date(),
|
||||
body: body
|
||||
};
|
||||
|
||||
scope.state.writer.write(re);
|
||||
|
||||
expect(scope.writerTitle).to.equal('Reply');
|
||||
expect(scope.to).to.equal(address);
|
||||
expect(scope.subject).to.equal('Re: ' + subject);
|
||||
expect(scope.body).to.contain(body);
|
||||
expect(scope.ciphertextPreview).to.not.be.empty;
|
||||
expect(verifyToMock.calledOnce).to.be.true;
|
||||
|
||||
scope.verifyTo.restore();
|
||||
});
|
||||
|
||||
it('should prevent markup injection', function() {
|
||||
var address = 'pity@dafool',
|
||||
subject = 'Ermahgerd!',
|
||||
body = '<div>markup</div><div>moreMarkup<div>',
|
||||
re = {
|
||||
from: [{
|
||||
address: address
|
||||
}],
|
||||
subject: subject,
|
||||
sentDate: new Date(),
|
||||
body: body,
|
||||
html: false
|
||||
};
|
||||
|
||||
sinon.stub(scope, 'verifyTo');
|
||||
|
||||
scope.state.writer.write(re);
|
||||
|
||||
expect(scope.body).to.contain('<br>markupmoreMarkup');
|
||||
|
||||
scope.verifyTo.restore();
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('verifyTo', function() {
|
||||
it('should verify the recipient as secure', function() {
|
||||
var id = scope.to = 'pity@da.fool';
|
||||
keychainMock.getReceiverPublicKey.withArgs(id).yields(null, {
|
||||
userId: id
|
||||
});
|
||||
|
||||
scope.verifyTo();
|
||||
|
||||
expect(scope.toSecure).to.be.true;
|
||||
expect(scope.sendBtnText).to.equal('Send securely');
|
||||
});
|
||||
|
||||
it('should verify the recipient as not secure', function() {
|
||||
var id = scope.to = 'pity@da.fool';
|
||||
keychainMock.getReceiverPublicKey.withArgs(id).yields({
|
||||
errMsg: '404 not found yadda yadda'
|
||||
});
|
||||
|
||||
scope.verifyTo();
|
||||
|
||||
expect(scope.toSecure).to.be.false;
|
||||
expect(scope.sendBtnText).to.equal('Invite & send securely');
|
||||
});
|
||||
|
||||
it('should reset display if there is no recipient', function() {
|
||||
scope.to = undefined;
|
||||
scope.verifyTo();
|
||||
});
|
||||
});
|
||||
|
||||
describe('send to outbox', function() {
|
||||
it('should work', function(done) {
|
||||
scope.state.writer.open = true;
|
||||
scope.to = 'a, b, c';
|
||||
scope.body = 'asd';
|
||||
scope.subject = 'yaddablabla';
|
||||
|
||||
deviceStorageMock.storeList.withArgs(sinon.match(function(mail) {
|
||||
return mail[0].from[0].address === emailAddress && mail[0].to.length === 3;
|
||||
})).yieldsAsync();
|
||||
scope.emptyOutbox = function() {
|
||||
expect(scope.state.writer.open).to.be.false;
|
||||
expect(deviceStorageMock.storeList.calledOnce).to.be.true;
|
||||
done();
|
||||
};
|
||||
|
||||
scope.sendToOutbox();
|
||||
});
|
||||
|
||||
it('should not work and not close the write view', function() {
|
||||
scope.state.writer.open = true;
|
||||
scope.to = 'a, b, c';
|
||||
scope.body = 'asd';
|
||||
scope.subject = 'yaddablabla';
|
||||
|
||||
deviceStorageMock.storeList.withArgs(sinon.match(function(mail) {
|
||||
return mail[0].from[0].address === emailAddress && mail[0].to.length === 3;
|
||||
})).yields({
|
||||
errMsg: 'snafu'
|
||||
});
|
||||
|
||||
scope.sendToOutbox();
|
||||
|
||||
expect(scope.state.writer.open).to.be.true;
|
||||
expect(deviceStorageMock.storeList.calledOnce).to.be.true;
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
Loading…
Reference in New Issue
Block a user