sproutcore 1.11.0.rc2 → 1.11.0.rc3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (104) hide show
  1. checksums.yaml +8 -8
  2. data/CHANGELOG +10 -0
  3. data/VERSION.yml +1 -1
  4. data/lib/frameworks/sproutcore/CHANGELOG.md +114 -1
  5. data/lib/frameworks/sproutcore/apps/showcase/views/views_item_view.js +1 -7
  6. data/lib/frameworks/sproutcore/apps/showcase/views/views_list_view.js +9 -9
  7. data/lib/frameworks/sproutcore/frameworks/ajax/system/request.js +167 -5
  8. data/lib/frameworks/sproutcore/frameworks/ajax/system/response.js +24 -8
  9. data/lib/frameworks/sproutcore/frameworks/core_foundation/child_view_layouts/stack_layout.js +737 -0
  10. data/lib/frameworks/sproutcore/frameworks/core_foundation/panes/layout.js +0 -6
  11. data/lib/frameworks/sproutcore/frameworks/core_foundation/panes/pane.js +11 -7
  12. data/lib/frameworks/sproutcore/frameworks/core_foundation/panes/pane_statechart.js +7 -11
  13. data/lib/frameworks/sproutcore/frameworks/core_foundation/protocols/child_view_layout_protocol.js +8 -3
  14. data/lib/frameworks/sproutcore/frameworks/core_foundation/protocols/observable_protocol.js +9 -6
  15. data/lib/frameworks/sproutcore/frameworks/{desktop/protocols/responder.js → core_foundation/protocols/responder_protocol.js} +83 -17
  16. data/lib/frameworks/sproutcore/frameworks/core_foundation/protocols/{sparse_array_delegate.js → sparse_array_delegate_protocol.js} +11 -7
  17. data/lib/frameworks/sproutcore/frameworks/core_foundation/protocols/view_transition_protocol.js +11 -6
  18. data/lib/frameworks/sproutcore/frameworks/core_foundation/system/color.js +2 -2
  19. data/lib/frameworks/sproutcore/frameworks/core_foundation/system/page.js +0 -22
  20. data/lib/frameworks/sproutcore/frameworks/core_foundation/system/root_responder.js +61 -56
  21. data/lib/frameworks/sproutcore/frameworks/core_foundation/tests/views/main_pane.js +2 -2
  22. data/lib/frameworks/sproutcore/frameworks/core_foundation/tests/views/pane/append_remove.js +3 -3
  23. data/lib/frameworks/sproutcore/frameworks/core_foundation/tests/views/view/animation.js +63 -39
  24. data/lib/frameworks/sproutcore/frameworks/core_foundation/tests/views/view/border_frame_test.js +28 -28
  25. data/lib/frameworks/sproutcore/frameworks/core_foundation/tests/views/view/createLayer.js +10 -4
  26. data/lib/frameworks/sproutcore/frameworks/core_foundation/tests/views/view/layout.js +102 -1
  27. data/lib/frameworks/sproutcore/frameworks/core_foundation/tests/views/view/layoutDidChange.js +4 -4
  28. data/lib/frameworks/sproutcore/frameworks/core_foundation/tests/views/view/layoutStyle.js +103 -103
  29. data/lib/frameworks/sproutcore/frameworks/core_foundation/tests/views/view/replaceAllChildren_test.js +1 -1
  30. data/lib/frameworks/sproutcore/frameworks/core_foundation/tests/views/view/view.js +77 -1
  31. data/lib/frameworks/sproutcore/frameworks/core_foundation/tests/views/view/view_states_test.js +18 -17
  32. data/lib/frameworks/sproutcore/frameworks/core_foundation/views/view.js +42 -49
  33. data/lib/frameworks/sproutcore/frameworks/core_foundation/views/view/animation.js +5 -6
  34. data/lib/frameworks/sproutcore/frameworks/core_foundation/views/view/enabled.js +16 -5
  35. data/lib/frameworks/sproutcore/frameworks/core_foundation/views/view/layout.js +241 -102
  36. data/lib/frameworks/sproutcore/frameworks/core_foundation/views/view/layout_style.js +1 -4
  37. data/lib/frameworks/sproutcore/frameworks/core_foundation/views/view/manipulation.js +0 -11
  38. data/lib/frameworks/sproutcore/frameworks/core_foundation/views/view/statechart.js +993 -610
  39. data/lib/frameworks/sproutcore/frameworks/core_foundation/views/view/theming.js +3 -2
  40. data/lib/frameworks/sproutcore/frameworks/datastore/data_sources/data_source.js +6 -11
  41. data/lib/frameworks/sproutcore/frameworks/datastore/system/nested_store.js +94 -27
  42. data/lib/frameworks/sproutcore/frameworks/datastore/system/query.js +133 -53
  43. data/lib/frameworks/sproutcore/frameworks/datastore/system/store.js +30 -35
  44. data/lib/frameworks/sproutcore/frameworks/datastore/tests/models/record/writeAttribute.js +3 -2
  45. data/lib/frameworks/sproutcore/frameworks/datastore/tests/system/nested_store/writeDataHash.js +73 -29
  46. data/lib/frameworks/sproutcore/frameworks/datastore/tests/system/store/conflictedStoreKeys_test.js +156 -0
  47. data/lib/frameworks/sproutcore/frameworks/datastore/tests/system/store/dataSourceCallbacks.js +61 -37
  48. data/lib/frameworks/sproutcore/frameworks/datastore/tests/system/store/find.js +2 -2
  49. data/lib/frameworks/sproutcore/frameworks/datetime/frameworks/core/system/datetime.js +68 -39
  50. data/lib/frameworks/sproutcore/frameworks/designer/tests/coders/page.js +1 -2
  51. data/lib/frameworks/sproutcore/frameworks/desktop/panes/panel.js +8 -6
  52. data/lib/frameworks/sproutcore/frameworks/desktop/panes/picker.js +80 -14
  53. data/lib/frameworks/sproutcore/frameworks/desktop/panes/sheet.js +2 -2
  54. data/lib/frameworks/sproutcore/frameworks/desktop/protocols/{drag_data_source.js → drag_data_source_protocol.js} +16 -10
  55. data/lib/frameworks/sproutcore/frameworks/desktop/protocols/{drag_source.js → drag_source_protocol.js} +28 -26
  56. data/lib/frameworks/sproutcore/frameworks/desktop/protocols/{drop_target.js → drop_target_protocol.js} +73 -75
  57. data/lib/frameworks/sproutcore/frameworks/desktop/system/drag.js +4 -4
  58. data/lib/frameworks/sproutcore/frameworks/desktop/tests/panes/panel/ui.js +39 -23
  59. data/lib/frameworks/sproutcore/frameworks/desktop/tests/views/collection/mouse.js +120 -97
  60. data/lib/frameworks/sproutcore/frameworks/desktop/tests/views/list/rowSizeForContentIndex.js +26 -25
  61. data/lib/frameworks/sproutcore/frameworks/desktop/tests/views/scroll/ui.js +3 -3
  62. data/lib/frameworks/sproutcore/frameworks/desktop/tests/views/segmented/ui.js +5 -0
  63. data/lib/frameworks/sproutcore/frameworks/desktop/tests/views/split/{dividers.js → dividers_test.js} +38 -38
  64. data/lib/frameworks/sproutcore/frameworks/desktop/views/collection.js +29 -14
  65. data/lib/frameworks/sproutcore/frameworks/desktop/views/menu_scroll.js +2 -1
  66. data/lib/frameworks/sproutcore/frameworks/desktop/views/scroll_view.js +13 -18
  67. data/lib/frameworks/sproutcore/frameworks/desktop/views/segmented.js +41 -35
  68. data/lib/frameworks/sproutcore/frameworks/desktop/views/slider.js +14 -14
  69. data/lib/frameworks/sproutcore/frameworks/desktop/views/split.js +41 -26
  70. data/lib/frameworks/sproutcore/frameworks/desktop/views/static_content.js +2 -12
  71. data/lib/frameworks/sproutcore/frameworks/foundation/gestures/tap.js +2 -2
  72. data/lib/frameworks/sproutcore/frameworks/foundation/mixins/auto_resize.js +14 -10
  73. data/lib/frameworks/sproutcore/frameworks/foundation/mixins/gesturable.js +104 -63
  74. data/lib/frameworks/sproutcore/frameworks/foundation/protocols/swap_transition_protocol.js +9 -4
  75. data/lib/frameworks/sproutcore/frameworks/foundation/tests/mixins/auto_mixin_tests.js +1 -2
  76. data/lib/frameworks/sproutcore/frameworks/foundation/tests/mixins/auto_resize_test.js +33 -33
  77. data/lib/frameworks/sproutcore/frameworks/foundation/tests/transitions/view_transitions_test.js +5 -5
  78. data/lib/frameworks/sproutcore/frameworks/foundation/tests/views/container/methods.js +0 -4
  79. data/lib/frameworks/sproutcore/frameworks/foundation/tests/views/container/transition_test.js +0 -4
  80. data/lib/frameworks/sproutcore/frameworks/foundation/tests/views/container/ui.js +0 -2
  81. data/lib/frameworks/sproutcore/frameworks/foundation/views/text_field.js +12 -8
  82. data/lib/frameworks/sproutcore/frameworks/media/resources/silence.mp3 +0 -0
  83. data/lib/frameworks/sproutcore/frameworks/media/tests/audio.js +69 -0
  84. data/lib/frameworks/sproutcore/frameworks/media/views/audio.js +1 -0
  85. data/lib/frameworks/sproutcore/frameworks/runtime/core.js +2 -2
  86. data/lib/frameworks/sproutcore/frameworks/runtime/mixins/observable.js +11 -4
  87. data/lib/frameworks/sproutcore/frameworks/runtime/protocols/mixin_protocol.js +150 -0
  88. data/lib/frameworks/sproutcore/frameworks/runtime/system/binding.js +447 -137
  89. data/lib/frameworks/sproutcore/frameworks/runtime/system/object.js +9 -15
  90. data/lib/frameworks/sproutcore/frameworks/runtime/system/set.js +19 -17
  91. data/lib/frameworks/sproutcore/frameworks/runtime/tests/system/binding.js +188 -16
  92. data/lib/frameworks/sproutcore/frameworks/statechart/system/state.js +1 -1
  93. data/lib/frameworks/sproutcore/frameworks/template_view/panes/template.js +0 -3
  94. data/lib/frameworks/sproutcore/frameworks/template_view/tests/panes/template.js +0 -17
  95. data/lib/frameworks/sproutcore/frameworks/template_view/tests/views/template/collection.js +43 -26
  96. data/lib/frameworks/sproutcore/frameworks/template_view/views/bindable_span.js +9 -2
  97. data/lib/frameworks/sproutcore/themes/ace/resources/collection/normal/list.css +0 -1
  98. data/lib/frameworks/sproutcore/themes/ace/resources/scroll/scroll.css +3 -0
  99. data/sproutcore.gemspec +3 -3
  100. metadata +19 -17
  101. data/lib/frameworks/sproutcore/frameworks/core_foundation/child_view_layouts/horizontal_stack_layout.js +0 -465
  102. data/lib/frameworks/sproutcore/frameworks/core_foundation/child_view_layouts/vertical_stack_layout.js +0 -472
  103. data/lib/frameworks/sproutcore/frameworks/core_foundation/tests/views/view/build.js +0 -87
  104. data/lib/frameworks/sproutcore/frameworks/core_foundation/tests/views/view/build_children.js +0 -89
@@ -444,6 +444,19 @@ SC.Store = SC.Object.extend( /** @scope SC.Store.prototype */ {
444
444
  if (!editables) editables = this.editables = [];
445
445
  editables[storeKey] = 1 ; // use number for dense array support
446
446
 
447
+ // propagate the data to the child records
448
+ this._updateChildRecordHashes(storeKey, hash, status);
449
+
450
+ return this ;
451
+ },
452
+
453
+ /** @private
454
+
455
+ Called by writeDataHash to update the child record hashes starting from the new (parent) data hash.
456
+
457
+ @returns {SC.Store} receiver
458
+ */
459
+ _updateChildRecordHashes: function(storeKey, hash, status) {
447
460
  var processedPaths={};
448
461
  // Update the child record hashes in place.
449
462
  if (!SC.none(this.parentRecords) ) {
@@ -485,8 +498,6 @@ SC.Store = SC.Object.extend( /** @scope SC.Store.prototype */ {
485
498
  }
486
499
  }
487
500
  }
488
-
489
- return this ;
490
501
  },
491
502
 
492
503
  /**
@@ -798,9 +809,11 @@ SC.Store = SC.Object.extend( /** @scope SC.Store.prototype */ {
798
809
  @param {Boolean} force
799
810
  @returns {SC.Store} receiver
800
811
  */
801
- commitChangesFromNestedStore: function(nestedStore, changes, force) {
812
+ commitChangesFromNestedStore: function (nestedStore, changes, force) {
802
813
  // first, check for optimistic locking problems
803
- if (!force) this._verifyLockRevisions(changes, nestedStore.locks);
814
+ if (!force && nestedStore.get('conflictedStoreKeys')) {
815
+ throw SC.Store.CHAIN_CONFLICT_ERROR;
816
+ }
804
817
 
805
818
  // OK, no locking issues. So let's just copy them changes.
806
819
  // get local reference to values.
@@ -853,32 +866,6 @@ SC.Store = SC.Object.extend( /** @scope SC.Store.prototype */ {
853
866
  return this ;
854
867
  },
855
868
 
856
- /** @private
857
- Verifies that the passed lock revisions match the current revisions
858
- in the receiver store. If the lock revisions do not match, then the
859
- store is in a conflict and an exception will be raised.
860
-
861
- @param {Array} changes set of changes we are trying to apply
862
- @param {SC.Set} locks the locks to verify
863
- @returns {SC.Store} receiver
864
- */
865
- _verifyLockRevisions: function(changes, locks) {
866
- var len = changes.length, revs = this.revisions, i, storeKey, lock, rev ;
867
- if (locks && revs) {
868
- for(i=0;i<len;i++) {
869
- storeKey = changes[i];
870
- lock = locks[storeKey] || 1;
871
- rev = revs[storeKey] || 1;
872
-
873
- // if the save revision for the item does not match the current rev
874
- // the someone has changed the data hash in this store and we have
875
- // a conflict.
876
- if (lock < rev) throw SC.Store.CHAIN_CONFLICT_ERROR;
877
- }
878
- }
879
- return this ;
880
- },
881
-
882
869
  // ..........................................................
883
870
  // HIGH-LEVEL RECORD API
884
871
  //
@@ -2373,11 +2360,11 @@ SC.Store = SC.Object.extend( /** @scope SC.Store.prototype */ {
2373
2360
  // otherwise, determine proper state transition
2374
2361
  if(status === K.BUSY_DESTROYING) {
2375
2362
  throw K.BAD_STATE_ERROR ;
2376
- } else status = K.READY_CLEAN ;
2363
+ } else status = K.READY_CLEAN;
2377
2364
 
2378
- this.writeStatus(storeKey, status) ;
2379
- if (dataHash) this.writeDataHash(storeKey, dataHash, status) ;
2380
- if (newId) SC.Store.replaceIdFor(storeKey, newId);
2365
+ this.writeStatus(storeKey, status);
2366
+ if (dataHash) this.writeDataHash(storeKey, dataHash, status);
2367
+ if (newId) { SC.Store.replaceIdFor(storeKey, newId); }
2381
2368
 
2382
2369
  statusOnly = dataHash || newId ? NO : YES;
2383
2370
  this.dataHashDidChange(storeKey, null, statusOnly);
@@ -2385,6 +2372,8 @@ SC.Store = SC.Object.extend( /** @scope SC.Store.prototype */ {
2385
2372
  // Force record to refresh its cached properties based on store key
2386
2373
  var record = this.materializeRecord(storeKey);
2387
2374
  if (record !== null) {
2375
+ // If the record's id property has been computed, ensure that it re-computes.
2376
+ if (newId) { record.propertyDidChange('id'); }
2388
2377
  record.notifyPropertyChange('status');
2389
2378
  }
2390
2379
  //update callbacks
@@ -2487,7 +2476,13 @@ SC.Store = SC.Object.extend( /** @scope SC.Store.prototype */ {
2487
2476
  if(dataHash === undefined) this.writeStatus(storeKey, status) ;
2488
2477
  else this.writeDataHash(storeKey, dataHash, status) ;
2489
2478
 
2490
- if (id && this.idFor(storeKey) !== id) SC.Store.replaceIdFor(storeKey, id);
2479
+ if (id && this.idFor(storeKey) !== id) {
2480
+ SC.Store.replaceIdFor(storeKey, id);
2481
+
2482
+ // If the record's id property has been computed, ensure that it re-computes.
2483
+ var record = this.materializeRecord(storeKey);
2484
+ record.propertyDidChange('id');
2485
+ }
2491
2486
  this.dataHashDidChange(storeKey);
2492
2487
 
2493
2488
  return storeKey;
@@ -3,7 +3,7 @@
3
3
  // Copyright: ©2006-2011 Apple Inc. and contributors.
4
4
  // License: Licensed under MIT license (see license.js)
5
5
  // ==========================================================================
6
- /*globals module ok equals same test MyApp */
6
+ /*globals module, ok, equals, same, test */
7
7
 
8
8
  var store, Foo, json, foo ;
9
9
  module("SC.Record#writeAttribute", {
@@ -108,10 +108,11 @@ test("Writing a new guid", function(){
108
108
  });
109
109
 
110
110
  test("Writing primaryKey of 'id'", function(){
111
- PrimaryKeyId = SC.Record.extend({ primaryKey: 'id' });
111
+ var PrimaryKeyId = SC.Record.extend({ primaryKey: 'id' });
112
112
  var foo2 = store.createRecord(PrimaryKeyId, { id: 1 });
113
113
 
114
114
  equals(foo2.get('id'), 1, 'foo2.id should be 1');
115
115
  foo2.set('id', 2);
116
116
  equals(foo2.get('id'), 2, 'foo2.id should be 2');
117
+ equals(store.idFor(foo2.get('storeKey')), 2, 'foo2.id should be 2 in the store');
117
118
  });
@@ -12,18 +12,18 @@ var parent, store, child, storeKey, json;
12
12
  module("SC.NestedStore#writeDataHash", {
13
13
  setup: function() {
14
14
  parent = SC.Store.create();
15
-
15
+
16
16
  json = {
17
17
  string: "string",
18
18
  number: 23,
19
19
  bool: YES
20
20
  };
21
-
21
+
22
22
  storeKey = SC.Store.generateStoreKey();
23
23
 
24
24
  parent.writeDataHash(storeKey, json, SC.Record.READY_CLEAN);
25
25
  parent.editables = null; // manually patch to setup test state
26
-
26
+
27
27
  store = parent.chain(); // create nested store
28
28
  child = store.chain(); // test multiple levels deep
29
29
  }
@@ -31,20 +31,20 @@ module("SC.NestedStore#writeDataHash", {
31
31
 
32
32
  // ..........................................................
33
33
  // BASIC STATE TRANSITIONS
34
- //
34
+ //
35
35
 
36
36
  // The transition from each base state performs the same operation, so just
37
37
  // run the same test on each state.
38
38
  function testWriteDataHash() {
39
39
  var oldrev = store.revisions[storeKey];
40
-
40
+
41
41
  // perform test
42
42
  var json2 = { foo: "bar" };
43
43
  equals(store.writeDataHash(storeKey, json2, SC.Record.READY_NEW), store, 'should return receiver');
44
-
44
+
45
45
  // verify
46
46
  equals(store.storeKeyEditState(storeKey), SC.Store.EDITABLE, 'new edit state should be editable');
47
-
47
+
48
48
  equals(store.readDataHash(storeKey), json2, 'should have new json data hash');
49
49
  equals(store.readStatus(storeKey), SC.Record.READY_NEW, 'should have new status');
50
50
 
@@ -56,45 +56,45 @@ function testWriteDataHash() {
56
56
 
57
57
 
58
58
  test("edit state=INHERITED", function() {
59
-
59
+
60
60
  // test preconditions
61
61
  equals(store.storeKeyEditState(storeKey), SC.Store.INHERITED, 'precond - edit state should be inherited');
62
-
62
+
63
63
  testWriteDataHash();
64
64
  });
65
65
 
66
66
  test("edit state=LOCKED", function() {
67
-
67
+
68
68
  // test preconditions
69
69
  store.readDataHash(storeKey);
70
70
  equals(store.storeKeyEditState(storeKey), SC.Store.LOCKED, 'precond - edit state should be locked');
71
-
71
+
72
72
  testWriteDataHash();
73
73
 
74
74
  });
75
75
 
76
76
  test("edit state=EDITABLE", function() {
77
-
77
+
78
78
  // test preconditions
79
79
  store.readEditableDataHash(storeKey);
80
80
  equals(store.storeKeyEditState(storeKey), SC.Store.EDITABLE, 'precond - edit state should be editable');
81
-
81
+
82
82
  testWriteDataHash();
83
83
 
84
84
  });
85
85
 
86
86
  // ..........................................................
87
87
  // WRITING NEW VS EXISTING
88
- //
88
+ //
89
89
 
90
90
  test("writing a new hash", function() {
91
91
  storeKey = SC.Store.generateStoreKey(); // new store key!
92
92
  equals(parent.readDataHash(storeKey), null, 'precond - parent should not have a data hash for store key yet');
93
93
  equals(store.storeKeyEditState(storeKey), SC.Store.INHERITED, 'precond - edit status should be inherited');
94
-
94
+
95
95
  // perform write
96
96
  equals(store.writeDataHash(storeKey, json, SC.Record.READY_NEW), store, 'should return receiver');
97
-
97
+
98
98
  // verify change
99
99
  equals(store.storeKeyEditState(storeKey), SC.Store.EDITABLE, 'new status should be editable');
100
100
  equals(store.readDataHash(storeKey), json, 'should match new json');
@@ -103,7 +103,7 @@ test("writing a new hash", function() {
103
103
 
104
104
  // ..........................................................
105
105
  // PROPOGATING TO NESTED STORES
106
- //
106
+ //
107
107
 
108
108
  test("change should propogate to child if child edit state = INHERITED", function() {
109
109
 
@@ -113,11 +113,11 @@ test("change should propogate to child if child edit state = INHERITED", functio
113
113
  // perform change
114
114
  var json2 = { version: 2 };
115
115
  store.writeDataHash(storeKey, json2, SC.Record.READY_NEW);
116
-
116
+
117
117
  // verify
118
118
  same(child.readDataHash(storeKey), json2, 'child should pick up change');
119
119
  equals(parent.readDataHash(storeKey), json, 'parent should still have old json');
120
-
120
+
121
121
  equals(child.readStatus(storeKey), SC.Record.READY_NEW, 'child should pick up new status');
122
122
  equals(parent.readStatus(storeKey), SC.Record.READY_CLEAN, 'parent should still have old status');
123
123
 
@@ -128,11 +128,11 @@ function testLockedOrEditableChild() {
128
128
  // perform change
129
129
  var json2 = { version: 2 };
130
130
  store.writeDataHash(storeKey, json2, SC.Record.READY_NEW);
131
-
131
+
132
132
  // verify
133
133
  same(child.readDataHash(storeKey), json, 'child should NOT pick up change');
134
134
  equals(parent.readDataHash(storeKey), json, 'parent should still have old json');
135
-
135
+
136
136
  equals(child.readStatus(storeKey), SC.Record.READY_CLEAN, 'child should pick up new status');
137
137
  equals(parent.readStatus(storeKey), SC.Record.READY_CLEAN, 'parent should still have old status');
138
138
  }
@@ -156,11 +156,55 @@ test("change should not propogate to child if child edit state = EDITABLE", func
156
156
  testLockedOrEditableChild();
157
157
  });
158
158
 
159
-
160
-
161
-
162
-
163
-
164
-
165
-
166
-
159
+ test("writeDataHash on parent records should be propagated to nested children and eventually to the parent store", function() {
160
+ var model = SC.Record.extend( {
161
+ v: SC.Record.attr( String ),
162
+ c: SC.Record.toMany( SC.Record.extend( {
163
+ v: SC.Record.attr( String ),
164
+ } ),
165
+ {
166
+ nested: YES
167
+ } )
168
+ } );
169
+ var json1 = { guid: "p1", v: "p1-1", c: [ { guid: "c1", v: "c1-1" }, { id: "c2", v: "c2-1" } ] };
170
+ var json12 = { guid: "p1", v: "p1-2", c: [ { guid: "c1", v: "c1-2" }, { id: "c2", v: "c2-1" } ] };
171
+
172
+ SC.RunLoop.begin();
173
+
174
+ // load the data into the main store
175
+ var storeKey1 = parent.loadRecord( model, json1 );
176
+ var rec1 = parent.find( model, "p1" );
177
+
178
+ equals( rec1.get( "v" ), "p1-1", "the data loaded into the record should be correct" );
179
+ equals( rec1.get( "c" ).objectAt( 0 ).get( "v" ), "c1-1", "the data loaded into the 1st child record should be correct" );
180
+ equals( rec1.get( "c" ).objectAt( 1 ).get( "v" ), "c2-1", "the data loaded into the 2nd child record should be correct" );
181
+
182
+ // start an "editing" session into the nested store store
183
+ var rec12 = store.find( rec1 );
184
+
185
+ equals( rec12.get( "c" ).objectAt( 0 ).get( "v" ), "c1-1", "the data loaded into the 1st child record should be correct" );
186
+ equals( rec12.get( "c" ).objectAt( 1 ).get( "v" ), "c2-1", "the data loaded into the 2nd child record should be correct" );
187
+
188
+ // replace the content and notify the changes
189
+ store.writeDataHash( storeKey1, json12, SC.Record.READY_CLEAN );
190
+ store.dataHashDidChange( storeKey1 );
191
+
192
+ SC.RunLoop.end();
193
+
194
+ SC.RunLoop.begin();
195
+ // check if the values from the hash are properly propagated to the record + children
196
+ equals( rec12.get( "v" ), "p1-2", "after writeDataHash the data loaded into the record should be updated" );
197
+ equals( rec12.get( "c" ).objectAt( 0 ).get( "v" ), "c1-2", "after writeDataHash the data loaded into the 1st child record should be updated" );
198
+ equals( rec12.get( "c" ).objectAt( 1 ).get( "v" ), "c2-1", "after writeDataHash the data loaded into the 2nd child record should not be updated" );
199
+
200
+ // push the changes to the parent store
201
+ store.commitChanges(YES);
202
+ SC.RunLoop.end();
203
+
204
+ SC.RunLoop.begin();
205
+ // check if the values updated into the nested store are properly propagated to the record + children
206
+ equals( rec1.get( "v" ), "p1-2", "after commitChanges the data loaded into the record should be updated" );
207
+ equals( rec1.get( "c" ).objectAt( 0 ).get( "v" ), "c1-2", "after commitChanges the data loaded into the 1st child record should be updated" );
208
+ equals( rec1.get( "c" ).objectAt( 1 ).get( "v" ), "c2-1", "the data loaded into the 2nd child record should be correct" );
209
+ SC.RunLoop.end();
210
+ });
@@ -0,0 +1,156 @@
1
+ // ==========================================================================
2
+ // Project: SproutCore - JavaScript Application Framework
3
+ // Copyright: ©2006-2011 Apple Inc. and contributors.
4
+ // License: Licensed under MIT license (see license.js)
5
+ // ==========================================================================
6
+ /*globals module, ok, equals, same, test */
7
+
8
+ var store, child, json;
9
+
10
+ module("SC.NestedStore.prototype.conflictedStoreKeys", {
11
+ setup: function () {
12
+ SC.run(function () {
13
+ store = SC.Store.create();
14
+
15
+ json = {
16
+ string: "string",
17
+ number: 23,
18
+ bool: true
19
+ };
20
+
21
+ child = store.chain(); // test multiple levels deep
22
+ });
23
+ },
24
+
25
+ teardown: function () {
26
+ child.destroy();
27
+ store.destroy();
28
+
29
+ store = child = json = null;
30
+ }
31
+ });
32
+
33
+ test("should return empty array when no conflict is present", function() {
34
+ SC.run(function () {
35
+ var storeKey = SC.Store.generateStoreKey();
36
+
37
+ // write basic status
38
+ child.writeDataHash(storeKey, json, SC.Record.READY_DIRTY);
39
+ child.dataHashDidChange(storeKey);
40
+ child.changelog = SC.Set.create();
41
+ child.changelog.add(storeKey);
42
+
43
+ same(child.get('conflictedStoreKeys'), null, "There should be no conflicted store keys");
44
+ });
45
+ });
46
+
47
+ test("should return an array with one or more storekeys when one or more conflicts exist", function() {
48
+ SC.run(function () {
49
+ var json2 = { kind: "json2" };
50
+ var json3 = { kind: "json3" };
51
+
52
+ // create a lock conflict. use a new storeKey since the old one has been
53
+ // setup in a way that won't work for this.
54
+ var storeKey = SC.Store.generateStoreKey();
55
+
56
+ // step 1: add data to root store
57
+ store.writeDataHash(storeKey, json, SC.Record.READY_CLEAN);
58
+ store.dataHashDidChange(storeKey);
59
+
60
+ // step 2: read data in chained store. this will create lock
61
+ child.readDataHash(storeKey);
62
+ ok(child.locks[storeKey], 'child store should now have lock');
63
+
64
+ // step 3: modify root store again
65
+ store.writeDataHash(storeKey, json2, SC.Record.READY_CLEAN);
66
+ store.dataHashDidChange(storeKey);
67
+
68
+ // step 4: modify data in chained store so we have something to commit.
69
+ child.writeDataHash(storeKey, json3, SC.Record.READY_DIRTY);
70
+ child.dataHashDidChange(storeKey);
71
+
72
+ // just to make sure verify that the lock and revision in parent do not match
73
+ ok(child.locks[storeKey] !== store.revisions[storeKey], 'child.lock (%@) should !== store.revision (%@)'.fmt(child.locks[storeKey], store.revisions[storeKey]));
74
+
75
+ // step 5: now try to retrieve conflicts
76
+ same(child.get('conflictedStoreKeys') , [storeKey], "There should be conflicted store key as");
77
+
78
+ });
79
+ });
80
+
81
+
82
+ test("should be able to bind and observe conflictedStoreKeys", function () {
83
+ var observerExpected = null,
84
+ observerObject = SC.Object.create({
85
+ conflictedStoreKeysDC: function () {
86
+ same(child.get('conflictedStoreKeys'), observerExpected, "There should be conflicted store keys observed as");
87
+ }
88
+ });
89
+
90
+ child.addObserver('conflictedStoreKeys', observerObject, 'conflictedStoreKeysDC');
91
+
92
+ SC.run(function () {
93
+ var json2 = { kind: "json2" };
94
+ var json3 = { kind: "json3" };
95
+ var json4 = { kind: "json4" };
96
+
97
+ // create a lock conflict. use a new storeKey since the old one has been
98
+ // setup in a way that won't work for this.
99
+ var storeKey = SC.Store.generateStoreKey();
100
+
101
+ // step 1: add data to root store
102
+ store.writeDataHash(storeKey, json, SC.Record.READY_CLEAN);
103
+ store.dataHashDidChange(storeKey);
104
+
105
+ // step 2: read data in chained store. this will create lock
106
+ child.readDataHash(storeKey);
107
+
108
+ // Run observer manually once.
109
+ observerObject.conflictedStoreKeysDC();
110
+
111
+ // step 3: modify root store again
112
+ store.writeDataHash(storeKey, json2, SC.Record.READY_CLEAN);
113
+ store.dataHashDidChange(storeKey);
114
+
115
+ // Observer should fire on its own.
116
+ observerExpected = [storeKey];
117
+
118
+ // step 4: modify data in chained store so we have something to commit.
119
+ child.writeDataHash(storeKey, json3, SC.Record.READY_DIRTY);
120
+ child.dataHashDidChange(storeKey);
121
+
122
+ // step 5: modify data again (shouldn't fire update b/c it's the same record)
123
+ child.writeDataHash(storeKey, json4, SC.Record.READY_DIRTY);
124
+ child.dataHashDidChange(storeKey);
125
+
126
+ var storeKey2 = SC.Store.generateStoreKey();
127
+
128
+ // step 6: add data to root store
129
+ store.writeDataHash(storeKey2, SC.copy(json), SC.Record.READY_CLEAN);
130
+ store.dataHashDidChange(storeKey2);
131
+
132
+ // step 7: read data in chained store. this will create lock
133
+ child.readDataHash(storeKey2);
134
+
135
+ // Run observer manually once.
136
+ observerObject.conflictedStoreKeysDC();
137
+
138
+ // step 8: modify root store again
139
+ store.writeDataHash(storeKey2, SC.copy(json2), SC.Record.READY_CLEAN);
140
+ store.dataHashDidChange(storeKey2);
141
+
142
+ // Observer should fire on its own.
143
+ observerExpected = [storeKey, storeKey2];
144
+
145
+ // step 4: modify data in chained store so we have something to commit.
146
+ child.writeDataHash(storeKey2, SC.copy(json3), SC.Record.READY_DIRTY);
147
+ child.dataHashDidChange(storeKey2);
148
+
149
+ // Observer should fire on its own.
150
+ observerExpected = null;
151
+
152
+ // step 6: throw away the changes, conflicted store keys should go to null.
153
+ child.discardChanges();
154
+ });
155
+ });
156
+