sproutit-sproutcore 1.0.20090721145281 → 1.0.20090721145282

Sign up to get free protection for your applications and to get access to all the features.
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