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));
-					}
-				}
-			}
-		}
-	}
+    }
 }
