I am trying to write a unit test for a view in flex. There is a two way binding between a TextInput, reportName
, and a property, _parameters
. The binding works fine when I run the code, but the tests fail. Below is one of many tests that fail in similar ways. The test fails with the following message:
Error: Expected: "newName"
but: was "defaultTitle"
The trace messages in parameters_changeHandler()
reveal the following:
parameters_changeHandler
_parameters.reportName defaultTitle
reportName.text newName
So the TextInput, reportName
, is being updated correctly, but the way I am setting the text on it in the test is undoing the binding, at least I think that is the problem.
How do I maintain the two-binding and still update the value? Is there another way to simulate a user entering data?
View.mxml:
<fx:Script>
<![CDATA[
import events.events.UpdatePointRadiusReportModalParametersEvent;
import model.LocationAnalysisParameters;
[Bindable]
internal var _parameters:LocationAnalysisParameters;
public function set parameters(parameters:LocationAnalysisParameters):void
{
this._parameters = parameters;
}
public function get parameters():LocationAnalysisParameters
{
return _parameters;
}
protected function parameters_changeHandler():void
{
trace('parameters_changeHandler');
trace('_parameters.reportName', _parameters.reportName);
trace('reportName.text', reportName.text);
dispatchEvent(new UpdatePointRadiusReportModalParametersEvent(_parameters));
}
]]>
</fx:Script>
<s:VGroup>
<s:Label id="reportNameLabel"
styleName="toolStyle"
text="Report Name:"/>
<s:TextInput id="reportName"
width="100%"
maxChars="50"
minWidth="200"
styleName="toolStyle"
text="{_parameters.reportName}"
change="parameters_changeHandler()"
restrict="a-zA-Z0-9 \-_"/>
</s:VGroup>
</components:FlyoutPanel>
LocationAnalysisParameters.as
package model
{
import utils.StringUtils;
[Bindable]
public class LocationAnalysisParameters
{
public var reportName:String;
public var reportDescription:String;
public function reset():void
{
reportName = null;
reportDescription = null;
}
public function isValid():Boolean
{
return !StringUtils.isNullOrEmpty(reportDescription) && !StringUtils.isNullOrEmpty(reportName);
}
public function clone():LocationAnalysisParameters
{
const c:LocationAnalysisParameters = new LocationAnalysisParameters();
c.reportName = reportName;
c.reportDescription = reportDescription;
return c;
}
}
}
ViewTest.as package views {
public class PointRadiusReportPopupViewTest
{
private var popupView:PointRadiusReportPopupView;
[Before(async, ui)]
public function setUp():void
{
popupView = new PointRadiusReportPopupView();
Async.proceedOnEvent(this, popupView, FlexEvent.CREATION_COMPLETE);
UIImpersonator.addChild(popupView);
}
[After(ui)]
public function tearDown():void
{
UIImpersonator.removeChild(popupView);
popupView = null;
}
[Test(async, ui)]
public function reportNameChangeShouldDispatchUpdatePointRadiusReportModalParametersEvent():void
{
//arrange
const parameters:LocationAnalysisParameters = new LocationAnalysisParameters();
parameters.reportName = 'defaultTitle';
parameters.reportDescription = 'defaultDescription';
popupView.parameters = parameters;
const expectedParameters:LocationAnalysisParameters = new LocationAnalysisParameters();
expectedParameters.reportName = 'newName';
expectedParameters.reportDescription = 'defaultDescription';
//act
Async.handleEvent(this, popupView, UpdatePointRadiusReportModalParametersEvent.TYPE, assertUpdatePointRadiusReportModalParametersEvent, 500, expectedParameters);
updateTextInput(popupView.reportName, 'newName');
}
private function assertUpdatePointRadiusReportModalParametersEvent(evt:UpdatePointRadiusReportModalParametersEvent, expectedParameters:LocationAnalysisParameters):void
{
assertThat(evt.parameters.reportName, equalTo(expectedParameters.reportName));
assertThat(evt.parameters.reportDescription, equalTo(expectedParameters.reportDescription));
}
/**
* Helpers
*/
internal static function updateTextInput(compontent:TextInput, value:String):void
{
compontent.text = value;
const event:TextOperationEvent = new TextOperationEvent(TextOperationEvent.CHANGE, false, true);
compontent.dispatchEvent(event);
}
}
}
I guess I just needed to sleep on it. The reason my tests were failing was two way binding only works as two way binding when you specify them as being two way binding.
WRONG (one way binding):
text="{_parameters.reportName}"
CORRECT (two way binding:
text="@{_parameters.reportName}"
Properly specifying the two binding was all that was needed to make things work.