diff options
author | Csaba Solya <csaba.solya@gmail.com> | 2018-05-10 19:26:02 +0800 |
---|---|---|
committer | Csaba Solya <csaba.solya@gmail.com> | 2018-05-10 19:26:02 +0800 |
commit | 9026651224f03069d3ab80cef5fe1386f9d7a532 (patch) | |
tree | 5ab373e3eef6549bc6ea0d319dbcb59d77c9ea85 | |
parent | f17dc5f4520ce6f9f08db1e87ec9a8917697029a (diff) | |
download | tangerine-wallet-browser-9026651224f03069d3ab80cef5fe1386f9d7a532.tar tangerine-wallet-browser-9026651224f03069d3ab80cef5fe1386f9d7a532.tar.gz tangerine-wallet-browser-9026651224f03069d3ab80cef5fe1386f9d7a532.tar.bz2 tangerine-wallet-browser-9026651224f03069d3ab80cef5fe1386f9d7a532.tar.lz tangerine-wallet-browser-9026651224f03069d3ab80cef5fe1386f9d7a532.tar.xz tangerine-wallet-browser-9026651224f03069d3ab80cef5fe1386f9d7a532.tar.zst tangerine-wallet-browser-9026651224f03069d3ab80cef5fe1386f9d7a532.zip |
add time stamps to transaction history log entries
-rw-r--r-- | app/scripts/controllers/transactions/lib/tx-state-history-helper.js | 21 | ||||
-rw-r--r-- | app/scripts/controllers/transactions/tx-state-manager.js | 23 | ||||
-rw-r--r-- | test/unit/tx-state-history-helper-test.js | 139 | ||||
-rw-r--r-- | test/unit/tx-state-history-helper.js | 46 | ||||
-rw-r--r-- | test/unit/tx-state-manager-test.js | 9 |
5 files changed, 157 insertions, 81 deletions
diff --git a/app/scripts/controllers/transactions/lib/tx-state-history-helper.js b/app/scripts/controllers/transactions/lib/tx-state-history-helper.js index 59a4b562c..bb51c9871 100644 --- a/app/scripts/controllers/transactions/lib/tx-state-history-helper.js +++ b/app/scripts/controllers/transactions/lib/tx-state-history-helper.js @@ -25,26 +25,31 @@ function migrateFromSnapshotsToDiffs (longHistory) { } /** - generates an array of history objects sense the previous state. - The object has the keys opp(the operation preformed), - path(the key and if a nested object then each key will be seperated with a `/`) - value - with the first entry having the note + Generates an array of history objects sense the previous state. + The object has the keys + op (the operation performed), + path (the key and if a nested object then each key will be seperated with a `/`) + value + with the first entry having the note and a timestamp when the change took place @param previousState {object} - the previous state of the object @param newState {object} - the update object @param note {string} - a optional note for the state change - @reurns {array} + @returns {array} */ function generateHistoryEntry (previousState, newState, note) { const entry = jsonDiffer.compare(previousState, newState) // Add a note to the first op, since it breaks if we append it to the entry - if (note && entry[0]) entry[0].note = note + if (entry[0]) { + if (note) entry[0].note = note + + entry[0].timestamp = (new Date()).getTime() + } return entry } /** Recovers previous txMeta state obj - @return {object} + @returns {object} */ function replayHistory (_shortHistory) { const shortHistory = clone(_shortHistory) diff --git a/app/scripts/controllers/transactions/tx-state-manager.js b/app/scripts/controllers/transactions/tx-state-manager.js index 380214c1d..0aae4774b 100644 --- a/app/scripts/controllers/transactions/tx-state-manager.js +++ b/app/scripts/controllers/transactions/tx-state-manager.js @@ -2,6 +2,7 @@ const extend = require('xtend') const EventEmitter = require('events') const ObservableStore = require('obs-store') const ethUtil = require('ethereumjs-util') +const log = require('loglevel') const txStateHistoryHelper = require('./lib/tx-state-history-helper') const createId = require('../../lib/random-id') const { getFinalStates } = require('./lib/util') @@ -158,7 +159,7 @@ class TransactionStateManager extends EventEmitter { /** updates the txMeta in the list and adds a history entry @param txMeta {Object} - the txMeta to update - @param [note] {string} - a not about the update for history + @param [note] {string} - a note about the update for history */ updateTx (txMeta, note) { // validate txParams @@ -398,13 +399,19 @@ class TransactionStateManager extends EventEmitter { _setTxStatus (txId, status) { const txMeta = this.getTx(txId) txMeta.status = status - this.emit(`${txMeta.id}:${status}`, txId) - this.emit(`tx:status-update`, txId, status) - if (['submitted', 'rejected', 'failed'].includes(status)) { - this.emit(`${txMeta.id}:finished`, txMeta) - } - this.updateTx(txMeta, `txStateManager: setting status to ${status}`) - this.emit('update:badge') + setTimeout(() => { + try { + this.updateTx(txMeta, `txStateManager: setting status to ${status}`) + this.emit(`${txMeta.id}:${status}`, txId) + this.emit(`tx:status-update`, txId, status) + if (['submitted', 'rejected', 'failed'].includes(status)) { + this.emit(`${txMeta.id}:finished`, txMeta) + } + this.emit('update:badge') + } catch (error) { + log.error(error) + } + }) } /** diff --git a/test/unit/tx-state-history-helper-test.js b/test/unit/tx-state-history-helper-test.js index 35e9ef188..5ad014dbb 100644 --- a/test/unit/tx-state-history-helper-test.js +++ b/test/unit/tx-state-history-helper-test.js @@ -1,26 +1,129 @@ const assert = require('assert') -const clone = require('clone') const txStateHistoryHelper = require('../../app/scripts/controllers/transactions/lib/tx-state-history-helper') +const testVault = require('../data/v17-long-history.json') -describe('deepCloneFromTxMeta', function () { - it('should clone deep', function () { - const input = { - foo: { - bar: { - bam: 'baz' +describe ('Transaction state history helper', function () { + + describe('#snapshotFromTxMeta', function () { + it('should clone deep', function () { + const input = { + foo: { + bar: { + bam: 'baz' + } } } - } - const output = txStateHistoryHelper.snapshotFromTxMeta(input) - assert('foo' in output, 'has a foo key') - assert('bar' in output.foo, 'has a bar key') - assert('bam' in output.foo.bar, 'has a bar key') - assert.equal(output.foo.bar.bam, 'baz', 'has a baz value') + const output = txStateHistoryHelper.snapshotFromTxMeta(input) + assert('foo' in output, 'has a foo key') + assert('bar' in output.foo, 'has a bar key') + assert('bam' in output.foo.bar, 'has a bar key') + assert.equal(output.foo.bar.bam, 'baz', 'has a baz value') + }) + + it('should remove the history key', function () { + const input = { foo: 'bar', history: 'remembered' } + const output = txStateHistoryHelper.snapshotFromTxMeta(input) + assert(typeof output.history, 'undefined', 'should remove history') + }) }) - it('should remove the history key', function () { - const input = { foo: 'bar', history: 'remembered' } - const output = txStateHistoryHelper.snapshotFromTxMeta(input) - assert(typeof output.history, 'undefined', 'should remove history') + describe('#migrateFromSnapshotsToDiffs', function () { + it('migrates history to diffs and can recover original values', function () { + testVault.data.TransactionController.transactions.forEach((tx, index) => { + const newHistory = txStateHistoryHelper.migrateFromSnapshotsToDiffs(tx.history) + newHistory.forEach((newEntry, index) => { + if (index === 0) { + assert.equal(Array.isArray(newEntry), false, 'initial history item IS NOT a json patch obj') + } else { + assert.equal(Array.isArray(newEntry), true, 'non-initial history entry IS a json patch obj') + } + const oldEntry = tx.history[index] + const historySubset = newHistory.slice(0, index + 1) + const reconstructedValue = txStateHistoryHelper.replayHistory(historySubset) + assert.deepEqual(oldEntry, reconstructedValue, 'was able to reconstruct old entry from diffs') + }) + }) + }) + }) + + describe('#replayHistory', function () { + it('replaying history does not mutate the original obj', function () { + const initialState = { test: true, message: 'hello', value: 1 } + const diff1 = [{ + "op": "replace", + "path": "/message", + "value": "haay", + }] + const diff2 = [{ + "op": "replace", + "path": "/value", + "value": 2, + }] + const history = [initialState, diff1, diff2] + + const beforeStateSnapshot = JSON.stringify(initialState) + const latestState = txStateHistoryHelper.replayHistory(history) + const afterStateSnapshot = JSON.stringify(initialState) + + assert.notEqual(initialState, latestState, 'initial state is not the same obj as the latest state') + assert.equal(beforeStateSnapshot, afterStateSnapshot, 'initial state is not modified during run') + }) + }) + + describe('#generateHistoryEntry', function () { + + function generateHistoryEntryTest(note) { + + const prevState = { + someValue: 'value 1', + foo: { + bar: { + bam: 'baz' + } + } + } + + const nextState = { + newPropRoot: 'new property - root', + someValue: 'value 2', + foo: { + newPropFirstLevel: 'new property - first level', + bar: { + bam: 'baz' + } + } + } + + const before = new Date().getTime() + const result = txStateHistoryHelper.generateHistoryEntry(prevState, nextState, note) + const after = new Date().getTime() + + assert.ok(Array.isArray(result)) + assert.equal(result.length, 3) + + const expectedEntry1 = { op: 'add', path: '/foo/newPropFirstLevel', value: 'new property - first level' } + assert.equal(result[0].op, expectedEntry1.op) + assert.equal(result[0].path, expectedEntry1.path) + assert.equal(result[0].value, expectedEntry1.value) + assert.equal(result[0].value, expectedEntry1.value) + if (note) + assert.equal(result[0].note, note) + + assert.ok(result[0].timestamp >= before && result[0].timestamp <= after) + + const expectedEntry2 = { op: 'replace', path: '/someValue', value: 'value 2' } + assert.deepEqual(result[1], expectedEntry2) + + const expectedEntry3 = { op: 'add', path: '/newPropRoot', value: 'new property - root' } + assert.deepEqual(result[2], expectedEntry3) + } + + it('should generate history entries', function () { + generateHistoryEntryTest() + }) + + it('should add note to first entry', function () { + generateHistoryEntryTest('custom note') + }) }) -}) +})
\ No newline at end of file diff --git a/test/unit/tx-state-history-helper.js b/test/unit/tx-state-history-helper.js deleted file mode 100644 index 35f7dac57..000000000 --- a/test/unit/tx-state-history-helper.js +++ /dev/null @@ -1,46 +0,0 @@ -const assert = require('assert') -const txStateHistoryHelper = require('../../app/scripts/controllers/transactions/lib/tx-state-history-helper') -const testVault = require('../data/v17-long-history.json') - - -describe('tx-state-history-helper', function () { - it('migrates history to diffs and can recover original values', function () { - testVault.data.TransactionController.transactions.forEach((tx, index) => { - const newHistory = txStateHistoryHelper.migrateFromSnapshotsToDiffs(tx.history) - newHistory.forEach((newEntry, index) => { - if (index === 0) { - assert.equal(Array.isArray(newEntry), false, 'initial history item IS NOT a json patch obj') - } else { - assert.equal(Array.isArray(newEntry), true, 'non-initial history entry IS a json patch obj') - } - const oldEntry = tx.history[index] - const historySubset = newHistory.slice(0, index + 1) - const reconstructedValue = txStateHistoryHelper.replayHistory(historySubset) - assert.deepEqual(oldEntry, reconstructedValue, 'was able to reconstruct old entry from diffs') - }) - }) - }) - - it('replaying history does not mutate the original obj', function () { - const initialState = { test: true, message: 'hello', value: 1 } - const diff1 = [{ - "op": "replace", - "path": "/message", - "value": "haay", - }] - const diff2 = [{ - "op": "replace", - "path": "/value", - "value": 2, - }] - const history = [initialState, diff1, diff2] - - const beforeStateSnapshot = JSON.stringify(initialState) - const latestState = txStateHistoryHelper.replayHistory(history) - const afterStateSnapshot = JSON.stringify(initialState) - - assert.notEqual(initialState, latestState, 'initial state is not the same obj as the latest state') - assert.equal(beforeStateSnapshot, afterStateSnapshot, 'initial state is not modified during run') - }) - -}) diff --git a/test/unit/tx-state-manager-test.js b/test/unit/tx-state-manager-test.js index e5fe68d0b..179542f90 100644 --- a/test/unit/tx-state-manager-test.js +++ b/test/unit/tx-state-manager-test.js @@ -176,14 +176,21 @@ describe('TransactionStateManager', function () { assert.deepEqual(updatedTx.history[0], txStateHistoryHelper.snapshotFromTxMeta(updatedTx), 'first history item is initial state') // modify value and updateTx updatedTx.txParams.gasPrice = desiredGasPrice + const before = new Date().getTime() txStateManager.updateTx(updatedTx) + const after = new Date().getTime() // check updated value const result = txStateManager.getTx('1') assert.equal(result.txParams.gasPrice, desiredGasPrice, 'gas price updated') // validate history was updated assert.equal(result.history.length, 2, 'two history items (initial + diff)') + assert.equal(result.history[1].length, 1, 'two history state items (initial + diff)') + const expectedEntry = { op: 'replace', path: '/txParams/gasPrice', value: desiredGasPrice } - assert.deepEqual(result.history[1], [expectedEntry], 'two history items (initial + diff)') + assert.deepEqual(result.history[1][0].op, expectedEntry.op, 'two history items (initial + diff) operation') + assert.deepEqual(result.history[1][0].path, expectedEntry.path, 'two history items (initial + diff) path') + assert.deepEqual(result.history[1][0].value, expectedEntry.value, 'two history items (initial + diff) value') + assert.ok(result.history[1][0].timestamp >= before && result.history[1][0].timestamp <= after) }) }) |