extjs-gpl
Version:
GPL licensed version of Sencha Ext JS
1,203 lines (1,015 loc) • 215 kB
JavaScript
describe("Ext.data.Session", function() {
function completeRequest(data, requestId) {
Ext.Ajax.mockComplete({
status: 200,
responseText: Ext.encode(data)
}, requestId);
}
var session;
function idSort(a, b) {
if (Ext.isObject(a)) {
a = a.id;
b = b.id;
}
return a - b;
}
var adminGroup, peonGroup;
var rufusGroups, billGroups, tedGroups;
var adminUsers, peonUsers;
var userRufus, userBill, userTed;
function getAndComplete(type, id, theSession, data) {
theSession = theSession || session;
data = data || {};
var rec = theSession.getRecord(type, id);
data.id = data.id || id;
completeRequest(data);
return rec;
}
beforeEach(function() {
MockAjaxManager.addMethods();
adminGroup = {
id: 42,
name: 'Admins'
};
peonGroup = {
id: 427,
name: 'Peons'
};
userRufus = {
id: 10,
name: 'Rufus'
};
userBill = {
id: 20,
name: 'Bill'
};
userTed = {
id: 30,
name: 'Ted'
};
rufusGroups = [ adminGroup, peonGroup ];
billGroups = [ peonGroup ];
tedGroups = [ peonGroup ];
adminUsers = [ userRufus ];
peonUsers = [ userBill, userTed, userRufus ];
});
afterEach(function() {
MockAjaxManager.removeMethods();
session = Ext.destroy(session);
});
describe("record access", function() {
var User, parent, rec;
beforeEach(function() {
Ext.data.Model.schema.setNamespace('spec');
User = Ext.define('spec.User', {
extend: 'Ext.data.Model',
fields: ['name', {
name: 'addressId',
reference: 'Address',
unique: true
}],
manyToMany: 'Group'
});
parent = new Ext.data.Session();
session = new Ext.data.Session();
});
afterEach(function() {
parent.destroy();
User = rec = parent = null;
Ext.undefine('spec.User');
Ext.data.Model.schema.clear(true);
});
describe("adopt", function() {
it("should cache the record into the session", function() {
rec = new User({
id: 1
});
session.adopt(rec);
expect(session.peekRecord('User', 1)).toBe(rec);
});
it("should put the session on the record", function() {
rec = new User({
id: 1
});
session.adopt(rec);
expect(rec.session).toBe(session);
});
it("should not throw an error if a record already in the session is adopted", function() {
rec = getAndComplete('User', 1);
expect(function() {
session.adopt(rec);
}).not.toThrow();
});
describe("invalid conditions", function() {
it("should not allow a record attached to another session", function() {
var other = new Ext.data.Session(),
rec = getAndComplete('User', 1, other);
expect(function() {
session.adopt(rec);
}).toThrow();
other.destroy();
});
it("should raise an error if add a model the schema does not know about", function() {
var customSchema = new Ext.data.schema.Schema();
Ext.define('spec.CustomModel', {
extend: 'Ext.data.Model',
schema: customSchema
});
rec = new spec.CustomModel({
id: 1
});
expect(function() {
session.adopt(rec);
}).toThrow();
});
it("should raise an error if adding an existing record", function() {
rec = getAndComplete('User', 1);
expect(function() {
session.adopt(new User({
id: 1
}));
}).toThrow();
});
});
describe("associations", function() {
describe("many to one", function() {
var user;
beforeEach(function() {
Ext.define('spec.Post', {
extend: 'Ext.data.Model',
fields: ['content', {
name: 'userId',
reference: 'User'
}]
});
});
afterEach(function() {
Ext.undefine('spec.Post');
user = null;
});
function makeUser(id) {
user = new User({
id: id
});
}
describe("the many", function() {
it("should not attempt to load the owner", function() {
var post = new spec.Post({
id: 101,
userId: 1
});
var spy = spyOn(User.getProxy(), 'read');
session.adopt(post);
expect(spy).not.toHaveBeenCalled();
});
it("should also adopt the owner", function() {
var post = new spec.Post({
id: 101,
userId: 1
});
makeUser(1);
post.setUser(user);
session.adopt(post);
expect(user.session).toBe(session);
});
});
describe("the one", function() {
it("should not load the store", function() {
makeUser(1);
user.posts();
var spy = spyOn(User.getProxy(), 'read');
session.adopt(user);
expect(spy).not.toHaveBeenCalled();
});
it("should set the session onto the store", function() {
makeUser(1);
var posts = user.posts();
session.adopt(user);
expect(posts.getSession()).toBe(session);
});
it("should adopt existing children", function() {
makeUser(1);
var posts = user.posts();
posts.add({id: 101}, {id: 102}, {id: 103});
session.adopt(user);
expect(posts.getAt(0).session).toBe(session);
expect(posts.getAt(1).session).toBe(session);
expect(posts.getAt(2).session).toBe(session);
});
it("should adopt any newly loaded items after adopting", function() {
makeUser(1);
var posts = user.posts();
session.adopt(user);
posts.load();
completeRequest([{id: 101, userId: 1}, {id: 102, userId: 1}, {id: 103, userId: 1}]);
expect(posts.getAt(0).session).toBe(session);
expect(posts.getAt(1).session).toBe(session);
expect(posts.getAt(2).session).toBe(session);
});
});
});
describe("one to one", function() {
beforeEach(function() {
Ext.define('spec.Address', {
extend: 'Ext.data.Model',
fields: ['city']
});
});
afterEach(function() {
Ext.undefine('spec.Address');
});
describe("the key holder", function() {
it("should not attempt to load the non key holder", function() {
var user = new User({
id: 1,
addressId: 101
});
var spy = spyOn(spec.Address.getProxy(), 'read');
session.adopt(user);
expect(spy).not.toHaveBeenCalled();
});
it("should adopt the non key holder", function() {
var address = new spec.Address({
id: 101
});
var user = new User({
id: 1
});
user.setAddress(address);
session.adopt(user);
expect(address.session).toBe(session);
});
});
describe("the non key holder", function() {
it("should not attempt to load the key holder", function() {
var address = new spec.Address({
id: 101
});
var spy = spyOn(User.getProxy(), 'read');
session.adopt(address);
expect(spy).not.toHaveBeenCalled();
});
it("should also adopt the key holder", function() {
var address = new spec.Address({
id: 101
});
var user = new User({
id: 1
});
address.setUser(user);
session.adopt(address);
expect(user.session).toBe(session);
});
});
});
describe("many to many", function() {
var Group;
beforeEach(function() {
Group = Ext.define('spec.Group', {
extend: 'Ext.data.Model',
fields: ['name']
});
});
afterEach(function() {
Ext.undefine('spec.Group');
Group = null;
});
describe("the left", function() {
it("should not load the store", function() {
var group = new Group({id: 1});
group.users();
var spy = spyOn(Group.getProxy(), 'read');
session.adopt(group);
expect(spy).not.toHaveBeenCalled();
});
it("should set the session onto the store", function() {
var group = new Group({id: 1}),
users = group.users();
session.adopt(group);
expect(users.getSession()).toBe(session);
});
it("should adopt existing children", function() {
var group = new Group({id: 1}),
users = group.users();
users.add({id: 101}, {id: 102}, {id: 103});
session.adopt(group);
expect(users.getAt(0).session).toBe(session);
expect(users.getAt(1).session).toBe(session);
expect(users.getAt(2).session).toBe(session);
});
it("should adopt any newly loaded items after adopting", function() {
var group = new Group({id: 1}),
users = group.users();
session.adopt(group);
users.load();
completeRequest([{id: 101}, {id: 102}, {id: 103}]);
expect(users.getAt(0).session).toBe(session);
expect(users.getAt(1).session).toBe(session);
expect(users.getAt(2).session).toBe(session);
});
});
describe("the right", function() {
it("should not load the store", function() {
var user = new User({id: 1});
user.groups();
var spy = spyOn(Group.getProxy(), 'read');
session.adopt(user);
expect(spy).not.toHaveBeenCalled();
});
it("should set the session onto the store", function() {
var user = new User({id: 1}),
groups = user.groups();
session.adopt(user);
expect(groups.getSession()).toBe(session);
});
it("should adopt existing children", function() {
var user = new User({id: 1}),
groups = user.groups();
groups.add({id: 101}, {id: 102}, {id: 103});
session.adopt(user);
expect(groups.getAt(0).session).toBe(session);
expect(groups.getAt(1).session).toBe(session);
expect(groups.getAt(2).session).toBe(session);
});
it("should adopt any newly loaded items after adopting", function() {
var user = new User({id: 1}),
groups = user.groups();
session.adopt(user);
groups.load();
completeRequest([{id: 101}, {id: 102}, {id: 103}]);
expect(groups.getAt(0).session).toBe(session);
expect(groups.getAt(1).session).toBe(session);
expect(groups.getAt(2).session).toBe(session);
});
});
});
describe("nested", function() {
beforeEach(function() {
Ext.define('spec.Order', {
extend: 'Ext.data.Model',
fields: [{
name: 'userId',
reference: 'User'
}, {
name: 'addressId',
reference: 'Address',
unique: true
}]
});
Ext.define('spec.OrderItem', {
extend: 'Ext.data.Model',
fields: [{
name: 'orderId',
reference: 'Order'
}]
});
Ext.define('spec.Address', {
extend: 'Ext.data.Model',
fields: ['city']
});
});
afterEach(function() {
Ext.undefine('spec.Address');
Ext.undefine('spec.OrderItem');
Ext.undefine('spec.Order');
});
it("should adopt data deeply", function() {
var user = User.load(1);
completeRequest({
id: 1,
orders: [{
id: 101,
userId: 1,
address: {
id: 201
},
orderItems: [{
id: 301,
orderId: 101
}, {
id: 302,
orderId: 101
}]
}, {
id: 102,
userId: 1,
address: {
id: 202
},
orderItems: [{
id: 303,
orderId: 102
}, {
id: 304,
orderId: 102
}]
}]
});
session.adopt(user);
var order = user.orders().getAt(0);
expect(order.session).toBe(session);
expect(order.getAddress().session).toBe(session);
expect(order.orderItems().getAt(0).session).toBe(session);
expect(order.orderItems().getAt(1).session).toBe(session);
order = user.orders().getAt(1);
expect(order.session).toBe(session);
expect(order.getAddress().session).toBe(session);
expect(order.orderItems().getAt(0).session).toBe(session);
expect(order.orderItems().getAt(1).session).toBe(session);
});
});
});
});
describe("createRecord", function() {
it("should accept the entity name", function() {
rec = session.createRecord('User', {
name: 'Foo'
});
expect(rec.$className).toBe('spec.User');
expect(rec.get('name')).toBe('Foo');
});
it("should accept the entity class", function() {
rec = session.createRecord(spec.User, {
name: 'Foo'
});
expect(rec.$className).toBe('spec.User');
expect(rec.get('name')).toBe('Foo');
});
it("should throw an exception with an unrecognized model name", function() {
expect(function() {
session.createRecord('Luser', {});
}).toThrow();
});
it("should throw an exception creating an anonymous model", function() {
var Model = Ext.define(null, {
extend: 'Ext.data.Model',
fields: ['name']
});
expect(function() {
session.createRecord(Model, {});
}).toThrow();
});
it("should cache the record in the session", function() {
rec = session.createRecord('User', {
});
expect(session.getRecord('User', rec.getId())).toBe(rec);
});
it("should set the session on the instance", function() {
rec = session.createRecord('User', {
});
expect(rec.session).toBe(session);
});
it("should throw an exception if the record exists in the session", function() {
getAndComplete('User', 1);
expect(function() {
rec = session.createRecord('User', {
id: 1
}).toThrow();
});
});
it("should be able to create a phantom with no data", function() {
var rec;
expect(function() {
rec = session.createRecord('User');
}).not.toThrow();
expect(rec.phantom).toBe(true);
});
it("should become dirty", function() {
rec = session.createRecord('User', {
name: 'Foo'
});
expect(session.isDirty()).toBe(true);
});
describe("with a parent", function() {
beforeEach(function() {
session.setParent(parent);
});
it("should not create the record in the parent session", function() {
getAndComplete('User', 1);
expect(parent.peekRecord('User', 1)).toBeNull();
});
it("should raise an exception if the record exists in the parent", function() {
getAndComplete('User', 1, parent);
expect(function() {
session.createRecord('User', {
id: 1
});
}).toThrow();
});
it("should be able to create a phantom with no data", function() {
var rec;
expect(function() {
rec = session.createRecord('User');
}).not.toThrow();
expect(rec.phantom).toBe(true);
});
});
});
describe("getRecord", function() {
it("should throw an exception with an unrecognized model name", function() {
expect(function() {
session.getRecord('Luser', 1);
}).toThrow();
});
it("should throw an exception creating an anonymous model", function() {
var Model = Ext.define(null, {
extend: 'Ext.data.Model',
fields: ['name']
});
expect(function() {
session.getRecord(Model, 1);
}).toThrow();
});
describe("with no record", function() {
it("should accept the entity name", function() {
rec = session.getRecord('User', 1);
expect(rec.getId()).toBe(1);
expect(rec.$className).toBe('spec.User');
});
it("should accept the entity class", function() {
rec = session.getRecord(spec.User, 1);
expect(rec.getId()).toBe(1);
expect(rec.$className).toBe('spec.User');
});
it("should accept an existing record and adopt it", function() {
rec = new spec.User({
id: 1
});
expect(session.getRecord(rec)).toBe(rec);
expect(rec.session).toBe(session);
});
it("should create a new record and track it in the session", function() {
rec = session.getRecord('User', 1);
expect(session.peekRecord('User', 1)).toBe(rec);
});
it("should set the session on the record", function() {
rec = session.getRecord('User', 1);
expect(rec.session).toBe(session);
});
describe("autoLoad", function() {
it("should autoLoad by default", function() {
var spy = spyOn(spec.User.getProxy(), 'read');
session.getRecord('User', 1);
expect(spy).toHaveBeenCalled();
});
it("should not autoLoad when passed: false", function() {
var spy = spyOn(spec.User.getProxy(), 'read');
session.getRecord('User', 1, false);
expect(spy).not.toHaveBeenCalled();
});
it("should pass parameters to load", function() {
var spy = spyOn(spec.User.getProxy(), 'read');
session.getRecord('User', 1, {
params: {
someId: 1
}
});
expect(spy.mostRecentCall.args[0].getParams()).toEqual({
someId: 1
});
});
});
describe("with parent session", function() {
beforeEach(function() {
session.setParent(parent);
});
describe("record exists in the parent", function() {
beforeEach(function() {
rec = getAndComplete('User', 1, parent, {name: 'Foo'});
});
describe("with type/id", function() {
it("should return an existing record from the parent", function() {
var child = session.getRecord('User', 1);
expect(child.get('name')).toBe('Foo');
expect(child.$className).toBe('spec.User');
});
it("should return a copy, not the same instance", function() {
var child = session.getRecord('User', 1);
expect(child).not.toBe(rec);
});
it("should set the session to be the child session", function() {
var child = session.getRecord('User', 1);
expect(child.session).toBe(session);
});
it("should not trigger a load", function() {
var spy = spyOn(spec.User.getProxy(), 'read');
session.getRecord('User', 1);
expect(spy).not.toHaveBeenCalled();
});
it("should not update the parent record when the child changes", function() {
var child = session.getRecord('User', 1);
child.set('name', 'Bar');
expect(rec.get('name')).toBe('Foo');
});
it("should not update the child record when the parent changes", function() {
var child = session.getRecord('User', 1);
rec.set('name', 'Bar');
expect(child.get('name')).toBe('Foo');
});
it("should not copy the record if the parent is loading", function() {
rec = parent.getRecord('User', 2);
var child = session.getRecord('User', 2);
completeRequest({name: 'Foo'});
expect(rec.get('name')).toBe('Foo');
expect(child.isLoading()).toBe(true);
expect(child.get('name')).toBeUndefined();
});
});
describe("with parent instance", function() {
it("should return an existing record from the parent", function() {
var child = session.getRecord(rec);
expect(child.get('name')).toBe('Foo');
expect(child.$className).toBe('spec.User');
});
it("should return a copy, not the same instance", function() {
var child = session.getRecord(rec);
expect(child).not.toBe(rec);
});
it("should set the session to be the child session", function() {
var child = session.getRecord(rec);
expect(child.session).toBe(session);
});
it("should not trigger a load", function() {
var spy = spyOn(spec.User.getProxy(), 'read');
session.getRecord(rec);
expect(spy).not.toHaveBeenCalled();
});
it("should not update the parent record when the child changes", function() {
var child = session.getRecord(rec);
child.set('name', 'Bar');
expect(rec.get('name')).toBe('Foo');
});
it("should not update the child record when the parent changes", function() {
var child = session.getRecord(rec);
rec.set('name', 'Bar');
expect(child.get('name')).toBe('Foo');
});
it("should not copy the record if the parent is loading", function() {
rec = parent.getRecord('User', 2);
var child = session.getRecord(rec);
completeRequest({name: 'Foo'});
expect(rec.get('name')).toBe('Foo');
expect(child.isLoading()).toBe(true);
expect(child.get('name')).toBeUndefined();
});
});
});
describe("record does not exist in the parent", function() {
describe("with type/id", function() {
it("should create an instance", function() {
rec = session.getRecord('User', 1);
expect(rec.getId()).toBe(1);
expect(rec.$className).toBe('spec.User');
});
it("not push the instance into the parent", function() {
session.getRecord('User', 1);
expect(parent.peekRecord('User', 1)).toBeNull();
});
});
describe("with an instance", function() {
it("should use the passed instance", function() {
rec = new spec.User({id: 1});
expect(session.getRecord(rec)).toBe(rec);
expect(rec.session).toBe(session);
});
it("not push the instance into the parent", function() {
rec = new spec.User({id: 1});
session.getRecord(rec);
expect(parent.peekRecord('User', 1)).toBeNull();
});
});
});
});
});
describe("with an existing record", function() {
beforeEach(function() {
rec = getAndComplete('User', 1);
});
it("should accept the entity name", function() {
expect(session.getRecord('User', 1)).toBe(rec);
});
it("should accept the entity class", function() {
expect(session.getRecord(spec.User, 1)).toBe(rec);
});
it("should return the same instance", function() {
expect(session.getRecord(rec)).toBe(rec);
});
it("should return the existing record", function() {
expect(session.getRecord('User', 1)).toBe(rec);
});
it("should not attempt to load the record", function() {
var spy = spyOn(spec.User.getProxy(), 'read');
session.getRecord('User', 1);
expect(spy).not.toHaveBeenCalled();
});
});
});
describe("peekRecord", function() {
beforeEach(function() {
rec = getAndComplete('User', 1);
});
it("should accept the entity name", function() {
expect(session.peekRecord('User', 1)).toBe(rec);
});
it("should accept the entity class", function() {
expect(session.peekRecord(spec.User, 1)).toBe(rec);
});
it("should throw an exception with an unrecognized model name", function() {
expect(function() {
session.peekRecord('Luser', 1);
}).toThrow();
});
it("should throw an exception creating an anonymous model", function() {
var Model = Ext.define(null, {
extend: 'Ext.data.Model',
fields: ['name']
});
expect(function() {
session.peekRecord(Model, 1);
}).toThrow();
});
it("should return the model instance", function() {
var result = session.peekRecord('User', 1);
expect(result.isModel).toBe(true);
expect(result).toBe(rec);
});
it("should return null if the record does not exist", function() {
expect(session.peekRecord('User', 12)).toBeNull();
});
describe("parent", function() {
it("should not return a record from a parent without deep=true", function() {
session.setParent(parent);
getAndComplete('User', 2, parent);
expect(session.peekRecord('User', 2)).toBeNull();
});
it("should find a record in the parent session if we pass deep=true", function() {
session.setParent(parent);
rec = getAndComplete('User', 2, parent);
expect(session.peekRecord('User', 2, true)).toBe(rec);
});
it("should favour a record in the child", function() {
session.setParent(parent);
getAndComplete('User', 2, parent);
rec = session.getRecord('User', 2);
expect(session.peekRecord('User', 2, true)).toBe(rec);
});
it("should not consider a parent if we pass deep=true and there is no parent", function() {
expect(session.peekRecord('User', 1000, true)).toBeNull();
});
});
});
describe("associations", function() {
describe("many to one", function() {
beforeEach(function() {
Ext.define('spec.Post', {
extend: 'Ext.data.Model',
fields: ['content', {
name: 'userId',
reference: 'User'
}]
});
});
function makePost(id, userId, data) {
data = data || {};
data.id = id;
data.userId = userId;
return getAndComplete('Post', id, session, data);
}
function makeUser(id, data) {
data = data || {};
data.id = id;
return getAndComplete('User', id, session, data);
}
afterEach(function() {
Ext.undefine('spec.Post');
});
describe("the one", function() {
it("should use an existing record instance from the session", function() {
var user = makeUser(1),
post = makePost(17, 1);
expect(post.getUser()).toBe(user);
});
it("should not trigger a load when the record instance exists", function() {
var user = makeUser(1),
post = makePost(17, 1),
spy = spyOn(spec.User.getProxy(), 'read');
post.getUser();
expect(spy).not.toHaveBeenCalled();
});
it("should request an instance it needs and put it in the session", function() {
var post = makePost(17, 1),
user = post.getUser();
completeRequest({
id: 1
});
expect(session.getRecord('User', 1)).toBe(user);
});
});
describe("the many", function() {
var user;
beforeEach(function() {
user = makeUser(1);
});
afterEach(function() {
user = null;
});
it("should be empty by default and not complete", function() {
var posts = user.posts();
expect(posts.getCount()).toBe(0);
expect(posts.complete).toBe(false);
});
it("should not trigger a load", function() {
var spy = spyOn(spec.Post.getProxy(), 'read');
user.posts();
expect(spy).not.toHaveBeenCalled();
});
it("should create records on loading", function() {
var posts = user.posts();
posts.load();
completeRequest([{id: 101, userId: 1}, {id: 102, userId: 1}, {id: 103, userId: 1}]);
expect(posts.getAt(0)).toBe(session.peekRecord('Post', 101));
expect(posts.getAt(1)).toBe(session.peekRecord('Post', 102));
expect(posts.getAt(2)).toBe(session.peekRecord('Post', 103));
});
it("should set the complete flag on loading", function() {
var posts = user.posts();
posts.load();
completeRequest([]);
expect(posts.complete).toBe(true);
});
describe("local modifications", function() {
it("should add items with a matching foreign key on creation, but not be complete", function() {
// post1 & post3 exist in the session with a matching FK, as soon as the
// store is spun up they should exist in the store
var post1 = makePost(101, 1),
post3 = makePost(103, 1),
posts = user.posts();
expect(posts.getCount()).toBe(2);
expect(posts.getAt(0)).toBe(post1);
expect(posts.getAt(1)).toBe(post3);
expect(posts.complete).toBe(false);
});
it("should respect the server order when loading with existing items", function() {
// Although we have the records, maintain the order the server sent.
var post1 = makePost(101, 1),
post2 = makePost(102, 1),
post3 = makePost(103, 1),
posts = user.posts();
posts.load();
completeRequest([{id: 103, userId: 1}, {id: 102, userId: 1}, {id: 101, userId: 1}]);
expect(posts.getAt(0)).toBe(post3);
expect(posts.getAt(1)).toBe(post2);
expect(posts.getAt(2)).toBe(post1);
});
it("should add matching FK items to the end when loading", function() {
// We have a record with a matching key before the store is created.
// Once we load the store we should include it in the active set
var post2 = makePost(102, 1),
posts = user.posts();
posts.load();
completeRequest([{id: 103, userId: 1}, {id: 101, userId: 1}]);
expect(posts.getAt(0)).toBe(session.peekRecord('Post', 103));
expect(posts.getAt(1)).toBe(session.peekRecord('Post', 101));
expect(posts.getAt(2)).toBe(session.peekRecord('Post', 102));
});
it("should remove no-longer matching FK items when loading", function() {
// We had a record with a matching key which was subsequently changed.
// Reject it from the server load since the local copy is correct.
var post2 = makePost(102, 1);
post2.set('userId', null);
var posts = user.posts();
posts.load();
completeRequest([{id: 101, userId: 1}, {id: 102, userId: 1}, {id: 103, userId: 1}]);
expect(posts.getCount()).toBe(2);
expect(posts.getAt(0)).toBe(session.peekRecord('Post', 101));
expect(posts.getAt(1)).toBe(session.peekRecord('Post', 103));
});
});
});
});
describe("one to one", function() {
beforeEach(function() {
Ext.define('spec.Address', {
extend: 'Ext.data.Model',
fields: ['city']
});
});
function makeAddress(id, data) {
data = data || {};
data.id = id;
return getAndComplete('Address', id, session, data);
}
function makeUser(id, addressId, data) {
data = data || {};
data.id = id;
data.addressId = addressId;
return getAndComplete('User', id, session, data);
}
afterEach(function() {
Ext.undefine('spec.Address');
});
describe("the key holder", function() {
it("should use an existing record instance from the session", function() {
var address = makeAddress(1),
user = makeUser(17, 1);
expect(user.getAddress()).toBe(address);
});
it("should not trigger a load when the record instance exists", function() {
var address = makeAddress(1),
user = makeUser(17, 1),
spy = spyOn(spec.User.getProxy(), 'read');
user.getAddress();
expect(spy).not.toHaveBeenCalled();
});
it("should request an instance it needs and put it in the session", function() {
var user = makeUser(17, 1),
address = user.getAddress();
completeRequest({
id: 1
});
expect(session.getRecord('Address', 1)).toBe(address);
});
});
});
describe("many to many", function() {
beforeEach(function() {
Ext.define('spec.Group', {
extend: 'Ext.data.Model',
fields: ['name']
});
});
function makeUser(id) {
return getAndComplete('User', id, session);
}
function makeGroup(id) {
return getAndComplete('Group', id, session);
}
afterEach(function() {
Ext.undefine('spec.Group');
});
describe("the left", function() {
var user;
beforeEach(function() {
user = makeUser(1);
});
afterEach(function() {
user = null;
});
it("should be empty by default and not complete", function() {
var groups = user.groups();
expect(groups.getCount()).toBe(0);
expect(groups.complete).toBe(false);
});
it("should not trigger a load", function() {
var spy = spyOn(spec.Group.getProxy(), 'read');
user.groups();
expect(spy).not.toHaveBeenCalled();
});
it("should create records on loading", function() {
var groups = user.groups();
groups.load();
completeRequest([{id: 101}, {id: 102}, {id: 103}]);
expect(groups.getAt(0)).toBe(session.peekRecord('Group', 101));
expect(groups.getAt(1)).toBe(session.peekRecord('Group', 102));
expect(groups.getAt(2)).toBe(session.peekRecord('Group', 103));
});
it("should set the complete flag on loading", function() {
var groups = user.groups();
groups.load();
completeRequest([]);
expect(groups.complete).toBe(true);
});
describe("local modifications", function() {
it("should respect the load order when loading with existing items", function() {
var group2 = makeGroup(102),
groups = user.groups();
groups.add(group2);
groups.load();
completeRequest([{id: 103}, {id: 102}, {id: 101}]);
expect(groups.getAt(0)).toBe(session.peekRecord('Group', 103));
expect(groups.getAt(1)).toBe(group2);
expect(groups.getAt(2)).toBe(session.peekRecord('Group', 101));
});
it("should add matching FK items to the end when loading", function() {
var group2 = makeGroup(102),
groups = user.groups();
groups.add(group2);
groups.load();
completeRequest([{id: 103}, {id: 101}]);
expect(groups.getAt(0)).toBe(session.peekRecord('Group', 103));
expect(groups.getAt(1)).toBe(session.peekRecord('Group', 101));
expect(groups.getAt(2)).toBe(group2);
});
});
});
describe("the right", function() {
var group;
beforeEach(function() {
group = makeGroup(1);
});
afterEach(function() {
group = null;
});
it("should be empty by default and not complete", function() {
var users = group.users();
expect(users.getCount()