mirror of
https://github.com/moparisthebest/mail
synced 2024-12-22 07:18:49 -05:00
Merge pull request #299 from whiteout-io/dev/WO-854
Show invite dialog in writer when recipient has no public key
This commit is contained in:
commit
6873fd7f3d
@ -12,6 +12,7 @@ module.exports = appCfg;
|
|||||||
* Global app configurations
|
* Global app configurations
|
||||||
*/
|
*/
|
||||||
appCfg.config = {
|
appCfg.config = {
|
||||||
|
pgpComment: 'Whiteout Mail - https://whiteout.io',
|
||||||
keyServerUrl: 'https://keys.whiteout.io',
|
keyServerUrl: 'https://keys.whiteout.io',
|
||||||
hkpUrl: 'http://keyserver.ubuntu.com',
|
hkpUrl: 'http://keyserver.ubuntu.com',
|
||||||
privkeyServerUrl: 'https://keychain.whiteout.io',
|
privkeyServerUrl: 'https://keychain.whiteout.io',
|
||||||
|
@ -6,8 +6,6 @@
|
|||||||
|
|
||||||
var ReadCtrl = function($scope, $location, $q, email, invitation, outbox, pgp, keychain, appConfig, download, auth, dialog, status) {
|
var ReadCtrl = function($scope, $location, $q, email, invitation, outbox, pgp, keychain, appConfig, download, auth, dialog, status) {
|
||||||
|
|
||||||
var str = appConfig.string;
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// scope state
|
// scope state
|
||||||
//
|
//
|
||||||
@ -158,18 +156,10 @@ var ReadCtrl = function($scope, $location, $q, email, invitation, outbox, pgp, k
|
|||||||
});
|
});
|
||||||
|
|
||||||
}).then(function() {
|
}).then(function() {
|
||||||
var invitationMail = {
|
var invitationMail = invitation.createMail({
|
||||||
from: [{
|
sender: sender,
|
||||||
address: sender
|
recipient: recipient
|
||||||
}],
|
});
|
||||||
to: [{
|
|
||||||
address: recipient
|
|
||||||
}],
|
|
||||||
cc: [],
|
|
||||||
bcc: [],
|
|
||||||
subject: str.invitationSubject,
|
|
||||||
body: str.invitationMessage
|
|
||||||
};
|
|
||||||
// send invitation mail
|
// send invitation mail
|
||||||
return outbox.put(invitationMail);
|
return outbox.put(invitationMail);
|
||||||
|
|
||||||
|
@ -6,7 +6,7 @@ var util = require('crypto-lib').util;
|
|||||||
// Controller
|
// Controller
|
||||||
//
|
//
|
||||||
|
|
||||||
var WriteCtrl = function($scope, $window, $filter, $q, appConfig, auth, keychain, pgp, email, outbox, dialog, axe, status) {
|
var WriteCtrl = function($scope, $window, $filter, $q, appConfig, auth, keychain, pgp, email, outbox, dialog, axe, status, invitation) {
|
||||||
|
|
||||||
var str = appConfig.string;
|
var str = appConfig.string;
|
||||||
var cfg = appConfig.config;
|
var cfg = appConfig.config;
|
||||||
@ -52,6 +52,8 @@ var WriteCtrl = function($scope, $window, $filter, $q, appConfig, auth, keychain
|
|||||||
$scope.body = '';
|
$scope.body = '';
|
||||||
$scope.attachments = [];
|
$scope.attachments = [];
|
||||||
$scope.addressBookCache = undefined;
|
$scope.addressBookCache = undefined;
|
||||||
|
$scope.showInvite = undefined;
|
||||||
|
$scope.invited = [];
|
||||||
}
|
}
|
||||||
|
|
||||||
function reportBug() {
|
function reportBug() {
|
||||||
@ -248,6 +250,9 @@ var WriteCtrl = function($scope, $window, $filter, $q, appConfig, auth, keychain
|
|||||||
recipient.key = key;
|
recipient.key = key;
|
||||||
recipient.secure = true;
|
recipient.secure = true;
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
// show invite dialog if no key found
|
||||||
|
$scope.showInvite = true;
|
||||||
}
|
}
|
||||||
$scope.checkSendStatus();
|
$scope.checkSendStatus();
|
||||||
|
|
||||||
@ -286,6 +291,7 @@ var WriteCtrl = function($scope, $window, $filter, $q, appConfig, auth, keychain
|
|||||||
|
|
||||||
// only allow sending if receviers exist
|
// only allow sending if receviers exist
|
||||||
if (numReceivers < 1) {
|
if (numReceivers < 1) {
|
||||||
|
$scope.showInvite = false;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -299,6 +305,7 @@ var WriteCtrl = function($scope, $window, $filter, $q, appConfig, auth, keychain
|
|||||||
$scope.okToSend = true;
|
$scope.okToSend = true;
|
||||||
$scope.sendBtnText = str.sendBtnSecure;
|
$scope.sendBtnText = str.sendBtnSecure;
|
||||||
$scope.sendBtnSecure = true;
|
$scope.sendBtnSecure = true;
|
||||||
|
$scope.showInvite = false;
|
||||||
} else {
|
} else {
|
||||||
// send plaintext
|
// send plaintext
|
||||||
$scope.okToSend = true;
|
$scope.okToSend = true;
|
||||||
@ -315,6 +322,56 @@ var WriteCtrl = function($scope, $window, $filter, $q, appConfig, auth, keychain
|
|||||||
$scope.attachments.splice($scope.attachments.indexOf(attachment), 1);
|
$scope.attachments.splice($scope.attachments.indexOf(attachment), 1);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Invite all users without a public key
|
||||||
|
*/
|
||||||
|
$scope.invite = function() {
|
||||||
|
var sender = auth.emailAddress,
|
||||||
|
sendJobs = [],
|
||||||
|
invitees = [];
|
||||||
|
|
||||||
|
$scope.showInvite = false;
|
||||||
|
|
||||||
|
// get recipients with no keys
|
||||||
|
$scope.to.forEach(check);
|
||||||
|
$scope.cc.forEach(check);
|
||||||
|
$scope.bcc.forEach(check);
|
||||||
|
|
||||||
|
function check(recipient) {
|
||||||
|
if (util.validateEmailAddress(recipient.address) && !recipient.secure && $scope.invited.indexOf(recipient.address) === -1) {
|
||||||
|
invitees.push(recipient.address);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $q(function(resolve) {
|
||||||
|
resolve();
|
||||||
|
|
||||||
|
}).then(function() {
|
||||||
|
invitees.forEach(function(recipientAddress) {
|
||||||
|
var invitationMail = invitation.createMail({
|
||||||
|
sender: sender,
|
||||||
|
recipient: recipientAddress
|
||||||
|
});
|
||||||
|
// send invitation mail
|
||||||
|
var promise = outbox.put(invitationMail).then(function() {
|
||||||
|
return invitation.invite({
|
||||||
|
recipient: recipientAddress,
|
||||||
|
sender: sender
|
||||||
|
});
|
||||||
|
});
|
||||||
|
sendJobs.push(promise);
|
||||||
|
// remember already invited users to prevent spamming
|
||||||
|
$scope.invited.push(recipientAddress);
|
||||||
|
});
|
||||||
|
|
||||||
|
return Promise.all(sendJobs);
|
||||||
|
|
||||||
|
}).catch(function(err) {
|
||||||
|
$scope.showInvite = true;
|
||||||
|
return dialog.error(err);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
//
|
//
|
||||||
// Editing email body
|
// Editing email body
|
||||||
//
|
//
|
||||||
|
@ -11,7 +11,7 @@ var util = openpgp.util,
|
|||||||
* High level crypto api that handles all calls to OpenPGP.js
|
* High level crypto api that handles all calls to OpenPGP.js
|
||||||
*/
|
*/
|
||||||
function PGP() {
|
function PGP() {
|
||||||
openpgp.config.commentstring = 'Whiteout Mail - https://whiteout.io';
|
openpgp.config.commentstring = config.pgpComment;
|
||||||
openpgp.config.prefer_hash_algorithm = openpgp.enums.hash.sha256;
|
openpgp.config.prefer_hash_algorithm = openpgp.enums.hash.sha256;
|
||||||
openpgp.initWorker(config.workerPath + '/openpgp.worker.min.js');
|
openpgp.initWorker(config.workerPath + '/openpgp.worker.min.js');
|
||||||
}
|
}
|
||||||
|
@ -62,6 +62,12 @@ Outbox.prototype.put = function(mail) {
|
|||||||
var self = this,
|
var self = this,
|
||||||
allReaders = mail.from.concat(mail.to.concat(mail.cc.concat(mail.bcc))); // all the users that should be able to read the mail
|
allReaders = mail.from.concat(mail.to.concat(mail.cc.concat(mail.bcc))); // all the users that should be able to read the mail
|
||||||
|
|
||||||
|
if (mail.to.concat(mail.cc.concat(mail.bcc)).length === 0) {
|
||||||
|
return new Promise(function() {
|
||||||
|
throw new Error('Message has no recipients!');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
mail.publicKeysArmored = []; // gather the public keys
|
mail.publicKeysArmored = []; // gather the public keys
|
||||||
mail.uid = mail.id = util.UUID(); // the mail needs a random id & uid for storage in the database
|
mail.uid = mail.id = util.UUID(); // the mail needs a random id & uid for storage in the database
|
||||||
|
|
||||||
|
@ -8,13 +8,33 @@ module.exports = Invitation;
|
|||||||
* The Invitation is a high level Data Access Object that access the invitation service REST endpoint.
|
* The Invitation is a high level Data Access Object that access the invitation service REST endpoint.
|
||||||
* @param {Object} restDao The REST Data Access Object abstraction
|
* @param {Object} restDao The REST Data Access Object abstraction
|
||||||
*/
|
*/
|
||||||
function Invitation(invitationRestDao) {
|
function Invitation(invitationRestDao, appConfig) {
|
||||||
this._restDao = invitationRestDao;
|
this._restDao = invitationRestDao;
|
||||||
|
this._appConfig = appConfig;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
/**
|
||||||
// API
|
* Create the invitation mail object
|
||||||
//
|
* @param {String} options.sender The sender's email address
|
||||||
|
* @param {String} options.recipient The recipient's email address
|
||||||
|
* @return {Object} The mail object
|
||||||
|
*/
|
||||||
|
Invitation.prototype.createMail = function(options) {
|
||||||
|
var str = this._appConfig.string;
|
||||||
|
|
||||||
|
return {
|
||||||
|
from: [{
|
||||||
|
address: options.sender
|
||||||
|
}],
|
||||||
|
to: [{
|
||||||
|
address: options.recipient
|
||||||
|
}],
|
||||||
|
cc: [],
|
||||||
|
bcc: [],
|
||||||
|
subject: str.invitationSubject,
|
||||||
|
body: str.invitationMessage
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Notes an invite for the recipient by the sender in the invitation web service
|
* Notes an invite for the recipient by the sender in the invitation web service
|
||||||
|
@ -21,6 +21,33 @@
|
|||||||
margin-top: 0.5em;
|
margin-top: 0.5em;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
&__invite {
|
||||||
|
position: relative;
|
||||||
|
margin-top: 1.3em;
|
||||||
|
border: 1px solid $color-red-light;
|
||||||
|
|
||||||
|
p {
|
||||||
|
color: $color-red-light;
|
||||||
|
margin: 0.7em 1em;
|
||||||
|
|
||||||
|
svg {
|
||||||
|
width: 1em;
|
||||||
|
height: 1em;
|
||||||
|
fill: $color-red-light;
|
||||||
|
|
||||||
|
// for better valignment
|
||||||
|
position: relative;
|
||||||
|
top: 0.15em;
|
||||||
|
margin-right: 0.3em;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn {
|
||||||
|
position: absolute;
|
||||||
|
top: 5px;
|
||||||
|
right: 5px;
|
||||||
|
}
|
||||||
|
}
|
||||||
&__subject {
|
&__subject {
|
||||||
position: relative;
|
position: relative;
|
||||||
margin-top: 1.3em;
|
margin-top: 1.3em;
|
||||||
|
@ -41,6 +41,18 @@
|
|||||||
</tags-input>
|
</tags-input>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="write__invite" ng-show="showInvite">
|
||||||
|
<p>
|
||||||
|
<svg role="presentation"><use xlink:href="#icon-decrypted"/></svg>
|
||||||
|
<strong>Key not found!</strong>
|
||||||
|
<span class="u-hidden-sm">Invite user to encrypt.</span>
|
||||||
|
</p>
|
||||||
|
<button class="btn btn--light" wo-touch="invite()" title="Invite to Whiteout Mail">
|
||||||
|
<svg role="presentation"><use xlink:href="#icon-add_contact"/></svg>
|
||||||
|
Invite
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="write__subject">
|
<div class="write__subject">
|
||||||
<input class="input-text" ng-model="subject" spellcheck="true" tabindex="2" placeholder="Subject" ng-change="updatePreview()">
|
<input class="input-text" ng-model="subject" spellcheck="true" tabindex="2" placeholder="Subject" ng-change="updatePreview()">
|
||||||
<input id="attachment-input" type="file" multiple attachment-input>
|
<input id="attachment-input" type="file" multiple attachment-input>
|
||||||
@ -61,10 +73,10 @@
|
|||||||
</header>
|
</header>
|
||||||
|
|
||||||
<textarea class="write__body" ng-model="body" spellcheck="true" wo-focus-me="state.lightbox === 'write' && writerTitle === 'Reply'" tabindex="3"></textarea>
|
<textarea class="write__body" ng-model="body" spellcheck="true" wo-focus-me="state.lightbox === 'write' && writerTitle === 'Reply'" tabindex="3"></textarea>
|
||||||
|
</div><!--/write-->
|
||||||
|
|
||||||
</div>
|
|
||||||
<footer class="lightbox__controls">
|
<footer class="lightbox__controls">
|
||||||
<button wo-touch="sendToOutbox()" class="btn" ng-class="{'btn--invalid': sendBtnSecure === false}"
|
<button wo-touch="sendToOutbox()" class="btn" ng-class="{'btn--invalid': sendBtnSecure === false}"
|
||||||
ng-disabled="!okToSend" tabindex="4">{{sendBtnText || 'Send'}}</button>
|
ng-disabled="!okToSend" tabindex="4">{{sendBtnText || 'Send'}}</button>
|
||||||
</footer>
|
</footer>
|
||||||
</div>
|
</div><!--/lightbox__body-->
|
@ -7,11 +7,12 @@ var WriteCtrl = require('../../../../src/js/controller/app/write'),
|
|||||||
Auth = require('../../../../src/js/service/auth'),
|
Auth = require('../../../../src/js/service/auth'),
|
||||||
PGP = require('../../../../src/js/crypto/pgp'),
|
PGP = require('../../../../src/js/crypto/pgp'),
|
||||||
Status = require('../../../../src/js/util/status'),
|
Status = require('../../../../src/js/util/status'),
|
||||||
Dialog = require('../../../../src/js/util/dialog');
|
Dialog = require('../../../../src/js/util/dialog'),
|
||||||
|
Invitation = require('../../../../src/js/service/invitation');
|
||||||
|
|
||||||
describe('Write controller unit test', function() {
|
describe('Write controller unit test', function() {
|
||||||
var ctrl, scope,
|
var ctrl, scope,
|
||||||
authMock, pgpMock, dialogMock, emailMock, keychainMock, outboxMock, statusMock,
|
authMock, pgpMock, dialogMock, emailMock, keychainMock, outboxMock, statusMock, invitationMock,
|
||||||
emailAddress, realname;
|
emailAddress, realname;
|
||||||
|
|
||||||
beforeEach(function() {
|
beforeEach(function() {
|
||||||
@ -23,6 +24,7 @@ describe('Write controller unit test', function() {
|
|||||||
emailMock = sinon.createStubInstance(Email);
|
emailMock = sinon.createStubInstance(Email);
|
||||||
keychainMock = sinon.createStubInstance(Keychain);
|
keychainMock = sinon.createStubInstance(Keychain);
|
||||||
statusMock = sinon.createStubInstance(Status);
|
statusMock = sinon.createStubInstance(Status);
|
||||||
|
invitationMock = sinon.createStubInstance(Invitation);
|
||||||
|
|
||||||
emailAddress = 'fred@foo.com';
|
emailAddress = 'fred@foo.com';
|
||||||
realname = 'Fred Foo';
|
realname = 'Fred Foo';
|
||||||
@ -43,7 +45,8 @@ describe('Write controller unit test', function() {
|
|||||||
email: emailMock,
|
email: emailMock,
|
||||||
outbox: outboxMock,
|
outbox: outboxMock,
|
||||||
dialog: dialogMock,
|
dialog: dialogMock,
|
||||||
status: statusMock
|
status: statusMock,
|
||||||
|
invitation: invitationMock
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -205,6 +208,25 @@ describe('Write controller unit test', function() {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should work for no key in keychain', function(done) {
|
||||||
|
var recipient = {
|
||||||
|
address: 'asds@example.com'
|
||||||
|
};
|
||||||
|
|
||||||
|
keychainMock.refreshKeyForUserId.withArgs({
|
||||||
|
userId: recipient.address
|
||||||
|
}).returns(resolves());
|
||||||
|
|
||||||
|
scope.verify(recipient).then(function() {
|
||||||
|
expect(recipient.key).to.be.undefined;
|
||||||
|
expect(recipient.secure).to.be.false;
|
||||||
|
expect(scope.showInvite).to.be.true;
|
||||||
|
expect(scope.checkSendStatus.callCount).to.equal(2);
|
||||||
|
expect(keychainMock.refreshKeyForUserId.calledOnce).to.be.true;
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
it('should work for main userId', function(done) {
|
it('should work for main userId', function(done) {
|
||||||
var recipient = {
|
var recipient = {
|
||||||
address: 'asdf@example.com'
|
address: 'asdf@example.com'
|
||||||
@ -226,6 +248,7 @@ describe('Write controller unit test', function() {
|
|||||||
userId: 'asdf@example.com'
|
userId: 'asdf@example.com'
|
||||||
});
|
});
|
||||||
expect(recipient.secure).to.be.true;
|
expect(recipient.secure).to.be.true;
|
||||||
|
expect(scope.showInvite).to.be.undefined;
|
||||||
expect(scope.checkSendStatus.callCount).to.equal(2);
|
expect(scope.checkSendStatus.callCount).to.equal(2);
|
||||||
expect(keychainMock.refreshKeyForUserId.calledOnce).to.be.true;
|
expect(keychainMock.refreshKeyForUserId.calledOnce).to.be.true;
|
||||||
done();
|
done();
|
||||||
@ -252,6 +275,7 @@ describe('Write controller unit test', function() {
|
|||||||
scope.verify(recipient).then(function() {
|
scope.verify(recipient).then(function() {
|
||||||
expect(recipient.key).to.deep.equal(key);
|
expect(recipient.key).to.deep.equal(key);
|
||||||
expect(recipient.secure).to.be.true;
|
expect(recipient.secure).to.be.true;
|
||||||
|
expect(scope.showInvite).to.be.undefined;
|
||||||
expect(scope.checkSendStatus.callCount).to.equal(2);
|
expect(scope.checkSendStatus.callCount).to.equal(2);
|
||||||
expect(keychainMock.refreshKeyForUserId.calledOnce).to.be.true;
|
expect(keychainMock.refreshKeyForUserId.calledOnce).to.be.true;
|
||||||
done();
|
done();
|
||||||
@ -272,6 +296,7 @@ describe('Write controller unit test', function() {
|
|||||||
expect(scope.okToSend).to.be.false;
|
expect(scope.okToSend).to.be.false;
|
||||||
expect(scope.sendBtnText).to.be.undefined;
|
expect(scope.sendBtnText).to.be.undefined;
|
||||||
expect(scope.sendBtnSecure).to.be.undefined;
|
expect(scope.sendBtnSecure).to.be.undefined;
|
||||||
|
expect(scope.showInvite).to.be.false;
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should be able to send plaintext', function() {
|
it('should be able to send plaintext', function() {
|
||||||
@ -312,6 +337,95 @@ describe('Write controller unit test', function() {
|
|||||||
expect(scope.okToSend).to.be.true;
|
expect(scope.okToSend).to.be.true;
|
||||||
expect(scope.sendBtnText).to.equal('Send securely');
|
expect(scope.sendBtnText).to.equal('Send securely');
|
||||||
expect(scope.sendBtnSecure).to.be.true;
|
expect(scope.sendBtnSecure).to.be.true;
|
||||||
|
expect(scope.showInvite).to.be.false;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('invite', function() {
|
||||||
|
beforeEach(function() {
|
||||||
|
scope.state.writer.write();
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(function() {});
|
||||||
|
|
||||||
|
it('should not invite anyone', function(done) {
|
||||||
|
scope.invite().then(function() {
|
||||||
|
expect(scope.showInvite).to.be.false;
|
||||||
|
expect(outboxMock.put.called).to.be.false;
|
||||||
|
expect(invitationMock.invite.called).to.be.false;
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should work', function(done) {
|
||||||
|
scope.to = [{
|
||||||
|
address: 'asdf@asdf.de'
|
||||||
|
}, {
|
||||||
|
address: 'qwer@asdf.de'
|
||||||
|
}];
|
||||||
|
|
||||||
|
outboxMock.put.returns(resolves());
|
||||||
|
invitationMock.invite.returns(resolves());
|
||||||
|
|
||||||
|
scope.invite().then(function() {
|
||||||
|
expect(scope.showInvite).to.be.false;
|
||||||
|
expect(outboxMock.put.callCount).to.equal(2);
|
||||||
|
expect(invitationMock.invite.callCount).to.equal(2);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should work for one already invited', function(done) {
|
||||||
|
scope.to = [{
|
||||||
|
address: 'asdf@asdf.de'
|
||||||
|
}, {
|
||||||
|
address: 'qwer@asdf.de'
|
||||||
|
}];
|
||||||
|
scope.invited.push('asdf@asdf.de');
|
||||||
|
|
||||||
|
outboxMock.put.returns(resolves());
|
||||||
|
invitationMock.invite.returns(resolves());
|
||||||
|
|
||||||
|
scope.invite().then(function() {
|
||||||
|
expect(scope.showInvite).to.be.false;
|
||||||
|
expect(outboxMock.put.callCount).to.equal(1);
|
||||||
|
expect(invitationMock.invite.callCount).to.equal(1);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should fail due to error in outbox.put', function(done) {
|
||||||
|
scope.to = [{
|
||||||
|
address: 'asdf@asdf.de'
|
||||||
|
}];
|
||||||
|
|
||||||
|
outboxMock.put.returns(rejects(new Error('Peng')));
|
||||||
|
invitationMock.invite.returns(resolves());
|
||||||
|
|
||||||
|
scope.invite().then(function() {
|
||||||
|
expect(dialogMock.error.calledOnce).to.be.true;
|
||||||
|
expect(scope.showInvite).to.be.true;
|
||||||
|
expect(outboxMock.put.callCount).to.equal(1);
|
||||||
|
expect(invitationMock.invite.callCount).to.equal(0);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should fail due to error in invitation.invite', function(done) {
|
||||||
|
scope.to = [{
|
||||||
|
address: 'asdf@asdf.de'
|
||||||
|
}];
|
||||||
|
|
||||||
|
outboxMock.put.returns(resolves());
|
||||||
|
invitationMock.invite.returns(rejects(new Error('Peng')));
|
||||||
|
|
||||||
|
scope.invite().then(function() {
|
||||||
|
expect(dialogMock.error.calledOnce).to.be.true;
|
||||||
|
expect(scope.showInvite).to.be.true;
|
||||||
|
expect(outboxMock.put.callCount).to.equal(1);
|
||||||
|
expect(invitationMock.invite.callCount).to.equal(1);
|
||||||
|
done();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -49,6 +49,24 @@ describe('Outbox unit test', function() {
|
|||||||
outbox._processOutbox.restore();
|
outbox._processOutbox.restore();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should throw error for message without recipients', function(done) {
|
||||||
|
var mail = {
|
||||||
|
from: [{
|
||||||
|
name: 'member',
|
||||||
|
address: 'member@whiteout.io'
|
||||||
|
}],
|
||||||
|
to: [],
|
||||||
|
cc: [],
|
||||||
|
bcc: []
|
||||||
|
};
|
||||||
|
|
||||||
|
outbox.put(mail).catch(function(err) {
|
||||||
|
expect(err).to.exist;
|
||||||
|
expect(keychainStub.getReceiverPublicKey.called).to.be.false;
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
it('should not encrypt and store a mail', function(done) {
|
it('should not encrypt and store a mail', function(done) {
|
||||||
var mail, senderKey, receiverKey;
|
var mail, senderKey, receiverKey;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user