1
0
mirror of https://github.com/moparisthebest/mail synced 2024-12-22 23:38:48 -05:00

Merge pull request #29 from whiteout-io/dev/no-jquery

Dev/no jquery
This commit is contained in:
Tankred Hase 2014-03-03 17:12:28 +01:00
commit 386fbfa307
6 changed files with 241 additions and 239 deletions

View File

@ -4,8 +4,7 @@
define(function(require) {
'use strict';
var $ = require('jquery'),
ImapClient = require('imap-client'),
var ImapClient = require('imap-client'),
mailreader = require('mailreader'),
PgpMailer = require('pgpmailer'),
EmailDAO = require('js/dao/email-dao'),
@ -149,32 +148,31 @@ define(function(require) {
};
self.getCertficate = function(localCallback) {
var xhr;
if (self.certificate) {
localCallback(null, self.certificate);
return;
}
// fetch pinned local ssl certificate
xhr = new XMLHttpRequest();
xhr.open('GET', '/ca/Google_Internet_Authority_G2.pem');
xhr.onload = function() {
if (xhr.readyState === 4 && xhr.status === 200 && xhr.responseText) {
self.certificate = xhr.responseText;
localCallback(null, self.certificate);
} else {
var ca = new RestDAO({
baseUri: '/ca'
});
ca.get({
uri: '/Google_Internet_Authority_G2.pem',
type: 'text'
}, function(err, cert) {
if (err || !cert) {
localCallback({
errMsg: 'Could not fetch pinned certificate!'
});
return;
}
};
xhr.onerror = function() {
localCallback({
errMsg: 'Could not fetch pinned certificate!'
});
};
xhr.send();
self.certificate = cert;
localCallback(null, self.certificate);
return;
});
};
self.isOnline = function() {
@ -277,29 +275,24 @@ define(function(require) {
}
// fetch gmail user's email address from the Google Authorization Server endpoint
$.ajax({
url: 'https://www.googleapis.com/oauth2/v1/tokeninfo?access_token=' + token,
type: 'GET',
dataType: 'json',
success: function(info) {
if (!info || !info.email) {
callback({
errMsg: 'Error looking up email address on google api!'
});
return;
}
var googleEndpoint = new RestDAO({
baseUri: 'https://www.googleapis.com'
});
// cache the email address on the device
self._appConfigStore.storeList([info.email], itemKey, function(err) {
callback(err, info.email);
});
},
error: function(xhr, textStatus, err) {
googleEndpoint.get({
uri: '/oauth2/v1/tokeninfo?access_token=' + token
}, function(err, info) {
if (err || !info || !info.email) {
callback({
errMsg: xhr.status + ': ' + xhr.statusText,
err: err
errMsg: 'Error looking up email address on google api!'
});
return;
}
// cache the email address on the device
self._appConfigStore.storeList([info.email], itemKey, function(err) {
callback(err, info.email);
});
});
}
};
@ -310,35 +303,34 @@ define(function(require) {
self.fetchOAuthToken = function(callback) {
// get OAuth Token from chrome
chrome.identity.getAuthToken({
'interactive': true
},
function(token) {
if ((chrome && chrome.runtime && chrome.runtime.lastError) || !token) {
'interactive': true
}, onToken);
function onToken(token) {
if ((chrome && chrome.runtime && chrome.runtime.lastError) || !token) {
callback({
errMsg: 'Error fetching an OAuth token for the user!'
});
return;
}
// get email address for the token
self.queryEmailAddress(token, function(err, emailAddress) {
if (err || !emailAddress) {
callback({
errMsg: 'Error fetching an OAuth token for the user!',
err: chrome.runtime.lastError
errMsg: 'Error looking up email address on login!',
err: err
});
return;
}
// get email address for the token
self.queryEmailAddress(token, function(err, emailAddress) {
if (err || !emailAddress) {
callback({
errMsg: 'Error looking up email address on login!',
err: err
});
return;
}
// init the email dao
callback(null, {
emailAddress: emailAddress,
token: token
});
// init the email dao
callback(null, {
emailAddress: emailAddress,
token: token
});
}
);
});
}
};
self.buildModules = function() {

View File

@ -1,8 +1,7 @@
define(function(require) {
'use strict';
var $ = require('jquery'),
config = require('js/app-config').config;
var config = require('js/app-config').config;
var RestDAO = function(options) {
if (options && options.baseUri) {
@ -18,7 +17,7 @@ define(function(require) {
* @param {String} options.type (optional) The type of data that you're expecting back from the server: json, xml, text. Default: json.
*/
RestDAO.prototype.get = function(options, callback) {
var acceptHeader;
var xhr, acceptHeader;
if (typeof options.uri === 'undefined') {
callback({
@ -44,66 +43,97 @@ define(function(require) {
return;
}
$.ajax({
url: this._baseUri + options.uri,
type: 'GET',
dataType: options.type,
headers: {
'Accept': acceptHeader
},
success: function(res, textStatus, xhr) {
xhr = new XMLHttpRequest();
xhr.open('GET', this._baseUri + options.uri);
xhr.setRequestHeader('Accept', acceptHeader);
xhr.onload = function() {
if (xhr.readyState === 4 && xhr.status === 200) {
var res;
if (options.type === 'json') {
res = JSON.parse(xhr.responseText);
} else {
res = xhr.responseText;
}
callback(null, res, xhr.status);
},
error: function(xhr, textStatus, err) {
callback({
code: xhr.status,
errMsg: xhr.statusText,
err: err
});
return;
}
});
callback({
code: xhr.status,
errMsg: xhr.statusText
});
};
xhr.onerror = function(e) {
callback({
errMsg: 'Error: ' + e.error
});
};
xhr.send();
};
/**
* 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(res, textStatus, xhr) {
callback(null, res, xhr.status);
},
error: function(xhr, textStatus, err) {
callback({
code: xhr.status,
errMsg: xhr.statusText,
err: err
});
var xhr;
xhr = new XMLHttpRequest();
xhr.open('PUT', this._baseUri + uri);
xhr.setRequestHeader('Content-Type', 'application/json');
xhr.onload = function() {
if (xhr.readyState === 4 && (xhr.status === 200 || xhr.status === 201 || xhr.status === 304)) {
callback(null, xhr.responseText, xhr.status);
return;
}
});
callback({
code: xhr.status,
errMsg: xhr.statusText
});
};
xhr.onerror = function(e) {
callback({
errMsg: 'Error: ' + e.error
});
};
xhr.send(JSON.stringify(item));
};
/**
* DELETE (remove) request
*/
RestDAO.prototype.remove = function(uri, callback) {
$.ajax({
url: this._baseUri + uri,
type: 'DELETE',
success: function(res, textStatus, xhr) {
callback(null, res, xhr.status);
},
error: function(xhr, textStatus, err) {
callback({
code: xhr.status,
errMsg: xhr.statusText,
err: err
});
var xhr;
xhr = new XMLHttpRequest();
xhr.open('DELETE', this._baseUri + uri);
xhr.onload = function() {
if (xhr.readyState === 4 && xhr.status === 200) {
callback(null, xhr.responseText, xhr.status);
return;
}
});
callback({
code: xhr.status,
errMsg: xhr.statusText
});
};
xhr.onerror = function(e) {
callback({
errMsg: 'Error: ' + e.error
});
};
xhr.send();
};
return RestDAO;

File diff suppressed because one or more lines are too long

View File

@ -14,7 +14,6 @@
lawnchair: 'lawnchair/lawnchair-git',
lawnchairSQL: 'lawnchair/lawnchair-adapter-webkit-sqlite-git',
lawnchairIDB: 'lawnchair/lawnchair-adapter-indexed-db-git',
jquery: 'jquery/jquery-2.0.3.min',
angular: 'angular/angular.min',
angularRoute: 'angular/angular-route.min',
angularTouch: 'angular/angular-touch.min',

View File

@ -5,14 +5,8 @@ define(function(require) {
EmailDAO = require('js/dao/email-dao'),
OutboxBO = require('js/bo/outbox'),
DeviceStorageDAO = require('js/dao/devicestorage-dao'),
$ = require('jquery'),
expect = chai.expect;
var appControllerTest = {
user: 'test@exmaple.com',
passphrase: 'asdf'
};
describe('App Controller unit tests', function() {
var emailDaoStub, outboxStub, appConfigStoreStub, isOnlineStub,
identityStub;
@ -27,11 +21,6 @@ define(function(require) {
isOnlineStub = sinon.stub(controller, 'isOnline');
sinon.stub($, 'get');
sinon.stub($, 'ajax').yieldsTo('success', {
email: appControllerTest.user
});
window.chrome = window.chrome || {};
window.chrome.identity = window.chrome.identity || {};
if (typeof window.chrome.identity.getAuthToken !== 'function') {
@ -41,8 +30,6 @@ define(function(require) {
});
afterEach(function() {
$.get.restore();
$.ajax.restore();
identityStub.restore();
isOnlineStub.restore();
});
@ -180,30 +167,49 @@ define(function(require) {
});
describe('fetchOAuthToken', function() {
it('should work the first time', function(done) {
appConfigStoreStub.listItems.yields(null, []);
appConfigStoreStub.storeList.yields();
identityStub.yields('token42');
var queryEmailAddressStub;
controller.fetchOAuthToken(function(err) {
beforeEach(function() {
// buildModules
queryEmailAddressStub = sinon.stub(controller, 'queryEmailAddress');
});
afterEach(function() {
queryEmailAddressStub.restore();
});
it('should work', function(done) {
identityStub.yields('token42');
queryEmailAddressStub.yields(null, 'bob@asdf.com');
controller.fetchOAuthToken(function(err, res) {
expect(err).to.not.exist;
expect(appConfigStoreStub.listItems.calledOnce).to.be.true;
expect(appConfigStoreStub.storeList.calledOnce).to.be.true;
expect(res.emailAddress).to.equal('bob@asdf.com');
expect(res.token).to.equal('token42');
expect(queryEmailAddressStub.calledOnce).to.be.true;
expect(identityStub.calledOnce).to.be.true;
expect($.ajax.calledOnce).to.be.true;
done();
});
});
it('should work when the email address is cached', function(done) {
appConfigStoreStub.listItems.yields(null, ['asdf']);
identityStub.yields('token42');
it('should fail due to chrome api error', function(done) {
identityStub.yields();
controller.fetchOAuthToken(function(err) {
expect(err).to.not.exist;
expect(appConfigStoreStub.listItems.calledOnce).to.be.true;
expect(err).to.exist;
expect(identityStub.calledOnce).to.be.true;
done();
});
});
it('should fail due error querying email address', function(done) {
identityStub.yields('token42');
queryEmailAddressStub.yields();
controller.fetchOAuthToken(function(err) {
expect(err).to.exist;
expect(queryEmailAddressStub.calledOnce).to.be.true;
expect(identityStub.calledOnce).to.be.true;
expect($.ajax.called).to.be.false;
done();
});
});

View File

@ -2,21 +2,24 @@ 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;
var restDao, xhrMock, requests;
beforeEach(function() {
restDao = new RestDAO();
xhrMock = sinon.useFakeXMLHttpRequest();
requests = [];
xhrMock.onCreate = function(xhr) {
requests.push(xhr);
};
});
afterEach(function() {
if (typeof $.ajax.callCount !== 'undefined') {
$.ajax.restore();
}
xhrMock.restore();
});
describe('contructor', function() {
@ -38,96 +41,86 @@ define(function(require) {
});
describe('get', function() {
it('should work with json as default type', function(done) {
var spy = sinon.stub($, 'ajax').yieldsTo('success', {
foo: 'bar'
}, 'success', {
status: 200
it('should work with json as default type', function() {
restDao.get({
uri: '/asdf'
}, function(err, data, status) {
expect(err).to.not.exist;
expect(data.foo).to.equal('bar');
var req = requests[0];
expect(req.requestHeaders.Accept).to.equal('application/json');
expect(status).to.equal(200);
});
expect(requests.length).to.equal(1);
requests[0].respond(200, {
"Content-Type": "application/json"
}, '{"foo": "bar"}');
});
it('should work with jsonz', function() {
restDao.get({
uri: '/asdf',
type: 'json'
}, function(err, data, status) {
expect(err).to.not.exist;
expect(data.foo).to.equal('bar');
expect(spy.calledWith(sinon.match(function(request) {
return request.headers.Accept === 'application/json' && request.dataType === 'json';
}))).to.be.true;
var req = requests[0];
expect(req.requestHeaders.Accept).to.equal('application/json');
expect(status).to.equal(200);
done();
});
expect(requests.length).to.equal(1);
requests[0].respond(200, {
"Content-Type": "application/json"
}, '{"foo": "bar"}');
});
it('should work with json', function(done) {
var spy = sinon.stub($, 'ajax').yieldsTo('success', {
foo: 'bar'
}, 'success', {
status: 200
});
restDao.get({
uri: '/asdf',
type: 'json'
}, function(err, data, status) {
expect(err).to.not.exist;
expect(data.foo).to.equal('bar');
expect(spy.calledWith(sinon.match(function(request) {
return request.headers.Accept === 'application/json' && request.dataType === 'json';
}))).to.be.true;
expect(status).to.equal(200);
done();
});
});
it('should work with plain text', function(done) {
var spy = sinon.stub($, 'ajax').yieldsTo('success', 'foobar!', 'success', {
status: 200
});
it('should work with plain text', function() {
restDao.get({
uri: '/asdf',
type: 'text'
}, function(err, data, status) {
expect(err).to.not.exist;
expect(data).to.equal('foobar!');
expect(spy.calledWith(sinon.match(function(request) {
return request.headers.Accept === 'text/plain' && request.dataType === 'text';
}))).to.be.true;
var req = requests[0];
expect(req.requestHeaders.Accept).to.equal('text/plain');
expect(status).to.equal(200);
done();
});
expect(requests.length).to.equal(1);
requests[0].respond(200, {
"Content-Type": "text/plain"
}, 'foobar!');
});
it('should work with xml', function(done) {
var spy = sinon.stub($, 'ajax').yieldsTo('success', '<foo>bar</foo>', 'success', {
status: 200
});
it('should work with xml', function() {
restDao.get({
uri: '/asdf',
type: 'xml'
}, function(err, data, status) {
expect(err).to.not.exist;
expect(data).to.equal('<foo>bar</foo>'); // that's probably not right, but in the unit test, it is :)
expect(spy.calledWith(sinon.match(function(request) {
return request.headers.Accept === 'application/xml' && request.dataType === 'xml';
}))).to.be.true;
expect(data).to.equal('<foo>bar</foo>');
var req = requests[0];
expect(req.requestHeaders.Accept).to.equal('application/xml');
expect(status).to.equal(200);
done();
});
expect(requests.length).to.equal(1);
requests[0].respond(200, {
"Content-Type": "application/xml"
}, '<foo>bar</foo>');
});
it('should fail for missing uri parameter', function(done) {
it('should fail for missing uri parameter', function() {
restDao.get({}, function(err, data) {
expect(err).to.exist;
expect(err.code).to.equal(400);
expect(data).to.not.exist;
done();
});
});
it('should fail for unhandled data type', function(done) {
it('should fail for unhandled data type', function() {
restDao.get({
uri: '/asdf',
type: 'snafu'
@ -135,84 +128,72 @@ define(function(require) {
expect(err).to.exist;
expect(err.code).to.equal(400);
expect(data).to.not.exist;
done();
});
});
it('should fail for server error', function(done) {
sinon.stub($, 'ajax').yieldsTo('error', {
status: 500
}, {
statusText: 'Internal error'
}, {});
it('should fail for server error', function() {
restDao.get({
uri: '/asdf'
}, function(err, data) {
expect(err).to.exist;
expect(err.code).to.equal(500);
expect(data).to.not.exist;
done();
});
expect(requests.length).to.equal(1);
requests[0].respond(500, {
"Content-Type": "text/plain"
}, 'Internal error');
});
});
describe('put', function() {
it('should fail', function(done) {
sinon.stub($, 'ajax').yieldsTo('error', {
status: 500
}, {
statusText: 'Internal error'
}, {});
it('should fail', function() {
restDao.put('/asdf', {}, function(err) {
expect(err).to.exist;
expect(err.code).to.equal(500);
done();
});
expect(requests.length).to.equal(1);
requests[0].respond(500, {
"Content-Type": "text/plain"
}, 'Internal error');
});
it('should work', function(done) {
var spy = sinon.stub($, 'ajax').yieldsTo('success', undefined, 'success', {
status: 201
});
it('should work', function() {
restDao.put('/asdf', {}, function(err, res, status) {
expect(err).to.not.exist;
expect(res).to.not.exist;
expect(spy.callCount).to.equal(1);
expect(res).to.equal('');
expect(status).to.equal(201);
done();
});
expect(requests.length).to.equal(1);
requests[0].respond(201);
});
});
describe('remove', function() {
it('should fail', function(done) {
sinon.stub($, 'ajax').yieldsTo('error', {
status: 500
}, {
statusText: 'Internal error'
}, {});
it('should fail', function() {
restDao.remove('/asdf', function(err) {
expect(err).to.exist;
expect(err.code).to.equal(500);
done();
});
expect(requests.length).to.equal(1);
requests[0].respond(500, {
"Content-Type": "text/plain"
}, 'Internal error');
});
it('should work', function(done) {
var spy = sinon.stub($, 'ajax').yieldsTo('success', undefined, 'success', {
status: 204
});
it('should work', function() {
restDao.remove('/asdf', function(err, res, status) {
expect(err).to.not.exist;
expect(res).to.not.exist;
expect(spy.callCount).to.equal(1);
expect(status).to.equal(204);
done();
expect(res).to.equal('');
expect(status).to.equal(200);
});
expect(requests.length).to.equal(1);
requests[0].respond(200);
});
});