mirror of https://github.com/keeweb/keeweb.git
model tests
This commit is contained in:
parent
4d1cbe7f62
commit
0f5b03ce64
|
@ -5,18 +5,18 @@ const SymbolEvents = Symbol('events');
|
||||||
const SymbolDefaults = Symbol('defaults');
|
const SymbolDefaults = Symbol('defaults');
|
||||||
const SymbolExtensions = Symbol('extensions');
|
const SymbolExtensions = Symbol('extensions');
|
||||||
|
|
||||||
function emitPropChange(target, property, value, prevValue, receiver) {
|
function emitPropChange(target, property, value, prevValue) {
|
||||||
const emitter = target[SymbolEvents];
|
const emitter = target[SymbolEvents];
|
||||||
if (!emitter.paused) {
|
if (!emitter.paused) {
|
||||||
emitter.emit('change:' + property, receiver, value, prevValue);
|
emitter.emit('change:' + property, target, value, prevValue);
|
||||||
if (!emitter.noChange) {
|
if (!emitter.noChange) {
|
||||||
emitter.emit('change', receiver, { [property]: value });
|
emitter.emit('change', target, { [property]: value });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const ProxyDef = {
|
const ProxyDef = {
|
||||||
deleteProperty(target, property, receiver) {
|
deleteProperty(target, property) {
|
||||||
if (Object.prototype.hasOwnProperty.call(target, property)) {
|
if (Object.prototype.hasOwnProperty.call(target, property)) {
|
||||||
const defaults = target[SymbolDefaults];
|
const defaults = target[SymbolDefaults];
|
||||||
const value = defaults[property];
|
const value = defaults[property];
|
||||||
|
@ -27,7 +27,7 @@ const ProxyDef = {
|
||||||
} else {
|
} else {
|
||||||
delete target[property];
|
delete target[property];
|
||||||
}
|
}
|
||||||
emitPropChange(target, property, value, prevValue, receiver);
|
emitPropChange(target, property, value, prevValue);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -38,7 +38,7 @@ const ProxyDef = {
|
||||||
if (target[property] !== value) {
|
if (target[property] !== value) {
|
||||||
const prevValue = target[property];
|
const prevValue = target[property];
|
||||||
target[property] = value;
|
target[property] = value;
|
||||||
emitPropChange(target, property, value, prevValue, receiver);
|
emitPropChange(target, property, value, prevValue);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
|
@ -61,6 +61,7 @@ class Model {
|
||||||
};
|
};
|
||||||
for (const [propName, defaultValue] of Object.entries(this[SymbolDefaults])) {
|
for (const [propName, defaultValue] of Object.entries(this[SymbolDefaults])) {
|
||||||
properties[propName] = {
|
properties[propName] = {
|
||||||
|
configurable: true,
|
||||||
enumerable: true,
|
enumerable: true,
|
||||||
writable: true,
|
writable: true,
|
||||||
value: defaultValue
|
value: defaultValue
|
||||||
|
|
|
@ -2,14 +2,143 @@ import { expect } from 'chai';
|
||||||
import { Model } from 'framework/model';
|
import { Model } from 'framework/model';
|
||||||
|
|
||||||
describe('Model', () => {
|
describe('Model', () => {
|
||||||
|
class TestModel extends Model {}
|
||||||
|
TestModel.defineModelProperties({ foo: 'bar', baz: 0 });
|
||||||
|
|
||||||
|
class TestExtensibleModel extends Model {}
|
||||||
|
TestExtensibleModel.defineModelProperties({ foo: 'bar' }, { extensions: true });
|
||||||
|
|
||||||
it('should create a model with default properties', () => {
|
it('should create a model with default properties', () => {
|
||||||
class MyModel extends Model {}
|
const model = new TestModel();
|
||||||
MyModel.defineModelProperties({ prop: 'default' });
|
|
||||||
|
|
||||||
const myModel = new MyModel();
|
expect(model).to.be.ok;
|
||||||
|
expect(model.foo).to.eql('bar');
|
||||||
|
expect(model.baz).to.eql(0);
|
||||||
|
expect(model.another).to.be.undefined;
|
||||||
|
});
|
||||||
|
|
||||||
expect(myModel).to.be.ok;
|
it('should serialize a model to JSON', () => {
|
||||||
expect(myModel.prop).to.eql('default');
|
const model = new TestModel();
|
||||||
expect(myModel.another).to.be.undefined;
|
|
||||||
|
model.baz = 1;
|
||||||
|
|
||||||
|
expect(JSON.stringify(model)).to.eql('{"foo":"bar","baz":1}');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should throw an error for unknown properties', () => {
|
||||||
|
const model = new TestModel();
|
||||||
|
expect(() => {
|
||||||
|
model.xxx = 'value';
|
||||||
|
}).to.throw();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should set properties', () => {
|
||||||
|
const model = new TestModel();
|
||||||
|
|
||||||
|
const calls = [];
|
||||||
|
const callsProp = [];
|
||||||
|
const callsAnother = [];
|
||||||
|
|
||||||
|
model.on('change', (...args) => calls.push(args));
|
||||||
|
model.on('change:foo', (...args) => callsProp.push(args));
|
||||||
|
model.on('change:baz', (...args) => callsAnother.push(args));
|
||||||
|
|
||||||
|
model.foo = 123;
|
||||||
|
|
||||||
|
expect(model.foo).to.eql(123);
|
||||||
|
expect(calls).to.eql([[model, { foo: 123 }]]);
|
||||||
|
expect(callsProp).to.eql([[model, 123, 'bar']]);
|
||||||
|
expect(callsAnother).to.eql([]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should set properties using "set" method', () => {
|
||||||
|
const model = new TestModel();
|
||||||
|
|
||||||
|
const calls = [];
|
||||||
|
const callsProp = [];
|
||||||
|
const callsAnother = [];
|
||||||
|
|
||||||
|
model.on('change', (...args) => calls.push(args));
|
||||||
|
model.on('change:foo', (...args) => callsProp.push(args));
|
||||||
|
model.on('change:baz', (...args) => callsAnother.push(args));
|
||||||
|
|
||||||
|
model.set({ foo: 123, baz: 456 });
|
||||||
|
|
||||||
|
expect(model.foo).to.eql(123);
|
||||||
|
expect(model.baz).to.eql(456);
|
||||||
|
expect(calls).to.eql([[model, { foo: 123, baz: 456 }]]);
|
||||||
|
expect(callsProp).to.eql([[model, 123, 'bar']]);
|
||||||
|
expect(callsAnother).to.eql([[model, 456, 0]]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should silently set properties using "set" method', () => {
|
||||||
|
const model = new TestModel();
|
||||||
|
|
||||||
|
const calls = [];
|
||||||
|
const callsProp = [];
|
||||||
|
const callsAnother = [];
|
||||||
|
|
||||||
|
model.on('change', (...args) => calls.push(args));
|
||||||
|
model.on('change:foo', (...args) => callsProp.push(args));
|
||||||
|
model.on('change:baz', (...args) => callsAnother.push(args));
|
||||||
|
|
||||||
|
model.set({ foo: 123, baz: 456 }, { silent: true });
|
||||||
|
|
||||||
|
expect(model.foo).to.eql(123);
|
||||||
|
expect(model.baz).to.eql(456);
|
||||||
|
expect(calls).to.eql([]);
|
||||||
|
expect(callsProp).to.eql([]);
|
||||||
|
expect(callsAnother).to.eql([]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should delete properties', () => {
|
||||||
|
const model = new TestModel();
|
||||||
|
|
||||||
|
model.foo = 123;
|
||||||
|
|
||||||
|
const calls = [];
|
||||||
|
const callsProp = [];
|
||||||
|
const callsAnother = [];
|
||||||
|
|
||||||
|
model.on('change', (...args) => calls.push(args));
|
||||||
|
model.on('change:foo', (...args) => callsProp.push(args));
|
||||||
|
model.on('change:baz', (...args) => callsAnother.push(args));
|
||||||
|
|
||||||
|
delete model.foo;
|
||||||
|
|
||||||
|
expect(model.foo).to.eql('bar');
|
||||||
|
expect(calls).to.eql([[model, { foo: 'bar' }]]);
|
||||||
|
expect(callsProp).to.eql([[model, 'bar', 123]]);
|
||||||
|
expect(callsAnother).to.eql([]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should allow extensions for extensible models', () => {
|
||||||
|
const model = new TestExtensibleModel();
|
||||||
|
|
||||||
|
expect(model.foo).to.eql('bar');
|
||||||
|
|
||||||
|
const calls = [];
|
||||||
|
model.on('change', (...args) => calls.push(args));
|
||||||
|
|
||||||
|
model.foo = 123;
|
||||||
|
model.xxx = 456;
|
||||||
|
|
||||||
|
expect(model.foo).to.eql(123);
|
||||||
|
expect(model.xxx).to.eql(456);
|
||||||
|
|
||||||
|
expect(model).to.have.property('xxx');
|
||||||
|
expect(JSON.stringify(model)).to.eql('{"foo":123,"xxx":456}');
|
||||||
|
|
||||||
|
delete model.xxx;
|
||||||
|
|
||||||
|
expect(model).to.not.have.property('xxx');
|
||||||
|
expect(model.xxx).to.be.undefined;
|
||||||
|
expect(JSON.stringify(model)).to.eql('{"foo":123}');
|
||||||
|
|
||||||
|
expect(calls).to.eql([
|
||||||
|
[model, { foo: 123 }],
|
||||||
|
[model, { xxx: 456 }],
|
||||||
|
[model, { xxx: undefined }]
|
||||||
|
]);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in New Issue