cleanup and refactor qunit tests to mocha

This commit is contained in:
Tankred Hase 2013-10-29 12:19:27 +01:00
parent b20ab9790c
commit 3e75397213
23 changed files with 1224 additions and 726 deletions

View File

@ -62,7 +62,8 @@ module.exports = function(grunt) {
all: {
options: {
urls: ['http://localhost:<%= connect.test.options.port %>/test/new-unit/index.html'],
run: false
run: false,
reporter: 'Spec'
}
}
},
@ -222,7 +223,7 @@ module.exports = function(grunt) {
// Test/Dev tasks
grunt.registerTask('dev', ['connect:dev']);
grunt.registerTask('test', ['jshint', 'connect:test', 'mocha', 'qunit']);
grunt.registerTask('test', ['jshint', 'connect:test', 'mocha']);
grunt.registerTask('prod', ['connect:prod']);
};

View File

@ -8,8 +8,10 @@ define(function(require) {
ImapClient = require('imap-client'),
SmtpClient = require('smtp-client'),
EmailDAO = require('js/dao/email-dao'),
RestDAO = require('js/dao/rest-dao'),
PublicKeyDAO = require('js/dao/publickey-dao'),
LawnchairDAO = require('js/dao/lawnchair-dao'),
KeychainDAO = require('js/dao/keychain-dao'),
cloudstorage = require('js/dao/cloudstorage-dao'),
DeviceStorageDAO = require('js/dao/devicestorage-dao'),
PGP = require('js/crypto/pgp'),
config = require('js/app-config').config;
@ -33,7 +35,7 @@ define(function(require) {
function onDeviceReady() {
console.log('Starting app.');
// init app config storage
self._appConfigStore = new DeviceStorageDAO();
self._appConfigStore = new DeviceStorageDAO(new LawnchairDAO());
self._appConfigStore.init('app-config', callback);
}
};
@ -129,6 +131,7 @@ define(function(require) {
*/
self.init = function(userId, token, callback) {
var auth, imapOptions, smtpOptions,
lawnchairDao, restDao, pubkeyDao,
keychain, imapClient, smtpClient, pgp, userStorage;
// create mail credentials objects for imap/smtp
@ -153,11 +156,14 @@ define(function(require) {
};
// init objects and inject dependencies
keychain = new KeychainDAO(cloudstorage);
restDao = new RestDAO();
pubkeyDao = new PublicKeyDAO(restDao);
lawnchairDao = new LawnchairDAO();
keychain = new KeychainDAO(lawnchairDao, pubkeyDao);
imapClient = new ImapClient(imapOptions);
smtpClient = new SmtpClient(smtpOptions);
pgp = new PGP();
userStorage = new DeviceStorageDAO();
userStorage = new DeviceStorageDAO(lawnchairDao);
self._emailDao = new EmailDAO(keychain, imapClient, smtpClient, pgp, userStorage);
// init email dao

View File

@ -1,200 +0,0 @@
/**
* High level storage api for handling syncing of data to
* and from the cloud.
*/
define(['jquery', 'js/app-config'], function($, app) {
'use strict';
var self = {};
//
// Generic Ajax helper functions
//
/**
* GET (read) request
*/
self.get = function(uri, callback) {
$.ajax({
url: uri,
type: 'GET',
dataType: 'json',
headers: {
'Accept': 'application/json',
},
success: function(res) {
callback(null, res);
},
error: function(xhr, textStatus, err) {
callback({
code: xhr.status,
errMsg: xhr.statusText,
err: err
});
}
});
};
/**
* PUT (update) request
*/
self.put = function(item, uri, callback) {
$.ajax({
url: uri,
type: 'PUT',
data: JSON.stringify(item),
contentType: 'application/json',
success: function() {
callback();
},
error: function(xhr, textStatus, err) {
callback({
code: xhr.status,
errMsg: xhr.statusText,
err: err
});
}
});
};
/**
* DELETE (remove) request
*/
self.remove = function(uri, callback) {
$.ajax({
url: uri,
type: 'DELETE',
success: function() {
callback();
},
error: function(xhr, textStatus, err) {
callback({
code: xhr.status,
errMsg: xhr.statusText,
err: err
});
}
});
};
//
// Encrypted Mail storage
//
/**
* Pushes an encrypted item to the user's cloud storage
* @param type [String] The type of item e.g. 'email'
*/
self.putEncryptedItem = function(item, type, emailAddress, folderName, callback) {
var uri = app.config.cloudUrl + '/' + type + '/user/' + emailAddress + '/folder/' + folderName + '/' + item.id;
self.put(item, uri, callback);
};
/**
* Deliver an email to the user's outbox
*/
self.deliverEmail = function(email, from, to, callback) {
var uri = app.config.cloudUrl + '/email/user/' + from + '/folder/outbox/' + email.id + '?to=' + to;
self.put(email, uri, callback);
};
/**
* Delete an encrypted item from the cloud
* @param type [String] The type of item e.g. 'email'
*/
self.deleteEncryptedItem = function(id, type, emailAddress, folderName, callback) {
var uri = app.config.cloudUrl + '/' + type + '/user/' + emailAddress + '/folder/' + folderName + '/' + id;
self.remove(uri, callback);
};
/**
* Lists the encrypted items
* @param type [String] The type of item e.g. 'email'
* @param offset [Number] The offset of items to fetch (0 is the last stored item)
* @param num [Number] The number of items to fetch (null means fetch all)
*/
self.listEncryptedItems = function(type, emailAddress, folderName, callback) {
var uri = app.config.cloudUrl + '/' + type + '/user/' + emailAddress + '/folder/' + folderName;
self.get(uri, callback);
};
//
// Public Key
//
/**
* Find the user's corresponding public key
*/
self.getPublicKey = function(keyId, callback) {
var uri = app.config.cloudUrl + '/publickey/key/' + keyId;
self.get(uri, function(err, key) {
if (err) {
callback(err);
return;
}
if (!key || !key._id) {
callback({
errMsg: 'No public key for that user!'
});
return;
}
callback(null, key);
});
};
/**
* Find the user's corresponding public key by email
*/
self.getPublicKeyByUserId = function(userId, callback) {
var uri = app.config.cloudUrl + '/publickey/user/' + userId;
self.get(uri, function(err, keys) {
// not found
if (err && err.code === 404) {
callback();
return;
}
if (err) {
callback(err);
return;
}
if (!keys || keys.length < 1) {
// 'No public key for that user!'
callback();
return;
}
if (keys.length > 1) {
callback({
errMsg: 'That user has multiple public keys!'
});
return;
}
callback(null, keys[0]);
});
};
/**
* Persist the user's publc key
*/
self.putPublicKey = function(pubkey, callback) {
var uri = app.config.cloudUrl + '/publickey/user/' + pubkey.userId + '/key/' + pubkey._id;
self.put(pubkey, uri, callback);
};
/**
* Delete the public key from the cloud storage service
*/
self.removePublicKey = function(keyId, callback) {
var uri = app.config.cloudUrl + '/publickey/key/' + keyId;
self.remove(uri, callback);
};
return self;
});

View File

@ -4,17 +4,15 @@
* through transparent encryption. If not, the crypto API is
* used to encrypt data on the fly before persisting via a JSON store.
*/
define(function(require) {
define(function() {
'use strict';
var jsonDao = require('js/dao/lawnchair-dao');
var DeviceStorageDAO = function() {
var DeviceStorageDAO = function(localDbDao) {
this._localDbDao = localDbDao;
};
DeviceStorageDAO.prototype.init = function(emailAddress, callback) {
jsonDao.init(emailAddress, callback);
this._localDbDao.init(emailAddress, callback);
};
/**
@ -48,26 +46,14 @@ define(function(require) {
});
});
jsonDao.batch(items, function() {
callback();
});
this._localDbDao.batch(items, callback);
};
/**
* Deletes items of a certain type from storage
*/
DeviceStorageDAO.prototype.removeList = function(type, callback) {
// validate type
if (!type) {
callback({
errMsg: 'Type is not set!'
});
return;
}
jsonDao.removeList(type, function() {
callback();
});
this._localDbDao.removeList(type, callback);
};
/**
@ -77,26 +63,15 @@ define(function(require) {
* @param num [Number] The number of items to fetch (null means fetch all)
*/
DeviceStorageDAO.prototype.listItems = function(type, offset, num, callback) {
// validate type
if (!type || typeof offset === 'undefined' || typeof num === 'undefined') {
callback({
errMsg: 'Args not is not set!'
});
return;
}
// fetch all items of a certain type from the data-store
jsonDao.list(type, offset, num, function(matchingList) {
callback(null, matchingList);
});
this._localDbDao.list(type, offset, num, callback);
};
/**
* Clear the whole device data-store
*/
DeviceStorageDAO.prototype.clear = function(callback) {
jsonDao.clear(callback);
this._localDbDao.clear(callback);
};
//

View File

@ -56,7 +56,7 @@ define(function(require) {
EmailDAO.prototype.unlock = function(keypair, passphrase, callback) {
var self = this;
if (keypair && keypair.privateKey && keypair.publicKey) {
// import existing key pair into crypto module
self._crypto.importKeys({
@ -264,7 +264,7 @@ define(function(require) {
list.forEach(function(i) {
// gather public keys required to verify signatures
var sender = i.from[0].address;
self._keychain.getReveiverPublicKey(sender, function(err, senderPubkey) {
self._keychain.getReceiverPublicKey(sender, function(err, senderPubkey) {
// decrypt and verfiy signatures
self._crypto.decrypt(i.body, senderPubkey.publicKey, function(err, decrypted) {
@ -488,7 +488,7 @@ define(function(require) {
// only support single recipient for e-2-e encryption
// check if receiver has a public key
self._keychain.getReveiverPublicKey(email.to[0].address, function(err, receiverPubkey) {
self._keychain.getReceiverPublicKey(email.to[0].address, function(err, receiverPubkey) {
if (err) {
callback(err);
return;

View File

@ -2,13 +2,14 @@
* A high-level Data-Access Api for handling Keypair synchronization
* between the cloud service and the device's local storage
*/
define(['underscore', 'js/dao/lawnchair-dao'], function(_, jsonDao) {
define(function(require) {
'use strict';
var KeychainDAO = function(cloudstorage) {
var self = this;
var _ = require('underscore');
self._cloudstorage = cloudstorage;
var KeychainDAO = function(localDbDao, publicKeyDao) {
this._localDbDao = localDbDao;
this._publicKeyDao = publicKeyDao;
};
/**
@ -60,47 +61,54 @@ define(['underscore', 'js/dao/lawnchair-dao'], function(_, jsonDao) {
* Look up a reveiver's public key by user id
* @param userId [String] the receiver's email address
*/
KeychainDAO.prototype.getReveiverPublicKey = function(userId, callback) {
KeychainDAO.prototype.getReceiverPublicKey = function(userId, callback) {
var self = this;
// search local keyring for public key
jsonDao.list('publickey', 0, null, function(allPubkeys) {
self._localDbDao.list('publickey', 0, null, function(err, allPubkeys) {
if (err) {
callback(err);
return;
}
var pubkey = _.findWhere(allPubkeys, {
userId: userId
});
if (!pubkey || !pubkey._id) {
// no public key by that user id in storage
// find from cloud by email address
self._cloudstorage.getPublicKeyByUserId(userId, function(err, cloudPubkey) {
if (err || !cloudPubkey) {
callback();
return;
}
if (cloudPubkey && cloudPubkey._id) {
// there is a public key for that user already in the cloud...
// save to local storage
self.saveLocalPublicKey(cloudPubkey, function(err) {
if (err) {
callback(err);
return;
}
callback(null, cloudPubkey);
});
} else {
// no public key for that user
callback();
return;
}
});
} else {
if (pubkey && pubkey._id) {
// that user's public key is already in local storage
callback(null, pubkey);
return;
}
// no public key by that user id in storage
// find from cloud by email address
self._publicKeyDao.getByUserId(userId, onKeyGotten);
});
function onKeyGotten(err, cloudPubkey) {
if (err) {
callback(err);
return;
}
if (!cloudPubkey) {
// no public key for that user
callback();
return;
}
// there is a public key for that user already in the cloud...
// save to local storage
self.saveLocalPublicKey(cloudPubkey, function(err) {
if (err) {
callback(err);
return;
}
callback(null, cloudPubkey);
});
}
};
/**
@ -113,36 +121,41 @@ define(['underscore', 'js/dao/lawnchair-dao'], function(_, jsonDao) {
var self = this;
// search for user's public key locally
jsonDao.list('publickey', 0, null, function(allPubkeys) {
self._localDbDao.list('publickey', 0, null, function(err, allPubkeys) {
if (err) {
callback(err);
return;
}
var pubkey = _.findWhere(allPubkeys, {
userId: userId
});
if (!pubkey || !pubkey._id) {
// no public key by that user id in storage
// find from cloud by email address
self._cloudstorage.getPublicKeyByUserId(userId, function(err, cloudPubkey) {
if (err) {
callback(err);
return;
}
if (cloudPubkey && cloudPubkey._id) {
// there is a public key for that user already in the cloud...
// sync keypair to local storage
syncKeypair(cloudPubkey._id);
} else {
// continue without keypair... generate in crypto.js
callback();
return;
}
});
} else {
if (pubkey && pubkey._id) {
// that user's public key is already in local storage...
// sync keypair to the cloud
syncKeypair(pubkey._id);
return;
}
// no public key by that user id in storage
// find from cloud by email address
self._publicKeyDao.getByUserId(userId, function(err, cloudPubkey) {
if (err) {
callback(err);
return;
}
if (cloudPubkey && cloudPubkey._id) {
// there is a public key for that user already in the cloud...
// sync keypair to local storage
syncKeypair(cloudPubkey._id);
return;
}
// continue without keypair... generate in crypto.js
callback();
});
});
function syncKeypair(keypairId) {
@ -165,7 +178,7 @@ define(['underscore', 'js/dao/lawnchair-dao'], function(_, jsonDao) {
if (savedPubkey && savedPubkey.publicKey) {
keys.publicKey = savedPubkey;
}
if (savedPrivkey && savedPrivkey.encryptedKey) {
keys.privateKey = savedPrivkey;
}
@ -200,7 +213,7 @@ define(['underscore', 'js/dao/lawnchair-dao'], function(_, jsonDao) {
}
// persist public key in cloud storage
self._cloudstorage.putPublicKey(keypair.publicKey, function(err) {
self._publicKeyDao.put(keypair.publicKey, function(err) {
// validate result
if (err) {
callback(err);
@ -220,11 +233,23 @@ define(['underscore', 'js/dao/lawnchair-dao'], function(_, jsonDao) {
KeychainDAO.prototype.lookupPublicKey = function(id, callback) {
var self = this;
if (!id) {
callback({
errMsg: 'ID must be set for public key query!'
});
return;
}
// lookup in local storage
jsonDao.read('publickey_' + id, function(pubkey) {
self._localDbDao.read('publickey_' + id, function(err, pubkey) {
if (err) {
callback(err);
return;
}
if (!pubkey) {
// fetch from cloud storage
self._cloudstorage.getPublicKey(id, function(err, cloudPubkey) {
self._publicKeyDao.get(id, function(err, cloudPubkey) {
if (err) {
callback(err);
return;
@ -249,43 +274,19 @@ define(['underscore', 'js/dao/lawnchair-dao'], function(_, jsonDao) {
KeychainDAO.prototype.lookupPrivateKey = function(id, callback) {
// lookup in local storage
jsonDao.read('privatekey_' + id, function(privkey) {
callback(null, privkey);
});
this._localDbDao.read('privatekey_' + id, callback);
};
KeychainDAO.prototype.saveLocalPublicKey = function(pubkey, callback) {
// persist public key (email, _id)
var pkLookupKey = 'publickey_' + pubkey._id;
jsonDao.persist(pkLookupKey, pubkey, function(res1) {
// validate result
if (res1.key !== pkLookupKey) {
callback({
errMsg: 'Persisting public key in local storage went wrong!'
});
return;
}
callback();
});
this._localDbDao.persist(pkLookupKey, pubkey, callback);
};
KeychainDAO.prototype.saveLocalPrivateKey = function(privkey, callback) {
// persist private key (email, _id)
var prkLookupKey = 'privatekey_' + privkey._id;
jsonDao.persist(prkLookupKey, privkey, function(res1) {
// validate result
if (res1.key !== prkLookupKey) {
callback({
errMsg: 'Persisting private key in local storage went wrong!'
});
return;
}
callback();
});
this._localDbDao.persist(prkLookupKey, privkey, callback);
};
return KeychainDAO;

View File

@ -1,27 +1,34 @@
/**
* Handles generic caching of JSON objects in a lawnchair adapter
*/
define(['underscore', 'lawnchair', 'lawnchairSQL', 'lawnchairIDB'], function(_, Lawnchair) {
define(function(require) {
'use strict';
var self = {},
db;
var _ = require('underscore'),
Lawnchair = require('lawnchair');
require('lawnchairSQL');
require('lawnchairIDB');
self.init = function(dbName, callback) {
var temp;
var LawnchairDAO = function() {};
LawnchairDAO.prototype.init = function(dbName, callback) {
if (!dbName) {
throw new Error('Lawnchair DB name must be specified!');
callback({
errMsg: 'Lawnchair DB name must be specified!'
});
return;
}
temp = new Lawnchair({
this._db = new Lawnchair({
name: dbName
}, function(lc) {
if (!lc) {
throw new Error('Lawnchair init failed!');
callback({
errMsg: 'Lawnchair init failed!'
});
return;
}
db = lc;
callback();
});
};
@ -29,27 +36,66 @@ define(['underscore', 'lawnchair', 'lawnchairSQL', 'lawnchairIDB'], function(_,
/**
* Create or update an object
*/
self.persist = function(key, object, callback) {
db.save({
LawnchairDAO.prototype.persist = function(key, object, callback) {
if (!key || !object) {
callback({
errMsg: 'Key and Object must be set!'
});
return;
}
this._db.save({
key: key,
object: object
}, callback);
}, function(persisted) {
if (persisted.key !== key) {
callback({
errMsg: 'Persisting failed!'
});
return;
}
callback();
});
};
/**
* Persist a bunch of items at once
*/
self.batch = function(list, callback) {
db.batch(list, callback);
LawnchairDAO.prototype.batch = function(list, callback) {
if (!(list instanceof Array)) {
callback({
errMsg: 'Input must be of type Array!'
});
return;
}
this._db.batch(list, function(res) {
if (!res) {
callback({
errMsg: 'Persisting batch failed!'
});
return;
}
callback();
});
};
/**
* Read a single item by its key
*/
self.read = function(key, callback) {
db.get(key, function(o) {
LawnchairDAO.prototype.read = function(key, callback) {
if (!key) {
callback({
errMsg: 'Key must be specified!'
});
return;
}
this._db.get(key, function(o) {
if (o) {
callback(o.object);
callback(null, o.object);
} else {
callback();
}
@ -62,14 +108,23 @@ define(['underscore', 'lawnchair', 'lawnchairSQL', 'lawnchairIDB'], function(_,
* @param offset [Number] The offset of items to fetch (0 is the last stored item)
* @param num [Number] The number of items to fetch (null means fetch all)
*/
self.list = function(type, offset, num, callback) {
var i, from, to,
LawnchairDAO.prototype.list = function(type, offset, num, callback) {
var self = this,
i, from, to,
matchingKeys = [],
intervalKeys = [],
list = [];
// validate input
if (!type || typeof offset === 'undefined' || typeof num === 'undefined') {
callback({
errMsg: 'Args not is not set!'
});
return;
}
// get all keys
db.keys(function(keys) {
self._db.keys(function(keys) {
// check if key begins with type
keys.forEach(function(key) {
@ -94,18 +149,18 @@ define(['underscore', 'lawnchair', 'lawnchairSQL', 'lawnchairIDB'], function(_,
// return if there are no matching keys
if (intervalKeys.length === 0) {
callback(list);
callback(null, list);
return;
}
// fetch all items from data-store with matching key
db.get(intervalKeys, function(intervalList) {
self._db.get(intervalKeys, function(intervalList) {
intervalList.forEach(function(item) {
list.push(item.object);
});
// return only the interval between offset and num
callback(list);
callback(null, list);
});
});
@ -114,19 +169,28 @@ define(['underscore', 'lawnchair', 'lawnchairSQL', 'lawnchairIDB'], function(_,
/**
* Removes an object liter from local storage by its key (delete)
*/
self.remove = function(key, callback) {
db.remove(key, callback);
LawnchairDAO.prototype.remove = function(key, callback) {
this._db.remove(key, callback);
};
/**
* Removes an object liter from local storage by its key (delete)
*/
self.removeList = function(type, callback) {
var matchingKeys = [],
LawnchairDAO.prototype.removeList = function(type, callback) {
var self = this,
matchingKeys = [],
after;
// validate type
if (!type) {
callback({
errMsg: 'Type is not set!'
});
return;
}
// get all keys
db.keys(function(keys) {
self._db.keys(function(keys) {
// check if key begins with type
keys.forEach(function(key) {
if (key.indexOf(type) === 0) {
@ -142,7 +206,7 @@ define(['underscore', 'lawnchair', 'lawnchairSQL', 'lawnchairIDB'], function(_,
// remove all matching keys
after = _.after(matchingKeys.length, callback);
_.each(matchingKeys, function(key) {
db.remove(key, after);
self._db.remove(key, after);
});
});
};
@ -150,9 +214,9 @@ define(['underscore', 'lawnchair', 'lawnchairSQL', 'lawnchairIDB'], function(_,
/**
* Clears the whole local storage cache
*/
self.clear = function(callback) {
db.nuke(callback);
LawnchairDAO.prototype.clear = function(callback) {
this._db.nuke(callback);
};
return self;
return LawnchairDAO;
});

View File

@ -0,0 +1,83 @@
define(function() {
'use strict';
var PublicKeyDAO = function(restDao) {
this._restDao = restDao;
};
/**
* Find the user's corresponding public key
*/
PublicKeyDAO.prototype.get = function(keyId, callback) {
var uri = '/publickey/key/' + keyId;
this._restDao.get(uri, function(err, key) {
if (err) {
callback(err);
return;
}
if (!key || !key._id) {
callback({
errMsg: 'No public key for that user!'
});
return;
}
callback(null, key);
});
};
/**
* Find the user's corresponding public key by email
*/
PublicKeyDAO.prototype.getByUserId = function(userId, callback) {
var uri = '/publickey/user/' + userId;
this._restDao.get(uri, function(err, keys) {
// not found
if (err && err.code === 404) {
callback();
return;
}
if (err) {
callback(err);
return;
}
if (!keys || keys.length < 1) {
// 'No public key for that user!'
callback();
return;
}
if (keys.length > 1) {
callback({
errMsg: 'That user has multiple public keys!'
});
return;
}
callback(null, keys[0]);
});
};
/**
* Persist the user's publc key
*/
PublicKeyDAO.prototype.put = function(pubkey, callback) {
var uri = '/publickey/user/' + pubkey.userId + '/key/' + pubkey._id;
this._restDao.put(pubkey, uri, callback);
};
/**
* Delete the public key from the cloud storage service
*/
PublicKeyDAO.prototype.remove = function(keyId, callback) {
var uri = '/publickey/key/' + keyId;
this._restDao.remove(uri, callback);
};
return PublicKeyDAO;
});

82
src/js/dao/rest-dao.js Normal file
View File

@ -0,0 +1,82 @@
define(function(require) {
'use strict';
var $ = require('jquery'),
config = require('js/app-config').config;
var RestDAO = function(options) {
if (options && options.baseUri) {
this._baseUri = options.baseUri;
} else {
this._baseUri = config.cloudUrl;
}
};
/**
* GET (read) request
*/
RestDAO.prototype.get = function(uri, callback) {
$.ajax({
url: this._baseUri + uri,
type: 'GET',
dataType: 'json',
headers: {
'Accept': 'application/json',
},
success: function(res) {
callback(null, res);
},
error: function(xhr, textStatus, err) {
callback({
code: xhr.status,
errMsg: xhr.statusText,
err: err
});
}
});
};
/**
* PUT (create/update) request
*/
RestDAO.prototype.put = function(item, uri, callback) {
$.ajax({
url: this._baseUri + uri,
type: 'PUT',
data: JSON.stringify(item),
contentType: 'application/json',
success: function() {
callback();
},
error: function(xhr, textStatus, err) {
callback({
code: xhr.status,
errMsg: xhr.statusText,
err: err
});
}
});
};
/**
* DELETE (remove) request
*/
RestDAO.prototype.remove = function(uri, callback) {
$.ajax({
url: this._baseUri + uri,
type: 'DELETE',
success: function() {
callback();
},
error: function(xhr, textStatus, err) {
callback({
code: xhr.status,
errMsg: xhr.statusText,
err: err
});
}
});
};
return RestDAO;
});

View File

@ -1,224 +0,0 @@
define(['js/dao/email-dao', 'js/dao/keychain-dao', 'js/dao/lawnchair-dao',
'js/dao/cloudstorage-dao', 'js/app-config'
], function(EmailDAO, KeychainDAO, jsonDao, cloudstorage, app) {
'use strict';
module("CloudStorage DAO");
var cloudstoragedaoTest = {
user: 'email.dao.it.test@mail.whiteout.io',
password: 'Xoza76645',
keySize: 128,
ivSize: 128,
rsaKeySize: 1024
};
asyncTest("Init", 1, function() {
// test keys
var pk = "-----BEGIN PUBLIC KEY-----\r\n" +
"MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDTIupLSuRD5gh6wHx1f4Q2Qv61\r\n" +
"trOWgqfi/eJUtheoOWkW6KGoLqo5xdklPVIqyP9702PDQtf1upwVB8MCGSiYMDyj\r\n" +
"Fr0XlYJnJM2ERVrSGkDNSI2+6bVq1k2TB4YeZoMVhel/igCr5Rbr8LyNswCQMIXl\r\n" +
"oiMEqmiN/YtLwD1z+QIDAQAB\r\n" +
"-----END PUBLIC KEY-----";
cloudstoragedaoTest.keypair = {
publicKey: {
_id: "01ca6e54-a6b3-4b5f-bb43-ede30aaccc9e",
userId: cloudstoragedaoTest.user,
publicKey: pk
},
privateKey: {
_id: "01ca6e54-a6b3-4b5f-bb43-ede30aaccc9e",
userId: cloudstoragedaoTest.user,
encryptedKey: "zXBmmR7fz6sfR0AIeOzvwKOb6BrBQBgyweJ4c0LZS9h7C18SgPSMcvpSgBIwJadi577DPmwfXPl6zCNtwoqlLqD6xdS6P/bDY6rIWbaGbRrWzs/KXJ7UjWq0uyZSUFQK8w/woHkyQ4eLqdwj+duPZzrerDyi1XX8XXCcNDpDwR+1L2TxWlDzShN7IiA4OUeFsDbgqN3lKUBSHw5USnassv7nRwWlSNWPVaIlx3YT2T/VIaNoBbX5jDDwhDT4h/1fOOEbxTIBEN65mGGNW9GPLbi/PVgKibrF6l8bHwW5FjIkoYZdzgPe5nowhbFb2FB7mWX4gXMzqT3wuOP9fCOCEj4muxYkV7daedAGFRKl5mTPd9Cu+vSY+SnZX55m1yXQixn55J50AgW+aY/LXV+UqYwVObp7o5qs0B+OhQIRxH2Sp6IjRRFAqsQgBoRXS1qWPLCGVLMoSUkOSOCQd6rsr70fGXxGpguJFigAMWDXAzuPH98UFaB7kCiohhFLZ25vMhd/cOz1MXTKKPQJXfpBr8uX/hhhdsZReVfqLFKpvs1MzdFoV6FiTwZwyDyRnANYRHnqnP148q5s0JOkFcHaHqYdbLvVU6jm/B3QYJ/IO/uKyHoIhVobSSUBLzLDV0Eila9LhCdfWVXIVfFNUr5ut1YyOoJ23G5ItBSq5VFaZv79lNIhWjw/effq1IJd4eKeBe2X2DoYv85FZifAf/kUN38g0rTfAmKedsTGGhMLo+3Aa12MzRF93aTOMyKpHSA0G/5dA5PSVSlgDd/hwn4AlKzfo8M2PF1fh+9q5YtWqs4+mSOmyvYKxg9g+ZBhAvHbVBUN2emoNoJTC6JToB9jeRvksl1iehx+3C8nHUzXsxqApA3a79RJ+izRT2f0GguEAlAz4B6EozFRJwjNyRL2Fe7bgtadJxTNZfcG+oCgCFNCOyOvSgcpkjvj2DlFdPvw5BXXodV5D0jIg+OnszWcgLUDLFMkPPJgYrx9smRqdPjFnjWvnm6bRVZbxaU+FXKFvplmOG3XK1sR9g91bg5nnKDHRf6OuwBBgX0AyzOz2ohO3NVuIcppHjecUEY8t9QgezGal/R1PepW/uNPn/zJgGthTb4rK/KrXZTEsvC3XI55VlSnhORfNJvjn5Up/iusKeKXEGb/lhyc058GZY5UCmoIsV30TYgzXeuj6VZBEtcvAvza0mYmGvXf91ebVZR+",
iv: "XE4c3X134YNkapbeSXP6GA=="
}
};
// init dependencies
jsonDao.init(cloudstoragedaoTest.user);
cloudstoragedaoTest.keychain = new KeychainDAO(cloudstorage);
cloudstoragedaoTest.emailDao = new EmailDAO(cloudstorage, cloudstoragedaoTest.keychain);
// clear db before tests
jsonDao.clear(function(err) {
ok(!err, 'DB cleared. Error status: ' + err);
start();
});
});
asyncTest("Put public key to cloud", 1, function() {
cloudstorage.putPublicKey(cloudstoragedaoTest.keypair.publicKey, function(err) {
ok(!err, 'Persist key to cloud');
start();
});
});
asyncTest("Get Public key from cloud by id", 2, function() {
cloudstorage.getPublicKey(cloudstoragedaoTest.keypair.publicKey._id, function(err, data) {
ok(!err && data && data.publicKey, 'Get public key from cloud');
deepEqual(data, cloudstoragedaoTest.keypair.publicKey, 'Public key is equal');
start();
});
});
asyncTest("Get Public key from cloud by email", 2, function() {
cloudstorage.getPublicKeyByUserId(cloudstoragedaoTest.keypair.publicKey.userId, function(err, data) {
ok(!err && data && data.publicKey, 'Get public key from cloud');
deepEqual(data, cloudstoragedaoTest.keypair.publicKey, 'Public key is equal');
start();
});
});
asyncTest("Delete Public key from cloud", 1, function() {
cloudstorage.removePublicKey(cloudstoragedaoTest.keypair.publicKey._id, function(err) {
ok(!err, 'Delete public key from cloud');
start();
});
});
asyncTest("Put private key to cloud", 1, function() {
cloudstorage.putPrivateKey(cloudstoragedaoTest.keypair.privateKey, function(err) {
ok(!err, 'Persist key to cloud');
start();
});
});
asyncTest("Get Private key from cloud", 2, function() {
cloudstorage.getPrivateKey(cloudstoragedaoTest.keypair.privateKey._id, function(err, data) {
ok(!err && data && data.encryptedKey, 'Get private key from cloud');
deepEqual(data, cloudstoragedaoTest.keypair.privateKey, 'Private key is equal');
start();
});
});
asyncTest("Delete Private key from cloud", 1, function() {
cloudstorage.removePrivateKey(cloudstoragedaoTest.keypair.privateKey._id, function(err) {
ok(!err, 'Delete private key from cloud');
start();
});
});
module("Keychain DAO");
asyncTest("Put User Keypair", 1, function() {
cloudstoragedaoTest.keychain.putUserKeyPair(cloudstoragedaoTest.keypair, function(err) {
ok(!err);
start();
});
});
asyncTest("Get User Keypair", 2, function() {
cloudstoragedaoTest.keychain.getUserKeyPair(cloudstoragedaoTest.user, function(err, keypair) {
ok(!err);
ok(keypair && keypair.publicKey && keypair.privateKey);
start();
});
});
asyncTest("Get Public Keys", 2, function() {
var pubkeyIds = [{
_id: cloudstoragedaoTest.keypair.publicKey._id
}
];
cloudstoragedaoTest.keychain.getPublicKeys(pubkeyIds, function(err, pubkeys) {
ok(!err);
deepEqual(pubkeys[0], cloudstoragedaoTest.keypair.publicKey, "Fetch public key");
start();
});
});
module("Email DAO");
asyncTest("Init", 1, function() {
var account = new app.model.Account({
emailAddress: cloudstoragedaoTest.user,
symKeySize: cloudstoragedaoTest.keySize,
symIvSize: cloudstoragedaoTest.ivSize,
asymKeySize: cloudstoragedaoTest.rsaKeySize
});
cloudstoragedaoTest.emailDao.init(account, cloudstoragedaoTest.password, function(err) {
ok(!err, 'Init complete');
start();
});
});
asyncTest("Send e-2-e Encrypted Email item", 1, function() {
var email = {
subject: 'Client Email DAO Test', // Subject line
body: 'Hello world' // plaintext body
};
email.from = [{
address: cloudstoragedaoTest.user
}
];
email.to = [{
address: cloudstoragedaoTest.user
}
];
cloudstoragedaoTest.emailDao.sendEmail(email, function(err) {
ok(!err, 'Email sent');
start();
});
});
asyncTest("Send Plaintext Email item", 1, function() {
var email = {
subject: 'Client Email DAO Test', // Subject line
body: 'Hello world' // plaintext body
};
email.from = [{
address: cloudstoragedaoTest.user
}
];
email.to = [{
address: 'safewithme.testuser@gmail.com'
}
];
cloudstoragedaoTest.emailDao.sendEmail(email, function(err) {
ok(!err, 'Email sent');
start();
});
});
asyncTest("Sync emails from cloud", 1, function() {
cloudstoragedaoTest.emailDao.syncFromCloud('inbox', function(err) {
ok(!err, 'Synced items');
start();
});
});
asyncTest("List emails from cloud", 2, function() {
cloudstoragedaoTest.emailDao.listItems('inbox', 0, null, function(err, gotten) {
ok(!err);
ok(gotten.length > 0, 'Read synced items');
start();
});
});
});

View File

@ -27,13 +27,21 @@ define(function(require) {
appController.start(function(err) {
expect(err).to.not.exist;
appController.fetchOAuthToken(test.passphrase, function(err) {
appController.fetchOAuthToken(function(err, auth) {
expect(err).to.not.exist;
emailDao = appController._emailDao;
emailDao.imapLogin(function(err) {
appController.init(auth.emailAddress, auth.token, function(err, availableKeys) {
expect(err).to.not.exist;
done();
emailDao = appController._emailDao;
emailDao.unlock(availableKeys, test.passphrase, function(err) {
expect(err).to.not.exist;
emailDao.imapLogin(function(err) {
expect(err).to.not.exist;
done();
});
});
});
});
});

View File

@ -1,20 +0,0 @@
define(function() {
'use strict';
var expect = chai.expect;
describe('Cloudstorage DAO unit tests', function() {
beforeEach(function() {});
afterEach(function() {});
describe('init', function() {
it('should not explode', function() {
expect(true).to.be.ok;
});
});
});
});

View File

@ -0,0 +1,105 @@
define(function(require) {
'use strict';
var LawnchairDAO = require('js/dao/lawnchair-dao'),
DeviceStorageDAO = require('js/dao/devicestorage-dao'),
expect = chai.expect;
var testUser = 'test@example.com';
describe('Device Storage DAO unit tests', function() {
var storageDao, 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();
});
});
});
describe('store list', function() {
it('should fail', 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();
});
});
});
describe('remove list', function() {
it('should work', function(done) {
lawnchairDaoStub.removeList.yields();
storageDao.removeList('email', function(err) {
expect(err).to.not.exist;
expect(lawnchairDaoStub.removeList.calledOnce).to.be.true;
done();
});
});
});
describe('list items', function() {
it('should work', function(done) {
lawnchairDaoStub.list.yields();
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();
});
});
});
});
});

View File

@ -235,7 +235,7 @@ define(function(require) {
it('should fail due to bad input', function(done) {
emailDao.smtpSend({}, function(err) {
expect(smtpClientStub.send.called).to.be.false;
expect(keychainStub.getReveiverPublicKey.called).to.be.false;
expect(keychainStub.getReceiverPublicKey.called).to.be.false;
expect(err).to.exist;
done();
});
@ -247,18 +247,18 @@ define(function(require) {
}];
emailDao.smtpSend(dummyMail, function(err) {
expect(smtpClientStub.send.called).to.be.false;
expect(keychainStub.getReveiverPublicKey.called).to.be.false;
expect(keychainStub.getReceiverPublicKey.called).to.be.false;
expect(err).to.exist;
done();
});
});
it('should work for a new user', function(done) {
keychainStub.getReveiverPublicKey.yields(null, null);
keychainStub.getReceiverPublicKey.yields(null, null);
smtpClientStub.send.yields();
emailDao.smtpSend(dummyMail, function(err) {
expect(keychainStub.getReveiverPublicKey.calledOnce).to.be.true;
expect(keychainStub.getReceiverPublicKey.calledOnce).to.be.true;
// expect(smtpClientStub.send.called).to.be.true;
// smtpClientStub.send.calledWith(sinon.match(function(o) {
// return typeof o.attachments === 'undefined';
@ -269,7 +269,7 @@ define(function(require) {
});
it('should work without attachments', function(done) {
keychainStub.getReveiverPublicKey.yields(null, {
keychainStub.getReceiverPublicKey.yields(null, {
_id: "fcf8b4aa-5d09-4089-8b4f-e3bc5091daf3",
userId: "safewithme.testuser@gmail.com",
publicKey: publicKey
@ -279,7 +279,7 @@ define(function(require) {
smtpClientStub.send.yields();
emailDao.smtpSend(dummyMail, function(err) {
expect(keychainStub.getReveiverPublicKey.calledOnce).to.be.true;
expect(keychainStub.getReceiverPublicKey.calledOnce).to.be.true;
expect(pgpStub.exportKeys.calledOnce).to.be.true;
expect(pgpStub.encrypt.calledOnce).to.be.true;
expect(smtpClientStub.send.calledOnce).to.be.true;
@ -297,7 +297,7 @@ define(function(require) {
// contentType: 'text/plain',
// binStr: 'barbarbarbarbar'
// }];
// keychainStub.getReveiverPublicKey.yields(null, {
// keychainStub.getReceiverPublicKey.yields(null, {
// _id: "fcf8b4aa-5d09-4089-8b4f-e3bc5091daf3",
// userId: "safewithme.testuser@gmail.com",
// publicKey: publicKey
@ -307,7 +307,7 @@ define(function(require) {
// smtpClientStub.send.yields();
// emailDao.smtpSend(dummyMail, function(err) {
// expect(keychainStub.getReveiverPublicKey.calledOnce).to.be.true;
// expect(keychainStub.getReceiverPublicKey.calledOnce).to.be.true;
// expect(pgpStub.exportKeys.calledOnce).to.be.true;
// expect(pgpStub.encrypt.calledOnce).to.be.true;
// expect(smtpClientStub.send.calledOnce).to.be.true;
@ -577,7 +577,7 @@ define(function(require) {
it('should work', function(done) {
dummyMail.body = app.string.cryptPrefix + btoa('asdf') + app.string.cryptSuffix;
devicestorageStub.listItems.yields(null, [dummyMail, dummyMail]);
keychainStub.getReveiverPublicKey.yields(null, {
keychainStub.getReceiverPublicKey.yields(null, {
_id: "fcf8b4aa-5d09-4089-8b4f-e3bc5091daf3",
userId: "safewithme.testuser@gmail.com",
publicKey: publicKey
@ -593,7 +593,7 @@ define(function(require) {
num: 2
}, function(err, emails) {
expect(devicestorageStub.listItems.calledOnce).to.be.true;
expect(keychainStub.getReveiverPublicKey.calledTwice).to.be.true;
expect(keychainStub.getReceiverPublicKey.calledTwice).to.be.true;
expect(pgpStub.decrypt.calledTwice).to.be.true;
expect(err).to.not.exist;
expect(emails.length).to.equal(2);

View File

@ -0,0 +1,302 @@
define(function(require) {
'use strict';
var LawnchairDAO = require('js/dao/lawnchair-dao'),
PublicKeyDAO = require('js/dao/publickey-dao'),
KeychainDAO = require('js/dao/keychain-dao'),
expect = chai.expect;
var testUser = 'test@example.com';
describe('Keychain DAO unit tests', function() {
var keychainDao, lawnchairDaoStub, pubkeyDaoStub;
beforeEach(function() {
lawnchairDaoStub = sinon.createStubInstance(LawnchairDAO);
pubkeyDaoStub = sinon.createStubInstance(PublicKeyDAO);
keychainDao = new KeychainDAO(lawnchairDaoStub, pubkeyDaoStub);
});
afterEach(function() {});
describe('lookup public key', function() {
it('should fail', function(done) {
keychainDao.lookupPublicKey(undefined, function(err, key) {
expect(err).to.exist;
expect(key).to.not.exist;
done();
});
});
it('should fail', function(done) {
lawnchairDaoStub.read.yields(42);
keychainDao.lookupPublicKey('12345', function(err, key) {
expect(err).to.exist;
expect(key).to.not.exist;
expect(lawnchairDaoStub.read.calledOnce).to.be.true;
done();
});
});
it('should work from local storage', function(done) {
lawnchairDaoStub.read.yields(null, {
_id: '12345',
publicKey: 'asdf'
});
keychainDao.lookupPublicKey('12345', function(err, key) {
expect(err).to.not.exist;
expect(key).to.exist;
expect(lawnchairDaoStub.read.calledOnce).to.be.true;
done();
});
});
it('should work from cloud', function(done) {
lawnchairDaoStub.read.yields();
pubkeyDaoStub.get.yields(null, {
_id: '12345',
publicKey: 'asdf'
});
lawnchairDaoStub.persist.yields();
keychainDao.lookupPublicKey('12345', function(err, key) {
expect(err).to.not.exist;
expect(key).to.exist;
expect(key._id).to.equal('12345');
expect(lawnchairDaoStub.read.calledOnce).to.be.true;
expect(pubkeyDaoStub.get.calledOnce).to.be.true;
expect(lawnchairDaoStub.persist.calledOnce).to.be.true;
done();
});
});
});
describe('get public keys by id', function() {
it('should fail', function(done) {
keychainDao.getPublicKeys([], function(err, keys) {
expect(err).to.not.exist;
expect(keys.length).to.equal(0);
done();
});
});
it('should fail', function(done) {
lawnchairDaoStub.read.yields(42);
var ids = [{
_id: '12345'
}];
keychainDao.getPublicKeys(ids, function(err, keys) {
expect(err).to.exist;
expect(keys).to.not.exist;
expect(lawnchairDaoStub.read.calledOnce).to.be.true;
done();
});
});
it('should work from local storage', function(done) {
lawnchairDaoStub.read.yields(null, {
_id: '12345',
publicKey: 'asdf'
});
var ids = [{
_id: '12345'
}];
keychainDao.getPublicKeys(ids, function(err, keys) {
expect(err).to.not.exist;
expect(keys.length).to.equal(1);
expect(keys[0]._id).to.equal('12345');
expect(lawnchairDaoStub.read.calledOnce).to.be.true;
done();
});
});
});
describe('get receiver public key', function() {
it('should fail due to error in lawnchair list', function(done) {
lawnchairDaoStub.list.yields(42);
keychainDao.getReceiverPublicKey(testUser, function(err, key) {
expect(err).to.exist;
expect(key).to.not.exist;
expect(lawnchairDaoStub.list.calledOnce).to.be.true;
done();
});
});
it('should work from lawnchair list', function(done) {
lawnchairDaoStub.list.yields(null, [{
_id: '12345',
userId: testUser,
publicKey: 'asdf'
}]);
keychainDao.getReceiverPublicKey(testUser, function(err, key) {
expect(err).to.not.exist;
expect(key).to.exist;
expect(key._id).to.equal('12345');
expect(lawnchairDaoStub.list.calledOnce).to.be.true;
done();
});
});
it('should fail due to error in pubkey dao', function(done) {
lawnchairDaoStub.list.yields();
pubkeyDaoStub.getByUserId.yields(42);
keychainDao.getReceiverPublicKey(testUser, function(err, key) {
expect(err).to.exist;
expect(key).to.not.exist;
expect(lawnchairDaoStub.list.calledOnce).to.be.true;
expect(pubkeyDaoStub.getByUserId.calledOnce).to.be.true;
done();
});
});
it('should work from pubkey dao with empty result', function(done) {
lawnchairDaoStub.list.yields();
pubkeyDaoStub.getByUserId.yields();
keychainDao.getReceiverPublicKey(testUser, function(err, key) {
expect(err).to.not.exist;
expect(key).to.not.exist;
expect(lawnchairDaoStub.list.calledOnce).to.be.true;
expect(pubkeyDaoStub.getByUserId.calledOnce).to.be.true;
done();
});
});
it('should work from pubkey dao', function(done) {
lawnchairDaoStub.list.yields();
pubkeyDaoStub.getByUserId.yields(null, {
_id: '12345',
publicKey: 'asdf'
});
lawnchairDaoStub.persist.yields();
keychainDao.getReceiverPublicKey(testUser, function(err, key) {
expect(err).to.not.exist;
expect(key).to.exist;
expect(key._id).to.equal('12345');
expect(lawnchairDaoStub.list.calledOnce).to.be.true;
expect(pubkeyDaoStub.getByUserId.calledOnce).to.be.true;
expect(lawnchairDaoStub.persist.calledOnce).to.be.true;
done();
});
});
});
describe('get user key pair', function() {
it('should work if local keys are already present', function(done) {
lawnchairDaoStub.list.yields(null, [{
_id: '12345',
userId: testUser,
publicKey: 'asdf'
}]);
lawnchairDaoStub.read.yields(null, {
_id: '12345',
publicKey: 'asdf',
encryptedKey: 'qwer'
});
keychainDao.getUserKeyPair(testUser, function(err, keys) {
expect(err).to.not.exist;
expect(keys).to.exist;
expect(keys.publicKey).to.exist;
expect(keys.privateKey).to.exist;
expect(lawnchairDaoStub.list.calledOnce).to.be.true;
expect(lawnchairDaoStub.read.calledTwice).to.be.true;
done();
});
});
it('should work if local keys are not already present', function(done) {
lawnchairDaoStub.list.yields();
pubkeyDaoStub.getByUserId.yields();
keychainDao.getUserKeyPair(testUser, function(err, keys) {
expect(err).to.not.exist;
expect(keys).to.not.exist;
expect(lawnchairDaoStub.list.calledOnce).to.be.true;
expect(pubkeyDaoStub.getByUserId.calledOnce).to.be.true;
done();
});
});
it('should work if local keys are not already present', function(done) {
lawnchairDaoStub.list.yields();
pubkeyDaoStub.getByUserId.yields(null, {
_id: '12345',
publicKey: 'asdf'
});
lawnchairDaoStub.read.yields(null, {
_id: '12345',
publicKey: 'asdf',
encryptedKey: 'qwer'
});
keychainDao.getUserKeyPair(testUser, function(err, keys) {
expect(err).to.not.exist;
expect(keys).to.exist;
expect(keys.publicKey).to.exist;
expect(keys.privateKey).to.exist;
expect(lawnchairDaoStub.list.calledOnce).to.be.true;
expect(lawnchairDaoStub.read.calledTwice).to.be.true;
done();
});
});
});
describe('put user keypair', function() {
it('should fail', function(done) {
var keypair = {
publicKey: {
_id: '12345',
userId: testUser,
publicKey: 'asdf'
},
privateKey: {
_id: '12345',
encryptedKey: 'qwer'
}
};
keychainDao.putUserKeyPair(keypair, function(err) {
expect(err).to.exist;
done();
});
});
it('should work', function(done) {
var keypair = {
publicKey: {
_id: '12345',
userId: testUser,
publicKey: 'asdf'
},
privateKey: {
_id: '12345',
userId: testUser,
encryptedKey: 'qwer'
}
};
lawnchairDaoStub.persist.yields();
pubkeyDaoStub.put.yields();
keychainDao.putUserKeyPair(keypair, function(err) {
expect(err).to.not.exist;
expect(lawnchairDaoStub.persist.calledTwice).to.be.true;
expect(pubkeyDaoStub.put.calledOnce).to.be.true;
done();
});
});
});
});
});

View File

@ -0,0 +1,152 @@
define(function(require) {
'use strict';
var LawnchairDAO = require('js/dao/lawnchair-dao'),
expect = chai.expect;
var dbName = 'lawnchair@test.com';
var key = 'type_1';
var data = {
name: 'testName1',
type: 'testType1'
};
var key2 = 'type_2';
var data2 = {
name: 'testName2',
type: 'testType2'
};
describe('Lawnchair DAO unit tests', function() {
var lawnchairDao;
beforeEach(function(done) {
lawnchairDao = new LawnchairDAO();
lawnchairDao.init(dbName, function(err) {
expect(err).to.not.exist;
expect(lawnchairDao._db).to.exist;
done();
});
});
afterEach(function(done) {
lawnchairDao.clear(function(err) {
expect(err).to.not.exist;
done();
});
});
describe('read', function() {
it('should fail', function(done) {
lawnchairDao.read(undefined, function(err) {
expect(err).to.exist;
done();
});
});
});
describe('list', function() {
it('should fail', function(done) {
lawnchairDao.list(undefined, 0, null, function(err) {
expect(err).to.exist;
done();
});
});
});
describe('remove list', function() {
it('should fail', function(done) {
lawnchairDao.removeList(undefined, function(err) {
expect(err).to.exist;
done();
});
});
});
describe('persist/read/remove', function() {
it('should fail', function(done) {
lawnchairDao.persist(undefined, data, function(err) {
expect(err).to.exist;
done();
});
});
it('should fail', function(done) {
lawnchairDao.persist('1234', undefined, function(err) {
expect(err).to.exist;
done();
});
});
it('should work', function(done) {
lawnchairDao.persist(key, data, function(err) {
expect(err).to.not.exist;
lawnchairDao.read(key, onRead);
});
function onRead(err, fetched) {
expect(err).to.not.exist;
expect(fetched).to.deep.equal(data);
lawnchairDao.remove(key, onRemove);
}
function onRemove(err) {
expect(err).to.not.exist;
lawnchairDao.read(key, onReadAgain);
}
function onReadAgain(err, fetched) {
expect(err).to.not.exist;
expect(fetched).to.not.exist;
done();
}
});
});
describe('batch/list/removeList', function() {
it('should fails', function(done) {
lawnchairDao.batch({}, function(err) {
expect(err).to.exist;
done();
});
});
it('should work', function(done) {
var list = [{
key: key,
object: data
}, {
key: key2,
object: data2
}];
lawnchairDao.batch(list, function(err) {
expect(err).to.not.exist;
lawnchairDao.list('type', 0, null, onList);
});
function onList(err, fetched) {
expect(err).to.not.exist;
expect(fetched.length).to.equal(2);
expect(fetched[0]).to.deep.equal(list[0].object);
lawnchairDao.removeList('type', onRemoveList);
}
function onRemoveList(err) {
expect(err).to.not.exist;
lawnchairDao.list('type', 0, null, onListAgain);
}
function onListAgain(err, fetched) {
expect(err).to.not.exist;
expect(fetched).to.exist;
expect(fetched.length).to.equal(0);
done();
}
});
});
});
});

View File

@ -22,7 +22,12 @@ function startTests() {
[
'test/new-unit/email-dao-test',
'test/new-unit/app-controller-test',
'test/new-unit/pgp-test'
'test/new-unit/pgp-test',
'test/new-unit/rest-dao-test',
'test/new-unit/publickey-dao-test',
'test/new-unit/lawnchair-dao-test',
'test/new-unit/keychain-dao-test',
'test/new-unit/devicestorage-dao-test'
], function() {
//Tests loaded, run tests
mocha.run();

View File

@ -0,0 +1,130 @@
define(function(require) {
'use strict';
var RestDAO = require('js/dao/rest-dao'),
PublicKeyDAO = require('js/dao/publickey-dao'),
expect = chai.expect;
describe('Public Key DAO unit tests', function() {
var pubkeyDao, restDaoStub;
beforeEach(function() {
restDaoStub = sinon.createStubInstance(RestDAO);
pubkeyDao = new PublicKeyDAO(restDaoStub);
});
afterEach(function() {});
describe('get', function() {
it('should fail', function(done) {
restDaoStub.get.yields(42);
pubkeyDao.get('id', function(err, key) {
expect(err).to.exist;
expect(key).to.not.exist;
expect(restDaoStub.get.calledOnce).to.be.true;
done();
});
});
it('should work', function(done) {
restDaoStub.get.yields(null, {
_id: '12345',
publicKey: 'asdf'
});
pubkeyDao.get('id', function(err, key) {
expect(err).to.not.exist;
expect(key).to.exist;
expect(key._id).to.exist;
expect(key.publicKey).to.exist;
expect(restDaoStub.get.calledOnce).to.be.true;
done();
});
});
});
describe('get by userId', function() {
it('should fail', function(done) {
restDaoStub.get.yields(42);
pubkeyDao.getByUserId('userId', function(err, key) {
expect(err).to.exist;
expect(key).to.not.exist;
expect(restDaoStub.get.calledOnce).to.be.true;
done();
});
});
it('should react to 404', function(done) {
restDaoStub.get.yields({
code: 404
});
pubkeyDao.getByUserId('userId', function(err, key) {
expect(err).to.not.exist;
expect(key).to.not.exist;
expect(restDaoStub.get.calledOnce).to.be.true;
done();
});
});
it('should return empty array', function(done) {
restDaoStub.get.yields(null, []);
pubkeyDao.getByUserId('userId', function(err, key) {
expect(err).to.not.exist;
expect(key).to.not.exist;
expect(restDaoStub.get.calledOnce).to.be.true;
done();
});
});
it('should work', function(done) {
restDaoStub.get.yields(null, [{
_id: '12345',
publicKey: 'asdf'
}]);
pubkeyDao.getByUserId('userId', function(err, key) {
expect(err).to.not.exist;
expect(key).to.exist;
expect(key._id).to.exist;
expect(key.publicKey).to.exist;
expect(restDaoStub.get.calledOnce).to.be.true;
done();
});
});
});
describe('put', function() {
it('should fail', function(done) {
restDaoStub.put.yields();
pubkeyDao.put({
_id: '12345',
publicKey: 'asdf'
}, function(err) {
expect(err).to.not.exist;
expect(restDaoStub.put.calledOnce).to.be.true;
done();
});
});
});
describe('remove', function() {
it('should fail', function(done) {
restDaoStub.remove.yields();
pubkeyDao.remove('12345', function(err) {
expect(err).to.not.exist;
expect(restDaoStub.remove.calledOnce).to.be.true;
done();
});
});
});
});
});

View File

@ -0,0 +1,117 @@
define(function(require) {
'use strict';
var RestDAO = require('js/dao/rest-dao'),
$ = require('jquery'),
expect = chai.expect;
describe('Rest DAO unit tests', function() {
var restDao;
beforeEach(function() {
sinon.stub($, 'ajax').yieldsTo('success', {
foo: 'bar'
});
restDao = new RestDAO();
});
afterEach(function() {
$.ajax.restore();
});
describe('contructor', function() {
it('should set default base uri', function() {
restDao = new RestDAO();
expect(restDao).to.exist;
expect(restDao._baseUri).to.exist;
});
it('should accept default base uri', function() {
var baseUri = 'http://custom.com';
restDao = new RestDAO({
baseUri: baseUri
});
expect(restDao).to.exist;
expect(restDao._baseUri).to.equal(baseUri);
});
});
describe('get', function() {
it('should fail', function(done) {
$.ajax.restore();
sinon.stub($, 'ajax').yieldsTo('error', {
status: 500
}, {
statusText: 'Internal error'
}, {});
restDao.get('/asdf', function(err, data) {
expect(err).to.exist;
expect(err.code).to.equal(500);
expect(data).to.not.exist;
done();
});
});
it('should work', function(done) {
restDao.get('/asdf', function(err, data) {
expect(err).to.not.exist;
expect(data.foo).to.equal('bar');
done();
});
});
});
describe('put', function() {
it('should fail', function(done) {
$.ajax.restore();
sinon.stub($, 'ajax').yieldsTo('error', {
status: 500
}, {
statusText: 'Internal error'
}, {});
restDao.put('/asdf', {}, function(err) {
expect(err).to.exist;
expect(err.code).to.equal(500);
done();
});
});
it('should work', function(done) {
restDao.put('/asdf', {}, function(err) {
expect(err).to.not.exist;
done();
});
});
});
describe('remove', function() {
it('should fail', function(done) {
$.ajax.restore();
sinon.stub($, 'ajax').yieldsTo('error', {
status: 500
}, {
statusText: 'Internal error'
}, {});
restDao.remove('/asdf', function(err) {
expect(err).to.exist;
expect(err.code).to.equal(500);
done();
});
});
it('should work', function(done) {
restDao.remove('/asdf', function(err) {
expect(err).to.not.exist;
done();
});
});
});
});
});

View File

@ -1,4 +1,4 @@
define(['underscore', 'cryptoLib/util', 'js/crypto/crypto', 'js/dao/devicestorage-dao', 'test/test-data'], function(_, util, Crypto, DeviceStorageDAO, testData) {
define(['underscore', 'cryptoLib/util', 'js/crypto/crypto', 'js/dao/devicestorage-dao', 'test/test-data', 'js/dao/lawnchair-dao'], function(_, util, Crypto, DeviceStorageDAO, testData, LawnchairDAO) {
'use strict';
module("DeviceStorage");
@ -15,7 +15,7 @@ define(['underscore', 'cryptoLib/util', 'js/crypto/crypto', 'js/dao/devicestorag
asyncTest("Init", 3, function() {
// init dependencies
storage = new DeviceStorageDAO();
storage = new DeviceStorageDAO(new LawnchairDAO());
storage.init(devicestorageTest.user, function() {
ok(storage, 'DeviceStorageDAO');

View File

@ -1,30 +1,29 @@
define(['js/dao/keychain-dao', 'js/dao/lawnchair-dao'], function(KeychainDAO, jsonDao) {
define(['js/dao/keychain-dao', 'js/dao/lawnchair-dao'], function(KeychainDAO, LawnchairDAO) {
'use strict';
module("Keychain DAO");
var keychaindaoTest = {
user: 'keychaindao_test@example.com',
password: 'Password',
keySize: 128,
ivSize: 128,
rsaKeySize: 512
};
var jsonDao,
keychaindaoTest = {
user: 'keychaindao_test@example.com',
password: 'Password',
keySize: 128,
ivSize: 128,
rsaKeySize: 512
};
asyncTest("Init", 2, function() {
// stubbing
var cloudstorageStub = {
putPublicKey: function(pk, callback) {
callback();
},
putPrivateKey: function(prk, callback) {
var pubkeyDaoStub = {
put: function(pk, callback) {
callback();
}
};
// module instancing
keychaindaoTest.keychainDao = new KeychainDAO(cloudstorageStub);
jsonDao = new LawnchairDAO();
keychaindaoTest.keychainDao = new KeychainDAO(jsonDao, pubkeyDaoStub);
ok(keychaindaoTest.keychainDao);
// init and clear db before test
@ -82,7 +81,7 @@ define(['js/dao/keychain-dao', 'js/dao/lawnchair-dao'], function(KeychainDAO, js
});
asyncTest("Get User Keypair", 2, function() {
keychaindaoTest.keychainDao.getReveiverPublicKey(keychaindaoTest.user, function(err, pubkey) {
keychaindaoTest.keychainDao.getReceiverPublicKey(keychaindaoTest.user, function(err, pubkey) {
ok(!err);
ok(pubkey && pubkey.publicKey);

View File

@ -1,87 +0,0 @@
define(['js/dao/lawnchair-dao'], function(jsonDao) {
'use strict';
module("Lawnchair DAO");
var lawnchairdaoTest = {
user: 'lawnchair@test.com'
};
asyncTest("Init", 2, function() {
// init dependencies
jsonDao.init(lawnchairdaoTest.user, function() {
ok(true, 'init db');
// clear db before test
jsonDao.clear(function() {
ok(true, 'cleared db');
start();
});
});
});
asyncTest("CRUD object literal", 5, function() {
var key = 'type_1';
var data = {
name: 'testName1',
type: 'testType1'
};
var key2 = 'type_2';
var data2 = {
name: 'testName2',
type: 'testType2'
};
// create
jsonDao.persist(key, data, function() {
// read
jsonDao.read(key, function(read) {
equal(data.name, read.name, 'Create, Read');
// list all
jsonDao.list('type', 0, null, function(list) {
ok(list.length === 1, 'List');
// update
var newName = 'updatedName';
read.name = newName;
jsonDao.persist(key, read, function() {
// read again
jsonDao.read(key, function(updated) {
equal(updated.name, newName, 'Update');
// persist 2nd type
jsonDao.persist(key2, data2, function() {
// delete all items of 2nd type
jsonDao.removeList(key2, function() {
jsonDao.list('type', 0, null, function(newList) {
ok(newList.length === 1, 'List');
// delete
jsonDao.remove(key, function() {
// should read empty
jsonDao.read(key, function(lastRead) {
equal(lastRead, undefined, 'Delete');
start();
});
});
});
});
});
});
});
});
});
});
});
});

View File

@ -10,7 +10,7 @@ require(['../../src/require-config'], function() {
require(['js/app-config', 'cordova'], function(app) {
// clear session storage of failed tests, so async order is correct after fail & refresh
window.sessionStorage.clear();
window.Worker = undefined;
//window.Worker = undefined;
app.config.workerPath = '../../src/js';
@ -24,7 +24,6 @@ function startTests() {
'test/unit/forge-test',
'test/unit/aes-test',
'test/unit/rsa-test',
'test/unit/lawnchair-dao-test',
'test/unit/keychain-dao-test',
'test/unit/crypto-test',
'test/unit/devicestorage-dao-test'