// ========================================================================== // Project: SproutCore
- JavaScript Application Framework // Copyright: ©2006-2011 Apple Inc. and contributors. // License: Licensed under MIT license (see license.js) // ========================================================================== /*globals module ok equals same test MyApp */
// test core array-mapping methods for RecordArray var store, storeKey, json, rec, storeKeys, recs, query, recsController, fooQuery, fooRecs, fooRecsController; module(“SC.RecordArray core methods”, {
setup: function() { // setup dummy store store = SC.Store.create(); storeKey = SC.Record.storeKeyFor('foo'); json = { guid: "foo", foo: "foo" }; store.writeDataHash(storeKey, json, SC.Record.READY_CLEAN); // get record rec = store.materializeRecord(storeKey); equals(rec.get('foo'), 'foo', 'record should have json'); // get record array. query = SC.Query.create({ recordType: SC.Record }); recs = SC.RecordArray.create({ store: store, query: query }); recsController = SC.Object.create({ content: recs, bigCost: NO, veryExpensiveObserver: function() { this.set('bigCost', YES); }.observes('.content.[]') }); fooQuery = SC.Query.create({ recordType: SC.Record, conditions: "foo='foo'" }); fooRecs = SC.RecordArray.create({ store: store, query: fooQuery }); fooRecsController = SC.Object.create({ content: fooRecs, bigCost: NO, veryExpensiveObserver: function() { this.set('bigCost', YES); }.observes('.content.[]') }); }
});
// .….….….….….….….….….….….….….….. // BASIC TESTS //
test(“should not initially populate storeKeys array until we flush()”, function() {
equals(recs.get('storeKeys'), null, 'should not have storeKeys yet'); recs.flush(); var storeKeys = recs.get('storeKeys'); same(storeKeys, [storeKey], 'after flush should have initial set of storeKeys');
});
test(“length property should flush”, function() {
equals(recs.get('storeKeys'), null,' should not have storeKeys yet'); equals(recs.get('length'), 1, 'should have length 1 when called'); same(recs.get('storeKeys'), [storeKey], 'after flush should have initial set of storeKeys');
});
test(“objectAt() should flush”, function() {
equals(recs.get('storeKeys'), null,' should not have storeKeys yet'); equals(recs.objectAt(0), rec, 'objectAt(0) should return record'); same(recs.get('storeKeys'), [storeKey], 'after flush should have initial set of storeKeys');
});
// .….….….….….….….….….….….….….….. // storeDidChangeStoreKeys() //
test(“calling storeDidChangeStoreKeys() with a matching recordType”, function() {
recs.flush(); // do initial setup var orig = recs.get('storeKeys').copy(); // do it this way instead of using store.createRecord() to isolate the // method call. storeKey = SC.Record.storeKeyFor("bar"); json = { guid: "bar", foo: "bar" }; store.writeDataHash(storeKey, json, SC.Record.READY_CLEAN); equals(recs.get('needsFlush'), NO, 'PRECOND - should not need flush'); same(recs.get('storeKeys'), orig, 'PRECOND - storeKeys should not have changed yet'); recs.storeDidChangeStoreKeys([storeKey], SC.Set.create().add(SC.Record)); orig.push(storeKey); // update - must be last b/c id.bar.storeKey < id.foo.storeKey equals(recs.get('needsFlush'), NO, 'should not need flush anymore'); same(recs.get('storeKeys'), orig, 'storeKeys should now be updated - rec1[%@]{%@} = %@, rec2[%@]{%@} = %@'.fmt( rec.get('id'), rec.get('storeKey'), rec, store.materializeRecord(storeKey).get('id'), storeKey, store.materializeRecord(storeKey)));
});
test(“calling storeDidChangeStoreKeys() with a non-matching recordType”, function() {
var Foo = SC.Record.extend(), Bar = SC.Record.extend(); storeKey = Foo.storeKeyFor('foo2'); json = { guid: "foo2" }; store.writeDataHash(storeKey, json, SC.Record.READY_CLEAN); query = SC.Query.create({ recordType: Foo }); recs = SC.RecordArray.create({ store: store, query: query }); equals(recs.get('length'), 1, 'should have a Foo record'); // now simulate adding a Bar record storeKey = Bar.storeKeyFor('bar'); json = { guid: "bar" }; store.writeDataHash(storeKey, json, SC.Record.READY_CLEAN); recs.storeDidChangeStoreKeys([storeKey], SC.Set.create().add(Bar)); equals(recs.get('needsFlush'), NO, 'should not have indicated it needed a flush');
});
test(“calling storeDidChangeStoreKeys() to remove a record”, function() {
equals(recs.get('length'), 1, 'PRECOND - should have storeKey'); store.writeStatus(storeKey, SC.Record.DESTROYED_CLEAN); equals(recs.get('storeKeys').length, 1, 'should still have storeKey'); recs.storeDidChangeStoreKeys([storeKey], SC.Set.create().add(SC.Record)); equals(recs.get('length'), 0, 'should remove storeKey on flush()');
});
test(“calling storeDidChangeStoreKeys() with a matching recordType should not unnecessarily call enumerableContentDidChange”, function() {
// do initial setup recs.flush(); fooRecs.flush(); recsController.set('bigCost', NO); fooRecsController.set('bigCost', NO); // do it this way instead of using store.createRecord() to isolate the // method call. storeKey = SC.Record.storeKeyFor("bar"); json = { guid: "bar", foo: "bar" }; store.writeDataHash(storeKey, json, SC.Record.READY_CLEAN); equals(recsController.get('bigCost'), NO, 'PRECOND - recsController should not have spent big cost'); equals(fooRecsController.get('bigCost'), NO, 'PRECOND - fooRecsController should not have spent big cost'); recs.storeDidChangeStoreKeys([storeKey], SC.Set.create().add(SC.Record)); fooRecs.storeDidChangeStoreKeys([storeKey], SC.Set.create().add(SC.Record)); equals(recsController.get('bigCost'), YES, 'recsController should have spent big cost'); equals(fooRecsController.get('bigCost'), NO, 'fooRecsController should not have spent big cost');
});
test(“adding an array observer to a SC
.RecordArray should cause the array to flush”, function() {
var callCount = 0; recs.addArrayObservers({ didChange: function() { callCount++; }, willChange: function() { } }); recs.get('length'); equals(callCount, 0, "does not cause array observers to be fired when getting length");
});
// .….….….….….….….….….….….….….….. // SPECIAL CASES //
var json2, foo, bar ;
module(“SC.RecordArray core methods”, {
setup: function() { // setup dummy store store = SC.Store.create(); storeKey = SC.Record.storeKeyFor('foo'); json = { guid: "foo", name: "foo" }; store.writeDataHash(storeKey, json, SC.Record.READY_CLEAN); foo = store.materializeRecord(storeKey); equals(foo.get('name'), 'foo', 'record should have json'); storeKey = SC.Record.storeKeyFor('bar'); json2 = { guid: "bar", name: "bar" }; store.writeDataHash(storeKey, json2, SC.Record.READY_CLEAN); bar = store.materializeRecord(storeKey); equals(bar.get('name'), 'bar', 'record should have json'); // get record array. query = SC.Query.create({ recordType: SC.Record, orderBy: 'name' }); recs = store.find(query); }
});
test(“local query should notify changes”, function() {
// note: important to retrieve records from RecordArray first to prime // any cache same(recs.mapProperty('id'), ['bar', 'foo'], 'PRECOND - bar should appear before foo'); SC.stopIt = YES; SC.RunLoop.begin(); bar.set('name', 'zzbar'); SC.RunLoop.end(); // should resort record array same(recs.mapProperty('id'), ['foo', 'bar'], 'order of records should change');
});