aboutsummaryrefslogtreecommitdiffstats
path: root/test/unit/tx-state-history-helper-test.js
blob: 5ad014dbb01a6ee0e63a9329cc9ea8c17b8974fe (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
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 ('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')
    })

    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')
    })    
  })
})