Merge remote-tracking branch 'remotes/origin/develop' into FlexUnit4TestsTLF
diff --git a/automation_tests/src/AllTestsSuite.as b/automation_tests/src/AllTestsSuite.as
index f6f8045..e7f603d 100644
--- a/automation_tests/src/AllTestsSuite.as
+++ b/automation_tests/src/AllTestsSuite.as
@@ -36,6 +36,7 @@
     import UnitTest.Tests.FactoryImportTest;
     import UnitTest.Tests.FloatTest;
     import UnitTest.Tests.FlowModelTest;
+    import UnitTest.Tests.GeneralFunctionsTest;
     import UnitTest.Tests.OperationTest;
     import UnitTest.Tests.ScrollingTest;
 
@@ -62,6 +63,7 @@
         public var elementOperationTest:ElementOperationTest;
         public var eventOverrideTest:EventOverrideTest;
         public var flowModelTest:FlowModelTest;
+        public var generalFunctionsTest:GeneralFunctionsTest;
     }
 
 }
diff --git a/automation_tests/src/UnitTest/Tests/GeneralFunctionsTest.as b/automation_tests/src/UnitTest/Tests/GeneralFunctionsTest.as
index 134f99c..fd022cb 100644
--- a/automation_tests/src/UnitTest/Tests/GeneralFunctionsTest.as
+++ b/automation_tests/src/UnitTest/Tests/GeneralFunctionsTest.as
@@ -18,33 +18,30 @@
 ////////////////////////////////////////////////////////////////////////////////
 package UnitTest.Tests
 {
-	import UnitTest.ExtendedClasses.TestDescriptor;
-	import UnitTest.ExtendedClasses.TestSuiteExtended;
-	import UnitTest.ExtendedClasses.VellumTestCase;
-	import UnitTest.Fixtures.TestConfig;
-	import UnitTest.Fixtures.TestEditManager;
-	
-	import flash.display.Sprite;
-	import flash.events.*;
-	import flash.text.engine.FontPosture;
-	import flash.text.engine.FontWeight;
-	import flash.ui.Keyboard;
-	import flash.utils.getDefinitionByName;
-	import flash.utils.getQualifiedClassName;
-	
-	import flashx.textLayout.container.ContainerController;
-	import flashx.textLayout.conversion.ITextImporter;
-	import flashx.textLayout.conversion.TextConverter;
-	import flashx.textLayout.edit.EditManager;
-	import flashx.textLayout.elements.*;
-	import flashx.textLayout.events.FlowOperationEvent;
-	import flashx.textLayout.events.SelectionEvent;
-	import flashx.textLayout.events.StatusChangeEvent;
-	import flashx.textLayout.formats.*;
-	import flashx.textLayout.operations.FlowOperation;
-	import flashx.textLayout.operations.UndoOperation;
-	import flashx.textLayout.tlf_internal;
-	import flashx.undo.UndoManager;
+    import UnitTest.ExtendedClasses.VellumTestCase;
+    import UnitTest.Fixtures.TestConfig;
+    import UnitTest.Fixtures.TestEditManager;
+
+    import flash.display.Sprite;
+    import flash.events.*;
+    import flash.text.engine.FontPosture;
+    import flash.text.engine.FontWeight;
+    import flash.ui.Keyboard;
+    import flash.utils.getQualifiedClassName;
+
+    import flashx.textLayout.container.ContainerController;
+    import flashx.textLayout.conversion.ITextImporter;
+    import flashx.textLayout.conversion.TextConverter;
+    import flashx.textLayout.edit.EditManager;
+    import flashx.textLayout.elements.*;
+    import flashx.textLayout.events.FlowOperationEvent;
+    import flashx.textLayout.events.SelectionEvent;
+    import flashx.textLayout.events.StatusChangeEvent;
+    import flashx.textLayout.formats.*;
+    import flashx.textLayout.operations.FlowOperation;
+    import flashx.textLayout.operations.UndoOperation;
+    import flashx.textLayout.tlf_internal;
+    import flashx.undo.UndoManager;
 
     import org.flexunit.asserts.assertTrue;
     import org.flexunit.asserts.fail;
@@ -52,1296 +49,1336 @@
     use namespace tlf_internal;
 
 
- 	public class GeneralFunctionsTest extends VellumTestCase
-	{
-		public var SelectionChanged:Boolean;
-		private var callback:Boolean;
+    public class GeneralFunctionsTest extends VellumTestCase
+    {
+        public static const childParentTable:Array =
+                [
+                    [ "child\parent", TextFlow, DivElement, ParagraphElement, LinkElement, TCYElement, SpanElement, InlineGraphicElement, BreakElement, TabElement, ListElement, ListItemElement, SubParagraphGroupElement ],
+                    [ TextFlow, "no", "no", "no", "no", "no", "no", "no", "no", "no", "no", "no", "no" ],
+                    [ DivElement, "yes", "yes", "no", "no", "no", "no", "no", "no", "no", "yes", "yes", "no" ],
+                    [ ParagraphElement, "yes", "yes", "no", "no", "no", "no", "no", "no", "no", "yes", "yes", "no" ],
+                    [ LinkElement, "no", "no", "yes", "no", "yes", "no", "no", "no", "no", "no", "no", "yes" ],
+                    [ TCYElement, "no", "no", "yes", "yes", "no", "no", "no", "no", "no", "no", "no", "yes" ],
+                    [ SpanElement, "no", "no", "yes", "yes", "yes", "no", "no", "no", "no", "no", "no", "yes" ],
+                    [ InlineGraphicElement, "no", "no", "yes", "yes", "yes", "no", "no", "no", "no", "no", "no", "yes" ],
+                    [ BreakElement, "no", "no", "yes", "yes", "yes", "no", "no", "no", "no", "no", "no", "yes" ],
+                    [ TabElement, "no", "no", "yes", "yes", "yes", "no", "no", "no", "no", "no", "no", "yes" ],
+                    [ ListElement, "yes", "yes", "no", "no", "no", "no", "no", "no", "no", "yes", "yes", "no" ],
+                    [ ListItemElement, "no", "no", "no", "no", "no", "no", "no", "no", "no", "yes", "no", "no" ],
+                    [ SubParagraphGroupElement, "no", "no", "yes", "yes", "yes", "no", "no", "no", "no", "no", "no", "yes" ]
+                ];
 
-		public function GeneralFunctionsTest(methodName:String, testID:String, testConfig:TestConfig, testXML:XML = null)
-		{
-			super(methodName, testID, testConfig);
+        private static const customResourceDict:Object =
+        {
+            invalidFlowElementConstruct_custom: "Attempted construct of invalid FlowElement subclass",
+            badMXMLChildrenArgument_custom: "Bad element of type {0} passed to mxmlChildren",
+            malformedTag: "Malformed tag </p/>",
+            XMLParserFailure: "TypeError: Error #1090: XML parser failure: element is malformed."
+        };
 
-			// Note: These must correspond to a Watson product area (case-sensitive)
-			metaData.productArea = "Editing";
-		}
+        /**
+         * pick up the actual operation
+         */
+        private var flowOp:FlowOperation;
+        private var SelectionChanged:Boolean;
+        private var ilgStatus:String;
 
-		public static function suite(testConfig:TestConfig, ts:TestSuiteExtended):void
-		{
-			ts.addTestDescriptor (new TestDescriptor(GeneralFunctionsTest, "arrowLeft", testConfig) );
-			ts.addTestDescriptor (new TestDescriptor(GeneralFunctionsTest, "arrowRight", testConfig) );
-			//ts.addTestDescriptor (new TestDescriptor(GeneralFunctionsTest, "arrowDown", testConfig) );
-			//ts.addTestDescriptor (new TestDescriptor(GeneralFunctionsTest, "arrowUp", testConfig) );
-			ts.addTestDescriptor (new TestDescriptor(GeneralFunctionsTest, "replaceSelectionTest", testConfig) );
-			ts.addTestDescriptor (new TestDescriptor(GeneralFunctionsTest, "backSpaceSelectionTest", testConfig) ); // KJT
-			ts.addTestDescriptor (new TestDescriptor(GeneralFunctionsTest, "backSpaceInsertionPointTest", testConfig) );
-			ts.addTestDescriptor (new TestDescriptor(GeneralFunctionsTest, "backSpaceLowerLimitTest", testConfig) );
-			ts.addTestDescriptor (new TestDescriptor(GeneralFunctionsTest, "deleteSelectionTest", testConfig) );
-			ts.addTestDescriptor (new TestDescriptor(GeneralFunctionsTest, "deleteInsertionPointTest", testConfig) );
-			ts.addTestDescriptor (new TestDescriptor(GeneralFunctionsTest, "deleteUpperLimitTest", testConfig) );
-			ts.addTestDescriptor (new TestDescriptor(GeneralFunctionsTest, "splitParagraphInsertionPointTest", testConfig) );
-			ts.addTestDescriptor (new TestDescriptor(GeneralFunctionsTest, "splitParagraphSelectionTest", testConfig) );
-			ts.addTestDescriptor (new TestDescriptor(GeneralFunctionsTest, "splitParagraphFormatTest", testConfig) );
-			ts.addTestDescriptor (new TestDescriptor(GeneralFunctionsTest, "unDoOp", testConfig) ); // undo redo// KJT
-			ts.addTestDescriptor (new TestDescriptor(GeneralFunctionsTest, "setSelectionRangeTest", testConfig) );// select range and listen for change event // KJT
-			ts.addTestDescriptor (new TestDescriptor(GeneralFunctionsTest, "insertTextTest", testConfig) ); // KJT
-			ts.addTestDescriptor (new TestDescriptor(GeneralFunctionsTest, "joinedBackspaceUndoTest", testConfig) );
-			ts.addTestDescriptor (new TestDescriptor(GeneralFunctionsTest, "joinedDeleteUndoTest", testConfig) );
-			/* Waiting for troubleshooting -*/ ts.addTestDescriptor (new TestDescriptor(GeneralFunctionsTest, "joinedInsertUndoTest", testConfig) );
-			ts.addTestDescriptor (new TestDescriptor(GeneralFunctionsTest, "joinedSplitParagraphUndoTest", testConfig) );
-			ts.addTestDescriptor (new TestDescriptor(GeneralFunctionsTest, "undoLimitTest", testConfig) );
-			ts.addTestDescriptor (new TestDescriptor(GeneralFunctionsTest, "transParagraphDeleteTest", testConfig) );
-			ts.addTestDescriptor (new TestDescriptor(GeneralFunctionsTest, "emptyParagraphTest", testConfig) );
-			ts.addTestDescriptor (new TestDescriptor(GeneralFunctionsTest, "splitUTF16Test", testConfig) );
-			ts.addTestDescriptor (new TestDescriptor(GeneralFunctionsTest, "splitUTF32Test", testConfig) );
-			ts.addTestDescriptor (new TestDescriptor(GeneralFunctionsTest, "undoWithModelChangeTest", testConfig) );
-			ts.addTestDescriptor (new TestDescriptor(GeneralFunctionsTest, "doubleClickTest", testConfig) );
-			ts.addTestDescriptor (new TestDescriptor(GeneralFunctionsTest, "doubleClickHyphenTest", testConfig) );
-			ts.addTestDescriptor (new TestDescriptor(GeneralFunctionsTest, "doubleClickPunctuationTest", testConfig) );
-			ts.addTestDescriptor (new TestDescriptor(GeneralFunctionsTest, "undoRedoStackTest", testConfig) );
-			if (testConfig.writingDirection[0] == BlockProgression.TB && testConfig.writingDirection[1] == Direction.LTR)
-			{
-				ts.addTestDescriptor (new TestDescriptor(GeneralFunctionsTest, "replaceChildrenFlowTest", testConfig) );
-				ts.addTestDescriptor (new TestDescriptor(GeneralFunctionsTest, "resolveInlinesTest", testConfig) );
-				ts.addTestDescriptor (new TestDescriptor(GeneralFunctionsTest, "nestingTest", testConfig) );
-				ts.addTestDescriptor (new TestDescriptor(GeneralFunctionsTest, "errorThrowing", testConfig ) );
-				ts.addTestDescriptor (new TestDescriptor(GeneralFunctionsTest, "AllNestingTest", testConfig ) );
-			}
-		}
+        public function GeneralFunctionsTest()
+        {
+            super("", "EventOverrideTest", TestConfig.getInstance());
 
-		/**
-		* selecting text from 10 to 20
-		*/
+            metaData = {};
+            // Note: These must correspond to a Watson product area (case-sensitive)
+            metaData.productArea = "Editing";
+        }
 
-		public function selChange(e:Event):void //KJT selection change event method
-		{
-			SelectionChanged = true;
-		}
 
-		public function setSelectionRangeTest():void  //KJT  test selection range and change event
-		{
-			var startIndx:int = 800;
-			var endIndx:int = 933;
-			//trace('CALL SET SELECTION');
+        [Before]
+        override public function setUpTest():void
+        {
+            super.setUpTest();
+        }
 
-			SelManager.textFlow.addEventListener(SelectionEvent.SELECTION_CHANGE, selChange, false, 0, true);
-			SelManager.selectRange(startIndx,endIndx);
+        [After]
+        override public function tearDownTest():void
+        {
+            super.tearDownTest();
+        }
 
-			assertTrue("beginning index should be 800, but is " + SelManager.anchorPosition,
-						SelManager.anchorPosition == 800);
-			assertTrue("end index should be 933, but is " + SelManager.activePosition,
-						SelManager.activePosition == 933);
-			assertTrue("SelectionChanged returned false", SelectionChanged == true);
-		}
-		/**
- 		 * Select 40 characters and replaces them with new text
- 		 */
-		public function replaceSelectionTest():void
-		{
-			var startIndx:int = 10;
-			var endIndx:int = 50;
 
-			var attributes:TextLayoutFormat  = new TextLayoutFormat();
-			attributes.fontWeight = FontWeight.BOLD;
-			attributes.lineThrough = true;
+        [Test]
+        public function setSelectionRangeTest():void  //KJT  test selection range and change event
+        {
+            var startIndx:int = 800;
+            var endIndx:int = 933;
+            //trace('CALL SET SELECTION');
 
-			SelManager.selectRange(startIndx,endIndx);
-			SelManager.applyLeafFormat(attributes);
+            SelManager.textFlow.addEventListener(SelectionEvent.SELECTION_CHANGE, selChange, false, 0, true);
+            SelManager.selectRange(startIndx, endIndx);
 
-			SelManager.insertText("New");
-			SelManager.flushPendingOperations();
+            assertTrue("beginning index should be 800, but is " + SelManager.anchorPosition,
+                    SelManager.anchorPosition == 800);
+            assertTrue("end index should be 933, but is " + SelManager.activePosition,
+                    SelManager.activePosition == 933);
+            assertTrue("SelectionChanged returned false", SelectionChanged == true);
+        }
 
-			var leaf:FlowLeafElement = SelManager.textFlow.findLeaf(startIndx);
-			var attributesNew:ITextLayoutFormat = leaf.format;
-			assertTrue("Invalid point format after block deletion", TextLayoutFormat.isEqual(attributes, attributesNew));
-		}
-		/**
- 		 * Select 40 characters and delete them.
- 		 */
-		public function backSpaceSelectionTest():void
-		{
-			var startIndx:int = 10;
-			var endIndx:int = 50;
+        [Test]
+        /**
+         * Select 40 characters and replaces them with new text
+         */
+        public function replaceSelectionTest():void
+        {
+            var startIndx:int = 10;
+            var endIndx:int = 50;
 
-			var attributes:TextLayoutFormat  = new TextLayoutFormat();
-			attributes.fontWeight = FontWeight.BOLD;
-			attributes.lineThrough = true;
+            var attributes:TextLayoutFormat = new TextLayoutFormat();
+            attributes.fontWeight = FontWeight.BOLD;
+            attributes.lineThrough = true;
 
-			SelManager.selectRange(startIndx,endIndx);
-			SelManager.applyLeafFormat(attributes);
+            SelManager.selectRange(startIndx, endIndx);
+            SelManager.applyLeafFormat(attributes);
 
-			var initLength:uint = SelManager.textFlow.textLength;
-			SelManager.deletePreviousCharacter();
-			var endLength:uint = SelManager.textFlow.textLength;
+            SelManager.insertText("New");
+            SelManager.flushPendingOperations();
 
-			assertTrue("deleting the selection should have removed " +(endIndx - startIndx) +
-						" characters.  It actually removed " + (initLength - endLength),
-						endLength == initLength - (endIndx - startIndx) );
+            var leaf:FlowLeafElement = SelManager.textFlow.findLeaf(startIndx);
+            var attributesNew:ITextLayoutFormat = leaf.format;
+            assertTrue("Invalid point format after block deletion", TextLayoutFormat.isEqual(attributes, attributesNew));
+        }
 
-			SelManager.insertText("New");
-			SelManager.flushPendingOperations();
+        [Test]
+        /**
+         * Select 40 characters and delete them.
+         */
+        public function backSpaceSelectionTest():void
+        {
+            var startIndx:int = 10;
+            var endIndx:int = 50;
 
-			var leaf:FlowLeafElement = SelManager.textFlow.findLeaf(startIndx);
-			var attributesNew:ITextLayoutFormat = leaf.format;
-			assertTrue("Invalid point format after block deletion", TextLayoutFormat.isEqual(attributes, attributesNew));
-		}
+            var attributes:TextLayoutFormat = new TextLayoutFormat();
+            attributes.fontWeight = FontWeight.BOLD;
+            attributes.lineThrough = true;
 
-		/**
- 		 * Set the cursor position back ten characters and delete the first ten characters.
- 		 */
-		public function backSpaceInsertionPointTest():void
-		{
-			var n:int = 10;
-			SelManager.selectRange(n,n);
+            SelManager.selectRange(startIndx, endIndx);
+            SelManager.applyLeafFormat(attributes);
 
-			var initLength:uint = SelManager.textFlow.textLength;
+            var initLength:uint = SelManager.textFlow.textLength;
+            SelManager.deletePreviousCharacter();
+            var endLength:uint = SelManager.textFlow.textLength;
 
-			for(var i:int = 0; i < n; i++){
-				SelManager.deletePreviousCharacter();
-			}
+            assertTrue("deleting the selection should have removed " + (endIndx - startIndx) +
+                    " characters.  It actually removed " + (initLength - endLength),
+                    endLength == initLength - (endIndx - startIndx));
 
-			var endLength:uint = SelManager.textFlow.textLength;
+            SelManager.insertText("New");
+            SelManager.flushPendingOperations();
 
-			assertTrue("should have removed " + n + " characters.  Actually removed " +
-						(initLength - endLength) , endLength == initLength - n);
-		}
+            var leaf:FlowLeafElement = SelManager.textFlow.findLeaf(startIndx);
+            var attributesNew:ITextLayoutFormat = leaf.format;
+            assertTrue("Invalid point format after block deletion", TextLayoutFormat.isEqual(attributes, attributesNew));
+        }
 
-		/**
- 		 * Set the cursor position back nine characters and delete the first ten characters.
- 		 * Ensure that only nine characters are deleted.
- 		 */
-		public function backSpaceLowerLimitTest():void
-		{
-			var n:int = 9;
-			SelManager.selectRange(n,n);
+        [Test]
+        /**
+         * Set the cursor position back ten characters and delete the first ten characters.
+         */
+        public function backSpaceInsertionPointTest():void
+        {
+            var n:int = 10;
+            SelManager.selectRange(n, n);
 
-			var initLength:uint = SelManager.textFlow.textLength;
+            var initLength:uint = SelManager.textFlow.textLength;
 
-			for(var i:int = 0; i <= n; i++){
-				SelManager.deletePreviousCharacter();
-			}
+            for (var i:int = 0; i < n; i++)
+            {
+                SelManager.deletePreviousCharacter();
+            }
 
-			var endLength:uint = SelManager.textFlow.textLength;
+            var endLength:uint = SelManager.textFlow.textLength;
 
-			assertTrue("should have removed " + n + " characters.  Actually removed " +
-						(initLength - endLength) , endLength == initLength - n);
-		}
+            assertTrue("should have removed " + n + " characters.  Actually removed " +
+                    (initLength - endLength), endLength == initLength - n);
+        }
 
-		/**
- 		 * Select 40 characters and delete them.
- 		 */
-		public function deleteSelectionTest():void
-		{
-			var startIndx:int = 10;
-			var endIndx:int = 50;
+        [Test]
+        /**
+         * Set the cursor position back nine characters and delete the first ten characters.
+         * Ensure that only nine characters are deleted.
+         */
+        public function backSpaceLowerLimitTest():void
+        {
+            var n:int = 9;
+            SelManager.selectRange(n, n);
 
-			SelManager.selectRange(startIndx,endIndx);
+            var initLength:uint = SelManager.textFlow.textLength;
 
-			var initLength:uint = SelManager.textFlow.textLength;
-			SelManager.deleteNextCharacter();
-			var endLength:uint = SelManager.textFlow.textLength;
+            for (var i:int = 0; i <= n; i++)
+            {
+                SelManager.deletePreviousCharacter();
+            }
 
-			assertTrue("should have removed " + (endIndx - startIndx) + " characters.  Actually removed " +
-						(initLength - endLength) , endLength == initLength - (endIndx - startIndx) );
-		}
+            var endLength:uint = SelManager.textFlow.textLength;
 
-		/**
- 		 * Delete the first ten characters.
- 		 */
-		public function deleteInsertionPointTest():void
-		{
-			var n:int = 10;
-			SelManager.selectRange(0,0);
+            assertTrue("should have removed " + n + " characters.  Actually removed " +
+                    (initLength - endLength), endLength == initLength - n);
+        }
 
-			var initLength:uint = SelManager.textFlow.textLength;
+        [Test]
+        /**
+         * Select 40 characters and delete them.
+         */
+        public function deleteSelectionTest():void
+        {
+            var startIndx:int = 10;
+            var endIndx:int = 50;
 
-			for(var i:int = 0; i < n; i++){
-				SelManager.deleteNextCharacter();
-			}
+            SelManager.selectRange(startIndx, endIndx);
 
-			var endLength:uint = SelManager.textFlow.textLength;
+            var initLength:uint = SelManager.textFlow.textLength;
+            SelManager.deleteNextCharacter();
+            var endLength:uint = SelManager.textFlow.textLength;
 
-			assertTrue("should have removed " + n + " characters.  Actually removed " +
-						(initLength - endLength), endLength == initLength - n);
-		}
+            assertTrue("should have removed " + (endIndx - startIndx) + " characters.  Actually removed " +
+                    (initLength - endLength), endLength == initLength - (endIndx - startIndx));
+        }
 
-		/**
- 		 * Set the cursor position back nine characters and delete the first ten characters.
- 		 * Ensure that only nine characters are deleted.
- 		 */
-		public function deleteUpperLimitTest():void
-		{
-			var n:int = 9;
+        [Test]
+        /**
+         * Delete the first ten characters.
+         */
+        public function deleteInsertionPointTest():void
+        {
+            var n:int = 10;
+            SelManager.selectRange(0, 0);
 
-			var initLength:uint = SelManager.textFlow.textLength;
-			SelManager.selectRange(initLength - (n+1), initLength - (n+1));
+            var initLength:uint = SelManager.textFlow.textLength;
 
-			for(var i:int = 0; i < n; i++){
-				SelManager.deleteNextCharacter();
-			}
+            for (var i:int = 0; i < n; i++)
+            {
+                SelManager.deleteNextCharacter();
+            }
 
-			var endLength:uint = SelManager.textFlow.textLength;
+            var endLength:uint = SelManager.textFlow.textLength;
 
-			assertTrue("should have removed " + n + " characters.  Actually removed " +
-						(initLength - endLength) , endLength == initLength - n);
-		}
+            assertTrue("should have removed " + n + " characters.  Actually removed " +
+                    (initLength - endLength), endLength == initLength - n);
+        }
 
-		/**
-		 * Splits the paragraph after the first fifty characters.
-		 * Verifies that there is one more line in the textFlow than it started with.
-		 * Verifies that the first leaf has only 50 characters in it.
-		 */
-		public function splitParagraphInsertionPointTest():void
-		{
-			var insertPoint:int = 50;
+        [Test]
+        /**
+         * Set the cursor position back nine characters and delete the first ten characters.
+         * Ensure that only nine characters are deleted.
+         */
+        public function deleteUpperLimitTest():void
+        {
+            var n:int = 9;
 
-			SelManager.selectRange(insertPoint, insertPoint);
+            var initLength:uint = SelManager.textFlow.textLength;
+            SelManager.selectRange(initLength - (n + 1), initLength - (n + 1));
 
-			var initLines:int = SelManager.textFlow.flowComposer.numLines;
-			SelManager.splitParagraph();
-			var endLines:int = SelManager.textFlow.flowComposer.numLines;
+            for (var i:int = 0; i < n; i++)
+            {
+                SelManager.deleteNextCharacter();
+            }
 
-			assertTrue("expected one additional line after splitting the paragraph.  Actually found " +
-						(endLines - initLines), initLines = endLines - 1);
+            var endLength:uint = SelManager.textFlow.textLength;
 
-			var lengthFirst:int = SelManager.textFlow.getFirstLeaf().textLength;
+            assertTrue("should have removed " + n + " characters.  Actually removed " +
+                    (initLength - endLength), endLength == initLength - n);
+        }
 
-			assertTrue("expected the first paragraph would have " + insertPoint +
-						" characters.  Actually found " + lengthFirst, lengthFirst = insertPoint);
-		}
+        [Test]
+        /**
+         * Splits the paragraph after the first fifty characters.
+         * Verifies that there is one more line in the textFlow than it started with.
+         * Verifies that the first leaf has only 50 characters in it.
+         */
+        public function splitParagraphInsertionPointTest():void
+        {
+            var insertPoint:int = 50;
 
-		/**
-		 * 1. Sets attributes before (A, B), after (B', C) and at (B'', D) at split point.
-		 * Splits paragraphs, adds new text and verifies that it has attributes (A, B'', C, D)
-	     * 2. Tests special case for splitting a paragraph at the end of a link; point format is reset in this case
-		 */
-		public function splitParagraphFormatTest():void
-		{
-			var insertPoint:int = 50;
+            SelManager.selectRange(insertPoint, insertPoint);
 
-			var attributes:TextLayoutFormat  = new TextLayoutFormat();
+            var initLines:int = SelManager.textFlow.flowComposer.numLines;
+            SelManager.splitParagraph();
+            var endLines:int = SelManager.textFlow.flowComposer.numLines;
 
-			attributes.fontWeight = FontWeight.BOLD;
-			attributes.lineThrough = true;
-			SelManager.selectRange(insertPoint-5, insertPoint);
-			SelManager.applyLeafFormat(attributes);
+            assertTrue("expected one additional line after splitting the paragraph.  Actually found " +
+                    (endLines - initLines), initLines = endLines - 1);
 
-			attributes.fontWeight = undefined;
-			attributes.textDecoration = flashx.textLayout.formats.TextDecoration.UNDERLINE;
-			attributes.fontSize = 72;
-			SelManager.selectRange(insertPoint, insertPoint+5);
-			SelManager.applyLeafFormat(attributes);
+            var lengthFirst:int = SelManager.textFlow.getFirstLeaf().textLength;
 
-			attributes.textDecoration = flashx.textLayout.formats.TextDecoration.UNDERLINE;
-			attributes.lineThrough = true;
-			attributes.fontFamily = "Verdana";
-			SelManager.selectRange(insertPoint, insertPoint);
-			SelManager.applyLeafFormat(attributes);
+            assertTrue("expected the first paragraph would have " + insertPoint +
+                    " characters.  Actually found " + lengthFirst, lengthFirst = insertPoint);
+        }
 
-			SelManager.splitParagraph();
+        [Test]
+        /**
+         * 1. Sets attributes before (A, B), after (B', C) and at (B'', D) at split point.
+         * Splits paragraphs, adds new text and verifies that it has attributes (A, B'', C, D)
+         * 2. Tests special case for splitting a paragraph at the end of a link; point format is reset in this case
+         */
+        public function splitParagraphFormatTest():void
+        {
+            var insertPoint:int = 50;
 
-			SelManager.insertText("New");
-			SelManager.flushPendingOperations();
+            var attributes:TextLayoutFormat = new TextLayoutFormat();
 
-			var leaf:FlowLeafElement = SelManager.textFlow.findLeaf(insertPoint+1);
-			attributes = new TextLayoutFormat(leaf.format);
+            attributes.fontWeight = FontWeight.BOLD;
+            attributes.lineThrough = true;
+            SelManager.selectRange(insertPoint - 5, insertPoint);
+            SelManager.applyLeafFormat(attributes);
 
-			assertTrue("Invalid point format for start of a new paragraph", attributes.fontWeight = FontWeight.BOLD);
-			assertTrue("Invalid point format for start of a new paragraph", attributes.fontSize = 72);
-			assertTrue("Invalid point format for start of a new paragraph", attributes.fontFamily = "Verdana");
-			assertTrue("Invalid point format for start of a new paragraph", attributes.textDecoration == flashx.textLayout.formats.TextDecoration.UNDERLINE && attributes.lineThrough);
+            attributes.fontWeight = undefined;
+            attributes.textDecoration = TextDecoration.UNDERLINE;
+            attributes.fontSize = 72;
+            SelManager.selectRange(insertPoint, insertPoint + 5);
+            SelManager.applyLeafFormat(attributes);
 
-			insertPoint = 40;
+            attributes.textDecoration = TextDecoration.UNDERLINE;
+            attributes.lineThrough = true;
+            attributes.fontFamily = "Verdana";
+            SelManager.selectRange(insertPoint, insertPoint);
+            SelManager.applyLeafFormat(attributes);
 
-			SelManager.selectRange(insertPoint-10, insertPoint);
-			SelManager.applyLink("http://www.google.com", "_self", false);
+            SelManager.splitParagraph();
 
-			SelManager.selectRange(insertPoint, insertPoint);
-			SelManager.splitParagraph();
+            SelManager.insertText("New");
+            SelManager.flushPendingOperations();
 
-			SelManager.insertText("New");
-			SelManager.flushPendingOperations();
+            var leaf:FlowLeafElement = SelManager.textFlow.findLeaf(insertPoint + 1);
+            attributes = new TextLayoutFormat(leaf.format);
 
-			leaf = SelManager.textFlow.findLeaf(insertPoint+1);
-			attributes = new TextLayoutFormat(leaf.format);
-			assertTrue("Invalid point format for start of a new paragraph after a link", TextLayoutFormat.isEqual(attributes, TextLayoutFormat.emptyTextLayoutFormat));
-		}
+            assertTrue("Invalid point format for start of a new paragraph", attributes.fontWeight = FontWeight.BOLD);
+            assertTrue("Invalid point format for start of a new paragraph", attributes.fontSize = 72);
+            assertTrue("Invalid point format for start of a new paragraph", attributes.fontFamily = "Verdana");
+            assertTrue("Invalid point format for start of a new paragraph", attributes.textDecoration == TextDecoration.UNDERLINE && attributes.lineThrough);
 
-		/**
-		 * Selects the characters between the 10th and 50th characters and splits the paragraph.
-		 * Verifies that there is one more line in the textFlow than it started with.
-		 * Verifies that the first leaf has only 10 characters in it.
-		 * Verifies that the final length has 39 less characters in it.
-		 */
-		public function splitParagraphSelectionTest():void
-		{
-			var startIndx:int = 10;
-			var endIndx:int = 50;
+            insertPoint = 40;
 
+            SelManager.selectRange(insertPoint - 10, insertPoint);
+            SelManager.applyLink("http://www.google.com", "_self", false);
 
-			SelManager.selectRange(startIndx, endIndx);
+            SelManager.selectRange(insertPoint, insertPoint);
+            SelManager.splitParagraph();
 
-			var initLength:int = SelManager.textFlow.textLength;
-			var initLines:int = SelManager.textFlow.flowComposer.numLines;
+            SelManager.insertText("New");
+            SelManager.flushPendingOperations();
 
-			SelManager.splitParagraph();
+            leaf = SelManager.textFlow.findLeaf(insertPoint + 1);
+            attributes = new TextLayoutFormat(leaf.format);
+            assertTrue("Invalid point format for start of a new paragraph after a link", TextLayoutFormat.isEqual(attributes, TextLayoutFormat.emptyTextLayoutFormat));
+        }
 
-			var endLength:int = SelManager.textFlow.textLength;
-			var endLines:int = SelManager.textFlow.flowComposer.numLines;
+        [Test]
+        /**
+         * Selects the characters between the 10th and 50th characters and splits the paragraph.
+         * Verifies that there is one more line in the textFlow than it started with.
+         * Verifies that the first leaf has only 10 characters in it.
+         * Verifies that the final length has 39 less characters in it.
+         */
+        public function splitParagraphSelectionTest():void
+        {
+            var startIndx:int = 10;
+            var endIndx:int = 50;
 
-			assertTrue("expected one additional line after splitting the paragraph.  Actually found " +
-						(endLines - initLines), initLines = endLines - 1);
 
-			var lengthFirst:int = SelManager.textFlow.getFirstLeaf().textLength;
+            SelManager.selectRange(startIndx, endIndx);
 
-			assertTrue("expected the first paragraph would have " + startIndx +
-						" characters.  Actually found " + lengthFirst, lengthFirst = startIndx);
-			assertTrue("expected the entire flow would have " + (initLength - (endIndx - startIndx) + 1) +
-						" characters.  Actually found " + endLength,
-						endLength == initLength - (endIndx - startIndx) + 1);
-		}
+            var initLength:int = SelManager.textFlow.textLength;
+            var initLines:int = SelManager.textFlow.flowComposer.numLines;
 
-		/**
-		 * Creates a selection area of six characters at the last index of the flow root
-		 * then inserts " BOOGA" into the selection area and verifies the length of the
-		 * flow root has increased by 6.
-		 */
-		public function insertTextTest():void //KJT
-		{
-			var textLength:uint = SelManager.textFlow.textLength;
-			SelManager.selectRange(textLength - 1, textLength + 5);
+            SelManager.splitParagraph();
 
-			SelManager.insertText(" BOOGA");
-			SelManager.selectRange(textLength - 1,textLength + 5);
+            var endLength:int = SelManager.textFlow.textLength;
+            var endLines:int = SelManager.textFlow.flowComposer.numLines;
 
-		 	assertTrue("expected to find " + (textLength + 6) + " characters.  Actually found " +
-		 				SelManager.textFlow.textLength, SelManager.textFlow.textLength == textLength + 6);
-		}
+            assertTrue("expected one additional line after splitting the paragraph.  Actually found " +
+                    (endLines - initLines), initLines = endLines - 1);
 
-		/**
-		 * Sets the insertion point at 50, then generates the "0" keyboard event
-		 * and verifies that the selBegIdx is 49.
-		 */
-		public function arrowLeft():void
-		{
-			var event:KeyboardEvent = new KeyboardEvent(KeyboardEvent.KEY_UP, true, false, 0, Keyboard.LEFT);
-			SelManager.selectRange(50,50);
-			SelManager.keyDownHandler(event);
+            var lengthFirst:int = SelManager.textFlow.getFirstLeaf().textLength;
 
-			if(SelManager.textFlow.computedFormat.blockProgression == BlockProgression.RL)
-			{
-//				assertTrue("expected insertion point at position 87. Actually found + " +
-//	    				SelManager.anchorPosition, SelManager.anchorPosition == 87);
-			}
-			else
-	    		{
-	    			if(SelManager.textFlow.computedFormat.direction == Direction.LTR)
-	    			{
-	    				assertTrue("expected insertion point at position 49. Actually found + " +
-	    				SelManager.activePosition, SelManager.activePosition == 49);
-	    			}
-	    			else
-	    			{
-	    				assertTrue("expected insertion point at position 51. Actually found + " +
-	    				SelManager.activePosition, SelManager.activePosition == 51);
-	    			}
-	    		}
-		}
+            assertTrue("expected the first paragraph would have " + startIndx +
+                    " characters.  Actually found " + lengthFirst, lengthFirst = startIndx);
+            assertTrue("expected the entire flow would have " + (initLength - (endIndx - startIndx) + 1) +
+                    " characters.  Actually found " + endLength,
+                    endLength == initLength - (endIndx - startIndx) + 1);
+        }
 
-		/**
-		 * Sets the insertion point at 50, then generates the "0" keyboard event
-		 * and verifies that the selBegIdx is 51.
-		 */
-		public function arrowRight():void
-		{
-			var event:KeyboardEvent = new KeyboardEvent(KeyboardEvent.KEY_UP, true, false, 0, Keyboard.RIGHT);
-			SelManager.selectRange(50,50);
-			SelManager.keyDownHandler(event);
-			if(SelManager.textFlow.computedFormat.blockProgression == BlockProgression.RL)
-			{
-//				assertTrue("expected insertion point at position 11. Actually found + " +
-//	    				SelManager.anchorPosition, SelManager.anchorPosition == 11);
-			}
-			else
-    		{
-    			if(SelManager.textFlow.computedFormat.direction == Direction.LTR)
-    			{
-	    			assertTrue("expected insertion point at position 51. Actually found " +
-	    				SelManager.activePosition, SelManager.activePosition == 51);
-    			}
-    			else
-    			{
-    				assertTrue("expected insertion point at position 49. Actually found " +
-	    				SelManager.activePosition, SelManager.activePosition == 49);
-    			}
-    		}
-		}
+        [Test]
+        /**
+         * Creates a selection area of six characters at the last index of the flow root
+         * then inserts " BOOGA" into the selection area and verifies the length of the
+         * flow root has increased by 6.
+         */
+        public function insertTextTest():void //KJT
+        {
+            var textLength:uint = SelManager.textFlow.textLength;
+            SelManager.selectRange(textLength - 1, textLength + 5);
 
-		/**
-		 * Sets the insertion point at 0, then generates the "40" keyboard event
-		 * and verifies that the cursor is on the second line.
-		 */
-		public function arrowDown():void
-		{
-			var event:KeyboardEvent = new KeyboardEvent(KeyboardEvent.KEY_UP, true, false,40);
-			SelManager.selectRange(0,0);
-			SelManager.keyDownHandler(event);
-			if(SelManager.textFlow.computedFormat.blockProgression == BlockProgression.TB)
-			{
-				//NYI
-			}
-			else
-    		{
-    			var ap:int = SelManager.activePosition;
-    			var index:int = SelManager.textFlow.findChildIndexAtPosition(ap);
-    			assertTrue("expected index at 2. Actually found " + index, index == 2);
-    		}
-		}
+            SelManager.insertText(" BOOGA");
+            SelManager.selectRange(textLength - 1, textLength + 5);
 
-		/**
-		 * Sets the insertion point at the last char, then generates the "38" keyboard event
-		 * and verifies that the cursor is on the second to last line.
-		 */
-		public function arrowUp():void
-		{
-			var event:KeyboardEvent = new KeyboardEvent(KeyboardEvent.KEY_UP, true, false,38);
-			var lastChar:int = SelManager.absoluteEnd;
-			var lastLine:int = SelManager.textFlow.findChildIndexAtPosition(lastChar);
-			SelManager.selectRange(lastChar,lastChar);
-			SelManager.keyDownHandler(event);
-			if(SelManager.textFlow.computedFormat.blockProgression == BlockProgression.TB)
-			{
-				//NYI
-			}
-			else
-    		{
-    			var index:int = SelManager.textFlow.findChildIndexAtPosition(SelManager.activePosition);
-    			assertTrue("expected index at " + (lastChar - 1) +
-    						". Actually found " + index,
-    						index == (lastChar - 1)
-    			);
-    		}
-		}
+            assertTrue("expected to find " + (textLength + 6) + " characters.  Actually found " +
+                    SelManager.textFlow.textLength, SelManager.textFlow.textLength == textLength + 6);
+        }
 
-		/**
- 		 * Tests the undo and redo stacks by applying typeface changes by undoing
- 		 * and redoing them.
- 		 */
-		public function unDoOp():void  //KJT
-		{
-			var ca:TextLayoutFormat = new TextLayoutFormat();
-			ca.fontWeight = FontWeight.BOLD;
-			SelManager.applyLeafFormat(ca);
+        [Test]
+        /**
+         * Sets the insertion point at 50, then generates the "0" keyboard event
+         * and verifies that the selBegIdx is 49.
+         */
+        public function arrowLeft():void
+        {
+            var event:KeyboardEvent = new KeyboardEvent(KeyboardEvent.KEY_UP, true, false, 0, Keyboard.LEFT);
+            SelManager.selectRange(50, 50);
+            SelManager.keyDownHandler(event);
 
-			SelManager.undo();
-			Redo();
+            if (SelManager.textFlow.computedFormat.blockProgression == BlockProgression.RL)
+            {
+                //				assertTrue("expected insertion point at position 87. Actually found + " +
+                //	    				SelManager.anchorPosition, SelManager.anchorPosition == 87);
+            }
+            else
+            {
+                if (SelManager.textFlow.computedFormat.direction == Direction.LTR)
+                {
+                    assertTrue("expected insertion point at position 49. Actually found + " +
+                            SelManager.activePosition, SelManager.activePosition == 49);
+                }
+                else
+                {
+                    assertTrue("expected insertion point at position 51. Actually found + " +
+                            SelManager.activePosition, SelManager.activePosition == 51);
+                }
+            }
+        }
 
-			ca.fontStyle = FontPosture.ITALIC;
-			SelManager.applyLeafFormat(ca);
+        [Test]
+        /**
+         * Sets the insertion point at 50, then generates the "0" keyboard event
+         * and verifies that the selBegIdx is 51.
+         */
+        public function arrowRight():void
+        {
+            var event:KeyboardEvent = new KeyboardEvent(KeyboardEvent.KEY_UP, true, false, 0, Keyboard.RIGHT);
+            SelManager.selectRange(50, 50);
+            SelManager.keyDownHandler(event);
+            if (SelManager.textFlow.computedFormat.blockProgression == BlockProgression.RL)
+            {
+                //				assertTrue("expected insertion point at position 11. Actually found + " +
+                //	    				SelManager.anchorPosition, SelManager.anchorPosition == 11);
+            }
+            else
+            {
+                if (SelManager.textFlow.computedFormat.direction == Direction.LTR)
+                {
+                    assertTrue("expected insertion point at position 51. Actually found " +
+                            SelManager.activePosition, SelManager.activePosition == 51);
+                }
+                else
+                {
+                    assertTrue("expected insertion point at position 49. Actually found " +
+                            SelManager.activePosition, SelManager.activePosition == 49);
+                }
+            }
+        }
 
-			SelManager.undo();
-			SelManager.undo();
-		}
+        [Test]
+        /**
+         * Sets the insertion point at 0, then generates the "40" keyboard event
+         * and verifies that the cursor is on the second line.
+         */
+        public function arrowDown():void
+        {
+            var event:KeyboardEvent = new KeyboardEvent(KeyboardEvent.KEY_UP, true, false, 40);
+            SelManager.selectRange(0, 0);
+            SelManager.keyDownHandler(event);
+            if (SelManager.textFlow.computedFormat.blockProgression == BlockProgression.TB)
+            {
+                //NYI
+            }
+            else
+            {
+                var ap:int = SelManager.activePosition;
+                var index:int = SelManager.textFlow.findChildIndexAtPosition(ap);
+                assertTrue("expected index at 2. Actually found " + index, index == 2);
+            }
+        }
 
-		/**
-		 * Performs successive backspaces and one undo to see if all the deleted content
-		 * is returned, then performs a redo to see if the content is correctly removed
-		 * again.
-		 */
-		public function joinedBackspaceUndoTest():void
-		{
-			var n:int = 10;
-			SelManager.selectRange(10,10);
+        [Test]
+        /**
+         * Sets the insertion point at the last char, then generates the "38" keyboard event
+         * and verifies that the cursor is on the second to last line.
+         */
+        public function arrowUp():void
+        {
+            var event:KeyboardEvent = new KeyboardEvent(KeyboardEvent.KEY_UP, true, false, 38);
+            var lastChar:int = SelManager.absoluteEnd;
+            var lastLine:int = SelManager.textFlow.findChildIndexAtPosition(lastChar);
+            SelManager.selectRange(lastChar, lastChar);
+            SelManager.keyDownHandler(event);
+            if (SelManager.textFlow.computedFormat.blockProgression == BlockProgression.TB)
+            {
+                //NYI
+            }
+            else
+            {
+                var index:int = SelManager.textFlow.findChildIndexAtPosition(SelManager.activePosition);
+                assertTrue("expected index at " + (lastChar - 1) +
+                        ". Actually found " + index,
+                        index == (lastChar - 1)
+                );
+            }
+        }
 
-			var initLength:uint = SelManager.textFlow.textLength;
+        [Test]
+        /**
+         * Tests the undo and redo stacks by applying typeface changes by undoing
+         * and redoing them.
+         */
+        public function unDoOp():void  //KJT
+        {
+            var ca:TextLayoutFormat = new TextLayoutFormat();
+            ca.fontWeight = FontWeight.BOLD;
+            SelManager.applyLeafFormat(ca);
 
-			for(var i:int = 0; i < n; i++){
-				var event:KeyboardEvent = new KeyboardEvent(KeyboardEvent.KEY_DOWN, true, false, 8);
-				dispatchEvent(event);
-			}
+            SelManager.undo();
+            Redo();
 
-			var endLength:uint = SelManager.textFlow.textLength;
+            ca.fontStyle = FontPosture.ITALIC;
+            SelManager.applyLeafFormat(ca);
 
-			SelManager.undo();
+            SelManager.undo();
+            SelManager.undo();
+        }
 
-			var undoLength:uint = SelManager.textFlow.textLength;
+        [Test]
+        /**
+         * Performs successive backspaces and one undo to see if all the deleted content
+         * is returned, then performs a redo to see if the content is correctly removed
+         * again.
+         */
+        public function joinedBackspaceUndoTest():void
+        {
+            var n:int = 10;
+            SelManager.selectRange(10, 10);
 
-			assertTrue("expected text length before undo to be " + n + " less.  Was actually " +
-						(endLength - initLength) + " less.", endLength == initLength - n );
-			assertTrue("expected text length after undo to be identical to the start, but it was off by " +
-						(undoLength-initLength), undoLength == initLength);
+            var initLength:uint = SelManager.textFlow.textLength;
 
-			Redo();
+            for (var i:int = 0; i < n; i++)
+            {
+                var event:KeyboardEvent = new KeyboardEvent(KeyboardEvent.KEY_DOWN, true, false, 8);
+                dispatchEvent(event);
+            }
 
-			var redoLength:uint = SelManager.textFlow.textLength;
+            var endLength:uint = SelManager.textFlow.textLength;
 
-			assertTrue("expected redo length to equal undo length, but found " +
-						redoLength + " and " + endLength, redoLength == endLength);
-		}
+            SelManager.undo();
 
-		/**
-		 * Performs successive deletes and one undo to see if all the deleted content
-		 * is returned, then performs a redo to see if the content is correctly removed
-		 * again.
-		 */
-		public function joinedDeleteUndoTest():void
-		{
-			var n:int = 10;
-			SelManager.selectRange(10,10);
+            var undoLength:uint = SelManager.textFlow.textLength;
 
-			var initLength:uint = SelManager.textFlow.textLength;
+            assertTrue("expected text length before undo to be " + n + " less.  Was actually " +
+                    (endLength - initLength) + " less.", endLength == initLength - n);
+            assertTrue("expected text length after undo to be identical to the start, but it was off by " +
+                    (undoLength - initLength), undoLength == initLength);
 
-			for(var i:int = 0; i < n; i++){
-				var event:KeyboardEvent = new KeyboardEvent(KeyboardEvent.KEY_DOWN, true, false, 127, Keyboard.DELETE);
-				dispatchEvent(event);
-			}
-			SelManager.flushPendingOperations();
+            Redo();
 
-			var endLength:uint = SelManager.textFlow.textLength;
+            var redoLength:uint = SelManager.textFlow.textLength;
 
-			SelManager.undo();
+            assertTrue("expected redo length to equal undo length, but found " +
+                    redoLength + " and " + endLength, redoLength == endLength);
+        }
 
-			var undoLength:uint = SelManager.textFlow.textLength;
+        [Test]
+        /**
+         * Performs successive deletes and one undo to see if all the deleted content
+         * is returned, then performs a redo to see if the content is correctly removed
+         * again.
+         */
+        public function joinedDeleteUndoTest():void
+        {
+            var n:int = 10;
+            SelManager.selectRange(10, 10);
 
-			assertTrue("expected text length before undo to be " + n + " less.  Was actually " +
-						(endLength - initLength) + " less.", endLength == initLength - n );
-			assertTrue("expected text length after undo to be identical to the start, but it was off by " +
-						(undoLength-initLength), undoLength == initLength);
+            var initLength:uint = SelManager.textFlow.textLength;
 
-			Redo();
+            for (var i:int = 0; i < n; i++)
+            {
+                var event:KeyboardEvent = new KeyboardEvent(KeyboardEvent.KEY_DOWN, true, false, 127, Keyboard.DELETE);
+                dispatchEvent(event);
+            }
+            SelManager.flushPendingOperations();
 
-			var redoLength:uint = SelManager.textFlow.textLength;
+            var endLength:uint = SelManager.textFlow.textLength;
 
-			assertTrue("expected redo length to equal undo length, but found " +
-						redoLength + " and " + endLength, redoLength == endLength);
-		}
+            SelManager.undo();
 
-		/**
-		 * Places a series of letter a's in and does one undo to see if all the a's
-		 * are removed, then performs a redo to see if they're returned.
-		 */
-		public function joinedInsertUndoTest():void
-		{
-			var n:int = 10;
-			SelManager.selectRange(10,10);
+            var undoLength:uint = SelManager.textFlow.textLength;
+
+            assertTrue("expected text length before undo to be " + n + " less.  Was actually " +
+                    (endLength - initLength) + " less.", endLength == initLength - n);
+            assertTrue("expected text length after undo to be identical to the start, but it was off by " +
+                    (undoLength - initLength), undoLength == initLength);
+
+            Redo();
+
+            var redoLength:uint = SelManager.textFlow.textLength;
+
+            assertTrue("expected redo length to equal undo length, but found " +
+                    redoLength + " and " + endLength, redoLength == endLength);
+        }
+
+        [Test]
+        /**
+         * Places a series of letter a's in and does one undo to see if all the a's
+         * are removed, then performs a redo to see if they're returned.
+         */
+        public function joinedInsertUndoTest():void
+        {
+            var n:int = 10;
+            SelManager.selectRange(10, 10);
+
+            var initLength:uint = SelManager.textFlow.textLength;
+
+            for (var i:int = 0; i < n; i++)
+            {
+                var event:TextEvent = new TextEvent(TextEvent.TEXT_INPUT, false, false, "a");
+                dispatchEvent(event);
+            }
+
+            SelManager.flushPendingOperations();
+
+            var endLength:uint = SelManager.textFlow.textLength;
+
+            SelManager.undo();
+
+            var undoLength:uint = SelManager.textFlow.textLength;
+
+            assertTrue("expected text length before undo to be " + n + " more.  Was actually " +
+                    (endLength - initLength) + " less.", endLength == initLength + n);
+            assertTrue("expected text length after undo to be identical to the start, but it was off by " +
+                    (undoLength - initLength), undoLength == initLength);
+            Redo();
+
+            var redoLength:uint = SelManager.textFlow.textLength;
+
+            assertTrue("expected redo length to equal undo length, but found " +
+                    redoLength + " and " + endLength, redoLength == endLength);
+        }
+
+        [Test]
+        /**
+         * Performs successive enters and one undo to see if all paragraph splits are
+         * undone, then performs a redo to see if they're all redone.
+         */
+        public function joinedSplitParagraphUndoTest():void
+        {
+            var n:int = 10;
+            SelManager.selectRange(10, 10);
+
+            var initLength:uint = SelManager.textFlow.textLength;
+
+            for (var i:int = 0; i < n; i++)
+            {
+                var event:KeyboardEvent = new KeyboardEvent(KeyboardEvent.KEY_DOWN, true, false, 13);
+                dispatchEvent(event);
+            }
+
+            var endLength:uint = SelManager.textFlow.textLength;
+
+            SelManager.undo();
+
+            var undoLength:uint = SelManager.textFlow.textLength;
+
+            assertTrue("expected text length before undo to be " + n + " more.  Was actually " +
+                    (endLength - initLength) + " less.", endLength == initLength + n);
+            assertTrue("expected text length after undo to be identical to the start, but it was off by " +
+                    (undoLength - initLength), undoLength == initLength);
+
+            Redo();
+
+            var redoLength:uint = SelManager.textFlow.textLength;
+
+            assertTrue("expected redo length to equal undo length, but found " +
+                    redoLength + " and " + endLength, redoLength == endLength);
+        }
+
+        [Test]
+        /**
+         * Create a new undo manager with an undo limit of ten, then perform eleven
+         * undoable operations and see how many times it will let you undo.
+         */
+        public function undoLimitTest():void
+        {
+            var undo:UndoManager = new UndoManager();
+            var n:int = 10;
+            undo.undoAndRedoItemLimit = n;
+
+            var newSM:EditManager = new EditManager(undo);
+            SelManager = newSM;
+            TestFrame.rootElement.getTextFlow().interactionManager = newSM;
+
+            //SelManager.selectRange(n,n);
+
+            for (var i:int = 0; i < n + 1; i++)
+            {
+                SelManager.selectRange(n, n + i);
+                var event:KeyboardEvent = (i % 2 == 0) ?
+                        new KeyboardEvent(KeyboardEvent.KEY_DOWN, true, false, 13) :
+                        new KeyboardEvent(KeyboardEvent.KEY_DOWN, true, false, 8);
+                dispatchEvent(event);
+                SelManager.selectRange(-1, -1);
+            }
+
+            var u:int = 0;
+            while (undo.canUndo())
+            {
+                SelManager.undo();
+                u++;
+            }
+
+            assertTrue("expected only " + n + " undos but found " + u, u == n);
+        }
+
+        [Test]
+        public function undoRedoStackTest():void
+        {
+            var undo:UndoManager = new UndoManager();
+            var n:int = 10;
+            undo.undoAndRedoItemLimit = n;
+
+            var newSM:EditManager = new EditManager(undo);
+            SelManager = newSM;
+            TestFrame.rootElement.getTextFlow().interactionManager = newSM;
+
+            //do n operations
+            for (var i:int = 0; i < n + 1; i++)
+            {
+                SelManager.selectRange(n, n + i);
+                var event:KeyboardEvent = (i % 2 == 0) ?
+                        new KeyboardEvent(KeyboardEvent.KEY_DOWN, true, false, 13) :
+                        new KeyboardEvent(KeyboardEvent.KEY_DOWN, true, false, 8);
+                dispatchEvent(event);
+                SelManager.selectRange(-1, -1);
+            }
+            var testManager:TestEditManager = new TestEditManager(undo);
+            var stackItemNum:int = testManager.UndoRedoEntireStack(undo);
+
+            assertTrue("expected only " + n + " undos but found " + stackItemNum, stackItemNum == n);
+        }
+
+        [Test]
+        /**
+         * Select a section of text that spans paragraphs then delete it and see if the
+         * size of the flow goes down by the appropriate amount.
+         */
+        public function transParagraphDeleteTest():void
+        {
+            var startLength:int = TestFrame.rootElement.textLength;
+
+            var flow1:FlowElement;
+            var flow2:FlowElement;
+
+            var start:int = 0;
+            var finish:int = 0;
+
+            var origParas:int = TestFrame.rootElement.numChildren;
 
-			var initLength:uint = SelManager.textFlow.textLength;
+            //Look for two back to back paragraphs.
+            for (var i:int = 0; i < TestFrame.rootElement.numChildren - 1; i++)
+            {
+                flow1 = TestFrame.rootElement.getChildAt(i);
+                flow2 = TestFrame.rootElement.getChildAt(i + 1);
 
-			for(var i:int = 0; i < n; i++){
-				var event:TextEvent = new TextEvent(TextEvent.TEXT_INPUT,false,false,"a");
-				dispatchEvent(event);
-			}
+                if (flow1 is ParagraphElement && flow2 is ParagraphElement)
+                {
+                    finish = start + flow1.textLength + flow2.textLength / 2;
+                    start = start + flow1.textLength / 2;
+                    break;
+                } else
+                {
+                    start = start + flow1.textLength;
+                }
+            }
 
-			SelManager.flushPendingOperations();
+            assertTrue("expected finish to be in the middle of the second para, but it's still 0", finish != 0);
 
-			var endLength:uint = SelManager.textFlow.textLength;
+            var para1:ParagraphElement = flow1 as ParagraphElement;
+            var para2:ParagraphElement = flow2 as ParagraphElement;
 
-			SelManager.undo();
+            var attrib1:ITextLayoutFormat = para1.computedFormat;
+            var pa:TextLayoutFormat = new TextLayoutFormat();
+            if (attrib1.textAlign == TextAlign.CENTER)
+                pa.textAlign = TextAlign.LEFT;
+            else
+                pa.textAlign = TextAlign.CENTER;
 
-			var undoLength:uint = SelManager.textFlow.textLength;
 
-			assertTrue("expected text length before undo to be " + n + " more.  Was actually " +
-						(endLength - initLength) + " less.", endLength == initLength + n );
-			assertTrue("expected text length after undo to be identical to the start, but it was off by " +
-						(undoLength-initLength), undoLength == initLength);
-			Redo();
+            SelManager.selectRange(para2.getAbsoluteStart(), para2.getAbsoluteStart() + 1);
 
-			var redoLength:uint = SelManager.textFlow.textLength;
+            SelManager.applyParagraphFormat(pa);
 
-			assertTrue("expected redo length to equal undo length, but found " +
-						redoLength + " and " + endLength, redoLength == endLength);
-		}
+            var attrib2:ITextLayoutFormat = para2.computedFormat;
+            assertTrue("para1 and para2 paraAttrs must be different for this test to work!",
+                    !TextLayoutFormat.isEqual(attrib1, attrib2)
+            );
 
-		/**
-		 * Performs successive enters and one undo to see if all paragraph splits are
-		 * undone, then performs a redo to see if they're all redone.
-		 */
-		public function joinedSplitParagraphUndoTest():void
-		{
-			var n:int = 10;
-			SelManager.selectRange(10,10);
+            SelManager.selectRange(start, finish);
+            SelManager.deleteNextCharacter();
+            var finishLength:int = TestFrame.rootElement.textLength;
 
-			var initLength:uint = SelManager.textFlow.textLength;
+            assertTrue("expected " + (finish - start) + " less characters but found " +
+                    (startLength - finishLength) + " less", startLength - finishLength == finish - start);
 
-			for(var i:int = 0; i < n; i++){
-				var event:KeyboardEvent = new KeyboardEvent(KeyboardEvent.KEY_DOWN, true, false, 13);
-				dispatchEvent(event);
-			}
+            /*
+             * TODO: this tests current behavior. Proper behavior would be only one
+             * remaining paragraph.
+             */
 
-			var endLength:uint = SelManager.textFlow.textLength;
+            assertTrue("number of paragraphs should have decreased!", origParas > TestFrame.rootElement.numChildren);
 
-			SelManager.undo();
+            var finalPara:ParagraphElement = TestFrame.rootElement.getChildAt(i) as ParagraphElement;
+            var finalAttrs:ITextLayoutFormat = finalPara.computedFormat;
 
-			var undoLength:uint = SelManager.textFlow.textLength;
+            assertTrue("paragraph attributes changed and should be the same!", TextLayoutFormat.isEqual(attrib1, finalAttrs));
+        }
 
-			assertTrue("expected text length before undo to be " + n + " more.  Was actually " +
-						(endLength - initLength) + " less.", endLength == initLength + n );
-			assertTrue("expected text length after undo to be identical to the start, but it was off by " +
-						(undoLength-initLength), undoLength == initLength);
+        [Test]
+        /**
+         * Create an empty paragraph and select the 0 position in it.
+         * Then delete all the content on the flow and see if the position selected is 0.
+         */
+        public function emptyParagraphTest():void
+        {
+            SelManager.selectRange(0, 0);
 
-			Redo();
+            var returnevent:KeyboardEvent =
+                    new KeyboardEvent(KeyboardEvent.KEY_DOWN, true, false, 13);
+            dispatchEvent(returnevent);
 
-			var redoLength:uint = SelManager.textFlow.textLength;
+            SelManager.selectRange(0, 0);
+            assertTrue("did not start with selection at 0,0", SelManager.anchorPosition == 0 && SelManager.activePosition == 0);
+            SelManager.selectAll();
+            SelManager.deleteNextCharacter();
+            assertTrue("did not end with selection at 0,0 after delete all", SelManager.anchorPosition == 0 && SelManager.activePosition == 0);
+        }
 
-			assertTrue("expected redo length to equal undo length, but found " +
-						redoLength + " and " + endLength, redoLength == endLength);
-		}
+        [Test]
+        public function splitUTF16Test():void
+        {
+            // remove all text
+            SelManager.selectAll();
+            SelManager.deleteNextCharacter();
 
-		/**
-		 * Create a new undo manager with an undo limit of ten, then perform eleven
-		 * undoable operations and see how many times it will let you undo.
-		 */
-		public function undoLimitTest():void
-		{
-			var undo:UndoManager = new UndoManager();
-			var n:int = 10;
-			undo.undoAndRedoItemLimit = n;
+            var a:uint = 0xD866;
+            var b:uint = 0xDDC1;
+            var c:uint = 0xD869;
+            var d:uint = 0xDED6;
+            var e:uint = 0xD8BF;
+            var f:uint = 0xDFFD;
 
-			var newSM:EditManager = new EditManager(undo);
-			SelManager = newSM;
-			TestFrame.rootElement.getTextFlow().interactionManager = newSM;
+            var y:String = String.fromCharCode(a, b, c, d, e, f);
+            SelManager.insertText(y);
+            SelManager.flushPendingOperations();
 
-			//SelManager.selectRange(n,n);
+            var begin:int = 0;
+            var end:int = SelManager.textFlow.textLength;
+            var middle:int = ((end - 1) - begin) / 2;
+            SelManager.selectRange(middle, middle);
 
-			for(var i:int = 0; i < n + 1; i++){
-				SelManager.selectRange(n,n+i);
-				var event:KeyboardEvent = (i % 2 == 0) ?
-					new KeyboardEvent(KeyboardEvent.KEY_DOWN, true, false, 13):
-					new KeyboardEvent(KeyboardEvent.KEY_DOWN, true, false, 8);
-				dispatchEvent(event);
-				SelManager.selectRange(-1,-1);
-			}
+            var gotRangeError:Boolean = false;
+            try
+            {
+                SelManager.splitParagraph();
+                SelManager.flushPendingOperations();
+            }
+            catch (e:RangeError)
+            {
+                gotRangeError = true;
+            }
+            /* See bug #1798067 */
+            assertTrue("Spliting a surrogate pair did not throw an error", gotRangeError);
 
-			var u:int = 0;
-			while(undo.canUndo()){
-				SelManager.undo();
-				u++;
-			}
+            SelManager.selectAll();
 
-			assertTrue("expected only " + n + " undos but found " + u, u == n);
-		}
-		
-		
-		public function undoRedoStackTest():void
-		{
-			var undo:UndoManager = new UndoManager();
-			var n:int = 10;
-			undo.undoAndRedoItemLimit = n;
-			
-			var newSM:EditManager = new EditManager(undo);
-			SelManager = newSM;
-			TestFrame.rootElement.getTextFlow().interactionManager = newSM;
-			
-			//do n operations
-			for(var i:int = 0; i < n + 1; i++){
-				SelManager.selectRange(n,n+i);
-				var event:KeyboardEvent = (i % 2 == 0) ?
-					new KeyboardEvent(KeyboardEvent.KEY_DOWN, true, false, 13):
-					new KeyboardEvent(KeyboardEvent.KEY_DOWN, true, false, 8);
-				dispatchEvent(event);
-				SelManager.selectRange(-1,-1);
-			}
-			var testManager:TestEditManager = new TestEditManager(undo);
-			var stackItemNum:int = testManager.UndoRedoEntireStack(undo);
+            var charAttr:TextLayoutFormat = new TextLayoutFormat();
+            charAttr.fontFamily = "Adobe Song Std L";
 
-			assertTrue("expected only " + n + " undos but found " + stackItemNum, stackItemNum == n);
-		}
+            SelManager.applyLeafFormat(charAttr);
+            SelManager.flushPendingOperations();
 
-		/**
-		 * Select a section of text that spans paragraphs then delete it and see if the
-		 * size of the flow goes down by the appropriate amount.
-		 */
-		public function transParagraphDeleteTest():void
-		{
-			var startLength:int = TestFrame.rootElement.textLength;
+            //trace(begin + ", " + middle + ", " + end);
+        }
 
-			var flow1:FlowElement;
-			var flow2:FlowElement;
+        [Test]
+        public function splitUTF32Test():void
+        {
+            // remove all text
+            SelManager.selectAll();
+            SelManager.deleteNextCharacter();
 
-			var start:int = 0;
-			var finish:int = 0;
+            var y:String = String.fromCharCode(0x00028023);
+            y = y + y + y;
 
-			var origParas:int = TestFrame.rootElement.numChildren;
+            SelManager.insertText(y);
+            SelManager.flushPendingOperations();
 
-			//Look for two back to back paragraphs.
-			for(var i:int = 0; i < TestFrame.rootElement.numChildren-1; i++){
-				flow1 = TestFrame.rootElement.getChildAt(i);
-				flow2 = TestFrame.rootElement.getChildAt(i+1);
+            var begin:int = 0;
+            var end:int = SelManager.textFlow.textLength;
+            var middle:int = ((end - 1) - begin) / 2;
+            SelManager.selectRange(middle, middle);
 
-				if(flow1 is ParagraphElement && flow2 is ParagraphElement){
-					finish = start + flow1.textLength + flow2.textLength/2;
-					start = start + flow1.textLength/2;
-					break;
-				}else{
-					start = start + flow1.textLength;
-				}
-			}
+            SelManager.splitParagraph();
+            SelManager.flushPendingOperations();
 
-			assertTrue("expected finish to be in the middle of the second para, but it's still 0", finish != 0);
+            SelManager.selectAll();
 
-			var para1:ParagraphElement = flow1 as ParagraphElement;
-			var para2:ParagraphElement = flow2 as ParagraphElement;
+            var charAttr:TextLayoutFormat = new TextLayoutFormat();
+            charAttr.fontFamily = "Adobe Song Std L";
 
-			var attrib1:ITextLayoutFormat = para1.computedFormat;
-			var pa:TextLayoutFormat = new TextLayoutFormat();
-			if(attrib1.textAlign == TextAlign.CENTER)
-				pa.textAlign = TextAlign.LEFT;
-			else
-				pa.textAlign = TextAlign.CENTER;
+            SelManager.applyLeafFormat(charAttr);
+            SelManager.flushPendingOperations();
 
+            //trace(begin + ", " + middle + ", " + end);
+        }
 
-			SelManager.selectRange(para2.getAbsoluteStart(),para2.getAbsoluteStart() + 1);
+        [Test]
+        /**
+         * Performs an operation, clear the selection manager and then make sure the operation doesn't undo
+         */
+        public function undoWithModelChangeTest():void
+        {
+            var tf:TextFlow = SelManager.textFlow;
+            var selManager:EditManager = SelManager;
 
-			SelManager.applyParagraphFormat(pa);
+            selManager.selectAll();
 
-			var attrib2:ITextLayoutFormat = para2.computedFormat;
-			assertTrue("para1 and para2 paraAttrs must be different for this test to work!",
-				!TextLayoutFormat.isEqual(attrib1,attrib2)
-			);
+            var initLength:uint = SelManager.textFlow.textLength;
 
-			SelManager.selectRange(start,finish);
-			SelManager.deleteNextCharacter();
-			var finishLength:int = TestFrame.rootElement.textLength;
 
-			assertTrue("expected " + (finish-start) + " less characters but found " +
-						(startLength - finishLength) + " less", startLength - finishLength == finish - start);
+            flowOp = null;
+            tf.addEventListener(FlowOperationEvent.FLOW_OPERATION_BEGIN, listenForOpBegin, false, 0, true);
 
-			/*
-			 * TODO: this tests current behavior. Proper behavior would be only one
-			 * remaining paragraph.
-			 */
+            // now do an operation
+            var ca:TextLayoutFormat = new TextLayoutFormat();
+            ca.color = 0xff;
+            selManager.applyFormatToElement(tf, ca);
 
-			assertTrue("number of paragraphs should have decreased!", origParas > TestFrame.rootElement.numChildren);
+            assertTrue("no begin operation event", flowOp != null);
+            assertTrue("textFlow characterFormat.color should be 0xff", tf.format && tf.format.color == 0xff);
 
-			var finalPara:ParagraphElement = TestFrame.rootElement.getChildAt(i) as ParagraphElement;
-			var finalAttrs:ITextLayoutFormat = finalPara.computedFormat;
+            // clear the selection manager
+            tf.interactionManager = null;
+            // now I've got a hold of the operation.  do an out of bounds model modification and then attempt an undo
+            tf.color = 0xff00;
+            assertTrue("textFlow characterFormat.color should be 0xff", tf.format.color == 0xff00);
 
-			assertTrue("paragraph attributes changed and should be the same!",TextLayoutFormat.isEqual(attrib1,finalAttrs));
-		}
+            // now restore the interactionManager
+            tf.interactionManager = selManager;
+            // CONFIG::debug { trace("GeneralFunctionsTest.undoWithModelChangeTest: expect to see message regarding skipping undo due to mismatched generation numbers."); }
+            // try to do an undo
+            selManager.undo();
 
-		/**
-		 * Create an empty paragraph and select the 0 position in it.
-		 * Then delete all the content on the flow and see if the position selected is 0.
-		 */
-		public function emptyParagraphTest():void
-		{
-			SelManager.selectRange(0,0);
+            // it should be skipped
+            assertTrue("no begin operation event", flowOp != null);
+            assertTrue("wrong begin operation event", flowOp is UndoOperation);
+            assertTrue("textFlow characterFormat.color should be 0xff00", tf.format && tf.format.color == 0xff00);
 
-			var returnevent:KeyboardEvent =
-				new KeyboardEvent(KeyboardEvent.KEY_DOWN, true, false, 13);
-			dispatchEvent(returnevent);
+            selManager.selectRange(0, 0);	// prevent assert in tearDown
+        }
 
-			SelManager.selectRange(0,0);
-			assertTrue("did not start with selection at 0,0", SelManager.anchorPosition == 0 && SelManager.activePosition == 0);
-			SelManager.selectAll();
-			SelManager.deleteNextCharacter();
-			assertTrue("did not end with selection at 0,0 after delete all", SelManager.anchorPosition == 0 && SelManager.activePosition == 0);
-		}
+        [Test]
+        public function doubleClickTest():void
+        {
+            SelManager.selectRange(68, 68);
+            var mEvent:MouseEvent = new MouseEvent(MouseEvent.DOUBLE_CLICK);
+            TestFrame.container["dispatchEvent"](mEvent);
 
-		public function splitUTF16Test():void
-		{
-			// remove all text
-			SelManager.selectAll();
-			SelManager.deleteNextCharacter();
+            assertTrue("Double click failed to correctly select word",
+                    SelManager.anchorPosition == 65 &&
+                            SelManager.activePosition == 72);
 
-			var a:uint = 0xD866; var b:uint = 0xDDC1;
-			var c:uint = 0xD869; var d:uint = 0xDED6;
-			var e:uint = 0xD8BF; var f:uint = 0xDFFD;
+            SelManager.selectRange(955, 955);
+            mEvent = new MouseEvent(MouseEvent.DOUBLE_CLICK);
+            TestFrame.container["dispatchEvent"](mEvent);
 
-			var y:String = String.fromCharCode(a,b,c,d,e,f);
-			SelManager.insertText(y);
-			SelManager.flushPendingOperations();
+            assertTrue("Double click failed to correctly select word",
+                    SelManager.anchorPosition == 954 &&
+                            SelManager.activePosition == 957);
+        }
 
-			var begin:int = 0;
-			var end:int = SelManager.textFlow.textLength;
-			var middle:int = ((end-1) - begin)/2;
-			SelManager.selectRange(middle, middle);
+        [Test]
+        public function doubleClickHyphenTest():void
+        {
+            SelManager.selectRange(24, 24);
+            var mEvent:MouseEvent = new MouseEvent(MouseEvent.DOUBLE_CLICK);
+            TestFrame.container["dispatchEvent"](mEvent);
 
-			var gotRangeError:Boolean = false;
-			try
-			{
-				SelManager.splitParagraph();
-				SelManager.flushPendingOperations();
-			}
-			catch ( e:RangeError )
-			{
-				gotRangeError = true;
-			}
-			/* See bug #1798067 */
-			assertTrue( "Spliting a surrogate pair did not throw an error", gotRangeError );
+            assertTrue("Double click failed on a hyphen",
+                    SelManager.anchorPosition == 24 &&
+                            SelManager.activePosition == 25);
 
-			SelManager.selectAll();
+            SelManager.selectRange(498, 498);
+            mEvent = new MouseEvent(MouseEvent.DOUBLE_CLICK);
+            TestFrame.container["dispatchEvent"](mEvent);
 
-			var charAttr:TextLayoutFormat = new TextLayoutFormat();
-			charAttr.fontFamily = "Adobe Song Std L";
+            assertTrue("Double click failed on a hyphenated word",
+                    SelManager.anchorPosition == 496 &&
+                            SelManager.activePosition == 502);
+        }
 
-			SelManager.applyLeafFormat(charAttr);
-			SelManager.flushPendingOperations();
+        [Test]
+        public function doubleClickPunctuationTest():void
+        {
+            SelManager.selectRange(951, 951);
+            var mEvent:MouseEvent = new MouseEvent(MouseEvent.DOUBLE_CLICK);
+            TestFrame.container["dispatchEvent"](mEvent);
 
-			//trace(begin + ", " + middle + ", " + end);
-		}
+            assertTrue("Double click failed on a word next to punctuation",
+                    SelManager.anchorPosition == 945 &&
+                            SelManager.activePosition == 952);
 
-		public function splitUTF32Test():void
-		{
-			// remove all text
-			SelManager.selectAll();
-			SelManager.deleteNextCharacter();
+            SelManager.selectRange(1964, 1964);
+            mEvent = new MouseEvent(MouseEvent.DOUBLE_CLICK);
+            TestFrame.container["dispatchEvent"](mEvent);
 
-			var y:String = String.fromCharCode(0x00028023);
-			y = y + y + y;
+            assertTrue("Double click failed on punctuation",
+                    SelManager.anchorPosition == 1963 &&
+                            SelManager.activePosition == 1966);
+        }
 
-			SelManager.insertText(y);
-			SelManager.flushPendingOperations();
+        [Test]
+        public function replaceChildrenFlowTest():void
+        {
+            var caught:Boolean = false;
 
-			var begin:int = 0;
-			var end:int = SelManager.textFlow.textLength;
-			var middle:int = ((end-1) - begin)/2;
-			SelManager.selectRange(middle, middle);
+            try
+            {
+                SelManager.textFlow.replaceChildren(0, 0, new TextFlow());
+            }
+            catch (err:ArgumentError)
+            {
+                caught = true;
+            }
 
-			SelManager.splitParagraph();
-			SelManager.flushPendingOperations();
+            assertTrue("TextFlow.replaceChildren with a TextFlow argument should throw an error", caught);
+        }
 
-			SelManager.selectAll();
+        [Test]
+        public function resolveInlinesTest():void
+        {
+            var textFlow:TextFlow;
+            const markup:String = "<flow:TextFlow xmlns:flow='http://ns.adobe.com/textLayout/2008'><flow:p><flow:img source='placeholder'/></flow:p></flow:TextFlow>";
 
-			var charAttr:TextLayoutFormat = new TextLayoutFormat();
-			charAttr.fontFamily = "Adobe Song Std L";
+            var config:Configuration = new Configuration();
+            config.inlineGraphicResolverFunction = resolveInlines;
+            textFlow = TextConverter.importToFlow(markup, TextConverter.TEXT_LAYOUT_FORMAT, config);
 
-			SelManager.applyLeafFormat(charAttr);
-			SelManager.flushPendingOperations();
+            textFlow.addEventListener(StatusChangeEvent.INLINE_GRAPHIC_STATUS_CHANGE, graphicStatusChangeEvent);
 
-			//trace(begin + ", " + middle + ", " + end);
-		}
+            textFlow.flowComposer.addController(new ContainerController(new Sprite(), 400, 200));
+            textFlow.flowComposer.updateAllControllers();
 
+            assertTrue("Inline Graphic resolution failed", ilgStatus == InlineGraphicElementStatus.READY); //
 
-		// pick up the actual operation
-		private var flowOp:FlowOperation;
+        }
 
-		private function listenForOpBegin(opEvent:FlowOperationEvent):void
-		{
-			flowOp = opEvent.operation;
-		}
+        [Test]
+        public function nestingTest():void
+        {
+            var link1:LinkElement = new LinkElement();
+            var tcy1:TCYElement = new TCYElement();
+            var link2:LinkElement = new LinkElement();
 
-		/**
-		 * Performs an operation, clear the selection manager and then make sure the operation doesn't undo
-		 */
-		public function undoWithModelChangeTest():void
-		{
-			var tf:TextFlow = SelManager.textFlow;
-			var selManager:EditManager = SelManager;
+            var exceptionThrown:Boolean = false;
+            try
+            {
+                link1.addChild(link2);
+            }
+            catch (e:*)
+            {
+                exceptionThrown = true;
+            }
+            assertTrue("Should not be able to add a link child to a link", exceptionThrown);
 
-			selManager.selectAll();
+            exceptionThrown = false;
+            link1.addChild(tcy1);
 
-			var initLength:uint = SelManager.textFlow.textLength;
+            try
+            {
+                tcy1.addChild(link2);
+            }
+            catch (e:*)
+            {
+                exceptionThrown = true;
+            }
+            assertTrue("Should not be able to add a link child to a TCY if the latter is contained in a link", exceptionThrown);
 
+            exceptionThrown = false;
+            link1.removeChild(tcy1);
+            tcy1.addChild(link2);
 
-			flowOp = null;
-			tf.addEventListener(FlowOperationEvent.FLOW_OPERATION_BEGIN,listenForOpBegin,false,0,true);
+            try
+            {
+                link1.addChild(tcy1);
+            }
+            catch (e:*)
+            {
+                exceptionThrown = true;
+            }
+            assertTrue("Should not be able to add a TCY child to a link if the former contains a link", exceptionThrown);
 
-			// now do an operation
-			var ca:TextLayoutFormat = new TextLayoutFormat();
-			ca.color = 0xff;
-			selManager.applyFormatToElement(tf, ca);
+        }
 
-			assertTrue("no begin operation event",flowOp != null);
-			assertTrue("textFlow characterFormat.color should be 0xff",tf.format && tf.format.color == 0xff);
+        [Test]
+        [Ignore]
+        /**
+         * Generate errors and make sure we get the right string
+         */
+        public function errorThrowing():void
+        {
+            var exceptionThrown:Boolean;
 
-			// clear the selection manager
-			tf.interactionManager = null;
-			// now I've got a hold of the operation.  do an out of bounds model modification and then attempt an undo
-			tf.color = 0xff00;
-			assertTrue("textFlow characterFormat.color should be 0xff",tf.format.color == 0xff00);
+            //use defaultResourceStringFunction to check the error message
+            // Invalid flowElement
+            try
+            {
+                new FlowGroupElement();
+            }
+            catch (e:Error)
+            {
+                exceptionThrown = true;
+                var invalidFlowElementConstruct_message:String = e.message;
+                assertTrue("errorThrowing: Error thrown but message is incorrect", e.message == GlobalSettings.resourceStringFunction("invalidFlowElementConstruct"));
 
-			// now restore the interactionManager
-			tf.interactionManager = selManager;
-			// CONFIG::debug { trace("GeneralFunctionsTest.undoWithModelChangeTest: expect to see message regarding skipping undo due to mismatched generation numbers."); }
-			// try to do an undo
-			selManager.undo();
+            }
+            assertTrue("errorThrowing: Expected error on new FlowGroupElement did not occur", exceptionThrown);
 
-			// it should be skipped
-			assertTrue("no begin operation event",flowOp != null);
-			assertTrue("wrong begin operation event",flowOp is UndoOperation);
-			assertTrue("textFlow characterFormat.color should be 0xff00",tf.format && tf.format.color == 0xff00);
+            // invalid mxmlchildren assignment
+            exceptionThrown = false;
+            try
+            {
+                var s:Sprite = new Sprite();
+                new DivElement().mxmlChildren = [ s ];
+            }
+            catch (e:Error)
+            {
+                exceptionThrown = true;
+                var badMXMLChildrenArgument_message:String = e.message;
+                assertTrue("errorThrowing: Error thrown but message is incorrect", e.message == GlobalSettings.resourceStringFunction("badMXMLChildrenArgument", [ getQualifiedClassName(s) ]));
+            }
+            assertTrue("errorThrowing: Expected error on bad MXMLChildren argument did not occur", exceptionThrown);
 
-			selManager.selectRange(0,0);	// prevent assert in tearDown
-		}
+            //use customResourceStringFunction to check the error message
+            try
+            {
+                GlobalSettings.resourceStringFunction = customResourceStringFunction;
 
-		private function Redo():void // KJT
-		{
-			try {
-				SelManager.redo();
-			}
-			catch(e:Error){
-				fail("Redo operation failed.");
-			}
-		}
+                //check Invalid flowElement and invalid mxmlchildren assignment
+                assertTrue("errorThrowing: Error thrown but message is incorrect", GlobalSettings.resourceStringFunction("invalidFlowElementConstruct_custom") == invalidFlowElementConstruct_message);
+                assertTrue("errorThrowing: Error thrown but message is incorrect", GlobalSettings.resourceStringFunction("badMXMLChildrenArgument_custom", [ getQualifiedClassName(s) ]) == badMXMLChildrenArgument_message);
 
-		private function dispatchEvent(event:Event):void
-		{
-			// assume containers support dispatchEvent.  Otherwise we get an error
-			TestFrame.container["dispatchEvent"](event);
-		}
+                //use custom resource string function to test HTML importer error
+                exceptionThrown = false;
+                var textImporter:ITextImporter = TextConverter.getImporter(TextConverter.TEXT_FIELD_HTML_FORMAT);
+                var textFlow:TextFlow;
 
-		public function doubleClickTest():void
-		{
-			SelManager.selectRange( 68, 68 );
-			var mEvent:MouseEvent = new MouseEvent( MouseEvent.DOUBLE_CLICK );
-			TestFrame.container["dispatchEvent"](mEvent);
+                var markup:String = '<p>Malformed tag next</p/>';
+                textFlow = textImporter.importToFlow(markup);
 
-			assertTrue( "Double click failed to correctly select word",
-						SelManager.anchorPosition == 65 &&
-						SelManager.activePosition == 72 );
+                if (textImporter.errors)
+                {
+                    exceptionThrown = true;
+                    assertTrue("errorThrowing: Error thrown but message is incorrect", textImporter.errors == GlobalSettings.resourceStringFunction("malformedTag"));
+                }
+                assertTrue("errorThrowing: Expected error on importer did not occur", exceptionThrown);
 
-			SelManager.selectRange( 955, 955 );
-			mEvent = new MouseEvent( MouseEvent.DOUBLE_CLICK );
-			TestFrame.container["dispatchEvent"](mEvent);
+                //use custom resource string function to test Text importer error
+                exceptionThrown = false;
+                markup = "<TextFlow columnCount='inherit'"
+                        + "<span>Ethan Brand</span></a></p></TextFlow>";
 
-			assertTrue( "Double click failed to correctly select word",
-						SelManager.anchorPosition == 954 &&
-						SelManager.activePosition == 957 );
-		}
+                textImporter = TextConverter.getImporter(TextConverter.TEXT_LAYOUT_FORMAT);
+                textFlow = textImporter.importToFlow(markup);
 
-		public function doubleClickHyphenTest():void
-		{
-			SelManager.selectRange( 24, 24 );
-			var mEvent:MouseEvent = new MouseEvent( MouseEvent.DOUBLE_CLICK );
-			TestFrame.container["dispatchEvent"](mEvent);
+                if (textImporter.errors)
+                {
+                    exceptionThrown = true;
+                    assertTrue("errorThrowing: Error thrown but message is incorrect", textImporter.errors == GlobalSettings.resourceStringFunction("XMLParserFailure"));
+                }
+                assertTrue("errorThrowing: Expected error on XML Parser Failure did not occur", exceptionThrown);
+            }
+            finally
+            {
+                GlobalSettings.resourceStringFunction = GlobalSettings.defaultResourceStringFunction;
+            }
 
-			assertTrue( "Double click failed on a hyphen",
-						SelManager.anchorPosition == 24 &&
-						SelManager.activePosition == 25 );
+        }
 
-			SelManager.selectRange( 498, 498 );
-			mEvent = new MouseEvent( MouseEvent.DOUBLE_CLICK );
-			TestFrame.container["dispatchEvent"](mEvent);
+        [Test]
+        /**
+         * Using above table for permitted child/parent relationships verify that canOwnFlowElement matches the table.
+         */
+        public function AllNestingTest():void
+        {
+            var parentRow:Array = childParentTable[0].slice(1);
+            var childRow:Array;
+            var childClassName:String;
+            var childClass:Class;
+            var sliceParentTable:Array = childParentTable.slice(1);
 
-			assertTrue( "Double click failed on a hyphenated word",
-						SelManager.anchorPosition == 496 &&
-						SelManager.activePosition == 502 );
-		}
+            for each (childRow in sliceParentTable)
+            {
+                childClassName = "flashx.textLayout.elements." + childRow[0];
+                childClass = childRow[0] as Class;
+                var childElement:FlowElement = new childClass as FlowElement;
+                assertTrue(childElement.defaultTypeName != null, "Bad defaultTypeName in " + childClassName);
 
-		public function doubleClickPunctuationTest():void
-		{
-			SelManager.selectRange( 951, 951 );
-			var mEvent:MouseEvent = new MouseEvent( MouseEvent.DOUBLE_CLICK );
-			TestFrame.container["dispatchEvent"](mEvent);
+                childRow = childRow.slice(1);
+                for (var idx:int = 0; idx < childRow.length; idx++)
+                {
+                    var parentClass:Class = parentRow[idx] as Class
+                    var parentElement:FlowElement = new parentClass as FlowElement;
 
-			assertTrue( "Double click failed on a word next to punctuation",
-						SelManager.anchorPosition == 945 &&
-						SelManager.activePosition == 952 );
+                    // trace(parentClass.toString(),childClass.toString(),childRow[idx]);
 
-			SelManager.selectRange( 1964, 1964 );
-			mEvent = new MouseEvent( MouseEvent.DOUBLE_CLICK );
-			TestFrame.container["dispatchEvent"](mEvent);
+                    if (parentElement is FlowGroupElement)
+                    {
+                        if (FlowGroupElement(parentElement).canOwnFlowElement(childElement))
+                            assertTrue("Bad canOwnFlowElement value for expected allowed " + parentClass.toString() + " " + childClass.toString(), childRow[idx] == "yes");
+                        else
+                            assertTrue("Bad canOwnFlowElement value for expected not allowed " + parentClass.toString() + " " + childClass.toString(), childRow[idx] == "no");
+                    }
+                    else
+                        assertTrue("Bad canOwnFlowElement value for a non FlowGroupElement parent " + parentClass.toString() + " " + childClass.toString(), childRow[idx] == "no");
+                }
+            }
 
-			assertTrue( "Double click failed on punctuation",
-						SelManager.anchorPosition == 1963 &&
-						SelManager.activePosition == 1966 );
-		}
+            // Check for indirect nesting of SubParagraphGroupElements
+            var textFlow:TextFlow = new TextFlow();
+            var paragraph:ParagraphElement = new ParagraphElement();
+            textFlow.replaceChildren(0, 0, paragraph);
+            var parentGroup:SubParagraphGroupElement = new SubParagraphGroupElement();
+            paragraph.replaceChildren(0, 0, parentGroup);
+            for each (childRow in sliceParentTable)
+            {
+                childClassName = "flashx.textLayout.elements." + childRow[0];
+                childClass = childRow[0] as Class;
+                var spgeChildElement:SubParagraphGroupElementBase = new childClass as SubParagraphGroupElementBase;
+                if (spgeChildElement)
+                {
+                    var groupElement:SubParagraphGroupElement = new SubParagraphGroupElement();
+                    groupElement.replaceChildren(0, 0, new SubParagraphGroupElement());
 
-		public function replaceChildrenFlowTest():void
-		{
-			var caught:Boolean = false;
+                    groupElement.replaceChildren(0, 0, spgeChildElement);
 
-			try
-			{
-				SelManager.textFlow.replaceChildren( 0,0, new TextFlow() );
-			}
-			catch ( err:ArgumentError )
-			{
-				caught = true;
-			}
+                    assertTrue(parentGroup.canOwnFlowElement(groupElement), "Expected this nesting to work");
 
-			assertTrue( "TextFlow.replaceChildren with a TextFlow argument should throw an error", caught );
-		}
-		private function resolveInlines(ilg:InlineGraphicElement):Object
-		{
-			return ilg.source == "placeholder" ? new Sprite() : ilg.source;
-		}
+                    if (!spgeChildElement.allowNesting)
+                    {
+                        var nestingParent:SubParagraphGroupElementBase = new childClass as SubParagraphGroupElementBase;
+                        parentGroup.replaceChildren(parentGroup.numChildren, parentGroup.numChildren, nestingParent);
+                        var nestingGroup:SubParagraphGroupElement = new SubParagraphGroupElement();
+                        nestingParent.replaceChildren(nestingParent.numChildren, nestingParent.numChildren, nestingGroup);
+                        assertTrue("Expected this nesting to fail because of nesting of Link or TCY", !nestingGroup.canOwnFlowElement(groupElement));
+                    }
+                }
+            }
+        }
 
-		private var _ilgStatus:String;
-		private function graphicStatusChangeEvent(e:StatusChangeEvent):void
-		{
-			_ilgStatus = e.status;
-		}
+        private function Redo():void // KJT
+        {
+            try
+            {
+                SelManager.redo();
+            }
+            catch (e:Error)
+            {
+                fail("Redo operation failed.");
+            }
+        }
 
-		public function resolveInlinesTest():void
-		{
-			var textFlow:TextFlow;
-			const markup:String = "<flow:TextFlow xmlns:flow='http://ns.adobe.com/textLayout/2008'><flow:p><flow:img source='placeholder'/></flow:p></flow:TextFlow>";
+        private function dispatchEvent(event:Event):void
+        {
+            // assume containers support dispatchEvent.  Otherwise we get an error
+            TestFrame.container["dispatchEvent"](event);
+        }
 
-			var config:Configuration = new Configuration();
-			config.inlineGraphicResolverFunction = resolveInlines;
-			textFlow = TextConverter.importToFlow(markup, TextConverter.TEXT_LAYOUT_FORMAT, config);
+        private function resolveInlines(ilg:InlineGraphicElement):Object
+        {
+            return ilg.source == "placeholder" ? new Sprite() : ilg.source;
+        }
 
-			textFlow.addEventListener(StatusChangeEvent.INLINE_GRAPHIC_STATUS_CHANGE,graphicStatusChangeEvent);
 
-			textFlow.flowComposer.addController(new ContainerController(new Sprite(), 400, 200));
-			textFlow.flowComposer.updateAllControllers();
+        private function graphicStatusChangeEvent(e:StatusChangeEvent):void
+        {
+            ilgStatus = e.status;
+        }
 
-			assertTrue( "Inline Graphic resolution failed",	_ilgStatus == InlineGraphicElementStatus.READY ); //
+        private function listenForOpBegin(opEvent:FlowOperationEvent):void
+        {
+            flowOp = opEvent.operation;
+        }
 
-		}
+        tlf_internal static function customResourceStringFunction(resourceName:String, parameters:Array = null):String
+        {
+            var value:String = String(customResourceDict[resourceName]);
 
-		public function nestingTest():void
-		{
-			var link1:LinkElement = new LinkElement();
-			var tcy1:TCYElement = new TCYElement();
-			var link2:LinkElement = new LinkElement();
+            if (value == null)
+            {
+                value = String(customResourceDict["missingStringResource"]);
+                parameters = [ resourceName ];
+            }
 
-			var exceptionThrown:Boolean = false;
-			try
-			{
-				link1.addChild(link2);
-			}
-			catch (e:*)
-			{
-				exceptionThrown = true;
-			}
-			assertTrue("Should not be able to add a link child to a link", exceptionThrown);
+            if (parameters)
+                value = customSubstitute(value, parameters);
 
-			exceptionThrown = false;
-			link1.addChild(tcy1);
+            return value;
+        }
 
-			try
-			{
-				tcy1.addChild(link2);
-			}
-			catch (e:*)
-			{
-				exceptionThrown = true;
-			}
-			assertTrue("Should not be able to add a link child to a TCY if the latter is contained in a link", exceptionThrown);
 
-			exceptionThrown = false;
-			link1.removeChild (tcy1);
-			tcy1.addChild(link2);
+        /**
+         * @private
+         * @param str
+         * @param rest
+         * @return
+         */
+        tlf_internal static function customSubstitute(str:String, ...rest):String
+        {
+            if (str == null)
+                return '';
 
-			try
-			{
-				link1.addChild(tcy1);
-			}
-			catch (e:*)
-			{
-				exceptionThrown = true;
-			}
-			assertTrue("Should not be able to add a TCY child to a link if the former contains a link", exceptionThrown);
+            // Replace all of the parameters in the msg string.
+            var len:uint = rest.length;
+            var args:Array;
+            if (len == 1 && rest[0] is Array)
+            {
+                args = rest[0] as Array;
+                len = args.length;
+            }
+            else
+            {
+                args = rest;
+            }
 
-		}
+            for (var i:int = 0; i < len; i++)
+            {
+                str = str.replace(new RegExp("\\{" + i + "\\}", "g"), args[i]);
+            }
 
-		private static const customResourceDict:Object = 
-		{
-			invalidFlowElementConstruct_custom:	"Attempted construct of invalid FlowElement subclass",
-			badMXMLChildrenArgument_custom: "Bad element of type {0} passed to mxmlChildren",
-			malformedTag:	"Malformed tag </p/>",
-			XMLParserFailure:	"TypeError: Error #1090: XML parser failure: element is malformed."
-		}
-		
-		tlf_internal static function customResourceStringFunction(resourceName:String, parameters:Array = null):String
-		{
-			var value:String = String(customResourceDict[resourceName]);
-			
-			if (value == null)
-			{
-				value = String(customResourceDict["missingStringResource"]);
-				parameters = [ resourceName ];
-			}
-			
-			if (parameters)
-				value = customSubstitute(value, parameters);
-			
-			return value;
-		}
-		
-		/** @private */
-		tlf_internal static function customSubstitute(str:String, ... rest):String
-		{
-			if (str == null) 
-				return '';
-			
-			// Replace all of the parameters in the msg string.
-			var len:uint = rest.length;
-			var args:Array;
-			if (len == 1 && rest[0] is Array)
-			{
-				args = rest[0] as Array;
-				len = args.length;
-			}
-			else
-			{
-				args = rest;
-			}
-			
-			for (var i:int = 0; i < len; i++)
-			{
-				str = str.replace(new RegExp("\\{"+i+"\\}", "g"), args[i]);
-			}
-			
-			return str;
-		}
-			
-		/** Generate errors and make sure we get the right string */
-		public function errorThrowing():void
-		{
-			var exceptionThrown:Boolean;
-			
-			//use defaultResourceStringFunction to check the error message
-			// Invalid flowElement
-			exceptionThrown = false;
-			try
-			{
-				new FlowGroupElement();
-			}
-			catch (e:Error)
-			{
-				exceptionThrown = true;
-				var invalidFlowElementConstruct_message:String = e.message;
-				assertTrue("errorThrowing: Error thrown but message is incorrect",e.message == GlobalSettings.resourceStringFunction("invalidFlowElementConstruct"));
-				
-			}
-			assertTrue("errorThrowing: Expected error on new FlowGroupElement did not occur", exceptionThrown);
-			
-			// invalid mxmlchildren assignment
-			exceptionThrown = false;
-			try
-			{
-				var s:Sprite = new Sprite();
-				new DivElement().mxmlChildren = [ s ];
-			}
-			catch (e:Error)
-			{
-				exceptionThrown = true;
-				var badMXMLChildrenArgument_message:String = e.message;
-				assertTrue("errorThrowing: Error thrown but message is incorrect",e.message == GlobalSettings.resourceStringFunction("badMXMLChildrenArgument",[ getQualifiedClassName(s) ]));
-			}
-			assertTrue("errorThrowing: Expected error on bad MXMLChildren argument did not occur", exceptionThrown);
-			
-			//use customResourceStringFunction to check the error message
-			try
-			{
-				GlobalSettings.resourceStringFunction= customResourceStringFunction;
-				
-				//check Invalid flowElement and invalid mxmlchildren assignment
-				assertTrue("errorThrowing: Error thrown but message is incorrect", GlobalSettings.resourceStringFunction("invalidFlowElementConstruct_custom") == invalidFlowElementConstruct_message);
-				assertTrue("errorThrowing: Error thrown but message is incorrect", GlobalSettings.resourceStringFunction("badMXMLChildrenArgument_custom",[ getQualifiedClassName(s) ]) == badMXMLChildrenArgument_message);
-				
-				//use custom resource string function to test HTML importer error
-				exceptionThrown = false;
-				var textImporter:ITextImporter = TextConverter.getImporter(TextConverter.TEXT_FIELD_HTML_FORMAT);
-				var textFlow:TextFlow;
-				
-				var markup:String = '<p>Malformed tag next</p/>';
-				textFlow = textImporter.importToFlow(markup);
-				
-				if (textImporter.errors)
-				{
-					exceptionThrown = true;
-					assertTrue("errorThrowing: Error thrown but message is incorrect",textImporter.errors == GlobalSettings.resourceStringFunction("malformedTag"));
-				}
-				assertTrue("errorThrowing: Expected error on importer did not occur", exceptionThrown);
-				
-				//use custom resource string function to test Text importer error
-				exceptionThrown = false;
-				markup = "<TextFlow columnCount='inherit'" 
-					+ "<span>Ethan Brand</span></a></p></TextFlow>";
-				
-		        textImporter = TextConverter.getImporter(TextConverter.TEXT_LAYOUT_FORMAT);
-				textFlow = textImporter.importToFlow(markup);
-			
-				if (textImporter.errors)
-				{
-					exceptionThrown = true;
-					assertTrue("errorThrowing: Error thrown but message is incorrect",textImporter.errors == GlobalSettings.resourceStringFunction("XMLParserFailure"));
-				}
-				assertTrue("errorThrowing: Expected error on XML Parser Failure did not occur", exceptionThrown);
-			}
-			finally
-			{
-				GlobalSettings.resourceStringFunction = GlobalSettings.defaultResourceStringFunction;
-			}
-		
-		}
-		
-		public static const childParentTable:Array = 
-		[
-			[ "child\parent",			TextFlow,	DivElement, ParagraphElement, LinkElement, TCYElement, SpanElement, InlineGraphicElement, BreakElement, TabElement, ListElement, ListItemElement, SubParagraphGroupElement ],
-			[ TextFlow,					"no",		"no",		"no",				"no",		"no",		"no",			"no",				"no",			"no",		"no",		"no",			"no" ],
-			[ DivElement,				"yes",		"yes",		"no",				"no",		"no",		"no",			"no",				"no",			"no",		"yes",		"yes",			"no" ],
-			[ ParagraphElement,			"yes",		"yes",		"no",				"no",		"no",		"no",			"no",				"no",			"no",		"yes",		"yes",			"no" ],
-			[ LinkElement,				"no",		"no",		"yes",				"no",		"yes",		"no",			"no",				"no",			"no",		"no",		"no",			"yes" ],
-			[ TCYElement,				"no",		"no",		"yes",				"yes",		"no",		"no",			"no",				"no",			"no",		"no",		"no",			"yes" ],
-			[ SpanElement,				"no",		"no",		"yes",				"yes",		"yes",		"no",			"no",				"no",			"no",		"no",		"no",			"yes" ],
-			[ InlineGraphicElement,		"no",		"no",		"yes",				"yes",		"yes",		"no",			"no",				"no",			"no",		"no",		"no",			"yes" ],
-			[ BreakElement,				"no",		"no",		"yes",				"yes",		"yes",		"no",			"no",				"no",			"no",		"no",		"no",			"yes" ],
-			[ TabElement,				"no",		"no",		"yes",				"yes",		"yes",		"no",			"no",				"no",			"no",		"no",		"no",			"yes" ],
-			[ ListElement,				"yes",		"yes",		"no",				"no",		"no",		"no",			"no",				"no",			"no",		"yes",		"yes",			"no" ],
-			[ ListItemElement,			"no",		"no",		"no",				"no",		"no",		"no",			"no",				"no",			"no",		"yes",		"no",			"no" ],
-			[ SubParagraphGroupElement,	"no",		"no",		"yes",				"yes",		"yes",		"no",			"no",				"no",			"no",		"no",		"no",			"yes" ]
-		];
-		
-		/** Using above table for permitted child/parent relationships verify that canOwnFlowElement matches the table. */
-		public function AllNestingTest():void
-		{			
-			var parentRow:Array = childParentTable[0].slice(1);
-			var childRow:Array;
-			var childClassName:String;
-			var childClass:Class;
-			
-			for each (childRow in childParentTable.slice(1))
-			{
-				childClassName = "flashx.textLayout.elements." + childRow[0];
-				childClass = childRow[0] as Class;
-				var childElement:FlowElement = new childClass as FlowElement;
-				assertTrue(childElement.defaultTypeName != null,"Bad defaultTypeName in " + childClassName);
+            return str;
+        }
 
-				childRow = childRow.slice(1);
-				for (var idx:int = 0; idx < childRow.length; idx++)
-				{
-					var parentClass:Class = parentRow[idx] as Class
-					var parentElement:FlowElement = new parentClass as FlowElement;
-					
-					// trace(parentClass.toString(),childClass.toString(),childRow[idx]);
-					
-					if (parentElement is FlowGroupElement)
-					{
-						if (FlowGroupElement(parentElement).canOwnFlowElement(childElement))
-							assertTrue("Bad canOwnFlowElement value for expected allowed "+parentClass.toString()+" "+childClass.toString(),childRow[idx] == "yes");
-						else
-							assertTrue("Bad canOwnFlowElement value for expected not allowed "+parentClass.toString()+" "+childClass.toString(), childRow[idx] == "no");
-					}
-					else 
-						assertTrue("Bad canOwnFlowElement value for a non FlowGroupElement parent "+parentClass.toString()+" "+childClass.toString(),childRow[idx] == "no");
-				}
-			}
-			
-			// Check for indirect nesting of SubParagraphGroupElements
-			var textFlow:TextFlow = new TextFlow();
-			var paragraph:ParagraphElement = new ParagraphElement();
-			textFlow.replaceChildren(0, 0, paragraph);
-			var parentGroup:SubParagraphGroupElement = new SubParagraphGroupElement();
-			paragraph.replaceChildren(0, 0, parentGroup);
-			for each (childRow in childParentTable.slice(1))
-			{
-				childClassName = "flashx.textLayout.elements." + childRow[0];
-				childClass = childRow[0] as Class;
-				var spgeChildElement:SubParagraphGroupElementBase = new childClass as SubParagraphGroupElementBase;
-				if (spgeChildElement)
-				{
-					var groupElement:SubParagraphGroupElement = new SubParagraphGroupElement();
-					groupElement.replaceChildren(0, 0, new SubParagraphGroupElement());
+        /**
+         * selecting text from 10 to 20
+         */
+        private function selChange(e:Event):void //KJT selection change event method
+        {
+            SelectionChanged = true;
+        }
 
-					groupElement.replaceChildren(0, 0, spgeChildElement);
-					
-					assertTrue (parentGroup.canOwnFlowElement(groupElement), "Expected this nesting to work");
-					
-					if (!spgeChildElement.allowNesting)
-					{
-						var nestingParent:SubParagraphGroupElementBase = new childClass as SubParagraphGroupElementBase;
-						parentGroup.replaceChildren(parentGroup.numChildren, parentGroup.numChildren, nestingParent);
-						var nestingGroup:SubParagraphGroupElement = new SubParagraphGroupElement();
-						nestingParent.replaceChildren(nestingParent.numChildren, nestingParent.numChildren, nestingGroup);
-						assertTrue("Expected this nesting to fail because of nesting of Link or TCY", !nestingGroup.canOwnFlowElement(groupElement));
-					}
-				}
-			}
-		}
-	}
+    }
 }