// ========================================================================== // 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 */
var store, child, storeKey, json; module(“SC.Store#commitChangesFromNestedStore”, {
setup: function() { SC.RunLoop.begin(); store = SC.Store.create(); json = { string: "string", number: 23, bool: YES }; storeKey = SC.Store.generateStoreKey(); child = store.chain(); // test multiple levels deep // write basic status child.writeDataHash(storeKey, json, SC.Record.READY_DIRTY); child.dataHashDidChange(storeKey); child.changelog = SC.Set.create(); child.changelog.add(storeKey); SC.RunLoop.end(); }
});
test(“copies changed data hashes, statuses, and revisions”, function() {
SC.RunLoop.begin(); // verify preconditions equals(store.readDataHash(storeKey), null, 'precond - should not have data yet'); ok(child.chainedChanges.contains(storeKey), 'precond - child changes should include storeKey'); // perform action equals(store.commitChangesFromNestedStore(child, child.chainedChanges, NO), store, 'should return receiver'); // verify new status equals(store.readDataHash(storeKey), json, 'now should have json'); equals(store.readStatus(storeKey), SC.Record.READY_DIRTY, 'now should have status'); equals(store.revisions[storeKey], child.revisions[storeKey], 'now shoulave have revision from child'); SC.RunLoop.end();
});
test(“adds items in changelog to receiver changelog”, function() {
var key1 = SC.Store.generateStoreKey(); SC.RunLoop.begin(); store.changelog = SC.Set.create(); store.changelog.add(key1); ok(child.changelog.contains(storeKey), 'precond - child.changelog should contain store key'); equals(store.commitChangesFromNestedStore(child, child.chainedChanges, NO), store, 'should return receiver'); // changelog should merge nested store & existing ok(store.changelog.contains(key1), 'changelog should still contain key1'); ok(store.changelog.contains(storeKey), 'changelog should also contain storeKey'); SC.RunLoop.end();
});
test(“ignores changed data hashes not passed in changes set”, function() {
// preconditions equals(store.readDataHash(storeKey), null, 'precond - should not have data yet'); // perform action equals(store.commitChangesFromNestedStore(child, SC.Set.create(), NO), store, 'should return receiver'); // verify results equals(store.readDataHash(storeKey), null, 'should not copy data hash for storeKey');
});
function createConflict(force) {
var json2 = { kind: "json2" }; var json3 = { kind: "json3" }; // create a lock conflict. use a new storeKey since the old one has been // setup in a way that won't work for this. storeKey = SC.Store.generateStoreKey(); // step 1: add data to root store store.writeDataHash(storeKey, json, SC.Record.READY_CLEAN); store.dataHashDidChange(storeKey); // step 2: read data in chained store. this will create lock child.readDataHash(storeKey); ok(child.locks[storeKey], 'child store should now have lock'); // step 3: modify root store again store.writeDataHash(storeKey, json2, SC.Record.READY_CLEAN); store.dataHashDidChange(storeKey); // step 4: modify data in chained store so we have something to commit. child.writeDataHash(storeKey, json3, SC.Record.READY_DIRTY); child.dataHashDidChange(storeKey); // just to make sure verify that the lock and revision in parent do not // match ok(child.locks[storeKey] !== store.revisions[storeKey], 'child.lock (%@) should !== store.revision (%@)'.fmt(child.locks[storeKey], store.revisions[storeKey])); // step 5: now try to commit changes from child store. This should throw // an exception. var errorCount = 0; try { child.commitChanges(force); } catch(e) { equals(e.message, SC.Store.CHAIN_CONFLICT_ERROR.toString(), 'should throw CHAIN_CONFLICT_ERROR'); errorCount++; } return errorCount ;
}
test(“throws exception if any record fails optimistic locking test”, function() {
var errorCount = createConflict(NO); equals(errorCount, 1, 'should have raised error');
});
test(“does not throw exception if optimistic locking fails but force option is passed”, function() {
var errorCount = createConflict(YES); equals(errorCount, 0, 'should not raise error');
});