/**
* Nested Record Array (SC.ChildRecord) Unit Test * * @author Evin Grano */
/*global same, equals, ok, test, module*/
// .….….….….….….….….….….….….….….. // Basic Set up needs to move to the setup and teardown // var NestedRecord, store, testParent, peopleData1, peopleData2, personData1, addressData1;
var initModels = function(){
NestedRecord.Group = SC.Record.extend({ /** Child Record Namespace */ nestedRecordNamespace: NestedRecord, name: SC.Record.attr(String), people: SC.Record.toMany('NestedRecord.Person', { nested: true }) }); NestedRecord.Person = SC.Record.extend({ /** Child Record Namespace */ nestedRecordNamespace: NestedRecord, name: SC.Record.attr(String), addresses: SC.Record.toMany('NestedRecord.Address', { nested: true }) }); NestedRecord.Address = SC.Record.extend({ street: SC.Record.attr(String), city: SC.Record.attr(String), state: SC.Record.attr(String, {defaultValue: "VA"}) });
};
// .….….….….….….….….….….….….….….. // Basic SC
.ParentRecord with an Array
of Children // module(“Complex SC
.Record: Parent > Array
of Children > Array
of Children”, {
setup: function() { NestedRecord = SC.Object.create({ store: SC.Store.create() }); window.NestedRecord = NestedRecord; store = NestedRecord.store; initModels(); SC.RunLoop.begin(); testParent = store.createRecord(NestedRecord.Group, { name: 'Test Group', people: [ { type: 'Person', name: 'Barack Obama', addresses: [ { type: 'Address', street: '123 Some Street', city: 'Chicago', state: 'IL'}, { type: 'Address', street: '222 Socialist Way ', city: 'Washington', state: 'DC'} ] }, { type: 'Person', name: 'John Doe', addresses: [ { type: 'Address', street: '1111 Cross Street', city: 'Anywhere', state: 'CA'}, { type: 'Address', street: '555 18th Street ', city: 'Boulder', state: 'CO'}, { type: 'Address', street: '444 Goofy Street ', city: 'Redneck', state: 'AR'} ] }, { type: 'Person', name: 'Jane Doe', addresses: [ { type: 'Address', street: '987 Crispy Kreme Lane', city: 'Lard', state: 'TX'} ] } ] }); SC.RunLoop.end(); // Second Array for testings peopleData2 = [ { type: 'Person', name: 'Tom Jones', addresses: [ { type: 'Address', street: '1 Freezing Circle', city: 'Nome', state: 'AK'}, { type: 'Address', street: '444 Not Unusual Love Place', city: 'Las Vegas', state: 'NV'}, { type: 'Address', street: '66 On The Road', city: 'Touring', state: 'Anywhere'} ] }, { type: 'Person', name: 'Dick Smothers', addresses: [ { type: 'Address', street: '1 Mom Likes Best Place', city: 'Tujunga', state: 'CA'} ] } ]; personData1 = { type: 'Person', name: 'Testikles, God Of Fertility', addresses: [ { type: 'Address', street: '45 Gods and Goddess Place', city: 'Mount', state: 'Olympus'}, { type: 'Address', street: '1 Special Circle', city: 'Your Mom', state: 'Your State'} ] }; // Address Test Data addressData1 = [ { type: 'Address', street: '1 Main Street', city: 'Greenbow', state: 'AL'}, { type: 'Address', street: '666 Wall Street', city: 'New York', state: 'NY'}, { type: 'Address', street: '4 Dirt Road', city: 'Pleasent', state: 'CO'}, { type: 'Address', street: '1 Yellow Brick Road', city: 'Dorothy', state: 'KA'} ]; }, teardown: function() { delete NestedRecord.Group; delete NestedRecord.Person; delete NestedRecord.Address; //delete window.NestedRecord; NestedRecord = null; testParent = null; peopleData1 = null; peopleData2 = null; personData1 = null; addressData1 = null; store = null; }
});
test(“Function: readAttribute()”, function() {
var ppl; ppl = testParent.readAttribute('people'); ok(ppl, "check to see that the child records array exists"); equals(ppl.length, 3, "checking to see that the length of the elements array is 3"); // Check the first person equals(ppl[0].name, 'Barack Obama', "first person, check to see name is Barack Obama"); equals(ppl[0].addresses.length, 2, "first person, check to see length of the addresses is 2"); same(ppl[0].addresses[0], { type: 'Address', street: '123 Some Street', city: 'Chicago', state: 'IL'}, "check to see if the first person's first address is as expected"); same(ppl[0].addresses[1], { type: 'Address', street: '222 Socialist Way ', city: 'Washington', state: 'DC'}, "check to see if the first person's last address is as expected"); // Check Last person equals(ppl[2].name, 'Jane Doe', "last person, check to see name is Jane Doe"); equals(ppl[2].addresses.length, 1, "last person, check to see length of the addresses is 2"); same(ppl[2].addresses[0], { type: 'Address', street: '987 Crispy Kreme Lane', city: 'Lard', state: 'TX'}, "check to see if the last person's first address is as expected");
});
test(“Function: writeAttribute()”, function() {
var ppl; testParent.writeAttribute('people', peopleData2); ppl = testParent.readAttribute('people'); ok(ppl, "after writeAttribute(), check to see that the child records array exists"); equals(ppl.length, 2, "after writeAttribute(), checking to see that the length of the elements array is 2"); // Check the first person equals(ppl[0].name, 'Tom Jones', "first person, check to see name is Tom Jones"); equals(ppl[0].addresses.length, 3, "first person, check to see length of the addresses is 3"); same(ppl[0].addresses[0], { type: 'Address', street: '1 Freezing Circle', city: 'Nome', state: 'AK'}, "check to see if the first person's first address is as expected"); same(ppl[0].addresses[2], { type: 'Address', street: '66 On The Road', city: 'Touring', state: 'Anywhere'}, "check to see if the first person's last address is as expected"); // Check Last person equals(ppl[1].name, 'Dick Smothers', "last person, check to see name is Dick Smothers"); equals(ppl[1].addresses.length, 1, "last person, check to see length of the addresses is 2"); same(ppl[1].addresses[0], { type: 'Address', street: '1 Mom Likes Best Place', city: 'Tujunga', state: 'CA'}, "check to see if the last person's first address is as expected");
});
test(“Basic Read, Testing the First Child Array”, function() {
var ppl, pplAttr, pplDup, p, pDup, pStore, key, oldKey; // Test general gets equals(testParent.get('name'), 'Test Group', "get should be correct for name attribute: Test Group"); equals(testParent.get('nothing'), null, "get should be correct for invalid key"); // Test Person (Child Record) creation ppl = testParent.get('people'); // Check Model Class information ok(SC.instanceOf(ppl, SC.ChildArray), "check that get() creates an actual instance of a SC.ChildArray"); equals(ppl.get('length'), 3, "check that the length of the array of child records is 3"); p = ppl.objectAt(0); ok(SC.kindOf(p, SC.Record), "check that first ChildRecord from the get() creates an actual instance that is a kind of a SC.Record Object"); ok(SC.instanceOf(p, NestedRecord.Person), "check that first ChildRecord from the get() creates an actual instance of a Person Object"); // Check reference information key = p.get('id'); pStore = store.find(NestedRecord.Person, key); ok(pStore, 'check that first ChildRecord that the store has the instance of the child record with proper primary key'); equals(p, pStore, "check the parent reference to the first child is the same as the direct store reference"); // Check to see if the attributes of a Child Record match the reference of the parent pplAttr = testParent.readAttribute('people'); ok(!SC.instanceOf(pplAttr, SC.ChildArray), "check that readAttribute() does not create an actual instance of a SC.ChildArray"); same(pplAttr[0], pStore.get('attributes'), "check that the ChildRecord's attributes are the same as the ParentRecord's readAttribute for the reference"); // Duplication check pplDup = testParent.get('people'); ok(pplDup, 'check to see that we get an array on the second call to the parent for the child records'); equals(pplDup.get('length'), 3, "check that the length of the array of child records is still 3"); pDup = pplDup.objectAt(0); ok(pDup, "check to see if we have an instance of a child record again"); oldKey = p.get('id'); key = pDup.get('id'); equals(key, oldKey, "check to see if the primary keys are the same"); equals(SC.guidFor(pDup), SC.guidFor(p), "check to see if the guid are the same"); same(pDup, p, "check to see that it is the same child record as before");
});
test(“Basic Read, Testing the Second Child Array”, function() {
var pDup, pStore; var ppl, pplAttr, p, addrs, addrsDup, addrsAttr, a, aDup, aStore, key, oldKey; // Test Addresses (Child Record) creation ppl = testParent.get('people'); p = ppl.objectAt(0); addrs = p.get('addresses'); // Check Model Class information ok(SC.instanceOf(addrs, SC.ChildArray), "check that get() creates an actual instance of a SC.ChildArray"); equals(addrs.get('length'), 2, "check that the length of the array of child records is 2"); a = addrs.objectAt(0); ok(SC.kindOf(a, SC.Record), "check that first ChildRecord from the get() creates an actual instance that is a kind of a SC.Record Object"); ok(SC.instanceOf(a, NestedRecord.Address), "check that first ChildRecord from the get() creates an actual instance of a Address Object"); // Check reference information key = a.get('id'); aStore = store.find(NestedRecord.Address, key); ok(aStore, 'check that first ChildRecord that the store has the instance of the child record with proper primary key'); equals(a, aStore, "check the parent reference to the first child is the same as the direct store reference"); // Check to see if the attributes of a Child Record match the reference of the parent addrsAttr = p.readAttribute('addresses'); ok(!SC.instanceOf(addrsAttr, SC.ChildArray), "check that readAttribute() does not create an actual instance of a SC.ChildArray"); same(addrsAttr[0], aStore.get('attributes'), "check that the ChildRecord's attributes are the same as the ParentRecord's readAttribute for the reference"); pplAttr = testParent.readAttribute('people'); ok(!SC.instanceOf(pplAttr[0].addresses, SC.ChildArray), "check from the Group (parent Record) that readAttribute() does not create an actual instance of a SC.ChildArray"); same(pplAttr[0].addresses[0], aStore.get('attributes'), "check from the Group (parent Record) that the ChildRecord's attributes are the same as the ParentRecord's readAttribute for the reference"); // Duplication check addrsDup = p.get('addresses'); ok(addrsDup, 'check to see that we get an array on the second call to the parent for the child records'); equals(addrsDup.get('length'), 2, "check that the length of the array of child records is still 2"); aDup = addrsDup.objectAt(0); ok(aDup, "check to see if we have an instance of a child record again"); oldKey = a.get('id'); key = aDup.get('id'); equals(key, oldKey, "check to see if the primary key are the same"); equals(SC.guidFor(aDup), SC.guidFor(a), "check to see if the guid are the same"); same(aDup, a, "check to see that it is the same child record as before");
});
test(“Basic Write: Testing the First Child Array”, function() {
var ppl, p, pAddrs, pAddrsAttr, pStore, key, oldKey, aFirst, aLast; // Test general gets testParent.set('name', 'New Group'); equals(testParent.get('name'), 'New Group', "set() should change name attribute"); testParent.set('nothing', 'nothing'); equals(testParent.get('nothing'), 'nothing', "set should change non-existent property to a new property"); testParent.set('people', peopleData2); ppl = testParent.get('people'); ok(SC.instanceOf(ppl, SC.ChildArray), "check that get() creates an actual instance of a SC.ChildArray"); equals(ppl.get('length'), 2, "after set() on parent, check that the length of the array of child records is 2"); p = ppl.objectAt(0); ok(SC.kindOf(p, SC.Record), "check that first ChildRecord from the get() creates an actual instance that is a kind of a SC.Record Object"); ok(SC.instanceOf(p, NestedRecord.Person), "check that first ChildRecord from the get() creates an actual instance of a Person Object"); // TODO: [EG] Add test to make sure the number of ChildRecords in store is correct when we add store record clearing // Check reference information key = p.get('id'); pStore = store.find(NestedRecord.Person, key); ok(pStore, 'after a set() with an object, checking that the store has the instance of the child record with proper primary key'); equals(pStore, p, "after a set with an object, checking the parent reference is the same as the direct store reference"); // Check for changes on the child bubble to the parent. p.set('addresses', addressData1); pAddrs = p.get('addresses'); ok(SC.kindOf(pAddrs, SC.ChildArray), "check to see that the set('addresses') has returned a SC.ChildArray"); equals(pAddrs.get('length'), 4, "check with a get() that the new address length is 4"); pAddrsAttr = p.readAttribute('addresses'); equals(pAddrsAttr.length, 4, "check with a readAttribute() that the new address length is 4"); aFirst = pAddrs.objectAt(0); aLast = pAddrs.objectAt(3); same(pAddrsAttr[0], aFirst.get('attributes'), "check from the Person (parent Record) that the first Address's attributes are the same as the Person's readAttribute for the reference"); same(pAddrsAttr[3], aLast.get('attributes'), "check from the Person (parent Record) that the last Address's attributes are the same as the Person's readAttribute for the reference"); ok(p.get('status') & SC.Record.DIRTY, 'check that the person (child record) is dirty'); ok(testParent.get('status') & SC.Record.DIRTY, 'check that the group (parent record) is dirty');
});
test(“Basic Write: Testing the Second Child Array”, function() {
var ppl, pplAttr, p, addrsAttr, addrs, a; ppl = testParent.get('people'); p = ppl.objectAt(0); addrs = p.get('addresses'); a = addrs.objectAt(0); // New do the test on the address a.set('street', '123 New Street'); ok(a.get('status') & SC.Record.DIRTY, 'check that the address (child record) is dirty'); ok(p.get('status') & SC.Record.DIRTY, 'check that the person (child record) is dirty'); ok(testParent.get('status') & SC.Record.DIRTY, 'check that the group (parent record) is dirty'); // Check for changes on the child bubble to the parent. addrsAttr = p.readAttribute('addresses'); equals(addrsAttr.length, 2, "check the length of the address attribute is still 2"); equals(addrsAttr[0], a.get('attributes'), "check to see if the person's address attribute is the same as the address's attributes"); // Check the group people stuff pplAttr = testParent.readAttribute('people'); equals(pplAttr[0].addresses[0], a.get('attributes'), "check to see if the groups reference's address attribute is the same as the address's attributes");
});
test(“Basic Array
Functionality: pushObject”, function() {
var ppl, pplAttr, p, pFirst, pLast; // Add something to the array ppl = testParent.get('people'); // PushObject Tests ppl.pushObject(personData1); ppl = testParent.get('people'); equals(ppl.get('length'), 4, "after pushObject() on parent, check that the length of the array of child records is 4"); p = ppl.objectAt(3); ok(SC.kindOf(p, SC.Record), "check that newly added ChildRecord creates an actual instance that is a kind of a SC.Record Object"); ok(SC.instanceOf(p, NestedRecord.Person), "check that newly added ChildRecord creates an actual instance of a Person Object"); equals(p.get('name'), 'Testikles, God Of Fertility', "after a pushObject on parent, check to see if it has all the right values for the attributes"); ok(p.get('status') & SC.Record.DIRTY, 'check that the child record is dirty'); ok(testParent.get('status') & SC.Record.DIRTY, 'check that the parent record is dirty'); // Verify the Attrs pplAttr = testParent.readAttribute('people'); equals(pplAttr.length, 4, "after pushObject() on parent, check that the length of the attribute array of child records is 4"); pFirst = ppl.objectAt(0); pLast = ppl.objectAt(3); same(pplAttr[0], pFirst.get('attributes'), "verify that parent attributes are the same as the first individual child attributes"); same(pplAttr[3], pLast.get('attributes'), "verify that parent attributes are the same as the last individual child attributes");
});
test(“Advanced Array
Functionality: pushObject”, function() {
var ppl, that = this; that.willChange = 0; that.didChange = 0; that.removedCount = 0; that.addedCount = 0; this.arrayContentWillChange = function(start, removedCount, addedCount) { that.willChange += 1; }; this.arrayContentDidChange = function(start, removedCount, addedCount) { that.didChange += 1; that.removedCount += removedCount; that.addedCount += addedCount; }; // Create thea rray and add observers ppl = testParent.get('people'); ppl.addArrayObservers({ target: this, willChange: this.arrayContentWillChange, didChange: this.arrayContentDidChange }); // This should fire willChange and didChange once each ppl.pushObject(peopleData2[0]); equals(that.willChange, 1, "arrayContentWillChange should have been executed once"); equals(that.didChange, 1, "arrayContentDidChange should have been executed once"); equals(that.removedCount, 0, "Zero records were removed"); equals(that.addedCount, 1, "1 Record was added"); // Reset that.willChange = 0; that.didChange = 0; that.removedCount = 0; that.addedCount = 0; // This should fire willChange and didChange once each ppl.pushObject(peopleData2[1]); equals(that.willChange, 1, "arrayContentWillChange should have been executed once"); equals(that.didChange, 1, "arrayContentDidChange should have been executed once"); equals(that.removedCount, 0, "Zero records were removed"); equals(that.addedCount, 1, "A second record was added");
});
test(“Basic Array
Functionality: popObject”, function() {
var ppl, pplAttr, p, pFirst, pLast; // Add something to the array ppl = testParent.get('people'); // popObject Tests ppl.popObject(); ppl = testParent.get('people'); equals(ppl.get('length'), 2, "after popObject() on parent, check that the length of the array of child records is 2"); p = ppl.objectAt(0); ok(SC.kindOf(p, SC.Record), "check that newly added ChildRecord creates an actual instance that is a kind of a SC.Record Object"); ok(SC.instanceOf(p, NestedRecord.Person), "check that newly added ChildRecord creates an actual instance of a Person Object"); equals(p.get('name'), 'Barack Obama', "after a pushObject on parent, check to see if it has all the right values for the attributes"); ok(p.get('status') & SC.Record.DIRTY, 'check that the child record is dirty'); ok(testParent.get('status') & SC.Record.DIRTY, 'check that the parent record is dirty'); // Verify the Attrs pplAttr = testParent.readAttribute('people'); equals(pplAttr.length, 2, "after pushObject() on parent, check that the length of the attribute array of child records is 2"); pFirst = ppl.objectAt(0); pLast = ppl.objectAt(1); same(pplAttr[0], pFirst.get('attributes'), "verify that parent attributes are the same as the first individual child attributes"); same(pplAttr[1], pLast.get('attributes'), "verify that parent attributes are the same as the last individual child attributes");
});
test(“Basic Array
Functionality: shiftObject access first”, function() {
var ppl, p, removed, first, second; // Add something to the array ppl = testParent.get('people'); SC.run(function () { first = ppl.objectAt(0); second = ppl.objectAt(1); equals(first.get('name'), 'Barack Obama', "The first instance has the name"); equals(second.get('name'), 'John Doe', "The second instance has the name"); removed = ppl.shiftObject(); equals(ppl.get('length'), 2, "after shiftObject() on parent, check that the length of the array of child records is 2"); }); SC.run(function () { p = ppl.objectAt(0); equals(removed.get('name'), 'Barack Obama', "The removed object should have name"); equals(p.get('name'), 'John Doe', "The new first instance should have name"); equals(first.get('name'), 'Barack Obama', "The previous instance should still have the name"); equals(second.get('name'), 'John Doe', "The previous instance should still have the name"); ok(testParent.get('status') & SC.Record.DIRTY, 'check that the parent record is dirty'); });
});
test(“Basic Array
Functionality: shiftObject access after”, function() {
var ppl, p, removed, first, second; // Add something to the array ppl = testParent.get('people'); SC.run(function () { removed = ppl.shiftObject(); equals(ppl.get('length'), 2, "after shiftObject() on parent, check that the length of the array of child records is 2"); }); SC.run(function () { first = ppl.objectAt(0); second = ppl.objectAt(1); equals(removed.get('name'), 'Barack Obama', "The removed object should have name"); equals(first.get('name'), 'John Doe', "The new first instance should have name"); equals(second.get('name'), 'Jane Doe', "The new second instance should have name"); ok(testParent.get('status') & SC.Record.DIRTY, 'check that the parent record is dirty'); });
});
test(“Basic Array
Functionality: unshiftObject”, function() {
var ppl, pplAttr, p, pFirst, pLast; // Add something to the array ppl = testParent.get('people'); // PushObject Tests SC.run(function () { ppl.unshiftObject(personData1); }); ppl = testParent.get('people'); equals(ppl.get('length'), 4, "after unshiftObject() on parent, check that the length of the array of child records is 4"); SC.run(function () { p = ppl.objectAt(0); }); ok(SC.kindOf(p, SC.Record), "check that newly added ChildRecord creates an actual instance that is a kind of a SC.Record Object"); ok(SC.instanceOf(p, NestedRecord.Person), "check that newly added ChildRecord creates an actual instance of a Person Object"); equals(p.get('name'), 'Testikles, God Of Fertility', "after a pushObject on parent, check to see if it has all the right values for the attributes"); ok(p.get('status') & SC.Record.DIRTY, 'check that the child record is dirty'); ok(testParent.get('status') & SC.Record.DIRTY, 'check that the parent record is dirty'); // Verify the Attrs pplAttr = testParent.readAttribute('people'); equals(pplAttr.length, 4, "after unshiftObject() on parent, check that the length of the attribute array of child records is 4"); SC.run(function () { pFirst = ppl.objectAt(0); pLast = ppl.objectAt(3); }); same(pplAttr[0], pFirst.get('attributes'), "verify that parent attributes are the same as the first individual child attributes"); same(pplAttr[3], pLast.get('attributes'), "verify that parent attributes are the same as the last individual child attributes");
});
test(“Test: normalization on complex nested records”, function() {
var ppl, addresses, pAttrs; // Add something to the array ppl = testParent.get('people'); SC.run(function () { addresses = ppl.objectAt(0).get('addresses'); addresses.pushObject({ type: 'Address', street: '2 Main Street', city: 'Awesome'}); testParent.normalize(); }); pAttrs = testParent.get('attributes'); equals(pAttrs.people[0].addresses[2].state, 'VA', "test normalization is the default value of VA");
});