1 // ========================================================================== 2 // Project: SproutCore - JavaScript Application Framework 3 // Copyright: ©2006-2010 Sprout Systems, Inc. and contributors. 4 // portions copyright ©2011 Apple Inc. 5 // License: Licensed under MIT license (see license.js) 6 // ========================================================================== 7 8 /* 9 Tests SplitView logic responsible for automatically creating divider views. 10 There are a few different parts to this: 11 12 - The automatic creation of dividers. 13 - The splitDividerView property. 14 - The splitViewDividerBetween method. 15 16 We don't have to worry about orientation; the code being tested creates 17 child views, but does nothing related to laying them out. 18 19 Note: We do NOT test the properties added to the split children (nextView, etc.); 20 Those are tested in children.js. 21 22 */ 23 var createSplitView; 24 25 module("SplitView Dividers", { 26 setup: function() { 27 // Rather than instantiate one here, we'll create a function that 28 // instantiates with the supplied options. 29 var SplitView = SC.SplitView.extend({ 30 childViews: [ 31 'left', 32 'right' 33 ], 34 35 left: SC.View.extend(SC.SplitChild, { name: 'left', canCollapse: YES, collapseAtSize: 50 }), 36 right: SC.View.extend(SC.SplitChild, { name: 'right', canCollapse: YES, collapseAtSize: 50 }), 37 38 layout: { left: 0, top: 0, width: 500, height: 500 } 39 }); 40 41 createSplitView = function(opts) { 42 opts = opts || {}; 43 SC.RunLoop.begin(); 44 var ret = SplitView.create(opts); 45 SC.RunLoop.end(); 46 return ret; 47 }; 48 }, 49 50 teardown: function() { 51 52 } 53 }); 54 55 test("SC.SplitDividerView is automatically created between child views", function(){ 56 var view = createSplitView(); 57 equals(view.childViews.length, 3, "Should have created 3 views: left, divider, and right."); 58 ok(view.childViews[1].kindOf(SC.SplitDividerView), "Middle view is an SC.SplitDividerView"); 59 }); 60 61 test("SC.SplitDividerView uses splitDividerView property", function(){ 62 var MyDividerType = SC.SplitDividerView.extend(); 63 var view = createSplitView({ splitDividerView: MyDividerType }); 64 equals(view.childViews.length, 3, "Should have created 3 views: left, divider, and right."); 65 ok(view.childViews[1].kindOf(MyDividerType), "Middle view is a MyDividerType"); 66 }); 67 68 test("SC.SplitDividerView uses splitViewDividerBetween method", function(){ 69 var MyDividerType = SC.SplitDividerView.extend(); 70 var view = createSplitView({ splitViewDividerBetween: function(split, view1, view2) { return MyDividerType.create(); } }); 71 equals(view.childViews.length, 3, "Should have created 3 views: left, divider, and right."); 72 ok(view.childViews[1].kindOf(MyDividerType), "Middle view is a MyDividerType"); 73 }); 74 75 test("splitViewDividerBetween works properly", function(){ 76 var MyDividerType1 = SC.SplitDividerView.extend({ dividerType: 1 }); 77 var MyDividerType2 = SC.SplitDividerView.extend({ dividerType: 2 }); 78 79 var view = createSplitView({ 80 childViews: 'left middle right'.w(), 81 middle: SC.View.design(SC.SplitChild, { name: 'middle' }), 82 splitViewDividerBetween: function(split, view1, view2) { 83 if (view1 === split.left) return MyDividerType1.create(); 84 if (view1 === split.middle) return MyDividerType2.create(); 85 } 86 }); 87 88 equals(view.childViews.length, 5, "Should have created 5 views: left, divider, middle, divider, and right."); 89 ok(view.childViews[1].kindOf(MyDividerType1), "2nd view is a MyDividerType1"); 90 ok(view.childViews[3].kindOf(MyDividerType2), "4th view is a MyDividerType2"); 91 }); 92 93 function checkDividers(view, number) { 94 var shouldBeDivider = NO; 95 96 equals(view.childViews.length, number * 2 - 1, "There should be " + (number * 2 - 1) + " children"); 97 98 for (var i = 1; i < number; i++) { 99 equals( 100 view.childViews[i - 1].isSplitDivider, shouldBeDivider, 101 "View " + i + (shouldBeDivider ? " SHOULD " : " SHOULD NOT ") + "be a divider" 102 ); 103 shouldBeDivider = !shouldBeDivider; 104 } 105 } 106 107 test("Adding/removing from end adds/removes dividers appropriately", function() { 108 var view = createSplitView({ 109 childViews: 'left middle right'.w(), 110 middle: SC.View.design(SC.SplitChild, { name: 'middle' }) 111 }); 112 113 // do an initial check: should be three views with dividers. 114 checkDividers(view, 3); 115 116 // add one, and check again. 117 var add = SC.View.create(SC.SplitChild, { name: 'add' }); 118 119 SC.RunLoop.begin(); 120 view.appendChild(add); 121 SC.RunLoop.end(); 122 123 checkDividers(view, 4); 124 125 // remove the one we added, and check again 126 SC.RunLoop.begin(); 127 view.removeChild(add); 128 SC.RunLoop.end(); 129 130 checkDividers(view, 3); 131 132 }); 133 134 test("Adding/removing from beginning adds/removes dividers appropriately", function() { 135 var view = createSplitView({ 136 childViews: 'left middle right'.w(), 137 middle: SC.View.design(SC.SplitChild, { name: 'middle' }) 138 }); 139 140 // do an initial check: should be three views with dividers. 141 checkDividers(view, 3); 142 143 // add one, and check again. 144 var add = SC.View.create(SC.SplitChild, { name: 'add' }); 145 146 SC.RunLoop.begin(); 147 view.insertBefore(add, view.childViews[0]); 148 SC.RunLoop.end(); 149 150 checkDividers(view, 4); 151 152 // remove the one we added, and check again 153 SC.RunLoop.begin(); 154 view.removeChild(add); 155 SC.RunLoop.end(); 156 157 checkDividers(view, 3); 158 159 }); 160 161 test("Adding/removing in middle adds/removes dividers appropriately", function() { 162 var view = createSplitView({ 163 childViews: 'left middle right'.w(), 164 middle: SC.View.design(SC.SplitChild, { name: 'middle' }) 165 }); 166 167 // do an initial check: should be three views with dividers. 168 checkDividers(view, 3); 169 170 // add one, and check again. 171 var add = SC.View.create(SC.SplitChild, { name: 'add' }); 172 173 SC.RunLoop.begin(); 174 view.insertBefore(add, view.childViews[2]); // note: 2 is the middle view 175 SC.RunLoop.end(); 176 177 checkDividers(view, 4); 178 179 // remove the one we added, and check again 180 SC.RunLoop.begin(); 181 view.removeChild(add); 182 SC.RunLoop.end(); 183 184 checkDividers(view, 3); 185 186 }); 187 188 test("Adding and removing before a divider doesn't screw things majorly", function() { 189 190 var view = createSplitView({ 191 childViews: 'left middle right'.w(), 192 middle: SC.View.design(SC.SplitChild, { name: 'middle' }) 193 }); 194 195 // do an initial check: should be three views with dividers. 196 checkDividers(view, 3); 197 198 // add one, and check again. 199 var add = SC.View.create(SC.SplitChild, { name: 'add' }); 200 201 SC.RunLoop.begin(); 202 view.insertBefore(add, view.childViews[1]); 203 SC.RunLoop.end(); 204 205 checkDividers(view, 4); 206 207 // remove the one we added, and check again 208 SC.RunLoop.begin(); 209 view.removeChild(add); 210 SC.RunLoop.end(); 211 212 checkDividers(view, 3); 213 214 }); 215 216 test("Adding and removing several views doesn't screw things up", function() { 217 var view = createSplitView({ 218 childViews: 'left middle right'.w(), 219 middle: SC.View.design(SC.SplitChild, { name: 'middle' }) 220 }); 221 222 // do an initial check: should be three views with dividers. 223 checkDividers(view, 3); 224 225 // add one, and check again. 226 var add1 = SC.View.create(SC.SplitChild, { name: 'add' }); 227 var add2 = SC.View.create(SC.SplitChild, { name: 'add' }); 228 var add3 = SC.View.create(SC.SplitChild, { name: 'add' }); 229 var add4 = SC.View.create(SC.SplitChild, { name: 'add' }); 230 231 SC.RunLoop.begin(); 232 view.removeChild(view.childViews[2]); 233 view.removeChild(view.childViews[3]); 234 235 // semi-random (I just picked 4 numbers): 236 view.insertBefore(add1, view.childViews[0]); 237 view.insertBefore(add2, view.childViews[0]); 238 view.insertBefore(add3, view.childViews[4]); 239 view.insertBefore(add4, view.childViews[3]); 240 SC.RunLoop.end(); 241 242 checkDividers(view, 5); 243 }); 244 245 test("SplitView#layoutDirection is correctly propagated to its dividers.", function() { 246 var view = createSplitView(), 247 layoutDirection = view.get('layoutDirection'), 248 nextLayoutDirection = layoutDirection === SC.LAYOUT_VERTICAL ? SC.LAYOUT_HORIZONTAL : SC.LAYOUT_VERTICAL; // hey just in case the default changes 249 250 var divider = view.childViews[1]; 251 ok(divider.isSplitDivider, "PRELIM: We found the divider."); 252 253 equals(divider.get('layoutDirection'), layoutDirection, "The divider's layoutDirection should match that of the SplitView."); 254 255 SC.RunLoop.begin(); 256 view.set('layoutDirection', nextLayoutDirection); 257 SC.RunLoop.end(); 258 259 equals(divider.get('layoutDirection'), nextLayoutDirection, "The divider's layoutDirection should update when the SplitView's does."); 260 261 view.destroy(); 262 }); 263