Reusable models for the Node server and browsers
I like the idea of Transfer Objects within application. In my applications I use Entities (simple TO but with some additional functions like data validation, type casting, etc). Because I planned to write modern one-page-apps I decided to have Entities on the front-end as well.
That is how the idea of Gleam was born. And now I am able to write Entity once and use it on the NodeJS side and on the browser side. Every entity is automatically serialized to JSON and deserialized on front-end to correct objects. Gleam is for now on the very early stage, it is more like "proof of concept". I still need to build some real projects based on it.
expect(Gleam).to.throw('Root');
expect(gleam).to.have.property('_root', root);
expect(Gleam).to.respondTo('entity');
expect(Gleam).to.respondTo('fromJson');
expect(Gleam).itself.to.respondTo('is');
expect(Gleam).itself.to.respondTo('buildSync');
function createNotExistingEntity() {
return gleam.entity('wrongSchema');
}
expect(createNotExistingEntity).to.throw(Error);
function createEntityWithWrongSchema() {
return gleam.entity('wrongSchema');
}
expect(createEntityWithWrongSchema).to.throw('Entity must be an object');
function createEntityWithFaultySchema() {
return gleam.entity('schemaWithProperties');
}
expect(createEntityWithFaultySchema).to.throw('Entity schema must not have any properties');
var entity = gleam.entity('user');
expect(entity).to.be.an('object');
expect(entity).to.have.keys('id', 'name', 'email');
expect(entity.id).to.be.a('function');
expect(entity.name).to.be.a('function');
expect(entity.email).to.be.a('function');
expect(Gleam.is(entity, 'user')).to.be.true;
var entity = gleam.entity('user/test');
expect(entity).to.be.an('object');
expect(entity).to.have.keys('id');
expect(entity.id).to.be.a('function');
expect(Gleam.is(entity, 'user/test')).to.be.true;
var entity = gleam.entity('user', userData);
expect(entity.id()).to.equal(userData.id);
expect(entity.name()).to.equal(userData.name);
expect(entity.email()).to.equal(userData.email);
function createEntityWithWrongData() {
return gleam.entity('user', 'not an object');
}
expect(createEntityWithWrongData).to.throw('Values must be an object');
var entity = gleam.entity('user', userData);
expect(entity.modified().id).to.be.false;
expect(entity.modified().name).to.be.false;
expect(entity.modified().email).to.be.false;
var entity = gleam.entity('user', userData);
expect(entity.initial().id).to.equal(userData.id);
expect(entity.initial().name).to.equal(userData.name);
expect(entity.initial().email).to.equal(userData.email);
var entity = gleam.fromJson(userJson);
expect(entity).to.be.an('object');
expect(Gleam.is(entity, 'user')).to.be.true;
expect(entity.id()).to.equal(1);
var list = gleam.fromJson(userListJson);
expect(list).to.be.an('array');
expect(list).to.have.length(2);
expect(Gleam.is(list[0], 'user')).to.be.true;
expect(list[0].id()).to.equal(1);
expect(Gleam.is(list[1], 'user')).to.be.true;
expect(list[1].id()).to.equal(2);
expect(Gleam.is(entity, 'user')).to.be.true;
expect(Gleam.is(entity, 'not/user')).to.be.false;
expect(Gleam.is('Not an object', 'user')).to.be.false;
expect(jsOut).to.be.a('string');
expect(spaceFix(jsOut)).to.be.equal(spaceFix(jsIn));
expect(function () {
return entity.set({id: 1});
}).to.not.throw(Error);
expect(function () {
return entity.set('Hello, world!');
}).to.throw('Values must be an object');
expect(function () {
return entity.set(['hello', 'world']);
}).to.throw('Values must be an object');
expect(function () {
return entity.set(function () {
});
}).to.throw('Values must be an object');
entity.set(userData);
expect(entity.id()).to.equal(userData.id);
expect(entity.name()).to.equal(userData.name);
expect(entity.email()).to.equal(userData.email);
expect(function () {
entity.set({email: 'wrong-email'});
}).to.throw('Value [wrong-email] is not valid for [user.email]');
var entity = gleam.entity('setterGetter', {email: 'nik@butenko.me'});
expect(entity.email()).to.equal('always@email.com');
var entity = gleam.entity('setterGetter', {password: 'test', password2: 'test2'});
expect(entity.password()).to.equal('test2');
var entity = gleam.entity('setterGetter', {id: 1});
expect(entity.id()).to.equal(43);
var entity = gleam.entity('user', userData);
expect(entity.get()).to.deep.equal({id: 1, name: "Nik", email: "nik@butenko.me"});
var entity = gleam.fromJson(userWithTestJson);
expect(entity.get()).to.deep.equal({id: 1, name: "Nik", email: "nik@butenko.me", test: {id: 2}});
var entity = gleam.fromJson(requireText('./fixtures/user-with-arrays.json'));
expect(entity.get()).to.deep.equal({id: 1, name: "Nik", email: "nik@butenko.me", tests: [
{id: 2},
{id: 3}
], messages: ["Message 1", "Message 2"]});
var entity = gleam.entity('setterGetter');
entity.name('Me');
expect(entity.name()).to.equal('Always');
var entity = gleam.entity('setterGetter');
entity.address('Address');
expect(entity.address()).to.equal('Always');
expect(entity.isValid('email', 'nik@butenko.me')).to.be.true;
expect(entity.isValid('email', 'wrong@email')).to.be.false;
expect(entity.getProperty('id')).to.equal(1);
expect(function () {
entity.getProperty('wrong');
}).to.throw('Accessing undefined property [user.wrong]');
var entity = gleam.fromJson(userWithTestJson);
expect(entity.getFlat()).to.deep.equal({id: 1, name: "Nik", email: "nik@butenko.me"});
var entity = gleam.fromJson(requireText('./fixtures/user-with-arrays.json'));
expect(entity.getFlat()).to.deep.equal({id: 1, name: "Nik", email: "nik@butenko.me", tests: [], messages: ["Message 1", "Message 2"]});
var entity = gleam.entity('user');
expect(entity.initial()).to.deep.equal({id: undefined, name: undefined, email: undefined});
var entity = gleam.entity('user', userData);
expect(entity.initial()).to.deep.equal({id: 1, name: "Nik", email: "nik@butenko.me"});
var entity = gleam.entity('user');
entity.set({id: 1});
expect(entity.initial().id).to.be.undefined;
var entity = gleam.entity('user');
expect(entity.modified()).to.deep.equal({id: false, name: false, email: false});
var entity = gleam.entity('user');
entity.set({id: 1});
expect(entity.modified().id).to.be.true;
expect(entity.modified().email).to.be.false;
expect(entity.is('user')).to.be.true;
expect(entity.is('not/user')).to.be.false;
var entity = gleam.fromJson(userJson);
expect(entity.toJSON()).to.deep.equal(userData);
var entity = gleam.fromJson(userWithTestJson);
expect(entity.toJSON()).to.deep.equal(userWithTestData);
var entity = gleam.fromJson(userJson);
expect(spaceFix(JSON.stringify(entity))).to.equal(spaceFix(userJson));
var entity = gleam.fromJson(userWithTestJson);
expect(spaceFix(JSON.stringify(entity))).to.equal(spaceFix(userWithTestJson));
var json = requireText('./fixtures/user-with-arrays.json'),
entity = gleam.fromJson(json);
expect(spaceFix(JSON.stringify(entity))).to.equal(spaceFix(json));
var entity = gleam.entity('user');
expect(entity.toString()).to.equal('[object Gleam:user]');
var entity = gleam.entity('user/test');
expect(['', entity].join('')).to.equal('[object Gleam:user/test]');