1 if(!dojo._hasResource["tests.data.ItemFileWriteStore"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
2 dojo._hasResource["tests.data.ItemFileWriteStore"] = true;
3 dojo.provide("tests.data.ItemFileWriteStore");
4 dojo.require("tests.data.readOnlyItemFileTestTemplates");
6 dojo.require("dojo.data.ItemFileWriteStore");
7 dojo.require("dojo.data.api.Read");
8 dojo.require("dojo.data.api.Identity");
9 dojo.require("dojo.data.api.Write");
10 dojo.require("dojo.data.api.Notification");
13 // First, make sure ItemFileWriteStore can still pass all the same unit tests
14 // that we use for its superclass, ItemFileReadStore:
15 tests.data.readOnlyItemFileTestTemplates.registerTestsForDatastore("dojo.data.ItemFileWriteStore");
17 tests.data.ItemFileWriteStore.getTestData = function(name){
19 if(name === "reference_integrity"){
21 data = {url: dojo.moduleUrl("tests", "data/reference_integrity.json").toString() };
28 {"id": 1, "name": "Item 1"},
29 {"id": 2, "name": "Item 2"},
30 {"id": 3, "name": "Item 3"},
31 {"id": 4, "name": "Item 4"},
32 {"id": 5, "name": "Item 5"},
33 {"id": 6, "name": "Item 6"},
34 {"id": 7, "name": "Item 7"},
35 {"id": 8, "name": "Item 8"},
36 {"id": 9, "name": "Item 9"},
37 {"id": 10, "name": "Item 10", "friends": [{"_reference": 1},{"_reference": 3},{"_reference": 5}]},
38 {"id": 11, "name": "Item 11", "friends": [{"_reference": 10}], "siblings": [{"_reference": 10}]},
39 {"id": 12, "name": "Item 12", "friends": [{"_reference": 3},{"_reference": 7}], "enemies": [{"_reference": 10}]},
40 {"id": 13, "name": "Item 13", "friends": [{"_reference": 10}]},
41 {"id": 14, "name": "Item 14", "friends": [{"_reference": 11}]},
42 {"id": 15, "name": "item 15", "friends": [{"id": 16, "name": "Item 16"}]}
52 // Now run some tests that are specific to the write-access features:
53 doh.register("tests.data.ItemFileWriteStore",
55 function test_getFeatures(){
57 // Simple test of the getFeatures function of the store
59 // Simple test of the getFeatures function of the store
60 var store = new dojo.data.ItemFileWriteStore(tests.data.readOnlyItemFileTestTemplates.getTestData("countries"));
62 var features = store.getFeatures();
64 // make sure we have the expected features:
65 doh.assertTrue(features["dojo.data.api.Read"] != null);
66 doh.assertTrue(features["dojo.data.api.Identity"] != null);
67 doh.assertTrue(features["dojo.data.api.Write"] != null);
68 doh.assertTrue(features["dojo.data.api.Notification"] != null);
69 doh.assertFalse(features["iggy"]);
71 // and only the expected features:
73 for(var i in features){
74 doh.assertTrue((i === "dojo.data.api.Read" ||
75 i === "dojo.data.api.Identity" ||
76 i === "dojo.data.api.Write" ||
77 i === "dojo.data.api.Notification"));
80 doh.assertEqual(count, 4);
82 function testWriteAPI_setValue(){
84 // Simple test of the setValue API
86 // Simple test of the setValue API
87 var store = new dojo.data.ItemFileWriteStore(tests.data.readOnlyItemFileTestTemplates.getTestData("countries"));
89 var deferred = new doh.Deferred();
90 function onComplete(items, request){
91 doh.assertEqual(1, items.length);
93 doh.assertTrue(store.containsValue(item, "capital", "Cairo"));
96 // Okay, so this seems very odd. Maybe I'm just being dense.
98 doh.assertEqual(store.isDirty(item), false);
99 doh.assertTrue(store.isDirty(item) == false);
100 // But these seemingly equivalent tests will not work:
101 // doh.assertFalse(store.isDirty(item));
102 // doh.assertTrue(!(store.isDirty(item)));
104 // All of which seems especially weird, given that this *does* work:
105 doh.assertFalse(store.isDirty());
108 doh.assertTrue(store.isDirty(item) == false);
109 doh.assertTrue(!store.isDirty());
110 store.setValue(item, "capital", "New Cairo");
111 doh.assertTrue(store.isDirty(item));
112 doh.assertTrue(store.isDirty());
113 doh.assertEqual(store.getValue(item, "capital").toString(), "New Cairo");
114 deferred.callback(true);
116 function onError(error, request){
117 deferred.errback(error);
119 store.fetch({query:{name:"Egypt"}, onComplete: onComplete, onError: onError});
120 return deferred; //Object
122 function testWriteAPI_setValues(){
124 // Simple test of the setValues API
126 // Simple test of the setValues API
127 var store = new dojo.data.ItemFileWriteStore(tests.data.readOnlyItemFileTestTemplates.getTestData("countries"));
129 var deferred = new doh.Deferred();
130 function onComplete(items, request){
131 doh.assertEqual(1, items.length);
133 doh.assertTrue(store.containsValue(item, "name", "Egypt"));
134 doh.assertTrue(store.isDirty(item) == false);
135 doh.assertTrue(!store.isDirty());
136 store.setValues(item, "name", ["Egypt 1", "Egypt 2"]);
137 doh.assertTrue(store.isDirty(item));
138 doh.assertTrue(store.isDirty());
139 var values = store.getValues(item, "name");
140 doh.assertTrue(values[0] == "Egypt 1");
141 doh.assertTrue(values[1] == "Egypt 2");
142 deferred.callback(true);
144 function onError(error, request){
145 deferred.errback(error);
147 store.fetch({query:{name:"Egypt"}, onComplete: onComplete, onError: onError});
148 return deferred; //Object
150 function testWriteAPI_unsetAttribute(){
152 // Simple test of the unsetAttribute API
154 // Simple test of the unsetAttribute API
155 var store = new dojo.data.ItemFileWriteStore(tests.data.readOnlyItemFileTestTemplates.getTestData("countries"));
157 var deferred = new doh.Deferred();
158 function onComplete(items, request) {
159 doh.assertEqual(1, items.length);
161 doh.assertTrue(store.containsValue(item, "name", "Egypt"));
162 doh.assertTrue(store.isDirty(item) == false);
163 doh.assertTrue(!store.isDirty());
164 store.unsetAttribute(item, "name");
165 doh.assertTrue(store.isDirty(item));
166 doh.assertTrue(store.isDirty());
167 doh.assertTrue(!store.hasAttribute(item, "name"));
168 deferred.callback(true);
170 function onError(error, request) {
171 deferred.errback(error);
173 store.fetch({query:{name:"Egypt"}, onComplete: onComplete, onError: onError});
174 return deferred; //Object
176 function testWriteAPI_newItem(){
178 // Simple test of the newItem API
180 // Simple test of the newItem API
181 var store = new dojo.data.ItemFileWriteStore(tests.data.readOnlyItemFileTestTemplates.getTestData("countries"));
183 var deferred = new doh.Deferred();
184 doh.assertTrue(!store.isDirty());
186 var onNewInvoked = false;
187 store.onNew = function(newItem, parentInfo){
189 doh.assertTrue(newItem !== null);
190 doh.assertTrue(parentInfo === null);
191 doh.assertTrue(store.isItem(newItem));
194 var canada = store.newItem({name: "Canada", abbr:"ca", capital:"Ottawa"});
195 doh.assertTrue(onNewInvoked);
197 doh.assertTrue(store.isDirty(canada));
198 doh.assertTrue(store.isDirty());
199 doh.assertTrue(store.getValues(canada, "name") == "Canada");
200 function onComplete(items, request){
201 doh.assertEqual(1, items.length);
203 doh.assertTrue(store.containsValue(item, "name", "Canada"));
204 deferred.callback(true);
206 function onError(error, request){
207 deferred.errback(error);
209 store.fetch({query:{name:"Canada"}, onComplete: onComplete, onError: onError});
210 return deferred; //Object
212 function testWriteAPI_newItem_withParent(){
214 // Simple test of the newItem API with a parent assignment
216 // Simple test of the newItem API with a parent assignment
217 var store = new dojo.data.ItemFileWriteStore(tests.data.readOnlyItemFileTestTemplates.getTestData("countries"));
219 var deferred = new doh.Deferred();
220 doh.assertTrue(!store.isDirty());
221 function onComplete(items, request){
222 doh.assertEqual(1, items.length);
224 doh.assertTrue(store.containsValue(item, "name", "Egypt"));
226 //Attach an onNew to validate we get expected values.
227 var onNewInvoked = false;
228 store.onNew = function(newItem, parentInfo){
229 doh.assertEqual(item, parentInfo.item);
230 doh.assertEqual("cities", parentInfo.attribute);
231 doh.assertTrue(parentInfo.oldValue === undefined);
232 doh.assertTrue(parentInfo.newValue === newItem);
236 //Attach an onSet and verify onSet is NOT called in this case.
237 store.onSet = function(item, attribute, oldValue, newValue){
238 doh.assertTrue(false);
241 //See if we can add in a new item representing the city of Cairo.
242 //This should also call the onNew set above....
243 var newItem = store.newItem({name: "Cairo", abbr: "Cairo"}, {parent: item, attribute: "cities"});
244 doh.assertTrue(onNewInvoked);
246 function onCompleteNewItemShallow(items, request){
247 doh.assertEqual(0, items.length);
248 function onCompleteNewItemDeep(items, request){
249 doh.assertEqual(1, items.length);
251 doh.assertEqual("Cairo", store.getValue(item, "name"));
252 deferred.callback(true);
254 //Do a deep search now, should find the new item of the city with name attribute Cairo.
255 store.fetch({query:{name:"Cairo"}, onComplete: onCompleteNewItemDeep, onError: onError, queryOptions: {deep:true}});
257 //Do a shallow search first, should find nothing.
258 store.fetch({query:{name:"Cairo"}, onComplete: onCompleteNewItemShallow, onError: onError});
260 function onError(error, request){
261 deferred.errback(error);
263 store.fetch({query:{name:"Egypt"}, onComplete: onComplete, onError: onError});
264 return deferred; //Object
267 function testWriteAPI_newItem_multiple_withParent(){
269 // Simple test of the newItem API with a parent assignment multiple times.
271 // Simple test of the newItem API with a parent assignment multiple times.
272 var store = new dojo.data.ItemFileWriteStore(tests.data.readOnlyItemFileTestTemplates.getTestData("countries"));
274 var deferred = new doh.Deferred();
276 doh.assertTrue(!store.isDirty());
278 function onComplete(items, request){
279 doh.assertEqual(1, items.length);
281 doh.assertTrue(store.containsValue(item, "name", "Egypt"));
283 //Attach an onNew to validate we get expected values.
284 store.onNew = function(newItem, parentInfo){
285 doh.assertEqual(item, parentInfo.item);
286 doh.assertEqual("cities", parentInfo.attribute);
288 doh.assertTrue(parentInfo.oldValue === undefined);
290 doh.assertTrue(parentInfo.newValue === newItem);
293 //See if we can add in a new item representing the city of Cairo.
294 //This should also call the onNew set above....
295 var newItem1 = store.newItem({name: "Cairo", abbr: "Cairo"}, {parent: item, attribute: "cities"});
297 //Attach a new onNew to validate we get expected values.
298 store.onNew = function(newItem, parentInfo){
299 doh.assertEqual(item, parentInfo.item);
300 doh.assertEqual("cities", parentInfo.attribute);
302 console.log(parentInfo.oldValue);
303 doh.assertTrue(parentInfo.oldValue == newItem1);
305 doh.assertTrue(parentInfo.newValue[0] == newItem1);
306 doh.assertTrue(parentInfo.newValue[1] == newItem);
308 var newItem2 = store.newItem({name: "Banha", abbr: "Banha"}, {parent: item, attribute: "cities"});
310 //Attach a new onNew to validate we get expected values.
311 store.onNew = function(newItem, parentInfo){
312 doh.assertEqual(item, parentInfo.item);
313 doh.assertEqual("cities", parentInfo.attribute);
315 doh.assertTrue(parentInfo.oldValue[0] == newItem1);
316 doh.assertTrue(parentInfo.oldValue[1] == newItem2);
318 doh.assertTrue(parentInfo.newValue[0] == newItem1);
319 doh.assertTrue(parentInfo.newValue[1] == newItem2);
320 doh.assertTrue(parentInfo.newValue[2] == newItem);
322 var newItem3 = store.newItem({name: "Damanhur", abbr: "Damanhur"}, {parent: item, attribute: "cities"});
323 deferred.callback(true);
325 function onError(error, request){
326 deferred.errback(error);
328 store.fetch({query:{name:"Egypt"}, onComplete: onComplete, onError: onError});
329 return deferred; //Object
332 function testWriteAPI_deleteItem(){
334 // Simple test of the deleteItem API
336 // Simple test of the deleteItem API
337 var store = new dojo.data.ItemFileWriteStore(tests.data.readOnlyItemFileTestTemplates.getTestData("countries"));
339 var deferred = new doh.Deferred();
340 function onComplete(items, request){
341 doh.assertEqual(1, items.length);
343 doh.assertTrue(store.containsValue(item, "name", "Egypt"));
344 doh.assertTrue(store.isDirty(item) == false);
345 doh.assertTrue(!store.isDirty());
346 store.deleteItem(item);
347 doh.assertTrue(store.isDirty(item));
348 doh.assertTrue(store.isDirty());
349 function onCompleteToo(itemsToo, requestToo) {
350 doh.assertEqual(0, itemsToo.length);
351 deferred.callback(true);
353 store.fetch({query:{name:"Egypt"}, onComplete: onCompleteToo, onError: onError});
355 function onError(error, request){
356 deferred.errback(error);
358 store.fetch({query:{name:"Egypt"}, onComplete: onComplete, onError: onError});
359 return deferred; //Object
361 function testWriteAPI_isDirty(){
363 // Simple test of the isDirty API
365 // Simple test of the isDirty API
366 var store = new dojo.data.ItemFileWriteStore(tests.data.readOnlyItemFileTestTemplates.getTestData("countries"));
368 var deferred = new doh.Deferred();
369 function onComplete(items, request) {
370 doh.assertEqual(1, items.length);
372 doh.assertTrue(store.containsValue(item, "name", "Egypt"));
373 store.setValue(item, "name", "Egypt 2");
374 doh.assertTrue(store.getValue(item, "name") == "Egypt 2");
375 doh.assertTrue(store.isDirty(item));
376 deferred.callback(true);
378 function onError(error, request) {
379 deferred.errback(error);
381 store.fetch({query:{name:"Egypt"}, onComplete: onComplete, onError: onError});
382 return deferred; //Object
384 function testWriteAPI_revert(){
386 // Simple test of the revert API
388 // Simple test of the revert API
389 var store = new dojo.data.ItemFileWriteStore(tests.data.readOnlyItemFileTestTemplates.getTestData("countries"));
391 var deferred = new doh.Deferred();
392 function onComplete(items, request) {
393 doh.assertEqual(1, items.length);
395 doh.assertTrue(store.containsValue(item, "name", "Egypt"));
396 doh.assertTrue(store.isDirty(item) == false);
397 doh.assertTrue(!store.isDirty());
398 store.setValue(item, "name", "Egypt 2");
399 doh.assertTrue(store.getValue(item, "name") == "Egypt 2");
400 doh.assertTrue(store.isDirty(item));
401 doh.assertTrue(store.isDirty());
404 //Fetch again to see if it reset the state.
405 function onCompleteToo(itemsToo, requestToo){
406 doh.assertEqual(1, itemsToo.length);
407 var itemToo = itemsToo[0];
408 doh.assertTrue(store.containsValue(itemToo, "name", "Egypt"));
409 deferred.callback(true);
411 store.fetch({query:{name:"Egypt"}, onComplete: onCompleteToo, onError: onError});
413 function onError(error, request){
414 deferred.errback(error);
416 store.fetch({query:{name:"Egypt"}, onComplete: onComplete, onError: onError});
417 return deferred; //Object
419 function testWriteAPI_save(){
421 // Simple test of the save API
423 // Simple test of the save API
424 var store = new dojo.data.ItemFileWriteStore(tests.data.readOnlyItemFileTestTemplates.getTestData("countries"));
426 var deferred = new doh.Deferred();
427 function onError(error){
428 deferred.errback(error);
430 function onItem(item){
431 store.setValue(item, "capital", "New Cairo");
432 function onComplete() {
433 deferred.callback(true);
435 store.save({onComplete:onComplete, onError:onError});
437 store.fetchItemByIdentity({identity:"eg", onItem:onItem, onError:onError});
438 return deferred; //Object
440 function testWriteAPI_saveVerifyState(){
442 // Simple test of the save API
444 // Simple test of the save API
445 var store = new dojo.data.ItemFileWriteStore(tests.data.readOnlyItemFileTestTemplates.getTestData("countries"));
447 var deferred = new doh.Deferred();
448 function onError(error){
449 deferred.errback(error);
451 function onItem(item){
452 store.setValue(item, "capital", "New Cairo");
453 function onComplete() {
454 //Check internal state. Note: Users should NOT do this, this is a UT verification
455 //of internals in this case. Ref tracker: #4394
456 doh.assertTrue(!store._saveInProgress);
457 deferred.callback(true);
459 store.save({onComplete:onComplete, onError:onError});
461 store.fetchItemByIdentity({identity:"eg", onItem:onItem, onError:onError});
462 return deferred; //Object
464 function testWriteAPI_saveEverything(){
466 // Simple test of the save API
468 // Simple test of the save API
469 var store = new dojo.data.ItemFileWriteStore(tests.data.readOnlyItemFileTestTemplates.getTestData("countries"));
471 store._saveEverything = function(saveCompleteCallback, saveFailedCallback, newFileContentString){
472 var struct = dojo.fromJson(newFileContentString);
473 doh.assertEqual(struct.identifier, store.getIdentityAttributes(egypt)[0]);
474 doh.assertEqual(struct.label, store.getLabelAttributes(egypt)[0]);
475 doh.assertEqual(struct.items.length, 7);
477 var cloneStore = new dojo.data.ItemFileWriteStore({data:struct});
478 function onItemClone(itemClone){
479 var egyptClone = itemClone;
480 doh.assertEqual(store.getIdentityAttributes(egypt)[0], cloneStore.getIdentityAttributes(egyptClone)[0]);
481 doh.assertEqual(store.getLabelAttributes(egypt)[0], cloneStore.getLabelAttributes(egyptClone)[0]);
482 doh.assertEqual(store.getValue(egypt, "name"), cloneStore.getValue(egyptClone, "name"));
484 cloneStore.fetchItemByIdentity({identity:"eg", onItem:onItemClone, onError:onError});
486 saveCompleteCallback();
489 var deferred = new doh.Deferred();
490 function onError(error){
491 deferred.errback(error);
493 function onItem(item){
495 function onComplete() {
496 deferred.callback(true);
498 store.setValue(egypt, "capital", "New Cairo");
499 store.save({onComplete:onComplete, onError:onError});
501 store.fetchItemByIdentity({identity:"eg", onItem:onItem, onError:onError});
502 return deferred; //Object
504 function testWriteAPI_saveEverything_withDateType(){
506 // Simple test of the save API with a non-atomic type (Date) that has a type mapping.
508 // Simple test of the save API with a non-atomic type (Date) that has a type mapping.
509 var store = new dojo.data.ItemFileWriteStore(tests.data.readOnlyItemFileTestTemplates.getTestData("countries"));
510 store._saveEverything = function(saveCompleteCallback, saveFailedCallback, newFileContentString){
512 //Now load the new data into a datastore and validate that it stored the date right.
513 var dataset = dojo.fromJson(newFileContentString);
514 var newStore = new dojo.data.ItemFileWriteStore({data: dataset});
516 function gotItem(item){
517 var independenceDate = newStore.getValue(item,"independence");
518 doh.assertTrue(independenceDate instanceof Date);
519 doh.assertTrue(dojo.date.compare(new Date(1993,04,24), independenceDate, "date") === 0);
520 saveCompleteCallback();
522 function failed(error, request){
523 deferred.errback(error);
524 saveFailedCallback();
526 newStore.fetchItemByIdentity({identity:"eg", onItem:gotItem, onError:failed});
529 var deferred = new doh.Deferred();
530 function onError(error){
531 deferred.errback(error);
533 function onItem(item){
534 function onComplete() {
535 deferred.callback(true);
537 store.setValue(item, "independence", new Date(1993,04,24));
538 store.save({onComplete:onComplete, onError:onError});
540 store.fetchItemByIdentity({identity:"eg", onItem:onItem, onError:onError});
541 return deferred; //Object
543 function testWriteAPI_saveEverything_withCustomColorTypeSimple(){
545 // Simple test of the save API with a non-atomic type (dojo.Color) that has a type mapping.
547 // Simple test of the save API with a non-atomic type (dojo.Color) that has a type mapping.
549 //Set up the store basics: What data it has, and what to do when save is called for saveEverything
550 //And how to map the 'Color' type in and out of the format.
551 //(Test of saving all to a some location...)
555 { name:'Kermit', species:'frog', color:{_type:'Color', _value:'green'} },
556 { name:'Beaker', hairColor:{_type:'Color', _value:'red'} }
560 var customTypeMap = {'Color': dojo.Color };
562 var store = new dojo.data.ItemFileWriteStore({
564 typeMap: customTypeMap
567 store._saveEverything = function(saveCompleteCallback, saveFailedCallback, newFileContentString){
568 //Now load the new data into a datastore and validate that it stored the Color right.
569 var dataset = dojo.fromJson(newFileContentString);
570 var newStore = new dojo.data.ItemFileWriteStore({data: dataset, typeMap: customTypeMap});
572 function gotItem(item){
573 var hairColor = newStore.getValue(item,"hairColor");
574 doh.assertTrue(hairColor instanceof dojo.Color);
575 doh.assertEqual("rgba(255, 255, 0, 1)", hairColor.toString());
576 saveCompleteCallback();
578 function failed(error, request){
579 deferred.errback(error);
580 saveFailedCallback();
582 newStore.fetchItemByIdentity({identity:"Animal", onItem:gotItem, onError:failed});
585 //Add a new item with a color type, then save it.
586 var deferred = new doh.Deferred();
587 function onError(error){
588 deferred.errback(error);
590 function onComplete() {
591 deferred.callback(true);
594 var animal = store.newItem({name: "Animal", hairColor: new dojo.Color("yellow")});
595 store.save({onComplete:onComplete, onError:onError});
596 return deferred; //Object
598 function testWriteAPI_saveEverything_withCustomColorTypeGeneral(){
600 // Simple test of the save API with a non-atomic type (dojo.Color) that has a type mapping.
602 // Simple test of the save API with a non-atomic type (dojo.Color) that has a type mapping.
604 //Set up the store basics: What data it has, and what to do when save is called for saveEverything
605 //And how to map the 'Color' type in and out of the format.
606 //(Test of saving all to a some location...)
610 { name:'Kermit', species:'frog', color:{_type:'Color', _value:'green'} },
611 { name:'Beaker', hairColor:{_type:'Color', _value:'red'} }
615 var customTypeMap = {'Color': {
617 deserialize: function(value){
618 return new dojo.Color(value);
620 serialize: function(obj){
621 return obj.toString();
625 var store = new dojo.data.ItemFileWriteStore({
627 typeMap: customTypeMap
629 store._saveEverything = function(saveCompleteCallback, saveFailedCallback, newFileContentString){
630 //Now load the new data into a datastore and validate that it stored the Color right.
631 var dataset = dojo.fromJson(newFileContentString);
632 var newStore = new dojo.data.ItemFileWriteStore({data: dataset, typeMap: customTypeMap});
634 function gotItem(item){
635 var hairColor = newStore.getValue(item,"hairColor");
636 doh.assertTrue(hairColor instanceof dojo.Color);
637 doh.assertEqual("rgba(255, 255, 0, 1)", hairColor.toString());
638 saveCompleteCallback();
640 function failed(error, request){
641 deferred.errback(error);
642 saveFailedCallback();
644 newStore.fetchItemByIdentity({identity:"Animal", onItem:gotItem, onError:failed});
647 //Add a new item with a color type, then save it.
648 var deferred = new doh.Deferred();
649 function onError(error){
650 deferred.errback(error);
652 function onComplete() {
653 deferred.callback(true);
656 var animal = store.newItem({name: "Animal", hairColor: new dojo.Color("yellow")});
657 store.save({onComplete:onComplete, onError:onError});
658 return deferred; //Object
660 function testWriteAPI_newItem_revert(){
662 // Test for bug #5357. Ensure that the revert properly nulls the identity position
663 // for a new item after revert.
667 {name:'Ecuador', capital:'Quito'},
668 {name:'Egypt', capital:'Cairo'},
669 {name:'El Salvador', capital:'San Salvador'},
670 {name:'Equatorial Guinea', capital:'Malabo'},
671 {name:'Eritrea', capital:'Asmara'},
672 {name:'Estonia', capital:'Tallinn'},
673 {name:'Ethiopia', capital:'Addis Ababa'}
676 var store = new dojo.data.ItemFileWriteStore(args);
678 var newCountry = store.newItem({name: "Utopia", capitol: "Perfect"});
680 //DO NOT ACCESS THIS WAY. THESE ARE INTERNAL VARIABLES. DOING THIS FOR TEST PURPOSES.
681 var itemEntryNum = newCountry[store._itemNumPropName];
682 doh.assertTrue(store._arrayOfAllItems[itemEntryNum] === newCountry);
684 doh.assertTrue(store._arrayOfAllItems[itemEntryNum] === null);
686 function testNotificationAPI_onSet(){
688 // Simple test of the onSet API
690 // Simple test of the onSet API
691 var store = new dojo.data.ItemFileWriteStore(tests.data.readOnlyItemFileTestTemplates.getTestData("countries"));
693 var deferred = new doh.Deferred();
694 function onError(error){
695 deferred.errback(error);
697 function onItem(fetchedItem){
698 var egypt = fetchedItem;
699 var connectHandle = null;
700 function setValueHandler(item, attribute, oldValue, newValue){
701 doh.assertTrue(store.isItem(item));
702 doh.assertTrue(item == egypt);
703 doh.assertTrue(attribute == "capital");
704 doh.assertTrue(oldValue == "Cairo");
705 doh.assertTrue(newValue == "New Cairo");
706 deferred.callback(true);
707 dojo.disconnect(connectHandle);
709 connectHandle = dojo.connect(store, "onSet", setValueHandler);
710 store.setValue(egypt, "capital", "New Cairo");
712 store.fetchItemByIdentity({identity:"eg", onItem:onItem, onError:onError});
714 function testNotificationAPI_onNew(){
716 // Simple test of the onNew API
718 // Simple test of the onNew API
719 var store = new dojo.data.ItemFileWriteStore(tests.data.readOnlyItemFileTestTemplates.getTestData("countries"));
721 var deferred = new doh.Deferred();
722 var connectHandle = null;
723 function newItemHandler(item){
724 doh.assertTrue(store.isItem(item));
725 doh.assertTrue(store.getValue(item, "name") == "Canada");
726 deferred.callback(true);
727 dojo.disconnect(connectHandle);
729 connectHandle = dojo.connect(store, "onNew", newItemHandler);
730 var canada = store.newItem({name:"Canada", abbr:"ca", capital:"Ottawa"});
732 function testNotificationAPI_onDelete(){
734 // Simple test of the onDelete API
736 // Simple test of the onDelete API
737 var store = new dojo.data.ItemFileWriteStore(tests.data.readOnlyItemFileTestTemplates.getTestData("countries"));
739 var deferred = new doh.Deferred();
740 function onError(error){
741 deferred.errback(error);
743 function onItem(fetchedItem){
744 var egypt = fetchedItem;
745 var connectHandle = null;
746 function deleteItemHandler(item){
747 doh.assertTrue(store.isItem(item) == false);
748 doh.assertTrue(item == egypt);
749 deferred.callback(true);
750 dojo.disconnect(connectHandle);
752 connectHandle = dojo.connect(store, "onDelete", deleteItemHandler);
753 store.deleteItem(egypt);
755 store.fetchItemByIdentity({identity:"eg", onItem:onItem, onError:onError});
757 function testReadAPI_functionConformanceToo(){
759 // Simple test read API conformance. Checks to see all declared functions are actual functions on the instances.
761 // Simple test read API conformance. Checks to see all declared functions are actual functions on the instances.
762 var testStore = new dojo.data.ItemFileWriteStore(tests.data.readOnlyItemFileTestTemplates.getTestData("countries"));
763 var readApi = new dojo.data.api.Read();
766 for(var functionName in readApi){
767 var member = readApi[functionName];
768 //Check that all the 'Read' defined functions exist on the test store.
769 if(typeof member === "function"){
770 var testStoreMember = testStore[functionName];
771 if(!(typeof testStoreMember === "function")){
777 doh.assertTrue(passed);
779 function testWriteAPI_functionConformance(){
781 // Simple test write API conformance. Checks to see all declared functions are actual functions on the instances.
783 // Simple test write API conformance. Checks to see all declared functions are actual functions on the instances.
784 var testStore = new dojo.data.ItemFileWriteStore(tests.data.readOnlyItemFileTestTemplates.getTestData("countries"));
785 var writeApi = new dojo.data.api.Write();
788 for(var functionName in writeApi){
789 var member = writeApi[functionName];
790 //Check that all the 'Write' defined functions exist on the test store.
791 if(typeof member === "function"){
792 var testStoreMember = testStore[functionName];
793 if(!(typeof testStoreMember === "function")){
799 doh.assertTrue(passed);
801 function testNotificationAPI_functionConformance(){
803 // Simple test Notification API conformance. Checks to see all declared functions are actual functions on the instances.
805 // Simple test Notification API conformance. Checks to see all declared functions are actual functions on the instances.
806 var testStore = new dojo.data.ItemFileWriteStore(tests.data.readOnlyItemFileTestTemplates.getTestData("countries"));
807 var api = new dojo.data.api.Notification();
810 for(var functionName in api){
811 var member = api[functionName];
812 //Check that all the 'Write' defined functions exist on the test store.
813 if(typeof member === "function"){
814 var testStoreMember = testStore[functionName];
815 if(!(typeof testStoreMember === "function")){
821 doh.assertTrue(passed);
823 function testIdentityAPI_noIdentifierSpecified(){
825 // Test for bug #3873. Given a datafile that does not specify an
826 // identifier, make sure ItemFileWriteStore auto-creates identities
827 // that are unique even after calls to deleteItem() and newItem()
831 {name:'Ecuador', capital:'Quito'},
832 {name:'Egypt', capital:'Cairo'},
833 {name:'El Salvador', capital:'San Salvador'},
834 {name:'Equatorial Guinea', capital:'Malabo'},
835 {name:'Eritrea', capital:'Asmara'},
836 {name:'Estonia', capital:'Tallinn'},
837 {name:'Ethiopia', capital:'Addis Ababa'}
840 var store = new dojo.data.ItemFileWriteStore(args);
841 var deferred = new doh.Deferred();
843 var onError = function(error, request){
844 deferred.errback(error);
846 var onComplete = function(items, request){
847 doh.assertEqual(7, items.length);
849 var lastItem = items[(items.length - 1)];
850 var idOfLastItem = store.getIdentity(lastItem);
851 store.deleteItem(lastItem);
852 store.newItem({name:'Canada', capital:'Ottawa'});
854 var onCompleteAgain = function(itemsAgain, requestAgain){
855 doh.assertEqual(7, itemsAgain.length);
856 var identitiesInUse = {};
857 for(var i = 0; i < itemsAgain.length; ++i){
858 var item = itemsAgain[i];
859 var id = store.getIdentity(item);
860 if(identitiesInUse.hasOwnProperty(id)){
861 // there should not already be an entry for this id
862 doh.assertTrue(false);
864 // we want to add the entry now
865 identitiesInUse[id] = item;
868 deferred.callback(true);
870 store.fetch({onComplete:onCompleteAgain, onError:onError});
873 store.fetch({onComplete:onComplete, onError:onError});
876 function testIdentityAPI_noIdentifierSpecified_revert(){
878 // Test for bug #4691 Given a datafile that does not specify an
879 // identifier, make sure ItemFileWriteStore auto-creates identities
880 // that are unique even after calls to deleteItem() and newItem()
884 {name:'Ecuador', capital:'Quito'},
885 {name:'Egypt', capital:'Cairo'},
886 {name:'El Salvador', capital:'San Salvador'},
887 {name:'Equatorial Guinea', capital:'Malabo'},
888 {name:'Eritrea', capital:'Asmara'},
889 {name:'Estonia', capital:'Tallinn'},
890 {name:'Ethiopia', capital:'Addis Ababa'}
893 var store = new dojo.data.ItemFileWriteStore(args);
894 var deferred = new doh.Deferred();
896 var onError = function(error, request){
897 deferred.errback(error);
899 var onComplete = function(items, request){
900 doh.assertEqual(7, items.length);
902 var lastItem = items[(items.length - 1)];
903 var idOfLastItem = store.getIdentity(lastItem);
904 store.deleteItem(lastItem);
905 store.newItem({name:'Canada', capital:'Ottawa'});
907 var onCompleteAgain = function(itemsAgain, requestAgain){
908 doh.assertEqual(7, itemsAgain.length);
909 var identitiesInUse = {};
910 for(var i = 0; i < itemsAgain.length; ++i){
911 var item = itemsAgain[i];
912 var id = store.getIdentity(item);
913 if(identitiesInUse.hasOwnProperty(id)){
914 // there should not already be an entry for this id
915 doh.assertTrue(false);
917 // we want to add the entry now
918 identitiesInUse[id] = item;
921 //Last test, revert everything and check item sizes.
924 //Now call fetch again and verify store state.
925 var revertComplete = function(itemsReverted, request){
926 doh.assertEqual(7, itemsReverted.length);
927 deferred.callback(true);
929 store.fetch({onComplete:revertComplete, onError:onError});
931 store.fetch({onComplete:onCompleteAgain, onError:onError});
933 store.fetch({onComplete:onComplete, onError:onError});
936 function testReferenceIntegrity_checkReferences(){
938 // Simple test to verify the references were properly resolved.
940 // Simple test to verify the references were properly resolved.
942 var store = new dojo.data.ItemFileWriteStore(tests.data.ItemFileWriteStore.getTestData("reference_integrity"));
944 var deferred = new doh.Deferred();
945 function onError(error, request){
946 deferred.errback(error);
948 function onComplete(items, request){
955 for (var i = 0; i < items.length; i++) {
956 var ident = store.getIdentity(items[i]);
959 }else if (ident === 1) {
961 }else if (ident === 3) {
963 }else if (ident === 5) {
967 var friends = store.getValues(item10, "friends");
968 doh.assertTrue(friends !== null);
969 doh.assertTrue(friends !== undefined);
971 doh.assertTrue(store.isItem(item10));
972 doh.assertTrue(store.isItem(item1));
973 doh.assertTrue(store.isItem(item3));
974 doh.assertTrue(store.isItem(item5));
977 for (var i = 0; i < friends.length; i++) {
979 doh.assertTrue(store.isItem(friends[i]));
980 doh.assertEqual(friends[i], item1);
981 doh.assertEqual(store.getIdentity(friends[i]), 1);
984 doh.assertTrue(store.isItem(friends[i]));
985 doh.assertEqual(friends[i], item3);
986 doh.assertEqual(store.getIdentity(friends[i]), 3);
989 doh.assertTrue(store.isItem(friends[i]));
990 doh.assertEqual(friends[i], item5);
991 doh.assertEqual(store.getIdentity(friends[i]), 5);
998 doh.assertEqual(3, found);
999 deferred.callback(true);
1001 store.fetch({onError: onError, onComplete: onComplete});
1004 function testReferenceIntegrity_deleteReferencedItem(){
1006 // Simple test to verify the references were properly deleted.
1008 // Simple test to verify the references were properly deleted.
1010 var store = new dojo.data.ItemFileWriteStore(tests.data.ItemFileWriteStore.getTestData("reference_integrity"));
1012 var deferred = new doh.Deferred();
1014 function onError(error, request){
1015 deferred.errback(error);
1017 function onItem(item, request){
1019 console.log("Before delete map state is: " + dojo.toJson(item[store._reverseRefMap]));
1020 store.deleteItem(item);
1021 console.log("After delete map state is: " + dojo.toJson(item[store._reverseRefMap]));
1022 function verifyRefDelete(items, request){
1024 for(var i = 0; i < items.length; i++){
1025 var curItem = items[i];
1026 var attributes = store.getAttributes(curItem);
1027 for(var j = 0; j < attributes.length; j++){
1028 var values = store.getValues(curItem, attributes[j]);
1030 for(var k = 0; k < values.length; k++){
1031 var value = values[k];
1033 var id = store.getIdentity(value);
1038 }catch(e){/*Not an item, even a dead one, just eat it.*/}
1041 deferred.errback(new Error("Found a reference remaining to a deleted item. Failure."));
1048 deferred.callback(true);
1051 store.fetch({onComplete: verifyRefDelete, onError: onError});
1053 deferred.errback(error);
1056 store.fetchItemByIdentity({identity: 10, onError: onError, onItem: onItem});
1059 function testReferenceIntegrity_deleteReferencedItemThenRevert(){
1061 // Simple test to verify the references were properly deleted.
1063 // Simple test to verify the references were properly deleted.
1065 var store = new dojo.data.ItemFileWriteStore(tests.data.ItemFileWriteStore.getTestData("reference_integrity"));
1067 var deferred = new doh.Deferred();
1069 function onError(error, request){
1070 deferred.errback(error);
1072 function onItem(item, request){
1074 //DO NOT EVER ACCESS THESE VARIABLES LIKE THIS!
1075 //THIS IS FOR TESTING INTERNAL STATE!
1076 console.log("Map before delete:");
1077 store._dumpReferenceMap();
1078 var beforeDelete = dojo.toJson(item[store._reverseRefMap]);
1079 store.deleteItem(item);
1080 console.log("Map after delete:");
1081 store._dumpReferenceMap();
1082 var afterDelete = dojo.toJson(item[store._reverseRefMap]);
1084 console.log("Map after revert:");
1085 store._dumpReferenceMap();
1086 var afterRevert = dojo.toJson(item[store._reverseRefMap]);
1087 doh.assertTrue(afterRevert === beforeDelete);
1089 deferred.errback(e);
1093 deferred.callback(true);
1096 store.fetchItemByIdentity({identity: 10, onError: onError, onItem: onItem});
1099 function testReferenceIntegrity_deleteMultipleItemsWithReferencesAndRevert(){
1101 // Simple test to verify that a flow of deleting items with references and reverting does not damage the internal structure.
1102 // Created for tracker bug: #5743
1104 // Simple test to verify that a flow of deleting items with references and reverting does not damage the internal structure.
1105 // Created for tracker bug: #5743
1107 var store = new dojo.data.ItemFileWriteStore(tests.data.readOnlyItemFileTestTemplates.getTestData("countries_references"));
1109 var deferred = new doh.Deferred();
1111 function onError(error, request){
1112 deferred.errback(error);
1113 doh.assertTrue(false);
1115 function onItem(item, request){
1116 //Save off the located item, then locate another one (peer to Egypt)
1117 doh.assertTrue(store.isItem(item));
1120 function onItem2(item, request){
1121 doh.assertTrue(store.isItem(item));
1125 store.deleteItem(egypt);
1126 store.deleteItem(nairobi);
1128 //Revert, then do a fetch. If the internals have been damaged, this will generally
1129 //cause onError to fire instead of onComplete.
1131 function onComplete(items, request){
1132 deferred.callback(true);
1134 store.fetch({query: {name: "*"}, start: 0, count: 20, onComplete: onComplete, onError: onError});
1139 store.fetchItemByIdentity({identity: "Nairobi", onError: onError, onItem: onItem2});
1141 store.fetchItemByIdentity({identity: "Egypt", onError: onError, onItem: onItem});
1144 function testReferenceIntegrity_removeReferenceFromAttribute(){
1146 // Simple test to verify the reference removal updates the internal map.
1148 // Simple test to verify the reference removal updates the internal map.
1150 var store = new dojo.data.ItemFileWriteStore(tests.data.ItemFileWriteStore.getTestData("reference_integrity"));
1152 var deferred = new doh.Deferred();
1154 function onError(error, request){
1155 deferred.errback(error);
1156 doh.assertTrue(false);
1158 function onItem(item, request){
1160 store.setValues(item, "friends", [null]);
1162 function onItem2(item10, request){
1163 //DO NOT EVER ACCESS THESE VARIABLES LIKE THIS!
1164 //THIS IS FOR TESTING INTERNAL STATE!
1165 var refMap = item10[store._reverseRefMap];
1166 store._dumpReferenceMap();
1168 console.log("MAP for Item 10 is: " + dojo.toJson(refMap));
1170 //Assert there is no reference to item 10 in item 11's attribute 'friends'.
1171 doh.assertTrue(!refMap["11"]["friends"]);
1172 store.setValues(item, "siblings", [0, 1, 2]);
1173 //Assert there are no more references to 10 in 11. Ergo, "11" should be a 'undefined' attribute for the map of items referencing '10'..
1174 doh.assertTrue(!refMap["11"]);
1175 deferred.callback(true);
1177 store.fetchItemByIdentity({identity: 10, onError: onError, onItem: onItem2});
1181 deferred.errback(e);
1182 doh.assertTrue(false);
1185 store.fetchItemByIdentity({identity: 11, onError: onError, onItem: onItem});
1188 function testReferenceIntegrity_deleteReferencedItemNonParent(){
1190 // Simple test to verify the references to a non-parent item was properly deleted.
1192 // Simple test to verify the references to a non-parent item was properly deleted.
1194 var store = new dojo.data.ItemFileWriteStore(tests.data.ItemFileWriteStore.getTestData("reference_integrity"));
1196 var deferred = new doh.Deferred();
1198 function onError(error, request){
1199 deferred.errback(error);
1201 function onItem(item, request){
1203 console.log("Reference state for item 16 is: " + dojo.toJson(item[store._reverseRefMap]));
1204 store.deleteItem(item);
1205 function verifyRefDelete(items, request){
1207 for(var i = 0; i < items.length; i++){
1208 var curItem = items[i];
1209 var attributes = store.getAttributes(curItem);
1210 for(var j = 0; j < attributes.length; j++){
1211 var values = store.getValues(curItem, attributes[j]);
1213 for(var k = 0; k < values.length; k++){
1214 var value = values[k];
1216 var id = store.getIdentity(value);
1221 }catch(e){/*Not an item, even a dead one, just eat it.*/}
1224 deferred.errback(new Error("Found a reference remaining to a deleted item. Failure."));
1231 deferred.callback(true);
1234 store.fetch({onComplete: verifyRefDelete, onError: onError});
1236 deferred.errback(error);
1239 store.fetchItemByIdentity({identity: 16, onError: onError, onItem: onItem});
1242 function testReferenceIntegrity_addReferenceToAttribute(){
1244 // Simple test to verify the reference additions can happen.
1246 // Simple test to verify the reference additions can happen.
1248 var store = new dojo.data.ItemFileWriteStore(tests.data.ItemFileWriteStore.getTestData("reference_integrity"));
1250 var deferred = new doh.Deferred();
1252 function onError(error, request){
1253 deferred.errback(error);
1254 doh.assertTrue(false);
1256 function onComplete(items, request){
1258 doh.assertTrue(items.length > 2);
1260 var item1 = items[0];
1261 var item2 = items[1];
1263 //DO NOT EVER ACCESS THESE VARIABLES LIKE THIS!
1264 //THIS IS FOR TESTING INTERNAL STATE!
1265 console.log("Map state for Item 1 is: " + dojo.toJson(item1[store._reverseRefMap]));
1266 console.log("Map state for Item 2 is: " + dojo.toJson(item2[store._reverseRefMap]));
1268 store.setValue(item1, "siblings", item2);
1270 //Emit the current map state for inspection.
1271 console.log("Map state for Item 1 is: " + dojo.toJson(item1[store._reverseRefMap]));
1272 console.log("Map state for Item 2 is: " + dojo.toJson(item2[store._reverseRefMap]));
1274 doh.assertTrue(item2[store._reverseRefMap] != null);
1276 //Assert there is a recorded reference to item 2 in item 1's attribute 'sibling'.
1277 doh.assertTrue(item2[store._reverseRefMap][store.getIdentity(item1)]["siblings"]);
1279 deferred.callback(true);
1281 store.fetch({onError: onError, onComplete: onComplete});
1284 function testReferenceIntegrity_newItemWithParentReference(){
1286 // Simple test to verify that newItems with a parent properly record the parent's reference in the map.
1288 // Simple test to verify that newItems with a parent properly record the parent's reference in the map.
1290 var store = new dojo.data.ItemFileWriteStore(tests.data.ItemFileWriteStore.getTestData("reference_integrity"));
1292 var deferred = new doh.Deferred();
1294 function onError(error, request){
1295 deferred.errback(error);
1296 doh.assertTrue(false);
1298 function onItem(item, request){
1300 //Create a new item and set its parent to item 10's uncle attribute.
1301 var newItem = store.newItem({id: 17, name: "Item 17"}, {parent: item, attribute: "uncles"});
1303 //DO NOT EVER ACCESS THESE VARIABLES LIKE THIS!
1304 //THIS IS FOR TESTING INTERNAL STATE!
1305 //Look up the references to 17, as item 10 has one now on attribute 'uncles'
1306 var refs = newItem[store._reverseRefMap];
1308 //Assert there is a reference from 10 to item 17, on attribute uncle
1309 doh.assertTrue(refs["10"]["uncles"]);
1311 console.log("State of map of item 17 after newItem: " + dojo.toJson(refs));
1314 deferred.errback(e);
1315 doh.assertTrue(false);
1319 deferred.callback(true);
1322 store.fetchItemByIdentity({identity: 10, onError: onError, onItem: onItem});
1325 function testReferenceIntegrity_newItemWithReferenceToExistingItem(){
1327 // Simple test to verify that a new item with references to existing items properly record the references in the map.
1329 // Simple test to verify that a new item with references to existing items properly record the references in the map.
1331 var store = new dojo.data.ItemFileWriteStore(tests.data.ItemFileWriteStore.getTestData("reference_integrity"));
1333 var deferred = new doh.Deferred();
1335 function onError(error, request){
1336 deferred.errback(error);
1337 doh.assertTrue(false);
1339 function onItem(item, request){
1341 //DO NOT EVER ACCESS THESE VARIABLES LIKE THIS!
1342 //THIS IS FOR TESTING INTERNAL STATE!
1343 console.log("State of reference map to item 10 before newItem: " + dojo.toJson(item[store._reverseRefMap]));
1345 //Create a new item and set its parent to item 10's uncle attribute.
1346 var newItem = store.newItem({id: 17, name: "Item 17", friends: [item]});
1348 //DO NOT EVER ACCESS THESE VARIABLES LIKE THIS!
1349 //THIS IS FOR TESTING INTERNAL STATE!
1350 //Look up the references to 10, as item 17 has one on friends now.
1351 var refs = item[store._reverseRefMap];
1353 //Assert there is a reference from 15 to item 10, on attribute friends
1354 doh.assertTrue(refs["17"]["friends"]);
1356 console.log("State of reference map to item 10 after newItem: " + dojo.toJson(refs));
1359 deferred.errback(e);
1360 doh.assertTrue(false);
1364 deferred.callback(true);
1367 store.fetchItemByIdentity({identity: 10, onError: onError, onItem: onItem});
1370 function testReferenceIntegrity_disableReferenceIntegrity(){
1372 // Simple test to verify reference integrity can be disabled.
1374 // Simple test to verify reference integrity can be disabled.
1376 var params = tests.data.ItemFileWriteStore.getTestData("reference_integrity");
1377 params.referenceIntegrity = false;
1378 var store = new dojo.data.ItemFileWriteStore(params);
1380 var deferred = new doh.Deferred();
1381 function onError(error, request){
1382 deferred.errback(error);
1383 doh.assertTrue(false);
1385 function onItem(item, request){
1386 //DO NOT EVER ACCESS THESE VARIABLES LIKE THIS!
1387 //THIS IS FOR TESTING INTERNAL STATE!
1388 if(item[store._reverseRefMap] === undefined){
1389 deferred.callback(true);
1391 deferred.errback(new Error("Disabling of reference integrity failed."));
1394 store.fetchItemByIdentity({identity: 10, onError: onError, onItem: onItem});