FLEX-35306 Addd unit test. Fails when reverting the fix, passes with the fix.
Project: http://git-wip-us.apache.org/repos/asf/flex-sdk/repo Commit: http://git-wip-us.apache.org/repos/asf/flex-sdk/commit/2750254b Tree: http://git-wip-us.apache.org/repos/asf/flex-sdk/tree/2750254b Diff: http://git-wip-us.apache.org/repos/asf/flex-sdk/diff/2750254b Branch: refs/heads/master Commit: 2750254ba51c284f8bb5dfce2b5101179600b21b Parents: 59cefd8 Author: Mihai Chira <mih...@apache.org> Authored: Mon May 22 10:52:55 2017 +0200 Committer: Mihai Chira <mih...@apache.org> Committed: Mon May 22 10:52:55 2017 +0200 ---------------------------------------------------------------------- .../spark/components/List_FLEX_35306_Tests.as | 274 +++++++++++++++++++ .../spark/tests/spark/components/_CompanyVO.as | 49 ++++ .../tests/spark/components/_HeadquarterVO.as | 23 ++ .../spark/components/_ListWithMXMLBinding.mxml | 22 ++ 4 files changed, 368 insertions(+) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/flex-sdk/blob/2750254b/frameworks/projects/spark/tests/spark/components/List_FLEX_35306_Tests.as ---------------------------------------------------------------------- diff --git a/frameworks/projects/spark/tests/spark/components/List_FLEX_35306_Tests.as b/frameworks/projects/spark/tests/spark/components/List_FLEX_35306_Tests.as new file mode 100644 index 0000000..1780240 --- /dev/null +++ b/frameworks/projects/spark/tests/spark/components/List_FLEX_35306_Tests.as @@ -0,0 +1,274 @@ +//////////////////////////////////////////////////////////////////////////////// +// +// Licensed to the Apache Software Foundation (ASF) under one or more +// contributor license agreements. See the NOTICE file distributed with +// this work for additional information regarding copyright ownership. +// The ASF licenses this file to You under the Apache License, Version 2.0 +// (the "License"); you may not use this file except in compliance with +// the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//////////////////////////////////////////////////////////////////////////////// + +package spark.components { + import flash.events.Event; + import flash.events.EventDispatcher; + + import mx.collections.ArrayCollection; + import mx.collections.IList; + import mx.core.mx_internal; + + import org.flexunit.asserts.assertEquals; + import org.flexunit.asserts.assertFalse; + import org.flexunit.asserts.assertNotNull; + import org.flexunit.async.Async; + import org.flexunit.runners.Parameterized; + import org.fluint.uiImpersonation.UIImpersonator; + + import spark.skins.spark.ListSkin; + + use namespace mx_internal; + + [RunWith("org.flexunit.runners.Parameterized")] + public class List_FLEX_35306_Tests + { + private static var foo:Parameterized; + + private static const NO_ENTER_FRAMES_TO_ALLOW:int = 4; + private static var noEnterFramesRemaining:int = NaN; + private static const _finishNotifier:EventDispatcher = new EventDispatcher(); + + private static var _sut:_ListWithMXMLBinding; + + private static var _hqRedmond:_HeadquarterVO; + private static var _hqSantaClara:_HeadquarterVO; + private static var _hqBerlin:_HeadquarterVO; + private static var _hqMunchen:_HeadquarterVO; + private static var _hqNewYork:_HeadquarterVO; + private static var _hqSantaMaria:_HeadquarterVO; + private static var _hqSantaDolores:_HeadquarterVO; + + [Bindable] + public var selectedCompany:_CompanyVO; + [Bindable] + public var potentialHeadquarters:IList; + + public static var models:Array; + { + models = [[createListOfCompaniesWithOnePotentialAddressEach()], [createListOfCompaniesWithMultiplePotentialAddresses()]]; + } + + [AfterClass] + public static function tearDownStatic():void + { + models = null; + } + + [Before] + public function setUp():void + { + _sut = new _ListWithMXMLBinding(); + _sut.container = this; + _sut.setStyle("skinClass", ListSkin); + _sut.requireSelection = true; + } + + [After] + public function tearDown():void + { + UIImpersonator.removeAllChildren(); + _sut = null; + } + + [Test(order=2, async, timeout=1000, dataProvider="models", description="this should run after the main test because it rewrites the model")] + public function test_double_binding(companies:IList):void + { + //given + const firstCompany:_CompanyVO = companies.getItemAt(0) as _CompanyVO; + const secondCompany:_CompanyVO = companies.getItemAt(1) as _CompanyVO; + const secondCompanyHQ:_HeadquarterVO = secondCompany.originalHeadquarter; + selectedCompany = firstCompany; + + UIImpersonator.addElement(_sut); + + //when 1 + selectedCompany = secondCompany; + potentialHeadquarters = secondCompany.potentialHeadquarters; + + //then 1 - wait some frames until there's a selection + noEnterFramesRemaining = NO_ENTER_FRAMES_TO_ALLOW; + UIImpersonator.testDisplay.addEventListener(Event.ENTER_FRAME, onEnterFrame); + Async.handleEvent(this, _finishNotifier, Event.COMPLETE, then_check_binding_from_bindable_var_to_list, 400, {companies:companies, expectedHQ:secondCompanyHQ}); + } + + private function then_check_binding_from_bindable_var_to_list(event:Event, passThroughData:Object):void + { + //given + const companies:IList = passThroughData.companies; + const expectedHQ:_HeadquarterVO = passThroughData.expectedHQ as _HeadquarterVO; + const thirdCompany:_CompanyVO = companies.getItemAt(2) as _CompanyVO; + + //then + assertEquals("The list's selected item didn't change (correctly?) when we changed the associated bindable variable!", expectedHQ, _sut.selectedItem); + + //given 2 + var extraHQ:_HeadquarterVO = new _HeadquarterVO("hello", "address"); + + //when 2 + thirdCompany.potentialHeadquarters.addItem(extraHQ); + potentialHeadquarters = thirdCompany.potentialHeadquarters; + selectedCompany = thirdCompany; + _sut.selectedItem = extraHQ; + + //then 2 - wait some frames until there's a selection + noEnterFramesRemaining = NO_ENTER_FRAMES_TO_ALLOW; + UIImpersonator.testDisplay.addEventListener(Event.ENTER_FRAME, onEnterFrame); + Async.handleEvent(this, _finishNotifier, Event.COMPLETE, then_check_binding_from_list_to_bindable_var, 400, {companies:companies, expectedHQ:extraHQ}); + } + + private function then_check_binding_from_list_to_bindable_var(event:Event, passThroughData:Object):void + { + //given + const companies:IList = passThroughData.companies as IList; + const expectedHQ:_HeadquarterVO = passThroughData.expectedHQ as _HeadquarterVO; + + //then 2 + assertEquals("The binding destination didn't change (correctly?) when we changed the list's selectedItem!", expectedHQ, selectedCompany.headquarter); + + //cleanup + const thirdCompany:_CompanyVO = companies.getItemAt(2) as _CompanyVO; + thirdCompany.potentialHeadquarters.removeItem(expectedHQ); + } + + + + + + [Test(order=1, async, timeout=1000, dataProvider="models")] + public function test_list_doesnt_rewrite_model(companies:IList):void + { + //given + const secondCompany:_CompanyVO = companies.getItemAt(1) as _CompanyVO; + + //when + selectedCompany = secondCompany; + potentialHeadquarters = secondCompany.potentialHeadquarters; + + UIImpersonator.addElement(_sut); + + //then - wait some frames until there's a selection + noEnterFramesRemaining = NO_ENTER_FRAMES_TO_ALLOW; + UIImpersonator.testDisplay.addEventListener(Event.ENTER_FRAME, onEnterFrame); + Async.handleEvent(this, _finishNotifier, Event.COMPLETE, then_change_dp_and_selected_item, 400, companies); + } + + private function then_change_dp_and_selected_item(event:Event, passThroughData:Object):void + { + //given + const model:IList = passThroughData as IList; + const secondCompany:_CompanyVO = model.getItemAt(1) as _CompanyVO; + const thirdCompany:_CompanyVO = model.getItemAt(2) as _CompanyVO; + + //then + assertNotNull(secondCompany.headquarter); //HUH? + assertEquals("The selection should be " + secondCompany.headquarter.name + "!", secondCompany.originalHeadquarter, _sut.selectedItem); + + //when + selectedCompany = thirdCompany; + potentialHeadquarters = thirdCompany.potentialHeadquarters; + + //then - wait some frames until the selection has changed + noEnterFramesRemaining = NO_ENTER_FRAMES_TO_ALLOW; + UIImpersonator.testDisplay.addEventListener(Event.ENTER_FRAME, onEnterFrame); + Async.handleEvent(this, _finishNotifier, Event.COMPLETE, then_check_if_model_has_been_rewritten, 400, model); + } + + private static function then_check_if_model_has_been_rewritten(event:Event, passThroughData:Object):void + { + //given + const model:IList = passThroughData as IList; + const thirdCompany:_CompanyVO = model.getItemAt(2) as _CompanyVO; + const expectedHQ:_HeadquarterVO = thirdCompany.originalHeadquarter; + + //then + assertEquals("The selection should be " + expectedHQ.name + "!", expectedHQ, _sut.selectedItem); + + assertCompaniesHaveCorrectHQ(model); + assertNoCompanyHQWasRewritten(model); + } + + private static function assertCompaniesHaveCorrectHQ(companiesList:IList):void + { + for each(var company:_CompanyVO in companiesList) + { + assertEquals("The headquarter of " + company.name + " has been changed to an invalid value!", company.originalHeadquarter, company.headquarter); + } + } + + private static function assertNoCompanyHQWasRewritten(companiesList:IList):void + { + for each(var company:_CompanyVO in companiesList) + { + assertFalse("The headquarter of " + company.name + " has been rewritten, although with the correct value in the end", company.headquarterRewritten); + } + } + + private static function onEnterFrame(event:Event):void + { + if(!--noEnterFramesRemaining) + { + UIImpersonator.testDisplay.removeEventListener(Event.ENTER_FRAME, onEnterFrame); + _finishNotifier.dispatchEvent(new Event(Event.COMPLETE)); + } + } + + //-------------------------------------------------------------------------- + // + // Set up methods + // + //-------------------------------------------------------------------------- + + private static function createListOfCompaniesWithMultiplePotentialAddresses():IList + { + createHeadquartersIfNeeded(); + + var microsoft:_CompanyVO = new _CompanyVO("Microsoft", _hqRedmond, new ArrayCollection([_hqRedmond, _hqNewYork])); + var intel:_CompanyVO = new _CompanyVO("Intel", _hqSantaClara, new ArrayCollection([_hqSantaClara, _hqSantaMaria, _hqSantaDolores])); + var wv:_CompanyVO = new _CompanyVO("VW", _hqBerlin, new ArrayCollection([_hqBerlin, _hqMunchen])); + + return new ArrayCollection([microsoft, intel, wv]); + } + + private static function createListOfCompaniesWithOnePotentialAddressEach():IList + { + createHeadquartersIfNeeded(); + + var microsoft:_CompanyVO = new _CompanyVO("Microsoft", _hqRedmond, new ArrayCollection([_hqRedmond])); + var intel:_CompanyVO = new _CompanyVO("Intel", _hqSantaClara, new ArrayCollection([_hqSantaClara])); + var wv:_CompanyVO = new _CompanyVO("VW", _hqBerlin, new ArrayCollection([_hqBerlin])); + + return new ArrayCollection([microsoft, intel, wv]); + } + + private static function createHeadquartersIfNeeded():void + { + if(_hqRedmond) + return; + + _hqRedmond = new _HeadquarterVO("Redmond", "redmond address 123"); + _hqNewYork = new _HeadquarterVO("New York", "NY address 123"); + _hqSantaClara = new _HeadquarterVO("Santa Clara", "santa clara address 123"); + _hqSantaMaria = new _HeadquarterVO("Santa Maria", "santa maria address 123"); + _hqSantaDolores = new _HeadquarterVO("Santa Dolores", "santa dolores address 123"); + _hqBerlin = new _HeadquarterVO("Berlin", "berlin address 123"); + _hqMunchen = new _HeadquarterVO("Munchen", "munchen address 123"); + } + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/flex-sdk/blob/2750254b/frameworks/projects/spark/tests/spark/components/_CompanyVO.as ---------------------------------------------------------------------- diff --git a/frameworks/projects/spark/tests/spark/components/_CompanyVO.as b/frameworks/projects/spark/tests/spark/components/_CompanyVO.as new file mode 100644 index 0000000..3889c62 --- /dev/null +++ b/frameworks/projects/spark/tests/spark/components/_CompanyVO.as @@ -0,0 +1,49 @@ +package spark.components { + import mx.collections.ArrayCollection; + + [Bindable] + public class _CompanyVO + { + private var _headquarter:_HeadquarterVO; + private var _headquarterRewritten:Boolean = false; + private var _originalHeadquarter:_HeadquarterVO; + + public var name:String; + public var potentialHeadquarters:ArrayCollection; + + + public function _CompanyVO(name:String, headquarter:_HeadquarterVO, potentialHeadquarters:ArrayCollection) + { + this.name = name; + this._headquarter = headquarter; + this._originalHeadquarter = headquarter; + this.potentialHeadquarters = potentialHeadquarters; + } + + public function get headquarter():_HeadquarterVO + { + return _headquarter; + } + + public function set headquarter(value:_HeadquarterVO):void + { + _headquarterRewritten = true; + _headquarter = value; + } + + public function get headquarterRewritten():Boolean + { + return _headquarterRewritten; + } + + public function get originalHeadquarter():_HeadquarterVO + { + return _originalHeadquarter; + } + + public function toString():String + { + return "CompanyVO{name=" + String(name) + ", #hqs="+potentialHeadquarters.length+"}"; + } + } +} http://git-wip-us.apache.org/repos/asf/flex-sdk/blob/2750254b/frameworks/projects/spark/tests/spark/components/_HeadquarterVO.as ---------------------------------------------------------------------- diff --git a/frameworks/projects/spark/tests/spark/components/_HeadquarterVO.as b/frameworks/projects/spark/tests/spark/components/_HeadquarterVO.as new file mode 100644 index 0000000..b41d129 --- /dev/null +++ b/frameworks/projects/spark/tests/spark/components/_HeadquarterVO.as @@ -0,0 +1,23 @@ +package spark.components { + [Bindable] + public class _HeadquarterVO { + public var name:String; + public var address:String; + + public function _HeadquarterVO(name:String, address:String) + { + this.name = name; + this.address = address; + } + + public function get label():String + { + return name; + } + + public function toString():String + { + return "HeadquarterVO{name=" + String(name) + "}"; + } + } +} http://git-wip-us.apache.org/repos/asf/flex-sdk/blob/2750254b/frameworks/projects/spark/tests/spark/components/_ListWithMXMLBinding.mxml ---------------------------------------------------------------------- diff --git a/frameworks/projects/spark/tests/spark/components/_ListWithMXMLBinding.mxml b/frameworks/projects/spark/tests/spark/components/_ListWithMXMLBinding.mxml new file mode 100644 index 0000000..3e65389 --- /dev/null +++ b/frameworks/projects/spark/tests/spark/components/_ListWithMXMLBinding.mxml @@ -0,0 +1,22 @@ +<?xml version="1.0"?> +<s:List xmlns:fx="http://ns.adobe.com/mxml/2009" xmlns:s="library://ns.adobe.com/flex/spark" + selectedItem="@{container.selectedCompany.headquarter}" + dataProvider="{container.potentialHeadquarters}"> + + <fx:Script> + <![CDATA[ + private var _container:Object; + + [Bindable] + public function get container():Object + { + return _container; + } + + public function set container(value:Object):void + { + _container = value; + } + ]]> + </fx:Script> +</s:List>