Repository: flex-sdk Updated Branches: refs/heads/develop 7b7ba9727 -> c7e77bbed
FLEX-26808 Added unit tests to make sure that the selection (made either programmatically or through ctrl-clicking on the grid) is preserved when the user starts dragging the items. The tests pass locally. -Also added VectorUtil.toArrayObject() to convert a Vector.<Object> to an Array (uses the same private function as VectorUtil.toArrayInt(), so I haven't added unit tests). -Added a missing semicolon in Grid.as Project: http://git-wip-us.apache.org/repos/asf/flex-sdk/repo Commit: http://git-wip-us.apache.org/repos/asf/flex-sdk/commit/f7077c66 Tree: http://git-wip-us.apache.org/repos/asf/flex-sdk/tree/f7077c66 Diff: http://git-wip-us.apache.org/repos/asf/flex-sdk/diff/f7077c66 Branch: refs/heads/develop Commit: f7077c669f807704706d2152cef2bcb360cb13a5 Parents: 7b7ba97 Author: Mihai Chira <mih...@apache.org> Authored: Thu Mar 31 13:10:38 2016 +0200 Committer: Mihai Chira <mih...@apache.org> Committed: Thu Mar 31 13:10:38 2016 +0200 ---------------------------------------------------------------------- .../framework/src/mx/utils/VectorUtil.as | 13 +- .../projects/spark/src/spark/components/Grid.as | 2 +- .../components/DataGrid_FLEX_26808_Tests.as | 125 ++++++++++++++++++- 3 files changed, 136 insertions(+), 4 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/flex-sdk/blob/f7077c66/frameworks/projects/framework/src/mx/utils/VectorUtil.as ---------------------------------------------------------------------- diff --git a/frameworks/projects/framework/src/mx/utils/VectorUtil.as b/frameworks/projects/framework/src/mx/utils/VectorUtil.as index 3e73895..c635746 100644 --- a/frameworks/projects/framework/src/mx/utils/VectorUtil.as +++ b/frameworks/projects/framework/src/mx/utils/VectorUtil.as @@ -29,8 +29,19 @@ package mx.utils { public static function toArrayInt(v:Vector.<int>):Array { + return v ? VectorToArray(v) : []; + } + + public static function toArrayObject(v:Vector.<Object>):Array + { + return v ? VectorToArray(v) : []; + } + + private static function VectorToArray(v:Object):Array + { + //this function assumes that v is a Vector! var result:Array = []; - for (var i:int = 0; i < (v ? v.length : 0); i++) + for (var i:int = 0; i < v.length; i++) { result.push(v[i]); } http://git-wip-us.apache.org/repos/asf/flex-sdk/blob/f7077c66/frameworks/projects/spark/src/spark/components/Grid.as ---------------------------------------------------------------------- diff --git a/frameworks/projects/spark/src/spark/components/Grid.as b/frameworks/projects/spark/src/spark/components/Grid.as index a489f31..23a6d5f 100644 --- a/frameworks/projects/spark/src/spark/components/Grid.as +++ b/frameworks/projects/spark/src/spark/components/Grid.as @@ -2377,7 +2377,7 @@ public class Grid extends Group implements IDataGridElement, IDataProviderEnhanc var f:Function = function():void { doSetSelectedIndices(valueCopy); - } + }; deferredOperations.push(f); // function f() to be called by commitProperties() invalidateProperties(); } http://git-wip-us.apache.org/repos/asf/flex-sdk/blob/f7077c66/frameworks/projects/spark/tests/spark/components/DataGrid_FLEX_26808_Tests.as ---------------------------------------------------------------------- diff --git a/frameworks/projects/spark/tests/spark/components/DataGrid_FLEX_26808_Tests.as b/frameworks/projects/spark/tests/spark/components/DataGrid_FLEX_26808_Tests.as index f5912afd..6b38388 100644 --- a/frameworks/projects/spark/tests/spark/components/DataGrid_FLEX_26808_Tests.as +++ b/frameworks/projects/spark/tests/spark/components/DataGrid_FLEX_26808_Tests.as @@ -26,8 +26,11 @@ package spark.components { import mx.collections.ArrayList; import mx.collections.IList; import mx.collections.ListCollectionView; + import mx.utils.ArrayUtil; + import mx.utils.VectorUtil; import org.flexunit.asserts.assertEquals; + import org.flexunit.asserts.assertFalse; import org.flexunit.asserts.assertNull; import org.flexunit.asserts.assertTrue; import org.flexunit.async.Async; @@ -44,6 +47,7 @@ package spark.components { private static var noEnterFramesRemaining:int = NaN; private var _sut:DataGridInspectable; private var _firstObject:FLEX_26808_VO; + private var _secondObject:FLEX_26808_VO; [Before] public function setUp():void @@ -58,6 +62,7 @@ package spark.components { const tenObjects:IList = generateVOs(10); _firstObject = tenObjects.getItemAt(0) as FLEX_26808_VO; + _secondObject = tenObjects.getItemAt(1) as FLEX_26808_VO; const dataProvider:ListCollectionView = new ListCollectionView(tenObjects); _sut.dataProvider = dataProvider; } @@ -80,10 +85,10 @@ package spark.components { noEnterFramesRemaining = NO_ENTER_FRAMES_TO_ALLOW; UIImpersonator.testDisplay.addEventListener(Event.ENTER_FRAME, onEnterFrame); - Async.handleEvent(this, _finishNotifier, Event.COMPLETE, testSelectionAndDeselection, 800); + Async.handleEvent(this, _finishNotifier, Event.COMPLETE, test_programmatic_selection_and_event_deselection_with_ctrl_click, 800); } - private function testSelectionAndDeselection(event:Event, passThroughData:Object):void + private function test_programmatic_selection_and_event_deselection_with_ctrl_click(event:Event, passThroughData:Object):void { function onGridMouseDown(event:GridEvent):void { @@ -112,6 +117,122 @@ package spark.components { _sut.removeEventListener(GridEvent.GRID_MOUSE_DOWN, onGridMouseDown); } + [Test(async, timeout=1000)] + public function test_ctrl_click_on_another_item_adds_it_to_selection():void + { + //when + UIImpersonator.addElement(_sut); + + //then + assertNull(_sut.selectedItem); + + noEnterFramesRemaining = NO_ENTER_FRAMES_TO_ALLOW; + UIImpersonator.testDisplay.addEventListener(Event.ENTER_FRAME, onEnterFrame); + Async.handleEvent(this, _finishNotifier, Event.COMPLETE, test_programmatic_selection_and_event_deselection_with_ctrl_click, 800); + } + + private function test_manual_multiple_selection_with_ctrl_click(event:Event, passThroughData:Object):void + { + function onGridMouseDown(event:GridEvent):void + { + assertTrue("The clicks should only happen on the first and second row!", event.rowIndex == 0 || event.rowIndex == 1); + assertTrue("Ctrl key should have been pressed on the second row!", event.rowIndex == 1 ? event.ctrlKey : true); + } + + //given + const mouseDownOnFirstItem:MouseEvent = new MouseEvent(MouseEvent.MOUSE_DOWN, true, false, 5, 5, null, false, false, false); + const mouseUpOnFirstItem:MouseEvent = new MouseEvent(MouseEvent.MOUSE_UP, true, false, 5, 5, null, false, false, false); + const mouseDownOnSecondItemWithCtrl:MouseEvent = new MouseEvent(MouseEvent.MOUSE_DOWN, true, false, 5, _sut.rowHeight + 2, null, false, false, false); + const mouseUpOnSecondItemWithCtrl:MouseEvent = new MouseEvent(MouseEvent.MOUSE_UP, true, false, 5, _sut.rowHeight + 2, null, false, false, false); + + //when - first click on first row to select it + _sut.addEventListener(GridEvent.GRID_MOUSE_DOWN, onGridMouseDown); + _sut.grid.dispatchEvent(mouseDownOnFirstItem); + _sut.grid.dispatchEvent(mouseUpOnFirstItem); + + //then + assertEquals(_firstObject, _sut.selectedItem); + + //when - ctrl+click on second item to add it to the selection + _sut.grid.dispatchEvent(mouseDownOnSecondItemWithCtrl); + _sut.grid.dispatchEvent(mouseUpOnSecondItemWithCtrl); + + //then + assertTrue(ArrayUtil.arraysMatch([_firstObject, _secondObject], VectorUtil.toArrayObject(_sut.selectedItems))); + _sut.removeEventListener(GridEvent.GRID_MOUSE_DOWN, onGridMouseDown); + } + + [Test(async, timeout=1000)] + public function test_dragging_maintains_programmatically_selected_items():void + { + //when + UIImpersonator.addElement(_sut); + + //then + assertNull(_sut.selectedItem); + + noEnterFramesRemaining = NO_ENTER_FRAMES_TO_ALLOW; + UIImpersonator.testDisplay.addEventListener(Event.ENTER_FRAME, onEnterFrame); + Async.handleEvent(this, _finishNotifier, Event.COMPLETE, test_programmatic_selection_and_dragging, 800); + } + + private function test_programmatic_selection_and_dragging(event:Event, passThroughData:Object):void + { + function onGridMouseDown(event:GridEvent):void + { + assertEquals(0, event.rowIndex); + assertFalse(event.ctrlKey); + } + + //when + _sut.selectedIndices = new <int>[0, 1]; + + //then + assertTrue(ArrayUtil.arraysMatch([_firstObject, _secondObject], VectorUtil.toArrayObject(_sut.selectedItems))); + + //given + const mouseDown:MouseEvent = new MouseEvent(MouseEvent.MOUSE_DOWN, true, false, 5, 5, null, false, false, false); + const mouseMove:MouseEvent = new MouseEvent(MouseEvent.MOUSE_MOVE, true, false, 5, 6, null, false, false, false); + _sut.addEventListener(GridEvent.GRID_MOUSE_DOWN, onGridMouseDown); + + //when - Mouse down and then mouse move to simulate drag + _sut.grid.dispatchEvent(mouseDown); + _sut.grid.dispatchEvent(mouseMove); + + //then + assertTrue(ArrayUtil.arraysMatch([_firstObject, _secondObject], VectorUtil.toArrayObject(_sut.selectedItems))); + _sut.removeEventListener(GridEvent.GRID_MOUSE_DOWN, onGridMouseDown); + } + + [Test(async, timeout=1000)] + public function test_dragging_maintains_manually_selected_items():void + { + //when + UIImpersonator.addElement(_sut); + + //then + assertNull(_sut.selectedItem); + + noEnterFramesRemaining = NO_ENTER_FRAMES_TO_ALLOW; + UIImpersonator.testDisplay.addEventListener(Event.ENTER_FRAME, onEnterFrame); + Async.handleEvent(this, _finishNotifier, Event.COMPLETE, test_programmatic_selection_and_dragging, 800); + } + + private function test_manual_selection_of_two_items_and_dragging(event:Event, passThroughData:Object):void + { + //given + const mouseDown:MouseEvent = new MouseEvent(MouseEvent.MOUSE_DOWN, true, false, 5, 5, null, false, false, false); + const mouseMove:MouseEvent = new MouseEvent(MouseEvent.MOUSE_MOVE, true, false, 5, 6, null, false, false, false); + + //when + test_manual_multiple_selection_with_ctrl_click(event, passThroughData); + _sut.grid.dispatchEvent(mouseDown); + _sut.grid.dispatchEvent(mouseMove); + + //then + assertTrue(ArrayUtil.arraysMatch([_firstObject, _secondObject], VectorUtil.toArrayObject(_sut.selectedItems))); + } + private static function onEnterFrame(event:Event):void { if(!--noEnterFramesRemaining)