diff options
-rw-r--r-- | README.md | 4 | ||||
-rw-r--r-- | app/scripts/lib/encryptor.js | 51 | ||||
-rw-r--r-- | package.json | 3 | ||||
-rw-r--r-- | test/integration/bundle.js | 103 | ||||
-rw-r--r-- | test/integration/index.html | 2 | ||||
-rw-r--r-- | test/integration/index.js | 21 | ||||
-rw-r--r-- | test/integration/lib/encryptor-test.js | 17 | ||||
-rw-r--r-- | test/integration/lib/first-time.js (renamed from test/integration/tests.js) | 3 |
8 files changed, 201 insertions, 3 deletions
@@ -90,6 +90,10 @@ You can also test with a continuously watching process, via `npm run watch`. You can run the linter by itself with `gulp lint`. +#### Writing Browser Tests + +To write tests that will be run in the browser using QUnit, add your test files to `test/integration/lib`. + ### Deploying the UI You must be authorized already on the MetaMask plugin. diff --git a/app/scripts/lib/encryptor.js b/app/scripts/lib/encryptor.js new file mode 100644 index 000000000..607825764 --- /dev/null +++ b/app/scripts/lib/encryptor.js @@ -0,0 +1,51 @@ +var vector = global.crypto.getRandomValues(new Uint8Array(16)) +var key = null + +module.exports = { + encrypt, + decrypt, + convertArrayBufferViewtoString, + keyFromPassword, +} + +// Takes a Pojo, returns encrypted text. +function encrypt (password, dataObj) { + var data = JSON.stringify(dataObj) + global.crypto.subtle.encrypt({name: 'AES-CBC', iv: vector}, key, convertStringToArrayBufferView(data)).then(function(result){ + const encryptedData = new Uint8Array(result) + return encryptedData + }, + function(e){ + console.log(e.message) + }) +} + +// Takes encrypted text, returns the restored Pojo. +function decrypt (password, text) { + +} + +function convertStringToArrayBufferView (str) { + var bytes = new Uint8Array(str.length) + for (var i = 0; i < str.length; i++) { + bytes[i] = str.charCodeAt(i) + } + + return bytes +} + +function convertArrayBufferViewtoString (buffer) { + var str = '' + for (var i = 0; i < buffer.byteLength; i++) { + str += String.fromCharCode(buffer[i]) + } + + return str +} + +function keyFromPassword (password) { + global.crypto.subtle.digest({name: 'SHA-256'}, convertStringToArrayBufferView(password)).then(function(result){ + return global.crypto.subtle.importKey('raw', result, {name: 'AES-CBC'}, false, ['encrypt', 'decrypt']) + }) +} + diff --git a/package.json b/package.json index 273117f8a..a4f234735 100644 --- a/package.json +++ b/package.json @@ -8,6 +8,7 @@ "lint": "gulp lint", "dev": "gulp dev", "dist": "gulp dist", + "buildCiUnits": "node test/integration/index.js", "test": "npm run fastTest && npm run ci && npm run lint", "fastTest": "mocha --require test/helper.js --compilers js:babel-register --recursive \"test/unit/**/*.js\"", "watch": "mocha watch --compilers js:babel-register --recursive \"test/unit/**/*.js\"", @@ -15,7 +16,7 @@ "mock": "beefy mock-dev.js:bundle.js --live --open --index=./development/index.html --cwd ./", "buildMock": "browserify ./mock-dev.js -o ./development/bundle.js", "testem": "npm run buildMock && testem", - "ci": "npm run buildMock && testem ci -P 2", + "ci": "npm run buildMock && npm run buildCiUnits && testem ci -P 2", "announce": "node development/announcer.js" }, "browserify": { diff --git a/test/integration/bundle.js b/test/integration/bundle.js new file mode 100644 index 000000000..5058259b1 --- /dev/null +++ b/test/integration/bundle.js @@ -0,0 +1,103 @@ +window.QUnit = QUnit; (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){ +(function (global){ +"use strict"; + +var vector = global.crypto.getRandomValues(new Uint8Array(16)); + +module.exports = { + encrypt: encrypt, + decrypt: decrypt +}; + +// Takes a Pojo, returns encrypted text. +function encrypt(password, dataObj) { + var data = JSON.stringify(dataObj); + global.crypto.subtle.encrypt({ name: "AES-CBC", iv: vector }, key, convertStringToArrayBufferView(data)).then(function (result) { + var encryptedData = new Uint8Array(result); + return encryptedData; + }, function (e) { + console.log(e.message); + }); +} + +// Takes encrypted text, returns the restored Pojo. +function decrypt(password, text) {} + +function convertStringToArrayBufferView(str) { + var bytes = new Uint8Array(str.length); + for (var i = 0; i < str.length; i++) { + bytes[i] = str.charCodeAt(i); + } + + return bytes; +} + +function convertArrayBufferViewtoString(buffer) { + var str = ""; + for (var i = 0; i < buffer.byteLength; i++) { + str += String.fromCharCode(buffer[i]); + } + + return str; +} + +var password = "password"; + +var key = null; + +function keyFromPassword(password) { + global.crypto.subtle.digest({ name: "SHA-256" }, convertStringToArrayBufferView(password)).then(function (result) { + return global.crypto.subtle.importKey("raw", result, { name: "AES-CBC" }, false, ["encrypt", "decrypt"]); + }); +} + +}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) +},{}],2:[function(require,module,exports){ +'use strict'; + +var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol ? "symbol" : typeof obj; }; + +var encryptor = require('../../../app/scripts/lib/encryptor'); + +QUnit.test('encryptor', function (assert) { + var password, data, encrypted; + + password = 'a sample passw0rd'; + data = { foo: 'data to encrypt' }; + + encryptor.encrypt(password, data).then(function (result) { + assert.equal(typeof result === 'undefined' ? 'undefined' : _typeof(result), 'string', 'returns a string'); + }).catch(function (reason) { + assert.ifError(reason, 'threw an error'); + }); +}); + +},{"../../../app/scripts/lib/encryptor":1}],3:[function(require,module,exports){ +'use strict'; + +QUnit.test('agree to terms', function (assert) { + var done = assert.async(); + + // Select the mock app root + var app = $('iframe').contents().find('#app-content .mock-app-root'); + + app.find('.markdown').prop('scrollTop', 100000000); + + wait().then(function () { + app.find('button').click(); + }).then(function () { + return wait(); + }).then(function () { + var title = app.find('h1').text(); + assert.equal(title, 'MetaMask', 'title screen'); + + var buttons = app.find('button'); + assert.equal(buttons.length, 1, 'one button: create new vault'); + + done(); + }); + + // Wait for view to transition: +}); + +},{}]},{},[2,3]); diff --git a/test/integration/index.html b/test/integration/index.html index 6de40b046..ad4b4eb14 100644 --- a/test/integration/index.html +++ b/test/integration/index.html @@ -12,7 +12,7 @@ <script src="https://code.jquery.com/qunit/qunit-2.0.0.js"></script> <script src="./jquery-3.1.0.min.js"></script> <script src="helpers.js"></script> - <script src="tests.js"></script> + <script src="bundle.js"></script> <script src="/testem.js"></script> <iframe src="/development/index.html" height="500px" width="360px"> diff --git a/test/integration/index.js b/test/integration/index.js new file mode 100644 index 000000000..ff6d1baf8 --- /dev/null +++ b/test/integration/index.js @@ -0,0 +1,21 @@ +var fs = require('fs') +var path = require('path') +var browserify = require('browserify'); +var tests = fs.readdirSync(path.join(__dirname, 'lib')) +var bundlePath = path.join(__dirname, 'bundle.js') + +var b = browserify(); + +// Remove old bundle +try { + fs.unlinkSync(bundlePath) +} catch (e) {} + +var writeStream = fs.createWriteStream(bundlePath) + +tests.forEach(function(fileName) { + b.add(path.join(__dirname, 'lib', fileName)) +}) + +b.bundle().pipe(writeStream); + diff --git a/test/integration/lib/encryptor-test.js b/test/integration/lib/encryptor-test.js new file mode 100644 index 000000000..21d6ee6f7 --- /dev/null +++ b/test/integration/lib/encryptor-test.js @@ -0,0 +1,17 @@ +var encryptor = require('../../../app/scripts/lib/encryptor') + +QUnit.test('encryptor', function(assert) { + var password, data, encrypted + + password = 'a sample passw0rd' + data = { foo: 'data to encrypt' } + + encryptor.encrypt(password, data) + .then(function(result) { + assert.equal(typeof result, 'string', 'returns a string') + }) + .catch(function(reason) { + assert.ifError(reason, 'threw an error') + }) + +}) diff --git a/test/integration/tests.js b/test/integration/lib/first-time.js index 92111b05b..af9b94e24 100644 --- a/test/integration/tests.js +++ b/test/integration/lib/first-time.js @@ -15,10 +15,11 @@ QUnit.test('agree to terms', function (assert) { assert.equal(title, 'MetaMask', 'title screen') var buttons = app.find('button') - assert.equal(buttons.length, 2, 'two buttons: create and restore') + assert.equal(buttons.length, 1, 'one button: create new vault') done() }) // Wait for view to transition: }) + |