<?xml version="1.0" encoding="utf-8"?>
<!--

  Licensed to the Apache Software Foundation (ASF) under one or more
  contributor license agreements.  See the NOTICE file distributed with
  this work for additional information regarding copyright ownership.
  The ASF licenses this file to You under the Apache License, Version 2.0
  (the "License"); you may not use this file except in compliance with
  the License.  You may obtain a copy of the License at

      http://www.apache.org/licenses/LICENSE-2.0

  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.

-->
<UnitTester xmlns:mx="http://www.adobe.com/2006/mxml" xmlns="*" testSWF="main.mxml">

	<!-- this set of lines form a template that must be in each unit test -->
	<mx:Script>
	<![CDATA[
	public static function init(o:DisplayObject):void
	{
	}
	]]>
	</mx:Script>
	<mx:Metadata>
	<![CDATA[
		[Mixin]
	]]>
	</mx:Metadata>
	<!-- end of set of lines that must be in each unit test -->

	<mx:Script>
	<![CDATA[
        import flash.text.engine.TextLine;
        import flash.display.DisplayObjectContainer;
        import mx.core.ITextInput;
        import mx.core.IUITextField;
        import mx.core.mx_internal;
        
        use namespace mx_internal;
        
        // Return true if the Label has a FTETextField.
        private function checkLabelTextField():Boolean
        {
            var textField:IUITextField = 
                application.haloFTETextTests.testFTELabel.getTextField();            
            
            var className:String = getQualifiedClassName(textField);
            
            return className == "mx.core::UIFTETextField";
        }

        // If text is set there should be at least one TextLine.
        private function checkLabelTextFieldChild():Boolean
        {
            var textField:IUITextField = 
                application.haloFTETextTests.testFTELabel.getTextField();

            return (textField is DisplayObjectContainer &&
                    DisplayObjectContainer(textField).numChildren > 0 &&                    
                    DisplayObjectContainer(textField).getChildAt(0) is TextLine);
        }
        
        // Return true if the NumericStepper has a MXFTETextInput.
        private function checkNSTextInputField():Boolean
        {
            var textInput:ITextInput = 
                application.haloFTETextTests.testFTENumericStepper.inputField;

            var className:String = getQualifiedClassName(textInput);
            
            return className == "mx.controls::MXFTETextInput";
        }
	]]>
	</mx:Script>

	<testCases>
		<TestCase testID="SetupFTETextTest">
			<body>
				<SetProperty target="" propertyName="currentState" value="haloFTETextTest" 
                    waitEvent="updateComplete" />
			</body>
		</TestCase>
        
		<TestCase testID="FTELabelTest">
			<body>
                <AssertPropertyValue target="haloFTETextTests.testFTELabel" propertyName="text" value="FTE text" />
                <AssertMethodValue method="value=checkLabelTextField()" valueExpression="value=true" />
                <AssertMethodValue method="value=checkLabelTextFieldChild()" valueExpression="value=true" />
			</body>
		</TestCase>
        
		<TestCase testID="FTENumericStepperTest">
			<body>
                <AssertPropertyValue target="haloFTETextTests.testFTENumericStepper" propertyName="value" value="7" />
                <AssertMethodValue method="value=checkNSTextInputField()" valueExpression="value=true" />
			</body>
		</TestCase>
	</testCases>
</UnitTester>
