conditions
Version:
A javascript configuration engine
245 lines (232 loc) • 10.7 kB
JavaScript
describe('Change tracker', function () {
'use strict';
const tracker = require('../src/change-tracker.js');
var tracked;
beforeEach(function () {
tracked = tracker({});
});
describe('tracked', function () {
it('should be a function', function () {
expect(tracker.tracked).to.be.a('function');
});
it('should return true if the supplied value is a tracked object', function () {
expect(tracker.tracked(tracked)).to.equal(true);
});
it('should return false if the supplied value is not a tracked object', function () {
expect(tracker.tracked(123)).to.equal(false);
expect(tracker.tracked({})).to.equal(false);
expect(tracker.tracked(true)).to.equal(false);
});
});
describe('changes', function () {
var changes;
beforeEach(function () {
tracked.foo = 'a';
tracked.bar = 'b';
tracked.baz = 'c';
tracker.commit(tracked);
tracked.foo = 'x';
tracked.bar = 'y';
tracked.hello = 'world!';
delete tracked.baz;
changes = tracker.changes(tracked);
})
it('should return an object', function () {
var changes = tracker.changes(tracked);
expect(changes).to.be.an('object');
});
it('should have an object called inserts containing inserted keys and their values', function () {
expect(changes.inserts).to.be.an('object');
const keys = Object.keys(changes.inserts);
expect(keys.length).to.equal(1);
expect(keys[0]).to.equal('hello');
expect(changes.inserts.hello).to.equal('world!');
});
it('should have an object called deletes containing all deleted fields and their values when deleted', function () {
expect(changes.deletes).to.be.an('object');
const keys = Object.keys(changes.deletes);
expect(keys.length).to.equal(1);
expect(keys[0]).to.equal('baz');
expect(changes.deletes.baz).to.equal('c');
});
it('should have an object called updates with all the updated properties, their original value, and their current value', function () {
expect(changes.updates).to.be.an('object');
const keys = Object.keys(changes.updates);
expect(keys.length).to.equal(2);
expect(keys.includes('foo')).to.equal(true);
expect(keys.includes('bar')).to.equal(true);
expect(changes.updates.foo).to.be.an('object');
expect(changes.updates.foo.value).to.equal('x');
expect(changes.updates.foo.old).to.equal('a');
expect(changes.updates.bar).to.be.an('object');
expect(changes.updates.bar.value).to.equal('y');
expect(changes.updates.bar.old).to.equal('b');
});
it('should return empty objects for inserts, updates and deletes if the supplied value is not a tracked object', function () {
changes = tracker.changes({});
expect(changes).to.be.an('object');
expect(changes.inserts).to.be.an('object');
expect(changes.updates).to.be.an('object');
expect(changes.deletes).to.be.an('object');
expect(Object.keys(changes.inserts).length).to.equal(0);
expect(Object.keys(changes.updates).length).to.equal(0);
expect(Object.keys(changes.deletes).length).to.equal(0);
});
});
describe('commit', function () {
it('should be a function', function () {
expect(tracker.commit).to.be.a('function');
});
it('should return true if the supplied object is a tracked object', function () {
expect(tracker.commit(tracked)).to.equal(true);
});
it('should return false if the supplied object is not a tracked object', function () {
expect(tracker.commit({})).to.equal(false);
});
it('should commit all inserts to the tracked object', function () {
tracked.foo = 'bar';
var changes = tracker.changes(tracked);
expect(changes.inserts.foo).to.equal('bar');
tracker.commit(tracked);
changes = tracker.changes(tracked);
expect(Object.keys(changes.inserts).length).to.equal(0);
expect(tracked.foo).to.equal('bar');
});
it('should commit all updates to the tracked object', function () {
tracked.foo = 'bar';
tracker.commit(tracked);
var changes = tracker.changes(tracked);
expect(Object.keys(changes.updates).length).to.equal(0);
tracked.foo = 'baz';
changes = tracker.changes(tracked);
expect(changes.updates.foo).to.be.an('object');
expect(changes.updates.foo.value).to.equal('baz');
expect(changes.updates.foo.old).to.equal('bar');
tracker.commit(tracked);
changes = tracker.changes(tracked);
expect(Object.keys(changes.updates).length).to.equal(0);
});
it('should commit all deletes to the tracked object', function () {
tracked.foo = 'bar';
tracker.commit(tracked);
var changes = tracker.changes(tracked);
expect(Object.keys(changes.updates).length).to.equal(0);
delete tracked.foo;
changes = tracker.changes(tracked);
expect(changes.deletes).to.be.an('object');
expect(changes.deletes.foo).to.equal('bar');
tracker.commit(tracked);
changes = tracker.changes(tracked);
expect(Object.keys(changes.deletes).length).to.equal(0);
});
});
describe('reset', function () {
it('should be a function', function () {
expect(tracker.reset).to.be.a('function');
});
it('should return true if the supplied object is a tracked object', function () {
expect(tracker.reset(tracked)).to.equal(true);
});
it('should return false if the supplied object is not a tracked object', function () {
expect(tracker.reset({})).to.equal(false);
});
it('should handle circular references', function () {
tracked.circ = tracked;
tracker.commit(tracked);
expect(tracker.reset(tracked)).to.equal(true);
});
it('should revert at a descriptor level', function () {
// Note: We do this first set and define property
// for coverage reasons
var val = 'barbaz';
Object.defineProperty(tracked, 'foo', {
enumerable: true,
configurable: true,
get: function () { return val },
set: function (v) { val = v; }
});
tracker.commit(tracked);
expect(tracked.foo).to.equal('barbaz');
tracked.foo = 'bar';
expect(tracker.changes(tracked).updates.foo.value).to.equal('bar');
tracker.commit(tracked);
Object.defineProperty(tracked, 'foo', {
enumerable: true,
configurable: true,
writable: true,
value: 456
});
expect(tracked.foo).to.equal(456);
var desc = Object.getOwnPropertyDescriptor(tracked, 'foo');
expect(desc).to.be.an('object');
expect(desc.value).to.equal(456);
tracker.reset(tracked);
desc = Object.getOwnPropertyDescriptor(tracked, 'foo');
expect(desc).to.be.an('object');
expect(desc.value).to.equal(undefined);
expect(desc.get).to.be.a('function');
expect(tracked.foo).to.equal('bar');
});
it('should revert all additions to the tracked object', function () {
tracked.foo = 'bar';
var changes = tracker.changes(tracked);
expect(changes.inserts.foo).to.equal('bar');
tracker.reset(tracked);
changes = tracker.changes(tracked);
expect(Object.keys(changes.inserts).length).to.equal(0);
expect(tracked.foo).to.equal(undefined);
});
it('should revert all udpates to the tracked object', function () {
tracked.foo = 'bar';
tracker.commit(tracked);
var changes = tracker.changes(tracked);
expect(Object.keys(changes.updates).length).to.equal(0);
tracked.foo = 'baz';
changes = tracker.changes(tracked);
expect(changes.updates.foo).to.be.an('object');
expect(changes.updates.foo.value).to.equal('baz');
expect(changes.updates.foo.old).to.equal('bar');
tracker.reset(tracked);
changes = tracker.changes(tracked);
expect(Object.keys(changes.updates).length).to.equal(0);
});
it('should revert all deletions from the tracked object', function () {
tracked.foo = 'bar';
tracker.commit(tracked);
var changes = tracker.changes(tracked);
expect(Object.keys(changes.updates).length).to.equal(0);
delete tracked.foo;
delete tracked.nonexistant; // For coverage
changes = tracker.changes(tracked);
expect(changes.deletes).to.be.an('object');
expect(changes.deletes.foo).to.equal('bar');
tracker.reset(tracked);
changes = tracker.changes(tracked);
expect(Object.keys(changes.deletes).length).to.equal(0);
expect(tracked.foo).to.equal('bar');
});
it('should call options.customRevert if it is supplied', function () {
var cr = chai.spy();
tracked = tracker({}, {
customRevert: cr
});
tracked.foo = 'bar';
tracker.commit(tracked);
tracked.foo = 'baz';
tracker.reset(tracked);
expect(cr).to.have.been.called.once.with(tracked, 'foo');
});
it('should not do normal reversion if options.customRevert returns true', function () {
var cr = chai.spy(() => true);
tracked = tracker({}, {
customRevert: cr
});
tracked.foo = 'bar';
tracker.commit(tracked);
tracked.foo = 'baz';
tracker.reset(tracked);
expect(cr).to.have.been.called.once.with(tracked, 'foo');
expect(tracked.foo).to.equal('baz');
});
});
});