sproutcore 0.9.14 → 0.9.15

Sign up to get free protection for your applications and to get access to all the features.
Files changed (61) hide show
  1. data/History.txt +43 -0
  2. data/Manifest.txt +12 -3
  3. data/bin/sc-build +19 -3
  4. data/bin/sc-install +5 -0
  5. data/bin/sc-remove +5 -0
  6. data/bin/sc-update +5 -0
  7. data/frameworks/prototype/prototype.js +267 -230
  8. data/frameworks/sproutcore/HISTORY +281 -135
  9. data/frameworks/sproutcore/controllers/array.js +133 -22
  10. data/frameworks/sproutcore/controllers/collection.js +4 -5
  11. data/frameworks/sproutcore/controllers/object.js +8 -2
  12. data/frameworks/sproutcore/core.js +361 -159
  13. data/frameworks/sproutcore/{foundation → debug}/unittest.js +3 -3
  14. data/frameworks/sproutcore/english.lproj/detect-browser +1 -1
  15. data/frameworks/sproutcore/english.lproj/theme.css +2 -2
  16. data/frameworks/sproutcore/foundation/application.js +6 -1
  17. data/frameworks/sproutcore/foundation/benchmark.js +37 -11
  18. data/frameworks/sproutcore/foundation/date.js +1 -1
  19. data/frameworks/sproutcore/foundation/enumerator.js +105 -0
  20. data/frameworks/sproutcore/foundation/object.js +19 -20
  21. data/frameworks/sproutcore/foundation/responder.js +1 -1
  22. data/frameworks/sproutcore/foundation/set.js +164 -57
  23. data/frameworks/sproutcore/foundation/string.js +151 -47
  24. data/frameworks/sproutcore/foundation/utils.js +84 -3
  25. data/frameworks/sproutcore/lib/collection_view.rb +1 -0
  26. data/frameworks/sproutcore/license.js +28 -0
  27. data/frameworks/sproutcore/mixins/array.js +73 -209
  28. data/frameworks/sproutcore/mixins/delegate_support.js +1 -1
  29. data/frameworks/sproutcore/mixins/enumerable.js +1006 -0
  30. data/frameworks/sproutcore/mixins/observable.js +153 -84
  31. data/frameworks/sproutcore/mixins/selection_support.js +13 -1
  32. data/frameworks/sproutcore/models/record.js +74 -27
  33. data/frameworks/sproutcore/models/store.js +7 -3
  34. data/frameworks/sproutcore/server/rails_server.js +82 -0
  35. data/frameworks/sproutcore/server/rest_server.js +178 -0
  36. data/frameworks/sproutcore/{foundation → server}/server.js +101 -48
  37. data/frameworks/sproutcore/tests/core/guidFor.rhtml +114 -0
  38. data/frameworks/sproutcore/tests/foundation/array.rhtml +6 -7
  39. data/frameworks/sproutcore/tests/foundation/set.rhtml +254 -0
  40. data/frameworks/sproutcore/tests/mixins/enumerable.rhtml +421 -0
  41. data/frameworks/sproutcore/tests/mixins/observable.rhtml +127 -0
  42. data/frameworks/sproutcore/tests/models/model.rhtml +23 -22
  43. data/frameworks/sproutcore/tests/views/collection/incremental_rendering.rhtml +2 -2
  44. data/frameworks/sproutcore/tests/views/view/clippingFrame.rhtml +112 -109
  45. data/frameworks/sproutcore/tests/views/view/frame.rhtml +91 -88
  46. data/frameworks/sproutcore/validators/date.js +1 -7
  47. data/frameworks/sproutcore/views/collection/collection.js +7 -2
  48. data/frameworks/sproutcore/views/list_item.js +141 -3
  49. data/frameworks/sproutcore/views/split.js +14 -11
  50. data/frameworks/sproutcore/views/view.js +9 -6
  51. data/lib/sproutcore/build_tools/html_builder.rb +19 -3
  52. data/lib/sproutcore/build_tools/resource_builder.rb +9 -3
  53. data/lib/sproutcore/bundle.rb +21 -0
  54. data/lib/sproutcore/bundle_manifest.rb +64 -20
  55. data/lib/sproutcore/helpers/capture_helper.rb +2 -2
  56. data/lib/sproutcore/library.rb +33 -9
  57. data/lib/sproutcore/merb/bundle_controller.rb +16 -5
  58. data/lib/sproutcore/version.rb +1 -1
  59. data/lib/sproutcore/view_helpers.rb +1 -1
  60. data/{sc-config.rb → sc-config} +5 -2
  61. metadata +24 -5
@@ -0,0 +1,254 @@
1
+ <% content_for('final') do %>
2
+ <script>
3
+
4
+ Test.context("creating SC.Set instances", {
5
+
6
+ setup: function() {
7
+ // create objects...
8
+ a = { name: "a" } ;
9
+ b = { name: "b" } ;
10
+ c = { name: "c" } ;
11
+ },
12
+
13
+ teardown: function() {
14
+ delete a;
15
+ delete b;
16
+ delete c;
17
+ },
18
+
19
+ "new SC.Set() should create empty set": function() {
20
+ var set = new SC.Set() ;
21
+ assertEqual(set.length, 0) ;
22
+ },
23
+
24
+ "new SC.Set([1,2,3]) should create set with three items in them": function(){
25
+ var set = new SC.Set([a,b,c]) ;
26
+ set.length.shouldEqual(3) ;
27
+ set.contains(a).shouldEqual(YES) ;
28
+ set.contains(b).shouldEqual(YES) ;
29
+ set.contains(c).shouldEqual(YES) ;
30
+ },
31
+
32
+ "SC.Set.create() is an alias for new SC.Set()": function() {
33
+ var set = SC.Set.create() ;
34
+ set.length.shouldEqual(0) ;
35
+
36
+ var set = SC.Set.create([a,b,c]) ;
37
+ set.length.shouldEqual(3) ;
38
+ set.contains(a).shouldEqual(YES) ;
39
+ set.contains(b).shouldEqual(YES) ;
40
+ set.contains(c).shouldEqual(YES) ;
41
+ },
42
+
43
+ "new SC.Set() should accept anything that implements SC.Array": function() {
44
+ var arrayLikeObject = SC.Object.create(SC.Array, {
45
+
46
+ _content: [a,b,c],
47
+ length: 3,
48
+ objectAt: function(idx) { return this._content[idx]; }
49
+ }) ;
50
+
51
+ var set = SC.Set.create(arrayLikeObject) ;
52
+ set.length.shouldEqual(3) ;
53
+ set.contains(a).shouldEqual(YES) ;
54
+ set.contains(b).shouldEqual(YES) ;
55
+ set.contains(c).shouldEqual(YES) ;
56
+ },
57
+
58
+ "new SC.Set() should accept anything that looks like an array, even if it does not implement SC.Array": function() {
59
+ var arrayLikeObject = { length: 3, '0': a, '1': b, '2': c } ;
60
+
61
+ var set = SC.Set.create(arrayLikeObject) ;
62
+ set.length.shouldEqual(3) ;
63
+ set.contains(a).shouldEqual(YES) ;
64
+ set.contains(b).shouldEqual(YES) ;
65
+ set.contains(c).shouldEqual(YES) ;
66
+ }
67
+
68
+ });
69
+
70
+ // The tests below also end up testing the contains() method pretty
71
+ // exhaustively.
72
+ Test.context("SC.Set.add + SC.Set.contains", {
73
+
74
+ setup: function() {
75
+ set = SC.Set.create() ;
76
+ },
77
+
78
+ teardown: function() {
79
+ delete set ;
80
+ },
81
+
82
+ "should add an SC.Object": function() {
83
+ var obj = SC.Object.create() ;
84
+
85
+ var oldLength = set.length ;
86
+ set.add(obj);
87
+ assertEqual(set.contains(obj), YES, "contains()") ;
88
+ assertEqual(oldLength+1, set.length, "new set length") ;
89
+ },
90
+
91
+ "should add a regular hash": function() {
92
+ var obj = {} ;
93
+
94
+ var oldLength = set.length ;
95
+ set.add(obj);
96
+ assertEqual(set.contains(obj), YES, "contains()") ;
97
+ assertEqual(oldLength+1, set.length, "new set length") ;
98
+ },
99
+
100
+ "should add a string": function() {
101
+ var obj = "String!" ;
102
+
103
+ var oldLength = set.length ;
104
+ set.add(obj);
105
+ assertEqual(set.contains(obj), YES, "contains()") ;
106
+ assertEqual(oldLength+1, set.length, "new set length") ;
107
+ },
108
+
109
+ "should add a number": function() {
110
+ var obj = 23 ;
111
+
112
+ var oldLength = set.length ;
113
+ set.add(obj);
114
+ assertEqual(set.contains(obj), YES, "contains()") ;
115
+ assertEqual(oldLength+1, set.length, "new set length") ;
116
+ },
117
+
118
+ "should add a bool": function() {
119
+ var obj = true ;
120
+
121
+ var oldLength = set.length ;
122
+ set.add(obj);
123
+ assertEqual(set.contains(obj), YES, "contains()") ;
124
+ assertEqual(oldLength+1, set.length, "new set length") ;
125
+ },
126
+
127
+ "should add a function": function() {
128
+ var obj = function() { return "Test function"; } ;
129
+
130
+ var oldLength = set.length ;
131
+ set.add(obj);
132
+ assertEqual(set.contains(obj), YES, "contains()") ;
133
+ assertEqual(oldLength+1, set.length, "new set length") ;
134
+ },
135
+
136
+ "should NOT add a null": function() {
137
+ set.add(null) ;
138
+ assertEqual(set.length, 0) ;
139
+ assertEqual(set.contains(null), NO) ;
140
+ },
141
+
142
+ "should NOT add an undefined": function() {
143
+ set.add(undefined) ;
144
+ assertEqual(set.length, 0) ;
145
+ assertEqual(set.contains(undefined), NO) ;
146
+ }
147
+
148
+ });
149
+
150
+ Test.context("SC.Set.remove + SC.Set.contains", {
151
+
152
+ // generate a set with every type of object, but none of the specific
153
+ // ones we add in the tests below...
154
+ setup: function() {
155
+ set = SC.Set.create([
156
+ SC.Object.create({ dummy: YES }),
157
+ { isHash: YES },
158
+ "Not the String",
159
+ 16, false]) ;
160
+ },
161
+
162
+ teardown: function() {
163
+ delete set ;
164
+ },
165
+
166
+ "should remove an SC.Object and reduce length": function() {
167
+ var obj = SC.Object.create() ;
168
+ set.add(obj);
169
+ assertEqual(set.contains(obj), YES) ;
170
+ var oldLength = set.length ;
171
+
172
+ set.remove(obj) ;
173
+ assertEqual(NO, set.contains(obj), "should be removed") ;
174
+ assertEqual(oldLength-1, set.length, "should be 1 shorter") ;
175
+ },
176
+
177
+ "should remove a regular hash and reduce length": function() {
178
+ var obj = {} ;
179
+ set.add(obj);
180
+ assertEqual(set.contains(obj), YES) ;
181
+ var oldLength = set.length ;
182
+
183
+ set.remove(obj) ;
184
+ assertEqual(NO, set.contains(obj), "should be removed") ;
185
+ assertEqual(oldLength-1, set.length, "should be 1 shorter") ;
186
+ },
187
+
188
+ "should remove a string and reduce length": function() {
189
+ var obj = "String!" ;
190
+ set.add(obj);
191
+ assertEqual(set.contains(obj), YES) ;
192
+ var oldLength = set.length ;
193
+
194
+ set.remove(obj) ;
195
+ assertEqual(NO, set.contains(obj), "should be removed") ;
196
+ assertEqual(oldLength-1, set.length, "should be 1 shorter") ;
197
+ },
198
+
199
+ "should remove a number and reduce length": function() {
200
+ var obj = 23 ;
201
+ set.add(obj);
202
+ assertEqual(set.contains(obj), YES) ;
203
+ var oldLength = set.length ;
204
+
205
+ set.remove(obj) ;
206
+ assertEqual(NO, set.contains(obj), "should be removed") ;
207
+ assertEqual(oldLength-1, set.length, "should be 1 shorter") ;
208
+ },
209
+
210
+ "should remove a bool and reduce length": function() {
211
+ var obj = true ;
212
+ set.add(obj);
213
+ assertEqual(set.contains(obj), YES) ;
214
+ var oldLength = set.length ;
215
+
216
+ set.remove(obj) ;
217
+ assertEqual(NO, set.contains(obj), "should be removed") ;
218
+ assertEqual(oldLength-1, set.length, "should be 1 shorter") ;
219
+ },
220
+
221
+ "should remove a function and reduce length": function() {
222
+ var obj = function() { return "Test function"; } ;
223
+ set.add(obj);
224
+ assertEqual(set.contains(obj), YES) ;
225
+ var oldLength = set.length ;
226
+
227
+ set.remove(obj) ;
228
+ assertEqual(NO, set.contains(obj), "should be removed") ;
229
+ assertEqual(oldLength-1, set.length, "should be 1 shorter") ;
230
+ },
231
+
232
+ "should NOT remove a null": function() {
233
+ var oldLength = set.length ;
234
+ set.remove(null) ;
235
+ assertEqual(oldLength, set.length) ;
236
+ },
237
+
238
+ "should NOT remove an undefined": function() {
239
+ var oldLength = set.length ;
240
+ set.remove(undefined) ;
241
+ assertEqual(oldLength, set.length) ;
242
+ },
243
+
244
+ "should ignore removing an object not in the set": function() {
245
+ var obj = SC.Object.create() ;
246
+ var oldLength = set.length ;
247
+ set.remove(obj) ;
248
+ assertEqual(oldLength, set.length) ;
249
+ }
250
+
251
+ });
252
+
253
+ </script>
254
+ <% end %>
@@ -0,0 +1,421 @@
1
+ <% content_for('final') do %>
2
+ <script>
3
+
4
+ // Define some standard tests. We need to test both on a custom enumerable
5
+ // and on a real Array.
6
+ var EnumerableTests = {
7
+
8
+ "should get enumerator that iterates through objects": function() {
9
+ var e = src.enumerator() ;
10
+ assertNotEqual(e, null, 'enumerator must not be null');
11
+
12
+ var idx = 0;
13
+ var cur ;
14
+ while(cur = e.nextObject()) {
15
+ assertEqual(src.objectAt(idx), cur, "object at index %@".fmt(idx)) ;
16
+ idx++;
17
+ }
18
+
19
+ assertEqual(src.get('length'), idx) ;
20
+ },
21
+
22
+ "should run forEach() to go through objects": function() {
23
+ var idx = 0;
24
+
25
+ // save for testing later
26
+ var items = [] ;
27
+ var indexes = [] ;
28
+ var arrays = [] ;
29
+ var targets = [] ;
30
+
31
+ src.forEach(function(item, index, array) {
32
+ items.push(item);
33
+ indexes.push(index);
34
+ arrays.push(array);
35
+ targets.push(this);
36
+ }, this);
37
+
38
+ var len = src.get('length') ;
39
+ for(var idx=0;idx<len;idx++) {
40
+ assertEqual(items[idx], src.objectAt(idx)) ;
41
+ assertEqual(indexes[idx], idx) ;
42
+ assertEqual(arrays[idx], src) ;
43
+ assertEqual(targets[idx], this) ;
44
+ }
45
+ },
46
+
47
+ "should map to values while passing proper params": function() {
48
+ var idx = 0;
49
+
50
+ // save for testing later
51
+ var items = [] ;
52
+ var indexes = [] ;
53
+ var arrays = [] ;
54
+ var targets = [] ;
55
+
56
+ var mapped = src.map(function(item, index, array) {
57
+ items.push(item);
58
+ indexes.push(index);
59
+ arrays.push(array);
60
+ targets.push(this);
61
+
62
+ return index ;
63
+ }, this);
64
+
65
+ var len = src.get('length') ;
66
+ for(var idx=0;idx<len;idx++) {
67
+ assertEqual(src.objectAt(idx), items[idx], "items") ;
68
+ assertEqual(idx, indexes[idx], "indexes") ;
69
+ assertEqual(src, arrays[idx], 'arrays') ;
70
+ assertEqual(SC.guidFor(this), SC.guidFor(targets[idx]), "this") ;
71
+
72
+ assertEqual(idx, mapped[idx], "mapped") ;
73
+ }
74
+ },
75
+
76
+ "should filter to items that return for callback": function() {
77
+ var idx = 0;
78
+
79
+ // save for testing later
80
+ var items = [] ;
81
+ var indexes = [] ;
82
+ var arrays = [] ;
83
+ var targets = [] ;
84
+
85
+ var filtered = src.filter(function(item, index, array) {
86
+ items.push(item);
87
+ indexes.push(index);
88
+ arrays.push(array);
89
+ targets.push(this);
90
+
91
+ return item.gender === "female" ;
92
+ }, this);
93
+
94
+ var len = src.get('length') ;
95
+ for(var idx=0;idx<len;idx++) {
96
+ assertEqual(src.objectAt(idx), items[idx], "items") ;
97
+ assertEqual(idx, indexes[idx], "indexes") ;
98
+ assertEqual(src, arrays[idx], 'arrays') ;
99
+ assertEqual(SC.guidFor(this), SC.guidFor(targets[idx]), "this") ;
100
+ }
101
+
102
+ filtered.length.shouldEqual(1) ;
103
+ filtered[0].first.shouldEqual("Jenna") ;
104
+ },
105
+
106
+ "should return true if function for every() returns true": function() {
107
+ var idx = 0;
108
+
109
+ // save for testing later
110
+ var items = [] ;
111
+ var indexes = [] ;
112
+ var arrays = [] ;
113
+ var targets = [] ;
114
+
115
+ var result = src.every(function(item, index, array) {
116
+ items.push(item);
117
+ indexes.push(index);
118
+ arrays.push(array);
119
+ targets.push(this);
120
+
121
+ return true ;
122
+ }, this);
123
+
124
+ var len = src.get('length') ;
125
+ for(var idx=0;idx<len;idx++) {
126
+ assertEqual(src.objectAt(idx), items[idx], "items") ;
127
+ assertEqual(idx, indexes[idx], "indexes") ;
128
+ assertEqual(src, arrays[idx], 'arrays') ;
129
+ assertEqual(SC.guidFor(this), SC.guidFor(targets[idx]), "this") ;
130
+ }
131
+
132
+ assertEqual(result, YES) ;
133
+ },
134
+
135
+ "should return false if one function for every() returns false": function() {
136
+ var result = src.every(function(item, index, array) {
137
+ return item.gender === "male" ;
138
+ }, this);
139
+ assertEqual(result, NO) ;
140
+ },
141
+
142
+ "should return false if all functions for some() returns false": function() {
143
+ var idx = 0;
144
+
145
+ // save for testing later
146
+ var items = [] ;
147
+ var indexes = [] ;
148
+ var arrays = [] ;
149
+ var targets = [] ;
150
+
151
+ var result = src.some(function(item, index, array) {
152
+ items.push(item);
153
+ indexes.push(index);
154
+ arrays.push(array);
155
+ targets.push(this);
156
+
157
+ return false ;
158
+ }, this);
159
+
160
+ var len = src.get('length') ;
161
+ for(var idx=0;idx<len;idx++) {
162
+ assertEqual(src.objectAt(idx), items[idx], "items") ;
163
+ assertEqual(idx, indexes[idx], "indexes") ;
164
+ assertEqual(src, arrays[idx], 'arrays') ;
165
+ assertEqual(SC.guidFor(this), SC.guidFor(targets[idx]), "this") ;
166
+ }
167
+
168
+ assertEqual(result, NO) ;
169
+ },
170
+
171
+ "should return true if one function for some() returns true": function() {
172
+ var result = src.some(function(item, index, array) {
173
+ return item.gender !== "male" ;
174
+ }, this);
175
+ assertEqual(result, YES) ;
176
+ },
177
+
178
+
179
+ "should mapProperty for all items": function() {
180
+ var mapped = src.mapProperty("first") ;
181
+ var idx ;
182
+ var len = src.get('length') ;
183
+ for(idx=0;idx<len;idx++) {
184
+ mapped[idx].shouldEqual(src.objectAt(idx).first) ;
185
+ }
186
+ },
187
+
188
+ "should filterProperty with match": function() {
189
+ var filtered = src.filterProperty("gender", "female") ;
190
+ filtered.length.shouldEqual(1) ;
191
+ filtered[0].first.shouldEqual("Jenna") ;
192
+ },
193
+
194
+ "should filterProperty with default bool": function() {
195
+ var filtered = src.filterProperty("californian") ;
196
+ filtered.length.shouldEqual(1) ;
197
+ filtered[0].first.shouldEqual("Jenna") ;
198
+ },
199
+
200
+
201
+
202
+ "everyProperty should return true if all properties macth": function() {
203
+ var ret = src.everyProperty('visited', 'Prague') ;
204
+ assertEqual(YES, ret, "visited") ;
205
+ },
206
+
207
+ "everyProperty should return true if all properties true": function() {
208
+ var ret = src.everyProperty('ready') ;
209
+ assertEqual(YES, ret, "ready") ;
210
+ },
211
+
212
+ "everyProperty should return false if any properties false": function() {
213
+ var ret = src.everyProperty('gender', 'male') ;
214
+ assertEqual(NO, ret, "ready") ;
215
+ },
216
+
217
+
218
+ "someProperty should return false if all properties not match": function() {
219
+ var ret = src.someProperty('visited', 'Timbuktu') ;
220
+ assertEqual(NO, ret, "visited") ;
221
+ },
222
+
223
+ "someProperty should return false if all properties false": function() {
224
+ var ret = src.someProperty('doneTravelling') ;
225
+ assertEqual(NO, ret, "doneTravelling") ;
226
+ },
227
+
228
+ "someProperty should return true if any properties true": function() {
229
+ var ret = src.someProperty('first', 'Charles') ;
230
+ assertEqual(YES, ret, "first") ;
231
+ },
232
+
233
+ "invokeWhile should call method on member objects until return does not match": function() {
234
+ var ret = src.invokeWhile("OK", "invokeWhileTest", "item2") ;
235
+ assertEqual("FAIL", ret, "return value");
236
+ },
237
+
238
+ "get @min(balance) should return the minimum balance": function() {
239
+ assertEqual(1, src.get('@min(balance)')) ;
240
+ },
241
+
242
+ "get @max(balance) should return the maximum balance": function() {
243
+ assertEqual(4, src.get('@max(balance)')) ;
244
+ },
245
+
246
+ "get @minObject(balance) should return the record with min balance": function() {
247
+ assertEqual(src.objectAt(0), src.get('@minObject(balance)')) ;
248
+ },
249
+
250
+ "get @maxObject(balance) should return the record with the max balance": function() {
251
+ assertEqual(src.objectAt(0), src.get('@maxObject(balance)')) ;
252
+ },
253
+
254
+ "get @sum(balance) should return the sum of the balances.": function() {
255
+ assertEqual(1+2+3+4, src.get("@sum(balance)")) ;
256
+ },
257
+
258
+ "get @average(balance) should return the average of balances": function() {
259
+ assertEqual((1+2+3+4)/4, src.get("@average(balance)")) ;
260
+ },
261
+
262
+ "should invoke custom reducer": function() {
263
+ // install reducer method
264
+ src.reduceTest = reduceTestFunc ;
265
+ assertEqual("TEST", src.get("@test")) ;
266
+ assertEqual("prop", src.get("@test(prop)")) ;
267
+ },
268
+ "should trigger observer of reduced prop when array changes once property retrieved once": function() {
269
+
270
+ // get the property...this will install the reducer property...
271
+ src.get("@max(balance)") ;
272
+
273
+ // install observer
274
+ var observedValue = null ;
275
+ src.addObserver("@max(balance)", function() {
276
+ observedValue = src.get("@max(balance)");
277
+ }) ;
278
+
279
+ src.addProbe('[]') ;
280
+ src.addProbe('@max(balance)');
281
+
282
+ // add record to array
283
+ src.pushObject({
284
+ first: "John",
285
+ gender: "male",
286
+ californian: NO,
287
+ ready: YES,
288
+ visited: "Paris",
289
+ balance: 5
290
+ }) ;
291
+
292
+ //SC.NotificationQueue.flush() ; // force observers to trigger
293
+
294
+ // observed value should now be set because the reduced property observer
295
+ // was triggered when we changed the array contents.
296
+ assertEqual(5, observedValue) ;
297
+ },
298
+
299
+ "should trigger observer of reduced prop when array changes - even if you never retrieved the property before": function() {
300
+ // install observer
301
+ var observedValue = null ;
302
+ src.addObserver("@max(balance)", function() {
303
+ observedValue = src.get("@max(balance)");
304
+ }) ;
305
+
306
+ // add record to array
307
+ src.pushObject({
308
+ first: "John",
309
+ gender: "male",
310
+ californian: NO,
311
+ ready: YES,
312
+ visited: "Paris",
313
+ balance: 5
314
+ }) ;
315
+
316
+ //SC.NotificationQueue.flush() ; // force observers to trigger
317
+
318
+ // observed value should now be set because the reduced property observer
319
+ // was triggered when we changed the array contents.
320
+ assertEqual(5, observedValue) ;
321
+ }
322
+
323
+ };
324
+
325
+ var DummyEnumerable = SC.Object.extend(SC.Enumerable, {
326
+
327
+ content: [],
328
+
329
+ length: function() { return this.content.length; }.property(),
330
+
331
+ objectAt: function(idx) { return this.content[idx]; },
332
+
333
+ nextObject: function(idx) { return this.content[idx]; },
334
+
335
+ // add support for reduced properties.
336
+ unknownProperty: function(key, value) {
337
+ var ret = this.reducedProperty(key, value) ;
338
+ if (ret === undefined) {
339
+ if (value !== undefined) this[key] = value ;
340
+ ret = value ;
341
+ }
342
+ return ret ;
343
+ },
344
+
345
+ pushObject: function(object) {
346
+ this.content.push(object) ;
347
+ this.enumerableContentDidChange() ;
348
+ }
349
+
350
+ }) ;
351
+
352
+ var runFunc = function(a,b) { return ['DONE', a, b]; } ;
353
+ var invokeWhileOK = function() { return "OK"; } ;
354
+ var invokeWhileNotOK = function() { return "FAIL"; };
355
+ var reduceTestFunc = function(prev, item, idx, e, pname) { return pname||'TEST'; } ;
356
+
357
+ var CommonArray = [
358
+ { first: "Charles",
359
+ gender: "male",
360
+ californian: NO,
361
+ ready: YES,
362
+ visited: "Prague",
363
+ doneTravelling: NO,
364
+ run: runFunc,
365
+ invokeWhileTest: invokeWhileOK,
366
+ balance: 1
367
+ },
368
+
369
+ { first: "Jenna",
370
+ gender: "female",
371
+ californian: YES,
372
+ ready: YES,
373
+ visited: "Prague",
374
+ doneTravelling: NO,
375
+ run: runFunc,
376
+ invokeWhileTest: invokeWhileOK,
377
+ balance: 2
378
+ },
379
+
380
+ { first: "Peter",
381
+ gender: "male",
382
+ californian: NO,
383
+ ready: YES,
384
+ visited: "Prague",
385
+ doneTravelling: NO,
386
+ run: runFunc,
387
+ invokeWhileTest: invokeWhileNotOK,
388
+ balance: 3
389
+ },
390
+
391
+ { first: "Chris",
392
+ gender: "male",
393
+ californian: NO,
394
+ ready: YES,
395
+ visited: "Prague",
396
+ doneTravelling: NO,
397
+ run: runFunc,
398
+ invokeWhileTest: invokeWhileOK,
399
+ balance: 4
400
+ } ] ;
401
+
402
+ Test.context("Real Array", SC.mixin(EnumerableTests, {
403
+
404
+ setup: function() { src = CommonArray.clone(); },
405
+
406
+ teardown: function() { src = null ; }
407
+
408
+ }));
409
+
410
+ Test.context("DummyEnumerable", SC.mixin(EnumerableTests, {
411
+
412
+ setup: function() {
413
+ src = DummyEnumerable.create({ content: CommonArray }) ;
414
+ },
415
+
416
+ teardown: function() { src = null ; }
417
+
418
+ }));
419
+
420
+ </script>
421
+ <% end %>