sproutit-sproutcore 1.0.20090721145281 → 1.0.20090721145282

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 (105) hide show
  1. data/Buildfile +4 -3
  2. data/VERSION.yml +2 -2
  3. data/buildtasks/entry.rake +3 -0
  4. data/buildtasks/manifest.rake +35 -9
  5. data/buildtasks/target.rake +25 -6
  6. data/frameworks/sproutcore/Buildfile +10 -0
  7. data/frameworks/sproutcore/frameworks/datastore/data_sources/data_source.js +41 -20
  8. data/frameworks/sproutcore/frameworks/datastore/data_sources/fixtures.js +14 -43
  9. data/frameworks/sproutcore/frameworks/datastore/models/record.js +11 -0
  10. data/frameworks/sproutcore/frameworks/datastore/models/record_attribute.js +6 -3
  11. data/frameworks/sproutcore/frameworks/datastore/system/nested_store.js +5 -1
  12. data/frameworks/sproutcore/frameworks/datastore/system/query.js +10 -7
  13. data/frameworks/sproutcore/frameworks/datastore/system/record_array.js +19 -20
  14. data/frameworks/sproutcore/frameworks/datastore/system/store.js +126 -93
  15. data/frameworks/sproutcore/frameworks/datastore/tests/data_sources/fixtures.js +9 -3
  16. data/frameworks/sproutcore/frameworks/datastore/tests/models/many_attribute.js +6 -1
  17. data/frameworks/sproutcore/frameworks/datastore/tests/models/record/core_methods.js +28 -3
  18. data/frameworks/sproutcore/frameworks/datastore/tests/models/record/destroy.js +13 -5
  19. data/frameworks/sproutcore/frameworks/datastore/tests/models/record/storeDidChangeProperties.js +46 -23
  20. data/frameworks/sproutcore/frameworks/datastore/tests/models/record/writeAttribute.js +29 -5
  21. data/frameworks/sproutcore/frameworks/datastore/tests/models/record_attribute.js +13 -4
  22. data/frameworks/sproutcore/frameworks/datastore/tests/system/nested_store/chain.js +109 -0
  23. data/frameworks/sproutcore/frameworks/datastore/tests/system/nested_store/commitChanges.js +69 -15
  24. data/frameworks/sproutcore/frameworks/datastore/tests/system/nested_store/commitChangesFromNestedStore.js +20 -1
  25. data/frameworks/sproutcore/frameworks/datastore/tests/system/nested_store/dataHashDidChange.js +4 -1
  26. data/frameworks/sproutcore/frameworks/datastore/tests/system/query/find_all.js +56 -6
  27. data/frameworks/sproutcore/frameworks/datastore/tests/system/store/commitRecord.js +9 -2
  28. data/frameworks/sproutcore/frameworks/datastore/tests/system/store/core_methods.js +45 -2
  29. data/frameworks/sproutcore/frameworks/datastore/tests/system/store/recordDidChange.js +0 -1
  30. data/frameworks/sproutcore/frameworks/datastore/tests/system/store/retrieveRecord.js +53 -6
  31. data/frameworks/sproutcore/frameworks/datastore/tests/system/store/writeDataHash.js +0 -5
  32. data/frameworks/sproutcore/frameworks/desktop/panes/menu.js +47 -27
  33. data/frameworks/sproutcore/frameworks/desktop/system/drag.js +5 -4
  34. data/frameworks/sproutcore/frameworks/desktop/tests/views/collection/mouse.js +23 -12
  35. data/frameworks/sproutcore/frameworks/desktop/tests/views/list/render.js +92 -0
  36. data/frameworks/sproutcore/frameworks/desktop/tests/views/select_field/methods.js +104 -53
  37. data/frameworks/sproutcore/frameworks/desktop/tests/views/select_field/ui.js +2 -0
  38. data/frameworks/sproutcore/frameworks/desktop/views/button.js +4 -3
  39. data/frameworks/sproutcore/frameworks/desktop/views/collection.js +6 -2
  40. data/frameworks/sproutcore/frameworks/desktop/views/list.js +9 -0
  41. data/frameworks/sproutcore/frameworks/desktop/views/list_item.js +2 -2
  42. data/frameworks/sproutcore/frameworks/desktop/views/menu_item.js +3 -3
  43. data/frameworks/sproutcore/frameworks/desktop/views/popup_button.js +9 -1
  44. data/frameworks/sproutcore/frameworks/desktop/views/select_field.js +80 -102
  45. data/frameworks/sproutcore/frameworks/foundation/controllers/array.js +0 -1
  46. data/frameworks/sproutcore/frameworks/foundation/english.lproj/text_field.css +5 -1
  47. data/frameworks/sproutcore/frameworks/foundation/panes/pane.js +8 -1
  48. data/frameworks/sproutcore/frameworks/foundation/private/tree_item_observer.js +0 -1
  49. data/frameworks/sproutcore/frameworks/foundation/system/datetime.js +31 -3
  50. data/frameworks/sproutcore/frameworks/foundation/system/event.js +0 -4
  51. data/frameworks/sproutcore/frameworks/foundation/system/render_context.js +3 -7
  52. data/frameworks/sproutcore/frameworks/foundation/system/request.js +3 -4
  53. data/frameworks/sproutcore/frameworks/foundation/system/user_defaults.js +78 -17
  54. data/frameworks/sproutcore/frameworks/foundation/system/utils.js +9 -0
  55. data/frameworks/sproutcore/frameworks/foundation/tests/controllers/array/single_case.js +2 -2
  56. data/frameworks/sproutcore/frameworks/foundation/tests/system/core_query/jquery_selector.js +2 -2
  57. data/frameworks/sproutcore/frameworks/foundation/tests/system/datetime.js +5 -0
  58. data/frameworks/sproutcore/frameworks/foundation/tests/system/request.js +2 -2
  59. data/frameworks/sproutcore/frameworks/foundation/tests/system/user_defaults.js +1 -4
  60. data/frameworks/sproutcore/frameworks/foundation/tests/validators/validator.js +20 -0
  61. data/frameworks/sproutcore/frameworks/foundation/tests/views/image/ui.js +13 -0
  62. data/frameworks/sproutcore/frameworks/foundation/tests/views/text_field/ui.js +132 -0
  63. data/frameworks/sproutcore/frameworks/foundation/tests/views/view/isVisibleInWindow.js +6 -3
  64. data/frameworks/sproutcore/frameworks/foundation/validators/validator.js +8 -5
  65. data/frameworks/sproutcore/frameworks/foundation/views/image.js +18 -5
  66. data/frameworks/sproutcore/frameworks/foundation/views/text_field.js +292 -21
  67. data/frameworks/sproutcore/frameworks/foundation/views/view.js +13 -14
  68. data/frameworks/sproutcore/frameworks/mini/license.js +28 -0
  69. data/frameworks/sproutcore/frameworks/runtime/core.js +35 -0
  70. data/frameworks/sproutcore/frameworks/runtime/mixins/enumerable.js +1 -1
  71. data/frameworks/sproutcore/frameworks/runtime/system/sparse_array.js +79 -5
  72. data/frameworks/sproutcore/frameworks/runtime/tests/mixins/enumerable.js +6 -6
  73. data/frameworks/sproutcore/frameworks/runtime/tests/system/sparse_array.js +53 -0
  74. data/frameworks/sproutcore/frameworks/testing/system/plan.js +4 -0
  75. data/frameworks/sproutcore/frameworks/testing/system/runner.js +1 -1
  76. data/frameworks/sproutcore/themes/standard_theme/english.lproj/radio.css +4 -0
  77. data/gen/design/Buildfile +23 -0
  78. data/gen/design/README +1 -0
  79. data/gen/design/USAGE +10 -0
  80. data/gen/design/templates/english.lproj/@filename@.js +16 -0
  81. data/gen/page/Buildfile +36 -0
  82. data/gen/page/README +1 -0
  83. data/gen/page/USAGE +15 -0
  84. data/gen/page/templates/pages/@target_name@/Buildfile +16 -0
  85. data/gen/page/templates/pages/@target_name@/core.js +22 -0
  86. data/gen/page/templates/pages/@target_name@/english.lproj/body.css +1 -0
  87. data/gen/page/templates/pages/@target_name@/english.lproj/body.rhtml +7 -0
  88. data/gen/page/templates/pages/@target_name@/english.lproj/strings.js +15 -0
  89. data/gen/view/README +1 -1
  90. data/gen/view/USAGE +5 -5
  91. data/lib/sproutcore/builders/base.rb +13 -2
  92. data/lib/sproutcore/builders/html.rb +28 -1
  93. data/lib/sproutcore/builders/minify.rb +84 -18
  94. data/lib/sproutcore/builders/test.rb +2 -1
  95. data/lib/sproutcore/helpers/entry_sorter.rb +16 -1
  96. data/lib/sproutcore/helpers/static_helper.rb +32 -4
  97. data/lib/sproutcore/helpers/tag_helper.rb +65 -0
  98. data/lib/sproutcore/models/manifest.rb +40 -6
  99. data/lib/sproutcore/models/target.rb +12 -3
  100. data/lib/sproutcore/rack/builder.rb +56 -4
  101. data/lib/sproutcore/tools/manifest.rb +1 -0
  102. data/lib/sproutcore/tools/server.rb +1 -0
  103. data/lib/sproutcore/tools.rb +21 -1
  104. data/lib/sproutcore.rb +13 -0
  105. metadata +16 -1
@@ -8,6 +8,8 @@
8
8
  var store, child, Foo, json, foo ;
9
9
  module("SC.Record#storeDidChangeProperties", {
10
10
  setup: function() {
11
+ SC.RunLoop.begin();
12
+
11
13
  store = SC.Store.create();
12
14
  Foo = SC.Record.extend({
13
15
 
@@ -33,7 +35,9 @@ module("SC.Record#storeDidChangeProperties", {
33
35
  };
34
36
 
35
37
  foo = store.createRecord(Foo, json);
36
- store.writeStatus(foo.storeKey, SC.Record.READY_CLEAN);
38
+ store.writeStatus(foo.storeKey, SC.Record.READY_CLEAN);
39
+
40
+ SC.RunLoop.end();
37
41
  }
38
42
  });
39
43
 
@@ -42,9 +46,9 @@ function checkPreconditions() {
42
46
  equals(foo.fooCnt, 0, 'precond - fooCnt');
43
47
  }
44
48
 
45
- function expect(expectedStatusCnt, expectedFooCnt) {
46
- equals(foo.statusCnt, expectedStatusCnt, 'status should have changed');
47
- equals(foo.fooCnt, expectedFooCnt, 'foo should have changed');
49
+ function expect(fooObject, expectedStatusCnt, expectedFooCnt) {
50
+ equals(fooObject.statusCnt, expectedStatusCnt, 'status should have changed');
51
+ equals(fooObject.fooCnt, expectedFooCnt, 'foo should have changed');
48
52
  }
49
53
 
50
54
  // ..........................................................
@@ -56,7 +60,7 @@ test("should change status only if statusOnly=YES", function() {
56
60
 
57
61
  foo.storeDidChangeProperties(YES);
58
62
 
59
- expect(1,0);
63
+ expect(foo,1,0);
60
64
  });
61
65
 
62
66
 
@@ -65,7 +69,7 @@ test("should change attrs & status if statusOnly=NO", function() {
65
69
 
66
70
  foo.storeDidChangeProperties(NO);
67
71
 
68
- expect(1,1);
72
+ expect(foo,1,1);
69
73
  });
70
74
 
71
75
  // ..........................................................
@@ -74,65 +78,84 @@ test("should change attrs & status if statusOnly=NO", function() {
74
78
 
75
79
  test("editing a clean record should change all", function() {
76
80
  checkPreconditions();
81
+ SC.RunLoop.begin();
77
82
  foo.writeAttribute("foo", "bar");
78
- expect(1,1);
83
+ SC.RunLoop.end();
84
+ expect(foo,1,1);
79
85
  });
80
86
 
81
87
  test("destroying a record should change all", function() {
82
88
  checkPreconditions();
89
+ SC.RunLoop.begin();
83
90
  foo.destroy();
84
- expect(1,1);
91
+ SC.RunLoop.end();
92
+ expect(foo,1,1);
85
93
  });
86
94
 
87
95
  test("refreshing a record should change status", function() {
88
96
  checkPreconditions();
97
+ SC.RunLoop.begin();
89
98
  foo.refresh();
90
- expect(1,0);
99
+ SC.RunLoop.end();
100
+ expect(foo,1,0);
91
101
  });
92
102
 
93
103
  test("committing attribute changes from nested store should change attrs", function() {
94
104
  checkPreconditions();
95
105
 
106
+ SC.RunLoop.begin();
96
107
  var child = store.chain();
97
108
  var foo2 = child.materializeRecord(foo.storeKey);
98
109
  foo2.writeAttribute('foo', 'bar');
99
-
110
+ SC.RunLoop.end();
100
111
  // no changes should happen yet on foo.
101
- expect(0,0);
112
+ expect(foo,0,0);
102
113
 
114
+ SC.RunLoop.begin();
103
115
  // commit
104
116
  child.commitChanges();
117
+ SC.RunLoop.end();
105
118
 
106
119
  // now changes
107
- expect(1,1);
120
+ expect(foo,1,1);
108
121
  });
109
122
 
110
123
  test("changing attributes on a parent store should notify child store if inherited", function() {
111
-
112
124
  var child = store.chain();
113
125
  var oldfoo = foo;
114
- foo = child.materializeRecord(foo.storeKey);
126
+ var parentfoo = store.materializeRecord(foo.storeKey);
127
+ var childfoo = child.materializeRecord(foo.storeKey);
115
128
  equals(child.storeKeyEditState(foo.storeKey), SC.Store.INHERITED, 'precond - foo should be inherited from parent store');
116
129
 
117
- oldfoo.writeAttribute('foo', 'bar');
130
+ SC.RunLoop.begin();
131
+ parentfoo.writeAttribute('foo', 'bar');
132
+ SC.RunLoop.end();
118
133
 
119
- expect(1,1); // should reflect on child
134
+ expect(childfoo,1,1); // should reflect on child
120
135
  });
121
136
 
122
137
  test("changing attributes on a parent store should NOT notify child store if locked", function() {
123
138
 
124
139
  var child = store.chain();
125
140
  var oldfoo = foo;
126
- foo = child.materializeRecord(foo.storeKey);
127
- foo.readAttribute('foo');
141
+ var parentfoo = store.materializeRecord(foo.storeKey);
142
+ var childfoo = child.materializeRecord(foo.storeKey);
143
+ childfoo.readAttribute('foo');
128
144
  equals(child.storeKeyEditState(foo.storeKey), SC.Store.EDITABLE, 'precond - foo should be locked from parent store');
129
145
 
130
- oldfoo.writeAttribute('foo', 'bar');
131
-
132
- expect(0,0); // should not reflect on child
133
-
146
+ SC.RunLoop.begin();
147
+ parentfoo.writeAttribute('foo', 'bar');
148
+ SC.RunLoop.end();
149
+ expect(childfoo,0,0); // should not reflect on child
150
+ expect(parentfoo,1,1);
134
151
  // discarding changes should update
152
+
153
+ // NOTE: recourds should change immediately on commit/discard changes.
154
+ // test results here BEFORE run loop ends
155
+ SC.RunLoop.begin();
135
156
  child.discardChanges(); // make it match parent again
136
- expect(1,1);
157
+ expect(childfoo,1,1); //the childfoo record is reset to whatever the parentValue is.
158
+ SC.RunLoop.end();
159
+
137
160
  });
138
161
 
@@ -8,17 +8,20 @@
8
8
  var store, Foo, json, foo ;
9
9
  module("SC.Record#writeAttribute", {
10
10
  setup: function() {
11
+ SC.RunLoop.begin();
11
12
  store = SC.Store.create();
12
13
  Foo = SC.Record.extend();
13
14
  json = {
14
15
  foo: "bar",
15
16
  number: 123,
16
17
  bool: YES,
17
- array: [1,2,3]
18
+ array: [1,2,3],
19
+ guid: 1
18
20
  };
19
21
 
20
22
  foo = store.createRecord(Foo, json);
21
- store.writeStatus(foo.storeKey, SC.Record.READY_CLEAN);
23
+ store.writeStatus(foo.storeKey, SC.Record.READY_CLEAN);
24
+ SC.RunLoop.end();
22
25
  }
23
26
  });
24
27
 
@@ -30,9 +33,11 @@ test("first time writing should mark record as dirty", function() {
30
33
  // precondition
31
34
  equals(foo.get('status'), SC.Record.READY_CLEAN, 'precond - start clean');
32
35
 
36
+ SC.RunLoop.begin();
33
37
  // action
34
38
  foo.writeAttribute("bar", "baz");
35
-
39
+ SC.RunLoop.end();
40
+
36
41
  // evaluate
37
42
  equals(foo.get('status'), SC.Record.READY_DIRTY, 'should make READY_DIRTY after write');
38
43
  });
@@ -42,14 +47,18 @@ test("state change should be deferred if writing inside of a beginEditing()/endE
42
47
  // precondition
43
48
  equals(foo.get('status'), SC.Record.READY_CLEAN, 'precond - start clean');
44
49
 
50
+ SC.RunLoop.begin();
45
51
  // action
46
52
  foo.beginEditing();
53
+
47
54
  foo.writeAttribute("bar", "baz");
48
-
55
+
49
56
  equals(foo.get('status'), SC.Record.READY_CLEAN, 'should not change state yet');
50
57
 
51
58
  foo.endEditing();
52
-
59
+
60
+ SC.RunLoop.end();
61
+
53
62
  // evaluate
54
63
  equals(foo.get('status'), SC.Record.READY_DIRTY, 'should make READY_DIRTY after write');
55
64
 
@@ -69,3 +78,18 @@ test("raises exception if you try to write an attribute before an attribute hash
69
78
  equals(cnt, 1, 'should raise exception');
70
79
  });
71
80
 
81
+
82
+ test("Writing to an attribute in chained store sets correct status", function() {
83
+
84
+ var chainedStore = store.chain() ;
85
+
86
+ var chainedRecord = chainedStore.find(Foo, foo.readAttribute('guid'));
87
+ equals(chainedRecord.get('status'), SC.Record.READY_CLEAN, 'precon - status should be READY_CLEAN');
88
+
89
+ chainedRecord.writeAttribute('foo', 'newValue');
90
+ //chainedRecord.set('foo', 'newValue');
91
+
92
+ equals(chainedRecord.get('status'), SC.Record.READY_DIRTY, 'status should be READY_DIRTY');
93
+
94
+ });
95
+
@@ -6,7 +6,8 @@
6
6
  /*globals module ok equals same test MyApp */
7
7
 
8
8
  // test core array-mapping methods for RecordArray with RecordAttribute
9
- var storeKeys, rec;
9
+ var storeKeys, rec, rec2, bar ;
10
+
10
11
  module("SC.RecordAttribute core methods", {
11
12
  setup: function() {
12
13
 
@@ -51,13 +52,14 @@ module("SC.RecordAttribute core methods", {
51
52
  relatedToComputed: SC.Record.toOne(function() {
52
53
  // not using .get() to avoid another transform which will
53
54
  // trigger an infinite loop
54
- return (this.readAttribute('relatedToComputed').indexOf("foo")==0) ? MyApp.Foo : MyApp.Bar;
55
+ return (this.readAttribute('relatedToComputed').indexOf("foo")===0) ? MyApp.Foo : MyApp.Bar;
55
56
  })
56
57
 
57
58
  });
58
59
 
59
60
  MyApp.Bar = SC.Record.extend({});
60
61
 
62
+ SC.RunLoop.begin();
61
63
  storeKeys = MyApp.store.loadRecords(MyApp.Foo, [
62
64
  {
63
65
  guid: 'foo1',
@@ -93,6 +95,8 @@ module("SC.RecordAttribute core methods", {
93
95
  { guid: 'bar1', city: "Chicago" }
94
96
  ]);
95
97
 
98
+ SC.RunLoop.end();
99
+
96
100
  rec = MyApp.store.find(MyApp.Foo, 'foo1');
97
101
  rec2 = MyApp.store.find(MyApp.Foo, 'foo2');
98
102
 
@@ -146,7 +150,7 @@ test("reading date should parse ISO date", function() {
146
150
  });
147
151
 
148
152
  test("reading date should parse non-ISO date", function() {
149
- var d = new Date(2009,6,10,8,55,50);
153
+ var d = new Date(1244624150000);
150
154
  equals(rec2.get('nonIsoDate').toString(), d.toString(), 'should have matched date');
151
155
  });
152
156
 
@@ -182,10 +186,15 @@ test("writing a value should override default value", function() {
182
186
  test("writing to a to-one relationship should update set guid", function() {
183
187
  var rec2 = MyApp.store.find(MyApp.Foo, 'foo2');
184
188
  equals(rec2.get('id'), 'foo2', 'precond - should find record 2');
189
+
185
190
  equals(rec2.get('relatedTo'), rec, 'precond - should get rec1 instance for rec2.relatedTo');
186
-
191
+
187
192
  rec2.set('relatedTo', rec2);
193
+
188
194
  equals(rec2.readAttribute('relatedTo'), 'foo2', 'should write ID for set record to relatedTo attribute');
195
+
196
+ equals(rec2.get('relatedTo'), rec2, 'should get foo record that was just set');
197
+
189
198
  });
190
199
 
191
200
  test("writing to a to-one computed relationship should update set guid", function() {
@@ -8,6 +8,22 @@
8
8
  // This file tests the initial state of the store when it is first created
9
9
  // either independently or as a chained store.
10
10
 
11
+ var Rec = SC.Record.extend({
12
+
13
+ title: SC.Record.attr(String),
14
+
15
+ fired: NO,
16
+
17
+ reset: function() {
18
+ this.fired = NO;
19
+ },
20
+
21
+ titleDidChange: function() {
22
+ this.fired = YES;
23
+ }.observes('title')
24
+
25
+ });
26
+
11
27
  // ..........................................................
12
28
  // SC.Store#chain - init
13
29
  //
@@ -38,3 +54,96 @@ test("initial setup for chained store", function() {
38
54
  ok(!store.editables, 'should not have editables');
39
55
  });
40
56
 
57
+
58
+ // ..........................................................
59
+ // SPECIAL CASES
60
+ //
61
+
62
+ test("chained store changes should propogate reliably", function() {
63
+ var parent = SC.Store.create(), rec, store, rec2;
64
+
65
+ SC.run(function() {
66
+ parent.loadRecords(Rec, [{ title: "foo", guid: 1 }]);
67
+ });
68
+
69
+ rec = parent.find(Rec, 1);
70
+ ok(rec && rec.get('title')==='foo', 'precond - base store should have record');
71
+
72
+ // run several times to make sure this works reliably when used several
73
+ // times in the same app
74
+
75
+ // trial 1
76
+ SC.RunLoop.begin();
77
+ store = parent.chain();
78
+ rec2 = store.find(Rec, 1);
79
+ ok(rec2 && rec2.get('title')==='foo', 'chain store should have record');
80
+
81
+ rec.reset();
82
+ rec2.set('title', 'bar');
83
+ SC.RunLoop.end();
84
+
85
+ equals(rec2.get('title'), 'bar', 'chained rec.title should changed');
86
+ equals(rec.get('title'), 'foo', 'original rec.title should NOT change');
87
+ equals(store.get('hasChanges'), YES, 'chained store.hasChanges');
88
+ equals(rec.fired, NO, 'original rec.title should not have notified');
89
+
90
+ SC.RunLoop.begin();
91
+ rec.reset();
92
+ store.commitChanges();
93
+ store.destroy();
94
+ SC.RunLoop.end();
95
+
96
+ equals(rec.get('title'), 'bar', 'original rec.title should change');
97
+ equals(rec.fired, YES, 'original rec.title should have notified');
98
+
99
+
100
+ // trial 2
101
+ SC.RunLoop.begin();
102
+ store = parent.chain();
103
+ rec2 = store.find(Rec, 1);
104
+ ok(rec2 && rec2.get('title')==='bar', 'chain store should have record');
105
+
106
+ rec.reset();
107
+ rec2.set('title', 'baz');
108
+ SC.RunLoop.end();
109
+
110
+ equals(rec2.get('title'), 'baz', 'chained rec.title should changed');
111
+ equals(rec.get('title'), 'bar', 'original rec.title should NOT change');
112
+ equals(store.get('hasChanges'), YES, 'chained store.hasChanges');
113
+ equals(rec.fired, NO, 'original rec.title should not have notified');
114
+
115
+ SC.RunLoop.begin();
116
+ rec.reset();
117
+ store.commitChanges();
118
+ store.destroy();
119
+ SC.RunLoop.end();
120
+
121
+ equals(rec.get('title'), 'baz', 'original rec.title should change');
122
+ equals(rec.fired, YES, 'original rec.title should have notified');
123
+
124
+
125
+ // trial 1
126
+ SC.RunLoop.begin();
127
+ store = parent.chain();
128
+ rec2 = store.find(Rec, 1);
129
+ ok(rec2 && rec2.get('title')==='baz', 'chain store should have record');
130
+
131
+ rec.reset();
132
+ rec2.set('title', 'FOO2');
133
+ SC.RunLoop.end();
134
+
135
+ equals(rec2.get('title'), 'FOO2', 'chained rec.title should changed');
136
+ equals(rec.get('title'), 'baz', 'original rec.title should NOT change');
137
+ equals(store.get('hasChanges'), YES, 'chained store.hasChanges');
138
+ equals(rec.fired, NO, 'original rec.title should not have notified');
139
+
140
+ SC.RunLoop.begin();
141
+ rec.reset();
142
+ store.commitChanges();
143
+ store.destroy();
144
+ SC.RunLoop.end();
145
+
146
+ equals(rec.get('title'), 'FOO2', 'original rec.title should change');
147
+ equals(rec.fired, YES, 'original rec.title should have notified');
148
+
149
+ });
@@ -11,6 +11,7 @@
11
11
  var parent, store, child, storeKey, json, args;
12
12
  module("SC.NestedStore#commitChanges", {
13
13
  setup: function() {
14
+
14
15
  parent = SC.Store.create();
15
16
 
16
17
  json = {
@@ -45,25 +46,30 @@ module("SC.NestedStore#commitChanges", {
45
46
  // BASIC STATE TRANSITIONS
46
47
  //
47
48
 
48
- function testStateTransition(shouldIncludeStoreKey) {
49
+ function testStateTransition(shouldIncludeStoreKey, shouldCallParent) {
49
50
 
50
51
  // attempt to commit
51
52
  equals(store.commitChanges(), store, 'should return receiver');
52
53
 
53
54
  // verify result
54
55
  equals(store.storeKeyEditState(storeKey), SC.Store.INHERITED, 'data edit state');
55
- equals(args.length, 1, 'should have called commitChangesFromNestedStore');
56
56
 
57
- var opts = args[0] || {}; // avoid exceptions
58
- equals(opts.target, parent, 'should have called on parent store');
59
-
60
- // verify if changes passed to callback included storeKey
61
- var changes = opts.changes;
62
- var didInclude = changes && changes.contains(storeKey);
63
- if (shouldIncludeStoreKey) {
64
- ok(didInclude, 'passed set of changes should include storeKey');
57
+ if (shouldCallParent === NO) {
58
+ ok(!args || args.length===0, 'should not call commitChangesFromNestedStore');
65
59
  } else {
66
- ok(!didInclude, 'passed set of changes should NOT include storeKey');
60
+ equals(args.length, 1, 'should have called commitChangesFromNestedStore');
61
+
62
+ var opts = args[0] || {}; // avoid exceptions
63
+ equals(opts.target, parent, 'should have called on parent store');
64
+
65
+ // verify if changes passed to callback included storeKey
66
+ var changes = opts.changes;
67
+ var didInclude = changes && changes.contains(storeKey);
68
+ if (shouldIncludeStoreKey) {
69
+ ok(didInclude, 'passed set of changes should include storeKey');
70
+ } else {
71
+ ok(!didInclude, 'passed set of changes should NOT include storeKey');
72
+ }
67
73
  }
68
74
 
69
75
  equals(store.get('hasChanges'), NO, 'hasChanges should be cleared');
@@ -78,7 +84,7 @@ test("state = INHERITED", function() {
78
84
  // check preconditions
79
85
  equals(store.storeKeyEditState(storeKey), SC.Store.INHERITED, 'precond - data edit state');
80
86
 
81
- testStateTransition(NO);
87
+ testStateTransition(NO, NO);
82
88
  });
83
89
 
84
90
 
@@ -93,7 +99,7 @@ test("state = LOCKED", function() {
93
99
  equals(store.storeKeyEditState(storeKey), SC.Store.LOCKED, 'precond - data edit state');
94
100
  ok(!store.chainedChanges || !store.chainedChanges.contains(storeKey), 'locked record should not be in chainedChanges set');
95
101
 
96
- testStateTransition(NO);
102
+ testStateTransition(NO, NO);
97
103
  });
98
104
 
99
105
  test("state = EDITABLE", function() {
@@ -106,7 +112,7 @@ test("state = EDITABLE", function() {
106
112
  equals(store.storeKeyEditState(storeKey), SC.Store.EDITABLE, 'precond - data edit state');
107
113
  ok(store.chainedChanges && store.chainedChanges.contains(storeKey), 'editable record should be in chainedChanges set');
108
114
 
109
- testStateTransition(YES);
115
+ testStateTransition(YES, YES);
110
116
  });
111
117
 
112
118
 
@@ -114,4 +120,52 @@ test("state = EDITABLE", function() {
114
120
  // SPECIAL CASES
115
121
  //
116
122
 
117
- // TODO: Add more special cases for SC.NestedStore#commitChanges
123
+ test("commiting a changed record should immediately notify outstanding records in parent store", function() {
124
+
125
+ var Rec = SC.Record.extend({
126
+
127
+ fooCnt: 0,
128
+ fooDidChange: function() { this.fooCnt++; }.observes('foo'),
129
+
130
+ statusCnt: 0,
131
+ statusDidChange: function() { this.statusCnt++; }.observes('status'),
132
+
133
+ reset: function() { this.fooCnt = this.statusCnt = 0; },
134
+
135
+ equals: function(fooCnt, statusCnt, str) {
136
+ if (!str) str = '' ;
137
+ equals(this.get('fooCnt'), fooCnt, str + ':fooCnt');
138
+ equals(this.get('statusCnt'), statusCnt, str + ':statusCnt');
139
+ }
140
+
141
+ });
142
+
143
+ SC.RunLoop.begin();
144
+
145
+ var store = SC.Store.create();
146
+ var prec = store.createRecord(Rec, { foo: "bar", guid: 1 });
147
+
148
+ var child = store.chain();
149
+ var crec = child.find(Rec, prec.get('id'));
150
+
151
+ // check assumptions
152
+ ok(!!crec, 'prerec - should find child record');
153
+ equals(crec.get('foo'), 'bar', 'prerec - child record should have foo');
154
+
155
+ // modify child record - should not modify parent
156
+ prec.reset();
157
+ crec.set('foo', 'baz');
158
+ equals(prec.get('foo'), 'bar', 'should not modify parent before commit');
159
+ prec.equals(0,0, 'before commitChanges');
160
+
161
+ // commit changes - note: still inside runloop
162
+ child.commitChanges();
163
+ equals(prec.get('foo'), 'baz', 'should push data to parent');
164
+ prec.equals(1,1, 'after commitChanges'); // should notify immediately
165
+
166
+ SC.RunLoop.end();
167
+
168
+ // should not notify again after runloop - nothing to do
169
+ prec.equals(1,1,'after runloop ends - should not notify again');
170
+
171
+ });
@@ -31,12 +31,15 @@ module("SC.NestedStore#commitChangesFromNestedStore", {
31
31
 
32
32
  test("copies changed data hashes, statuses, and revisions", function() {
33
33
 
34
+ SC.RunLoop.begin();
35
+
34
36
  // verify preconditions
35
37
  equals(store.readDataHash(storeKey), null, 'precond - should not have data yet');
36
38
  ok(child.chainedChanges.contains(storeKey), 'precond - child changes should include storeKey');
37
39
 
38
40
  // perform action
39
41
  equals(store.commitChangesFromNestedStore(child, child.chainedChanges, NO), store, 'should return receiver');
42
+ SC.RunLoop.end();
40
43
 
41
44
  // verify new status
42
45
  equals(store.readDataHash(storeKey), json, 'now should have json');
@@ -47,6 +50,8 @@ test("copies changed data hashes, statuses, and revisions", function() {
47
50
 
48
51
  test("adds lock on any items not already locked", function() {
49
52
 
53
+ SC.RunLoop.begin();
54
+
50
55
  var storeKey2 = SC.Store.generateStoreKey();
51
56
  var json2 = { kind: "json2" };
52
57
 
@@ -65,6 +70,7 @@ test("adds lock on any items not already locked", function() {
65
70
 
66
71
  // now commit back to parent
67
72
  equals(store.commitChangesFromNestedStore(child, changes, NO), store, 'should return reciever');
73
+ SC.RunLoop.end();
68
74
 
69
75
  // and verify that both have locks
70
76
  ok(store.locks[storeKey], 'storeKey should have lock after commit (actual: %@)'.fmt(store.locks[storeKey]));
@@ -74,6 +80,8 @@ test("adds lock on any items not already locked", function() {
74
80
 
75
81
  test("adds items in chainedChanges to reciever chainedChanges", function() {
76
82
 
83
+ SC.RunLoop.begin();
84
+
77
85
  var key1 = SC.Store.generateStoreKey();
78
86
 
79
87
  store.dataHashDidChange(key1);
@@ -81,6 +89,7 @@ test("adds items in chainedChanges to reciever chainedChanges", function() {
81
89
  ok(child.chainedChanges.contains(storeKey), 'precond - child.chainedChanges should contain store key');
82
90
 
83
91
  equals(store.commitChangesFromNestedStore(child, child.chainedChanges, NO), store, 'should return receiver');
92
+ SC.RunLoop.end();
84
93
 
85
94
  // changelog should merge nested store & existing
86
95
  ok(store.chainedChanges.contains(key1), 'chainedChanges should still contain key1');
@@ -89,6 +98,8 @@ test("adds items in chainedChanges to reciever chainedChanges", function() {
89
98
 
90
99
  test("should set hasChanges to YES if has changes", function() {
91
100
 
101
+ SC.RunLoop.begin();
102
+
92
103
  var changes = child.chainedChanges;
93
104
  ok(changes.length>0, 'precond - should have some changes in child');
94
105
  equals(store.get('hasChanges'), NO, 'precond - store should not have changes');
@@ -99,6 +110,8 @@ test("should set hasChanges to YES if has changes", function() {
99
110
 
100
111
  test("should set hasChanges to NO if no changes", function() {
101
112
 
113
+ SC.RunLoop.begin();
114
+
102
115
  child = store.chain() ; // get a new child store
103
116
 
104
117
  var changes = child.chainedChanges || SC.Set.create();
@@ -106,6 +119,8 @@ test("should set hasChanges to NO if no changes", function() {
106
119
  equals(store.get('hasChanges'), NO, 'precond - store should not have changes');
107
120
 
108
121
  store.commitChangesFromNestedStore(child, changes, NO);
122
+ SC.RunLoop.end();
123
+
109
124
  equals(store.get('hasChanges'), NO, 'store should NOT now have changes');
110
125
  });
111
126
 
@@ -115,6 +130,8 @@ test("should set hasChanges to NO if no changes", function() {
115
130
 
116
131
  test("committing changes should chain back each step", function() {
117
132
 
133
+ SC.RunLoop.begin();
134
+
118
135
  // preconditions
119
136
  equals(child.readDataHash(storeKey), json, 'precond - child should have data');
120
137
  equals(store.readDataHash(storeKey), null, 'precond - store should not have data');
@@ -122,14 +139,16 @@ test("committing changes should chain back each step", function() {
122
139
 
123
140
  // do commits
124
141
  child.commitChanges();
142
+
125
143
  equals(store.get('hasChanges'), YES, 'store should now have changes');
126
144
  equals(store.readDataHash(storeKey), json, 'store should now have json');
127
145
 
128
146
  store.commitChanges();
129
147
  equals(store.get('hasChanges'), NO, 'store should no longer have changes');
130
148
  equals(parent.readDataHash(storeKey), json, 'parent should now have json');
149
+ SC.RunLoop.end();
150
+
131
151
  });
132
152
 
133
153
 
134
154
 
135
-
@@ -20,8 +20,11 @@ module("SC.NestedStore#dataHashDidChange", {
20
20
  };
21
21
 
22
22
  storeKey = SC.Store.generateStoreKey();
23
-
23
+
24
+ SC.RunLoop.begin();
24
25
  parent.writeDataHash(storeKey, json, SC.Record.READY_CLEAN);
26
+ SC.RunLoop.end();
27
+
25
28
  parent.editables = null; // manually patch to setup test state
26
29
 
27
30
  store = parent.chain(); // create nested store