sproutcore 1.6.0.rc.2-x86-mingw32 → 1.6.0.1-x86-mingw32

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (209) hide show
  1. data/CHANGELOG +12 -0
  2. data/VERSION.yml +1 -1
  3. data/bin/sc-docs +6 -1
  4. data/lib/buildtasks/target.rake +1 -1
  5. data/lib/frameworks/sproutcore/Buildfile +5 -1
  6. data/lib/frameworks/sproutcore/CHANGELOG.md +175 -1
  7. data/lib/frameworks/sproutcore/apps/test_controls/controllers/select.js +12 -0
  8. data/lib/frameworks/sproutcore/apps/test_controls/resources/select_page.js +19 -5
  9. data/lib/frameworks/sproutcore/frameworks/ajax/system/request.js +28 -31
  10. data/lib/frameworks/sproutcore/frameworks/ajax/system/response.js +9 -2
  11. data/lib/frameworks/sproutcore/frameworks/core_foundation/controllers/controller.js +21 -1
  12. data/lib/frameworks/sproutcore/frameworks/core_foundation/mixins/responder_context.js +1 -1
  13. data/lib/frameworks/sproutcore/frameworks/core_foundation/mixins/template_helpers/checkbox_support.js +6 -1
  14. data/lib/frameworks/sproutcore/frameworks/core_foundation/mixins/template_helpers/text_field_support.js +26 -8
  15. data/lib/frameworks/sproutcore/frameworks/core_foundation/panes/keyboard.js +2 -0
  16. data/lib/frameworks/sproutcore/frameworks/core_foundation/panes/pane.js +12 -5
  17. data/lib/frameworks/sproutcore/frameworks/core_foundation/panes/template.js +25 -9
  18. data/lib/frameworks/sproutcore/frameworks/core_foundation/system/locale.js +157 -5
  19. data/lib/frameworks/sproutcore/frameworks/core_foundation/system/render_context.js +7 -6
  20. data/lib/frameworks/sproutcore/frameworks/core_foundation/system/root_responder.js +9 -3
  21. data/lib/frameworks/sproutcore/frameworks/core_foundation/system/sparse_array.js +8 -8
  22. data/lib/frameworks/sproutcore/frameworks/core_foundation/system/string.js +104 -4
  23. data/lib/frameworks/sproutcore/frameworks/core_foundation/system/theme.js +3 -56
  24. data/lib/frameworks/sproutcore/frameworks/core_foundation/system/utils.js +4 -2
  25. data/lib/frameworks/sproutcore/frameworks/core_foundation/tests/controllers/object/content_destroyed.js +59 -0
  26. data/lib/frameworks/sproutcore/frameworks/core_foundation/tests/mixins/string.js +41 -1
  27. data/lib/frameworks/sproutcore/frameworks/core_foundation/tests/mixins/template_helpers/text_field_support.js +10 -2
  28. data/lib/frameworks/sproutcore/frameworks/core_foundation/tests/panes/template.js +16 -1
  29. data/lib/frameworks/sproutcore/frameworks/core_foundation/tests/views/template/handlebars.js +1 -1
  30. data/lib/frameworks/sproutcore/frameworks/core_foundation/tests/views/view/clippingFrame.js +11 -0
  31. data/lib/frameworks/sproutcore/frameworks/core_foundation/tests/views/view/didAppendToDocument.js +18 -2
  32. data/lib/frameworks/sproutcore/frameworks/core_foundation/tests/views/view/insertBefore.js +10 -6
  33. data/lib/frameworks/sproutcore/frameworks/core_foundation/tests/views/view/keyboard.js +18 -1
  34. data/lib/frameworks/sproutcore/frameworks/core_foundation/views/template_collection.js +9 -1
  35. data/lib/frameworks/sproutcore/frameworks/core_foundation/views/view.js +9 -4
  36. data/lib/frameworks/sproutcore/frameworks/core_foundation/views/view/keyboard.js +15 -3
  37. data/lib/frameworks/sproutcore/frameworks/core_foundation/views/view/manipulation.js +14 -8
  38. data/lib/frameworks/sproutcore/frameworks/core_foundation/views/view/theming.js +8 -18
  39. data/lib/frameworks/sproutcore/frameworks/datastore/data_sources/fixtures.js +12 -2
  40. data/lib/frameworks/sproutcore/frameworks/datastore/mixins/relationship_support.js +296 -0
  41. data/lib/frameworks/sproutcore/frameworks/datastore/models/child_record.js +1 -1
  42. data/lib/frameworks/sproutcore/frameworks/datastore/models/record.js +330 -326
  43. data/lib/frameworks/sproutcore/frameworks/datastore/models/record_attribute.js +22 -1
  44. data/lib/frameworks/sproutcore/frameworks/datastore/system/nested_store.js +1 -1
  45. data/lib/frameworks/sproutcore/frameworks/datastore/system/store.js +614 -614
  46. data/lib/frameworks/sproutcore/frameworks/datastore/tests/data_sources/data_source.js +14 -1
  47. data/lib/frameworks/sproutcore/frameworks/datastore/tests/models/nested_records/nested_record.js +3 -1
  48. data/lib/frameworks/sproutcore/frameworks/datastore/tests/models/nested_records/nested_record_array_complex.js +2 -0
  49. data/lib/frameworks/sproutcore/frameworks/datastore/tests/models/nested_records/nested_record_complex.js +2 -0
  50. data/lib/frameworks/sproutcore/frameworks/datastore/tests/models/record/core_methods.js +20 -13
  51. data/lib/frameworks/sproutcore/frameworks/datastore/tests/models/record_attribute.js +61 -46
  52. data/lib/frameworks/sproutcore/frameworks/datastore/tests/system/nested_store/commitChangesFromNestedStore.js +30 -30
  53. data/lib/frameworks/sproutcore/frameworks/datastore/tests/system/store/commitChangesFromNestedStore.js +24 -24
  54. data/lib/frameworks/sproutcore/frameworks/datastore/tests/system/store/connectDataSource.js +31 -0
  55. data/lib/frameworks/sproutcore/frameworks/datastore/tests/system/store/pushRelationships.js +1177 -0
  56. data/lib/frameworks/sproutcore/frameworks/datetime/frameworks/localized/system/datetime.js +4 -63
  57. data/lib/frameworks/sproutcore/frameworks/desktop/mixins/border.js +1 -1
  58. data/lib/frameworks/sproutcore/frameworks/desktop/mixins/scrollable.js +1 -1
  59. data/lib/frameworks/sproutcore/frameworks/desktop/panes/alert.js +7 -8
  60. data/lib/frameworks/sproutcore/frameworks/desktop/panes/menu.js +18 -1
  61. data/lib/frameworks/sproutcore/frameworks/desktop/panes/panel.js +9 -0
  62. data/lib/frameworks/sproutcore/frameworks/desktop/protocols/drag_data_source.js +3 -3
  63. data/lib/frameworks/sproutcore/frameworks/desktop/protocols/drop_target.js +3 -3
  64. data/lib/frameworks/sproutcore/frameworks/desktop/render_delegates/button.js +1 -1
  65. data/lib/frameworks/sproutcore/frameworks/desktop/render_delegates/checkbox.js +1 -1
  66. data/lib/frameworks/sproutcore/frameworks/desktop/render_delegates/collection.js +1 -1
  67. data/lib/frameworks/sproutcore/frameworks/desktop/render_delegates/disclosure.js +1 -1
  68. data/lib/frameworks/sproutcore/frameworks/desktop/render_delegates/image_button.js +1 -1
  69. data/lib/frameworks/sproutcore/frameworks/desktop/render_delegates/master_detail.js +3 -2
  70. data/lib/frameworks/sproutcore/frameworks/desktop/render_delegates/menu.js +12 -2
  71. data/lib/frameworks/sproutcore/frameworks/desktop/render_delegates/panel.js +1 -1
  72. data/lib/frameworks/sproutcore/frameworks/desktop/render_delegates/picker.js +1 -1
  73. data/lib/frameworks/sproutcore/frameworks/desktop/render_delegates/progress.js +1 -1
  74. data/lib/frameworks/sproutcore/frameworks/desktop/render_delegates/radio.js +1 -1
  75. data/lib/frameworks/sproutcore/frameworks/desktop/render_delegates/radio_group.js +2 -2
  76. data/lib/frameworks/sproutcore/frameworks/desktop/render_delegates/segment.js +1 -1
  77. data/lib/frameworks/sproutcore/frameworks/desktop/render_delegates/segmented.js +1 -1
  78. data/lib/frameworks/sproutcore/frameworks/desktop/render_delegates/slider.js +1 -1
  79. data/lib/frameworks/sproutcore/frameworks/desktop/render_delegates/toolbar.js +1 -1
  80. data/lib/frameworks/sproutcore/frameworks/desktop/render_delegates/well.js +1 -1
  81. data/lib/frameworks/sproutcore/frameworks/desktop/render_delegates/workspace.js +1 -1
  82. data/lib/frameworks/sproutcore/frameworks/desktop/resources/segmented.css +1 -0
  83. data/lib/frameworks/sproutcore/frameworks/desktop/tests/panes/alert/ui.js +33 -22
  84. data/lib/frameworks/sproutcore/frameworks/desktop/tests/panes/panel/methods.js +20 -1
  85. data/lib/frameworks/sproutcore/frameworks/desktop/tests/views/checkbox/methods.js +10 -3
  86. data/lib/frameworks/sproutcore/frameworks/desktop/tests/views/date_field/methods.js +34 -7
  87. data/lib/frameworks/sproutcore/frameworks/desktop/views/button.js +14 -15
  88. data/lib/frameworks/sproutcore/frameworks/desktop/views/checkbox.js +40 -14
  89. data/lib/frameworks/sproutcore/frameworks/desktop/views/collection.js +699 -700
  90. data/lib/frameworks/sproutcore/frameworks/desktop/views/list_item.js +2 -2
  91. data/lib/frameworks/sproutcore/frameworks/desktop/views/master_detail.js +11 -1
  92. data/lib/frameworks/sproutcore/frameworks/desktop/views/menu_item.js +16 -6
  93. data/lib/frameworks/sproutcore/frameworks/desktop/views/progress.js +0 -1
  94. data/lib/frameworks/sproutcore/frameworks/desktop/views/radio.js +49 -7
  95. data/lib/frameworks/sproutcore/frameworks/desktop/views/select_button.js +9 -0
  96. data/lib/frameworks/sproutcore/frameworks/desktop/views/select_field.js +6 -2
  97. data/lib/frameworks/sproutcore/frameworks/desktop/views/slider.js +4 -26
  98. data/lib/frameworks/sproutcore/frameworks/desktop/views/web.js +20 -19
  99. data/lib/frameworks/sproutcore/frameworks/experimental/Buildfile +2 -0
  100. data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/designer/designers/view_designer.js +249 -249
  101. data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/forms/mixins/edit_mode.js +13 -5
  102. data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/forms/mixins/emptiness.js +53 -37
  103. data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/forms/render_delegates/form.js +2 -1
  104. data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/forms/render_delegates/form_row.js +3 -11
  105. data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/forms/tests/mixins/edit_mode.js +53 -0
  106. data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/forms/tests/mixins/emptiness.js +114 -0
  107. data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/forms/tests/views/form.js +174 -6
  108. data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/forms/tests/views/form_row.js +86 -6
  109. data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/forms/views/form.js +80 -110
  110. data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/forms/views/form_row.js +96 -97
  111. data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/polymorphism/README.md +2 -1
  112. data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/polymorphism/models/record.js +20 -36
  113. data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/select_view/ext/menu.js +121 -0
  114. data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/select_view/ext/menu_item.js +90 -0
  115. data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/select_view/mixins/select_view_menu.js +139 -0
  116. data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/select_view/render_delegates/select_button.js +14 -0
  117. data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/select_view/tests/ext/menu_resizing.js +25 -0
  118. data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/select_view/tests/mixins/select_view_menu/bindings.js +43 -0
  119. data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/select_view/tests/mixins/select_view_menu/check_selected.js +32 -0
  120. data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/select_view/tests/views/popup_button/menu_setup.js +40 -0
  121. data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/select_view/tests/views/popup_button/show_menu.js +45 -0
  122. data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/select_view/tests/views/select/menu_width.js +49 -0
  123. data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/select_view/tests/views/select/selected_item.js +191 -0
  124. data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/select_view/views/popup_button.js +264 -0
  125. data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/select_view/views/select.js +450 -0
  126. data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/split_view/mixins/split_child.js +14 -6
  127. data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/split_view/mixins/split_thumb.js +1 -1
  128. data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/split_view/render_delegates/split.js +1 -1
  129. data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/split_view/render_delegates/split_divider.js +1 -1
  130. data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/split_view/views/split.js +9 -0
  131. data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/split_view/views/thumb.js +3 -2
  132. data/lib/frameworks/sproutcore/frameworks/foundation/mixins/auto_resize.js +7 -17
  133. data/lib/frameworks/sproutcore/frameworks/foundation/mixins/content_value_support.js +1 -1
  134. data/lib/frameworks/sproutcore/frameworks/foundation/mixins/flowed_layout.js +35 -8
  135. data/lib/frameworks/sproutcore/frameworks/foundation/mixins/inline_editable.js +1 -1
  136. data/lib/frameworks/sproutcore/frameworks/foundation/mixins/inline_editor.js +1 -1
  137. data/lib/frameworks/sproutcore/frameworks/foundation/mixins/inline_editor_delegate.js +1 -1
  138. data/lib/frameworks/sproutcore/frameworks/foundation/mixins/inner_frame.js +1 -1
  139. data/lib/frameworks/sproutcore/frameworks/foundation/render_delegates/canvas_image.js +1 -1
  140. data/lib/frameworks/sproutcore/frameworks/foundation/render_delegates/helpers/sizing.js +2 -0
  141. data/lib/frameworks/sproutcore/frameworks/foundation/render_delegates/image.js +1 -1
  142. data/lib/frameworks/sproutcore/frameworks/foundation/render_delegates/label.js +1 -1
  143. data/lib/frameworks/sproutcore/frameworks/foundation/render_delegates/render_delegate.js +6 -6
  144. data/lib/frameworks/sproutcore/frameworks/foundation/resources/images/favicon.ico +0 -0
  145. data/lib/frameworks/sproutcore/frameworks/foundation/resources/text_field.css +0 -5
  146. data/lib/frameworks/sproutcore/frameworks/foundation/system/exception_handler.js +4 -2
  147. data/lib/frameworks/sproutcore/frameworks/foundation/system/math.js +2 -1
  148. data/lib/frameworks/sproutcore/frameworks/foundation/system/module.js +13 -0
  149. data/lib/frameworks/sproutcore/frameworks/foundation/system/utils/string_measurement.js +6 -9
  150. data/lib/frameworks/sproutcore/frameworks/foundation/tests/mixins/flowed_layout/tests.js +912 -0
  151. data/lib/frameworks/sproutcore/frameworks/foundation/tests/views/text_field/methods.js +36 -7
  152. data/lib/frameworks/sproutcore/frameworks/foundation/tests/views/text_field/ui.js +58 -4
  153. data/lib/frameworks/sproutcore/frameworks/foundation/validators/validator.js +1 -3
  154. data/lib/frameworks/sproutcore/frameworks/foundation/views/field.js +0 -15
  155. data/lib/frameworks/sproutcore/frameworks/foundation/views/label.js +2 -2
  156. data/lib/frameworks/sproutcore/frameworks/foundation/views/text_field.js +25 -14
  157. data/lib/frameworks/sproutcore/frameworks/handlebars/handlebars.js +1 -1
  158. data/lib/frameworks/sproutcore/frameworks/runtime/core.js +15 -9
  159. data/lib/frameworks/sproutcore/frameworks/runtime/debug/test_suites/array/flatten.js +24 -0
  160. data/lib/frameworks/sproutcore/frameworks/runtime/ext/array.js +2 -1
  161. data/lib/frameworks/sproutcore/frameworks/runtime/ext/function.js +5 -5
  162. data/lib/frameworks/sproutcore/frameworks/runtime/mixins/array.js +19 -0
  163. data/lib/frameworks/sproutcore/frameworks/runtime/mixins/copyable.js +3 -2
  164. data/lib/frameworks/sproutcore/frameworks/runtime/mixins/freezable.js +1 -1
  165. data/lib/frameworks/sproutcore/frameworks/runtime/mixins/observable.js +1 -1
  166. data/lib/frameworks/sproutcore/frameworks/runtime/system/binding.js +14 -14
  167. data/lib/frameworks/sproutcore/frameworks/runtime/system/error.js +3 -0
  168. data/lib/frameworks/sproutcore/frameworks/runtime/system/logger.js +2 -2
  169. data/lib/frameworks/sproutcore/frameworks/runtime/system/object.js +2 -2
  170. data/lib/frameworks/sproutcore/frameworks/runtime/system/range_observer.js +1 -1
  171. data/lib/frameworks/sproutcore/frameworks/runtime/system/run_loop.js +3 -3
  172. data/lib/frameworks/sproutcore/frameworks/runtime/system/set.js +15 -16
  173. data/lib/frameworks/sproutcore/frameworks/runtime/tests/core/itemType.js +6 -2
  174. data/lib/frameworks/sproutcore/frameworks/runtime/tests/system/object/enhance.js +30 -0
  175. data/lib/frameworks/sproutcore/frameworks/runtime/tests/system/range_observer/create.js +17 -0
  176. data/lib/frameworks/sproutcore/frameworks/statechart/system/state.js +9 -2
  177. data/lib/frameworks/sproutcore/frameworks/statechart/system/statechart.js +3 -1
  178. data/lib/frameworks/sproutcore/frameworks/testing/resources/runner.css +0 -1
  179. data/lib/frameworks/sproutcore/frameworks/yuireset/resources/base.css +80 -0
  180. data/lib/frameworks/sproutcore/frameworks/yuireset/resources/core.css +0 -4
  181. data/lib/frameworks/sproutcore/lib/index.rhtml +2 -1
  182. data/lib/frameworks/sproutcore/themes/ace/resources/collection/normal/list.css +3 -3
  183. data/lib/frameworks/sproutcore/themes/ace/resources/collection/normal/list_item.css +2 -2
  184. data/lib/frameworks/sproutcore/themes/ace/resources/form/form.css +9 -0
  185. data/lib/frameworks/sproutcore/themes/ace/resources/menu/menu.css +3 -1
  186. data/lib/frameworks/sproutcore/themes/ace/resources/picker/popover/picker.js +1 -1
  187. data/lib/frameworks/sproutcore/themes/ace/resources/picker/popover/workspace.js +1 -1
  188. data/lib/frameworks/sproutcore/themes/legacy_theme/render_delegates/button.js +1 -1
  189. data/lib/frameworks/sproutcore/themes/legacy_theme/render_delegates/panel.js +1 -1
  190. data/lib/frameworks/sproutcore/themes/legacy_theme/render_delegates/progress.js +2 -0
  191. data/lib/frameworks/sproutcore/themes/legacy_theme/render_delegates/slider.js +1 -1
  192. data/lib/frameworks/sproutcore/themes/legacy_theme/render_delegates/well.js +1 -1
  193. data/lib/sproutcore/builders/base.rb +5 -1
  194. data/lib/sproutcore/builders/handlebars.rb +12 -1
  195. data/lib/sproutcore/models/target.rb +1 -9
  196. data/lib/sproutcore/rack/proxy.rb +238 -92
  197. data/lib/sproutcore/tools/docs.rb +1 -7
  198. data/spec/fixtures/builder_tests/apps/handlebars_test/Buildfile +1 -0
  199. data/spec/fixtures/builder_tests/apps/handlebars_test/{template.handlebars → templates/template.handlebars} +2 -0
  200. data/spec/lib/builders/handlebars_spec.rb +10 -4
  201. data/sproutcore.gemspec +3 -1
  202. metadata +73 -44
  203. data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/forms/english.lproj/default_styles.css +0 -5
  204. data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/forms/english.lproj/strings.js +0 -15
  205. data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/forms/tests/views/form_checkbox_field.js +0 -17
  206. data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/forms/tests/views/form_field.js +0 -17
  207. data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/forms/tests/views/form_label.js +0 -17
  208. data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/forms/tests/views/form_radio_field.js +0 -17
  209. data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/forms/tests/views/form_text_field.js +0 -17
@@ -11,13 +11,13 @@ module("SC.Store#commitChangesFromNestedStore", {
11
11
  SC.RunLoop.begin();
12
12
 
13
13
  store = SC.Store.create();
14
-
14
+
15
15
  json = {
16
16
  string: "string",
17
17
  number: 23,
18
18
  bool: YES
19
19
  };
20
-
20
+
21
21
  storeKey = SC.Store.generateStoreKey();
22
22
 
23
23
  child = store.chain(); // test multiple levels deep
@@ -33,46 +33,46 @@ module("SC.Store#commitChangesFromNestedStore", {
33
33
  });
34
34
 
35
35
  test("copies changed data hashes, statuses, and revisions", function() {
36
-
36
+
37
37
  SC.RunLoop.begin();
38
-
38
+
39
39
  // verify preconditions
40
40
  equals(store.readDataHash(storeKey), null, 'precond - should not have data yet');
41
41
  ok(child.chainedChanges.contains(storeKey), 'precond - child changes should include storeKey');
42
-
42
+
43
43
  // perform action
44
44
  equals(store.commitChangesFromNestedStore(child, child.chainedChanges, NO), store, 'should return receiver');
45
-
45
+
46
46
  // verify new status
47
47
  equals(store.readDataHash(storeKey), json, 'now should have json');
48
48
  equals(store.readStatus(storeKey), SC.Record.READY_DIRTY, 'now should have status');
49
- equals(store.revisions[storeKey], child.revisions[storeKey], 'now shoulave have revision from child');
50
-
49
+ equals(store.revisions[storeKey], child.revisions[storeKey], 'now shoulave have revision from child');
50
+
51
51
  SC.RunLoop.end();
52
52
  });
53
53
 
54
- test("adds items in changelog to reciever changelog", function() {
54
+ test("adds items in changelog to receiver changelog", function() {
55
55
 
56
56
  var key1 = SC.Store.generateStoreKey();
57
57
 
58
58
  SC.RunLoop.begin();
59
-
59
+
60
60
  store.changelog = SC.Set.create();
61
61
  store.changelog.add(key1);
62
-
62
+
63
63
  ok(child.changelog.contains(storeKey), 'precond - child.changelog should contain store key');
64
-
64
+
65
65
  equals(store.commitChangesFromNestedStore(child, child.chainedChanges, NO), store, 'should return receiver');
66
66
 
67
67
  // changelog should merge nested store & existing
68
68
  ok(store.changelog.contains(key1), 'changelog should still contain key1');
69
69
  ok(store.changelog.contains(storeKey), 'changelog should also contain storeKey');
70
-
70
+
71
71
  SC.RunLoop.end();
72
72
  });
73
73
 
74
74
  test("ignores changed data hashes not passed in changes set", function() {
75
-
75
+
76
76
  // preconditions
77
77
  equals(store.readDataHash(storeKey), null, 'precond - should not have data yet');
78
78
 
@@ -81,25 +81,25 @@ test("ignores changed data hashes not passed in changes set", function() {
81
81
 
82
82
  // verify results
83
83
  equals(store.readDataHash(storeKey), null, 'should not copy data hash for storeKey');
84
-
84
+
85
85
  });
86
86
 
87
87
  function createConflict(force) {
88
88
  var json2 = { kind: "json2" };
89
89
  var json3 = { kind: "json3" };
90
-
90
+
91
91
  // create a lock conflict. use a new storeKey since the old one has been
92
92
  // setup in a way that won't work for this.
93
93
  storeKey = SC.Store.generateStoreKey();
94
-
94
+
95
95
  // step 1: add data to root store
96
96
  store.writeDataHash(storeKey, json, SC.Record.READY_CLEAN);
97
97
  store.dataHashDidChange(storeKey);
98
-
98
+
99
99
  // step 2: read data in chained store. this will create lock
100
100
  child.readDataHash(storeKey);
101
101
  ok(child.locks[storeKey], 'child store should now have lock');
102
-
102
+
103
103
  // step 3: modify root store again
104
104
  store.writeDataHash(storeKey, json2, SC.Record.READY_CLEAN);
105
105
  store.dataHashDidChange(storeKey);
@@ -107,11 +107,11 @@ function createConflict(force) {
107
107
  // step 4: modify data in chained store so we have something to commit.
108
108
  child.writeDataHash(storeKey, json3, SC.Record.READY_DIRTY);
109
109
  child.dataHashDidChange(storeKey);
110
-
111
- // just to make sure verify that the lock and revision in parent do not
110
+
111
+ // just to make sure verify that the lock and revision in parent do not
112
112
  // match
113
113
  ok(child.locks[storeKey] !== store.revisions[storeKey], 'child.lock (%@) should !== store.revision (%@)'.fmt(child.locks[storeKey], store.revisions[storeKey]));
114
-
114
+
115
115
  // step 5: now try to commit changes from child store. This should throw
116
116
  // an exception.
117
117
  var errorCount = 0;
@@ -120,8 +120,8 @@ function createConflict(force) {
120
120
  } catch(e) {
121
121
  equals(e, SC.Store.CHAIN_CONFLICT_ERROR, 'should throw CHAIN_CONFLICT_ERROR');
122
122
  errorCount++;
123
- }
124
-
123
+ }
124
+
125
125
  return errorCount ;
126
126
  }
127
127
 
@@ -0,0 +1,31 @@
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
+
7
+ module("connecting DataSource to a store");
8
+
9
+ test("data source passed as string should be available as after running _getDataSource", function() {
10
+ window.MyTestDataSource = SC.DataSource.extend({
11
+ foo: 'bar'
12
+ });
13
+
14
+ var store = SC.Store.create().from("MyTestDataSource");
15
+ same(store.get("dataSource"), "MyTestDataSource");
16
+
17
+ var dataSource = store._getDataSource();
18
+ same(dataSource.foo, 'bar');
19
+
20
+ same(store.get('dataSource').foo, 'bar');
21
+ });
22
+
23
+ test("data source is required, if it can't be found, error should be thrown", function() {
24
+ expect(1);
25
+
26
+ try {
27
+ SC.Store.create().from("SC.YourTestDataSource")._getDataSource();
28
+ } catch (x) {
29
+ same(x, 'SC.YourTestDataSource could not be found');
30
+ }
31
+ });
@@ -0,0 +1,1177 @@
1
+ /*globals MyApp module test ok equals same stop start */
2
+
3
+ module("Propogating relationships with Store#pushRetrieve and Store#pushDestroy", {
4
+ setup: function () {
5
+ var MyApp = window.MyApp = SC.Object.create({
6
+ store: SC.Store.create(SC.RelationshipSupport)
7
+ });
8
+ }
9
+ });
10
+
11
+ // ..........................................................
12
+ // pushRetrieve BEHAVIOR
13
+ //
14
+
15
+ /**
16
+ [master] --> [slave]
17
+
18
+ precond - master has a slave
19
+ test - slave has a master
20
+ */
21
+ test("Master updates a slave [one(master) to one(slave)].", function () {
22
+ MyApp.Master = SC.Record.extend({
23
+ slave: SC.Record.toOne('MyApp.Slave', {
24
+ inverse: 'master',
25
+ isMaster: YES
26
+ })
27
+ });
28
+
29
+ MyApp.Slave = SC.Record.extend({
30
+ master: SC.Record.toOne('MyApp.Master', {
31
+ inverse: 'slave',
32
+ isMaster: NO
33
+ })
34
+ });
35
+
36
+ SC.RunLoop.begin();
37
+ MyApp.store.loadRecords(MyApp.Slave, [
38
+ { guid: 's1' }
39
+ ]);
40
+
41
+ MyApp.store.loadRecords(MyApp.Master, [
42
+ { guid: 'm1', slave: 's1' }
43
+ ]);
44
+ SC.RunLoop.end();
45
+
46
+ var s1 = MyApp.store.find(MyApp.Slave, 's1'),
47
+ m1 = MyApp.store.find(MyApp.Master, 'm1');
48
+
49
+ equals(m1.get('slave'), s1, 'precond - m1 should have a slave');
50
+ equals(s1.get('master'), m1, 's1 should have a master');
51
+ });
52
+
53
+ /**
54
+ [master]
55
+ v
56
+ |
57
+ +--> [slave1]
58
+ |
59
+ ...
60
+ |
61
+ +--> [slaveN]
62
+
63
+ precond - master has slaves
64
+ test - slaves have a master
65
+ */
66
+ test("A master updates many slave [one(master) to many(slave)].", function () {
67
+ MyApp.Slave = SC.Record.extend({
68
+ master: SC.Record.toOne('MyApp.Master', {
69
+ inverse: 'slaves',
70
+ isMaster: NO
71
+ })
72
+ });
73
+
74
+ MyApp.Master = SC.Record.extend({
75
+ slaves: SC.Record.toMany('MyApp.Slave', {
76
+ inverse: 'master',
77
+ isMaster: YES
78
+ })
79
+ });
80
+
81
+ SC.RunLoop.begin();
82
+ MyApp.store.loadRecords(MyApp.Slave, [
83
+ { guid: 's1' },
84
+ { guid: 's2' }
85
+ ]);
86
+
87
+ MyApp.store.loadRecords(MyApp.Master, [
88
+ { guid: 'm1', slaves: ['s1', 's2'] }
89
+ ]);
90
+ SC.RunLoop.end();
91
+
92
+ var s1 = MyApp.store.find(MyApp.Slave, 's1'),
93
+ s2 = MyApp.store.find(MyApp.Slave, 's2'),
94
+ m1 = MyApp.store.find(MyApp.Master, 'm1');
95
+
96
+ equals(m1.get('slaves').length(), 2, 'precond - m1 has 2 slaves');
97
+ equals(s1.get('master'), m1, 's1 should have master m1');
98
+ equals(s2.get('master'), m1, 's2 should have master m1');
99
+ });
100
+
101
+ /**
102
+ [slave]
103
+ ^
104
+ |
105
+ +--< [master1]
106
+ |
107
+ ...
108
+ |
109
+ +--< [masterN]
110
+
111
+ precond - master has a slave
112
+ test - slave has many masters
113
+ */
114
+ test("Many parent master updates a slave [many(master) to one(slave)]", function () {
115
+ MyApp.Slave = SC.Record.extend({
116
+ masters: SC.Record.toMany('MyApp.Master', {
117
+ inverse: 'slave',
118
+ isMaster: NO
119
+ })
120
+ });
121
+
122
+ MyApp.Master = SC.Record.extend({
123
+ slave: SC.Record.toOne('MyApp.Slave', {
124
+ inverse: 'masters',
125
+ isMaster: YES
126
+ })
127
+ });
128
+
129
+ SC.RunLoop.begin();
130
+ MyApp.store.loadRecords(MyApp.Slave, [
131
+ { guid: 's1' }
132
+ ]);
133
+
134
+ MyApp.store.loadRecords(MyApp.Master, [
135
+ { guid: 'm1', slave: 's1' },
136
+ { guid: 'm2', slave: 's1' }
137
+ ]);
138
+ SC.RunLoop.end();
139
+
140
+ var m1 = MyApp.store.find(MyApp.Master, 'm1'),
141
+ m2 = MyApp.store.find(MyApp.Master, 'm2'),
142
+ s1 = MyApp.store.find(MyApp.Slave, 's1');
143
+
144
+ equals(m1.get('slave'), s1, 'precond - m1 should have slave s1');
145
+ equals(m2.get('slave'), s1, 'precond - m2 should have slave s1');
146
+
147
+ equals(s1.get('masters').length(), 2, 'slave has 2 masters');
148
+ ok(s1.get('masters').indexOf(m1) !== -1, 'slave has master m1');
149
+ ok(s1.get('masters').indexOf(m2) !== -1, 'slave has master m2');
150
+ });
151
+
152
+ /**
153
+ [master1] ... [masterN]
154
+ v v
155
+ | |
156
+ >------- ... -> [slave1]
157
+ | |
158
+ ... ...
159
+ | |
160
+ >------- ... -> [slaveN]
161
+
162
+ precond - masters have many slaves
163
+ test - slaves have many masters
164
+ */
165
+ test("Many masters update many slaves [many(master) to many(slave)]", function () {
166
+ MyApp.Master = SC.Record.extend({
167
+ slaves: SC.Record.toMany('MyApp.Slave', {
168
+ inverse: 'masters',
169
+ isMaster: YES
170
+ })
171
+ });
172
+
173
+ MyApp.Slave = SC.Record.extend({
174
+ masters: SC.Record.toMany('MyApp.Master', {
175
+ inverse: 'slaves',
176
+ isMaster: NO
177
+ })
178
+ });
179
+
180
+ SC.RunLoop.begin();
181
+ MyApp.store.loadRecords(MyApp.Slave, [
182
+ { guid: 's1' },
183
+ { guid: 's2' }
184
+ ]);
185
+
186
+ MyApp.store.loadRecords(MyApp.Master, [
187
+ { guid: 'm1', slaves: ['s1', 's2'] },
188
+ { guid: 'm2', slaves: ['s1', 's2'] }
189
+ ]);
190
+ SC.RunLoop.end();
191
+
192
+ var m1 = MyApp.store.find(MyApp.Master, 'm1'),
193
+ m2 = MyApp.store.find(MyApp.Master, 'm2'),
194
+ s1 = MyApp.store.find(MyApp.Slave, 's1'),
195
+ s2 = MyApp.store.find(MyApp.Slave, 's2');
196
+
197
+ equals(m1.get('slaves').length(), 2, 'precond - m1 should have 2 slaves');
198
+ equals(m2.get('slaves').length(), 2, 'precond - m2 should have 2 slaves');
199
+
200
+ equals(s1.get('masters').length(), 2, 's1 should have 2 masters');
201
+ ok(s1.get('masters').indexOf(m1) !== -1, 's1 should have m1 as a master');
202
+ ok(s1.get('masters').indexOf(m2) !== -1, 's1 should have m2 as a master');
203
+
204
+ equals(s2.get('masters').length(), 2, 's2 should have 2 masters');
205
+ ok(s2.get('masters').indexOf(m1) !== -1, 's2 should have m1 as a master');
206
+ ok(s2.get('masters').indexOf(m2) !== -1, 's2 should have m2 as a master');
207
+ });
208
+
209
+ /**
210
+ [slave] >--- X ---> [*]
211
+
212
+ precond - * is related to slave
213
+ test - after update to slave, * is related to slave
214
+ */
215
+ test("A slave does NOT update a relationship [one(slave) to *]", function () {
216
+ MyApp.Slave = SC.Record.extend({
217
+ relative: SC.Record.toOne('MyApp.Relative', {
218
+ inverse: 'slave',
219
+ isMaster: NO
220
+ })
221
+ });
222
+
223
+ MyApp.Relative = SC.Record.extend({
224
+ slave: SC.Record.toOne('MyApp.Slave', {
225
+ inverse: 'relative',
226
+ isMaster: YES
227
+ })
228
+ });
229
+
230
+ // case create slave WITHOUT relationship
231
+ SC.RunLoop.begin();
232
+ MyApp.store.loadRecords(MyApp.Slave, [
233
+ { guid: 's1' }
234
+ ]);
235
+
236
+ MyApp.store.loadRecords(MyApp.Relative, [
237
+ { guid: 'r1', slave: 's1' }
238
+ ]);
239
+ SC.RunLoop.end();
240
+
241
+ var s1 = MyApp.store.find(MyApp.Slave, 's1'),
242
+ r1 = MyApp.store.find(MyApp.Relative, 'r1');
243
+
244
+ equals(s1.get('relative'), r1, 'precond1 - s1 has relative r1');
245
+
246
+ SC.RunLoop.begin();
247
+ MyApp.store.loadRecords(MyApp.Slave, [
248
+ { guid: 's1' }
249
+ ]);
250
+ SC.RunLoop.end();
251
+
252
+ ok(SC.none(s1.get('relative')), 'precond2 - s1 has no relative');
253
+ equals(r1.get('slave'), s1, 'test1- r1 is related to s1');
254
+
255
+ // case - create slave WITH releationship
256
+ SC.RunLoop.begin();
257
+ MyApp.store.loadRecords(MyApp.Relative, [
258
+ { guid: 'r2'}
259
+ ]);
260
+
261
+ MyApp.store.loadRecords(MyApp.Slave, [
262
+ { guid: 's2', relative: 'r2' }
263
+ ]);
264
+ SC.RunLoop.end();
265
+
266
+ var s2 = MyApp.store.find(MyApp.Slave, 's2'),
267
+ r2 = MyApp.store.find(MyApp.Relative, 'r2');
268
+
269
+ equals(s2.get('relative'), r2, 'precond3 - s2 is related to r2');
270
+ ok(SC.none(r2.get('slave')), 'test2 - r2 should NOT have a slave');
271
+ });
272
+
273
+ /**
274
+ [master1] <----> [master2]
275
+
276
+ precond - master1 has master2
277
+ test - master2 has master1
278
+ */
279
+ test("A master will mutually update a master [one(master) to one(master)].", function () {
280
+ MyApp.Master = SC.Record.extend({
281
+ relative: SC.Record.toOne('MyApp.Master', {
282
+ inverse: 'relative',
283
+ isMaster: YES
284
+ })
285
+ });
286
+
287
+ SC.RunLoop.begin();
288
+ MyApp.store.loadRecords(MyApp.Master, [
289
+ { guid: 'm1' }
290
+ ]);
291
+
292
+ MyApp.store.loadRecords(MyApp.Master, [
293
+ { guid: 'm2', relative: 'm1' }
294
+ ]);
295
+ SC.RunLoop.end();
296
+
297
+ var m1 = MyApp.store.find(MyApp.Master, 'm1'),
298
+ m2 = MyApp.store.find(MyApp.Master, 'm2');
299
+
300
+ equals(m1.get('relative'), m2, 'precond - m1 should have a relative "m2"');
301
+ equals(m2.get('relative'), m1, 'm2 should have a relative "m1"');
302
+ });
303
+
304
+ // ..........................................................
305
+ // REPLACING RELATIONSHIPS
306
+ //
307
+
308
+ /**
309
+ [master1] <--> [slave]
310
+
311
+ precond - master1 has slave
312
+ precond - slave has master1
313
+
314
+ ...relate master2 to slave...
315
+
316
+ [master1] --> [slave]
317
+ ^
318
+ |
319
+ [master2] <----+
320
+
321
+ precond - master2 has slave
322
+ precond - slave has master2
323
+ test - master1 has slave
324
+ */
325
+ test("Stealing relationship does NOT propagate to other masters [one(master) to one(slave)]", function () {
326
+ MyApp.Slave = SC.Record.extend({
327
+ master: SC.Record.toOne('MyApp.Master', {
328
+ inverse: 'slave',
329
+ isMaster: NO
330
+ })
331
+ });
332
+
333
+ MyApp.Master = SC.Record.extend({
334
+ slave: SC.Record.toOne('MyApp.Slave', {
335
+ inverse: 'master',
336
+ isMaster: YES
337
+ })
338
+ });
339
+
340
+ SC.RunLoop.begin();
341
+ MyApp.store.loadRecords(MyApp.Slave, [
342
+ { guid: 's1' }
343
+ ]);
344
+
345
+ MyApp.store.loadRecords(MyApp.Master, [
346
+ { guid: 'm1', slave: 's1' }
347
+ ]);
348
+ SC.RunLoop.end();
349
+
350
+ var s1 = MyApp.store.find(MyApp.Slave, 's1'),
351
+ m1 = MyApp.store.find(MyApp.Master, 'm1');
352
+
353
+ equals(m1.get('slave'), s1, 'precond - m1 should have s1');
354
+ equals(s1.get('master'), m1, 'precond - s1 should relate to m1');
355
+
356
+ SC.RunLoop.begin();
357
+ MyApp.store.loadRecords(MyApp.Master, [
358
+ { guid: 'm2', slave: 's1' }
359
+ ]);
360
+ SC.RunLoop.end();
361
+
362
+ var m2 = MyApp.store.find(MyApp.Master, 'm2');
363
+
364
+ equals(m2.get('slave'), s1, 'precond - m2 should have s1');
365
+ equals(s1.get('master'), m2, 'precond - s1 should relate to m2');
366
+
367
+ equals(m1.get('slave'), s1, 'm1 should have child s1');
368
+ });
369
+
370
+
371
+ // ..........................................................
372
+ // RELINQUISHING RELATIONSHIPS
373
+ //
374
+
375
+ /**
376
+ [master] <----> [slave1]
377
+
378
+ precond - master has slave1
379
+ precond - slave1 has master
380
+
381
+ [master] <----> [slave2]
382
+
383
+ X--- [slave1]
384
+
385
+ precond - master has slave2
386
+ precond - slave2 has master
387
+
388
+ test - slave1 does NOT have master
389
+ */
390
+ test("Relinquishing relationship on master<->* does propagate [one(master) to one(*)]", function () {
391
+ MyApp.Slave = SC.Record.extend({
392
+ master: SC.Record.toOne('MyApp.Master', {
393
+ inverse: 'slave',
394
+ isMaster: NO
395
+ })
396
+ });
397
+
398
+ MyApp.Master = SC.Record.extend({
399
+ slave: SC.Record.toOne('MyApp.Slave', {
400
+ inverse: 'master',
401
+ isMaster: YES
402
+ })
403
+ });
404
+
405
+ SC.RunLoop.begin();
406
+ MyApp.store.loadRecords(MyApp.Slave, [
407
+ { guid: 's1' },
408
+ { guid: 's2' }
409
+ ]);
410
+
411
+ MyApp.store.loadRecords(MyApp.Master, [
412
+ { guid: 'm1', slave: 's1' }
413
+ ]);
414
+ SC.RunLoop.end();
415
+
416
+ var s1 = MyApp.store.find(MyApp.Slave, 's1'),
417
+ s2 = MyApp.store.find(MyApp.Slave, 's2'),
418
+ m1 = MyApp.store.find(MyApp.Master, 'm1');
419
+
420
+ equals(m1.get('slave'), s1, 'precond - m1 should have s1');
421
+ equals(s1.get('master'), m1, 'precond - s1 should relate to m1');
422
+ ok(SC.none(s2.get('master')), 'precond - s2 has NO master');
423
+
424
+ SC.RunLoop.begin();
425
+ MyApp.store.loadRecords(MyApp.Master, [
426
+ { guid: 'm1', slave: 's2' }
427
+ ]);
428
+ SC.RunLoop.end();
429
+
430
+ equals(m1.get('slave'), s2, 'precond - m1 should have s2');
431
+ equals(s2.get('master'), m1, 'precond - s2 should relate to m1');
432
+
433
+ ok(SC.none(s1.get('master')), 'test1 - s1 should have NO master');
434
+ });
435
+
436
+ /**
437
+ [master] <----> [slave1, ..., slaveN]
438
+
439
+ precond - master has slaves
440
+ precond - slaves have master
441
+
442
+ [master] ---X [slave1]
443
+
444
+ precond - master does NOT have slave1
445
+ test - slave1 does NOT have master
446
+ */
447
+ test("Relinquishing a toMany relationship does propagate from master [one(master) to many(*)]", function () {
448
+ MyApp.Slave = SC.Record.extend({
449
+ master: SC.Record.toOne('MyApp.Master', {
450
+ inverse: 'slaves',
451
+ isMaster: NO
452
+ })
453
+ });
454
+
455
+ MyApp.Master = SC.Record.extend({
456
+ slaves: SC.Record.toMany('MyApp.Slave', {
457
+ inverse: 'master',
458
+ isMaster: YES
459
+ })
460
+ });
461
+
462
+ SC.RunLoop.begin();
463
+ MyApp.store.loadRecords(MyApp.Slave, [
464
+ { guid: 's1' },
465
+ { guid: 's2' }
466
+ ]);
467
+
468
+ MyApp.store.loadRecords(MyApp.Master, [
469
+ { guid: 'm1', slaves: ['s1', 's2'] }
470
+ ]);
471
+ SC.RunLoop.end();
472
+
473
+ var s1 = MyApp.store.find(MyApp.Slave, 's1'),
474
+ s2 = MyApp.store.find(MyApp.Slave, 's2'),
475
+ m1 = MyApp.store.find(MyApp.Master, 'm1');
476
+
477
+ equals(m1.get('slaves').length(), 2, 'precond1 - m1 should have 2 slaves');
478
+ equals(s1.get('master'), m1, 'precond2 - s1 should relate to m1');
479
+ equals(s2.get('master'), m1, 'precond3 - s2 should relate to m1');
480
+
481
+ SC.RunLoop.begin();
482
+ MyApp.store.loadRecords(MyApp.Master, [
483
+ { guid: 'm1', slaves: ['s1'] }
484
+ ]);
485
+ SC.RunLoop.end();
486
+
487
+ equals(m1.get('slaves').length(), 1, 'precond4 - m1 should have 1 slave');
488
+ equals(m1.get('slaves').objectAt(0), s1, 'precond5 - m1 should have slave s1');
489
+ equals(s1.get('master'), m1, 'precond6 - s1 should relate to m1');
490
+
491
+ ok(SC.none(s2.get('master')), 's2 should NOT have master');
492
+ });
493
+
494
+ /**
495
+ [slave]
496
+ ^
497
+ |
498
+ +--< [master1]
499
+ |
500
+ ...
501
+ |
502
+ +--< [masterN]
503
+
504
+ precond - master1 has relationship to slave
505
+ precond - slave has relationship many masters
506
+ precond - slave has relationship to master1
507
+
508
+ ...master1 relinquishes relationship to slave...
509
+
510
+ [slave]
511
+ ^
512
+ |
513
+ ...
514
+ |
515
+ +--< [masterN]
516
+
517
+ precond - master1 has no slave
518
+ test - slave has many masters, none of which is master1
519
+
520
+ */
521
+ test("Relinquish propagates from many master to one slave [many(master) to one(slave)]", function () {
522
+ MyApp.Master = SC.Record.extend({
523
+ slave: SC.Record.toOne('MyApp.Slave', {
524
+ inverse: 'masters',
525
+ isMaster: YES
526
+ })
527
+ });
528
+
529
+ MyApp.Slave = SC.Record.extend({
530
+ masters: SC.Record.toMany('MyApp.Master', {
531
+ inverse: 'slave',
532
+ isMaster: NO
533
+ })
534
+ });
535
+
536
+ SC.RunLoop.begin();
537
+ MyApp.store.loadRecords(MyApp.Slave, [
538
+ { guid: 's1' }
539
+ ]);
540
+
541
+ MyApp.store.loadRecords(MyApp.Master, [
542
+ { guid: 'm1', slave: 's1' },
543
+ { guid: 'm2', slave: 's1' }
544
+ ]);
545
+ SC.RunLoop.end();
546
+
547
+ var m1 = MyApp.store.find(MyApp.Master, 'm1'),
548
+ m2 = MyApp.store.find(MyApp.Master, 'm2'),
549
+ s1 = MyApp.store.find(MyApp.Slave, 's1');
550
+
551
+ equals(s1.get('masters').length(), 2, 'precond - s1 should have 2 masters');
552
+ equals(m1.get('slave'), s1, 'precond - m1 should have slave s1');
553
+ equals(m2.get('slave'), s1, 'precond - m2 should have slave s1');
554
+
555
+ SC.RunLoop.begin();
556
+ MyApp.store.loadRecords(MyApp.Master, [
557
+ { guid: 'm1' }
558
+ ]);
559
+ SC.RunLoop.end();
560
+
561
+ ok(SC.none(m1.get('slave')), 'precond - m1 should NOT have relationship with s1');
562
+ equals(s1.get('masters').length(), 1, 's1 should have 1 master');
563
+ equals(s1.get('masters').indexOf(m1), -1, 'm1 should NOT be that master');
564
+ });
565
+
566
+ /**
567
+ [master1] ... [masterN]
568
+ v v
569
+ | |
570
+ >------- ... -> [slave1]
571
+ | |
572
+ ... ...
573
+ | |
574
+ >------- ... -> [slaveN]
575
+
576
+ precond - masters have many slaves
577
+ precond - slaves have many masters
578
+
579
+ ... master1 relinquishes relationship to slave1 ...
580
+
581
+ [master1] ... [masterN]
582
+ v v
583
+ | |
584
+ >-- X > [slave1]
585
+ | |
586
+ ... ...
587
+ | |
588
+ >------- ... -> [slaveM]
589
+
590
+ precond - master1 has M-1 slaves (& not slave 1)
591
+
592
+ test - slave1 has N-1 masters
593
+ test - slave does NOT have relationship to master1
594
+ */
595
+ test("Removing a relationship propagates from many master to many slave [many(master) to many(slave)]", function () {
596
+ MyApp.Master = SC.Record.extend({
597
+ slaves: SC.Record.toMany('MyApp.Slave', {
598
+ inverse: 'masters',
599
+ isMaster: YES
600
+ })
601
+ });
602
+
603
+ MyApp.Slave = SC.Record.extend({
604
+ masters: SC.Record.toMany('MyApp.Master', {
605
+ inverse: 'slaves',
606
+ isMaster: NO
607
+ })
608
+ });
609
+
610
+ SC.RunLoop.begin();
611
+ MyApp.store.loadRecords(MyApp.Slave, [
612
+ { guid: 's1' },
613
+ { guid: 's2' }
614
+ ]);
615
+
616
+ MyApp.store.loadRecords(MyApp.Master, [
617
+ { guid: 'm1', slaves: ['s1', 's2'] },
618
+ { guid: 'm2', slaves: ['s1', 's2'] }
619
+ ]);
620
+ SC.RunLoop.end();
621
+
622
+ var m1 = MyApp.store.find(MyApp.Master, 'm1'),
623
+ m2 = MyApp.store.find(MyApp.Master, 'm2'),
624
+ s1 = MyApp.store.find(MyApp.Slave, 's1'),
625
+ s2 = MyApp.store.find(MyApp.Slave, 's2');
626
+
627
+ equals(m1.get('slaves').length(), 2, 'precond - m1 should have 2 slaves');
628
+ equals(m2.get('slaves').length(), 2, 'precond - m2 should have 2 slaves');
629
+ ok(s1.get('masters').indexOf(m1) !== -1, 'precond - s1 should have m1 as a master');
630
+ ok(s1.get('masters').indexOf(m2) !== -1, 'precond - s1 should have m2 as a master');
631
+ ok(s2.get('masters').indexOf(m1) !== -1, 'precond - s2 should have m1 as a master');
632
+ ok(s2.get('masters').indexOf(m2) !== -1, 'precond - s2 should have m2 as a master');
633
+
634
+ SC.RunLoop.begin();
635
+ MyApp.store.loadRecords(MyApp.Master, [
636
+ { guid: 'm1', slaves: ['s2'] }
637
+ ]);
638
+ SC.RunLoop.end();
639
+
640
+ equals(m1.get('slaves').length(), 1, 'precond - m1 should have 1 slave');
641
+ equals(m1.get('slaves').objectAt(0), s2, 'precond - m1 should have relationship to s2');
642
+
643
+ ok(s1.get('masters').indexOf(m1) === -1, 's1 should NOT have m1 as a master');
644
+ ok(s1.get('masters').indexOf(m2) !== -1, 's1 should have m2 as a master');
645
+ });
646
+
647
+ // ..........................................................
648
+ // pushDestroy BEHAVIOR
649
+ //
650
+
651
+ /**
652
+ [master] --> [slave]
653
+
654
+ precond - master has slave
655
+ precond - slave has master
656
+
657
+ ... pushDestroy master ...
658
+
659
+ test - slave has NO master
660
+ */
661
+ test("pushDestroy record propagates from master to slave [*(master) to one(slave)]", function () {
662
+ MyApp.Master = SC.Record.extend({
663
+ slave: SC.Record.toOne('MyApp.Slave', {
664
+ inverse: 'master',
665
+ isMaster: YES
666
+ })
667
+ });
668
+
669
+ MyApp.Slave = SC.Record.extend({
670
+ master: SC.Record.toOne('MyApp.Master', {
671
+ inverse: 'slave',
672
+ isMaster: NO
673
+ })
674
+ });
675
+
676
+ SC.RunLoop.begin();
677
+ MyApp.store.loadRecords(MyApp.Slave, [
678
+ { guid: 's1' }
679
+ ]);
680
+
681
+ MyApp.store.loadRecords(MyApp.Master, [
682
+ { guid: 'm1', slave: 's1' }
683
+ ]);
684
+ SC.RunLoop.end();
685
+
686
+ var m1 = MyApp.store.find(MyApp.Master, 'm1'),
687
+ s1 = MyApp.store.find(MyApp.Slave, 's1');
688
+
689
+ equals(m1.get('slave'), s1, 'precond - m1 should have s1 as slave');
690
+ equals(s1.get('master'), m1, 'precond - s1 should have m1 as slave');
691
+
692
+ SC.RunLoop.begin();
693
+ MyApp.store.pushDestroy(MyApp.Master, 'm1');
694
+ SC.RunLoop.end();
695
+
696
+ equals(m1.get('status'), SC.Record.DESTROYED_CLEAN, 'precond - m1 was destroyed');
697
+ ok(SC.none(s1.get('master')), 's1 should NOT have a master');
698
+ });
699
+
700
+ /**
701
+ [master] --> [slave]
702
+
703
+ precond - master has slave
704
+ precond - slave has master
705
+
706
+ ... pushDestroy master ...
707
+
708
+ test - slave has NO master
709
+ */
710
+ test("pushDestroy record propagates from master to many slaves [*(master) to many(slave)]", function () {
711
+ MyApp.Master = SC.Record.extend({
712
+ slaves: SC.Record.toMany('MyApp.Slave', {
713
+ inverse: 'masters',
714
+ isMaster: YES
715
+ })
716
+ });
717
+
718
+ MyApp.Slave = SC.Record.extend({
719
+ masters: SC.Record.toMany('MyApp.Master', {
720
+ inverse: 'slaves',
721
+ isMaster: NO
722
+ })
723
+ });
724
+
725
+ SC.RunLoop.begin();
726
+ MyApp.store.loadRecords(MyApp.Slave, [
727
+ { guid: 's1' },
728
+ { guid: 's2' }
729
+ ]);
730
+
731
+ MyApp.store.loadRecords(MyApp.Master, [
732
+ { guid: 'm1', slaves: ['s1', 's2'] }
733
+ ]);
734
+ SC.RunLoop.end();
735
+
736
+ var m1 = MyApp.store.find(MyApp.Master, 'm1'),
737
+ s1 = MyApp.store.find(MyApp.Slave, 's1'),
738
+ s2 = MyApp.store.find(MyApp.Slave, 's2');
739
+
740
+ equals(m1.get('slaves').length(), 2, 'precond - m1 should have 2 slaves');
741
+ ok(s1.get('masters').indexOf(m1) !== -1, 'precond - s1 should have m1 as a master');
742
+ ok(s2.get('masters').indexOf(m1) !== -1, 'precond - s2 should have m1 as a master');
743
+
744
+ SC.RunLoop.begin();
745
+ MyApp.store.pushDestroy(MyApp.Master, 'm1');
746
+ SC.RunLoop.end();
747
+
748
+ equals(m1.get('status'), SC.Record.DESTROYED_CLEAN, 'precond - m1 was destroyed');
749
+ equals(s1.get('masters').length(), 0, 's1 should NOT have a master');
750
+ equals(s2.get('masters').length(), 0, 's2 should NOT have a master');
751
+ });
752
+
753
+ /**
754
+ [master] --> [slave]
755
+
756
+ precond - slave has a master
757
+ precond - master has a slave
758
+
759
+ slave.destroy();
760
+
761
+ precond - slave is destroyed
762
+
763
+ ... pushDestroy master ...
764
+
765
+ test - slave does NOT exist
766
+ test - master does NOT exist
767
+ */
768
+ test("pushDestroy record doesn't create a slave when it's been destroyed [*(master) to one(slave)]", function () {
769
+ MyApp.Master = SC.Record.extend({
770
+ slave: SC.Record.toOne('MyApp.Slave', {
771
+ inverse: 'master',
772
+ isMaster: YES
773
+ })
774
+ });
775
+
776
+ MyApp.Slave = SC.Record.extend({
777
+ master: SC.Record.toOne('MyApp.Master', {
778
+ inverse: 'slave',
779
+ isMaster: NO
780
+ })
781
+ });
782
+
783
+ SC.RunLoop.begin();
784
+ MyApp.store.loadRecords(MyApp.Slave, [
785
+ { guid: 's1' }
786
+ ]);
787
+
788
+ MyApp.store.loadRecords(MyApp.Master, [
789
+ { guid: 'm1', slave: 's1' }
790
+ ]);
791
+ SC.RunLoop.end();
792
+
793
+ var m1 = MyApp.store.find(MyApp.Master, 'm1'),
794
+ s1 = MyApp.store.find(MyApp.Slave, 's1');
795
+
796
+ equals(m1.get('slave'), s1, 'precond - m1 should have 2 slaves');
797
+ equals(s1.get('master'), m1, 'precond - s1 should have m1 as a master');
798
+
799
+ SC.RunLoop.begin();
800
+ s1.destroy();
801
+ MyApp.store.commitRecords();
802
+ MyApp.store.dataSourceDidDestroy(s1.storeKey);
803
+ SC.RunLoop.end();
804
+
805
+ ok(s1.isDestroyed(), 'precond - s1 should be destroyed');
806
+
807
+ SC.RunLoop.begin();
808
+ MyApp.store.pushDestroy(MyApp.Master, 'm1');
809
+ SC.RunLoop.end();
810
+
811
+ ok(s1.isDestroyed(), 'test - s1 should be destroyed');
812
+ ok(m1.isDestroyed(), 'test - m1 should be destroyed');
813
+ });
814
+
815
+ /**
816
+ Standard Sproutcore Behaviors
817
+
818
+ This is data showing up from the server- after pushing in changes,
819
+ all records should have status READY_CLEAN.
820
+ */
821
+ test("Record status for master and slave should be READY_CLEAN", function () {
822
+ MyApp.Master = SC.Record.extend({
823
+ master: SC.Record.toOne('MyApp.Slave', {
824
+ inverse: 'slave',
825
+ isMaster: YES
826
+ })
827
+ });
828
+
829
+ MyApp.Slave = SC.Record.extend({
830
+ slave: SC.Record.toOne('MyApp.Master', {
831
+ inverse: 'master',
832
+ isMaster: NO
833
+ })
834
+ });
835
+
836
+ // link one -> one
837
+ SC.RunLoop.begin();
838
+ MyApp.store.loadRecords(MyApp.Slave, [
839
+ { guid: 's1' }
840
+ ]);
841
+ SC.RunLoop.end();
842
+
843
+ var s1 = MyApp.store.find(MyApp.Slave, 's1');
844
+ ok(s1.get('status') & SC.Record.READY_CLEAN, 'precond - s1 should be ready clean');
845
+
846
+ SC.RunLoop.begin();
847
+ MyApp.store.loadRecords(MyApp.Master, [
848
+ { guid: 'm1', slave: 's1' }
849
+ ]);
850
+ SC.RunLoop.end();
851
+
852
+ var m1 = MyApp.store.find(MyApp.Master, 'm1');
853
+
854
+ ok(m1.get('status') & SC.Record.READY_CLEAN, 'm1 should be ready clean after linkage');
855
+ ok(s1.get('status') & SC.Record.READY_CLEAN, 's1 should be ready clean after linkage');
856
+
857
+ // unlink
858
+ SC.RunLoop.begin();
859
+ MyApp.store.loadRecords(MyApp.Master, [
860
+ { guid: 'm1' }
861
+ ]);
862
+ SC.RunLoop.end();
863
+
864
+ ok(m1.get('status') & SC.Record.READY_CLEAN, 'm1 should be ready clean after unlink');
865
+ ok(s1.get('status') & SC.Record.READY_CLEAN, 's1 should be ready clean after unlink');
866
+ });
867
+
868
+ test("Record relationships are NOT propagated if related store item does NOT exist at load time", function () {
869
+ MyApp.Generic = SC.Record.extend({
870
+ relative: SC.Record.toOne('MyApp.Generic', {
871
+ inverse: 'relative',
872
+ isMaster: YES
873
+ })
874
+ });
875
+
876
+ SC.RunLoop.begin();
877
+ MyApp.store.loadRecords(MyApp.Generic, [
878
+ { guid: 'g2', relative: 'g1' },
879
+ { guid: 'g1' }
880
+ ]);
881
+ SC.RunLoop.end();
882
+
883
+ var g1 = MyApp.store.find(MyApp.Generic, 'g1'),
884
+ g2 = MyApp.store.find(MyApp.Generic, 'g2');
885
+
886
+ equals(g2.get('relative'), g1, 'precond - g2 should be relative of g1');
887
+ ok(SC.none(g1.get('relative')), 'g1 should not be related to g2');
888
+ });
889
+
890
+ test("Record Attribute can reference renamed attribute key", function () {
891
+ MyApp.Master = SC.Record.extend({
892
+ slave: SC.Record.toOne('MyApp.Slave', {
893
+ inverse: 'master',
894
+ isMaster: YES,
895
+ key: 'alice'
896
+ })
897
+ });
898
+
899
+ MyApp.Slave = SC.Record.extend({
900
+ master: SC.Record.toOne('MyApp.Master', {
901
+ inverse: 'slave',
902
+ isMaster: NO
903
+ })
904
+ });
905
+
906
+ // link one -> one
907
+ SC.RunLoop.begin();
908
+ MyApp.store.loadRecords(MyApp.Slave, [
909
+ { guid: 's1' }
910
+ ]);
911
+ SC.RunLoop.end();
912
+
913
+
914
+ var s1 = MyApp.store.find(MyApp.Slave, 's1');
915
+ ok(s1.get('status') & SC.Record.READY_CLEAN, 'precond - s1 should be ready clean');
916
+
917
+ SC.RunLoop.begin();
918
+ MyApp.store.loadRecords(MyApp.Master, [
919
+ { guid: 'm1', alice: 's1' }
920
+ ]);
921
+ SC.RunLoop.end();
922
+
923
+ var m1 = MyApp.store.find(MyApp.Master, 'm1');
924
+
925
+ equals(m1.get('slave'), s1, 'm1 should be master of s1');
926
+ equals(s1.get('master'), m1, 's1 should have master of m1');
927
+ });
928
+
929
+
930
+ test("Record Attribute can reference renamed attribute key (on remote side)", function () {
931
+ MyApp.Master = SC.Record.extend({
932
+ slave: SC.Record.toOne('MyApp.Slave', {
933
+ inverse: 'master',
934
+ isMaster: YES
935
+ })
936
+ });
937
+
938
+ MyApp.Slave = SC.Record.extend({
939
+ master: SC.Record.toOne('MyApp.Master', {
940
+ inverse: 'slave',
941
+ isMaster: NO,
942
+ key: 'bob'
943
+ })
944
+ });
945
+
946
+ // link one -> one
947
+ SC.RunLoop.begin();
948
+ MyApp.store.loadRecords(MyApp.Slave, [
949
+ { guid: 's1' }
950
+ ]);
951
+ SC.RunLoop.end();
952
+
953
+
954
+ var s1 = MyApp.store.find(MyApp.Slave, 's1');
955
+ ok(s1.get('status') & SC.Record.READY_CLEAN, 'precond - s1 should be ready clean');
956
+
957
+ SC.RunLoop.begin();
958
+ MyApp.store.loadRecords(MyApp.Master, [
959
+ { guid: 'm1', slave: 's1' }
960
+ ]);
961
+ SC.RunLoop.end();
962
+
963
+ var m1 = MyApp.store.find(MyApp.Master, 'm1');
964
+
965
+ equals(m1.get('slave'), s1, 'm1 should be master of s1');
966
+ equals(s1.get('master'), m1, 's1 should have master of m1');
967
+ });
968
+
969
+ test("Record property does change on linkage", function () {
970
+ MyApp.Generic = SC.Record.extend({
971
+ relative: SC.Record.toOne('MyApp.Generic', {
972
+ inverse: 'relative',
973
+ isMaster: YES
974
+ }),
975
+
976
+ callCount: 0,
977
+
978
+ _relativeObserver: function () {
979
+ this.incrementProperty('callCount');
980
+ }.observes('relative')
981
+ });
982
+
983
+ SC.RunLoop.begin();
984
+ MyApp.store.loadRecords(MyApp.Generic, [
985
+ { guid: 'g1' },
986
+ { guid: 'g2' }
987
+ ]);
988
+ SC.RunLoop.end();
989
+
990
+ var g1 = MyApp.store.find(MyApp.Generic, 'g1'),
991
+ g2 = MyApp.store.find(MyApp.Generic, 'g2');
992
+
993
+ equals(g1.get('callCount'), 0, 'precond - g1._relativeObserver should NOT have fired yet');
994
+ equals(g2.get('callCount'), 0, 'precond - g2._relativeObserver should NOT have fired yet');
995
+
996
+ SC.RunLoop.begin();
997
+ MyApp.store.loadRecords(MyApp.Generic, [
998
+ { guid: 'g2', relative: 'g1' }
999
+ ]);
1000
+ SC.RunLoop.end();
1001
+
1002
+ equals(g1.get('relative'), g2, 'precond - g1 should be relative of g2');
1003
+ equals(g2.get('relative'), g1, 'precond - g2 should be relative of g1');
1004
+
1005
+ equals(g1.get('callCount'), 1, 'g1._relativeObserver should fire once');
1006
+ equals(g2.get('callCount'), 1, 'g2._relativeObserver should fire once');
1007
+ });
1008
+
1009
+ // ..........................................................
1010
+ // RECORD ATTRIBUTE
1011
+ //
1012
+
1013
+ /**
1014
+ lazilyInstantiate RecordAttribute flag tests.
1015
+ */
1016
+ test("RecordAttribute flag 'lazilyInstantiate' tests", function () {
1017
+ MyApp.Master = SC.Record.extend({
1018
+ slave: SC.Record.toOne('MyApp.Slave', {
1019
+ inverse: 'master',
1020
+ isMaster: YES,
1021
+ lazilyInstantiate: YES
1022
+ })
1023
+ });
1024
+
1025
+ MyApp.Slave = SC.Record.extend({
1026
+ master: SC.Record.toOne('MyApp.Master', {
1027
+ inverse: 'slave',
1028
+ isMaster: NO,
1029
+ lazilyInstantiate: YES // should be a noop
1030
+ })
1031
+ });
1032
+
1033
+ SC.RunLoop.begin();
1034
+ MyApp.store.loadRecords(MyApp.Master, [
1035
+ { guid: 'm1', slave: 's1' }
1036
+ ]);
1037
+
1038
+ MyApp.store.loadRecords(MyApp.Slave, [
1039
+ { guid: 's2', master: 'm2' }
1040
+ ]);
1041
+ SC.RunLoop.end();
1042
+
1043
+ var m1 = MyApp.store.find(MyApp.Master, 'm1'),
1044
+ m2 = MyApp.store.find(MyApp.Master, 'm2'),
1045
+ s1 = MyApp.store.find(MyApp.Slave, 's1'),
1046
+ s2 = MyApp.store.find(MyApp.Slave, 's2');
1047
+
1048
+ // test lazy creation on isMaster => YES
1049
+ ok(s1, 's1 should be created lazily');
1050
+ equals(m1.get('slave'), s1, 'm1 should be master of s1');
1051
+
1052
+ // test lazy creation fails on isMaster => NO
1053
+ ok(SC.none(m2), 'm2 should NOT have been creaetd');
1054
+ ok(!s2.get('master') ||
1055
+ s2.get('master').get('status') & SC.Record.ERROR, 's2 should have no master record');
1056
+ });
1057
+
1058
+ /**
1059
+ lazilyInstantiate RecordAttribute flag can be a function.
1060
+ */
1061
+ test("RecordAttribute flag 'lazilyInstantiate' can be a function", function () {
1062
+ MyApp.Master = SC.Record.extend({
1063
+ slave: SC.Record.toOne('MyApp.Slave', {
1064
+ inverse: 'master',
1065
+ isMaster: YES,
1066
+ lazilyInstantiate: function () {
1067
+ return NO;
1068
+ }
1069
+ })
1070
+ });
1071
+
1072
+ MyApp.Slave = SC.Record.extend({
1073
+ master: SC.Record.toOne('MyApp.Master', {
1074
+ inverse: 'slave',
1075
+ isMaster: NO,
1076
+ lazilyInstantiate: YES // should be a noop
1077
+ })
1078
+ });
1079
+
1080
+ SC.RunLoop.begin();
1081
+ MyApp.store.loadRecords(MyApp.Master, [
1082
+ { guid: 'm1', slave: 's1' }
1083
+ ]);
1084
+
1085
+ MyApp.store.loadRecords(MyApp.Slave, [
1086
+ { guid: 's2', master: 'm2' }
1087
+ ]);
1088
+ SC.RunLoop.end();
1089
+
1090
+ var m1 = MyApp.store.find(MyApp.Master, 'm1'),
1091
+ m2 = MyApp.store.find(MyApp.Master, 'm2'),
1092
+ s1 = MyApp.store.find(MyApp.Slave, 's1'),
1093
+ s2 = MyApp.store.find(MyApp.Slave, 's2');
1094
+
1095
+ // test lazy creation on isMaster => NO
1096
+ ok(!s1, 's1 should NOT be created lazily');
1097
+
1098
+ // test lazy creation fails on isMaster => NO
1099
+ ok(SC.none(m2), 'm2 should NOT have been creaetd');
1100
+ ok(!s2.get('master') ||
1101
+ s2.get('master').get('status') & SC.Record.ERROR, 's2 should have no master record');
1102
+ });
1103
+
1104
+
1105
+ /**
1106
+ lazilyInstantiate should ride the chain all the way to the top.
1107
+
1108
+ That is, if a record's primaryKey is a record that has the
1109
+ flag 'lazilyInstantiate' on it, it should lazily create that one,
1110
+ and so on.
1111
+ */
1112
+ test("RecordAttribute flag 'lazilyInstantiate' will create chains of records properly", function () {
1113
+ MyApp.SuperMaster = SC.Record.extend({
1114
+ master: SC.Record.toOne('MyApp.Master', {
1115
+ inverse: 'superMaster',
1116
+ isMaster: YES,
1117
+ lazilyInstantiate: YES
1118
+ })
1119
+ });
1120
+
1121
+ MyApp.Master = SC.Record.extend({
1122
+ primaryKey: 'slave',
1123
+
1124
+ superMaster: SC.Record.toOne('MyApp.SuperMaster', {
1125
+ inverse: 'master',
1126
+ isMaster: NO
1127
+ }),
1128
+
1129
+ slave: SC.Record.toOne('MyApp.Slave', {
1130
+ inverse: 'master',
1131
+ isMaster: YES,
1132
+ lazilyInstantiate: YES
1133
+ })
1134
+ });
1135
+
1136
+ MyApp.Slave = SC.Record.extend({
1137
+ primaryKey: 'subSlave',
1138
+
1139
+ master: SC.Record.toOne('MyApp.Master', {
1140
+ inverse: 'slave',
1141
+ isMaster: NO
1142
+ }),
1143
+
1144
+ subSlave: SC.Record.toOne('MyApp.SubSlave', {
1145
+ inverse: 'slave',
1146
+ isMaster: YES,
1147
+ lazilyInstantiate: YES
1148
+ })
1149
+ });
1150
+
1151
+ MyApp.SubSlave = SC.Record.extend({
1152
+ slave: SC.Record.toOne('MyApp.Slave', {
1153
+ inverse: 'subSlave',
1154
+ isMaster: NO
1155
+ })
1156
+ });
1157
+
1158
+ SC.RunLoop.begin();
1159
+ MyApp.store.loadRecords(MyApp.SuperMaster, [
1160
+ { guid: 'sm', master: 's' }
1161
+ ]);
1162
+ SC.RunLoop.end();
1163
+
1164
+ var sm = MyApp.store.find(MyApp.SuperMaster, 'sm'),
1165
+ m = MyApp.store.find(MyApp.Master, 's'),
1166
+ s = MyApp.store.find(MyApp.Slave, 's'),
1167
+ ss = MyApp.store.find(MyApp.SubSlave, 's');
1168
+
1169
+ ok(m, 'm should be created lazily');
1170
+ equals(m.get('superMaster'), sm, 'sm should be master of m');
1171
+
1172
+ ok(s, 's should be created lazily');
1173
+ equals(s.get('master'), m, 'm should be master of s');
1174
+
1175
+ ok(ss, 'ss should be created lazily');
1176
+ equals(ss.get('slave'), s, 's should be master of ss');
1177
+ });