17 Replies Latest reply on Sep 2, 2011 8:19 AM by Rambo 007

    Testing with PopUps?

    Rambo 007

      I have a need to write a test that involves validaing correct functionality of components that are displayed within PopUps.  I feel like I'm missing something obvious, but what I am seeing is that the primary component that I create the popup with is seemingly being created correctly (at least it's dispatching the correct lifecycle events as it would normally), but its children are not being instantiated at all; they all appear to be null.  The primary component is a VBox subclass, and the children that won't instantiate are Label subclasses.  I don't have any special magic going on (such as deferred creation) on the VBox that might cause this.  This is with Flex 3.5, but I imagine that Flex 4 or 4.5 the same sort of  thing would occur.

       

      This case is not covered in the documentation, and before I waste another day or two on it, I thought I'd seek advice from the collective wisdom (you).

       

      Thanks for any insight or assistance you can provide.

       

      Steve

        • 1. Re: Testing with PopUps?
          bucpatr1 Level 2

          When you talk about 'the primary component that I create the popup with' are you referring to the parent component or the actual component that gets displayed by the PopUpManager?

          • 2. Re: Testing with PopUps?
            Rambo 007 Level 1

            The component under test is the one "in" the PopUpManager.  I want to make sure it behaves correctly when displayed as a pop up.  But, there may also be situations where the compoent under test is a child or descendant of the component popped up by the manager.

            • 3. Re: Testing with PopUps?
              bucpatr1 Level 2

              Could you post a snippet of your test code? If I had to take a guess, I would say that you test is trying to do assertions before your component is fully initialized. Keep in mind that the creationComplete event does not garuantee that your you subcomponents are fully initialized, only the parent.

              • 4. Re: Testing with PopUps?
                Rambo 007 Level 1

                First, here's the output of interposing on dispatchEvent in the popped up component:

                 

                Dispatching enabledChanged label null
                Dispatching propertyChange label null
                Dispatching add label null
                Dispatching preinitialize label null
                Dispatching initialize label null
                Dispatching childrenChanged label null
                Dispatching creationComplete label null
                Dispatching updateComplete label null

                 

                The component I actually want to test it a Label, and so I print its value along with each event as they happen.  The label never becomes non-null.  This makes me think that there is some oddball case with creation policy in popups.   And, I've tried waiting for both creationc omplete and update complete on this class, but as you can see, the label is  has not been created in either case. 

                 

                This document: http://livedocs.adobe.com/flex/3/html/help.html?content=containers_intro_3.html, says "Flex dispatches the creationComplete event  for a container when those children that are initially required are  fully processed and drawn on the screen, including all required children  of the children and so on. Create a listener for the creationComplete event, for example, if you must have the children's dimensions and positions in your event handler. Do not use the creationComplete event for actions that set layout properties, as doing so results in excess processing"  So, I would think that waiting for createionComplete would be sufficient.  Even if I alter this VBox to have creationPolicy="all", the label still does not get instantiated.

                 

                <mx:VBox
                    xmlns:mx="http://www.adobe.com/2006/mxml"
                >

                    <mx:Script>
                    <![CDATA[
                        import flash.events.Event;

                 

                        override public function dispatchEvent(e: Event): Boolean {
                            trace("Dispatching " + e.type + " label " + label1);
                            return super.dispatchEvent(e);
                        }

                    ]]>
                    </mx:Script>

                    <!-- this should have a valid substituted value  -->
                    <dor:DLabel id="label1" text="foo"
                                preinitialize="trace('preinit')"
                                initialize="trace('label init')"
                                creationComplete="trace('label creation complete')"
                                />

                </mx:VBox>

                • 5. Re: Testing with PopUps?
                  Rambo 007 Level 1

                  edit: replace "dor:DLabel" with "mx:Label".  These are locally subclasses of the mx counterparts that are identical in their behavior.

                  • 6. Re: Testing with PopUps?
                    bucpatr1 Level 2

                    So what does your test code look like? I was able to create a simple test and the label seemd to get created with no problem.

                    • 7. Re: Testing with PopUps?
                      Rambo 007 Level 1

                      What did you use for the owner of the PopUp?  I created an instance of mx.core.Application, and added that as the child of the UIImpersonator.

                       

                      Here's both my main test app, and a cleaned up version of the component under test.  After that, is the content of flashlog.txt showing the label remains null.

                       

                      ----------------------------------- PopUpLocalization.as

                      package com.dorado.flex.flexplatform.resources.PopUpLocalization {

                          import flash.events.Event;

                       

                          import mx.core.Application;
                          import mx.events.FlexEvent;
                          import mx.managers.PopUpManager;

                       

                          import org.flexunit.Assert;
                          import org.flexunit.async.Async;
                          import org.fluint.uiImpersonation.UIImpersonator;

                       

                          public class PopUpLocalizationTest {
                              private var app: Application;

                       

                              [Before(async, ui)]
                              public function setUp() : void {
                                  app = new Application();

                       

                                  //After added to display list wait for signal that component was created to continue the test
                                  Async.proceedOnEvent(this, app, FlexEvent.APPLICATION_COMPLETE, 500);

                       

                                  //Add to display list
                                  UIImpersonator.addChild(app);
                              }

                       

                              [Test(async,ui)]
                              public function testLocalizedPopup(): void {
                                  var locPopup: LocalizedPopup = new LocalizedPopup();
                                  locPopup.document = app;
                                  var asyncHandler: Function =
                                      Async.asyncHandler(this, handlePopupReady, 500, locPopup, handlePopupDidntShow);

                       

                                  locPopup.addEventListener(FlexEvent.UPDATE_COMPLETE, asyncHandler);

                       

                                  PopUpManager.addPopUp(locPopup, app);
                              }

                       

                              private function handlePopupReady(e: Event, passThroughData: Object): void {
                                  trace("pass through data is " + passThroughData);
                                 
                                  var locPopup: LocalizedPopup = passThroughData as LocalizedPopup;

                       

                                  trace("label 1 is " + locPopup.label1);
                              }
                           
                              private function handlePopupDidntShow(passThroughData: Object): void {
                                  Assert.fail("Popup didn't show up!");
                              }

                       

                              [After(async, ui)]
                              public function tearDown() : void {
                                  UIImpersonator.removeChild(app);
                                  app = null;
                              }
                          }
                      }

                       

                       

                      -------------------- LocalizedPopup.as

                      <mx:VBox
                          xmlns:mx="http://www.adobe.com/2006/mxml"
                          creationPolicy="all"
                      >
                          <mx:Script>
                          <![CDATA[
                                      
                              import flash.events.Event;

                       

                              override public function dispatchEvent(e: Event): Boolean {
                                  trace("Dispatching " + e.type + " label " + label1);
                                  return super.dispatchEvent(e);
                              }
                          ]]>
                          </mx:Script>

                       

                          <!-- this should have a valid substituted value  -->
                          <mx:Label id="label1" text="label1"
                                      preinitialize="trace('preinit')"
                                      initialize="trace('label init')"
                                      creationComplete="trace('label creation complete')"
                                      />

                       

                          <!-- this should have NOT a valid substituted value, and should just show the resource name  -->
                          <mx:Label id="label2" text="label2"/>

                       

                      </mx:VBox>

                       

                       

                      ------------------------------------------------ flashlog.txt

                      Dispatching enabledChanged label null
                      Dispatching add label null
                      Dispatching preinitialize label null
                      Dispatching initialize label null
                      Dispatching childrenChanged label null
                      Dispatching creationComplete label null
                      Dispatching updateComplete label null
                      pass through data is LocalizedPopup18
                      label 1 is null
                      <testcase classname="com.dorado.flex.flexplatform.resources.PopUpLocalization::PopUpLocalizationTes t" name="testLocalizedPopup" time="567" status="failure"><failure message="Timeout Occurred before expected event" type="com.dorado.flex.flexplatform.resources.PopUpLocalization::PopUpLocalizationTest.tes tLocalizedPopup" ><![CDATA[Error: Timeout Occurred before expected event
                          at org.flexunit.internals.runners.statements::ExpectAsync/handleAsyncTimeOut()[/Users/dblegr os/Documents/workspace/flexunit/FlexUnit4/src/org/flexunit/internals/runners/statements/Ex pectAsync.as:317]
                          at flash.events::EventDispatcher/dispatchEventFunction()
                          at flash.events::EventDispatcher/dispatchEvent()
                          at org.flexunit.async::AsyncHandler/handleTimeout()[/Users/dblegros/Documents/workspace/flex unit/FlexUnit4/src/org/flexunit/async/AsyncHandler.as:175]
                          at flash.events::EventDispatcher/dispatchEventFunction()
                          at flash.events::EventDispatcher/dispatchEvent()
                          at flash.utils::Timer/tick()]]></failure></testcase>
                      <endOfTestRun/>

                      • 8. Re: Testing with PopUps?
                        bucpatr1 Level 2

                        I'll have to look more closely if I get time later, but from a quick glance at your code it looks like you are making your test responsible for way too much. If I understood what you are doing you want to test that some properties of your custom component are initialized correctly when it displayed in a PopUp. Since you are adding things to an Application, I'm assuming you want to test the behavior of your component in the context of a specific project ( as opposed to a more generic test to see how it behaves no matter where it is used). That means you should have something in your code that triggers the pop-up display, either a public method you can call or an event dispatch that triggers the pop-up. The test shouldn't know anything about the in-between steps, all it should do is simulate the user interaction or event dispatch that opens the pop-up and wait for an event that signals that your component is ready to be tested.

                         

                        So rather than manually creating the LocalizedPopup instance in your test you want to trigger the display and retrieve the instance to test either from the event your test is waiting on or from whatever class is responsible for opening and closing the pop-up; most likely the Application in your case.

                        • 9. Re: Testing with PopUps?
                          Rambo 007 Level 1

                          What's not shown by this test is that there is a specialized version of Application that's being used, and a specialed resource bundle that SHOULD pick up the locale from whatever is prevailing in the application.  The test is validating that the locale discovery mechanism is operating correclty when used in popups.  So, it's actually a reasonable test for that.  The issue is not that however -- it's that the components in the popup are not being instantiated for some strange reason.

                           

                          Can I ask what component you used for the parent of your popup?  I dont' think UIImpersonator is a component, so I'm curious what you specified.

                          • 10. Re: Testing with PopUps?
                            bucpatr1 Level 2

                            So what you are interested in testing is the behavior of the custom VBox component under different conditions. In that case what you are doing should work fine. application is the correct parent to use for the pop-up. I created a bunch of different tests that display a pop-up including one that exactly mimic the code you posted and they all seemed to work fine. If you simply run your application is it behaving correctly?

                            • 11. Re: Testing with PopUps?
                              bucpatr1 Level 2

                              Also, what version of flexunit are you using? If you are actually running the test as it's posted here it should not even be getting to the test cases since Applications don't dispatch the APPLICATION_COMPLETE event when they are added using UIImpersonator.

                              • 12. Re: Testing with PopUps?
                                Rambo 007 Level 1

                                Well, now there's the $64k question.  It's 4.1.  And I'm using Flex 3.5.

                                 

                                What version are you using that's working?

                                • 13. Re: Testing with PopUps?
                                  Rambo 007 Level 1

                                  Also the switch to APPLICATION_COMPLETE was done just before I sent the code; previously, I'd been using CREATION_COMPLETE, but I thought I'd just double check with APP COMPLETE to make sure that absolutely everything had finished before I tried to create the popup.

                                  • 14. Re: Testing with PopUps?
                                    bucpatr1 Level 2

                                    I'm using flexunit 4.1 as well. I am using a newer version of the flex sdk but I don't think that would be an issue. Here is what my passing test method looks like:

                                     

                                           public var application:mx.core.Application;

                                     

                                            public var vbox:CustVBox;

                                     

                                            [Test(async, ui, timeout=12250)]
                                            public function newTest5():void
                                            {
                                                trace("test started");
                                                Assert.assertNotNull(application);
                                                vbox=new CustVBox();
                                                vbox.document=application;
                                                vbox.addEventListener(FlexEvent.UPDATE_COMPLETE, Async.asyncHandler(this, handleTest5Complete, 5000));
                                                PopUpManager.addPopUp(vbox, application);
                                            }

                                     

                                            protected function handleTest5Complete(event:Event, passThroughData:Object):void
                                            {
                                                Assert.assertNotNull(vbox);
                                                Assert.assertNotNull(vbox.label1);
                                                Assert.assertEquals("foo", vbox.label1.text);
                                                trace("label: " + vbox.label1);
                                                trace("test completed");
                                            }

                                    1 person found this helpful
                                    • 15. Re: Testing with PopUps?
                                      Rambo 007 Level 1

                                      Maybe it IS the new Flex SDK (you're in the 4 series, right?).  I've tried your example, and even that does not work.  I've tried messing around with the outer test runner, making the run start on updateComplete instead of creationComplete, and nothing seems to work. I think there were changes in Flex 4 around how popups and global layers work in general, so maybe it works for you because of that.

                                       

                                      I'm just using CIListener for my tests, since these need to run standalone in Hudson/Jenkins:

                                       

                                      <?xml version="1.0" encoding="utf-8"?>
                                      <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
                                         creationComplete="runTests();"
                                         layout="absolute">
                                        
                                         <mx:Script>
                                            <![CDATA[
                                               import org.flexunit.listeners.CIListener;
                                               import org.flexunit.runner.FlexUnitCore;
                                              
                                               import com.dorado.generated.flex.flexunit.TestRunnerTests;

                                               public function runTests() : void {
                                                      var core : FlexUnitCore = new FlexUnitCore();
                                           
                                                      core.addListener(new CIListener());
                                                     
                                                  core.run(TestRunnerTests.ALL_TESTS);
                                               }

                                           ]]>
                                         </mx:Script>
                                      </mx:Application>

                                      • 16. Re: Testing with PopUps?
                                        bucpatr1 Level 2

                                        Good news, I think I have a solution for you. I tried doing the test on a project built with the 3.5 sdk and it behaved as you described. They application it self was working but it would fail when run in the test. The problem seems to be that line where you assign application as the document of your component. Not sure why exactly but as soon as I removed that line the test started working. Hope that helps.

                                        1 person found this helpful
                                        • 17. Re: Testing with PopUps?
                                          Rambo 007 Level 1

                                          That's awesome news -- both that it's a 3.5 problem (and will be fixed in 4.x), and that there is a way to work around it.  I'll have to look at my upward display list traversal code to see if it can be adapted to use something other than the document chain (when it hits the root popup, whose parent is I think SystemManager, it applies a strategy to "jump" over to something else to continue up the hierarchy.).

                                           

                                          I'll look at the 3.5 Flex code also to see why this is behaviing this way; perhaps there are assumptions about having the document set that implies initialized() has been called?

                                           

                                          Thank you VERY MUCH for all your patient help!!!  I really appreciate it!