diff --git a/.gitignore b/.gitignore index 97d8d25..babcf49 100644 --- a/.gitignore +++ b/.gitignore @@ -8,3 +8,5 @@ dist/ release/ test/integration/src/ .elasticbeanstalk/ +test/unit/index.js +test/unit/index.js.map diff --git a/.jshintrc b/.jshintrc index 79d663e..a3064a8 100644 --- a/.jshintrc +++ b/.jshintrc @@ -18,19 +18,18 @@ "unused": true, "predef": [ + "self", "console", - "Notification", - "importScripts", - "process", - "Event", + "process", "chrome", - "define", - "self", + "Notification", + "Event", + "sinon", + "mocha", + "chai", + "expect", "describe", "it", - "chai", - "sinon", - "mocha", "before", "beforeEach", "after", diff --git a/Gruntfile.js b/Gruntfile.js index dacb48e..ce09983 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -1,6 +1,8 @@ module.exports = function(grunt) { 'use strict'; + require('time-grunt')(grunt); + var version = grunt.option('release'), zipName = (version) ? version : 'DEV'; @@ -24,7 +26,7 @@ module.exports = function(grunt) { }, jshint: { - all: ['Gruntfile.js', 'src/*.js', 'src/js/**/*.js', 'test/unit/*.js', 'test/integration/*.js'], + all: ['Gruntfile.js', 'src/*.js', 'src/js/**/*.js', 'test/unit/*-test.js', 'test/integration/*.js'], options: { jshintrc: '.jshintrc' } @@ -109,16 +111,22 @@ module.exports = function(grunt) { 'dist/js/app.min.js': ['src/js/app.js'] }, options: { - external: ['node-forge', 'net', 'tls'] // common.js apis not required at build time + external: [] } }, - /* TODO: - tls-worker: {}, - mailreader-worker: {}, - pbkdf2-worker: {}, - unitTest: {}, - unitTest: {}, - integrationTest: {} + unitTest: { + files: { + 'test/unit/index.js': ['test/unit/*-test.js'] + }, + options: { + external: [] + } + }, + /* + TODO: + mailreader-worker: {}, + pbkdf2-worker: {}, + integrationTest: {} */ }, @@ -126,6 +134,7 @@ module.exports = function(grunt) { all: { files: { 'dist/js/app.min.js': [ + 'src/lib/openpgp/openpgp.js', 'src/lib/underscore/underscore-min.js', 'node_modules/jquery/dist/jquery.min.js', 'src/lib/angular/angular.min.js', @@ -142,6 +151,28 @@ module.exports = function(grunt) { ] } }, + unitTest: { + files: { + 'test/unit/index.js': [ + 'src/lib/underscore/underscore-min.js', + 'node_modules/jquery/dist/jquery.min.js', + 'src/lib/openpgp/openpgp.js', + 'src/lib/angular/angular.min.js', + 'node_modules/angular-mocks/angular-mocks.js', + 'src/lib/angular/angular-route.min.js', + 'src/lib/angular/angular-animate.min.js', + 'src/lib/ngtagsinput/ng-tags-input.min.js', + 'src/lib/fastclick/fastclick.js', + 'node_modules/ng-infinite-scroll/build/ng-infinite-scroll.min.js', + 'src/lib/lawnchair/lawnchair-git.js', + 'src/lib/lawnchair/lawnchair-adapter-webkit-sqlite-git.js', + 'src/lib/lawnchair/lawnchair-adapter-indexed-db-git.js', + 'node_modules/dompurify/purify.js', + 'test/lib/angular-mocks.js', + 'test/unit/index.js' + ] + } + }, options: { banner: '/*! Copyright © <%= grunt.template.today("yyyy") %>, Whiteout Networks GmbH.*/\n' } @@ -152,7 +183,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', 'angularjs/src/ngMock/angular-mocks.js', 'browsercrow/src/*.js', 'browsersmtp/src/*.js'], + src: ['mocha/mocha.css', 'mocha/mocha.js', 'chai/chai.js', 'sinon/pkg/sinon.js', 'browsercrow/src/*.js', 'browsersmtp/src/*.js'], dest: 'test/lib/' }, font: { diff --git a/package.json b/package.json index a6e3162..614c632 100644 --- a/package.json +++ b/package.json @@ -1,70 +1,72 @@ { - "name": "whiteout-mail", - "version": "0.0.1", - "description": "Mail App with integrated OpenPGP encryption.", - "author": "Whiteout Networks", - "homepage": "https://whiteout.io", - "repository": { - "type": "git", - "url": "https://github.com/whiteout-io/mail-html5.git" - }, - "keywords": [ - "email", - "mail", - "client", - "app", - "openpgp", - "pgp", - "gpg", - "imap", - "smtp" - ], - "engines": { - "node": ">=0.10" - }, - "scripts": { - "test": "grunt && grunt test", - "start": "node server.js" - }, - "dependencies": { - "axe-logger": "~0.0.2", - "compression": "^1.0.11", - "config": "^1.0.2", - "crypto-lib": "~0.2.1", - "dompurify": "~0.4.2", - "express": "^4.8.3", - "imap-client": "~0.4.3", - "jquery": "~2.1.1", - "mailreader": "~0.3.5", - "morgan": "^1.2.3", - "ng-infinite-scroll": "~1.1.2", - "npmlog": "^0.1.1", - "pgpbuilder": "~0.4.0", - "pgpmailer": "~0.4.0", - "socket.io": "^1.0.6", - "tcp-socket": "^0.3.9", - "wo-smtpclient": "^0.3.8" - }, - "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", - "chai": "~1.7.2", - "grunt": "~0.4.1", - "grunt-autoprefixer": "~0.7.2", - "grunt-browserify": "^3.0.1", - "grunt-contrib-clean": "~0.5.0", - "grunt-contrib-compress": "~0.5.2", - "grunt-contrib-connect": "~0.5.0", - "grunt-contrib-copy": "~0.4.1", - "grunt-contrib-jshint": "~0.6.4", - "grunt-contrib-sass": "~0.7.3", - "grunt-contrib-uglify": "^0.6.0", - "grunt-contrib-watch": "~0.5.3", - "grunt-csso": "~0.6.1", - "grunt-manifest": "^0.4.0", - "grunt-mocha": "~0.4.1", - "mocha": "~1.13.0", - "sinon": "~1.7.3" - } -} \ No newline at end of file + "name": "whiteout-mail", + "version": "0.0.1", + "description": "Mail App with integrated OpenPGP encryption.", + "author": "Whiteout Networks", + "homepage": "https://whiteout.io", + "repository": { + "type": "git", + "url": "https://github.com/whiteout-io/mail-html5.git" + }, + "keywords": [ + "email", + "mail", + "client", + "app", + "openpgp", + "pgp", + "gpg", + "imap", + "smtp" + ], + "engines": { + "node": ">=0.10" + }, + "scripts": { + "test": "grunt && grunt test", + "start": "node server.js" + }, + "dependencies": { + "axe-logger": "~0.0.2", + "compression": "^1.0.11", + "config": "^1.0.2", + "crypto-lib": "~0.2.1", + "dompurify": "~0.4.2", + "express": "^4.8.3", + "imap-client": "~0.4.3", + "jquery": "~2.1.1", + "mailreader": "~0.3.5", + "morgan": "^1.2.3", + "ng-infinite-scroll": "~1.1.2", + "npmlog": "^0.1.1", + "pgpbuilder": "~0.4.0", + "pgpmailer": "~0.4.0", + "socket.io": "^1.0.6", + "tcp-socket": "^0.3.9", + "wo-smtpclient": "^0.3.8" + }, + "devDependencies": { + "angular-mocks": "^1.2.25", + "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", + "chai": "~1.7.2", + "grunt": "~0.4.1", + "grunt-autoprefixer": "~0.7.2", + "grunt-browserify": "^3.0.1", + "grunt-contrib-clean": "~0.5.0", + "grunt-contrib-compress": "~0.5.2", + "grunt-contrib-connect": "~0.5.0", + "grunt-contrib-copy": "~0.4.1", + "grunt-contrib-jshint": "~0.6.4", + "grunt-contrib-sass": "~0.7.3", + "grunt-contrib-uglify": "^0.6.0", + "grunt-contrib-watch": "~0.5.3", + "grunt-csso": "~0.6.1", + "grunt-manifest": "^0.4.0", + "grunt-mocha": "~0.4.1", + "mocha": "~1.13.0", + "sinon": "~1.7.3", + "time-grunt": "^1.0.0" + } +} diff --git a/test/unit/account-ctrl-test.js b/test/unit/account-ctrl-test.js index 1902d0b..5deacd7 100644 --- a/test/unit/account-ctrl-test.js +++ b/test/unit/account-ctrl-test.js @@ -1,101 +1,97 @@ -define(function(require) { - 'use strict'; +'use strict'; - var expect = chai.expect, - angular = require('angular'), - mocks = require('angularMocks'), - AccountCtrl = require('js/controller/account'), - PGP = require('js/crypto/pgp'), - dl = require('js/util/download'), - appController = require('js/app-controller'), - KeychainDAO = require('js/dao/keychain-dao'); +var mocks = angular.mocks, + AccountCtrl = require('../../src/js/controller/account'), + PGP = require('../../src/js/crypto/pgp'), + dl = require('../../src/js/util/download'), + appController = require('../../src/js/app-controller'), + KeychainDAO = require('../../src/js/dao/keychain-dao'); - describe('Account Controller unit test', function() { - var scope, accountCtrl, - dummyFingerprint, expectedFingerprint, - dummyKeyId, expectedKeyId, - emailAddress, keySize, pgpMock, keychainMock; +describe('Account Controller unit test', function() { + var scope, accountCtrl, + dummyFingerprint, expectedFingerprint, + dummyKeyId, expectedKeyId, + emailAddress, keySize, pgpMock, keychainMock; - beforeEach(function() { - appController._pgp = pgpMock = sinon.createStubInstance(PGP); - appController._keychain = keychainMock = sinon.createStubInstance(KeychainDAO); + beforeEach(function() { + appController._pgp = pgpMock = sinon.createStubInstance(PGP); + appController._keychain = keychainMock = sinon.createStubInstance(KeychainDAO); - dummyFingerprint = '3A2D39B4E1404190B8B949DE7D7E99036E712926'; - expectedFingerprint = '3A2D 39B4 E140 4190 B8B9 49DE 7D7E 9903 6E71 2926'; - dummyKeyId = '9FEB47936E712926'; - expectedKeyId = '6E712926'; - pgpMock.getFingerprint.returns(dummyFingerprint); - pgpMock.getKeyId.returns(dummyKeyId); - emailAddress = 'fred@foo.com'; - keySize = 1234; - appController._emailDao = { - _account: { - emailAddress: emailAddress, - asymKeySize: keySize - } - }; - pgpMock.getKeyParams.returns({ - _id: dummyKeyId, - fingerprint: dummyFingerprint, - userId: emailAddress, - bitSize: keySize - }); - - angular.module('accounttest', []); - mocks.module('accounttest'); - mocks.inject(function($rootScope, $controller) { - scope = $rootScope.$new(); - scope.state = {}; - accountCtrl = $controller(AccountCtrl, { - $scope: scope - }); - }); + dummyFingerprint = '3A2D39B4E1404190B8B949DE7D7E99036E712926'; + expectedFingerprint = '3A2D 39B4 E140 4190 B8B9 49DE 7D7E 9903 6E71 2926'; + dummyKeyId = '9FEB47936E712926'; + expectedKeyId = '6E712926'; + pgpMock.getFingerprint.returns(dummyFingerprint); + pgpMock.getKeyId.returns(dummyKeyId); + emailAddress = 'fred@foo.com'; + keySize = 1234; + appController._emailDao = { + _account: { + emailAddress: emailAddress, + asymKeySize: keySize + } + }; + pgpMock.getKeyParams.returns({ + _id: dummyKeyId, + fingerprint: dummyFingerprint, + userId: emailAddress, + bitSize: keySize }); - afterEach(function() {}); - - 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'); - keychainMock.getUserKeyPair.withArgs(emailAddress).yields(null, { - publicKey: { - _id: dummyKeyId, - publicKey: 'a' - }, - privateKey: { - encryptedKey: 'b' - } - }); - createDownloadMock.withArgs(sinon.match(function(arg) { - return arg.content === 'a\r\nb' && arg.filename === 'whiteout_mail_' + emailAddress + '_' + expectedKeyId + '.asc' && arg.contentType === 'text/plain'; - })).returns(); - - scope.exportKeyFile(); - - expect(scope.state.lightbox).to.equal(undefined); - expect(keychainMock.getUserKeyPair.calledOnce).to.be.true; - expect(dl.createDownload.calledOnce).to.be.true; - dl.createDownload.restore(); - }); - - it('should not work when key export failed', function(done) { - keychainMock.getUserKeyPair.yields(new Error('Boom!')); - scope.onError = function(err) { - expect(err.message).to.equal('Boom!'); - expect(keychainMock.getUserKeyPair.calledOnce).to.be.true; - done(); - }; - - scope.exportKeyFile(); + angular.module('accounttest', []); + mocks.module('accounttest'); + mocks.inject(function($rootScope, $controller) { + scope = $rootScope.$new(); + scope.state = {}; + accountCtrl = $controller(AccountCtrl, { + $scope: scope }); }); }); + + afterEach(function() {}); + + 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'); + keychainMock.getUserKeyPair.withArgs(emailAddress).yields(null, { + publicKey: { + _id: dummyKeyId, + publicKey: 'a' + }, + privateKey: { + encryptedKey: 'b' + } + }); + createDownloadMock.withArgs(sinon.match(function(arg) { + return arg.content === 'a\r\nb' && arg.filename === 'whiteout_mail_' + emailAddress + '_' + expectedKeyId + '.asc' && arg.contentType === 'text/plain'; + })).returns(); + + scope.exportKeyFile(); + + expect(scope.state.lightbox).to.equal(undefined); + expect(keychainMock.getUserKeyPair.calledOnce).to.be.true; + expect(dl.createDownload.calledOnce).to.be.true; + dl.createDownload.restore(); + }); + + it('should not work when key export failed', function(done) { + keychainMock.getUserKeyPair.yields(new Error('Boom!')); + scope.onError = function(err) { + expect(err.message).to.equal('Boom!'); + expect(keychainMock.getUserKeyPair.calledOnce).to.be.true; + done(); + }; + + scope.exportKeyFile(); + }); + }); }); \ No newline at end of file diff --git a/test/unit/add-account-ctrl-test.js b/test/unit/add-account-ctrl-test.js index 4f42e92..69d2430 100644 --- a/test/unit/add-account-ctrl-test.js +++ b/test/unit/add-account-ctrl-test.js @@ -1,216 +1,212 @@ -define(function(require) { - 'use strict'; +'use strict'; - var expect = chai.expect, - angular = require('angular'), - mocks = require('angularMocks'), - AddAccountCtrl = require('js/controller/add-account'), - Auth = require('js/bo/auth'), - AdminDao = require('js/dao/admin-dao'), - appController = require('js/app-controller'); +var mocks = angular.mocks, + AddAccountCtrl = require('../../src/js/controller/add-account'), + Auth = require('../../src/js/bo/auth'), + AdminDao = require('../../src/js/dao/admin-dao'), + appController = require('../../src/js/app-controller'); - describe('Add Account Controller unit test', function() { - var scope, location, ctrl, authStub, origAuth, adminStub; +describe('Add Account Controller unit test', function() { + var scope, location, ctrl, authStub, origAuth, adminStub; - beforeEach(function() { - // remember original module to restore later, then replace it - origAuth = appController._auth; - appController._auth = authStub = sinon.createStubInstance(Auth); - appController._adminDao = adminStub = sinon.createStubInstance(AdminDao); + beforeEach(function() { + // remember original module to restore later, then replace it + origAuth = appController._auth; + appController._auth = authStub = sinon.createStubInstance(Auth); + appController._adminDao = adminStub = sinon.createStubInstance(AdminDao); - angular.module('addaccounttest', []); - mocks.module('addaccounttest'); - mocks.inject(function($controller, $rootScope, $location) { - location = $location; - scope = $rootScope.$new(); - scope.state = {}; - scope.form = {}; - scope.formValidate = {}; + angular.module('addaccounttest', []); + mocks.module('addaccounttest'); + mocks.inject(function($controller, $rootScope, $location) { + location = $location; + scope = $rootScope.$new(); + scope.state = {}; + scope.form = {}; + scope.formValidate = {}; - sinon.stub(location, 'path').returns(location); - sinon.stub(location, 'search').returns(location); - sinon.stub(scope, '$apply', function() {}); + 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: {} - }); + ctrl = $controller(AddAccountCtrl, { + $location: location, + $scope: scope, + $routeParams: {} }); }); - - afterEach(function() { - // restore the app controller module - appController._auth = origAuth; - - location.path.restore(); - location.search.restore(); - if (scope.$apply.restore) { - scope.$apply.restore(); - } - }); - - describe('createWhiteoutAccount', function() { - it('should return early for invalid form', function() { - scope.form.$invalid = true; - scope.createWhiteoutAccount(); - expect(adminStub.createUser.called).to.be.false; - }); - - it('should fail to error creating user', function(done) { - scope.form.$invalid = false; - scope.betaCode = 'asfd'; - scope.phone = '12345'; - adminStub.createUser.yieldsAsync(new Error('asdf')); - - scope.$apply = function() { - expect(scope.busy).to.be.false; - expect(scope.errMsg).to.equal('asdf'); - expect(adminStub.createUser.calledOnce).to.be.true; - done(); - }; - - scope.createWhiteoutAccount(); - expect(scope.busy).to.be.true; - }); - - it('should work', function(done) { - scope.form.$invalid = false; - scope.betaCode = 'asfd'; - scope.phone = '12345'; - adminStub.createUser.yieldsAsync(); - - scope.$apply = function() { - expect(scope.busy).to.be.false; - expect(scope.errMsg).to.be.undefined; - expect(scope.step).to.equal(3); - expect(adminStub.createUser.calledOnce).to.be.true; - done(); - }; - - scope.createWhiteoutAccount(); - expect(scope.busy).to.be.true; - }); - }); - - describe('validateUser', function() { - it('should return early for invalid form', function() { - scope.formValidate.$invalid = true; - scope.validateUser(); - expect(adminStub.validateUser.called).to.be.false; - }); - - it('should fail to error creating user', function(done) { - scope.formValidate.$invalid = false; - scope.token = 'asfd'; - adminStub.validateUser.yieldsAsync(new Error('asdf')); - - scope.$apply = function() { - expect(scope.busyValidate).to.be.false; - expect(scope.errMsgValidate).to.equal('asdf'); - expect(adminStub.validateUser.calledOnce).to.be.true; - done(); - }; - - scope.validateUser(); - expect(scope.busyValidate).to.be.true; - }); - - it('should work', function(done) { - scope.formValidate.$invalid = false; - scope.token = 'asfd'; - adminStub.validateUser.yieldsAsync(); - - scope.login = function() { - expect(scope.busyValidate).to.be.true; - expect(scope.errMsgValidate).to.be.undefined; - expect(adminStub.validateUser.calledOnce).to.be.true; - done(); - }; - - scope.validateUser(); - expect(scope.busyValidate).to.be.true; - }); - }); - - describe('login', function() { - it('should work', function() { - scope.form.$invalid = false; - authStub.setCredentials.returns(); - - scope.login(); - expect(authStub.setCredentials.calledOnce).to.be.true; - expect(location.path.calledWith('/login')).to.be.true; - }); - }); - - describe('connectToGoogle', function() { - it('should forward to login', function() { - authStub._oauth = { - isSupported: function() { - return true; - } - }; - - authStub.getOAuthToken.yields(); - - scope.connectToGoogle(); - - expect(location.path.calledWith('/login-set-credentials')).to.be.true; - expect(location.search.calledWith({ - provider: 'gmail' - })).to.be.true; - expect(authStub.getOAuthToken.calledOnce).to.be.true; - }); - - it('should not use oauth for gmail', function() { - authStub._oauth = { - isSupported: function() { - return false; - } - }; - - scope.connectToGoogle(); - - expect(location.path.calledWith('/login-set-credentials')).to.be.true; - expect(location.search.calledWith({ - provider: 'gmail' - })).to.be.true; - expect(authStub.getOAuthToken.called).to.be.false; - }); - - it('should not forward to login when oauth fails', function(done) { - authStub._oauth = { - isSupported: function() { - return true; - } - }; - - authStub.getOAuthToken.yields(new Error()); - - scope.onError = function(err) { - expect(err).to.exist; - expect(location.path.called).to.be.false; - expect(location.search.called).to.be.false; - - done(); - }; - - scope.connectToGoogle(); - }); - }); - - describe('connectTo', function() { - it('should forward to login', function() { - var provider = 'wmail'; - scope.connectTo(provider); - - expect(location.path.calledWith('/login-set-credentials')).to.be.true; - expect(location.search.calledWith({ - provider: provider - })).to.be.true; - }); - }); - }); + + afterEach(function() { + // restore the app controller module + appController._auth = origAuth; + + location.path.restore(); + location.search.restore(); + if (scope.$apply.restore) { + scope.$apply.restore(); + } + }); + + describe('createWhiteoutAccount', function() { + it('should return early for invalid form', function() { + scope.form.$invalid = true; + scope.createWhiteoutAccount(); + expect(adminStub.createUser.called).to.be.false; + }); + + it('should fail to error creating user', function(done) { + scope.form.$invalid = false; + scope.betaCode = 'asfd'; + scope.phone = '12345'; + adminStub.createUser.yieldsAsync(new Error('asdf')); + + scope.$apply = function() { + expect(scope.busy).to.be.false; + expect(scope.errMsg).to.equal('asdf'); + expect(adminStub.createUser.calledOnce).to.be.true; + done(); + }; + + scope.createWhiteoutAccount(); + expect(scope.busy).to.be.true; + }); + + it('should work', function(done) { + scope.form.$invalid = false; + scope.betaCode = 'asfd'; + scope.phone = '12345'; + adminStub.createUser.yieldsAsync(); + + scope.$apply = function() { + expect(scope.busy).to.be.false; + expect(scope.errMsg).to.be.undefined; + expect(scope.step).to.equal(3); + expect(adminStub.createUser.calledOnce).to.be.true; + done(); + }; + + scope.createWhiteoutAccount(); + expect(scope.busy).to.be.true; + }); + }); + + describe('validateUser', function() { + it('should return early for invalid form', function() { + scope.formValidate.$invalid = true; + scope.validateUser(); + expect(adminStub.validateUser.called).to.be.false; + }); + + it('should fail to error creating user', function(done) { + scope.formValidate.$invalid = false; + scope.token = 'asfd'; + adminStub.validateUser.yieldsAsync(new Error('asdf')); + + scope.$apply = function() { + expect(scope.busyValidate).to.be.false; + expect(scope.errMsgValidate).to.equal('asdf'); + expect(adminStub.validateUser.calledOnce).to.be.true; + done(); + }; + + scope.validateUser(); + expect(scope.busyValidate).to.be.true; + }); + + it('should work', function(done) { + scope.formValidate.$invalid = false; + scope.token = 'asfd'; + adminStub.validateUser.yieldsAsync(); + + scope.login = function() { + expect(scope.busyValidate).to.be.true; + expect(scope.errMsgValidate).to.be.undefined; + expect(adminStub.validateUser.calledOnce).to.be.true; + done(); + }; + + scope.validateUser(); + expect(scope.busyValidate).to.be.true; + }); + }); + + describe('login', function() { + it('should work', function() { + scope.form.$invalid = false; + authStub.setCredentials.returns(); + + scope.login(); + expect(authStub.setCredentials.calledOnce).to.be.true; + expect(location.path.calledWith('/login')).to.be.true; + }); + }); + + describe('connectToGoogle', function() { + it('should forward to login', function() { + authStub._oauth = { + isSupported: function() { + return true; + } + }; + + authStub.getOAuthToken.yields(); + + scope.connectToGoogle(); + + expect(location.path.calledWith('/login-set-credentials')).to.be.true; + expect(location.search.calledWith({ + provider: 'gmail' + })).to.be.true; + expect(authStub.getOAuthToken.calledOnce).to.be.true; + }); + + it('should not use oauth for gmail', function() { + authStub._oauth = { + isSupported: function() { + return false; + } + }; + + scope.connectToGoogle(); + + expect(location.path.calledWith('/login-set-credentials')).to.be.true; + expect(location.search.calledWith({ + provider: 'gmail' + })).to.be.true; + expect(authStub.getOAuthToken.called).to.be.false; + }); + + it('should not forward to login when oauth fails', function(done) { + authStub._oauth = { + isSupported: function() { + return true; + } + }; + + authStub.getOAuthToken.yields(new Error()); + + scope.onError = function(err) { + expect(err).to.exist; + expect(location.path.called).to.be.false; + expect(location.search.called).to.be.false; + + done(); + }; + + scope.connectToGoogle(); + }); + }); + + describe('connectTo', function() { + it('should forward to login', function() { + var provider = 'wmail'; + scope.connectTo(provider); + + expect(location.path.calledWith('/login-set-credentials')).to.be.true; + expect(location.search.calledWith({ + provider: provider + })).to.be.true; + }); + }); + }); \ No newline at end of file diff --git a/test/unit/admin-dao-test.js b/test/unit/admin-dao-test.js index 06811b2..2550374 100644 --- a/test/unit/admin-dao-test.js +++ b/test/unit/admin-dao-test.js @@ -1,146 +1,142 @@ -define(function(require) { - 'use strict'; +'use strict'; - var RestDAO = require('js/dao/rest-dao'), - AdminDAO = require('js/dao/admin-dao'), - expect = chai.expect; +var RestDAO = require('../../src/js/dao/rest-dao'), + AdminDAO = require('../../src/js/dao/admin-dao'); - describe('Admin DAO unit tests', function() { +describe('Admin DAO unit tests', function() { - var adminDao, restDaoStub, - emailAddress = 'test@example.com', - password = 'secret'; + var adminDao, restDaoStub, + emailAddress = 'test@example.com', + password = 'secret'; - beforeEach(function() { - restDaoStub = sinon.createStubInstance(RestDAO); - adminDao = new AdminDAO(restDaoStub); - }); + beforeEach(function() { + restDaoStub = sinon.createStubInstance(RestDAO); + adminDao = new AdminDAO(restDaoStub); + }); - afterEach(function() {}); + afterEach(function() {}); - describe('createUser', function() { - it('should fail due to incomplete args', function(done) { - var opt = { - emailAddress: emailAddress - }; + describe('createUser', function() { + it('should fail due to incomplete args', function(done) { + var opt = { + emailAddress: emailAddress + }; - adminDao.createUser(opt, function(err) { - expect(err).to.exist; - done(); - }); - }); - - it('should fail if user already exists', function(done) { - var opt = { - emailAddress: emailAddress, - password: password, - phone: '12345' - }; - - restDaoStub.post.withArgs(opt, '/user').yields({ - code: 409 - }); - - adminDao.createUser(opt, function(err) { - expect(err.message).to.contain('already taken'); - expect(restDaoStub.post.calledOnce).to.be.true; - done(); - }); - }); - - it('should fail due to unknown error', function(done) { - var opt = { - emailAddress: emailAddress, - password: password, - phone: '12345' - }; - - restDaoStub.post.withArgs(opt, '/user').yields(new Error()); - - adminDao.createUser(opt, function(err) { - expect(err).to.exist; - expect(restDaoStub.post.calledOnce).to.be.true; - done(); - }); - }); - - it('should work', function(done) { - var opt = { - emailAddress: emailAddress, - password: password, - phone: '12345' - }; - - restDaoStub.post.withArgs(opt, '/user').yields(); - - adminDao.createUser(opt, function(err) { - expect(err).to.not.exist; - expect(restDaoStub.post.calledOnce).to.be.true; - done(); - }); + adminDao.createUser(opt, function(err) { + expect(err).to.exist; + done(); }); }); - describe('validateUser', function() { - it('should fail due to incomplete args', function(done) { - var opt = { - emailAddress: emailAddress - }; + it('should fail if user already exists', function(done) { + var opt = { + emailAddress: emailAddress, + password: password, + phone: '12345' + }; - adminDao.validateUser(opt, function(err) { - expect(err).to.exist; - done(); - }); + restDaoStub.post.withArgs(opt, '/user').yields({ + code: 409 }); - it('should fail due to error in rest api', function(done) { - var opt = { - emailAddress: emailAddress, - token: 'H45Z6D' - }; - - restDaoStub.post.withArgs(opt, '/user/validate').yields(new Error()); - - adminDao.validateUser(opt, function(err) { - expect(err).to.exist; - expect(restDaoStub.post.calledOnce).to.be.true; - done(); - }); - }); - - it('should work with no error object', function(done) { - var opt = { - emailAddress: emailAddress, - token: 'H45Z6D' - }; - - restDaoStub.post.withArgs(opt, '/user/validate').yields(); - - adminDao.validateUser(opt, function(err) { - expect(err).to.not.exist; - expect(restDaoStub.post.calledOnce).to.be.true; - done(); - }); - }); - - it('should work with 202', function(done) { - var opt = { - emailAddress: emailAddress, - token: 'H45Z6D' - }; - - restDaoStub.post.withArgs(opt, '/user/validate').yields({ - code: 202 - }); - - adminDao.validateUser(opt, function(err) { - expect(err).to.not.exist; - expect(restDaoStub.post.calledOnce).to.be.true; - done(); - }); + adminDao.createUser(opt, function(err) { + expect(err.message).to.contain('already taken'); + expect(restDaoStub.post.calledOnce).to.be.true; + done(); }); }); + it('should fail due to unknown error', function(done) { + var opt = { + emailAddress: emailAddress, + password: password, + phone: '12345' + }; + + restDaoStub.post.withArgs(opt, '/user').yields(new Error()); + + adminDao.createUser(opt, function(err) { + expect(err).to.exist; + expect(restDaoStub.post.calledOnce).to.be.true; + done(); + }); + }); + + it('should work', function(done) { + var opt = { + emailAddress: emailAddress, + password: password, + phone: '12345' + }; + + restDaoStub.post.withArgs(opt, '/user').yields(); + + adminDao.createUser(opt, function(err) { + expect(err).to.not.exist; + expect(restDaoStub.post.calledOnce).to.be.true; + done(); + }); + }); + }); + + describe('validateUser', function() { + it('should fail due to incomplete args', function(done) { + var opt = { + emailAddress: emailAddress + }; + + adminDao.validateUser(opt, function(err) { + expect(err).to.exist; + done(); + }); + }); + + it('should fail due to error in rest api', function(done) { + var opt = { + emailAddress: emailAddress, + token: 'H45Z6D' + }; + + restDaoStub.post.withArgs(opt, '/user/validate').yields(new Error()); + + adminDao.validateUser(opt, function(err) { + expect(err).to.exist; + expect(restDaoStub.post.calledOnce).to.be.true; + done(); + }); + }); + + it('should work with no error object', function(done) { + var opt = { + emailAddress: emailAddress, + token: 'H45Z6D' + }; + + restDaoStub.post.withArgs(opt, '/user/validate').yields(); + + adminDao.validateUser(opt, function(err) { + expect(err).to.not.exist; + expect(restDaoStub.post.calledOnce).to.be.true; + done(); + }); + }); + + it('should work with 202', function(done) { + var opt = { + emailAddress: emailAddress, + token: 'H45Z6D' + }; + + restDaoStub.post.withArgs(opt, '/user/validate').yields({ + code: 202 + }); + + adminDao.validateUser(opt, function(err) { + expect(err).to.not.exist; + expect(restDaoStub.post.calledOnce).to.be.true; + done(); + }); + }); }); }); \ No newline at end of file diff --git a/test/unit/app-controller-test.js b/test/unit/app-controller-test.js index 21f622b..b260ab2 100644 --- a/test/unit/app-controller-test.js +++ b/test/unit/app-controller-test.js @@ -1,212 +1,209 @@ -define(function(require) { - 'use strict'; +'use strict'; - var controller = require('js/app-controller'), - EmailDAO = require('js/dao/email-dao'), - OutboxBO = require('js/bo/outbox'), - DeviceStorageDAO = require('js/dao/devicestorage-dao'), - UpdateHandler = require('js/util/update/update-handler'), - Auth = require('js/bo/auth'), - expect = chai.expect; +var controller = require('../../src/js/app-controller'), + EmailDAO = require('../../src/js/dao/email-dao'), + OutboxBO = require('../../src/js/bo/outbox'), + DeviceStorageDAO = require('../../src/js/dao/devicestorage-dao'), + UpdateHandler = require('../../src/js/util/update/update-handler'), + Auth = require('../../src/js/bo/auth'); - describe('App Controller unit tests', function() { - var emailDaoStub, outboxStub, updateHandlerStub, appConfigStoreStub, devicestorageStub, isOnlineStub, authStub; +describe('App Controller unit tests', function() { + var emailDaoStub, outboxStub, updateHandlerStub, appConfigStoreStub, devicestorageStub, isOnlineStub, authStub; + + beforeEach(function() { + controller._emailDao = emailDaoStub = sinon.createStubInstance(EmailDAO); + controller._outboxBo = outboxStub = sinon.createStubInstance(OutboxBO); + controller._appConfigStore = appConfigStoreStub = sinon.createStubInstance(DeviceStorageDAO); + controller._userStorage = devicestorageStub = sinon.createStubInstance(DeviceStorageDAO); + controller._updateHandler = updateHandlerStub = sinon.createStubInstance(UpdateHandler); + controller._auth = authStub = sinon.createStubInstance(Auth); + + isOnlineStub = sinon.stub(controller, 'isOnline'); + }); + + afterEach(function() { + isOnlineStub.restore(); + }); + + describe('buildModules', function() { + it('should work', function() { + controller.buildModules({ + onError: function() {} + }); + expect(controller._appConfigStore).to.exist; + expect(controller._auth).to.exist; + expect(controller._userStorage).to.exist; + expect(controller._invitationDao).to.exist; + expect(controller._keychain).to.exist; + expect(controller._pgp).to.exist; + expect(controller._pgpbuilder).to.exist; + expect(controller._emailDao).to.exist; + expect(controller._outboxBo).to.exist; + expect(controller._updateHandler).to.exist; + }); + }); + + describe('start', function() { + it('should not explode', function(done) { + controller.start({ + onError: function() {} + }, function(err) { + expect(err).to.not.exist; + done(); + }); + }); + }); + + describe('onDisconnect', function() { + it('should work', function() { + controller.onDisconnect(); + + expect(emailDaoStub.onDisconnect.calledOnce).to.be.true; + }); + }); + + describe('logout', function() { + it('should work', function(done) { + authStub.logout.yields(); + emailDaoStub.onDisconnect.yields(new Error()); + + controller.onError = function(err) { + expect(err).to.exist; + expect(authStub.logout.calledOnce).to.be.true; + expect(emailDaoStub.onDisconnect.calledOnce).to.be.true; + done(); + }; + + controller.logout(); + }); + }); + + describe('onConnect', function() { + beforeEach(function() { + controller._emailDao._account = {}; + }); + + it('should not connect if offline', function(done) { + isOnlineStub.returns(false); + + controller.onConnect(function(err) { + expect(err).to.not.exist; + done(); + }); + }); + + it('should not connect if account is not initialized', function(done) { + controller._emailDao._account = null; + + controller.onConnect(function(err) { + expect(err).to.not.exist; + done(); + }); + }); + + it('should fail due to error in auth.getCredentials', function(done) { + isOnlineStub.returns(true); + authStub.getCredentials.yields(new Error()); + + controller.onConnect(function(err) { + expect(err).to.exist; + expect(authStub.getCredentials.calledOnce).to.be.true; + done(); + }); + }); + + it('should work', function(done) { + isOnlineStub.returns(true); + authStub.getCredentials.yields(null, { + emailAddress: 'asdf@example.com', + oauthToken: 'token', + sslCert: 'cert', + imap: {}, + smtp: {} + }); + emailDaoStub.onConnect.yields(); + + controller.onConnect(function(err) { + expect(err).to.not.exist; + expect(authStub.getCredentials.calledOnce).to.be.true; + expect(emailDaoStub.onConnect.calledOnce).to.be.true; + done(); + }); + }); + }); + + describe('init', function() { + var onConnectStub, emailAddress; beforeEach(function() { - controller._emailDao = emailDaoStub = sinon.createStubInstance(EmailDAO); - controller._outboxBo = outboxStub = sinon.createStubInstance(OutboxBO); - controller._appConfigStore = appConfigStoreStub = sinon.createStubInstance(DeviceStorageDAO); - controller._userStorage = devicestorageStub = sinon.createStubInstance(DeviceStorageDAO); - controller._updateHandler = updateHandlerStub = sinon.createStubInstance(UpdateHandler); - controller._auth = authStub = sinon.createStubInstance(Auth); + emailAddress = 'alice@bob.com'; - isOnlineStub = sinon.stub(controller, 'isOnline'); + // onConnect + onConnectStub = sinon.stub(controller, 'onConnect'); }); afterEach(function() { - isOnlineStub.restore(); + onConnectStub.restore(); }); - describe('buildModules', function() { - it('should work', function() { - controller.buildModules({ - onError: function() {} - }); - expect(controller._appConfigStore).to.exist; - expect(controller._auth).to.exist; - expect(controller._userStorage).to.exist; - expect(controller._invitationDao).to.exist; - expect(controller._keychain).to.exist; - expect(controller._pgp).to.exist; - expect(controller._pgpbuilder).to.exist; - expect(controller._emailDao).to.exist; - expect(controller._outboxBo).to.exist; - expect(controller._updateHandler).to.exist; + it('should fail due to error in storage initialization', function(done) { + devicestorageStub.init.withArgs(undefined).yields({}); + + controller.init({}, function(err, keypair) { + expect(err).to.exist; + expect(keypair).to.not.exist; + expect(devicestorageStub.init.calledOnce).to.be.true; + expect(updateHandlerStub.update.calledOnce).to.be.false; + done(); }); }); - describe('start', function() { - it('should not explode', function(done) { - controller.start({ - onError: function() {} - }, function(err) { - expect(err).to.not.exist; - done(); - }); + it('should fail due to error in update handler', function(done) { + devicestorageStub.init.yields(); + updateHandlerStub.update.yields({}); + + controller.init({ + emailAddress: emailAddress + }, function(err, keypair) { + expect(err).to.exist; + expect(keypair).to.not.exist; + expect(updateHandlerStub.update.calledOnce).to.be.true; + expect(devicestorageStub.init.calledOnce).to.be.true; + done(); }); }); - describe('onDisconnect', function() { - it('should work', function() { - controller.onDisconnect(); + it('should fail due to error in emailDao.init', function(done) { + devicestorageStub.init.yields(); + updateHandlerStub.update.yields(); + emailDaoStub.init.yields({}); - expect(emailDaoStub.onDisconnect.calledOnce).to.be.true; + controller.init({ + emailAddress: emailAddress + }, function(err, keypair) { + expect(err).to.exist; + expect(keypair).to.not.exist; + expect(updateHandlerStub.update.calledOnce).to.be.true; + expect(emailDaoStub.init.calledOnce).to.be.true; + expect(devicestorageStub.init.calledOnce).to.be.true; + done(); }); }); - describe('logout', function() { - it('should work', function(done) { - authStub.logout.yields(); - emailDaoStub.onDisconnect.yields(new Error()); + it('should work and return a keypair', function(done) { + devicestorageStub.init.withArgs(emailAddress).yields(); + emailDaoStub.init.yields(null, {}); + updateHandlerStub.update.yields(); - controller.onError = function(err) { - expect(err).to.exist; - expect(authStub.logout.calledOnce).to.be.true; - expect(emailDaoStub.onDisconnect.calledOnce).to.be.true; - done(); - }; - - controller.logout(); - }); - }); - - describe('onConnect', function() { - beforeEach(function() { - controller._emailDao._account = {}; - }); - - it('should not connect if offline', function(done) { - isOnlineStub.returns(false); - - controller.onConnect(function(err) { - expect(err).to.not.exist; - done(); - }); - }); - - it('should not connect if account is not initialized', function(done) { - controller._emailDao._account = null; - - controller.onConnect(function(err) { - expect(err).to.not.exist; - done(); - }); - }); - - it('should fail due to error in auth.getCredentials', function(done) { - isOnlineStub.returns(true); - authStub.getCredentials.yields(new Error()); - - controller.onConnect(function(err) { - expect(err).to.exist; - expect(authStub.getCredentials.calledOnce).to.be.true; - done(); - }); - }); - - it('should work', function(done) { - isOnlineStub.returns(true); - authStub.getCredentials.yields(null, { - emailAddress: 'asdf@example.com', - oauthToken: 'token', - sslCert: 'cert', - imap: {}, - smtp: {} - }); - emailDaoStub.onConnect.yields(); - - controller.onConnect(function(err) { - expect(err).to.not.exist; - expect(authStub.getCredentials.calledOnce).to.be.true; - expect(emailDaoStub.onConnect.calledOnce).to.be.true; - done(); - }); - }); - }); - - describe('init', function() { - var onConnectStub, emailAddress; - - beforeEach(function() { - emailAddress = 'alice@bob.com'; - - // onConnect - onConnectStub = sinon.stub(controller, 'onConnect'); - }); - - afterEach(function() { - onConnectStub.restore(); - }); - - it('should fail due to error in storage initialization', function(done) { - devicestorageStub.init.withArgs(undefined).yields({}); - - controller.init({}, function(err, keypair) { - expect(err).to.exist; - expect(keypair).to.not.exist; - expect(devicestorageStub.init.calledOnce).to.be.true; - expect(updateHandlerStub.update.calledOnce).to.be.false; - done(); - }); - }); - - it('should fail due to error in update handler', function(done) { - devicestorageStub.init.yields(); - updateHandlerStub.update.yields({}); - - controller.init({ - emailAddress: emailAddress - }, function(err, keypair) { - expect(err).to.exist; - expect(keypair).to.not.exist; - expect(updateHandlerStub.update.calledOnce).to.be.true; - expect(devicestorageStub.init.calledOnce).to.be.true; - done(); - }); - }); - - it('should fail due to error in emailDao.init', function(done) { - devicestorageStub.init.yields(); - updateHandlerStub.update.yields(); - emailDaoStub.init.yields({}); - - controller.init({ - emailAddress: emailAddress - }, function(err, keypair) { - expect(err).to.exist; - expect(keypair).to.not.exist; - expect(updateHandlerStub.update.calledOnce).to.be.true; - expect(emailDaoStub.init.calledOnce).to.be.true; - expect(devicestorageStub.init.calledOnce).to.be.true; - done(); - }); - }); - - it('should work and return a keypair', function(done) { - devicestorageStub.init.withArgs(emailAddress).yields(); - emailDaoStub.init.yields(null, {}); - updateHandlerStub.update.yields(); - - controller.init({ - emailAddress: emailAddress - }, function(err, keypair) { - expect(err).to.not.exist; - expect(keypair).to.exist; - expect(updateHandlerStub.update.calledOnce).to.be.true; - expect(emailDaoStub.init.calledOnce).to.be.true; - expect(devicestorageStub.init.calledOnce).to.be.true; - done(); - }); + controller.init({ + emailAddress: emailAddress + }, function(err, keypair) { + expect(err).to.not.exist; + expect(keypair).to.exist; + expect(updateHandlerStub.update.calledOnce).to.be.true; + expect(emailDaoStub.init.calledOnce).to.be.true; + expect(devicestorageStub.init.calledOnce).to.be.true; + done(); }); }); }); diff --git a/test/unit/auth-test.js b/test/unit/auth-test.js index 5df3c25..c3bea37 100644 --- a/test/unit/auth-test.js +++ b/test/unit/auth-test.js @@ -1,377 +1,374 @@ -define(function(require) { - 'use strict'; +'use strict'; - var Auth = require('js/bo/auth'), - OAuth = require('js/util/oauth'), - PGP = require('js/crypto/pgp'), - DeviceStorageDAO = require('js/dao/devicestorage-dao'), - expect = chai.expect; +var Auth = require('../../src/js/bo/auth'), + OAuth = require('../../src/js/util/oauth'), + PGP = require('../../src/js/crypto/pgp'), + DeviceStorageDAO = require('../../src/js/dao/devicestorage-dao'); - describe('Auth unit tests', function() { - // Constancts - var EMAIL_ADDR_DB_KEY = 'emailaddress'; - var USERNAME_DB_KEY = 'username'; - var REALNAME_DB_KEY = 'realname'; - var PASSWD_DB_KEY = 'password'; - var PROVIDER_DB_KEY = 'provider'; - var IMAP_DB_KEY = 'imap'; - var SMTP_DB_KEY = 'smtp'; - // SUT - var auth; +describe('Auth unit tests', function() { + // Constancts + var EMAIL_ADDR_DB_KEY = 'emailaddress'; + var USERNAME_DB_KEY = 'username'; + var REALNAME_DB_KEY = 'realname'; + var PASSWD_DB_KEY = 'password'; + var PROVIDER_DB_KEY = 'provider'; + var IMAP_DB_KEY = 'imap'; + var SMTP_DB_KEY = 'smtp'; + // SUT + var auth; - // Dependencies - var storageStub, oauthStub, pgpStub; + // Dependencies + var storageStub, oauthStub, pgpStub; - // test data - var emailAddress = 'bla@blubb.com'; - var password = 'passwordpasswordpassword'; - var encryptedPassword = 'pgppasswordpgppassword'; - var oauthToken = 'tokentokentokentoken'; - var provider = 'gmail'; - var realname = 'Bla Blubb'; - var username = 'bla'; - var imap = { - host: 'mail.blablubb.com', - port: 123, - secure: true, - ca: 'PEMPEMPEMPEMPEMPEMPEMPEMPEMPEM' - }; - var smtp = { - host: 'mail.blablubb.com', - port: 456, - secure: true, - ca: 'PEMPEMPEMPEMPEMPEMPEMPEMPEMPEM' - }; + // test data + var emailAddress = 'bla@blubb.com'; + var password = 'passwordpasswordpassword'; + var encryptedPassword = 'pgppasswordpgppassword'; + var oauthToken = 'tokentokentokentoken'; + var provider = 'gmail'; + var realname = 'Bla Blubb'; + var username = 'bla'; + var imap = { + host: 'mail.blablubb.com', + port: 123, + secure: true, + ca: 'PEMPEMPEMPEMPEMPEMPEMPEMPEMPEM' + }; + var smtp = { + host: 'mail.blablubb.com', + port: 456, + secure: true, + ca: 'PEMPEMPEMPEMPEMPEMPEMPEMPEMPEM' + }; - beforeEach(function() { - storageStub = sinon.createStubInstance(DeviceStorageDAO); - oauthStub = sinon.createStubInstance(OAuth); - pgpStub = sinon.createStubInstance(PGP); - auth = new Auth(storageStub, oauthStub, pgpStub); + beforeEach(function() { + storageStub = sinon.createStubInstance(DeviceStorageDAO); + oauthStub = sinon.createStubInstance(OAuth); + pgpStub = sinon.createStubInstance(PGP); + auth = new Auth(storageStub, oauthStub, pgpStub); + }); + + describe('#getCredentials', function() { + it('should load credentials and retrieve credentials from cfg', function(done) { + storageStub.listItems.withArgs(EMAIL_ADDR_DB_KEY, 0, null).yieldsAsync(null, [emailAddress]); + storageStub.listItems.withArgs(PASSWD_DB_KEY, 0, null).yieldsAsync(null, [encryptedPassword]); + storageStub.listItems.withArgs(PROVIDER_DB_KEY, 0, null).yieldsAsync(null, [provider]); + storageStub.listItems.withArgs(USERNAME_DB_KEY, 0, null).yieldsAsync(null, [username]); + storageStub.listItems.withArgs(REALNAME_DB_KEY, 0, null).yieldsAsync(null, [realname]); + storageStub.listItems.withArgs(IMAP_DB_KEY, 0, null).yieldsAsync(null, [imap]); + storageStub.listItems.withArgs(SMTP_DB_KEY, 0, null).yieldsAsync(null, [smtp]); + pgpStub.decrypt.withArgs(encryptedPassword, undefined).yields(null, password); + + auth.getCredentials(function(err, cred) { + expect(err).to.not.exist; + + expect(auth.provider).to.equal(provider); + expect(auth.emailAddress).to.equal(emailAddress); + expect(auth.password).to.equal(password); + + expect(cred.imap.host).to.equal(imap.host); + expect(cred.imap.port).to.equal(imap.port); + expect(cred.imap.secure).to.equal(imap.secure); + expect(cred.imap.ca).to.equal(imap.ca); + expect(cred.imap.auth.user).to.equal(username); + expect(cred.imap.auth.pass).to.equal(password); + + expect(cred.smtp.host).to.equal(smtp.host); + expect(cred.smtp.port).to.equal(smtp.port); + expect(cred.smtp.secure).to.equal(smtp.secure); + expect(cred.smtp.ca).to.equal(smtp.ca); + expect(cred.smtp.auth.user).to.equal(username); + expect(cred.smtp.auth.pass).to.equal(password); + + expect(storageStub.listItems.callCount).to.equal(7); + expect(pgpStub.decrypt.calledOnce).to.be.true; + + done(); + }); + }); + }); + + describe('#setCredentials', function() { + it('should set the credentials', function() { + auth.setCredentials({ + provider: 'albhsvadlbvsdalbsadflb', + emailAddress: emailAddress, + username: username, + realname: realname, + password: password, + imap: imap, + smtp: smtp + }); + + expect(auth.provider).to.equal('albhsvadlbvsdalbsadflb'); + expect(auth.emailAddress).to.equal(emailAddress); + expect(auth.username).to.equal(username); + expect(auth.realname).to.equal(realname); + expect(auth.password).to.equal(password); + expect(auth.smtp).to.equal(smtp); + expect(auth.imap).to.equal(imap); + expect(auth.credentialsDirty).to.be.true; }); - describe('#getCredentials', function() { - it('should load credentials and retrieve credentials from cfg', function(done) { - storageStub.listItems.withArgs(EMAIL_ADDR_DB_KEY, 0, null).yieldsAsync(null, [emailAddress]); - storageStub.listItems.withArgs(PASSWD_DB_KEY, 0, null).yieldsAsync(null, [encryptedPassword]); - storageStub.listItems.withArgs(PROVIDER_DB_KEY, 0, null).yieldsAsync(null, [provider]); - storageStub.listItems.withArgs(USERNAME_DB_KEY, 0, null).yieldsAsync(null, [username]); - storageStub.listItems.withArgs(REALNAME_DB_KEY, 0, null).yieldsAsync(null, [realname]); - storageStub.listItems.withArgs(IMAP_DB_KEY, 0, null).yieldsAsync(null, [imap]); - storageStub.listItems.withArgs(SMTP_DB_KEY, 0, null).yieldsAsync(null, [smtp]); - pgpStub.decrypt.withArgs(encryptedPassword, undefined).yields(null, password); + }); - auth.getCredentials(function(err, cred) { - expect(err).to.not.exist; + describe('#storeCredentials', function() { + it('should persist ALL the things!', function(done) { + auth.credentialsDirty = true; + auth.emailAddress = emailAddress; + auth.username = username; + auth.realname = realname; + auth.password = password; + auth.smtp = smtp; + auth.imap = imap; + auth.provider = provider; - expect(auth.provider).to.equal(provider); - expect(auth.emailAddress).to.equal(emailAddress); - expect(auth.password).to.equal(password); + storageStub.storeList.withArgs([encryptedPassword], PASSWD_DB_KEY).yieldsAsync(); + storageStub.storeList.withArgs([emailAddress], EMAIL_ADDR_DB_KEY).yieldsAsync(); + storageStub.storeList.withArgs([provider], PROVIDER_DB_KEY).yieldsAsync(); + storageStub.storeList.withArgs([username], USERNAME_DB_KEY).yieldsAsync(); + storageStub.storeList.withArgs([realname], REALNAME_DB_KEY).yieldsAsync(); + storageStub.storeList.withArgs([imap], IMAP_DB_KEY).yieldsAsync(); + storageStub.storeList.withArgs([smtp], SMTP_DB_KEY).yieldsAsync(); + pgpStub.encrypt.withArgs(password).yields(null, encryptedPassword); - expect(cred.imap.host).to.equal(imap.host); - expect(cred.imap.port).to.equal(imap.port); - expect(cred.imap.secure).to.equal(imap.secure); - expect(cred.imap.ca).to.equal(imap.ca); - expect(cred.imap.auth.user).to.equal(username); - expect(cred.imap.auth.pass).to.equal(password); + auth.storeCredentials(function(err) { + expect(err).to.not.exist; - expect(cred.smtp.host).to.equal(smtp.host); - expect(cred.smtp.port).to.equal(smtp.port); - expect(cred.smtp.secure).to.equal(smtp.secure); - expect(cred.smtp.ca).to.equal(smtp.ca); - expect(cred.smtp.auth.user).to.equal(username); - expect(cred.smtp.auth.pass).to.equal(password); + expect(storageStub.storeList.callCount).to.equal(7); + expect(pgpStub.encrypt.calledOnce).to.be.true; - expect(storageStub.listItems.callCount).to.equal(7); - expect(pgpStub.decrypt.calledOnce).to.be.true; + done(); + }); + }); + }); - done(); - }); + describe('#getOAuthToken', function() { + it('should refresh token with known email address', function(done) { + auth.emailAddress = emailAddress; + auth.oauthToken = 'oldToken'; + + oauthStub.refreshToken.withArgs({ + emailAddress: emailAddress, + oldToken: 'oldToken' + }).yieldsAsync(null, oauthToken); + + auth.getOAuthToken(function(err) { + expect(err).to.not.exist; + expect(auth.emailAddress).to.equal(emailAddress); + expect(auth.oauthToken).to.equal(oauthToken); + + expect(oauthStub.refreshToken.calledOnce).to.be.true; + + done(); }); }); - describe('#setCredentials', function() { - it('should set the credentials', function() { - auth.setCredentials({ - provider: 'albhsvadlbvsdalbsadflb', - emailAddress: emailAddress, - username: username, - realname: realname, - password: password, - imap: imap, - smtp: smtp - }); + it('should fetch token with known email address', function(done) { + auth.emailAddress = emailAddress; + oauthStub.getOAuthToken.withArgs(emailAddress).yieldsAsync(null, oauthToken); - expect(auth.provider).to.equal('albhsvadlbvsdalbsadflb'); + auth.getOAuthToken(function(err) { + expect(err).to.not.exist; expect(auth.emailAddress).to.equal(emailAddress); + expect(auth.oauthToken).to.equal(oauthToken); + + expect(oauthStub.getOAuthToken.calledOnce).to.be.true; + + done(); + }); + }); + + it('should fetch token with unknown email address', function(done) { + oauthStub.getOAuthToken.withArgs(undefined).yieldsAsync(null, oauthToken); + oauthStub.queryEmailAddress.withArgs(oauthToken).yieldsAsync(null, emailAddress); + + auth.getOAuthToken(function(err) { + expect(err).to.not.exist; + expect(auth.emailAddress).to.equal(emailAddress); + expect(auth.oauthToken).to.equal(oauthToken); + + expect(oauthStub.getOAuthToken.calledOnce).to.be.true; + expect(oauthStub.queryEmailAddress.calledOnce).to.be.true; + + done(); + }); + }); + + it('should fail when email address fetch fails', function(done) { + oauthStub.getOAuthToken.yieldsAsync(null, oauthToken); + oauthStub.queryEmailAddress.yieldsAsync(new Error()); + + auth.getOAuthToken(function(err) { + expect(err).to.exist; + expect(auth.emailAddress).to.not.exist; + expect(auth.oauthToken).to.not.exist; + + expect(oauthStub.getOAuthToken.calledOnce).to.be.true; + expect(oauthStub.queryEmailAddress.calledOnce).to.be.true; + + done(); + }); + }); + + it('should fail when oauth fetch fails', function(done) { + oauthStub.getOAuthToken.yieldsAsync(new Error()); + + auth.getOAuthToken(function(err) { + expect(err).to.exist; + expect(auth.emailAddress).to.not.exist; + expect(auth.oauthToken).to.not.exist; + + expect(oauthStub.getOAuthToken.calledOnce).to.be.true; + expect(oauthStub.queryEmailAddress.called).to.be.false; + + done(); + }); + }); + }); + + describe('#_loadCredentials', function() { + it('should work', function(done) { + storageStub.listItems.withArgs(EMAIL_ADDR_DB_KEY, 0, null).yieldsAsync(null, [emailAddress]); + storageStub.listItems.withArgs(PASSWD_DB_KEY, 0, null).yieldsAsync(null, [encryptedPassword]); + storageStub.listItems.withArgs(PROVIDER_DB_KEY, 0, null).yieldsAsync(null, [provider]); + storageStub.listItems.withArgs(USERNAME_DB_KEY, 0, null).yieldsAsync(null, [username]); + storageStub.listItems.withArgs(REALNAME_DB_KEY, 0, null).yieldsAsync(null, [realname]); + storageStub.listItems.withArgs(IMAP_DB_KEY, 0, null).yieldsAsync(null, [imap]); + storageStub.listItems.withArgs(SMTP_DB_KEY, 0, null).yieldsAsync(null, [smtp]); + + auth._loadCredentials(function(err) { + expect(err).to.not.exist; + expect(auth.emailAddress).to.equal(emailAddress); + expect(auth.password).to.equal(encryptedPassword); + expect(auth.provider).to.equal(provider); + expect(auth.imap).to.equal(imap); + expect(auth.smtp).to.equal(smtp); expect(auth.username).to.equal(username); expect(auth.realname).to.equal(realname); - expect(auth.password).to.equal(password); - expect(auth.smtp).to.equal(smtp); - expect(auth.imap).to.equal(imap); - expect(auth.credentialsDirty).to.be.true; - }); - }); + expect(auth.passwordNeedsDecryption).to.be.true; - describe('#storeCredentials', function() { - it('should persist ALL the things!', function(done) { - auth.credentialsDirty = true; - auth.emailAddress = emailAddress; - auth.username = username; - auth.realname = realname; - auth.password = password; - auth.smtp = smtp; - auth.imap = imap; - auth.provider = provider; + expect(storageStub.listItems.callCount).to.equal(7); - storageStub.storeList.withArgs([encryptedPassword], PASSWD_DB_KEY).yieldsAsync(); - storageStub.storeList.withArgs([emailAddress], EMAIL_ADDR_DB_KEY).yieldsAsync(); - storageStub.storeList.withArgs([provider], PROVIDER_DB_KEY).yieldsAsync(); - storageStub.storeList.withArgs([username], USERNAME_DB_KEY).yieldsAsync(); - storageStub.storeList.withArgs([realname], REALNAME_DB_KEY).yieldsAsync(); - storageStub.storeList.withArgs([imap], IMAP_DB_KEY).yieldsAsync(); - storageStub.storeList.withArgs([smtp], SMTP_DB_KEY).yieldsAsync(); - pgpStub.encrypt.withArgs(password).yields(null, encryptedPassword); - - auth.storeCredentials(function(err) { - expect(err).to.not.exist; - - expect(storageStub.storeList.callCount).to.equal(7); - expect(pgpStub.encrypt.calledOnce).to.be.true; - - done(); - }); + done(); }); }); - describe('#getOAuthToken', function() { - it('should refresh token with known email address', function(done) { - auth.emailAddress = emailAddress; - auth.oauthToken = 'oldToken'; + it('should fail', function(done) { + storageStub.listItems.yieldsAsync(new Error()); - oauthStub.refreshToken.withArgs({ - emailAddress: emailAddress, - oldToken: 'oldToken' - }).yieldsAsync(null, oauthToken); + auth._loadCredentials(function(err) { + expect(err).to.exist; + expect(auth.emailAddress).to.not.exist; + expect(auth.password).to.not.exist; + expect(auth.provider).to.not.exist; + expect(auth.imap).to.not.exist; + expect(auth.smtp).to.not.exist; + expect(auth.username).to.not.exist; + expect(auth.realname).to.not.exist; - auth.getOAuthToken(function(err) { - expect(err).to.not.exist; - expect(auth.emailAddress).to.equal(emailAddress); - expect(auth.oauthToken).to.equal(oauthToken); + expect(storageStub.listItems.calledOnce).to.be.true; - expect(oauthStub.refreshToken.calledOnce).to.be.true; - - done(); - }); - }); - - it('should fetch token with known email address', function(done) { - auth.emailAddress = emailAddress; - oauthStub.getOAuthToken.withArgs(emailAddress).yieldsAsync(null, oauthToken); - - auth.getOAuthToken(function(err) { - expect(err).to.not.exist; - expect(auth.emailAddress).to.equal(emailAddress); - expect(auth.oauthToken).to.equal(oauthToken); - - expect(oauthStub.getOAuthToken.calledOnce).to.be.true; - - done(); - }); - }); - - it('should fetch token with unknown email address', function(done) { - oauthStub.getOAuthToken.withArgs(undefined).yieldsAsync(null, oauthToken); - oauthStub.queryEmailAddress.withArgs(oauthToken).yieldsAsync(null, emailAddress); - - auth.getOAuthToken(function(err) { - expect(err).to.not.exist; - expect(auth.emailAddress).to.equal(emailAddress); - expect(auth.oauthToken).to.equal(oauthToken); - - expect(oauthStub.getOAuthToken.calledOnce).to.be.true; - expect(oauthStub.queryEmailAddress.calledOnce).to.be.true; - - done(); - }); - }); - - it('should fail when email address fetch fails', function(done) { - oauthStub.getOAuthToken.yieldsAsync(null, oauthToken); - oauthStub.queryEmailAddress.yieldsAsync(new Error()); - - auth.getOAuthToken(function(err) { - expect(err).to.exist; - expect(auth.emailAddress).to.not.exist; - expect(auth.oauthToken).to.not.exist; - - expect(oauthStub.getOAuthToken.calledOnce).to.be.true; - expect(oauthStub.queryEmailAddress.calledOnce).to.be.true; - - done(); - }); - }); - - it('should fail when oauth fetch fails', function(done) { - oauthStub.getOAuthToken.yieldsAsync(new Error()); - - auth.getOAuthToken(function(err) { - expect(err).to.exist; - expect(auth.emailAddress).to.not.exist; - expect(auth.oauthToken).to.not.exist; - - expect(oauthStub.getOAuthToken.calledOnce).to.be.true; - expect(oauthStub.queryEmailAddress.called).to.be.false; - - done(); - }); + done(); }); }); + }); - describe('#_loadCredentials', function() { - it('should work', function(done) { - storageStub.listItems.withArgs(EMAIL_ADDR_DB_KEY, 0, null).yieldsAsync(null, [emailAddress]); - storageStub.listItems.withArgs(PASSWD_DB_KEY, 0, null).yieldsAsync(null, [encryptedPassword]); - storageStub.listItems.withArgs(PROVIDER_DB_KEY, 0, null).yieldsAsync(null, [provider]); - storageStub.listItems.withArgs(USERNAME_DB_KEY, 0, null).yieldsAsync(null, [username]); - storageStub.listItems.withArgs(REALNAME_DB_KEY, 0, null).yieldsAsync(null, [realname]); - storageStub.listItems.withArgs(IMAP_DB_KEY, 0, null).yieldsAsync(null, [imap]); - storageStub.listItems.withArgs(SMTP_DB_KEY, 0, null).yieldsAsync(null, [smtp]); + describe('#handleCertificateUpdate', function() { + var storeCredentialsStub; + var dummyCert = 'cert'; - auth._loadCredentials(function(err) { - expect(err).to.not.exist; - expect(auth.emailAddress).to.equal(emailAddress); - expect(auth.password).to.equal(encryptedPassword); - expect(auth.provider).to.equal(provider); - expect(auth.imap).to.equal(imap); - expect(auth.smtp).to.equal(smtp); - expect(auth.username).to.equal(username); - expect(auth.realname).to.equal(realname); + function onConnectDummy() {} - expect(auth.passwordNeedsDecryption).to.be.true; - - expect(storageStub.listItems.callCount).to.equal(7); - - done(); - }); - }); - - it('should fail', function(done) { - storageStub.listItems.yieldsAsync(new Error()); - - auth._loadCredentials(function(err) { - expect(err).to.exist; - expect(auth.emailAddress).to.not.exist; - expect(auth.password).to.not.exist; - expect(auth.provider).to.not.exist; - expect(auth.imap).to.not.exist; - expect(auth.smtp).to.not.exist; - expect(auth.username).to.not.exist; - expect(auth.realname).to.not.exist; - - expect(storageStub.listItems.calledOnce).to.be.true; - - done(); - }); - }); + beforeEach(function() { + storeCredentialsStub = sinon.stub(auth, 'storeCredentials'); }); - describe('#handleCertificateUpdate', function() { - var storeCredentialsStub; - var dummyCert = 'cert'; + it('should work for Trust on first use', function(done) { + auth.imap = {}; + storeCredentialsStub.yields(); - function onConnectDummy() {} + function callback(err) { + expect(err).to.not.exist; + expect(storeCredentialsStub.callCount).to.equal(1); + done(); + } + auth.handleCertificateUpdate('imap', onConnectDummy, callback, dummyCert); + }); - beforeEach(function() { - storeCredentialsStub = sinon.stub(auth, 'storeCredentials'); - }); + it('should work for stored cert', function() { + auth.imap = { + ca: dummyCert + }; + storeCredentialsStub.yields(); - it('should work for Trust on first use', function(done) { - auth.imap = {}; - storeCredentialsStub.yields(); + auth.handleCertificateUpdate('imap', onConnectDummy, onConnectDummy, dummyCert); + expect(storeCredentialsStub.callCount).to.equal(0); + }); - function callback(err) { - expect(err).to.not.exist; - expect(storeCredentialsStub.callCount).to.equal(1); - done(); - } - auth.handleCertificateUpdate('imap', onConnectDummy, callback, dummyCert); - }); + it('should work for pinned cert', function(done) { + auth.imap = { + ca: 'other', + pinned: true + }; + storeCredentialsStub.yields(); - it('should work for stored cert', function() { - auth.imap = { - ca: dummyCert - }; - storeCredentialsStub.yields(); - - auth.handleCertificateUpdate('imap', onConnectDummy, onConnectDummy, dummyCert); + function callback(err) { + expect(err).to.exist; + expect(err.message).to.exist; expect(storeCredentialsStub.callCount).to.equal(0); - }); + done(); + } + auth.handleCertificateUpdate('imap', onConnectDummy, callback, dummyCert); + }); - it('should work for pinned cert', function(done) { - auth.imap = { - ca: 'other', - pinned: true - }; - storeCredentialsStub.yields(); + it('should work for updated cert', function(done) { + auth.imap = { + ca: 'other' + }; + storeCredentialsStub.yields(); - function callback(err) { + function callback(err) { + if (err && err.callback) { expect(err).to.exist; expect(err.message).to.exist; expect(storeCredentialsStub.callCount).to.equal(0); + err.callback(true); + } else { + expect(storeCredentialsStub.callCount).to.equal(1); done(); } - auth.handleCertificateUpdate('imap', onConnectDummy, callback, dummyCert); - }); + } - it('should work for updated cert', function(done) { - auth.imap = { - ca: 'other' - }; - storeCredentialsStub.yields(); + function onConnect(callback) { + callback(); + } - function callback(err) { - if (err && err.callback) { - expect(err).to.exist; - expect(err.message).to.exist; - expect(storeCredentialsStub.callCount).to.equal(0); - err.callback(true); - } else { - expect(storeCredentialsStub.callCount).to.equal(1); - done(); - } - } + auth.handleCertificateUpdate('imap', onConnect, callback, dummyCert); + }); + }); - function onConnect(callback) { - callback(); - } + describe('#logout', function() { + it('should fail to to error in calling db clear', function(done) { + storageStub.clear.yields(new Error()); - auth.handleCertificateUpdate('imap', onConnect, callback, dummyCert); + auth.logout(function(err) { + expect(err).to.exist; + done(); }); }); - describe('#logout', function() { - it('should fail to to error in calling db clear', function(done) { - storageStub.clear.yields(new Error()); + it('should work', function(done) { + storageStub.clear.yields(); - auth.logout(function(err) { - expect(err).to.exist; - done(); - }); - }); - - it('should work', function(done) { - storageStub.clear.yields(); - - auth.logout(function(err) { - expect(err).to.not.exist; - expect(auth.password).to.be.undefined; - expect(auth.initialized).to.be.undefined; - expect(auth.credentialsDirty).to.be.undefined; - expect(auth.passwordNeedsDecryption).to.be.undefined; - done(); - }); + auth.logout(function(err) { + expect(err).to.not.exist; + expect(auth.password).to.be.undefined; + expect(auth.initialized).to.be.undefined; + expect(auth.credentialsDirty).to.be.undefined; + expect(auth.passwordNeedsDecryption).to.be.undefined; + done(); }); }); }); diff --git a/test/unit/backbutton-handler-test.js b/test/unit/backbutton-handler-test.js index 3e312b3..66fc05b 100644 --- a/test/unit/backbutton-handler-test.js +++ b/test/unit/backbutton-handler-test.js @@ -1,67 +1,64 @@ -define(function(require) { - 'use strict'; +'use strict'; - var btnHandler = require('js/util/backbutton-handler'), - expect = chai.expect; +var btnHandler = require('../../src/js/util/backbutton-handler'); - describe('Backbutton Handler', function() { - chai.Assertion.includeStack = true; +describe('Backbutton Handler', function() { + chai.Assertion.includeStack = true; - var scope, event; + var scope, event; - beforeEach(function() { - scope = { - state: {}, - $apply: function() {} - }; + beforeEach(function() { + scope = { + state: {}, + $apply: function() {} + }; - event = new CustomEvent('backbutton'); + event = new CustomEvent('backbutton'); - // this is a precondition for the test. throw an exception - // if this would produce side effects - expect(navigator.app).to.not.exist; - navigator.app = {}; + // this is a precondition for the test. throw an exception + // if this would produce side effects + expect(navigator.app).to.not.exist; + navigator.app = {}; - btnHandler.attachHandler(scope); - btnHandler.start(); - }); + btnHandler.attachHandler(scope); + btnHandler.start(); + }); - afterEach(function() { - btnHandler.stop(); - delete navigator.app; - }); + afterEach(function() { + btnHandler.stop(); + delete navigator.app; + }); - it('should close lightbox', function() { - scope.state.lightbox = 'asd'; - document.dispatchEvent(event); - expect(scope.state.lightbox).to.be.undefined; - }); + it('should close lightbox', function() { + scope.state.lightbox = 'asd'; + document.dispatchEvent(event); + expect(scope.state.lightbox).to.be.undefined; + }); - it('should close reader', function() { - scope.state.read = { - open: true, - toggle: function(state) { - scope.state.read.open = state; - } - }; - document.dispatchEvent(event); - expect(scope.state.read.open).to.be.false; - }); + it('should close reader', function() { + scope.state.read = { + open: true, + toggle: function(state) { + scope.state.read.open = state; + } + }; + document.dispatchEvent(event); + expect(scope.state.read.open).to.be.false; + }); - it('should close navigation', function() { - scope.state.nav = { - open: true, - toggle: function(state) { - scope.state.nav.open = state; - } - }; - document.dispatchEvent(event); - expect(scope.state.nav.open).to.be.false; - }); + it('should close navigation', function() { + scope.state.nav = { + open: true, + toggle: function(state) { + scope.state.nav.open = state; + } + }; + document.dispatchEvent(event); + expect(scope.state.nav.open).to.be.false; + }); - it('should close app', function(done) { - navigator.app.exitApp = done; - document.dispatchEvent(event); - }); + it('should close app', function(done) { + navigator.app.exitApp = done; + document.dispatchEvent(event); }); }); \ No newline at end of file diff --git a/test/unit/connection-doctor-test.js b/test/unit/connection-doctor-test.js index 1ffeb08..7a50499 100644 --- a/test/unit/connection-doctor-test.js +++ b/test/unit/connection-doctor-test.js @@ -1,413 +1,410 @@ -define(function(require) { - 'use strict'; +'use strict'; - var ConnectionDoctor = require('js/util/connection-doctor'), - TCPSocket = require('tcp-socket'), - ImapClient = require('imap-client'), - SmtpClient = require('smtpclient'), - cfg = require('js/app-config').config, - expect = chai.expect; +var TCPSocket = require('tcp-socket'), + ImapClient = require('imap-client'), + SmtpClient = require('wo-smtpclient'), + ConnectionDoctor = require('../../src/js/util/connection-doctor'), + cfg = require('../../src/js/app-config').config; - describe('Connection Doctor', function() { - var doctor; - var socketStub, imapStub, smtpStub, credentials; +describe('Connection Doctor', function() { + var doctor; + var socketStub, imapStub, smtpStub, credentials; - beforeEach(function() { - // - // Stubs - // + beforeEach(function() { + // + // Stubs + // - // there is no socket shim for for this use case, use dummy object - socketStub = { - close: function() { - this.onclose(); + // there is no socket shim for for this use case, use dummy object + socketStub = { + close: function() { + this.onclose(); + } + }; + + imapStub = sinon.createStubInstance(ImapClient); + smtpStub = sinon.createStubInstance(SmtpClient); + + // + // Fixture + // + credentials = { + imap: { + host: 'asd', + port: 1234, + secure: true, + ca: 'cert' + }, + smtp: { + host: 'qwe', + port: 5678, + secure: false, + ca: 'cert' + }, + username: 'username', + password: 'password' + }; + + sinon.stub(TCPSocket, 'open').returns(socketStub); // convenience constructors suck + + // + // Setup SUT + // + doctor = new ConnectionDoctor(); + doctor.configure(credentials); + doctor._imap = imapStub; + doctor._smtp = smtpStub; + }); + + afterEach(function() { + TCPSocket.open.restore(); + }); + + describe('#_checkOnline', function() { + it('should check if browser is online', function(done) { + doctor._checkOnline(function(error) { + if (navigator.onLine) { + expect(error).to.not.exist; + } else { + expect(error).to.exist; + expect(error.code).to.equal(ConnectionDoctor.OFFLINE); } - }; + done(); + }); + }); + }); - imapStub = sinon.createStubInstance(ImapClient); - smtpStub = sinon.createStubInstance(SmtpClient); + describe('#_checkReachable', function() { + it('should be able to reach the host w/o cert', function(done) { + credentials.imap.ca = undefined; - // - // Fixture - // - credentials = { - imap: { - host: 'asd', - port: 1234, - secure: true, - ca: 'cert' - }, - smtp: { - host: 'qwe', - port: 5678, - secure: false, - ca: 'cert' - }, - username: 'username', - password: 'password' - }; + doctor._checkReachable(credentials.imap, function(error) { + expect(error).to.not.exist; + expect(TCPSocket.open.calledOnce).to.be.true; + expect(TCPSocket.open.calledWith(credentials.imap.host, credentials.imap.port, { + binaryType: 'arraybuffer', + useSecureTransport: credentials.imap.secure, + ca: credentials.imap.ca + })).to.be.true; - sinon.stub(TCPSocket, 'open').returns(socketStub); // convenience constructors suck + done(); + }); - // - // Setup SUT - // - doctor = new ConnectionDoctor(); - doctor.configure(credentials); - doctor._imap = imapStub; - doctor._smtp = smtpStub; + socketStub.oncert(); + socketStub.onopen(); }); - afterEach(function() { - TCPSocket.open.restore(); + it('should catch Mozilla TCPSocket exception', function(done) { + // Mozilla forbids extensions to the TCPSocket object + Object.defineProperty(socketStub, 'oncert', { + set: function() { + throw 'Mozilla specific behavior'; + } + }); + + doctor._checkReachable(credentials.imap, function(error) { + expect(error).to.not.exist; + expect(TCPSocket.open.calledOnce).to.be.true; + expect(TCPSocket.open.calledWith(credentials.imap.host, credentials.imap.port, { + binaryType: 'arraybuffer', + useSecureTransport: credentials.imap.secure, + ca: credentials.imap.ca + })).to.be.true; + + done(); + }); + + socketStub.onopen(); }); - describe('#_checkOnline', function() { - it('should check if browser is online', function(done) { - doctor._checkOnline(function(error) { - if (navigator.onLine) { - expect(error).to.not.exist; - } else { - expect(error).to.exist; - expect(error.code).to.equal(ConnectionDoctor.OFFLINE); - } - done(); - }); + it('should fail w/ wrong cert', function(done) { + doctor._checkReachable(credentials.imap, function(error) { + expect(error).to.exist; + expect(error.code).to.equal(ConnectionDoctor.TLS_WRONG_CERT); + expect(TCPSocket.open.calledOnce).to.be.true; + expect(TCPSocket.open.calledWith(credentials.imap.host, credentials.imap.port, { + binaryType: 'arraybuffer', + useSecureTransport: credentials.imap.secure, + ca: credentials.imap.ca + })).to.be.true; + + done(); + }); + + socketStub.oncert(); + socketStub.onerror(); + socketStub.onclose(); + }); + + it('should fail w/ host unreachable', function(done) { + doctor._checkReachable(credentials.imap, function(error) { + expect(error).to.exist; + expect(error.code).to.equal(ConnectionDoctor.HOST_UNREACHABLE); + expect(TCPSocket.open.calledOnce).to.be.true; + + done(); + }); + + socketStub.onerror({ + data: new Error() + }); + socketStub.onclose(); + }); + + it('should fail w/ timeout', function(done) { + var origTimeout = cfg.connDocTimeout; // remember timeout from the config to reset it on done + cfg.connDocTimeout = 20; // set to 20ms for the test + + doctor._checkReachable(credentials.imap, function(error) { + expect(error).to.exist; + expect(error.code).to.equal(ConnectionDoctor.HOST_TIMEOUT); + expect(TCPSocket.open.calledOnce).to.be.true; + cfg.connDocTimeout = origTimeout; + + done(); + }); + }); + }); + + describe('#_checkImap', function() { + it('should perform IMAP login, list folders, logout', function(done) { + imapStub.login.yieldsAsync(); + imapStub.listWellKnownFolders.yieldsAsync(null, { + Inbox: [{}] + }); + imapStub.logout.yieldsAsync(); + + doctor._checkImap(function(error) { + expect(error).to.not.exist; + expect(imapStub.login.calledOnce).to.be.true; + expect(imapStub.listWellKnownFolders.calledOnce).to.be.true; + expect(imapStub.logout.calledOnce).to.be.true; + + done(); }); }); - describe('#_checkReachable', function() { - it('should be able to reach the host w/o cert', function(done) { - credentials.imap.ca = undefined; - - doctor._checkReachable(credentials.imap, function(error) { - expect(error).to.not.exist; - expect(TCPSocket.open.calledOnce).to.be.true; - expect(TCPSocket.open.calledWith(credentials.imap.host, credentials.imap.port, { - binaryType: 'arraybuffer', - useSecureTransport: credentials.imap.secure, - ca: credentials.imap.ca - })).to.be.true; - - done(); - }); - - socketStub.oncert(); - socketStub.onopen(); + it('should fail w/ generic error on logout', function(done) { + imapStub.login.yieldsAsync(); + imapStub.listWellKnownFolders.yieldsAsync(null, { + Inbox: [{}] }); - it('should catch Mozilla TCPSocket exception', function(done) { - // Mozilla forbids extensions to the TCPSocket object - Object.defineProperty(socketStub, 'oncert', { - set: function() { - throw 'Mozilla specific behavior'; - } - }); + doctor._checkImap(function(error) { + expect(error).to.exist; + expect(error.code).to.equal(ConnectionDoctor.GENERIC_ERROR); + expect(error.underlyingError).to.exist; + expect(imapStub.login.calledOnce).to.be.true; + expect(imapStub.listWellKnownFolders.calledOnce).to.be.true; + expect(imapStub.logout.calledOnce).to.be.true; - doctor._checkReachable(credentials.imap, function(error) { - expect(error).to.not.exist; - expect(TCPSocket.open.calledOnce).to.be.true; - expect(TCPSocket.open.calledWith(credentials.imap.host, credentials.imap.port, { - binaryType: 'arraybuffer', - useSecureTransport: credentials.imap.secure, - ca: credentials.imap.ca - })).to.be.true; - - done(); - }); - - socketStub.onopen(); + done(); }); - it('should fail w/ wrong cert', function(done) { - doctor._checkReachable(credentials.imap, function(error) { - expect(error).to.exist; - expect(error.code).to.equal(ConnectionDoctor.TLS_WRONG_CERT); - expect(TCPSocket.open.calledOnce).to.be.true; - expect(TCPSocket.open.calledWith(credentials.imap.host, credentials.imap.port, { - binaryType: 'arraybuffer', - useSecureTransport: credentials.imap.secure, - ca: credentials.imap.ca - })).to.be.true; + setTimeout(function() { + // this error is thrown while we're waiting for the logout + imapStub.onError(new Error()); + }, 50); + }); - done(); - }); - - socketStub.oncert(); - socketStub.onerror(); - socketStub.onclose(); + it('should fail w/ generic error on inbox missing', function(done) { + imapStub.login.yieldsAsync(); + imapStub.listWellKnownFolders.yieldsAsync(null, { + Inbox: [] }); - it('should fail w/ host unreachable', function(done) { - doctor._checkReachable(credentials.imap, function(error) { - expect(error).to.exist; - expect(error.code).to.equal(ConnectionDoctor.HOST_UNREACHABLE); - expect(TCPSocket.open.calledOnce).to.be.true; + doctor._checkImap(function(error) { + expect(error).to.exist; + expect(error.code).to.equal(ConnectionDoctor.NO_INBOX); + expect(imapStub.login.calledOnce).to.be.true; + expect(imapStub.listWellKnownFolders.calledOnce).to.be.true; + expect(imapStub.logout.called).to.be.false; - done(); - }); - - socketStub.onerror({ - data: new Error() - }); - socketStub.onclose(); - }); - - it('should fail w/ timeout', function(done) { - var origTimeout = cfg.connDocTimeout; // remember timeout from the config to reset it on done - cfg.connDocTimeout = 20; // set to 20ms for the test - - doctor._checkReachable(credentials.imap, function(error) { - expect(error).to.exist; - expect(error.code).to.equal(ConnectionDoctor.HOST_TIMEOUT); - expect(TCPSocket.open.calledOnce).to.be.true; - cfg.connDocTimeout = origTimeout; - - done(); - }); + done(); }); }); - describe('#_checkImap', function() { - it('should perform IMAP login, list folders, logout', function(done) { - imapStub.login.yieldsAsync(); - imapStub.listWellKnownFolders.yieldsAsync(null, { - Inbox: [{}] - }); - imapStub.logout.yieldsAsync(); + it('should fail w/ generic error on listing folders fails', function(done) { + imapStub.login.yieldsAsync(); + imapStub.listWellKnownFolders.yieldsAsync(new Error()); - doctor._checkImap(function(error) { - expect(error).to.not.exist; - expect(imapStub.login.calledOnce).to.be.true; - expect(imapStub.listWellKnownFolders.calledOnce).to.be.true; - expect(imapStub.logout.calledOnce).to.be.true; + doctor._checkImap(function(error) { + expect(error).to.exist; + expect(error.code).to.equal(ConnectionDoctor.GENERIC_ERROR); + expect(error.underlyingError).to.exist; + expect(imapStub.login.calledOnce).to.be.true; + expect(imapStub.listWellKnownFolders.calledOnce).to.be.true; + expect(imapStub.logout.called).to.be.false; - done(); - }); - }); - - it('should fail w/ generic error on logout', function(done) { - imapStub.login.yieldsAsync(); - imapStub.listWellKnownFolders.yieldsAsync(null, { - Inbox: [{}] - }); - - doctor._checkImap(function(error) { - expect(error).to.exist; - expect(error.code).to.equal(ConnectionDoctor.GENERIC_ERROR); - expect(error.underlyingError).to.exist; - expect(imapStub.login.calledOnce).to.be.true; - expect(imapStub.listWellKnownFolders.calledOnce).to.be.true; - expect(imapStub.logout.calledOnce).to.be.true; - - done(); - }); - - setTimeout(function() { - // this error is thrown while we're waiting for the logout - imapStub.onError(new Error()); - }, 50); - }); - - it('should fail w/ generic error on inbox missing', function(done) { - imapStub.login.yieldsAsync(); - imapStub.listWellKnownFolders.yieldsAsync(null, { - Inbox: [] - }); - - doctor._checkImap(function(error) { - expect(error).to.exist; - expect(error.code).to.equal(ConnectionDoctor.NO_INBOX); - expect(imapStub.login.calledOnce).to.be.true; - expect(imapStub.listWellKnownFolders.calledOnce).to.be.true; - expect(imapStub.logout.called).to.be.false; - - done(); - }); - }); - - it('should fail w/ generic error on listing folders fails', function(done) { - imapStub.login.yieldsAsync(); - imapStub.listWellKnownFolders.yieldsAsync(new Error()); - - doctor._checkImap(function(error) { - expect(error).to.exist; - expect(error.code).to.equal(ConnectionDoctor.GENERIC_ERROR); - expect(error.underlyingError).to.exist; - expect(imapStub.login.calledOnce).to.be.true; - expect(imapStub.listWellKnownFolders.calledOnce).to.be.true; - expect(imapStub.logout.called).to.be.false; - - done(); - }); - }); - - it('should fail w/ auth rejected', function(done) { - doctor._checkImap(function(error) { - expect(error).to.exist; - expect(error.code).to.equal(ConnectionDoctor.AUTH_REJECTED); - expect(error.underlyingError).to.exist; - expect(imapStub.login.calledOnce).to.be.true; - expect(imapStub.listWellKnownFolders.called).to.be.false; - expect(imapStub.logout.called).to.be.false; - - done(); - }); - - setTimeout(function() { - // this error is thrown while we're waiting for the login - imapStub.onError(new Error()); - }, 50); + done(); }); }); - describe('#_checkSmtp', function() { - it('should perform SMTP login, logout', function(done) { - doctor._checkSmtp(function(error) { - expect(error).to.not.exist; - expect(smtpStub.connect.calledOnce).to.be.true; - expect(smtpStub.quit.calledOnce).to.be.true; + it('should fail w/ auth rejected', function(done) { + doctor._checkImap(function(error) { + expect(error).to.exist; + expect(error.code).to.equal(ConnectionDoctor.AUTH_REJECTED); + expect(error.underlyingError).to.exist; + expect(imapStub.login.calledOnce).to.be.true; + expect(imapStub.listWellKnownFolders.called).to.be.false; + expect(imapStub.logout.called).to.be.false; - done(); - }); - - smtpStub.onidle(); - smtpStub.onclose(); + done(); }); - it('should fail w/ auth rejected', function(done) { - doctor._checkSmtp(function(error) { - expect(error).to.exist; - expect(error.code).to.equal(ConnectionDoctor.AUTH_REJECTED); - expect(error.underlyingError).to.exist; - expect(smtpStub.connect.calledOnce).to.be.true; - expect(smtpStub.quit.called).to.be.false; + setTimeout(function() { + // this error is thrown while we're waiting for the login + imapStub.onError(new Error()); + }, 50); + }); + }); - done(); - }); + describe('#_checkSmtp', function() { + it('should perform SMTP login, logout', function(done) { + doctor._checkSmtp(function(error) { + expect(error).to.not.exist; + expect(smtpStub.connect.calledOnce).to.be.true; + expect(smtpStub.quit.calledOnce).to.be.true; - smtpStub.onerror(new Error()); + done(); + }); + + smtpStub.onidle(); + smtpStub.onclose(); + }); + + it('should fail w/ auth rejected', function(done) { + doctor._checkSmtp(function(error) { + expect(error).to.exist; + expect(error.code).to.equal(ConnectionDoctor.AUTH_REJECTED); + expect(error.underlyingError).to.exist; + expect(smtpStub.connect.calledOnce).to.be.true; + expect(smtpStub.quit.called).to.be.false; + + done(); + }); + + smtpStub.onerror(new Error()); + }); + }); + + describe('#check', function() { + beforeEach(function() { + sinon.stub(doctor, '_checkOnline'); + sinon.stub(doctor, '_checkReachable'); + sinon.stub(doctor, '_checkImap'); + sinon.stub(doctor, '_checkSmtp'); + }); + + it('should perform all tests', function(done) { + doctor._checkOnline.yieldsAsync(); + doctor._checkReachable.withArgs(credentials.imap).yieldsAsync(); + doctor._checkReachable.withArgs(credentials.smtp).yieldsAsync(); + doctor._checkImap.yieldsAsync(); + doctor._checkSmtp.yieldsAsync(); + + doctor.check(function(err) { + expect(err).to.not.exist; + expect(doctor._checkOnline.calledOnce).to.be.true; + expect(doctor._checkReachable.calledTwice).to.be.true; + expect(doctor._checkImap.calledOnce).to.be.true; + expect(doctor._checkSmtp.calledOnce).to.be.true; + + done(); }); }); - describe('#check', function() { - beforeEach(function() { - sinon.stub(doctor, '_checkOnline'); - sinon.stub(doctor, '_checkReachable'); - sinon.stub(doctor, '_checkImap'); - sinon.stub(doctor, '_checkSmtp'); + it('should fail for smtp', function(done) { + doctor._checkOnline.yieldsAsync(); + doctor._checkReachable.withArgs(credentials.imap).yieldsAsync(); + doctor._checkReachable.withArgs(credentials.smtp).yieldsAsync(); + doctor._checkImap.yieldsAsync(); + doctor._checkSmtp.yieldsAsync(new Error()); + + doctor.check(function(err) { + expect(err).to.exist; + expect(doctor._checkOnline.calledOnce).to.be.true; + expect(doctor._checkReachable.calledTwice).to.be.true; + expect(doctor._checkImap.calledOnce).to.be.true; + expect(doctor._checkSmtp.calledOnce).to.be.true; + + done(); }); + }); - it('should perform all tests', function(done) { - doctor._checkOnline.yieldsAsync(); - doctor._checkReachable.withArgs(credentials.imap).yieldsAsync(); - doctor._checkReachable.withArgs(credentials.smtp).yieldsAsync(); - doctor._checkImap.yieldsAsync(); - doctor._checkSmtp.yieldsAsync(); + it('should fail for imap', function(done) { + doctor._checkOnline.yieldsAsync(); + doctor._checkReachable.withArgs(credentials.imap).yieldsAsync(); + doctor._checkReachable.withArgs(credentials.smtp).yieldsAsync(); + doctor._checkImap.yieldsAsync(new Error()); - doctor.check(function(err) { - expect(err).to.not.exist; - expect(doctor._checkOnline.calledOnce).to.be.true; - expect(doctor._checkReachable.calledTwice).to.be.true; - expect(doctor._checkImap.calledOnce).to.be.true; - expect(doctor._checkSmtp.calledOnce).to.be.true; + doctor.check(function(err) { + expect(err).to.exist; + expect(doctor._checkOnline.calledOnce).to.be.true; + expect(doctor._checkReachable.calledTwice).to.be.true; + expect(doctor._checkImap.calledOnce).to.be.true; + expect(doctor._checkSmtp.called).to.be.false; - done(); - }); + done(); }); + }); - it('should fail for smtp', function(done) { - doctor._checkOnline.yieldsAsync(); - doctor._checkReachable.withArgs(credentials.imap).yieldsAsync(); - doctor._checkReachable.withArgs(credentials.smtp).yieldsAsync(); - doctor._checkImap.yieldsAsync(); - doctor._checkSmtp.yieldsAsync(new Error()); + it('should fail for smtp reachability', function(done) { + doctor._checkOnline.yieldsAsync(); + doctor._checkReachable.withArgs(credentials.imap).yieldsAsync(); + doctor._checkReachable.withArgs(credentials.smtp).yieldsAsync(new Error()); - doctor.check(function(err) { - expect(err).to.exist; - expect(doctor._checkOnline.calledOnce).to.be.true; - expect(doctor._checkReachable.calledTwice).to.be.true; - expect(doctor._checkImap.calledOnce).to.be.true; - expect(doctor._checkSmtp.calledOnce).to.be.true; + doctor.check(function(err) { + expect(err).to.exist; + expect(doctor._checkOnline.calledOnce).to.be.true; + expect(doctor._checkReachable.calledTwice).to.be.true; + expect(doctor._checkImap.called).to.be.false; + expect(doctor._checkSmtp.called).to.be.false; - done(); - }); + done(); }); + }); - it('should fail for imap', function(done) { - doctor._checkOnline.yieldsAsync(); - doctor._checkReachable.withArgs(credentials.imap).yieldsAsync(); - doctor._checkReachable.withArgs(credentials.smtp).yieldsAsync(); - doctor._checkImap.yieldsAsync(new Error()); + it('should fail for imap reachability', function(done) { + doctor._checkOnline.yieldsAsync(); + doctor._checkReachable.withArgs(credentials.imap).yieldsAsync(new Error()); - doctor.check(function(err) { - expect(err).to.exist; - expect(doctor._checkOnline.calledOnce).to.be.true; - expect(doctor._checkReachable.calledTwice).to.be.true; - expect(doctor._checkImap.calledOnce).to.be.true; - expect(doctor._checkSmtp.called).to.be.false; + doctor.check(function(err) { + expect(err).to.exist; + expect(doctor._checkOnline.calledOnce).to.be.true; + expect(doctor._checkReachable.calledOnce).to.be.true; + expect(doctor._checkImap.called).to.be.false; + expect(doctor._checkSmtp.called).to.be.false; - done(); - }); + done(); }); + }); - it('should fail for smtp reachability', function(done) { - doctor._checkOnline.yieldsAsync(); - doctor._checkReachable.withArgs(credentials.imap).yieldsAsync(); - doctor._checkReachable.withArgs(credentials.smtp).yieldsAsync(new Error()); + it('should fail for offline', function(done) { + doctor._checkOnline.yieldsAsync(new Error()); - doctor.check(function(err) { - expect(err).to.exist; - expect(doctor._checkOnline.calledOnce).to.be.true; - expect(doctor._checkReachable.calledTwice).to.be.true; - expect(doctor._checkImap.called).to.be.false; - expect(doctor._checkSmtp.called).to.be.false; + doctor.check(function(err) { + expect(err).to.exist; + expect(doctor._checkOnline.calledOnce).to.be.true; + expect(doctor._checkReachable.called).to.be.false; + expect(doctor._checkImap.called).to.be.false; + expect(doctor._checkSmtp.called).to.be.false; - done(); - }); + done(); }); + }); - it('should fail for imap reachability', function(done) { - doctor._checkOnline.yieldsAsync(); - doctor._checkReachable.withArgs(credentials.imap).yieldsAsync(new Error()); + it('should fail w/o config', function(done) { + doctor.credentials = doctor._imap = doctor._smtp = undefined; - doctor.check(function(err) { - expect(err).to.exist; - expect(doctor._checkOnline.calledOnce).to.be.true; - expect(doctor._checkReachable.calledOnce).to.be.true; - expect(doctor._checkImap.called).to.be.false; - expect(doctor._checkSmtp.called).to.be.false; + doctor.check(function(err) { + expect(err).to.exist; + expect(doctor._checkOnline.called).to.be.false; + expect(doctor._checkReachable.called).to.be.false; + expect(doctor._checkImap.called).to.be.false; + expect(doctor._checkSmtp.called).to.be.false; - done(); - }); - }); - - it('should fail for offline', function(done) { - doctor._checkOnline.yieldsAsync(new Error()); - - doctor.check(function(err) { - expect(err).to.exist; - expect(doctor._checkOnline.calledOnce).to.be.true; - expect(doctor._checkReachable.called).to.be.false; - expect(doctor._checkImap.called).to.be.false; - expect(doctor._checkSmtp.called).to.be.false; - - done(); - }); - }); - - it('should fail w/o config', function(done) { - doctor.credentials = doctor._imap = doctor._smtp = undefined; - - doctor.check(function(err) { - expect(err).to.exist; - expect(doctor._checkOnline.called).to.be.false; - expect(doctor._checkReachable.called).to.be.false; - expect(doctor._checkImap.called).to.be.false; - expect(doctor._checkSmtp.called).to.be.false; - - done(); - }); + done(); }); }); }); diff --git a/test/unit/contacts-ctrl-test.js b/test/unit/contacts-ctrl-test.js index 15085ef..05212c4 100644 --- a/test/unit/contacts-ctrl-test.js +++ b/test/unit/contacts-ctrl-test.js @@ -1,190 +1,186 @@ -define(function(require) { - 'use strict'; +'use strict'; - var expect = chai.expect, - angular = require('angular'), - mocks = require('angularMocks'), - ContactsCtrl = require('js/controller/contacts'), - appController = require('js/app-controller'), - KeychainDAO = require('js/dao/keychain-dao'), - PGP = require('js/crypto/pgp'); +var mocks = angular.mocks, + ContactsCtrl = require('../../src/js/controller/contacts'), + appController = require('../../src/js/app-controller'), + KeychainDAO = require('../../src/js/dao/keychain-dao'), + PGP = require('../../src/js/crypto/pgp'); - describe('Contacts Controller unit test', function() { - var scope, contactsCtrl, - origKeychain, keychainMock, - origPgp, pgpMock; +describe('Contacts Controller unit test', function() { + var scope, contactsCtrl, + origKeychain, keychainMock, + origPgp, pgpMock; - beforeEach(function() { - origPgp = appController._pgp; - appController._pgp = pgpMock = sinon.createStubInstance(PGP); - origKeychain = appController._keychain; - appController._keychain = keychainMock = sinon.createStubInstance(KeychainDAO); + beforeEach(function() { + origPgp = appController._pgp; + appController._pgp = pgpMock = sinon.createStubInstance(PGP); + origKeychain = appController._keychain; + appController._keychain = keychainMock = sinon.createStubInstance(KeychainDAO); - angular.module('contactstest', []); - mocks.module('contactstest'); - mocks.inject(function($rootScope, $controller) { - scope = $rootScope.$new(); - scope.state = {}; - contactsCtrl = $controller(ContactsCtrl, { - $scope: scope - }); - }); - }); - - afterEach(function() { - // restore the module - appController._pgp = origPgp; - appController._keychain = origKeychain; - }); - - describe('scope variables', function() { - it('should be set correctly', function() { - expect(scope.fingerprint).to.equal('XXXX XXXX XXXX XXXX XXXX XXXX XXXX XXXX XXXX XXXX'); - expect(scope.state.contacts.toggle).to.exist; - }); - }); - - describe('listKeys', function() { - it('should fail due to error in keychain.listLocalPublicKeys', function(done) { - keychainMock.listLocalPublicKeys.yields(42); - - scope.onError = function(err) { - expect(err).to.equal(42); - done(); - }; - - scope.listKeys(); - }); - - it('should work', function(done) { - keychainMock.listLocalPublicKeys.yields(null, [{ - _id: '12345' - }]); - pgpMock.getKeyParams.returns({ - fingerprint: 'asdf' - }); - - scope.$apply = function() { - expect(scope.keys.length).to.equal(1); - expect(scope.keys[0]._id).to.equal('12345'); - expect(scope.keys[0].fingerprint).to.equal('asdf'); - done(); - }; - - expect(scope.keys).to.not.exist; - scope.listKeys(); - }); - }); - - describe('getFingerprint', function() { - it('should work', function() { - var key = { - fingerprint: 'YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY' - }; - - scope.getFingerprint(key); - - expect(scope.fingerprint).to.equal('YYYY YYYY YYYY YYYY YYYY ... YYYY YYYY YYYY YYYY YYYY'); - }); - }); - - describe('importKey', function() { - it('should work', function(done) { - var keyArmored = '-----BEGIN PGP PUBLIC KEY BLOCK-----'; - - pgpMock.getKeyParams.returns({ - _id: '12345', - userId: 'max@example.com', - userIds: [] - }); - - keychainMock.saveLocalPublicKey.withArgs({ - _id: '12345', - userId: 'max@example.com', - userIds: [], - publicKey: '-----BEGIN PGP PUBLIC KEY BLOCK-----', - imported: true - }).yields(); - - scope.listKeys = function() { - done(); - }; - - scope.importKey(keyArmored); - }); - - it('should fail due to invalid armored key', function(done) { - var keyArmored = '-----BEGIN PGP PRIVATE KEY BLOCK-----'; - - scope.onError = function(err) { - expect(err).to.exist; - done(); - }; - - scope.importKey(keyArmored); - }); - - it('should fail due to error in pgp.getKeyParams', function(done) { - var keyArmored = '-----BEGIN PGP PUBLIC KEY BLOCK-----'; - - pgpMock.getKeyParams.throws(new Error('WAT')); - - scope.onError = function(err) { - expect(err).to.exist; - done(); - }; - - scope.importKey(keyArmored); - }); - - it('should fail due to error in keychain.saveLocalPublicKey', function(done) { - var keyArmored = '-----BEGIN PGP PUBLIC KEY BLOCK-----'; - - pgpMock.getKeyParams.returns({ - _id: '12345', - userId: 'max@example.com' - }); - - keychainMock.saveLocalPublicKey.yields(42); - - scope.onError = function(err) { - expect(err).to.equal(42); - done(); - }; - - scope.importKey(keyArmored); - }); - }); - - describe('removeKey', function() { - it('should work', function(done) { - var key = { - _id: '12345' - }; - - keychainMock.removeLocalPublicKey.withArgs('12345').yields(); - - scope.listKeys = function() { - done(); - }; - - scope.removeKey(key); - }); - - it('should fail due to error in keychain.removeLocalPublicKey', function(done) { - var key = { - _id: '12345' - }; - - keychainMock.removeLocalPublicKey.withArgs('12345').yields(42); - - scope.onError = function(err) { - expect(err).to.equal(42); - done(); - }; - - scope.removeKey(key); + angular.module('contactstest', []); + mocks.module('contactstest'); + mocks.inject(function($rootScope, $controller) { + scope = $rootScope.$new(); + scope.state = {}; + contactsCtrl = $controller(ContactsCtrl, { + $scope: scope }); }); }); + + afterEach(function() { + // restore the module + appController._pgp = origPgp; + appController._keychain = origKeychain; + }); + + describe('scope variables', function() { + it('should be set correctly', function() { + expect(scope.fingerprint).to.equal('XXXX XXXX XXXX XXXX XXXX XXXX XXXX XXXX XXXX XXXX'); + expect(scope.state.contacts.toggle).to.exist; + }); + }); + + describe('listKeys', function() { + it('should fail due to error in keychain.listLocalPublicKeys', function(done) { + keychainMock.listLocalPublicKeys.yields(42); + + scope.onError = function(err) { + expect(err).to.equal(42); + done(); + }; + + scope.listKeys(); + }); + + it('should work', function(done) { + keychainMock.listLocalPublicKeys.yields(null, [{ + _id: '12345' + }]); + pgpMock.getKeyParams.returns({ + fingerprint: 'asdf' + }); + + scope.$apply = function() { + expect(scope.keys.length).to.equal(1); + expect(scope.keys[0]._id).to.equal('12345'); + expect(scope.keys[0].fingerprint).to.equal('asdf'); + done(); + }; + + expect(scope.keys).to.not.exist; + scope.listKeys(); + }); + }); + + describe('getFingerprint', function() { + it('should work', function() { + var key = { + fingerprint: 'YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY' + }; + + scope.getFingerprint(key); + + expect(scope.fingerprint).to.equal('YYYY YYYY YYYY YYYY YYYY ... YYYY YYYY YYYY YYYY YYYY'); + }); + }); + + describe('importKey', function() { + it('should work', function(done) { + var keyArmored = '-----BEGIN PGP PUBLIC KEY BLOCK-----'; + + pgpMock.getKeyParams.returns({ + _id: '12345', + userId: 'max@example.com', + userIds: [] + }); + + keychainMock.saveLocalPublicKey.withArgs({ + _id: '12345', + userId: 'max@example.com', + userIds: [], + publicKey: '-----BEGIN PGP PUBLIC KEY BLOCK-----', + imported: true + }).yields(); + + scope.listKeys = function() { + done(); + }; + + scope.importKey(keyArmored); + }); + + it('should fail due to invalid armored key', function(done) { + var keyArmored = '-----BEGIN PGP PRIVATE KEY BLOCK-----'; + + scope.onError = function(err) { + expect(err).to.exist; + done(); + }; + + scope.importKey(keyArmored); + }); + + it('should fail due to error in pgp.getKeyParams', function(done) { + var keyArmored = '-----BEGIN PGP PUBLIC KEY BLOCK-----'; + + pgpMock.getKeyParams.throws(new Error('WAT')); + + scope.onError = function(err) { + expect(err).to.exist; + done(); + }; + + scope.importKey(keyArmored); + }); + + it('should fail due to error in keychain.saveLocalPublicKey', function(done) { + var keyArmored = '-----BEGIN PGP PUBLIC KEY BLOCK-----'; + + pgpMock.getKeyParams.returns({ + _id: '12345', + userId: 'max@example.com' + }); + + keychainMock.saveLocalPublicKey.yields(42); + + scope.onError = function(err) { + expect(err).to.equal(42); + done(); + }; + + scope.importKey(keyArmored); + }); + }); + + describe('removeKey', function() { + it('should work', function(done) { + var key = { + _id: '12345' + }; + + keychainMock.removeLocalPublicKey.withArgs('12345').yields(); + + scope.listKeys = function() { + done(); + }; + + scope.removeKey(key); + }); + + it('should fail due to error in keychain.removeLocalPublicKey', function(done) { + var key = { + _id: '12345' + }; + + keychainMock.removeLocalPublicKey.withArgs('12345').yields(42); + + scope.onError = function(err) { + expect(err).to.equal(42); + done(); + }; + + scope.removeKey(key); + }); + }); }); \ No newline at end of file diff --git a/test/unit/crypto-test.js b/test/unit/crypto-test.js index 5cbe272..7647514 100644 --- a/test/unit/crypto-test.js +++ b/test/unit/crypto-test.js @@ -1,58 +1,55 @@ -define(function(require) { - 'use strict'; +'use strict'; - var Crypto = require('js/crypto/crypto'), - util = require('js/crypto/util'), - config = require('js/app-config').config, - expect = chai.expect; +var Crypto = require('../../src/js/crypto/crypto'), + config = require('../../src/js/app-config').config, + util = require('crypto-lib').util; - describe('Crypto unit tests', function() { - this.timeout(20000); +describe('Crypto unit tests', function() { + this.timeout(20000); - var crypto, - password = 'password', - keySize = config.symKeySize, - ivSize = config.symIvSize; + var crypto, + password = 'password', + keySize = config.symKeySize, + ivSize = config.symIvSize; - beforeEach(function() { - crypto = new Crypto(); - }); + beforeEach(function() { + crypto = new Crypto(); + }); - afterEach(function() {}); + afterEach(function() {}); - describe('AES encrypt/decrypt', function() { - it('should work', function(done) { - var plaintext = 'Hello, World!'; - var key = util.random(keySize); - var iv = util.random(ivSize); + describe('AES encrypt/decrypt', function() { + it('should work', function(done) { + var plaintext = 'Hello, World!'; + var key = util.random(keySize); + var iv = util.random(ivSize); - crypto.encrypt(plaintext, key, iv, function(err, ciphertext) { + crypto.encrypt(plaintext, key, iv, function(err, ciphertext) { + expect(err).to.not.exist; + expect(ciphertext).to.exist; + + crypto.decrypt(ciphertext, key, iv, function(err, decrypted) { expect(err).to.not.exist; - expect(ciphertext).to.exist; - - crypto.decrypt(ciphertext, key, iv, function(err, decrypted) { - expect(err).to.not.exist; - expect(decrypted).to.equal(plaintext); - - done(); - }); - }); - }); - }); - - describe("PBKDF2 (Async/Worker)", function() { - it('should work', function(done) { - var salt = util.random(keySize); - - crypto.deriveKey(password, salt, keySize, function(err, key) { - expect(err).to.not.exist; - expect(util.base642Str(key).length * 8).to.equal(keySize); + expect(decrypted).to.equal(plaintext); done(); }); }); + }); + }); + describe("PBKDF2 (Async/Worker)", function() { + it('should work', function(done) { + var salt = util.random(keySize); + + crypto.deriveKey(password, salt, keySize, function(err, key) { + expect(err).to.not.exist; + expect(util.base642Str(key).length * 8).to.equal(keySize); + + done(); + }); }); }); + }); \ No newline at end of file diff --git a/test/unit/devicestorage-dao-test.js b/test/unit/devicestorage-dao-test.js index f593e39..1cc49d5 100644 --- a/test/unit/devicestorage-dao-test.js +++ b/test/unit/devicestorage-dao-test.js @@ -1,105 +1,101 @@ -define(function(require) { - 'use strict'; +'use strict'; - var LawnchairDAO = require('js/dao/lawnchair-dao'), - DeviceStorageDAO = require('js/dao/devicestorage-dao'), - expect = chai.expect; +var LawnchairDAO = require('../../src/js/dao/lawnchair-dao'), + DeviceStorageDAO = require('../../src/js/dao/devicestorage-dao'); - var testUser = 'test@example.com'; +var testUser = 'test@example.com'; - describe('Device Storage DAO unit tests', function() { +describe('Device Storage DAO unit tests', function() { - var storageDao, lawnchairDaoStub; + var storageDao, lawnchairDaoStub; - beforeEach(function() { - lawnchairDaoStub = sinon.createStubInstance(LawnchairDAO); - storageDao = new DeviceStorageDAO(lawnchairDaoStub); + beforeEach(function() { + lawnchairDaoStub = sinon.createStubInstance(LawnchairDAO); + storageDao = new DeviceStorageDAO(lawnchairDaoStub); + }); + + afterEach(function() {}); + + describe('init', function() { + it('should work', function(done) { + lawnchairDaoStub.init.yields(); + + storageDao.init(testUser, function(err) { + expect(err).to.not.exist; + expect(lawnchairDaoStub.init.calledOnce).to.be.true; + done(); + }); }); + }); - afterEach(function() {}); + describe('store list', function() { + it('should fail', function(done) { + var list = [{}]; - describe('init', function() { - it('should work', function(done) { - lawnchairDaoStub.init.yields(); - - storageDao.init(testUser, function(err) { - expect(err).to.not.exist; - expect(lawnchairDaoStub.init.calledOnce).to.be.true; - done(); - }); + storageDao.storeList(list, '', function(err) { + expect(err).to.exist; + done(); }); }); - describe('store list', function() { - it('should fail', function(done) { - var list = [{}]; + it('should work with empty list', function(done) { + var list = []; - storageDao.storeList(list, '', function(err) { - expect(err).to.exist; - done(); - }); - }); - - it('should work with empty list', function(done) { - var list = []; - - storageDao.storeList(list, 'email', function(err) { - expect(err).to.not.exist; - done(); - }); - }); - - it('should work', function(done) { - lawnchairDaoStub.batch.yields(); - - var list = [{ - foo: 'bar' - }]; - - storageDao.storeList(list, 'email', function(err) { - expect(err).to.not.exist; - expect(lawnchairDaoStub.batch.calledOnce).to.be.true; - done(); - }); + storageDao.storeList(list, 'email', function(err) { + expect(err).to.not.exist; + done(); }); }); - describe('remove list', function() { - it('should work', function(done) { - lawnchairDaoStub.removeList.yields(); + it('should work', function(done) { + lawnchairDaoStub.batch.yields(); - storageDao.removeList('email', function(err) { - expect(err).to.not.exist; - expect(lawnchairDaoStub.removeList.calledOnce).to.be.true; - done(); - }); + var list = [{ + foo: 'bar' + }]; + + storageDao.storeList(list, 'email', function(err) { + expect(err).to.not.exist; + expect(lawnchairDaoStub.batch.calledOnce).to.be.true; + done(); }); }); + }); - describe('list items', function() { - it('should work', function(done) { - lawnchairDaoStub.list.yields(); + describe('remove list', function() { + it('should work', function(done) { + lawnchairDaoStub.removeList.yields(); - storageDao.listItems('email', 0, null, function(err) { - expect(err).to.not.exist; - expect(lawnchairDaoStub.list.calledOnce).to.be.true; - done(); - }); + storageDao.removeList('email', function(err) { + expect(err).to.not.exist; + expect(lawnchairDaoStub.removeList.calledOnce).to.be.true; + done(); }); }); + }); - describe('clear', function() { - it('should work', function(done) { - lawnchairDaoStub.clear.yields(); + describe('list items', function() { + it('should work', function(done) { + lawnchairDaoStub.list.yields(); - storageDao.clear(function(err) { - expect(err).to.not.exist; - expect(lawnchairDaoStub.clear.calledOnce).to.be.true; - done(); - }); + storageDao.listItems('email', 0, null, function(err) { + expect(err).to.not.exist; + expect(lawnchairDaoStub.list.calledOnce).to.be.true; + done(); }); }); + }); + describe('clear', function() { + it('should work', function(done) { + lawnchairDaoStub.clear.yields(); + + storageDao.clear(function(err) { + expect(err).to.not.exist; + expect(lawnchairDaoStub.clear.calledOnce).to.be.true; + done(); + }); + }); }); }); \ No newline at end of file diff --git a/test/unit/dialog-ctrl-test.js b/test/unit/dialog-ctrl-test.js index 7ff73cd..191cd4f 100644 --- a/test/unit/dialog-ctrl-test.js +++ b/test/unit/dialog-ctrl-test.js @@ -1,50 +1,46 @@ -define(function(require) { - 'use strict'; +'use strict'; - var expect = chai.expect, - angular = require('angular'), - mocks = require('angularMocks'), - DialogCtrl = require('js/controller/dialog'); +var mocks = angular.mocks, + DialogCtrl = require('../../src/js/controller/dialog'); - describe('Dialog Controller unit test', function() { - var scope, dialogCtrl; +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); + 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); + }); + }); }); \ No newline at end of file diff --git a/test/unit/email-dao-test.js b/test/unit/email-dao-test.js index 305f8f1..0ba3553 100644 --- a/test/unit/email-dao-test.js +++ b/test/unit/email-dao-test.js @@ -1,2304 +1,2301 @@ -define(function(require) { - 'use strict'; +'use strict'; - var EmailDAO = require('js/dao/email-dao'), - KeychainDAO = require('js/dao/keychain-dao'), - ImapClient = require('imap-client'), - PgpMailer = require('pgpmailer'), - PgpBuilder = require('pgpbuilder'), - PGP = require('js/crypto/pgp'), - DeviceStorageDAO = require('js/dao/devicestorage-dao'), - mailreader = require('mailreader'), - cfg = require('js/app-config').config, - expect = chai.expect; +var mailreader = require('mailreader'), + ImapClient = require('imap-client'), + PgpMailer = require('pgpmailer'), + PgpBuilder = require('pgpbuilder'), + cfg = require('../../src/js/app-config').config, + EmailDAO = require('../../src/js/dao/email-dao'), + KeychainDAO = require('../../src/js/dao/keychain-dao'), + PGP = require('../../src/js/crypto/pgp'), + DeviceStorageDAO = require('../../src/js/dao/devicestorage-dao'); - describe('Email DAO unit tests', function() { - // show the stack trace when an error occurred - chai.Assertion.includeStack = true; +describe('Email DAO unit tests', function() { + // show the stack trace when an error occurred + chai.Assertion.includeStack = true; - // SUT - var dao; + // SUT + var dao; - // mocks - var keychainStub, imapClientStub, pgpMailerStub, pgpBuilderStub, pgpStub, devicestorageStub, parseStub; + // mocks + var keychainStub, imapClientStub, pgpMailerStub, pgpBuilderStub, pgpStub, devicestorageStub, parseStub; - // config - var emailAddress, passphrase, asymKeySize, account; + // config + var emailAddress, passphrase, asymKeySize, account; + // test data + var folders, inboxFolder, sentFolder, draftsFolder, outboxFolder, trashFolder, mockKeyPair; + + beforeEach(function() { + // // test data - var folders, inboxFolder, sentFolder, draftsFolder, outboxFolder, trashFolder, mockKeyPair; + // + emailAddress = 'asdf@asdf.com'; + passphrase = 'asdf'; + asymKeySize = 2048; - beforeEach(function() { - // - // test data - // - emailAddress = 'asdf@asdf.com'; - passphrase = 'asdf'; - asymKeySize = 2048; + inboxFolder = { + name: 'Inbox', + type: 'Inbox', + path: 'INBOX', + messages: [] + }; - inboxFolder = { - name: 'Inbox', - type: 'Inbox', - path: 'INBOX', - messages: [] - }; + sentFolder = { + name: 'Sent', + type: 'Sent', + path: 'SENT', + messages: [] + }; - sentFolder = { - name: 'Sent', - type: 'Sent', - path: 'SENT', - messages: [] - }; + draftsFolder = { + name: 'Drafts', + type: 'Drafts', + path: 'DRAFTS', + messages: [] + }; - draftsFolder = { - name: 'Drafts', - type: 'Drafts', - path: 'DRAFTS', - messages: [] - }; + outboxFolder = { + name: 'Outbox', + type: 'Outbox', + path: 'OUTBOX', + messages: [] + }; - outboxFolder = { - name: 'Outbox', - type: 'Outbox', - path: 'OUTBOX', - messages: [] - }; + trashFolder = { + name: 'Trash', + type: 'Trash', + path: 'TRASH', + messages: [] + }; - trashFolder = { - name: 'Trash', - type: 'Trash', - path: 'TRASH', - messages: [] - }; + folders = [inboxFolder, outboxFolder, trashFolder, sentFolder]; - folders = [inboxFolder, outboxFolder, trashFolder, sentFolder]; + account = { + emailAddress: emailAddress, + asymKeySize: asymKeySize, + folders: folders, + online: true + }; - account = { - emailAddress: emailAddress, - asymKeySize: asymKeySize, - folders: folders, - online: true - }; + mockKeyPair = { + publicKey: { + _id: 1234, + userId: emailAddress, + publicKey: 'publicpublicpublicpublic' + }, + privateKey: { + _id: 1234, + userId: emailAddress, + encryptedKey: 'privateprivateprivateprivate' + } + }; - mockKeyPair = { - publicKey: { - _id: 1234, - userId: emailAddress, - publicKey: 'publicpublicpublicpublic' - }, - privateKey: { - _id: 1234, - userId: emailAddress, - encryptedKey: 'privateprivateprivateprivate' - } - }; + // + // setup the mocks + // + keychainStub = sinon.createStubInstance(KeychainDAO); + imapClientStub = sinon.createStubInstance(ImapClient); + pgpMailerStub = sinon.createStubInstance(PgpMailer); + pgpBuilderStub = sinon.createStubInstance(PgpBuilder); + pgpStub = sinon.createStubInstance(PGP); + parseStub = sinon.stub(mailreader, 'parse'); + devicestorageStub = sinon.createStubInstance(DeviceStorageDAO); - // - // setup the mocks - // - keychainStub = sinon.createStubInstance(KeychainDAO); - imapClientStub = sinon.createStubInstance(ImapClient); - pgpMailerStub = sinon.createStubInstance(PgpMailer); - pgpBuilderStub = sinon.createStubInstance(PgpBuilder); - pgpStub = sinon.createStubInstance(PGP); - parseStub = sinon.stub(mailreader, 'parse'); - devicestorageStub = sinon.createStubInstance(DeviceStorageDAO); + // + // setup the SUT + // + dao = new EmailDAO(keychainStub, pgpStub, devicestorageStub, pgpBuilderStub, mailreader); + dao._account = account; + dao._pgpMailer = pgpMailerStub; + dao._imapClient = imapClientStub; - // - // setup the SUT - // - dao = new EmailDAO(keychainStub, pgpStub, devicestorageStub, pgpBuilderStub, mailreader); - dao._account = account; - dao._pgpMailer = pgpMailerStub; - dao._imapClient = imapClientStub; + // + // check configuration + // + expect(dao._keychain).to.equal(keychainStub); + expect(dao._pgp).to.equal(pgpStub); + expect(dao._devicestorage).to.equal(devicestorageStub); + expect(dao._mailreader).to.equal(mailreader); + expect(dao._pgpbuilder).to.equal(pgpBuilderStub); + }); - // - // check configuration - // - expect(dao._keychain).to.equal(keychainStub); - expect(dao._pgp).to.equal(pgpStub); - expect(dao._devicestorage).to.equal(devicestorageStub); - expect(dao._mailreader).to.equal(mailreader); - expect(dao._pgpbuilder).to.equal(pgpBuilderStub); - }); + afterEach(function() { + mailreader.parse.restore(); + }); - afterEach(function() { - mailreader.parse.restore(); - }); + describe('public API', function() { + describe('#init', function() { + var initFoldersStub; - describe('public API', function() { - describe('#init', function() { - var initFoldersStub; + beforeEach(function() { + delete dao._account; + initFoldersStub = sinon.stub(dao, '_initFoldersFromDisk'); + }); - beforeEach(function() { - delete dao._account; - initFoldersStub = sinon.stub(dao, '_initFoldersFromDisk'); - }); + it('should initialize folders and return keypair', function(done) { + keychainStub.getUserKeyPair.withArgs(emailAddress).yieldsAsync(null, mockKeyPair); + initFoldersStub.yieldsAsync(); - it('should initialize folders and return keypair', function(done) { - keychainStub.getUserKeyPair.withArgs(emailAddress).yieldsAsync(null, mockKeyPair); - initFoldersStub.yieldsAsync(); + dao.init({ + account: account + }, function(err, keypair) { + expect(err).to.not.exist; + expect(keypair).to.exist; + expect(keychainStub.getUserKeyPair.calledOnce).to.be.true; + expect(initFoldersStub.calledOnce).to.be.true; - dao.init({ - account: account - }, function(err, keypair) { - expect(err).to.not.exist; - expect(keypair).to.exist; - expect(keychainStub.getUserKeyPair.calledOnce).to.be.true; - expect(initFoldersStub.calledOnce).to.be.true; - - done(); - }); - }); - - it('should fail when keychain errors', function(done) { - keychainStub.getUserKeyPair.yieldsAsync({}); - - dao.init({ - account: account - }, function(err, keypair) { - expect(err).to.exist; - expect(keypair).to.not.exist; - expect(keychainStub.getUserKeyPair.calledOnce).to.be.true; - expect(initFoldersStub.called).to.be.false; - - done(); - }); + done(); }); }); - describe('#unlock', function() { - it('should unlock', function(done) { - pgpStub.getKeyParams.returns({ - _id: mockKeyPair.publicKey._id, - userId: emailAddress, - userIds: [{ - emailAddress: emailAddress - }] - }); + it('should fail when keychain errors', function(done) { + keychainStub.getUserKeyPair.yieldsAsync({}); - pgpStub.importKeys.withArgs({ - passphrase: passphrase, - privateKeyArmored: mockKeyPair.privateKey.encryptedKey, - publicKeyArmored: mockKeyPair.publicKey.publicKey - }).yieldsAsync(); - pgpStub._privateKey = { - foo: 'bar' - }; + dao.init({ + account: account + }, function(err, keypair) { + expect(err).to.exist; + expect(keypair).to.not.exist; + expect(keychainStub.getUserKeyPair.calledOnce).to.be.true; + expect(initFoldersStub.called).to.be.false; - dao.unlock({ - passphrase: passphrase, - keypair: mockKeyPair - }, function(err) { - expect(err).to.not.exist; + done(); + }); + }); + }); - expect(pgpStub.importKeys.calledOnce).to.be.true; - expect(dao._pgpbuilder._privateKey).to.equal(pgpStub._privateKey); - - done(); - }); + describe('#unlock', function() { + it('should unlock', function(done) { + pgpStub.getKeyParams.returns({ + _id: mockKeyPair.publicKey._id, + userId: emailAddress, + userIds: [{ + emailAddress: emailAddress + }] }); - it('should generate a keypair and unlock', function(done) { - var keypair = { - keyId: 123, - publicKeyArmored: mockKeyPair.publicKey.publicKey, - privateKeyArmored: mockKeyPair.privateKey.encryptedKey - }; + pgpStub.importKeys.withArgs({ + passphrase: passphrase, + privateKeyArmored: mockKeyPair.privateKey.encryptedKey, + publicKeyArmored: mockKeyPair.publicKey.publicKey + }).yieldsAsync(); + pgpStub._privateKey = { + foo: 'bar' + }; - pgpStub.generateKeys.withArgs({ - emailAddress: emailAddress, - keySize: asymKeySize, - passphrase: passphrase - }).yieldsAsync(null, keypair); + dao.unlock({ + passphrase: passphrase, + keypair: mockKeyPair + }, function(err) { + expect(err).to.not.exist; - pgpStub.importKeys.withArgs({ - passphrase: passphrase, - privateKeyArmored: mockKeyPair.privateKey.encryptedKey, - publicKeyArmored: mockKeyPair.publicKey.publicKey - }).yieldsAsync(); - keychainStub.putUserKeyPair.withArgs().yieldsAsync(); + expect(pgpStub.importKeys.calledOnce).to.be.true; + expect(dao._pgpbuilder._privateKey).to.equal(pgpStub._privateKey); - dao.unlock({ - passphrase: passphrase - }, function(err) { - expect(err).to.not.exist; - - expect(pgpStub.generateKeys.calledOnce).to.be.true; - expect(pgpStub.importKeys.calledOnce).to.be.true; - expect(keychainStub.putUserKeyPair.calledOnce).to.be.true; - - done(); - }); - }); - - it('should fail when persisting fails', function(done) { - var keypair = { - keyId: 123, - publicKeyArmored: 'qwerty', - privateKeyArmored: 'asdfgh' - }; - pgpStub.generateKeys.yieldsAsync(null, keypair); - pgpStub.importKeys.withArgs().yieldsAsync(); - keychainStub.putUserKeyPair.yieldsAsync({}); - - dao.unlock({ - passphrase: passphrase - }, function(err) { - expect(err).to.exist; - - expect(pgpStub.generateKeys.calledOnce).to.be.true; - expect(pgpStub.importKeys.calledOnce).to.be.true; - expect(keychainStub.putUserKeyPair.calledOnce).to.be.true; - - done(); - }); - }); - - it('should fail when import fails', function(done) { - var keypair = { - keyId: 123, - publicKeyArmored: 'qwerty', - privateKeyArmored: 'asdfgh' - }; - - pgpStub.generateKeys.withArgs().yieldsAsync(null, keypair); - pgpStub.importKeys.withArgs().yieldsAsync({}); - - dao.unlock({ - passphrase: passphrase - }, function(err) { - expect(err).to.exist; - - expect(pgpStub.generateKeys.calledOnce).to.be.true; - expect(pgpStub.importKeys.calledOnce).to.be.true; - - done(); - }); - }); - - it('should fail when generation fails', function(done) { - pgpStub.generateKeys.yieldsAsync({}); - - dao.unlock({ - passphrase: passphrase - }, function(err) { - expect(err).to.exist; - - expect(pgpStub.generateKeys.calledOnce).to.be.true; - - done(); - }); + done(); }); }); - describe('#openFolder', function() { - it('should open an imap mailbox', function(done) { - imapClientStub.selectMailbox.withArgs({ - path: inboxFolder.path - }).yieldsAsync(); + it('should generate a keypair and unlock', function(done) { + var keypair = { + keyId: 123, + publicKeyArmored: mockKeyPair.publicKey.publicKey, + privateKeyArmored: mockKeyPair.privateKey.encryptedKey + }; - dao.openFolder({ - folder: inboxFolder - }, function(err) { - expect(err).to.not.exist; - expect(imapClientStub.selectMailbox.calledOnce).to.be.true; - done(); - }); + pgpStub.generateKeys.withArgs({ + emailAddress: emailAddress, + keySize: asymKeySize, + passphrase: passphrase + }).yieldsAsync(null, keypair); + + pgpStub.importKeys.withArgs({ + passphrase: passphrase, + privateKeyArmored: mockKeyPair.privateKey.encryptedKey, + publicKeyArmored: mockKeyPair.publicKey.publicKey + }).yieldsAsync(); + keychainStub.putUserKeyPair.withArgs().yieldsAsync(); + + dao.unlock({ + passphrase: passphrase + }, function(err) { + expect(err).to.not.exist; + + expect(pgpStub.generateKeys.calledOnce).to.be.true; + expect(pgpStub.importKeys.calledOnce).to.be.true; + expect(keychainStub.putUserKeyPair.calledOnce).to.be.true; + + done(); + }); + }); + + it('should fail when persisting fails', function(done) { + var keypair = { + keyId: 123, + publicKeyArmored: 'qwerty', + privateKeyArmored: 'asdfgh' + }; + pgpStub.generateKeys.yieldsAsync(null, keypair); + pgpStub.importKeys.withArgs().yieldsAsync(); + keychainStub.putUserKeyPair.yieldsAsync({}); + + dao.unlock({ + passphrase: passphrase + }, function(err) { + expect(err).to.exist; + + expect(pgpStub.generateKeys.calledOnce).to.be.true; + expect(pgpStub.importKeys.calledOnce).to.be.true; + expect(keychainStub.putUserKeyPair.calledOnce).to.be.true; + + done(); + }); + }); + + it('should fail when import fails', function(done) { + var keypair = { + keyId: 123, + publicKeyArmored: 'qwerty', + privateKeyArmored: 'asdfgh' + }; + + pgpStub.generateKeys.withArgs().yieldsAsync(null, keypair); + pgpStub.importKeys.withArgs().yieldsAsync({}); + + dao.unlock({ + passphrase: passphrase + }, function(err) { + expect(err).to.exist; + + expect(pgpStub.generateKeys.calledOnce).to.be.true; + expect(pgpStub.importKeys.calledOnce).to.be.true; + + done(); + }); + }); + + it('should fail when generation fails', function(done) { + pgpStub.generateKeys.yieldsAsync({}); + + dao.unlock({ + passphrase: passphrase + }, function(err) { + expect(err).to.exist; + + expect(pgpStub.generateKeys.calledOnce).to.be.true; + + done(); + }); + }); + }); + + describe('#openFolder', function() { + it('should open an imap mailbox', function(done) { + imapClientStub.selectMailbox.withArgs({ + path: inboxFolder.path + }).yieldsAsync(); + + dao.openFolder({ + folder: inboxFolder + }, function(err) { + expect(err).to.not.exist; + expect(imapClientStub.selectMailbox.calledOnce).to.be.true; + done(); + }); + }); + + it('should not open the virtual outbox folder in imap', function() { + dao.openFolder({ + folder: outboxFolder }); - it('should not open the virtual outbox folder in imap', function() { - dao.openFolder({ - folder: outboxFolder - }); + expect(imapClientStub.selectMailbox.called).to.be.false; + }); + it('should not do anything in offline mode', function(done) { + account.online = false; + + dao.openFolder({ + folder: inboxFolder + }, function(err) { + expect(err).to.exist; expect(imapClientStub.selectMailbox.called).to.be.false; + done(); }); - it('should not do anything in offline mode', function(done) { - account.online = false; + }); + }); - dao.openFolder({ - folder: inboxFolder - }, function(err) { - expect(err).to.exist; - expect(imapClientStub.selectMailbox.called).to.be.false; - done(); - }); + describe('#refreshFolder', function() { + var localListStub, mail; + beforeEach(function() { + localListStub = sinon.stub(dao, '_localListMessages'); + mail = { + uid: 123, + unread: true + }; + }); + + it('should add messages from disk', function(done) { + localListStub.withArgs({ + folder: inboxFolder + }).yieldsAsync(null, [mail]); + + dao.refreshFolder({ + folder: inboxFolder + }, function(err) { + expect(err).to.not.exist; + expect(inboxFolder.count).to.equal(1); + expect(inboxFolder.messages).to.contain(mail); + + done(); }); }); - describe('#refreshFolder', function() { - var localListStub, mail; + it('should not add messages from disk', function(done) { + inboxFolder.messages = [mail]; + localListStub.withArgs({ + folder: inboxFolder + }).yieldsAsync(null, [mail]); - beforeEach(function() { - localListStub = sinon.stub(dao, '_localListMessages'); - mail = { - uid: 123, - unread: true - }; - }); + dao.refreshFolder({ + folder: inboxFolder + }, function(err) { + expect(err).to.not.exist; + expect(inboxFolder.count).to.equal(1); + expect(inboxFolder.messages).to.contain(mail); - it('should add messages from disk', function(done) { - localListStub.withArgs({ - folder: inboxFolder - }).yieldsAsync(null, [mail]); - - dao.refreshFolder({ - folder: inboxFolder - }, function(err) { - expect(err).to.not.exist; - expect(inboxFolder.count).to.equal(1); - expect(inboxFolder.messages).to.contain(mail); - - done(); - }); - }); - - it('should not add messages from disk', function(done) { - inboxFolder.messages = [mail]; - localListStub.withArgs({ - folder: inboxFolder - }).yieldsAsync(null, [mail]); - - dao.refreshFolder({ - folder: inboxFolder - }, function(err) { - expect(err).to.not.exist; - expect(inboxFolder.count).to.equal(1); - expect(inboxFolder.messages).to.contain(mail); - - done(); - }); - }); - - it('should remove messages from memory', function(done) { - inboxFolder.messages = [mail]; - localListStub.withArgs({ - folder: inboxFolder - }).yieldsAsync(null, []); - - dao.refreshFolder({ - folder: inboxFolder - }, function(err) { - expect(err).to.not.exist; - expect(inboxFolder.count).to.equal(0); - expect(inboxFolder.messages).to.be.empty; - - done(); - }); + done(); }); }); - describe('#fetchMessages', function() { - var imapListStub, imapGetStub, imapDeleteStub, localStoreStub; - var opts, message, validUuid, corruptedUuid, verificationSubject; - var notified; + it('should remove messages from memory', function(done) { + inboxFolder.messages = [mail]; + localListStub.withArgs({ + folder: inboxFolder + }).yieldsAsync(null, []); - beforeEach(function() { - imapListStub = sinon.stub(dao, '_imapListMessages'); - imapDeleteStub = sinon.stub(dao, '_imapDeleteMessage'); - imapGetStub = sinon.stub(dao, '_getBodyParts'); - localStoreStub = sinon.stub(dao, '_localStoreMessages'); + dao.refreshFolder({ + folder: inboxFolder + }, function(err) { + expect(err).to.not.exist; + expect(inboxFolder.count).to.equal(0); + expect(inboxFolder.messages).to.be.empty; - opts = { - folder: inboxFolder, - firstUid: 123, - lastUid: 123 - }; - message = { - uid: 123, - subject: 'asdasd', - unread: true, - bodyParts: [] - }; - validUuid = '9A858952-17EE-4273-9E74-D309EAFDFAFB'; - corruptedUuid = 'OMFG_FUCKING_BASTARD_UUID_FROM_HELL!'; - verificationSubject = "[whiteout] New public key uploaded"; - - notified = false; - dao.onIncomingMessage = function(newMessages) { - expect(newMessages).to.contain(message); - notified = true; - }; + done(); }); + }); + }); - it('should fetch message downstream', function(done) { - imapListStub.withArgs(opts).yieldsAsync(null, [message]); + describe('#fetchMessages', function() { + var imapListStub, imapGetStub, imapDeleteStub, localStoreStub; + var opts, message, validUuid, corruptedUuid, verificationSubject; + var notified; - localStoreStub.withArgs({ - folder: inboxFolder, - emails: [message] - }).yieldsAsync(); + beforeEach(function() { + imapListStub = sinon.stub(dao, '_imapListMessages'); + imapDeleteStub = sinon.stub(dao, '_imapDeleteMessage'); + imapGetStub = sinon.stub(dao, '_getBodyParts'); + localStoreStub = sinon.stub(dao, '_localStoreMessages'); - dao.fetchMessages(opts, function(err) { - expect(err).to.not.exist; - expect(inboxFolder.messages).to.contain(message); - expect(notified).to.be.true; - expect(localStoreStub.calledOnce).to.be.true; - expect(imapListStub.calledOnce).to.be.true; + opts = { + folder: inboxFolder, + firstUid: 123, + lastUid: 123 + }; + message = { + uid: 123, + subject: 'asdasd', + unread: true, + bodyParts: [] + }; + validUuid = '9A858952-17EE-4273-9E74-D309EAFDFAFB'; + corruptedUuid = 'OMFG_FUCKING_BASTARD_UUID_FROM_HELL!'; + verificationSubject = "[whiteout] New public key uploaded"; - done(); - }); - }); + notified = false; + dao.onIncomingMessage = function(newMessages) { + expect(newMessages).to.contain(message); + notified = true; + }; + }); - it('should not notify for other folders', function(done) { - opts.folder = sentFolder; + it('should fetch message downstream', function(done) { + imapListStub.withArgs(opts).yieldsAsync(null, [message]); - imapListStub.withArgs(opts).yieldsAsync(null, [message]); + localStoreStub.withArgs({ + folder: inboxFolder, + emails: [message] + }).yieldsAsync(); - localStoreStub.withArgs({ - folder: sentFolder, - emails: [message] - }).yieldsAsync(); + dao.fetchMessages(opts, function(err) { + expect(err).to.not.exist; + expect(inboxFolder.messages).to.contain(message); + expect(notified).to.be.true; + expect(localStoreStub.calledOnce).to.be.true; + expect(imapListStub.calledOnce).to.be.true; - dao.fetchMessages(opts, function(err) { - expect(err).to.not.exist; - expect(sentFolder.messages).to.contain(message); - expect(notified).to.be.false; - expect(localStoreStub.calledOnce).to.be.true; - expect(imapListStub.calledOnce).to.be.true; - - done(); - }); - }); - - it('should verify verification mails', function(done) { - message.subject = verificationSubject; - - imapListStub.withArgs(opts).yieldsAsync(null, [message]); - - imapGetStub.withArgs({ - folder: inboxFolder, - uid: message.uid, - bodyParts: message.bodyParts - }).yieldsAsync(null, [{ - type: 'text', - content: '' + cfg.cloudUrl + cfg.verificationUrl + validUuid - }]); - - keychainStub.verifyPublicKey.withArgs(validUuid).yieldsAsync(); - - imapDeleteStub.withArgs({ - folder: inboxFolder, - uid: message.uid - }).yieldsAsync(); - - dao.fetchMessages(opts, function(err) { - expect(err).to.not.exist; - expect(inboxFolder.messages).to.not.contain(message); - expect(notified).to.be.false; - expect(imapListStub.calledOnce).to.be.true; - expect(imapGetStub.calledOnce).to.be.true; - expect(keychainStub.verifyPublicKey.calledOnce).to.be.true; - expect(imapDeleteStub.calledOnce).to.be.true; - expect(localStoreStub.called).to.be.false; - done(); - }); - }); - - it('should not verify invalid verification mails', function(done) { - message.subject = verificationSubject; - - imapListStub.withArgs(opts).yieldsAsync(null, [message]); - - imapGetStub.withArgs({ - folder: inboxFolder, - uid: message.uid, - bodyParts: message.bodyParts - }).yieldsAsync(null, [{ - type: 'text', - content: '' + cfg.cloudUrl + cfg.verificationUrl + corruptedUuid - }]); - - localStoreStub.withArgs({ - folder: inboxFolder, - emails: [message] - }).yieldsAsync(); - - dao.fetchMessages(opts, function(err) { - expect(err).to.not.exist; - expect(inboxFolder.messages).to.contain(message); - expect(notified).to.be.true; - expect(imapListStub.calledOnce).to.be.true; - expect(imapGetStub.calledOnce).to.be.true; - expect(keychainStub.verifyPublicKey.called).to.be.false; - expect(imapDeleteStub.called).to.be.false; - expect(localStoreStub.calledOnce).to.be.true; - done(); - }); - }); - - it('should display verification mail when verification failed', function(done) { - message.subject = verificationSubject; - - imapListStub.withArgs(opts).yieldsAsync(null, [message]); - - imapGetStub.withArgs({ - folder: inboxFolder, - uid: message.uid, - bodyParts: message.bodyParts - }).yieldsAsync(null, [{ - type: 'text', - content: '' + cfg.cloudUrl + cfg.verificationUrl + validUuid - }]); - - keychainStub.verifyPublicKey.withArgs(validUuid).yieldsAsync({}); - - localStoreStub.withArgs({ - folder: inboxFolder, - emails: [message] - }).yieldsAsync(); - - - dao.fetchMessages(opts, function(err) { - expect(err).to.not.exist; - expect(inboxFolder.messages).to.contain(message); - expect(notified).to.be.true; - expect(imapListStub.calledOnce).to.be.true; - expect(imapGetStub.calledOnce).to.be.true; - expect(keychainStub.verifyPublicKey.calledOnce).to.be.true; - expect(imapDeleteStub.called).to.be.false; - expect(localStoreStub.calledOnce).to.be.true; - done(); - }); + done(); }); }); - describe('#deleteMessage', function() { - var imapDeleteStub, localDeleteStub, message; + it('should not notify for other folders', function(done) { + opts.folder = sentFolder; - beforeEach(function() { - message = { - uid: 1234 - }; - imapDeleteStub = sinon.stub(dao, '_imapDeleteMessage'); - localDeleteStub = sinon.stub(dao, '_localDeleteMessage'); - inboxFolder.messages = [message]; - outboxFolder.messages = [message]; - }); + imapListStub.withArgs(opts).yieldsAsync(null, [message]); - it('should delete from imap, local, memory', function(done) { - var deleteOpts = { - folder: inboxFolder, - uid: message.uid - }; + localStoreStub.withArgs({ + folder: sentFolder, + emails: [message] + }).yieldsAsync(); - imapDeleteStub.withArgs(deleteOpts).yieldsAsync(); - localDeleteStub.withArgs(deleteOpts).yieldsAsync(); + dao.fetchMessages(opts, function(err) { + expect(err).to.not.exist; + expect(sentFolder.messages).to.contain(message); + expect(notified).to.be.false; + expect(localStoreStub.calledOnce).to.be.true; + expect(imapListStub.calledOnce).to.be.true; - dao.deleteMessage({ - folder: inboxFolder, - message: message - }, function(err) { - expect(err).to.not.exist; - expect(imapDeleteStub.calledOnce).to.be.true; - expect(localDeleteStub.calledOnce).to.be.true; - expect(inboxFolder.messages).to.not.contain(message); - - done(); - }); - }); - - it('should delete from local, memory', function(done) { - var deleteOpts = { - folder: inboxFolder, - uid: message.uid - }; - - localDeleteStub.withArgs(deleteOpts).yieldsAsync(); - - dao.deleteMessage({ - folder: inboxFolder, - message: message, - localOnly: true - }, function(err) { - expect(err).to.not.exist; - expect(imapDeleteStub.called).to.be.false; - expect(localDeleteStub.calledOnce).to.be.true; - expect(inboxFolder.messages).to.not.contain(message); - - done(); - }); - }); - - it('should delete from outbox from local, memory', function(done) { - var deleteOpts = { - folder: outboxFolder, - uid: message.uid - }; - - localDeleteStub.withArgs(deleteOpts).yieldsAsync(); - - dao.deleteMessage({ - folder: outboxFolder, - message: message - }, function(err) { - expect(err).to.not.exist; - expect(imapDeleteStub.called).to.be.false; - expect(localDeleteStub.calledOnce).to.be.true; - expect(outboxFolder.messages).to.not.contain(message); - - done(); - }); - }); - - it('should fail at delete from local', function(done) { - var deleteOpts = { - folder: inboxFolder, - uid: message.uid - }; - - imapDeleteStub.withArgs(deleteOpts).yieldsAsync(); - localDeleteStub.withArgs(deleteOpts).yieldsAsync({}); - - dao.deleteMessage({ - folder: inboxFolder, - message: message - }, function(err) { - expect(err).to.exist; - expect(imapDeleteStub.calledOnce).to.be.true; - expect(localDeleteStub.calledOnce).to.be.true; - expect(inboxFolder.messages).to.contain(message); - - done(); - }); - }); - - it('should fail at delete from imap', function(done) { - var deleteOpts = { - folder: inboxFolder, - uid: message.uid - }; - - imapDeleteStub.withArgs(deleteOpts).yieldsAsync({}); - - dao.deleteMessage({ - folder: inboxFolder, - message: message - }, function(err) { - expect(err).to.exist; - expect(imapDeleteStub.calledOnce).to.be.true; - expect(localDeleteStub.called).to.be.false; - expect(inboxFolder.messages).to.contain(message); - - done(); - }); - }); - - it('should fail at delete from imap in offline', function(done) { - account.online = false; - dao.deleteMessage({ - folder: inboxFolder, - message: message - }, function(err) { - expect(err).to.exist; - expect(imapDeleteStub.called).to.be.false; - expect(localDeleteStub.called).to.be.false; - expect(inboxFolder.messages).to.contain(message); - - done(); - }); + done(); }); }); - describe('#setFlags', function() { - var imapMark, localListStub, localStoreStub, message; + it('should verify verification mails', function(done) { + message.subject = verificationSubject; - beforeEach(function() { - message = { - uid: 1234 - }; - imapMark = sinon.stub(dao, '_imapMark'); - localListStub = sinon.stub(dao, '_localListMessages'); - localStoreStub = sinon.stub(dao, '_localStoreMessages'); - inboxFolder.messages = [message]; - outboxFolder.messages = [message]; - }); + imapListStub.withArgs(opts).yieldsAsync(null, [message]); - it('should set flags for imap, disk, memory', function(done) { - imapMark.withArgs({ - folder: inboxFolder, - uid: message.uid, - unread: message.unread, - answered: message.answered - }).yieldsAsync(); + imapGetStub.withArgs({ + folder: inboxFolder, + uid: message.uid, + bodyParts: message.bodyParts + }).yieldsAsync(null, [{ + type: 'text', + content: '' + cfg.cloudUrl + cfg.verificationUrl + validUuid + }]); - localListStub.withArgs({ - folder: inboxFolder, - uid: message.uid - }).yieldsAsync(null, [message]); + keychainStub.verifyPublicKey.withArgs(validUuid).yieldsAsync(); - localStoreStub.withArgs({ - folder: inboxFolder, - emails: [message] - }).yieldsAsync(); + imapDeleteStub.withArgs({ + folder: inboxFolder, + uid: message.uid + }).yieldsAsync(); - dao.setFlags({ - folder: inboxFolder, - message: message - }, function(err) { - expect(err).to.not.exist; - expect(imapMark.calledOnce).to.be.true; - expect(localListStub.calledOnce).to.be.true; - expect(localStoreStub.calledOnce).to.be.true; - - done(); - }); - }); - - it('should set flags for outbox for disk, memory', function(done) { - localListStub.withArgs({ - folder: outboxFolder, - uid: message.uid - }).yieldsAsync(null, [message]); - - localStoreStub.withArgs({ - folder: outboxFolder, - emails: [message] - }).yieldsAsync(); - - dao.setFlags({ - folder: outboxFolder, - message: message - }, function(err) { - expect(err).to.not.exist; - expect(imapMark.called).to.be.false; - expect(localListStub.calledOnce).to.be.true; - expect(localStoreStub.calledOnce).to.be.true; - - done(); - }); - }); - - it('should set flags for disk, memory', function(done) { - localListStub.withArgs({ - folder: inboxFolder, - uid: message.uid - }).yieldsAsync(null, [message]); - - localStoreStub.withArgs({ - folder: inboxFolder, - emails: [message] - }).yieldsAsync(); - - dao.setFlags({ - folder: inboxFolder, - message: message, - localOnly: true - }, function(err) { - expect(err).to.not.exist; - expect(imapMark.called).to.be.false; - expect(localListStub.calledOnce).to.be.true; - expect(localStoreStub.calledOnce).to.be.true; - - done(); - }); - }); - - it('should fail to set flags for imap', function(done) { - imapMark.yieldsAsync({}); - localListStub.yieldsAsync(null, [message]); - localStoreStub.yieldsAsync(); - - dao.setFlags({ - folder: inboxFolder, - message: message - }, function(err) { - expect(err).to.exist; - expect(imapMark.calledOnce).to.be.true; - expect(localListStub.called).to.be.false; - expect(localStoreStub.called).to.be.false; - - done(); - }); - }); - it('should fail to set flags for imap in offline mode', function(done) { - account.online = false; - localListStub.yieldsAsync(null, [message]); - localStoreStub.yieldsAsync(); - - dao.setFlags({ - folder: inboxFolder, - message: message - }, function(err) { - expect(err).to.exist; - expect(imapMark.called).to.be.false; - expect(localListStub.called).to.be.false; - expect(localStoreStub.called).to.be.false; - - done(); - }); + dao.fetchMessages(opts, function(err) { + expect(err).to.not.exist; + expect(inboxFolder.messages).to.not.contain(message); + expect(notified).to.be.false; + expect(imapListStub.calledOnce).to.be.true; + expect(imapGetStub.calledOnce).to.be.true; + expect(keychainStub.verifyPublicKey.calledOnce).to.be.true; + expect(imapDeleteStub.calledOnce).to.be.true; + expect(localStoreStub.called).to.be.false; + done(); }); }); - describe('#getBody', function() { - var localListStub, localStoreStub, imapGetStub, uid; + it('should not verify invalid verification mails', function(done) { + message.subject = verificationSubject; - beforeEach(function() { - uid = 12345, - localListStub = sinon.stub(dao, '_localListMessages'); - localStoreStub = sinon.stub(dao, '_localStoreMessages'); - imapGetStub = sinon.stub(dao, '_getBodyParts'); + imapListStub.withArgs(opts).yieldsAsync(null, [message]); + + imapGetStub.withArgs({ + folder: inboxFolder, + uid: message.uid, + bodyParts: message.bodyParts + }).yieldsAsync(null, [{ + type: 'text', + content: '' + cfg.cloudUrl + cfg.verificationUrl + corruptedUuid + }]); + + localStoreStub.withArgs({ + folder: inboxFolder, + emails: [message] + }).yieldsAsync(); + + dao.fetchMessages(opts, function(err) { + expect(err).to.not.exist; + expect(inboxFolder.messages).to.contain(message); + expect(notified).to.be.true; + expect(imapListStub.calledOnce).to.be.true; + expect(imapGetStub.calledOnce).to.be.true; + expect(keychainStub.verifyPublicKey.called).to.be.false; + expect(imapDeleteStub.called).to.be.false; + expect(localStoreStub.calledOnce).to.be.true; + done(); + }); + }); + + it('should display verification mail when verification failed', function(done) { + message.subject = verificationSubject; + + imapListStub.withArgs(opts).yieldsAsync(null, [message]); + + imapGetStub.withArgs({ + folder: inboxFolder, + uid: message.uid, + bodyParts: message.bodyParts + }).yieldsAsync(null, [{ + type: 'text', + content: '' + cfg.cloudUrl + cfg.verificationUrl + validUuid + }]); + + keychainStub.verifyPublicKey.withArgs(validUuid).yieldsAsync({}); + + localStoreStub.withArgs({ + folder: inboxFolder, + emails: [message] + }).yieldsAsync(); + + + dao.fetchMessages(opts, function(err) { + expect(err).to.not.exist; + expect(inboxFolder.messages).to.contain(message); + expect(notified).to.be.true; + expect(imapListStub.calledOnce).to.be.true; + expect(imapGetStub.calledOnce).to.be.true; + expect(keychainStub.verifyPublicKey.calledOnce).to.be.true; + expect(imapDeleteStub.called).to.be.false; + expect(localStoreStub.calledOnce).to.be.true; + done(); + }); + }); + }); + + describe('#deleteMessage', function() { + var imapDeleteStub, localDeleteStub, message; + + beforeEach(function() { + message = { + uid: 1234 + }; + imapDeleteStub = sinon.stub(dao, '_imapDeleteMessage'); + localDeleteStub = sinon.stub(dao, '_localDeleteMessage'); + inboxFolder.messages = [message]; + outboxFolder.messages = [message]; + }); + + it('should delete from imap, local, memory', function(done) { + var deleteOpts = { + folder: inboxFolder, + uid: message.uid + }; + + imapDeleteStub.withArgs(deleteOpts).yieldsAsync(); + localDeleteStub.withArgs(deleteOpts).yieldsAsync(); + + dao.deleteMessage({ + folder: inboxFolder, + message: message + }, function(err) { + expect(err).to.not.exist; + expect(imapDeleteStub.calledOnce).to.be.true; + expect(localDeleteStub.calledOnce).to.be.true; + expect(inboxFolder.messages).to.not.contain(message); + + done(); + }); + }); + + it('should delete from local, memory', function(done) { + var deleteOpts = { + folder: inboxFolder, + uid: message.uid + }; + + localDeleteStub.withArgs(deleteOpts).yieldsAsync(); + + dao.deleteMessage({ + folder: inboxFolder, + message: message, + localOnly: true + }, function(err) { + expect(err).to.not.exist; + expect(imapDeleteStub.called).to.be.false; + expect(localDeleteStub.calledOnce).to.be.true; + expect(inboxFolder.messages).to.not.contain(message); + + done(); + }); + }); + + it('should delete from outbox from local, memory', function(done) { + var deleteOpts = { + folder: outboxFolder, + uid: message.uid + }; + + localDeleteStub.withArgs(deleteOpts).yieldsAsync(); + + dao.deleteMessage({ + folder: outboxFolder, + message: message + }, function(err) { + expect(err).to.not.exist; + expect(imapDeleteStub.called).to.be.false; + expect(localDeleteStub.calledOnce).to.be.true; + expect(outboxFolder.messages).to.not.contain(message); + + done(); + }); + }); + + it('should fail at delete from local', function(done) { + var deleteOpts = { + folder: inboxFolder, + uid: message.uid + }; + + imapDeleteStub.withArgs(deleteOpts).yieldsAsync(); + localDeleteStub.withArgs(deleteOpts).yieldsAsync({}); + + dao.deleteMessage({ + folder: inboxFolder, + message: message + }, function(err) { + expect(err).to.exist; + expect(imapDeleteStub.calledOnce).to.be.true; + expect(localDeleteStub.calledOnce).to.be.true; + expect(inboxFolder.messages).to.contain(message); + + done(); + }); + }); + + it('should fail at delete from imap', function(done) { + var deleteOpts = { + folder: inboxFolder, + uid: message.uid + }; + + imapDeleteStub.withArgs(deleteOpts).yieldsAsync({}); + + dao.deleteMessage({ + folder: inboxFolder, + message: message + }, function(err) { + expect(err).to.exist; + expect(imapDeleteStub.calledOnce).to.be.true; + expect(localDeleteStub.called).to.be.false; + expect(inboxFolder.messages).to.contain(message); + + done(); + }); + }); + + it('should fail at delete from imap in offline', function(done) { + account.online = false; + dao.deleteMessage({ + folder: inboxFolder, + message: message + }, function(err) { + expect(err).to.exist; + expect(imapDeleteStub.called).to.be.false; + expect(localDeleteStub.called).to.be.false; + expect(inboxFolder.messages).to.contain(message); + + done(); + }); + }); + }); + + describe('#setFlags', function() { + var imapMark, localListStub, localStoreStub, message; + + beforeEach(function() { + message = { + uid: 1234 + }; + imapMark = sinon.stub(dao, '_imapMark'); + localListStub = sinon.stub(dao, '_localListMessages'); + localStoreStub = sinon.stub(dao, '_localStoreMessages'); + inboxFolder.messages = [message]; + outboxFolder.messages = [message]; + }); + + it('should set flags for imap, disk, memory', function(done) { + imapMark.withArgs({ + folder: inboxFolder, + uid: message.uid, + unread: message.unread, + answered: message.answered + }).yieldsAsync(); + + localListStub.withArgs({ + folder: inboxFolder, + uid: message.uid + }).yieldsAsync(null, [message]); + + localStoreStub.withArgs({ + folder: inboxFolder, + emails: [message] + }).yieldsAsync(); + + dao.setFlags({ + folder: inboxFolder, + message: message + }, function(err) { + expect(err).to.not.exist; + expect(imapMark.calledOnce).to.be.true; + expect(localListStub.calledOnce).to.be.true; + expect(localStoreStub.calledOnce).to.be.true; + + done(); + }); + }); + + it('should set flags for outbox for disk, memory', function(done) { + localListStub.withArgs({ + folder: outboxFolder, + uid: message.uid + }).yieldsAsync(null, [message]); + + localStoreStub.withArgs({ + folder: outboxFolder, + emails: [message] + }).yieldsAsync(); + + dao.setFlags({ + folder: outboxFolder, + message: message + }, function(err) { + expect(err).to.not.exist; + expect(imapMark.called).to.be.false; + expect(localListStub.calledOnce).to.be.true; + expect(localStoreStub.calledOnce).to.be.true; + + done(); + }); + }); + + it('should set flags for disk, memory', function(done) { + localListStub.withArgs({ + folder: inboxFolder, + uid: message.uid + }).yieldsAsync(null, [message]); + + localStoreStub.withArgs({ + folder: inboxFolder, + emails: [message] + }).yieldsAsync(); + + dao.setFlags({ + folder: inboxFolder, + message: message, + localOnly: true + }, function(err) { + expect(err).to.not.exist; + expect(imapMark.called).to.be.false; + expect(localListStub.calledOnce).to.be.true; + expect(localStoreStub.calledOnce).to.be.true; + + done(); + }); + }); + + it('should fail to set flags for imap', function(done) { + imapMark.yieldsAsync({}); + localListStub.yieldsAsync(null, [message]); + localStoreStub.yieldsAsync(); + + dao.setFlags({ + folder: inboxFolder, + message: message + }, function(err) { + expect(err).to.exist; + expect(imapMark.calledOnce).to.be.true; + expect(localListStub.called).to.be.false; + expect(localStoreStub.called).to.be.false; + + done(); + }); + }); + it('should fail to set flags for imap in offline mode', function(done) { + account.online = false; + localListStub.yieldsAsync(null, [message]); + localStoreStub.yieldsAsync(); + + dao.setFlags({ + folder: inboxFolder, + message: message + }, function(err) { + expect(err).to.exist; + expect(imapMark.called).to.be.false; + expect(localListStub.called).to.be.false; + expect(localStoreStub.called).to.be.false; + + done(); + }); + }); + }); + + describe('#getBody', function() { + var localListStub, localStoreStub, imapGetStub, uid; + + beforeEach(function() { + uid = 12345, + localListStub = sinon.stub(dao, '_localListMessages'); + localStoreStub = sinon.stub(dao, '_localStoreMessages'); + imapGetStub = sinon.stub(dao, '_getBodyParts'); + }); + + it('should not do anything if the message already has content', function() { + var message = { + body: 'bender is great!' + }; + + dao.getBody({ + message: message }); - it('should not do anything if the message already has content', function() { - var message = { - body: 'bender is great!' - }; + // should do nothing + }); - dao.getBody({ - message: message - }); + it('should read an unencrypted body from the device', function(done) { + var message, body; - // should do nothing - }); + body = 'bender is great! bender is great!'; + message = { + uid: uid + }; - it('should read an unencrypted body from the device', function(done) { - var message, body; - - body = 'bender is great! bender is great!'; - message = { - uid: uid - }; - - localListStub.withArgs({ - folder: inboxFolder, - uid: uid - }).yieldsAsync(null, [{ - bodyParts: [{ - type: 'text', - content: body - }] - }]); - - dao.getBody({ - message: message, - folder: inboxFolder - }, function(err, msg) { - expect(err).to.not.exist; - - expect(msg).to.equal(message); - expect(msg.body).to.equal(body); - expect(msg.loadingBody).to.be.false; - - expect(localListStub.calledOnce).to.be.true; - - done(); - }); - expect(message.loadingBody).to.be.true; - }); - - it('should read a pgp/mime from the device', function(done) { - var message, ct, pt; - - pt = 'bender is great!'; - ct = '-----BEGIN PGP MESSAGE-----asdasdasd-----END PGP MESSAGE-----'; - message = { - uid: uid, - encrypted: true - }; - - localListStub.withArgs({ - folder: inboxFolder, - uid: uid - }).yieldsAsync(null, [{ - bodyParts: [{ - type: 'text', - content: pt - }, { - type: 'encrypted', - content: ct - }] - }]); - - dao.getBody({ - message: message, - folder: inboxFolder - }, function(err, msg) { - expect(err).to.not.exist; - - expect(msg).to.equal(message); - expect(msg.body).to.equal(ct); - expect(msg.encrypted).to.be.true; - expect(message.loadingBody).to.be.false; - - expect(localListStub.calledOnce).to.be.true; - - done(); - }); - expect(message.loadingBody).to.be.true; - }); - - it('should read a signed pgp/mime from the device', function(done) { - var message, signed, pt, signedMimeTree, signature; - - pt = 'bender is great!'; - signed = 'omg signed text'; - signedMimeTree = 'trallalalalala'; - signature = 'ugauga'; - message = { - uid: uid, - signed: true, - from: [{ - address: 'asdasdasd' - }] - }; - - localListStub.withArgs({ - folder: inboxFolder, - uid: uid - }).yieldsAsync(null, [{ - bodyParts: [{ - type: 'text', - content: pt - }, { - type: 'signed', - content: [{ - type: 'text', - content: signed - }], - signedMessage: signedMimeTree, - signature: signature - }] - }]); - keychainStub.getReceiverPublicKey.withArgs(message.from[0].address).yieldsAsync(null, mockKeyPair.publicKey); - pgpStub.verifySignedMessage.withArgs(signedMimeTree, signature, mockKeyPair.publicKey.publicKey).yieldsAsync(null, true); - - dao.getBody({ - message: message, - folder: inboxFolder - }, function(err, msg) { - expect(err).to.not.exist; - - expect(msg).to.equal(message); - expect(msg.body).to.equal(signed); - expect(message.signed).to.be.true; - expect(message.signaturesValid).to.be.true; - expect(message.loadingBody).to.be.false; - - expect(localListStub.calledOnce).to.be.true; - expect(pgpStub.verifySignedMessage.calledOnce).to.be.true; - expect(keychainStub.getReceiverPublicKey.calledOnce).to.be.true; - - done(); - }); - expect(message.loadingBody).to.be.true; - }); - - it('should read a pgp/inline from the device', function(done) { - var message, ct, pt; - - ct = '-----BEGIN PGP MESSAGE-----\nasdasdasd\n-----END PGP MESSAGE-----'; - pt = 'bla bla yadda yadda'; - message = { - uid: uid - }; - - localListStub.yieldsAsync(null, [{ - bodyParts: [{ - type: 'text', - content: pt - }, { - type: 'text', - content: ct - }, { - type: 'text', - content: pt - }] - }]); - - dao.getBody({ - message: message, - folder: inboxFolder - }, function(err, msg) { - expect(err).to.not.exist; - - expect(msg).to.equal(message); - expect(msg.body).to.equal(ct); - expect(msg.bodyParts[0].type).to.equal('encrypted'); - expect(msg.bodyParts[0].content).to.equal(ct); - expect(msg.encrypted).to.be.true; - expect(message.loadingBody).to.be.false; - - expect(localListStub.calledOnce).to.be.true; - - done(); - }); - expect(message.loadingBody).to.be.true; - }); - - it('should read a signed pgp/inline from the device', function(done) { - var message, pt, expected; - - expected = 'Lorem ipsum Aliquip tempor veniam proident.\n\nafguab;igab;igubalw\n\nLorem ipsum Dolor sed irure sint in non.\n\n\n'; - pt = '-----BEGIN PGP SIGNED MESSAGE-----\nHash: WTFHASH\n\n' + expected + '\n-----BEGIN PGP SIGNATURE----------END PGP SIGNATURE-----'; - message = { - uid: uid, - from: [{ - address: 'asdasdasd' - }] - }; - - localListStub.yieldsAsync(null, [{ - bodyParts: [{ - type: 'text', - content: pt - }] - }]); - keychainStub.getReceiverPublicKey.withArgs(message.from[0].address).yieldsAsync(null, mockKeyPair.publicKey); - pgpStub.verifyClearSignedMessage.withArgs(pt, mockKeyPair.publicKey.publicKey).yieldsAsync(null, true); - - dao.getBody({ - message: message, - folder: inboxFolder - }, function(err, msg) { - expect(err).to.not.exist; - - expect(msg).to.equal(message); - expect(msg.body).to.equal(expected); - expect(message.signed).to.be.true; - expect(message.signaturesValid).to.be.true; - expect(message.loadingBody).to.be.false; - - expect(localListStub.calledOnce).to.be.true; - expect(pgpStub.verifyClearSignedMessage.calledOnce).to.be.true; - expect(keychainStub.getReceiverPublicKey.calledOnce).to.be.true; - - done(); - }); - expect(message.loadingBody).to.be.true; - }); - - it('should stream from imap and set plain text body', function(done) { - var message, body, uid; - - body = 'bender is great! bender is great!'; - uid = 1234; - message = { - uid: uid, - bodyParts: [{ - type: 'text' - }] - }; - - localListStub.withArgs({ - folder: inboxFolder, - uid: uid - }).yieldsAsync(null, [message]); - - localStoreStub.withArgs({ - folder: inboxFolder, - emails: [message] - }).yieldsAsync(); - - imapGetStub.withArgs({ - folder: inboxFolder, - uid: message.uid, - bodyParts: message.bodyParts - }).yieldsAsync(null, [{ + localListStub.withArgs({ + folder: inboxFolder, + uid: uid + }).yieldsAsync(null, [{ + bodyParts: [{ type: 'text', content: body - }]); + }] + }]); - dao.getBody({ - message: message, - folder: inboxFolder - }, function(err, msg) { - expect(err).to.not.exist; + dao.getBody({ + message: message, + folder: inboxFolder + }, function(err, msg) { + expect(err).to.not.exist; - expect(msg).to.equal(message); - expect(msg.body).to.equal(body); - expect(msg.loadingBody).to.be.false; + expect(msg).to.equal(message); + expect(msg.body).to.equal(body); + expect(msg.loadingBody).to.be.false; - expect(localListStub.calledOnce).to.be.true; - expect(imapGetStub.calledOnce).to.be.true; - expect(localStoreStub.calledOnce).to.be.true; + expect(localListStub.calledOnce).to.be.true; - done(); - }); - expect(message.loadingBody).to.be.true; + done(); }); + expect(message.loadingBody).to.be.true; + }); - it('should stream from imap and set encrypted body', function(done) { - var message, ct, pt; + it('should read a pgp/mime from the device', function(done) { + var message, ct, pt; - pt = 'bender is great'; - ct = '-----BEGIN PGP MESSAGE-----asdasdasd-----END PGP MESSAGE-----'; - message = { - uid: uid, - encrypted: true, - bodyParts: [{ - type: 'text' - }, { - type: 'encrypted' - }] - }; + pt = 'bender is great!'; + ct = '-----BEGIN PGP MESSAGE-----asdasdasd-----END PGP MESSAGE-----'; + message = { + uid: uid, + encrypted: true + }; - localListStub.withArgs({ - folder: inboxFolder, - uid: uid - }).yieldsAsync(null, [message]); - - localStoreStub.withArgs({ - folder: inboxFolder, - emails: [message] - }).yieldsAsync(); - - imapGetStub.withArgs({ - folder: inboxFolder, - uid: message.uid, - bodyParts: message.bodyParts - }).yieldsAsync(null, [{ + localListStub.withArgs({ + folder: inboxFolder, + uid: uid + }).yieldsAsync(null, [{ + bodyParts: [{ type: 'text', content: pt }, { type: 'encrypted', content: ct - }]); + }] + }]); + dao.getBody({ + message: message, + folder: inboxFolder + }, function(err, msg) { + expect(err).to.not.exist; - dao.getBody({ - message: message, - folder: inboxFolder - }, function(err, msg) { - expect(err).to.not.exist; + expect(msg).to.equal(message); + expect(msg.body).to.equal(ct); + expect(msg.encrypted).to.be.true; + expect(message.loadingBody).to.be.false; - expect(msg).to.equal(message); - expect(msg.body).to.equal(ct); - expect(msg.encrypted).to.be.true; - expect(msg.loadingBody).to.be.false; + expect(localListStub.calledOnce).to.be.true; - expect(localListStub.calledOnce).to.be.true; - expect(imapGetStub.calledOnce).to.be.true; - expect(localStoreStub.calledOnce).to.be.true; - - done(); - }); - expect(message.loadingBody).to.be.true; + done(); }); + expect(message.loadingBody).to.be.true; + }); - it('fail to stream from imap due to error when persisting', function(done) { - var message = { - uid: uid, - bodyParts: [{ - type: 'text' - }] - }; + it('should read a signed pgp/mime from the device', function(done) { + var message, signed, pt, signedMimeTree, signature; - localListStub.yieldsAsync(null, [message]); - localStoreStub.yieldsAsync({}); - imapGetStub.yieldsAsync(null, [{ + pt = 'bender is great!'; + signed = 'omg signed text'; + signedMimeTree = 'trallalalalala'; + signature = 'ugauga'; + message = { + uid: uid, + signed: true, + from: [{ + address: 'asdasdasd' + }] + }; + + localListStub.withArgs({ + folder: inboxFolder, + uid: uid + }).yieldsAsync(null, [{ + bodyParts: [{ type: 'text', - content: 'bender is great! bender is great!' - }]); - - dao.getBody({ - message: message, - folder: inboxFolder - }, function(err, msg) { - expect(err).to.exist; - expect(msg).to.not.exist; - expect(localListStub.calledOnce).to.be.true; - expect(imapGetStub.calledOnce).to.be.true; - expect(localStoreStub.calledOnce).to.be.true; - - expect(message.loadingBody).to.be.false; - - done(); - }); - }); - - it('fail to stream from imap due to stream error', function(done) { - var message = { - uid: uid, - bodyParts: [{ - type: 'text' - }] - }; - - localListStub.yieldsAsync(null, [message]); - imapGetStub.yieldsAsync({}); - - dao.getBody({ - message: message, - folder: inboxFolder - }, function(err, msg) { - expect(err).to.exist; - expect(msg).to.not.exist; - expect(localListStub.calledOnce).to.be.true; - expect(imapGetStub.calledOnce).to.be.true; - expect(localStoreStub.called).to.be.false; - - expect(message.loadingBody).to.be.false; - - done(); - }); - }); - }); - - describe('#getAttachment', function() { - var imapGetStub, uid; - - beforeEach(function() { - uid = 123456; - imapGetStub = sinon.stub(dao, '_getBodyParts'); - }); - - it('should fetch an attachment from imap', function(done) { - var attmt = {}; - - imapGetStub.withArgs({ - folder: inboxFolder, - uid: uid, - bodyParts: [attmt] - }).yieldsAsync(null, [{ - content: 'CONTENT!!!' - }]); - - dao.getAttachment({ - folder: inboxFolder, - uid: uid, - attachment: attmt - }, function(err, fetchedAttmt) { - expect(err).to.not.exist; - expect(fetchedAttmt).to.equal(attmt); - expect(attmt.content).to.not.be.empty; - expect(imapGetStub.calledOnce).to.be.true; - - done(); - }); - }); - - it('should error during fetch', function(done) { - var attmt = {}; - - imapGetStub.yieldsAsync({}); - - dao.getAttachment({ - folder: inboxFolder, - uid: uid, - attachment: attmt - }, function(err, fetchedAttmt) { - expect(err).to.exist; - expect(fetchedAttmt).to.not.exist; - expect(imapGetStub.calledOnce).to.be.true; - - done(); - }); - }); - }); - - describe('#decryptBody', function() { - it('should do nothing when the message is not encrypted', function(done) { - var message = { - encrypted: false, - decrypted: true, - body: 'asd' - }; - - dao.decryptBody({ - message: message - }, done); - }); - - it('should do nothing when the message is already decrypted', function(done) { - var message = { - encrypted: true, - decrypted: true, - body: 'asd' - }; - - dao.decryptBody({ - message: message - }, done); - }); - - it('should do nothing when the message has no body', function(done) { - var message = { - encrypted: true, - decrypted: false, - body: '' - }; - - dao.decryptBody({ - message: message - }, done); - }); - - it('should do nothing when the message is decrypting', function(done) { - var message = { - encrypted: true, - decrypted: false, - body: 'asd', - decryptingBody: true - }; - - dao.decryptBody({ - message: message - }, done); - }); - - it('decrypt a pgp/mime message', function(done) { - var message, ct, pt, parsed; - - pt = 'bender is great'; - ct = '-----BEGIN PGP MESSAGE-----asdasdasd-----END PGP MESSAGE-----'; - parsed = 'bender! bender! bender!'; - message = { - from: [{ - address: 'asdasdasd' - }], - body: ct, - encrypted: true, - bodyParts: [{ - type: 'encrypted', - content: ct - }] - }; - - keychainStub.getReceiverPublicKey.withArgs(message.from[0].address).yieldsAsync(null, mockKeyPair.publicKey); - pgpStub.decrypt.withArgs(ct, mockKeyPair.publicKey.publicKey).yieldsAsync(null, pt, true); - parseStub.withArgs({ - bodyParts: [{ - type: 'encrypted', - content: ct, - raw: pt - }] - }).yieldsAsync(null, [{ - type: 'encrypted', + content: pt + }, { + type: 'signed', content: [{ type: 'text', - content: parsed - }] - }]); - - dao.decryptBody({ - message: message - }, function(error, msg) { - expect(error).to.not.exist; - expect(msg).to.equal(message); - expect(message.decrypted).to.be.true; - expect(message.signed).to.be.true; - expect(message.signaturesValid).to.be.true; - expect(message.body).to.equal(parsed); - expect(message.decryptingBody).to.be.false; - expect(keychainStub.getReceiverPublicKey.calledOnce).to.be.true; - expect(pgpStub.decrypt.calledOnce).to.be.true; - expect(parseStub.calledOnce).to.be.true; - - done(); - }); - - expect(message.decryptingBody).to.be.true; - }); - - it('decrypt a pgp/mime message with inner signature', function(done) { - var message, ct, pt, parsed, signed, signedMimeTree, signature; - - pt = 'bender is great'; - ct = '-----BEGIN PGP MESSAGE-----asdasdasd-----END PGP MESSAGE-----'; - signedMimeTree = 'trallalalalala'; - signature = 'ugauga'; - signed = 'omg signed text'; - parsed = 'bender! bender! bender!'; - message = { - from: [{ - address: 'asdasdasd' + content: signed }], - body: ct, - encrypted: true, - bodyParts: [{ - type: 'encrypted', - content: ct - }] - }; + signedMessage: signedMimeTree, + signature: signature + }] + }]); + keychainStub.getReceiverPublicKey.withArgs(message.from[0].address).yieldsAsync(null, mockKeyPair.publicKey); + pgpStub.verifySignedMessage.withArgs(signedMimeTree, signature, mockKeyPair.publicKey.publicKey).yieldsAsync(null, true); - keychainStub.getReceiverPublicKey.withArgs(message.from[0].address).yieldsAsync(null, mockKeyPair.publicKey); - pgpStub.decrypt.withArgs(ct, mockKeyPair.publicKey.publicKey).yieldsAsync(null, pt, undefined); - pgpStub.verifySignedMessage.withArgs(signedMimeTree, signature, mockKeyPair.publicKey.publicKey).yieldsAsync(null, true); + dao.getBody({ + message: message, + folder: inboxFolder + }, function(err, msg) { + expect(err).to.not.exist; - parseStub.withArgs({ - bodyParts: [{ - type: 'encrypted', - content: ct, - raw: pt - }] - }).yieldsAsync(null, [{ + expect(msg).to.equal(message); + expect(msg.body).to.equal(signed); + expect(message.signed).to.be.true; + expect(message.signaturesValid).to.be.true; + expect(message.loadingBody).to.be.false; + + expect(localListStub.calledOnce).to.be.true; + expect(pgpStub.verifySignedMessage.calledOnce).to.be.true; + expect(keychainStub.getReceiverPublicKey.calledOnce).to.be.true; + + done(); + }); + expect(message.loadingBody).to.be.true; + }); + + it('should read a pgp/inline from the device', function(done) { + var message, ct, pt; + + ct = '-----BEGIN PGP MESSAGE-----\nasdasdasd\n-----END PGP MESSAGE-----'; + pt = 'bla bla yadda yadda'; + message = { + uid: uid + }; + + localListStub.yieldsAsync(null, [{ + bodyParts: [{ + type: 'text', + content: pt + }, { + type: 'text', + content: ct + }, { + type: 'text', + content: pt + }] + }]); + + dao.getBody({ + message: message, + folder: inboxFolder + }, function(err, msg) { + expect(err).to.not.exist; + + expect(msg).to.equal(message); + expect(msg.body).to.equal(ct); + expect(msg.bodyParts[0].type).to.equal('encrypted'); + expect(msg.bodyParts[0].content).to.equal(ct); + expect(msg.encrypted).to.be.true; + expect(message.loadingBody).to.be.false; + + expect(localListStub.calledOnce).to.be.true; + + done(); + }); + expect(message.loadingBody).to.be.true; + }); + + it('should read a signed pgp/inline from the device', function(done) { + var message, pt, expected; + + expected = 'Lorem ipsum Aliquip tempor veniam proident.\n\nafguab;igab;igubalw\n\nLorem ipsum Dolor sed irure sint in non.\n\n\n'; + pt = '-----BEGIN PGP SIGNED MESSAGE-----\nHash: WTFHASH\n\n' + expected + '\n-----BEGIN PGP SIGNATURE----------END PGP SIGNATURE-----'; + message = { + uid: uid, + from: [{ + address: 'asdasdasd' + }] + }; + + localListStub.yieldsAsync(null, [{ + bodyParts: [{ + type: 'text', + content: pt + }] + }]); + keychainStub.getReceiverPublicKey.withArgs(message.from[0].address).yieldsAsync(null, mockKeyPair.publicKey); + pgpStub.verifyClearSignedMessage.withArgs(pt, mockKeyPair.publicKey.publicKey).yieldsAsync(null, true); + + dao.getBody({ + message: message, + folder: inboxFolder + }, function(err, msg) { + expect(err).to.not.exist; + + expect(msg).to.equal(message); + expect(msg.body).to.equal(expected); + expect(message.signed).to.be.true; + expect(message.signaturesValid).to.be.true; + expect(message.loadingBody).to.be.false; + + expect(localListStub.calledOnce).to.be.true; + expect(pgpStub.verifyClearSignedMessage.calledOnce).to.be.true; + expect(keychainStub.getReceiverPublicKey.calledOnce).to.be.true; + + done(); + }); + expect(message.loadingBody).to.be.true; + }); + + it('should stream from imap and set plain text body', function(done) { + var message, body, uid; + + body = 'bender is great! bender is great!'; + uid = 1234; + message = { + uid: uid, + bodyParts: [{ + type: 'text' + }] + }; + + localListStub.withArgs({ + folder: inboxFolder, + uid: uid + }).yieldsAsync(null, [message]); + + localStoreStub.withArgs({ + folder: inboxFolder, + emails: [message] + }).yieldsAsync(); + + imapGetStub.withArgs({ + folder: inboxFolder, + uid: message.uid, + bodyParts: message.bodyParts + }).yieldsAsync(null, [{ + type: 'text', + content: body + }]); + + dao.getBody({ + message: message, + folder: inboxFolder + }, function(err, msg) { + expect(err).to.not.exist; + + expect(msg).to.equal(message); + expect(msg.body).to.equal(body); + expect(msg.loadingBody).to.be.false; + + expect(localListStub.calledOnce).to.be.true; + expect(imapGetStub.calledOnce).to.be.true; + expect(localStoreStub.calledOnce).to.be.true; + + done(); + }); + expect(message.loadingBody).to.be.true; + }); + + it('should stream from imap and set encrypted body', function(done) { + var message, ct, pt; + + pt = 'bender is great'; + ct = '-----BEGIN PGP MESSAGE-----asdasdasd-----END PGP MESSAGE-----'; + message = { + uid: uid, + encrypted: true, + bodyParts: [{ + type: 'text' + }, { + type: 'encrypted' + }] + }; + + localListStub.withArgs({ + folder: inboxFolder, + uid: uid + }).yieldsAsync(null, [message]); + + localStoreStub.withArgs({ + folder: inboxFolder, + emails: [message] + }).yieldsAsync(); + + imapGetStub.withArgs({ + folder: inboxFolder, + uid: message.uid, + bodyParts: message.bodyParts + }).yieldsAsync(null, [{ + type: 'text', + content: pt + }, { + type: 'encrypted', + content: ct + }]); + + + dao.getBody({ + message: message, + folder: inboxFolder + }, function(err, msg) { + expect(err).to.not.exist; + + expect(msg).to.equal(message); + expect(msg.body).to.equal(ct); + expect(msg.encrypted).to.be.true; + expect(msg.loadingBody).to.be.false; + + expect(localListStub.calledOnce).to.be.true; + expect(imapGetStub.calledOnce).to.be.true; + expect(localStoreStub.calledOnce).to.be.true; + + done(); + }); + expect(message.loadingBody).to.be.true; + }); + + it('fail to stream from imap due to error when persisting', function(done) { + var message = { + uid: uid, + bodyParts: [{ + type: 'text' + }] + }; + + localListStub.yieldsAsync(null, [message]); + localStoreStub.yieldsAsync({}); + imapGetStub.yieldsAsync(null, [{ + type: 'text', + content: 'bender is great! bender is great!' + }]); + + dao.getBody({ + message: message, + folder: inboxFolder + }, function(err, msg) { + expect(err).to.exist; + expect(msg).to.not.exist; + expect(localListStub.calledOnce).to.be.true; + expect(imapGetStub.calledOnce).to.be.true; + expect(localStoreStub.calledOnce).to.be.true; + + expect(message.loadingBody).to.be.false; + + done(); + }); + }); + + it('fail to stream from imap due to stream error', function(done) { + var message = { + uid: uid, + bodyParts: [{ + type: 'text' + }] + }; + + localListStub.yieldsAsync(null, [message]); + imapGetStub.yieldsAsync({}); + + dao.getBody({ + message: message, + folder: inboxFolder + }, function(err, msg) { + expect(err).to.exist; + expect(msg).to.not.exist; + expect(localListStub.calledOnce).to.be.true; + expect(imapGetStub.calledOnce).to.be.true; + expect(localStoreStub.called).to.be.false; + + expect(message.loadingBody).to.be.false; + + done(); + }); + }); + }); + + describe('#getAttachment', function() { + var imapGetStub, uid; + + beforeEach(function() { + uid = 123456; + imapGetStub = sinon.stub(dao, '_getBodyParts'); + }); + + it('should fetch an attachment from imap', function(done) { + var attmt = {}; + + imapGetStub.withArgs({ + folder: inboxFolder, + uid: uid, + bodyParts: [attmt] + }).yieldsAsync(null, [{ + content: 'CONTENT!!!' + }]); + + dao.getAttachment({ + folder: inboxFolder, + uid: uid, + attachment: attmt + }, function(err, fetchedAttmt) { + expect(err).to.not.exist; + expect(fetchedAttmt).to.equal(attmt); + expect(attmt.content).to.not.be.empty; + expect(imapGetStub.calledOnce).to.be.true; + + done(); + }); + }); + + it('should error during fetch', function(done) { + var attmt = {}; + + imapGetStub.yieldsAsync({}); + + dao.getAttachment({ + folder: inboxFolder, + uid: uid, + attachment: attmt + }, function(err, fetchedAttmt) { + expect(err).to.exist; + expect(fetchedAttmt).to.not.exist; + expect(imapGetStub.calledOnce).to.be.true; + + done(); + }); + }); + }); + + describe('#decryptBody', function() { + it('should do nothing when the message is not encrypted', function(done) { + var message = { + encrypted: false, + decrypted: true, + body: 'asd' + }; + + dao.decryptBody({ + message: message + }, done); + }); + + it('should do nothing when the message is already decrypted', function(done) { + var message = { + encrypted: true, + decrypted: true, + body: 'asd' + }; + + dao.decryptBody({ + message: message + }, done); + }); + + it('should do nothing when the message has no body', function(done) { + var message = { + encrypted: true, + decrypted: false, + body: '' + }; + + dao.decryptBody({ + message: message + }, done); + }); + + it('should do nothing when the message is decrypting', function(done) { + var message = { + encrypted: true, + decrypted: false, + body: 'asd', + decryptingBody: true + }; + + dao.decryptBody({ + message: message + }, done); + }); + + it('decrypt a pgp/mime message', function(done) { + var message, ct, pt, parsed; + + pt = 'bender is great'; + ct = '-----BEGIN PGP MESSAGE-----asdasdasd-----END PGP MESSAGE-----'; + parsed = 'bender! bender! bender!'; + message = { + from: [{ + address: 'asdasdasd' + }], + body: ct, + encrypted: true, + bodyParts: [{ type: 'encrypted', + content: ct + }] + }; + + keychainStub.getReceiverPublicKey.withArgs(message.from[0].address).yieldsAsync(null, mockKeyPair.publicKey); + pgpStub.decrypt.withArgs(ct, mockKeyPair.publicKey.publicKey).yieldsAsync(null, pt, true); + parseStub.withArgs({ + bodyParts: [{ + type: 'encrypted', + content: ct, + raw: pt + }] + }).yieldsAsync(null, [{ + type: 'encrypted', + content: [{ + type: 'text', + content: parsed + }] + }]); + + dao.decryptBody({ + message: message + }, function(error, msg) { + expect(error).to.not.exist; + expect(msg).to.equal(message); + expect(message.decrypted).to.be.true; + expect(message.signed).to.be.true; + expect(message.signaturesValid).to.be.true; + expect(message.body).to.equal(parsed); + expect(message.decryptingBody).to.be.false; + expect(keychainStub.getReceiverPublicKey.calledOnce).to.be.true; + expect(pgpStub.decrypt.calledOnce).to.be.true; + expect(parseStub.calledOnce).to.be.true; + + done(); + }); + + expect(message.decryptingBody).to.be.true; + }); + + it('decrypt a pgp/mime message with inner signature', function(done) { + var message, ct, pt, parsed, signed, signedMimeTree, signature; + + pt = 'bender is great'; + ct = '-----BEGIN PGP MESSAGE-----asdasdasd-----END PGP MESSAGE-----'; + signedMimeTree = 'trallalalalala'; + signature = 'ugauga'; + signed = 'omg signed text'; + parsed = 'bender! bender! bender!'; + message = { + from: [{ + address: 'asdasdasd' + }], + body: ct, + encrypted: true, + bodyParts: [{ + type: 'encrypted', + content: ct + }] + }; + + keychainStub.getReceiverPublicKey.withArgs(message.from[0].address).yieldsAsync(null, mockKeyPair.publicKey); + pgpStub.decrypt.withArgs(ct, mockKeyPair.publicKey.publicKey).yieldsAsync(null, pt, undefined); + pgpStub.verifySignedMessage.withArgs(signedMimeTree, signature, mockKeyPair.publicKey.publicKey).yieldsAsync(null, true); + + parseStub.withArgs({ + bodyParts: [{ + type: 'encrypted', + content: ct, + raw: pt + }] + }).yieldsAsync(null, [{ + type: 'encrypted', + content: [{ + type: 'signed', content: [{ - type: 'signed', - content: [{ - type: 'text', - content: signed - }], - signedMessage: signedMimeTree, - signature: signature - }] - }]); + type: 'text', + content: signed + }], + signedMessage: signedMimeTree, + signature: signature + }] + }]); - dao.decryptBody({ - message: message - }, function(error, msg) { - expect(error).to.not.exist; - expect(msg).to.equal(message); - expect(message.decrypted).to.be.true; - expect(message.body).to.equal(signed); - expect(message.signed).to.be.true; - expect(message.signaturesValid).to.be.true; - expect(message.decryptingBody).to.be.false; - expect(keychainStub.getReceiverPublicKey.calledTwice).to.be.true; - expect(pgpStub.decrypt.calledOnce).to.be.true; - expect(pgpStub.verifySignedMessage.calledOnce).to.be.true; - expect(parseStub.calledOnce).to.be.true; + dao.decryptBody({ + message: message + }, function(error, msg) { + expect(error).to.not.exist; + expect(msg).to.equal(message); + expect(message.decrypted).to.be.true; + expect(message.body).to.equal(signed); + expect(message.signed).to.be.true; + expect(message.signaturesValid).to.be.true; + expect(message.decryptingBody).to.be.false; + expect(keychainStub.getReceiverPublicKey.calledTwice).to.be.true; + expect(pgpStub.decrypt.calledOnce).to.be.true; + expect(pgpStub.verifySignedMessage.calledOnce).to.be.true; + expect(parseStub.calledOnce).to.be.true; - done(); - }); - - expect(message.decryptingBody).to.be.true; + done(); }); - it('decrypt a pgp/inline message', function(done) { - var message, ct, pt; + expect(message.decryptingBody).to.be.true; + }); - pt = 'bender is great'; - ct = '-----BEGIN PGP MESSAGE-----asdasdasd-----END PGP MESSAGE-----'; - message = { - from: [{ - address: 'asdasdasd' - }], - body: ct, - encrypted: true, - bodyParts: [{ - type: 'encrypted', - content: ct, - _isPgpInline: true - }] - }; + it('decrypt a pgp/inline message', function(done) { + var message, ct, pt; - keychainStub.getReceiverPublicKey.withArgs(message.from[0].address).yieldsAsync(null, mockKeyPair.publicKey); - pgpStub.decrypt.withArgs(ct, mockKeyPair.publicKey.publicKey).yieldsAsync(null, pt, true); + pt = 'bender is great'; + ct = '-----BEGIN PGP MESSAGE-----asdasdasd-----END PGP MESSAGE-----'; + message = { + from: [{ + address: 'asdasdasd' + }], + body: ct, + encrypted: true, + bodyParts: [{ + type: 'encrypted', + content: ct, + _isPgpInline: true + }] + }; - dao.decryptBody({ - message: message - }, function(error, msg) { - expect(error).to.not.exist; + keychainStub.getReceiverPublicKey.withArgs(message.from[0].address).yieldsAsync(null, mockKeyPair.publicKey); + pgpStub.decrypt.withArgs(ct, mockKeyPair.publicKey.publicKey).yieldsAsync(null, pt, true); - expect(msg).to.equal(message); - expect(message.decrypted).to.be.true; - expect(message.body).to.equal(pt); - expect(message.decryptingBody).to.be.false; - expect(message.signed).to.be.true; - expect(message.signaturesValid).to.be.true; - expect(keychainStub.getReceiverPublicKey.calledOnce).to.be.true; - expect(pgpStub.decrypt.calledOnce).to.be.true; - expect(parseStub.called).to.be.false; + dao.decryptBody({ + message: message + }, function(error, msg) { + expect(error).to.not.exist; - done(); - }); + expect(msg).to.equal(message); + expect(message.decrypted).to.be.true; + expect(message.body).to.equal(pt); + expect(message.decryptingBody).to.be.false; + expect(message.signed).to.be.true; + expect(message.signaturesValid).to.be.true; + expect(keychainStub.getReceiverPublicKey.calledOnce).to.be.true; + expect(pgpStub.decrypt.calledOnce).to.be.true; + expect(parseStub.called).to.be.false; - expect(message.decryptingBody).to.be.true; + done(); }); - it('should fail during decryption message', function(done) { - var message = { - from: [{ - address: 'asdasdasd' - }], - body: 'asdjafuad', - encrypted: true, - bodyParts: [{ - type: 'encrypted', - content: '-----BEGIN PGP MESSAGE-----asdasdasd-----END PGP MESSAGE-----' - }] - }; + expect(message.decryptingBody).to.be.true; + }); - keychainStub.getReceiverPublicKey.yieldsAsync(null, mockKeyPair.publicKey); - pgpStub.decrypt.yieldsAsync(new Error('fail.')); + it('should fail during decryption message', function(done) { + var message = { + from: [{ + address: 'asdasdasd' + }], + body: 'asdjafuad', + encrypted: true, + bodyParts: [{ + type: 'encrypted', + content: '-----BEGIN PGP MESSAGE-----asdasdasd-----END PGP MESSAGE-----' + }] + }; - dao.decryptBody({ - message: message - }, function(error, msg) { - expect(error).to.not.exist; - expect(msg.body).to.equal('fail.'); - expect(msg).to.exist; - expect(message.decryptingBody).to.be.false; - expect(keychainStub.getReceiverPublicKey.calledOnce).to.be.true; - expect(pgpStub.decrypt.calledOnce).to.be.true; - expect(parseStub.called).to.be.false; + keychainStub.getReceiverPublicKey.yieldsAsync(null, mockKeyPair.publicKey); + pgpStub.decrypt.yieldsAsync(new Error('fail.')); - done(); - }); - }); + dao.decryptBody({ + message: message + }, function(error, msg) { + expect(error).to.not.exist; + expect(msg.body).to.equal('fail.'); + expect(msg).to.exist; + expect(message.decryptingBody).to.be.false; + expect(keychainStub.getReceiverPublicKey.calledOnce).to.be.true; + expect(pgpStub.decrypt.calledOnce).to.be.true; + expect(parseStub.called).to.be.false; - it('should fail during key export', function(done) { - var message = { - from: [{ - address: 'asdasdasd' - }], - encrypted: true, - body: 'asdjafuad', - bodyParts: [{ - type: 'encrypted', - content: '-----BEGIN PGP MESSAGE-----asdasdasd-----END PGP MESSAGE-----' - }] - }; - - keychainStub.getReceiverPublicKey.yieldsAsync({}); - - dao.decryptBody({ - message: message - }, function(error, msg) { - expect(error).to.exist; - expect(msg).to.not.exist; - expect(message.decryptingBody).to.be.false; - expect(keychainStub.getReceiverPublicKey.calledOnce).to.be.true; - expect(pgpStub.decrypt.called).to.be.false; - expect(parseStub.called).to.be.false; - - done(); - }); + done(); }); }); - describe('#sendEncrypted', function() { - var publicKeys = ["PUBLIC KEY"], - dummyMail = { - publicKeysArmored: publicKeys - }; + it('should fail during key export', function(done) { + var message = { + from: [{ + address: 'asdasdasd' + }], + encrypted: true, + body: 'asdjafuad', + bodyParts: [{ + type: 'encrypted', + content: '-----BEGIN PGP MESSAGE-----asdasdasd-----END PGP MESSAGE-----' + }] + }; - it('should send encrypted and upload to sent', function(done) { - var msg = 'wow. such message. much rfc2822.'; + keychainStub.getReceiverPublicKey.yieldsAsync({}); - imapClientStub.uploadMessage.withArgs({ - path: sentFolder.path, - message: msg - }).yields(); + dao.decryptBody({ + message: message + }, function(error, msg) { + expect(error).to.exist; + expect(msg).to.not.exist; + expect(message.decryptingBody).to.be.false; + expect(keychainStub.getReceiverPublicKey.calledOnce).to.be.true; + expect(pgpStub.decrypt.called).to.be.false; + expect(parseStub.called).to.be.false; - pgpMailerStub.send.withArgs({ - encrypt: true, - mail: dummyMail, - smtpclient: undefined, - publicKeysArmored: publicKeys - }).yieldsAsync(null, msg); - - dao.sendEncrypted({ - email: dummyMail - }, function(err) { - expect(err).to.not.exist; - - expect(pgpMailerStub.send.calledOnce).to.be.true; - expect(imapClientStub.uploadMessage.calledOnce).to.be.true; - - done(); - }); - }); - - it('should send encrypted and not upload to sent', function(done) { - var msg = 'wow. such message. much rfc2822.'; - - dao.ignoreUploadOnSent = true; - - pgpMailerStub.send.withArgs({ - encrypt: true, - mail: dummyMail, - smtpclient: undefined, - publicKeysArmored: publicKeys - }).yieldsAsync(null, msg); - - dao.sendEncrypted({ - email: dummyMail - }, function(err) { - expect(err).to.not.exist; - - expect(pgpMailerStub.send.calledOnce).to.be.true; - expect(imapClientStub.uploadMessage.called).to.be.false; - - done(); - }); - }); - - it('should not send when pgpmailer fails', function(done) { - pgpMailerStub.send.yieldsAsync({}); - - dao.sendEncrypted({ - email: dummyMail - }, function(err) { - expect(err).to.exist; - - expect(pgpMailerStub.send.calledOnce).to.be.true; - expect(imapClientStub.uploadMessage.called).to.be.false; - - done(); - }); - }); - - it('should not send in offline mode', function(done) { - account.online = false; - - dao.sendEncrypted({}, function(err) { - expect(err).to.exist; - expect(pgpMailerStub.send.called).to.be.false; - expect(imapClientStub.uploadMessage.called).to.be.false; - done(); - }); - }); - - }); - - describe('#sendPlaintext', function() { - var dummyMail = {}; - - it('should send in the plain and upload to sent', function(done) { - var msg = 'wow. such message. much rfc2822.'; - - pgpMailerStub.send.withArgs({ - smtpclient: undefined, - mail: dummyMail - }).yieldsAsync(null, msg); - - imapClientStub.uploadMessage.withArgs({ - path: sentFolder.path, - message: msg - }).yields(); - - dao.sendPlaintext({ - email: dummyMail - }, function(err) { - expect(err).to.not.exist; - expect(pgpMailerStub.send.calledOnce).to.be.true; - expect(imapClientStub.uploadMessage.calledOnce).to.be.true; - done(); - }); - }); - - it('should send in the plain and not upload to sent', function(done) { - var msg = 'wow. such message. much rfc2822.'; - - dao.ignoreUploadOnSent = true; - - pgpMailerStub.send.withArgs({ - smtpclient: undefined, - mail: dummyMail - }).yieldsAsync(null, msg); - - dao.sendPlaintext({ - email: dummyMail - }, function(err) { - expect(err).to.not.exist; - expect(pgpMailerStub.send.calledOnce).to.be.true; - expect(imapClientStub.uploadMessage.called).to.be.false; - done(); - }); - }); - - it('should not send due to error', function(done) { - pgpMailerStub.send.yieldsAsync({}); - - dao.sendPlaintext({ - email: dummyMail - }, function(err) { - expect(err).to.exist; - expect(pgpMailerStub.send.calledOnce).to.be.true; - expect(imapClientStub.uploadMessage.called).to.be.false; - done(); - }); - }); - - it('should not send in offline mode', function(done) { - account.online = false; - - dao.sendPlaintext({}, function(err) { - expect(err).to.exist; - expect(pgpMailerStub.send.called).to.be.false; - expect(imapClientStub.uploadMessage.called).to.be.false; - done(); - }); - }); - }); - - describe('#encrypt', function() { - it('should encrypt', function(done) { - pgpBuilderStub.encrypt.yieldsAsync(); - - dao.encrypt({}, function() { - expect(pgpBuilderStub.encrypt.calledOnce).to.be.true; - done(); - }); + done(); }); }); }); - describe('event handlers', function() { + describe('#sendEncrypted', function() { + var publicKeys = ["PUBLIC KEY"], + dummyMail = { + publicKeysArmored: publicKeys + }; - describe('#onConnect', function() { - var initFoldersStub; + it('should send encrypted and upload to sent', function(done) { + var msg = 'wow. such message. much rfc2822.'; - beforeEach(function() { - initFoldersStub = sinon.stub(dao, '_initFoldersFromImap'); - delete dao._imapClient; - delete dao._pgpMailer; - }); + imapClientStub.uploadMessage.withArgs({ + path: sentFolder.path, + message: msg + }).yields(); - it('should connect', function(done) { - inboxFolder.messages = [{ - uid: 123, - modseq: 123 - }]; - imapClientStub.login.yieldsAsync(); - imapClientStub.listenForChanges.yieldsAsync(); - initFoldersStub.yieldsAsync(); + pgpMailerStub.send.withArgs({ + encrypt: true, + mail: dummyMail, + smtpclient: undefined, + publicKeysArmored: publicKeys + }).yieldsAsync(null, msg); - dao.onConnect({ - imapClient: imapClientStub, - pgpMailer: pgpMailerStub - }, function(err) { + dao.sendEncrypted({ + email: dummyMail + }, function(err) { + expect(err).to.not.exist; - expect(err).to.not.exist; - expect(imapClientStub.login.calledOnce).to.be.true; - expect(initFoldersStub.calledOnce).to.be.true; - expect(imapClientStub.mailboxCache).to.deep.equal({ - 'INBOX': { - exists: 123, - uidNext: 124, - uidlist: [123], - highestModseq: 123 - } - }); + expect(pgpMailerStub.send.calledOnce).to.be.true; + expect(imapClientStub.uploadMessage.calledOnce).to.be.true; - done(); - }); + done(); }); }); - describe('#onDisconnect', function() { - it('should discard imapClient and pgpMailer', function(done) { - imapClientStub.logout.yieldsAsync(); + it('should send encrypted and not upload to sent', function(done) { + var msg = 'wow. such message. much rfc2822.'; - dao.onDisconnect(done); + dao.ignoreUploadOnSent = true; - expect(dao._account.online).to.be.false; - expect(dao._imapClient).to.not.exist; - expect(dao._pgpMailer).to.not.exist; + pgpMailerStub.send.withArgs({ + encrypt: true, + mail: dummyMail, + smtpclient: undefined, + publicKeysArmored: publicKeys + }).yieldsAsync(null, msg); + + dao.sendEncrypted({ + email: dummyMail + }, function(err) { + expect(err).to.not.exist; + + expect(pgpMailerStub.send.calledOnce).to.be.true; + expect(imapClientStub.uploadMessage.called).to.be.false; + + done(); }); }); - describe('#_onSyncUpdate', function() { - var fetchMessagesStub, deleteMessagesStub, setFlagsStub, msgs; + it('should not send when pgpmailer fails', function(done) { + pgpMailerStub.send.yieldsAsync({}); - beforeEach(function() { - msgs = [{ - uid: 5, - flags: ['\\Answered', '\\Seen'] - }]; - inboxFolder.messages = msgs; - fetchMessagesStub = sinon.stub(dao, 'fetchMessages'); - deleteMessagesStub = sinon.stub(dao, 'deleteMessage'); - setFlagsStub = sinon.stub(dao, 'setFlags'); + dao.sendEncrypted({ + email: dummyMail + }, function(err) { + expect(err).to.exist; + + expect(pgpMailerStub.send.calledOnce).to.be.true; + expect(imapClientStub.uploadMessage.called).to.be.false; + + done(); }); + }); - it('should get new message', function(done) { - fetchMessagesStub.withArgs({ - folder: inboxFolder, - firstUid: 1, - lastUid: 3 - }).yieldsAsync(); + it('should not send in offline mode', function(done) { + account.online = false; - dao.onError = function(err) { - expect(err).to.not.exist; - expect(fetchMessagesStub.calledOnce).to.be.true; - done(); - }; - - dao._onSyncUpdate({ - type: 'new', - path: inboxFolder.path, - list: [1, 3] - }); + dao.sendEncrypted({}, function(err) { + expect(err).to.exist; + expect(pgpMailerStub.send.called).to.be.false; + expect(imapClientStub.uploadMessage.called).to.be.false; + done(); }); + }); - it('should delete message', function(done) { - deleteMessagesStub.withArgs({ - folder: inboxFolder, - message: msgs[0], - localOnly: true - }).yieldsAsync(); + }); - dao.onError = function(err) { - expect(err).to.not.exist; - expect(deleteMessagesStub.calledOnce).to.be.true; - done(); - }; + describe('#sendPlaintext', function() { + var dummyMail = {}; - dao._onSyncUpdate({ - type: 'deleted', - path: inboxFolder.path, - list: [5] - }); + it('should send in the plain and upload to sent', function(done) { + var msg = 'wow. such message. much rfc2822.'; + + pgpMailerStub.send.withArgs({ + smtpclient: undefined, + mail: dummyMail + }).yieldsAsync(null, msg); + + imapClientStub.uploadMessage.withArgs({ + path: sentFolder.path, + message: msg + }).yields(); + + dao.sendPlaintext({ + email: dummyMail + }, function(err) { + expect(err).to.not.exist; + expect(pgpMailerStub.send.calledOnce).to.be.true; + expect(imapClientStub.uploadMessage.calledOnce).to.be.true; + done(); }); + }); - it('should fetch flags', function(done) { - setFlagsStub.withArgs({ - folder: inboxFolder, - message: msgs[0], - localOnly: true - }).yieldsAsync(); + it('should send in the plain and not upload to sent', function(done) { + var msg = 'wow. such message. much rfc2822.'; - dao.onError = function(err) { - expect(err).to.not.exist; - expect(setFlagsStub.calledOnce).to.be.true; - done(); - }; + dao.ignoreUploadOnSent = true; - dao._onSyncUpdate({ - type: 'messages', - path: inboxFolder.path, - list: msgs - }); + pgpMailerStub.send.withArgs({ + smtpclient: undefined, + mail: dummyMail + }).yieldsAsync(null, msg); + + dao.sendPlaintext({ + email: dummyMail + }, function(err) { + expect(err).to.not.exist; + expect(pgpMailerStub.send.calledOnce).to.be.true; + expect(imapClientStub.uploadMessage.called).to.be.false; + done(); + }); + }); + + it('should not send due to error', function(done) { + pgpMailerStub.send.yieldsAsync({}); + + dao.sendPlaintext({ + email: dummyMail + }, function(err) { + expect(err).to.exist; + expect(pgpMailerStub.send.calledOnce).to.be.true; + expect(imapClientStub.uploadMessage.called).to.be.false; + done(); + }); + }); + + it('should not send in offline mode', function(done) { + account.online = false; + + dao.sendPlaintext({}, function(err) { + expect(err).to.exist; + expect(pgpMailerStub.send.called).to.be.false; + expect(imapClientStub.uploadMessage.called).to.be.false; + done(); }); }); }); + describe('#encrypt', function() { + it('should encrypt', function(done) { + pgpBuilderStub.encrypt.yieldsAsync(); - describe('internal API', function() { - describe('#_checkSignatures', function() { - it('should check signatures in clearsigned message', function(done) { - var message = { - from: [{ - address: 'asdasdasd' - }], - clearSignedMessage: 'trallalalalala' - }; - - keychainStub.getReceiverPublicKey.withArgs(message.from[0].address).yieldsAsync(null, mockKeyPair.publicKey); - pgpStub.verifyClearSignedMessage.withArgs(message.clearSignedMessage, mockKeyPair.publicKey.publicKey).yieldsAsync(null, true); - - dao._checkSignatures(message, function(error, signaturesValid) { - expect(error).to.not.exist; - expect(signaturesValid).to.be.true; - expect(keychainStub.getReceiverPublicKey.calledOnce).to.be.true; - expect(pgpStub.verifyClearSignedMessage.calledOnce).to.be.true; - done(); - }); + dao.encrypt({}, function() { + expect(pgpBuilderStub.encrypt.calledOnce).to.be.true; + done(); }); - - it('should check signatures in pgp/mime signed message', function(done) { - var message = { - from: [{ - address: 'asdasdasd' - }], - signedMessage: 'trallalalalala', - signature: 'ugauga' - }; - - keychainStub.getReceiverPublicKey.withArgs(message.from[0].address).yieldsAsync(null, mockKeyPair.publicKey); - pgpStub.verifySignedMessage.withArgs(message.signedMessage, message.signature, mockKeyPair.publicKey.publicKey).yieldsAsync(null, true); - - dao._checkSignatures(message, function(error, signaturesValid) { - expect(error).to.not.exist; - expect(signaturesValid).to.be.true; - expect(keychainStub.getReceiverPublicKey.calledOnce).to.be.true; - expect(pgpStub.verifySignedMessage.calledOnce).to.be.true; - done(); - }); - }); - - it('should error while checking signatures', function(done) { - var message = { - from: [{ - address: 'asdasdasd' - }], - signedMessage: 'trallalalalala', - signature: 'ugauga' - }; - - keychainStub.getReceiverPublicKey.withArgs(message.from[0].address).yieldsAsync(null, mockKeyPair.publicKey); - pgpStub.verifySignedMessage.yieldsAsync(new Error()); - - dao._checkSignatures(message, function(error, signaturesValid) { - expect(error).to.exist; - expect(signaturesValid).to.not.exist; - expect(keychainStub.getReceiverPublicKey.calledOnce).to.be.true; - expect(pgpStub.verifySignedMessage.calledOnce).to.be.true; - done(); - }); - }); - - it('should error while fetching public key', function(done) { - var message = { - from: [{ - address: 'asdasdasd' - }], - signedMessage: 'trallalalalala', - signature: 'ugauga' - }; - - keychainStub.getReceiverPublicKey.yieldsAsync(new Error()); - - dao._checkSignatures(message, function(error, signaturesValid) { - expect(error).to.exist; - expect(signaturesValid).to.not.exist; - expect(keychainStub.getReceiverPublicKey.calledOnce).to.be.true; - expect(pgpStub.verifySignedMessage.called).to.be.false; - done(); - }); - }); - }); - - describe('#_initFoldersFromDisk', function() { - beforeEach(function() { - sinon.stub(dao, 'refreshFolder'); - }); - - it('should initialize from disk if offline and not refresh folder', function(done) { - devicestorageStub.listItems.withArgs('folders').yieldsAsync(null, [ - [inboxFolder] - ]); - dao.refreshFolder.withArgs({ - folder: inboxFolder - }).yieldsAsync(); - - dao._initFoldersFromDisk(function(err) { - expect(err).to.not.exist; - expect(devicestorageStub.listItems.calledOnce).to.be.true; - expect(dao.refreshFolder.called).to.be.false; - done(); - }); - }); - - it('should initialize from disk if offline and refresh folder', function(done) { - delete inboxFolder.messages; - devicestorageStub.listItems.withArgs('folders').yieldsAsync(null, [ - [inboxFolder] - ]); - dao.refreshFolder.withArgs({ - folder: inboxFolder - }).yieldsAsync(); - - dao._initFoldersFromDisk(function(err) { - expect(err).to.not.exist; - expect(devicestorageStub.listItems.calledOnce).to.be.true; - expect(dao.refreshFolder.calledOnce).to.be.true; - done(); - }); - }); - }); - - describe('#_initFoldersFromImap', function() { - beforeEach(function() { - sinon.stub(dao, 'refreshFolder'); - }); - - it('should initialize from imap if online', function(done) { - account.folders = []; - imapClientStub.listWellKnownFolders.yieldsAsync(null, { - Inbox: [inboxFolder], - Sent: [sentFolder], - Drafts: [draftsFolder], - Trash: [trashFolder] - }); - devicestorageStub.storeList.withArgs(sinon.match(function(arg) { - expect(arg[0][0].name).to.deep.equal(inboxFolder.name); - expect(arg[0][0].path).to.deep.equal(inboxFolder.path); - expect(arg[0][0].type).to.deep.equal(inboxFolder.type); - expect(arg[0][1].name).to.deep.equal(sentFolder.name); - expect(arg[0][1].path).to.deep.equal(sentFolder.path); - expect(arg[0][1].type).to.deep.equal(sentFolder.type); - expect(arg[0][2].name).to.deep.equal(outboxFolder.name); - expect(arg[0][2].path).to.deep.equal(outboxFolder.path); - expect(arg[0][2].type).to.deep.equal(outboxFolder.type); - expect(arg[0][3].name).to.deep.equal(draftsFolder.name); - expect(arg[0][3].path).to.deep.equal(draftsFolder.path); - expect(arg[0][3].type).to.deep.equal(draftsFolder.type); - expect(arg[0][4].name).to.deep.equal(trashFolder.name); - expect(arg[0][4].path).to.deep.equal(trashFolder.path); - expect(arg[0][4].type).to.deep.equal(trashFolder.type); - return true; - }), 'folders').yieldsAsync(); - - dao.refreshFolder.yieldsAsync(); - - dao._initFoldersFromImap(function(err) { - expect(err).to.not.exist; - expect(imapClientStub.listWellKnownFolders.calledOnce).to.be.true; - expect(devicestorageStub.storeList.calledOnce).to.be.true; - done(); - }); - }); - - it('should update folders from imap', function(done) { - account.folders = [inboxFolder, outboxFolder, trashFolder, { - name: 'foo', - type: 'Sent', - path: 'bar', - }]; - - imapClientStub.listWellKnownFolders.yieldsAsync(null, { - Inbox: [inboxFolder], - Sent: [sentFolder], - Drafts: [draftsFolder], - Trash: [trashFolder] - }); - devicestorageStub.storeList.withArgs(sinon.match(function(arg) { - expect(arg[0]).to.deep.equal([{ - name: inboxFolder.name, - path: inboxFolder.path, - type: inboxFolder.type - }, { - name: outboxFolder.name, - path: outboxFolder.path, - type: outboxFolder.type - }, { - name: trashFolder.name, - path: trashFolder.path, - type: trashFolder.type - }, { - name: sentFolder.name, - path: sentFolder.path, - type: sentFolder.type - }, { - name: draftsFolder.name, - path: draftsFolder.path, - type: draftsFolder.type - }]); - - return true; - }), 'folders').yieldsAsync(); - - dao.refreshFolder.yieldsAsync(); - - dao._initFoldersFromImap(function(err) { - expect(err).to.not.exist; - expect(imapClientStub.listWellKnownFolders.calledOnce).to.be.true; - expect(devicestorageStub.storeList.calledOnce).to.be.true; - done(); - }); - }); - }); - - describe('#_imapMark', function() { - it('should flag a mail', function(done) { - imapClientStub.updateFlags.withArgs({ - path: inboxFolder.path, - folder: inboxFolder, - uid: 1, - unread: false, - answered: false - }).yieldsAsync(); - - dao._imapMark({ - folder: inboxFolder, - uid: 1, - unread: false, - answered: false - }, function(err) { - expect(err).to.not.exist; - expect(imapClientStub.updateFlags.calledOnce).to.be.true; - done(); - }); - }); - }); - - describe('#_imapDeleteMessage', function() { - var uid = 1337; - - it('should fail when disconnected', function(done) { - dao._account.online = false; - - dao._imapDeleteMessage({}, function(err) { - expect(err.code).to.equal(42); - done(); - }); - }); - - it('should move to trash', function(done) { - imapClientStub.moveMessage.withArgs({ - path: inboxFolder.path, - uid: uid, - destination: trashFolder.path - }).yieldsAsync(); - - dao._imapDeleteMessage({ - folder: inboxFolder, - uid: uid - }, done); - }); - - it('should purge message', function(done) { - imapClientStub.deleteMessage.withArgs({ - path: trashFolder.path, - uid: uid - }).yieldsAsync(); - - dao._imapDeleteMessage({ - folder: trashFolder, - uid: uid - }, done); - }); - }); - - describe('#_imapListMessages', function() { - var firstUid = 1337, - lastUid = 1339; - - it('should list messages', function(done) { - imapClientStub.listMessages.withArgs({ - folder: inboxFolder, - path: inboxFolder.path, - firstUid: firstUid, - lastUid: lastUid - }).yieldsAsync(null, []); - - dao._imapListMessages({ - folder: inboxFolder, - firstUid: firstUid, - lastUid: lastUid - }, function(err, msgs) { - expect(err).to.not.exist; - expect(msgs).to.exist; - - expect(imapClientStub.listMessages.calledOnce).to.be.true; - - done(); - }); - }); - - it('should fail when listMessages fails', function(done) { - imapClientStub.listMessages.yieldsAsync({}); - - dao._imapListMessages({ - folder: inboxFolder, - firstUid: firstUid, - lastUid: lastUid - }, function(err, msgs) { - expect(err).to.exist; - expect(msgs).to.not.exist; - expect(imapClientStub.listMessages.calledOnce).to.be.true; - - done(); - }); - }); - - it('should fail when disconnected', function(done) { - dao._account.online = false; - - dao._imapListMessages({}, function(err) { - expect(err.code).to.equal(42); - done(); - }); - }); - }); - - describe('#_getBodyParts', function() { - it('should get bodyParts', function(done) { - imapClientStub.getBodyParts.withArgs({ - folder: inboxFolder, - path: inboxFolder.path, - uid: 123, - bodyParts: [] - }).yieldsAsync(null, {}); - parseStub.yieldsAsync(null, []); - - dao._getBodyParts({ - folder: inboxFolder, - uid: 123, - bodyParts: [] - }, function(err, parts) { - expect(err).to.not.exist; - expect(parts).to.exist; - - expect(imapClientStub.getBodyParts.calledOnce).to.be.true; - expect(parseStub.calledOnce).to.be.true; - - done(); - }); - }); - - it('should fail when getBody fails', function(done) { - imapClientStub.getBodyParts.yieldsAsync({}); - - dao._getBodyParts({ - folder: inboxFolder, - uid: 123, - bodyParts: [] - }, function(err, msg) { - expect(err).to.exist; - expect(msg).to.not.exist; - - expect(imapClientStub.getBodyParts.calledOnce).to.be.true; - expect(parseStub.called).to.be.false; - - done(); - }); - }); - - it('should fail when disconnected', function(done) { - dao._account.online = false; - - dao._getBodyParts({}, function(err) { - expect(err.code).to.equal(42); - done(); - }); - }); - }); - - describe('#_localListMessages', function() { - var uid = 123; - - it('should list without uid', function(done) { - devicestorageStub.listItems.withArgs('email_' + inboxFolder.path, 0, null).yieldsAsync(); - - dao._localListMessages({ - folder: inboxFolder - }, done); - }); - - it('should list with uid', function(done) { - devicestorageStub.listItems.withArgs('email_' + inboxFolder.path + '_' + uid, 0, null).yieldsAsync(); - - dao._localListMessages({ - folder: inboxFolder, - uid: uid - }, done); - }); - - }); - - describe('#_localStoreMessages', function() { - it('should store messages', function(done) { - devicestorageStub.storeList.withArgs([{}], 'email_' + inboxFolder.path).yieldsAsync(); - - dao._localStoreMessages({ - folder: inboxFolder, - emails: [{}] - }, done); - }); - }); - - describe('#_localDeleteMessage', function() { - var uid = 1337; - - it('should delete message', function(done) { - devicestorageStub.removeList.withArgs('email_' + inboxFolder.path + '_' + uid).yieldsAsync(); - - dao._localDeleteMessage({ - folder: inboxFolder, - uid: uid - }, done); - }); - - it('should fail when uid is missing', function(done) { - dao._localDeleteMessage({ - folder: inboxFolder - }, function(err) { - expect(err).to.exist; - done(); - }); - }); - }); }); }); + + describe('event handlers', function() { + + describe('#onConnect', function() { + var initFoldersStub; + + beforeEach(function() { + initFoldersStub = sinon.stub(dao, '_initFoldersFromImap'); + delete dao._imapClient; + delete dao._pgpMailer; + }); + + it('should connect', function(done) { + inboxFolder.messages = [{ + uid: 123, + modseq: 123 + }]; + imapClientStub.login.yieldsAsync(); + imapClientStub.listenForChanges.yieldsAsync(); + initFoldersStub.yieldsAsync(); + + dao.onConnect({ + imapClient: imapClientStub, + pgpMailer: pgpMailerStub + }, function(err) { + + expect(err).to.not.exist; + expect(imapClientStub.login.calledOnce).to.be.true; + expect(initFoldersStub.calledOnce).to.be.true; + expect(imapClientStub.mailboxCache).to.deep.equal({ + 'INBOX': { + exists: 123, + uidNext: 124, + uidlist: [123], + highestModseq: 123 + } + }); + + done(); + }); + }); + }); + + describe('#onDisconnect', function() { + it('should discard imapClient and pgpMailer', function(done) { + imapClientStub.logout.yieldsAsync(); + + dao.onDisconnect(done); + + expect(dao._account.online).to.be.false; + expect(dao._imapClient).to.not.exist; + expect(dao._pgpMailer).to.not.exist; + }); + }); + + describe('#_onSyncUpdate', function() { + var fetchMessagesStub, deleteMessagesStub, setFlagsStub, msgs; + + beforeEach(function() { + msgs = [{ + uid: 5, + flags: ['\\Answered', '\\Seen'] + }]; + inboxFolder.messages = msgs; + fetchMessagesStub = sinon.stub(dao, 'fetchMessages'); + deleteMessagesStub = sinon.stub(dao, 'deleteMessage'); + setFlagsStub = sinon.stub(dao, 'setFlags'); + }); + + it('should get new message', function(done) { + fetchMessagesStub.withArgs({ + folder: inboxFolder, + firstUid: 1, + lastUid: 3 + }).yieldsAsync(); + + dao.onError = function(err) { + expect(err).to.not.exist; + expect(fetchMessagesStub.calledOnce).to.be.true; + done(); + }; + + dao._onSyncUpdate({ + type: 'new', + path: inboxFolder.path, + list: [1, 3] + }); + }); + + it('should delete message', function(done) { + deleteMessagesStub.withArgs({ + folder: inboxFolder, + message: msgs[0], + localOnly: true + }).yieldsAsync(); + + dao.onError = function(err) { + expect(err).to.not.exist; + expect(deleteMessagesStub.calledOnce).to.be.true; + done(); + }; + + dao._onSyncUpdate({ + type: 'deleted', + path: inboxFolder.path, + list: [5] + }); + }); + + it('should fetch flags', function(done) { + setFlagsStub.withArgs({ + folder: inboxFolder, + message: msgs[0], + localOnly: true + }).yieldsAsync(); + + dao.onError = function(err) { + expect(err).to.not.exist; + expect(setFlagsStub.calledOnce).to.be.true; + done(); + }; + + dao._onSyncUpdate({ + type: 'messages', + path: inboxFolder.path, + list: msgs + }); + }); + }); + }); + + + describe('internal API', function() { + describe('#_checkSignatures', function() { + it('should check signatures in clearsigned message', function(done) { + var message = { + from: [{ + address: 'asdasdasd' + }], + clearSignedMessage: 'trallalalalala' + }; + + keychainStub.getReceiverPublicKey.withArgs(message.from[0].address).yieldsAsync(null, mockKeyPair.publicKey); + pgpStub.verifyClearSignedMessage.withArgs(message.clearSignedMessage, mockKeyPair.publicKey.publicKey).yieldsAsync(null, true); + + dao._checkSignatures(message, function(error, signaturesValid) { + expect(error).to.not.exist; + expect(signaturesValid).to.be.true; + expect(keychainStub.getReceiverPublicKey.calledOnce).to.be.true; + expect(pgpStub.verifyClearSignedMessage.calledOnce).to.be.true; + done(); + }); + }); + + it('should check signatures in pgp/mime signed message', function(done) { + var message = { + from: [{ + address: 'asdasdasd' + }], + signedMessage: 'trallalalalala', + signature: 'ugauga' + }; + + keychainStub.getReceiverPublicKey.withArgs(message.from[0].address).yieldsAsync(null, mockKeyPair.publicKey); + pgpStub.verifySignedMessage.withArgs(message.signedMessage, message.signature, mockKeyPair.publicKey.publicKey).yieldsAsync(null, true); + + dao._checkSignatures(message, function(error, signaturesValid) { + expect(error).to.not.exist; + expect(signaturesValid).to.be.true; + expect(keychainStub.getReceiverPublicKey.calledOnce).to.be.true; + expect(pgpStub.verifySignedMessage.calledOnce).to.be.true; + done(); + }); + }); + + it('should error while checking signatures', function(done) { + var message = { + from: [{ + address: 'asdasdasd' + }], + signedMessage: 'trallalalalala', + signature: 'ugauga' + }; + + keychainStub.getReceiverPublicKey.withArgs(message.from[0].address).yieldsAsync(null, mockKeyPair.publicKey); + pgpStub.verifySignedMessage.yieldsAsync(new Error()); + + dao._checkSignatures(message, function(error, signaturesValid) { + expect(error).to.exist; + expect(signaturesValid).to.not.exist; + expect(keychainStub.getReceiverPublicKey.calledOnce).to.be.true; + expect(pgpStub.verifySignedMessage.calledOnce).to.be.true; + done(); + }); + }); + + it('should error while fetching public key', function(done) { + var message = { + from: [{ + address: 'asdasdasd' + }], + signedMessage: 'trallalalalala', + signature: 'ugauga' + }; + + keychainStub.getReceiverPublicKey.yieldsAsync(new Error()); + + dao._checkSignatures(message, function(error, signaturesValid) { + expect(error).to.exist; + expect(signaturesValid).to.not.exist; + expect(keychainStub.getReceiverPublicKey.calledOnce).to.be.true; + expect(pgpStub.verifySignedMessage.called).to.be.false; + done(); + }); + }); + }); + + describe('#_initFoldersFromDisk', function() { + beforeEach(function() { + sinon.stub(dao, 'refreshFolder'); + }); + + it('should initialize from disk if offline and not refresh folder', function(done) { + devicestorageStub.listItems.withArgs('folders').yieldsAsync(null, [ + [inboxFolder] + ]); + dao.refreshFolder.withArgs({ + folder: inboxFolder + }).yieldsAsync(); + + dao._initFoldersFromDisk(function(err) { + expect(err).to.not.exist; + expect(devicestorageStub.listItems.calledOnce).to.be.true; + expect(dao.refreshFolder.called).to.be.false; + done(); + }); + }); + + it('should initialize from disk if offline and refresh folder', function(done) { + delete inboxFolder.messages; + devicestorageStub.listItems.withArgs('folders').yieldsAsync(null, [ + [inboxFolder] + ]); + dao.refreshFolder.withArgs({ + folder: inboxFolder + }).yieldsAsync(); + + dao._initFoldersFromDisk(function(err) { + expect(err).to.not.exist; + expect(devicestorageStub.listItems.calledOnce).to.be.true; + expect(dao.refreshFolder.calledOnce).to.be.true; + done(); + }); + }); + }); + + describe('#_initFoldersFromImap', function() { + beforeEach(function() { + sinon.stub(dao, 'refreshFolder'); + }); + + it('should initialize from imap if online', function(done) { + account.folders = []; + imapClientStub.listWellKnownFolders.yieldsAsync(null, { + Inbox: [inboxFolder], + Sent: [sentFolder], + Drafts: [draftsFolder], + Trash: [trashFolder] + }); + devicestorageStub.storeList.withArgs(sinon.match(function(arg) { + expect(arg[0][0].name).to.deep.equal(inboxFolder.name); + expect(arg[0][0].path).to.deep.equal(inboxFolder.path); + expect(arg[0][0].type).to.deep.equal(inboxFolder.type); + expect(arg[0][1].name).to.deep.equal(sentFolder.name); + expect(arg[0][1].path).to.deep.equal(sentFolder.path); + expect(arg[0][1].type).to.deep.equal(sentFolder.type); + expect(arg[0][2].name).to.deep.equal(outboxFolder.name); + expect(arg[0][2].path).to.deep.equal(outboxFolder.path); + expect(arg[0][2].type).to.deep.equal(outboxFolder.type); + expect(arg[0][3].name).to.deep.equal(draftsFolder.name); + expect(arg[0][3].path).to.deep.equal(draftsFolder.path); + expect(arg[0][3].type).to.deep.equal(draftsFolder.type); + expect(arg[0][4].name).to.deep.equal(trashFolder.name); + expect(arg[0][4].path).to.deep.equal(trashFolder.path); + expect(arg[0][4].type).to.deep.equal(trashFolder.type); + return true; + }), 'folders').yieldsAsync(); + + dao.refreshFolder.yieldsAsync(); + + dao._initFoldersFromImap(function(err) { + expect(err).to.not.exist; + expect(imapClientStub.listWellKnownFolders.calledOnce).to.be.true; + expect(devicestorageStub.storeList.calledOnce).to.be.true; + done(); + }); + }); + + it('should update folders from imap', function(done) { + account.folders = [inboxFolder, outboxFolder, trashFolder, { + name: 'foo', + type: 'Sent', + path: 'bar', + }]; + + imapClientStub.listWellKnownFolders.yieldsAsync(null, { + Inbox: [inboxFolder], + Sent: [sentFolder], + Drafts: [draftsFolder], + Trash: [trashFolder] + }); + devicestorageStub.storeList.withArgs(sinon.match(function(arg) { + expect(arg[0]).to.deep.equal([{ + name: inboxFolder.name, + path: inboxFolder.path, + type: inboxFolder.type + }, { + name: outboxFolder.name, + path: outboxFolder.path, + type: outboxFolder.type + }, { + name: trashFolder.name, + path: trashFolder.path, + type: trashFolder.type + }, { + name: sentFolder.name, + path: sentFolder.path, + type: sentFolder.type + }, { + name: draftsFolder.name, + path: draftsFolder.path, + type: draftsFolder.type + }]); + + return true; + }), 'folders').yieldsAsync(); + + dao.refreshFolder.yieldsAsync(); + + dao._initFoldersFromImap(function(err) { + expect(err).to.not.exist; + expect(imapClientStub.listWellKnownFolders.calledOnce).to.be.true; + expect(devicestorageStub.storeList.calledOnce).to.be.true; + done(); + }); + }); + }); + + describe('#_imapMark', function() { + it('should flag a mail', function(done) { + imapClientStub.updateFlags.withArgs({ + path: inboxFolder.path, + folder: inboxFolder, + uid: 1, + unread: false, + answered: false + }).yieldsAsync(); + + dao._imapMark({ + folder: inboxFolder, + uid: 1, + unread: false, + answered: false + }, function(err) { + expect(err).to.not.exist; + expect(imapClientStub.updateFlags.calledOnce).to.be.true; + done(); + }); + }); + }); + + describe('#_imapDeleteMessage', function() { + var uid = 1337; + + it('should fail when disconnected', function(done) { + dao._account.online = false; + + dao._imapDeleteMessage({}, function(err) { + expect(err.code).to.equal(42); + done(); + }); + }); + + it('should move to trash', function(done) { + imapClientStub.moveMessage.withArgs({ + path: inboxFolder.path, + uid: uid, + destination: trashFolder.path + }).yieldsAsync(); + + dao._imapDeleteMessage({ + folder: inboxFolder, + uid: uid + }, done); + }); + + it('should purge message', function(done) { + imapClientStub.deleteMessage.withArgs({ + path: trashFolder.path, + uid: uid + }).yieldsAsync(); + + dao._imapDeleteMessage({ + folder: trashFolder, + uid: uid + }, done); + }); + }); + + describe('#_imapListMessages', function() { + var firstUid = 1337, + lastUid = 1339; + + it('should list messages', function(done) { + imapClientStub.listMessages.withArgs({ + folder: inboxFolder, + path: inboxFolder.path, + firstUid: firstUid, + lastUid: lastUid + }).yieldsAsync(null, []); + + dao._imapListMessages({ + folder: inboxFolder, + firstUid: firstUid, + lastUid: lastUid + }, function(err, msgs) { + expect(err).to.not.exist; + expect(msgs).to.exist; + + expect(imapClientStub.listMessages.calledOnce).to.be.true; + + done(); + }); + }); + + it('should fail when listMessages fails', function(done) { + imapClientStub.listMessages.yieldsAsync({}); + + dao._imapListMessages({ + folder: inboxFolder, + firstUid: firstUid, + lastUid: lastUid + }, function(err, msgs) { + expect(err).to.exist; + expect(msgs).to.not.exist; + expect(imapClientStub.listMessages.calledOnce).to.be.true; + + done(); + }); + }); + + it('should fail when disconnected', function(done) { + dao._account.online = false; + + dao._imapListMessages({}, function(err) { + expect(err.code).to.equal(42); + done(); + }); + }); + }); + + describe('#_getBodyParts', function() { + it('should get bodyParts', function(done) { + imapClientStub.getBodyParts.withArgs({ + folder: inboxFolder, + path: inboxFolder.path, + uid: 123, + bodyParts: [] + }).yieldsAsync(null, {}); + parseStub.yieldsAsync(null, []); + + dao._getBodyParts({ + folder: inboxFolder, + uid: 123, + bodyParts: [] + }, function(err, parts) { + expect(err).to.not.exist; + expect(parts).to.exist; + + expect(imapClientStub.getBodyParts.calledOnce).to.be.true; + expect(parseStub.calledOnce).to.be.true; + + done(); + }); + }); + + it('should fail when getBody fails', function(done) { + imapClientStub.getBodyParts.yieldsAsync({}); + + dao._getBodyParts({ + folder: inboxFolder, + uid: 123, + bodyParts: [] + }, function(err, msg) { + expect(err).to.exist; + expect(msg).to.not.exist; + + expect(imapClientStub.getBodyParts.calledOnce).to.be.true; + expect(parseStub.called).to.be.false; + + done(); + }); + }); + + it('should fail when disconnected', function(done) { + dao._account.online = false; + + dao._getBodyParts({}, function(err) { + expect(err.code).to.equal(42); + done(); + }); + }); + }); + + describe('#_localListMessages', function() { + var uid = 123; + + it('should list without uid', function(done) { + devicestorageStub.listItems.withArgs('email_' + inboxFolder.path, 0, null).yieldsAsync(); + + dao._localListMessages({ + folder: inboxFolder + }, done); + }); + + it('should list with uid', function(done) { + devicestorageStub.listItems.withArgs('email_' + inboxFolder.path + '_' + uid, 0, null).yieldsAsync(); + + dao._localListMessages({ + folder: inboxFolder, + uid: uid + }, done); + }); + + }); + + describe('#_localStoreMessages', function() { + it('should store messages', function(done) { + devicestorageStub.storeList.withArgs([{}], 'email_' + inboxFolder.path).yieldsAsync(); + + dao._localStoreMessages({ + folder: inboxFolder, + emails: [{}] + }, done); + }); + }); + + describe('#_localDeleteMessage', function() { + var uid = 1337; + + it('should delete message', function(done) { + devicestorageStub.removeList.withArgs('email_' + inboxFolder.path + '_' + uid).yieldsAsync(); + + dao._localDeleteMessage({ + folder: inboxFolder, + uid: uid + }, done); + }); + + it('should fail when uid is missing', function(done) { + dao._localDeleteMessage({ + folder: inboxFolder + }, function(err) { + expect(err).to.exist; + done(); + }); + }); + + }); + }); }); \ No newline at end of file diff --git a/test/unit/index.html b/test/unit/index.html index 8a0094a..c6366e0 100644 --- a/test/unit/index.html +++ b/test/unit/index.html @@ -8,12 +8,71 @@
+ + - + - + + + +