document.js
Version:
General purpose ODM supporting memory and mongo database adapters
466 lines (358 loc) • 12.7 kB
JavaScript
require('./helpers/spec_helper');
describe('Relation', function() {
var Relation = require('..')().Relation;
var Channel, relation;
beforeEach(function() {
Channel = require('../examples/models/channel');
relation = new Relation(Channel);
});
it('should have the model class', function() {
expect(relation.modelClass).toBe(Channel);
});
it('should not be loaded', function() {
expect(relation.loaded).toBe(false);
});
it('should not have size or items', function() {
expect(relation.items).toBeNull();
expect(relation.size).toBeNull();
});
it('should have the query', function() {
expect(relation.query()).toEqual({});
});
describe('#count', function() {
var count, callback;
beforeEach(function() {
callback = null;
spyOn(Channel.adapter(), 'count').and.callFake(function(c) {
callback = c;
});
count = relation.count();
spyOn(count, 'kept');
});
it('should return a count', function() {
expect(count instanceof Document.Count).toBe(true);
});
it('should have the relation', function() {
expect(count.relation).toBe(relation);
});
it('should not be loaded', function() {
expect(relation.loaded).toBe(false);
});
it('should call the adapter count', function() {
relation.count();
expect(Channel.adapter().count).toHaveBeenCalled();
});
describe('when the adapter succeeds', function() {
beforeEach(function() {
callback(26);
});
it('should be loaded', function() {
expect(relation.loaded).toBe(true);
});
it('should have have the count', function() {
expect(count.kept).toHaveBeenCalledWith(26);
});
});
describe('when the adapter errors', function() {
beforeEach(function() {
callback(null);
});
it('should be loaded', function() {
expect(relation.loaded).toBe(true);
});
it('should have have the count', function() {
expect(count.kept).toHaveBeenCalledWith(null);
});
});
});
describe('#find', function() {
var model, object, find, findOptions, callback;
beforeEach(function() {
model = object = findOptions = callback = null;
});
describe('for a query', function() {
beforeEach(function() {
relation = new Relation(Channel);
spyOn(Channel.adapter(), 'where').and.callFake(function(b,c) {
findOptions = b; callback = c;
});
object = relation.find({buffered: 5, foo: 'bar'});
});
it('should return a relation', function() {
expect(object instanceof Relation).toBe(true);
});
it('should not be loaded', function() {
expect(relation.loaded).toBe(false);
});
it('should call the adapter find with the translated options' , function() {
expect(findOptions).toEqual({bu: 5, foo: 'bar'});
});
describe('when the adapter succeeds', function() {
beforeEach(function() {
callback([{_id: '445', name: 'Channel 445'}, {_id: '556', name: 'Channel 556'}]);
});
it('should be loaded', function() {
expect(relation.loaded).toBe(true);
});
it('should have the models', function() {
var models = relation.items;
expect(models.length).toBe(2);
expect(models[0].id).toBe('445');
expect(models[0].get('name')).toBe('Channel 445');
expect(models[1].id).toBe('556');
expect(models[1].get('name')).toBe('Channel 556');
});
it('should have the model status', function() {
var models = relation.items;
expect(models[0].loaded).toBe(true);
expect(models[0].persisted).toBe(true);
expect(models[1].loaded).toBe(true);
expect(models[1].persisted).toBe(true);
});
it('should not have the size', function() {
expect(relation.size).toBeNull();
});
});
describe('when the adapter fails', function() {
beforeEach(function() {
callback(null);
});
it('should be loaded', function() {
expect(relation.loaded).toBe(true);
});
it('should not have the models', function() {
expect(relation.items).toBeNull();
});
it('should not have the number of records', function() {
expect(relation.size).toBeNull();
});
});
});
describe('with a model', function() {
beforeEach(function() {
model = new Channel({_id: '5'});
relation = new Relation(Channel, model);
spyOn(Channel.adapter(), 'where').and.callFake(function(b,c) {
findOptions = b; callback = c;
});
spyOn(model, 'kept');
find = relation.find();
});
it('should return the model', function() {
expect(find instanceof Channel).toBe(true);
expect(find).toBe(model);
});
it('should not be loaded', function() {
expect(relation.loaded).toBe(false);
});
it('should call the adapter find with the model id' , function() {
expect(findOptions).toEqual({_id: '5'});
});
describe('when the adapter succeeds', function() {
beforeEach(function() {
callback([{_id: 5, name: 'From adapter'}]);
});
it('should be loaded', function() {
expect(relation.loaded).toBe(true);
});
it('should return the result', function() {
expect(model.kept).toHaveBeenCalledWith({_id: 5, name: 'From adapter'});
});
});
describe('when the adapter errors', function() {
beforeEach(function() {
callback(null);
});
it('should be loaded', function() {
expect(relation.loaded).toBe(true);
});
it('should return the result', function() {
expect(model.kept).toHaveBeenCalledWith(null);
});
});
});
});
describe('#asJSON', function() {
it('should be null', function() {
expect(relation.asJSON()).toBeNull();
});
describe('when there are items', function() {
beforeEach(function() {
relation.items = [new Channel({id: '2'}), new Channel({id: '4', name: 'Four'})];
});
it('should be the items', function() {
var json = relation.asJSON();
expect(json.length).toBe(2);
expect(json[0].id).toBe('2');
expect(json[1].id).toBe('4');
expect(json[1].name).toBe('Four');
})
});
describe('when there is a size', function() {
beforeEach(function() {
relation.size = 5;
});
it('should be the size', function() {
expect(relation.asJSON()).toBe(5);
});
});
});
describe('#create', function() {
var model, object, adapterOptions, adapterCallback;
describe('with a model', function() {
beforeEach(function() {
model = new Channel({id: 556});
spyOn(model, 'kept');
relation = new Relation(Channel, model);
adapterOptions = adapterCallback = null;
spyOn(Channel.adapter(), 'create').and.callFake(function(b,c) {
adapterOptions = b; adapterCallback = c;
});
object = relation.create({_id: 556, name: 'Name value'});
});
it('should return the model', function() {
expect(object instanceof Channel).toBe(true);
expect(object).toBe(model);
});
it('should send the create to the adapter with the translated values', function() {
expect(Channel.adapter().create).toHaveBeenCalled();
expect(adapterOptions._id).toBe(556);
expect(adapterOptions.n).toBe('Name value');
expectToBeNow(adapterOptions.cT);
expectToBeNow(adapterOptions.uT);
expect(Object.keys(adapterOptions).length).toBe(4);
});
describe('when the adapter succeeds', function() {
beforeEach(function() {
adapterCallback(true);
});
it('should be loaded', function() {
expect(relation.loaded).toBe(true);
});
it('should keep the promise', function() {
expect(model.kept).toHaveBeenCalledWith(true);
});
});
describe('when the adapter errors', function() {
beforeEach(function() {
adapterCallback(null);
});
it('should be loaded', function() {
expect(relation.loaded).toBe(true);
});
it('should keep the promise', function() {
expect(model.kept).toHaveBeenCalledWith(null);
});
});
});
});
describe('#update', function() {
var model, object, adapterFinder, adapterOptions, adapterCallback;
describe('for a query', function() {
var success, error;
beforeEach(function() {
success = error = false;
adapterFinder = adapterOptions = adapterCallback = null;
spyOn(Channel.adapter(), 'update').and.callFake(function(a,b,c) {
adapterFinder = a; adapterOptions = b; adapterCallback = c;
});
relation.loaded = true;
object = relation.update({name: 'Name value'});
object.then(function(s) {
success = s;
}, function() {
error = true;
});
});
it('should not have the model', function() {
expect(relation.model).toBeUndefined();
});
it('should return the relation', function() {
expect(object instanceof Relation).toBe(true);
expect(object).toBe(relation);
});
it('should not be loaded', function() {
expect(relation.loaded).toBe(false);
});
it('should update all records', function() {
expect(Channel.adapter().update).toHaveBeenCalled();
expect(adapterFinder).toEqual({});
expect(adapterOptions.n).toBe('Name value');
expectToBeNow(adapterOptions.uT);
expect(Object.keys(adapterOptions).length).toBe(2);
});
describe('when the adapter succeeds', function() {
beforeEach(function() {
adapterCallback(true);
});
it('should be loaded', function() {
expect(relation.loaded).toBe(true);
});
it('should make the success callback', function() {
expect(success).toBe(true);
expect(error).toBe(false);
});
});
describe('when the adapter errors', function() {
beforeEach(function() {
adapterCallback(null);
});
it('should be loaded', function() {
expect(relation.loaded).toBe(true);
});
it('should make the error callback', function() {
expect(success).toBe(false);
expect(error).toBe(true);
});
});
});
describe('with a model', function() {
beforeEach(function() {
model = new Channel({id: '556'});
spyOn(model, 'kept');
relation = new Relation(Channel, model);
adapterFinder = adapterOptions = adapterCallback = null;
spyOn(Channel.adapter(), 'update').and.callFake(function(a,b,c) {
adapterFinder = a; adapterOptions = b; adapterCallback = c;
});
object = relation.update({name: 'Name value'});
});
it('should not have the query', function() {
expect(relation.query()).toBeNull();
});
it('should return the model', function() {
expect(object instanceof Channel).toBe(true);
expect(object).toBe(model);
});
it('should send the update to the adapter', function() {
expect(Channel.adapter().update).toHaveBeenCalled();
expect(adapterFinder).toEqual({_id: '556'});
expect(adapterOptions.n).toEqual('Name value');
expectToBeNow(adapterOptions.uT);
expect(Object.keys(adapterOptions).length).toBe(2);
});
describe('when the adapter succeeds', function() {
beforeEach(function() {
adapterCallback(true);
});
it('should be loaded', function() {
expect(relation.loaded).toBe(true);
});
it('should keep the promise', function() {
expect(model.kept).toHaveBeenCalledWith(true);
});
});
describe('when the adapter errors', function() {
beforeEach(function() {
adapterCallback(null);
});
it('should be loaded', function() {
expect(relation.loaded).toBe(true);
});
it('should keep the promise', function() {
expect(model.kept).toHaveBeenCalledWith(null);
});
});
});
});
});