//////////////////////////////////////////////////////////////////////////////// // // Licensed to the Apache Software Foundation (ASF) under one or more // contributor license agreements. See the NOTICE file distributed with // this work for additional information regarding copyright ownership. // The ASF licenses this file to You under the Apache License, Version 2.0 // (the "License"); you may not use this file except in compliance with // the License. You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// package UnitTest.Tests { import UnitTest.ExtendedClasses.TestSuiteExtended; import UnitTest.ExtendedClasses.VellumTestCase; import UnitTest.Fixtures.TestConfig; import UnitTest.Validation.*; import flash.display.DisplayObjectContainer; import flash.display.Shape; import flash.events.*; import flash.geom.Point; import flash.geom.Rectangle; import flash.text.engine.TextLine; import flashx.textLayout.compose.IFlowComposer; import flashx.textLayout.compose.TextFlowLine; import flashx.textLayout.container.ContainerController; import flashx.textLayout.container.ScrollPolicy; import flashx.textLayout.edit.IEditManager; import flashx.textLayout.edit.SelectionManager; import flashx.textLayout.edit.SelectionState; import flashx.textLayout.edit.TextScrap; import flashx.textLayout.elements.*; import flashx.textLayout.events.CompositionCompleteEvent; import flashx.textLayout.events.DamageEvent; import flashx.textLayout.events.FlowElementMouseEvent; import flashx.textLayout.events.FlowOperationEvent; import flashx.textLayout.events.ScrollEvent; import flashx.textLayout.events.ScrollEventDirection; import flashx.textLayout.events.SelectionEvent; import flashx.textLayout.events.StatusChangeEvent; import flashx.textLayout.events.TextLayoutEvent; import flashx.textLayout.events.UpdateCompleteEvent; import flashx.textLayout.formats.BlockProgression; import flashx.textLayout.formats.TextAlign; import flashx.textLayout.formats.TextLayoutFormat; import flashx.textLayout.operations.FlowElementOperation; import flashx.textLayout.operations.FlowOperation; import flashx.textLayout.operations.InsertInlineGraphicOperation; import flashx.textLayout.operations.RedoOperation; import flashx.textLayout.operations.UndoOperation; import flashx.textLayout.tlf_internal; import flashx.textLayout.utils.GeometryUtil; import mx.controls.scrollClasses.ScrollBar; import mx.utils.LoaderUtil; use namespace tlf_internal; public class AllEventTest extends VellumTestCase { public function AllEventTest(methodName:String, testID:String, testConfig:TestConfig, testCaseXML:XML=null) { super(methodName, testID, testConfig, testCaseXML); // Note: These must correspond to a Watson product area (case-sensitive) metaData.productArea = "Text Composition"; } public static function suiteFromXML(testListXML:XML, testConfig:TestConfig, ts:TestSuiteExtended):void { var testCaseClass:Class = AllEventTest; VellumTestCase.suiteFromXML(testCaseClass, testListXML, testConfig, ts); } private function beginSelectionEventValidation(target:IEventDispatcher, eventCount:int, validater:Function):void { target.addEventListener(SelectionEvent.SELECTION_CHANGE, validater); } //SelectionEvent Test Cases public function selectionEventTest():void { metaData.productArea = "Editing"; this.SelManager.selectRange(0,0); var textFlow:TextFlow = this.SelManager.textFlow; var endIdx:int = 200; var startIdx:int = 100; var theRects:Array = GeometryUtil.getHighlightBounds(new TextRange(textFlow, startIdx, endIdx)); for each(var lineRectPair:Object in theRects) { var theLine:TextLine = lineRectPair.textLine as TextLine; var rect:Rectangle = lineRectPair.rect as Rectangle; var tfl:TextFlowLine = theLine.userData as TextFlowLine; assertTrue( "userData on a textLine should be a TextFlowLine!", tfl); var parentObj:DisplayObjectContainer = theLine.parent; var selObj:Shape = new Shape(); var globalStart:Point = new Point(rect.x, rect.y); //first "click" inside the bounds of the rect and make sure we have a point within the selection range: var index:int = SelectionManager.tlf_internal::computeSelectionIndex(textFlow, theLine, null, rect.x + (rect.width/2), rect.y + (rect.height/2)); //validate using a calculated index. If this is a partial line selection, then using the abs start and end isn't valid. var checkStart:int = tfl.absoluteStart >= startIdx ? tfl.absoluteStart : startIdx; var checkEnd:int = (tfl.absoluteStart + tfl.textLength) <= endIdx ? (tfl.absoluteStart + tfl.textLength) : endIdx; //validate assertTrue( "the computed index derived from the selection shape must be within the line!", checkStart <= index && checkEnd >= index); } // Select All var validator:SelectionEventValidator = new SelectionEventValidator(TestFrame.textFlow, new SelectionEvent(SelectionEvent.SELECTION_CHANGE, false, false, new SelectionState(TestFrame.textFlow, 0, TestFrame.textFlow.textLength - 1))); SelManager.selectAll(); assertTrue("Expected selection event showing entire flow selected", validator.validate(1)); // Select range validator.reset(new SelectionEvent(SelectionEvent.SELECTION_CHANGE, false, false, new SelectionState(TestFrame.textFlow, 10, 100))); SelManager.selectRange(10, 100); SelManager.refreshSelection(); assertTrue("Expected selection event showing range selected", validator.validate(1)); // Apply format -- expects selection changed on selected area b/c the contents changed var format:TextLayoutFormat = new TextLayoutFormat(); format.fontSize = 48; validator.reset(); (SelManager as IEditManager).applyLeafFormat(format); assertTrue("Expected selection event after formatting applied", validator.validate(1)); // Insert text -- expects selection changed on selected area b/c the contents changed const textToInsert:String = "FOO"; validator.reset(new SelectionEvent(SelectionEvent.SELECTION_CHANGE, false, false, new SelectionState(TestFrame.textFlow, 20 + textToInsert.length, 20 + textToInsert.length))); SelManager.selectRange(20, 20); (SelManager as IEditManager).insertText("FOO"); SelManager.flushPendingOperations(); // force insert to happen right away assertTrue("Expected selection event after text insertion", validator.validate(1)); // Change select range - test that client code can change the selection from within a selection event handler textFlow.addEventListener(SelectionEvent.SELECTION_CHANGE, changeSelectionHandler); SelManager.selectRange(10, 100); SelManager.refreshSelection(); assertTrue("Expected entire flow selected", SelManager.absoluteStart == 0 && SelManager.absoluteEnd == textFlow.textLength - 1); // Test selection by mouse. We should get one and only one event from this. SelManager.selectRange(10, 11); theRects = GeometryUtil.getHighlightBounds(new TextRange(textFlow, SelManager.absoluteStart, SelManager.absoluteEnd)); theLine = theRects[0].textLine as TextLine; rect = theRects[0].rect as Rectangle; tfl = theLine.userData as TextFlowLine; var mouseEvent:MouseEvent = new MouseEvent(MouseEvent.MOUSE_DOWN, true, true, rect.x, rect.y, theLine, false, false, false, false); validator.reset(new SelectionEvent(SelectionEvent.SELECTION_CHANGE, false, false, new SelectionState(TestFrame.textFlow, 10, 10))); theLine.dispatchEvent(mouseEvent); assertTrue("Expected single selection event after mouse click", validator.validate(1)); } private function changeSelectionHandler(event:SelectionEvent):void { var textFlow:TextFlow = event.selectionState.textFlow; textFlow.removeEventListener(SelectionEvent.SELECTION_CHANGE, changeSelectionHandler); textFlow.interactionManager.selectRange(0, textFlow.textLength); } // DamageEvent Test Cases public function damageEventTest():void { //Change Color Test var selectionBegin:int = 20; var selectionEnd:int = 400; SelManager.selectRange(selectionBegin,selectionEnd); var validator:DamageEventValidator = new DamageEventValidator(TestFrame.textFlow, new DamageEvent(DamageEvent.DAMAGE, false, false, null, SelManager.absoluteStart, SelManager.absoluteEnd-SelManager.absoluteStart)); const fontColor:int = 0xFF0000; var ca:TextLayoutFormat = new TextLayoutFormat(); ca.color = fontColor; SelManager.applyLeafFormat(ca); SelManager.flushPendingOperations(); assertTrue("Expected damage event showing after color change",validator.validate(1)); //Delete Text Test validator.reset(new DamageEvent(DamageEvent.DAMAGE, false, false, null, SelManager.absoluteStart, SelManager.absoluteEnd-SelManager.absoluteStart)); SelManager.cutTextScrap(SelManager.getSelectionState()); SelManager.flushPendingOperations(); assertTrue("Expected damage event showing after text deletion",validator.validate(1)); //Delete Character Test SelManager.selectRange(90,91); validator.reset(new DamageEvent(DamageEvent.DAMAGE, false, false, null, SelManager.absoluteStart, SelManager.absoluteEnd-SelManager.absoluteStart)); SelManager.cutTextScrap(SelManager.getSelectionState()); SelManager.flushPendingOperations(); assertTrue("Expected damage event showing after character deletion",validator.validate(1)); //Change Geometry Test validator.reset(new DamageEvent(DamageEvent.DAMAGE, false, false, TestFrame.textFlow, 0, TestFrame.textFlow.textLength)); TestFrame.setCompositionSize(500,500); TestFrame.textFlow.flowComposer.updateAllControllers(); assertTrue("Expected damage event showing after Geometry change",validator.validate(1)); //Change Block Progression Test validator.reset(new DamageEvent(DamageEvent.DAMAGE, false, false, TestFrame.textFlow, 0, TestFrame.textFlow.textLength)); TestFrame.textFlow.blockProgression = "rl"; TestFrame.textFlow.flowComposer.updateAllControllers(); assertTrue("Expected damage event showing after Block Progression change",validator.validate(1)); //Change Font Size Test validator.reset(new DamageEvent(DamageEvent.DAMAGE, false, false, TestFrame.textFlow, 0, TestFrame.textFlow.textLength)); TestFrame.textFlow.fontSize = 32; TestFrame.textFlow.flowComposer.updateAllControllers(); assertTrue("Expected DamageEvent showing after Font Size change",validator.validate(1)); } public function statusChangeEventTest():void { metaData.productArea = "Editing"; //Insert Picture Test var src:String = LoaderUtil.createAbsoluteURL(baseURL,"../../test/testFiles/assets/leaves.jpg"); var element:InlineGraphicElement = new InlineGraphicElement(); element.source = src; element.width = 30; element.height = 30; var validator:StatusChangeEventValidator = new StatusChangeEventValidator(TestFrame.textFlow, new StatusChangeEvent(StatusChangeEvent.INLINE_GRAPHIC_STATUS_CHANGE, false, false, element, "loading", null)); var width:int = 30; var height:int = 30; var selectionBegin:int = 10; var selectionEnd:int = 10; SelManager.selectRange(selectionBegin, selectionEnd); SelManager.insertInlineGraphic(src,width,height); SelManager.flushPendingOperations(); assertTrue("Expected StatusChangeEvent showing after picture insertion",validator.validate(1)); } public function FlowOperationEventTest():void { metaData.productArea = "Editing"; var src:String = LoaderUtil.createAbsoluteURL(baseURL,"../../test/testFiles/assets/leaves.jpg"); var width:int = 30; var height:int = 30; var selectionBegin:int = 10; var selectionEnd:int = 10; SelManager.selectRange(selectionBegin, selectionEnd); var operation:InsertInlineGraphicOperation = new InsertInlineGraphicOperation(SelManager.getSelectionState(), src, width, height,"none"); var beginValidator:FlowOperationEventValidator = new FlowOperationEventValidator(TestFrame.textFlow, new FlowOperationEvent(FlowOperationEvent.FLOW_OPERATION_BEGIN, false, false, operation, 0, null)); var endValidator:FlowOperationEventValidator = new FlowOperationEventValidator(TestFrame.textFlow, new FlowOperationEvent(FlowOperationEvent.FLOW_OPERATION_END, false, false, operation, 0, null)); var completeValidator:FlowOperationEventValidator = new FlowOperationEventValidator(TestFrame.textFlow, new FlowOperationEvent(FlowOperationEvent.FLOW_OPERATION_COMPLETE, false, false, operation, 0, null)); var compositionValidator:CompositionCompleteEventValidator = new CompositionCompleteEventValidator(TestFrame.textFlow, new CompositionCompleteEvent(CompositionCompleteEvent.COMPOSITION_COMPLETE, false, false, TestFrame.textFlow, 0, TestFrame.textFlow.textLength+1)); SelManager.insertInlineGraphic(src,width,height); assertTrue("Expected FlowOperationBeginEvent during picture insertion", beginValidator.validate(1)); assertTrue("Expected FlowOperationEndEvent during picture insertion", endValidator.validate(1)); assertTrue("Expected FlowOperationCompleteEvent during picture insertion", completeValidator.validate(1)); assertTrue("Expected CompositionCompleEvent during picture insertion", compositionValidator.validate(1)); // Check undo var pseudoUndoOperation:UndoOperation = new UndoOperation(operation); beginValidator.reset(new FlowOperationEvent(FlowOperationEvent.FLOW_OPERATION_BEGIN, false, false, pseudoUndoOperation, 0, null)); endValidator.reset(new FlowOperationEvent(FlowOperationEvent.FLOW_OPERATION_END, false, false, pseudoUndoOperation, 0, null)); completeValidator.reset(new FlowOperationEvent(FlowOperationEvent.FLOW_OPERATION_COMPLETE, false, false, pseudoUndoOperation, 0, null)); SelManager.undo(); assertTrue("Expected FlowOperationBeginEvent during undo picture insertion", beginValidator.validate(1)); assertTrue("Pseudo undo event should have been broadcast", FlowOperationEvent(beginValidator.lastEvent).operation is UndoOperation); assertTrue("Expected FlowOperationEndEvent during undo picture insertion", endValidator.validate(1)); assertTrue("Pseudo undo event should have been broadcast", FlowOperationEvent(endValidator.lastEvent).operation is UndoOperation); assertTrue("Expected FlowOperationCompleteEvent undo during picture insertion", completeValidator.validate(1)); assertTrue("Pseudo undo event should have been broadcast", FlowOperationEvent(completeValidator.lastEvent).operation is UndoOperation); // Check redo var pseudoRedoOperation:RedoOperation = new RedoOperation(operation); beginValidator.reset(new FlowOperationEvent(FlowOperationEvent.FLOW_OPERATION_BEGIN, false, false, pseudoRedoOperation, 0, null)); endValidator.reset(new FlowOperationEvent(FlowOperationEvent.FLOW_OPERATION_END, false, false, pseudoRedoOperation, 0, null)); completeValidator.reset(new FlowOperationEvent(FlowOperationEvent.FLOW_OPERATION_COMPLETE, false, false, pseudoRedoOperation, 0, null)); SelManager.redo(); assertTrue("Expected FlowOperationBeginEvent during redo picture insertion", beginValidator.validate(1)); assertTrue("Pseudo redo event should have been broadcast", FlowOperationEvent(beginValidator.lastEvent).operation is RedoOperation); assertTrue("Expected FlowOperationEndEvent during redo picture insertion", endValidator.validate(1)); assertTrue("Pseudo redo event should have been broadcast", FlowOperationEvent(endValidator.lastEvent).operation is RedoOperation); assertTrue("Expected FlowOperationCompleteEvent redo during picture insertion", completeValidator.validate(1)); assertTrue("Pseudo redo event should have been broadcast", FlowOperationEvent(completeValidator.lastEvent).operation is RedoOperation); } public function FlowCompositeOperationEventTest():void { metaData.productArea = "Editing"; var beginValidator:FlowOperationEventValidator = new FlowOperationEventValidator(TestFrame.textFlow, new FlowOperationEvent(FlowOperationEvent.FLOW_OPERATION_BEGIN, false, false, new FlowOperation(TestFrame.textFlow), 1, null)); var endValidator:FlowOperationEventValidator = new FlowOperationEventValidator(TestFrame.textFlow, new FlowOperationEvent(FlowOperationEvent.FLOW_OPERATION_END, false, false, new FlowOperation(TestFrame.textFlow), 1, null)); var completeValidator:FlowOperationEventValidator = new FlowOperationEventValidator(TestFrame.textFlow, new FlowOperationEvent(FlowOperationEvent.FLOW_OPERATION_COMPLETE, false, false, new FlowOperation(TestFrame.textFlow), 0, null)); var compositionValidator:CompositionCompleteEventValidator = new CompositionCompleteEventValidator(TestFrame.textFlow, new CompositionCompleteEvent(CompositionCompleteEvent.COMPOSITION_COMPLETE, false, false, TestFrame.textFlow, 0, TestFrame.textFlow.textLength)); SelManager.selectAll(); SelManager.beginCompositeOperation(); var leafFormat:TextLayoutFormat = new TextLayoutFormat(); leafFormat.fontSize = 18; SelManager.applyLeafFormat(leafFormat); var paraFormat:TextLayoutFormat = new TextLayoutFormat(); paraFormat.textAlign = TextAlign.CENTER; SelManager.applyParagraphFormat(paraFormat); SelManager.endCompositeOperation(); assertTrue("Expected FlowOperationBeginEvent during composite operation", beginValidator.validate(2)); assertTrue("Expected FlowOperationEndEvent during composite operation", endValidator.validate(2)); assertTrue("Expected FlowOperationCompleteEvent during composite operation", completeValidator.validate(1)); assertTrue("Expected CompositionCompleEvent during composite operation", compositionValidator.validate(1)); } public function CompositionCompleteEventTest():void { var validator:CompositionCompleteEventValidator; var scroll:ScrollBar = new ScrollBar(); var textHeight:int = Math.ceil(TestFrame.getContentBounds().height); var textWidth:int = Math.ceil(TestFrame.getContentBounds().width); if (TestFrame.textFlow.blockProgression == "rl") { validator = new CompositionCompleteEventValidator(TestFrame.textFlow, new CompositionCompleteEvent(CompositionCompleteEvent.COMPOSITION_COMPLETE, false, false, TestFrame.textFlow, 0, 744)); } else { validator = new CompositionCompleteEventValidator(TestFrame.textFlow, new CompositionCompleteEvent(CompositionCompleteEvent.COMPOSITION_COMPLETE, false, false, TestFrame.textFlow, 0, 831)); } TestFrame.textFlow.fontSize = 30; TestFrame.textFlow.flowComposer.updateAllControllers(); assertTrue("Expected CompositionCompleEvent showing after font size changing", validator.validate(1)); } public function UpdateCompleteEventTest():void { var validator:UpdateCompleteEventValidator = new UpdateCompleteEventValidator(TestFrame.textFlow, new UpdateCompleteEvent(UpdateCompleteEvent.UPDATE_COMPLETE, false, false, TestFrame.textFlow, TestFrame)); var selectionBegin:int = 40; var selectionEnd:int = 50; SelManager.selectRange(selectionBegin, selectionEnd); SelManager.deleteNextWord(); SelManager.textFlow.flowComposer.updateAllControllers(); // should not result in a compose and not generate an UpdateCompleteEvent assertTrue("Expected One UpdateCompleteEvent showing after deleteNextWord", validator.validate(1)); } // Test cases that should be covered // 1. link on part of the line // 2. link across several lines // For now, only covering first line in link public function FlowElementMouseEventTest():void { var validator:FlowElementMouseEventValidator; var cc:ContainerController = SelManager.textFlow.flowComposer.getControllerAt(0); if (TestData.id == "FlowElementMouseEventTestScrollingOn") { cc.verticalScrollPolicy = ScrollPolicy.ON; cc.horizontalScrollPolicy = ScrollPolicy.ON; }else if (TestData.id == "FlowElementMouseEventTestScrolled") { cc.verticalScrollPolicy = ScrollPolicy.ON; cc.horizontalScrollPolicy = ScrollPolicy.ON; var originalXScroll:Number = cc.horizontalScrollPosition; var originalYScroll:Number = cc.verticalScrollPosition; // Copy and paste the entire text, which should cause a scroll event SelManager.selectRange(0, int.MAX_VALUE); var scrap:TextScrap = TextScrap.createTextScrap(new TextRange(SelManager.textFlow, 0, SelManager.textFlow.textLength)); var validator1:EventValidator = new EventValidator(SelManager.textFlow, new ScrollEvent(TextLayoutEvent.SCROLL, false, false)); SelManager.selectRange(int.MAX_VALUE, int.MAX_VALUE); SelManager.pasteTextScrap(scrap); assertTrue("Expected to get a scroll event, but didn't", validator1.validate(1)); // Verify that the direction and delta in the event are correct var scrollEvent:ScrollEvent = validator1.lastEvent as ScrollEvent; validateScrollEvent(validator1.lastEvent as ScrollEvent, originalXScroll, originalYScroll); // scroll to a new position, and check that works as expected originalXScroll = cc.horizontalScrollPosition; originalYScroll = cc.verticalScrollPosition; validator1.reset(new ScrollEvent(TextLayoutEvent.SCROLL, false, false)); validateScrollEvent(validator1.lastEvent as ScrollEvent, originalXScroll, originalYScroll); TestFrame.textFlow.flowComposer.updateAllControllers(); } SelManager.selectRange(76, 85); SelManager.applyLink("http://www.adobe.com/go/flashplayer","_self" ,false); TestFrame.textFlow.flowComposer.updateAllControllers(); var container:DisplayObjectContainer = SelManager.textFlow.flowComposer.getControllerAt(0).container; if (TestData.id == "FlowElementMouseEventTestMeasure") { container.height = NaN; container.width = NaN; } // Get the bounds of the link in TextLine coordinates var boundsInfo:Object = GeometryUtil.getHighlightBounds(SelManager.getSelectionState())[0]; var bounds:Rectangle = boundsInfo.rect as Rectangle; var textLine:TextLine = boundsInfo.textLine; // get the event mirror off the link var leaf:FlowLeafElement = SelManager.textFlow.findLeaf(SelManager.absoluteStart); var link:LinkElement = leaf.parent as LinkElement; var textFlow:TextFlow = SelManager.textFlow; // save it for later SelManager.textFlow.interactionManager = null; // turn off editing // before we've done anything, link in normal state assertTrue("before we've done anything, link should be in normal state", link.linkState == LinkState.LINK); // listen for rollOver event on the link, send an ersatz mouse_over, which will cause a rollOver // after mouseOver, link should be in hover state validator = new FlowElementMouseEventValidator(link, new FlowElementMouseEvent(FlowElementMouseEvent.ROLL_OVER, false, true, link, null)); var mouseOverEvent:MouseEvent = new MouseEvent(MouseEvent.MOUSE_OVER, true, false, (bounds.left + bounds.right) / 2, (bounds.top + bounds.bottom) / 2, textLine); textLine.dispatchEvent(mouseOverEvent); validator.validate(1); assertTrue("after mouseOver, link should be in hover state", link.linkState == LinkState.HOVER); // mouseMove validator = new FlowElementMouseEventValidator(link, new FlowElementMouseEvent(FlowElementMouseEvent.MOUSE_MOVE, false, true, link, null)); var mouseMoveEvent:MouseEvent = new MouseEvent(MouseEvent.MOUSE_MOVE, true, false, (bounds.left + bounds.right) / 2, (bounds.top + bounds.bottom) / 2, textLine); textLine.dispatchEvent(mouseMoveEvent); validator.validate(1); // mouseDown validator = new FlowElementMouseEventValidator(link, new FlowElementMouseEvent(FlowElementMouseEvent.MOUSE_DOWN, false, true, link, null)); var mouseDownEvent:MouseEvent = new MouseEvent(MouseEvent.MOUSE_DOWN, true, false, (bounds.left + bounds.right) / 2, (bounds.top + bounds.bottom) / 2, textLine); textLine.dispatchEvent(mouseDownEvent); validator.validate(1); assertTrue("after mouseDown, link should be in active state", link.linkState == LinkState.ACTIVE); // mouseUp -- also generates click validator = new FlowElementMouseEventValidator(link, new FlowElementMouseEvent(FlowElementMouseEvent.MOUSE_UP, false, true, link, null)); var clickValidator:FlowElementMouseEventValidator = new FlowElementMouseEventValidator(link, new FlowElementMouseEvent(FlowElementMouseEvent.CLICK, false, true, link, null)); var mouseUpEvent:MouseEvent = new MouseEvent(MouseEvent.MOUSE_UP, true, false, (bounds.left + bounds.right) / 2, (bounds.top + bounds.bottom) / 2, textLine); textLine.dispatchEvent(mouseUpEvent); validator.validate(1); clickValidator.validate(1); assertTrue("after mouseUp, link should be in hover state", link.linkState == LinkState.HOVER); // mouseOut validator = new FlowElementMouseEventValidator(link, new FlowElementMouseEvent(FlowElementMouseEvent.ROLL_OUT, false, true, link, null)); var mouseOutEvent:MouseEvent = new MouseEvent(MouseEvent.MOUSE_OUT, true, false, bounds.right + 1, bounds.bottom + 1, textLine); textLine.dispatchEvent(mouseOutEvent); validator.validate(1); assertTrue("after mouseOut, link should be in default (normal) state", link.linkState == LinkState.LINK); // avoid tearDown assert about no Selectionmanager textFlow.interactionManager = SelManager; SelManager.selectRange(0, 0); } private function validateScrollEvent(scrollEvent:ScrollEvent, originalXScroll:Number, originalYScroll:Number):void { var flowComposer:IFlowComposer = SelManager.textFlow.flowComposer; var controller:ContainerController = flowComposer.getControllerAt(flowComposer.numControllers - 1); if (originalXScroll != controller.horizontalScrollPosition) { assertTrue("Scrolled horizontally, but got vertical scroll event", scrollEvent.direction == ScrollEventDirection.HORIZONTAL); assertTrue("Scroll delta doesn't match expected", scrollEvent.delta == controller.horizontalScrollPosition - originalXScroll); } if (originalYScroll != controller.verticalScrollPosition) { assertTrue("Scrolled vertically, but got horizontal scroll event", scrollEvent.direction == ScrollEventDirection.VERTICAL); assertTrue("Scroll delta doesn't match expected", scrollEvent.delta == controller.verticalScrollPosition - originalYScroll); } } public function scrollEventTest():void { var textFlow:TextFlow = SelManager.textFlow; var controller:ContainerController = textFlow.flowComposer.getControllerAt(0); controller.verticalScrollPolicy = ScrollPolicy.ON; controller.horizontalScrollPolicy = ScrollPolicy.ON; var originalXScroll:Number = controller.horizontalScrollPosition; var originalYScroll:Number = controller.verticalScrollPosition; // Copy and paste the entire text, which should cause a scroll event SelManager.selectRange(0, int.MAX_VALUE); var scrap:TextScrap = TextScrap.createTextScrap(new TextRange(textFlow, 0, textFlow.textLength)); var validator:EventValidator = new EventValidator(SelManager.textFlow, new ScrollEvent(TextLayoutEvent.SCROLL, false, false)); SelManager.selectRange(int.MAX_VALUE, int.MAX_VALUE); SelManager.pasteTextScrap(scrap); assertTrue("Expected to get a scroll event, but didn't", validator.validate(1)); // Verify that the direction and delta in the event are correct var scrollEvent:ScrollEvent = validator.lastEvent as ScrollEvent; validateScrollEvent(validator.lastEvent as ScrollEvent, originalXScroll, originalYScroll); // Now scroll up, and check that works as expected originalXScroll = controller.horizontalScrollPosition; originalYScroll = controller.verticalScrollPosition; var verticalText:Boolean = textFlow.computedFormat.blockProgression == BlockProgression.RL; validator.reset(new ScrollEvent(TextLayoutEvent.SCROLL, false, false)); if (verticalText) controller.horizontalScrollPosition = 0; else controller.verticalScrollPosition = 0; validateScrollEvent(validator.lastEvent as ScrollEvent, originalXScroll, originalYScroll); } } }