Introduction

Many of us know we should be using test first development, however it is hard to break old habits.  I have to admit, I started to solve this particular problem I’m going to use an an example first without test first, then realized what a pickle I was going to be in proving to myself it worked.  So, I thought, why not blog my experience as I do it.  Using Visual Studio unit testing makes this pretty easy.

 

The Problem

I’m currently building a multithreaded email processor and part of that process is I have to figure out, for any given use whether they are supposed to have there email server checked.  So, the way I look at it, I need a method that takes in the following parameter.

    1. Now – This is actually todays date and time in UTC, but since this method need to be tested, I’m going to pass in now rather just use it directly.
    2. LastActivityOfUserDateTime – This is the last time we saw any activity for this user.
    3. LastEmailSession – This is when the email session was last run (server check).
    4. DefaultSecondsForLastActivityTreshold – This is used to determine weather the user last activity makes that user considered active or inactive.  That is, say this is 60 seconds.  Then, if the user has been active in the last 60 seconds, then this user is considered active.
    5. DefaultSecondsBetweenEmailRetryOutsideThreshold – If the user is not active (as defined by DefaultSecondsForLastActivityTreshold) then this is the number of seconds we should wait before we should try and contact the users email server again.
    6. DefaultSecondsBetweenEmailRetryInsideThreshold – If the user is active (as defined by DefaultSecondsForLastActivityTreshold) then this is the number of seconds we should wait before we should try and contact the users email server again.

Given these 4 parameters, we should write a method that returns a Boolean indicating weather the mail server needs to be rechecked for a given user.

 

The Method To Test

So, let’s write a method signature.  We will use this in our real project, then write some tests to see if it works correctly.  We have not written the actual method yet, we are just defining what it does, then first, very important, writing the tests to prove it will work.  This way, as we add all the corner cases, we can keep making sure the original cases we programmed have not broken.

So, here is how I see the class definition:

public bool IsUserReadyToContactEmailServer(DateTime currentDateTime,
            DateTime lastActivityOfUserDateTime,
            DateTime lastEmailSession,
            int defaultSecondsForLastActivityTreshold,
            int defaultSecondsBetweenEmailRetryOutsideThreshold,
            int defaultSecondsBetweenEmailRetryInsideThreshold)
        {
            bool activeUser = IsUserCurrentlyActive(currentDateTime, lastActivityOfUserDateTime,
                                                      defaultSecondsForLastActivityTreshold);
            int thresholdForRetrySeconds =
                activeUser
                    ? defaultSecondsBetweenEmailRetryInsideThreshold
                    : defaultSecondsBetweenEmailRetryOutsideThreshold;

            // this has to be a double because could be huge number if last email send very long ago
            double timeSinceLastEmailSessionSeconds =
                currentDateTime.Subtract(lastEmailSession).TotalSeconds;

           return timeSinceLastEmailSessionSeconds > thresholdForRetrySeconds;
        }

Creating a Test Project In Visual Studio 2011 Preview

Now that we have our method we want to test, let’s create a test project.  This is very straight forward.  We first just say “File/New Project” then choose “Unit Test Project”.

 

image

 

I’m going to simply create a method called TestMethodIsUserReadyToContactEmailServer().

using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace AEWeb.Tests
{
    [TestClass]
    public class UnitTest1
    {
        [TestMethod]
        public void TestMethodIsUserReadyToContactEmailServer()
        {
        }
    }
}

Now, we need to add some guts.  There is an automated way to create the actual test stubs, but at the moment I can’t seem to find it.  In this case, we really just need to test a bunch of corner cases so let’s code the tests up. Below are the tests I’ve come up with including comments that make them self explanatory.

So, as I’m creating my tests, I realize I need to create an extra class to help this one.  That is specifically, I need to add a method that simply determines if the user is currently active.  I’m going to call that IsCurrentlyActive and have it take three paramaters.  currentDateTime, DefaultSecondsForLastActivityThreshold and usersLastActivityDate.  I realized this because solving the full problem of figuring out if the user is ready to sync email is to complex in one step.

If I were developing this without unit tests, I would have figured the same thing out, but then as I built it, I would not be verifying it’s correctness with testing.

Creating Stub Classes

So, my new class I want to test will be this:

 /// <summary>
        /// This really just a supporting method for the above IsUserReadyToContactEmailServer call
        /// </summary>
        /// <param name="currentDateTime">Current datetime (for testing can be anything)</param>
        /// <param name="usersLastActivityDate">time user was last seen </param>
        /// <param name="defaultSecondsForLastActivityTreshold">our definition of what makes a user currently active</param>
        /// <returns></returns>
        public bool IsUserCurrentlyActive(DateTime currentDateTime,
            DateTime usersLastActivityDate,
            int defaultSecondsForLastActivityTreshold
            )
        {

            return true;
        }

The Unit Tests Themselves

So, now is time to actually write the tests.  I’m not going to explain here all the mechanics of testing.  I assume you understand the basics are you right calls to methods, then make assertions for correctness.  If the assertion is wrong, then print that message and of course the test fails.

So, Here are my test cases for just the helper method (IsUserCurrentlyActive).

using System;
using AELib;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace AEWeb.Tests
{
    [TestClass]
    public class UnitTestEmailReadyCheck
    {

        [TestMethod]
        public void UnitTestRecentActivity()
        {
            {
                // a long time ago
                var currentDateTime = new DateTime(2012, 3, 1, 12, 0, 0); // assume current time is 3/1/2012 at noon
                var lastActivityOfUserDateTime = new DateTime(2012, 2, 1, 12, 0, 0);
                // last activity was a month ago, 2/1/2012 at noon
                // threshhold for calling a user active
                const int defaultSecondsForLastActivityTreshold = 60*15; // let's call this 15 minute threshhold
                bool isActive = new MailServerReadyCheck().
                    IsUserCurrentlyActive(currentDateTime, lastActivityOfUserDateTime,
                                          defaultSecondsForLastActivityTreshold);
                Assert.IsFalse(isActive,
                               "User Should Be Inactive because last activity was 1 month ago and threshhold is 15 minutes");
            }
        }

        [TestMethod]
        public void UnitTestNoRecentActivity()
        {
            // a just inside threshold
            var currentDateTime = new DateTime(2012, 3, 1, 12, 0, 0); // assume current time is 3/1/2012 at noon
            var lastActivityOfUserDateTime = new DateTime(2012, 3, 1, 11, 55, 0);
            // last activity was 5 minutes before noon on 2/1/2012
            // threshhold for calling a user active
            const int defaultSecondsForLastActivityTreshold = 60*15; // let's call this 15 minute threshhold
            bool isActive = new MailServerReadyCheck().
                IsUserCurrentlyActive(currentDateTime, lastActivityOfUserDateTime,
                                      defaultSecondsForLastActivityTreshold);
            Assert.IsTrue(isActive,
                          "User Should Be active because last activity was 5 minutes ago and threshhold is 15 minutes");
        }

        [TestMethod]
        public void UnitTestCurrentDateBehindActivity()
        {
            // impossible cause of last activity being after current time. just need to
            // make sure it returns true and does not crash
            var currentDateTime = new DateTime(2012, 3, 1, 12, 0, 0); // assume current time is 3/1/2012 at noon
            var lastActivityOfUserDateTime = new DateTime(2012, 3, 1, 18, 0, 0);
            // last activity was 5 minutes after noon on 2/1/2012
            // threshhold for calling a user active
            const int defaultSecondsForLastActivityTreshold = 60*15; // let's call this 15 minute threshhold
            bool isActive = new MailServerReadyCheck().
                IsUserCurrentlyActive(currentDateTime, lastActivityOfUserDateTime,
                                      defaultSecondsForLastActivityTreshold);
            Assert.IsTrue(isActive,
                          "User Should Be active because last activity was 5 minutes after current time");
        }
    }
}

 

Then, I write the actual method:

 

       /// <summary>
        /// This really just a supporting method for the above IsUserReadyToContactEmailServer call
        /// </summary>
        /// <param name="currentDateTime">Current datetime (for testing can be anything)</param>
        /// <param name="usersLastActivityDate">time user was last seen </param>
        /// <param name="defaultSecondsForLastActivityTreshold">our definition of what makes a user currently active</param>
        /// <returns></returns>
        public bool IsUserCurrentlyActive(DateTime currentDateTime,
            DateTime usersLastActivityDate,
            int defaultSecondsForLastActivityTreshold
            )
        {
            int secondsSinceLastActivity = Convert.ToInt32(currentDateTime.Subtract(usersLastActivityDate).TotalSeconds);
            bool activeStatus = defaultSecondsForLastActivityTreshold > secondsSinceLastActivity;
            return activeStatus;
        }

And finally, run the test (skipping a little debugging to make them all work)

Presto!

 

image

 

For completeness, I’m pasting the full unit test for the other main class I’m interested in testing below (as well as the class itself), however I won’t go into all the details.  Everything is basically the same, just more of it

 

Conclusions and Observations

Turns out, this was quite a bit of work to generate all these tests.  At first pass, I can hear someone saying it seems like a lot to do just for two fairly simple methods.  My answer is that I struggled trying to get it right until I finally decided to write the tests.  Now, I’m confident it works correctly.  What is more, if there is a bug in my algorithm, or something else comes up I need to include (which is very likely) I now have a great way to prove to myself (and others) that my class works.  Also, this serves as great documentation for what expectations are for this very important function.

 

Appendex – Full Unit Test And Class Source

 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace AELib
{
    public class MailServerReadyCheck
    {
        /// <summary>
        /// 
        /// </summary>
        /// <param name="currentDateTime">This is actually todays date and time in UTC, but since 
        ///    this method need to be tested, I’m going to pass in now rather just use it directly</param>
        /// <param name="lastActivityOfUserDateTime"> This is used to determine weather the user last activity
        ///      makes that user considered active or inactive.  That is, say this is 60 seconds.
        ///      Then, if the user has been active in the last 60 seconds, then this user is considered active.</param>
        /// <param name="lastEmailSession">When the last email completed for this user</param>
        /// <param name="defaultSecondsForLastActivityTreshold">This is used to determine weather the user last activity makes that 
        ///      user considered active or inactive.  That is, say this is 60 seconds.  Then, if the user has 
        ///      been active in the last 60 seconds, then this user is considered active.</param>
        /// <param name="defaultSecondsBetweenEmailRetryOutsideThreshold"> If the user is not active (as defined by 
        ///      DefaultSecondsForLastActivityTreshold) then this is the number of seconds we should wait before 
        ///      we should try and contact the users email server again.</param>
        /// <param name="defaultSecondsBetweenEmailRetryInsideThreshold">If the user is active (as defined by 
        ///      DefaultSecondsForLastActivityTreshold) then this is the number of seconds we should wait 
        ///      before we should try and contact the users email server again.</param>
        /// <returns>returns a boolean indicating weather the mail server needs to be rechecked for a given user.</returns>
        public bool IsUserReadyToContactEmailServer(DateTime currentDateTime,
            DateTime lastActivityOfUserDateTime,
            DateTime lastEmailSession,
            int defaultSecondsForLastActivityTreshold,
            int defaultSecondsBetweenEmailRetryOutsideThreshold,
            int defaultSecondsBetweenEmailRetryInsideThreshold)
        {
            bool activeUser = IsUserCurrentlyActive(currentDateTime, lastActivityOfUserDateTime,
                                                      defaultSecondsForLastActivityTreshold);
            int thresholdForRetrySeconds =
                activeUser
                    ? defaultSecondsBetweenEmailRetryInsideThreshold
                    : defaultSecondsBetweenEmailRetryOutsideThreshold;

            // this has to be a double because could be huge number if last email send very long ago
            double timeSinceLastEmailSessionSeconds =
                currentDateTime.Subtract(lastEmailSession).TotalSeconds;

           return timeSinceLastEmailSessionSeconds > thresholdForRetrySeconds;
        }

        /// <summary>
        /// This really just a supporting method for the above IsUserReadyToContactEmailServer call
        /// </summary>
        /// <param name="currentDateTime">Current datetime (for testing can be anything)</param>
        /// <param name="usersLastActivityDate">time user was last seen </param>
        /// <param name="defaultSecondsForLastActivityTreshold">our definition of what makes a user currently active</param>
        /// <returns></returns>
        public bool IsUserCurrentlyActive(DateTime currentDateTime,
            DateTime usersLastActivityDate,
            int defaultSecondsForLastActivityTreshold
            )
        {
            int secondsSinceLastActivity = Convert.ToInt32(currentDateTime.Subtract(usersLastActivityDate).TotalSeconds);
            bool activeStatus = defaultSecondsForLastActivityTreshold > secondsSinceLastActivity;
            return activeStatus;
        }
    }
}

And the tests…

 

using System;
using AELib;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace AEWeb.Tests
{
    [TestClass]
    public class UnitTestEmailReadyCheck
    {

        ///////////////////// IsUserCurrentlyActive follows

        [TestMethod]
        public void UnitTestRecentActivity()
        {
            {
                // a long time ago
                var currentDateTime = new DateTime(2012, 3, 1, 12, 0, 0); // assume current time is 3/1/2012 at noon
                var lastActivityOfUserDateTime = new DateTime(2012, 2, 1, 12, 0, 0);
                // last activity was a month ago, 2/1/2012 at noon
                // threshhold for calling a user active
                const int defaultSecondsForLastActivityTreshold = 60*15; // let's call this 15 minute threshhold
                bool isActive = new MailServerReadyCheck().
                    IsUserCurrentlyActive(currentDateTime, lastActivityOfUserDateTime,
                                          defaultSecondsForLastActivityTreshold);
                Assert.IsFalse(isActive,
                               "User Should Be Inactive because last activity was 1 month ago and threshhold is 15 minutes");
            }
        }

        [TestMethod]
        public void UnitTestNoRecentActivity()
        {
            // a just inside threshold
            var currentDateTime = new DateTime(2012, 3, 1, 12, 0, 0); // assume current time is 3/1/2012 at noon
            var lastActivityOfUserDateTime = new DateTime(2012, 3, 1, 11, 55, 0);
            // last activity was 5 minutes before noon on 2/1/2012
            // threshhold for calling a user active
            const int defaultSecondsForLastActivityTreshold = 60*15; // let's call this 15 minute threshhold
            bool isActive = new MailServerReadyCheck().
                IsUserCurrentlyActive(currentDateTime, lastActivityOfUserDateTime,
                                      defaultSecondsForLastActivityTreshold);
            Assert.IsTrue(isActive,
                          "User Should Be active because last activity was 5 minutes ago and threshhold is 15 minutes");
        }

        [TestMethod]
        public void UnitTestCurrentDateBehindActivity()
        {
            // impossible cause of last activity being after current time. just need to
            // make sure it returns true and does not crash
            var currentDateTime = new DateTime(2012, 3, 1, 12, 0, 0); // assume current time is 3/1/2012 at noon
            var lastActivityOfUserDateTime = new DateTime(2012, 3, 1, 18, 0, 0);
            // last activity was 5 minutes after noon on 2/1/2012
            // threshhold for calling a user active
            const int defaultSecondsForLastActivityTreshold = 60*15; // let's call this 15 minute threshhold
            bool isActive = new MailServerReadyCheck().
                IsUserCurrentlyActive(currentDateTime, lastActivityOfUserDateTime,
                                      defaultSecondsForLastActivityTreshold);
            Assert.IsTrue(isActive,
                          "User Should Be active because last activity was 5 minutes after current time");
        }

        ///////////////////// IsUserReadyToContactEmailServer follows

        [TestMethod]
        public void UnitTestIsUserReadyToContactEmailServerLongTimeAgoUserInActive()
        {
            // let's use these parameters for every test

            // let's call this 30 minute threshhold. no contact within 30 minutes, than user is inactive
            const int defaultSecondsForLastActivityTreshold = 60 * 30;

            // if active user, check email every 2 minutes
            const int defaultSecondsBetweenEmailRetryInsideThreshold = 60 * 2;

            // if inactive user, check email every 20 minutes
            const int defaultSecondsBetweenEmailRetryOutsideThreshold = 60 * 20; 

            // user checked email 5 hours ago and email has not been run for 3 hours
            var currentDateTime = new DateTime(2012, 3, 1, 12, 0, 0); // assume current time is 3/1/2012 at noon
            var lastEmailSessionDateTime = new DateTime(2011,3,1,2, 0, 0); // email session 2am of 1 year ago (very long ago)
            var lastActivityOfUserDateTime = new DateTime(2011, 3, 1, 7, 0, 0); // user checked email at 7am a year ago

            bool emailSessionNeeded = new MailServerReadyCheck().IsUserReadyToContactEmailServer(currentDateTime,
                lastActivityOfUserDateTime,lastEmailSessionDateTime,defaultSecondsForLastActivityTreshold,
                defaultSecondsBetweenEmailRetryOutsideThreshold,
                defaultSecondsBetweenEmailRetryInsideThreshold);

            Assert.IsTrue(emailSessionNeeded,
                          "user checked email 5 hours ago and email has not been run for 3 hours. Should have needed email session");
        }

        [TestMethod]
        public void UnitTestIsUserReadyToContactEmailServerLongTimeAgoUserActive()
        {
            // let's use these parameters for every test
            // let's call this 30 minute threshhold. no contact within 30 minutes, than user is inactive
            const int defaultSecondsForLastActivityTreshold = 60 * 30;

            // if active user, check email every 2 minutes
            const int defaultSecondsBetweenEmailRetryInsideThreshold = 60 * 2;

            // if inactive user, check email every 20 minutes
            const int defaultSecondsBetweenEmailRetryOutsideThreshold = 60 * 20;

            // user checked email 1 minute ago and email has not been run for 3 hours
            var currentDateTime = new DateTime(2012, 3, 1, 12, 0, 0); // assume current time is 3/1/2012 at noon
            var lastEmailSessionDateTime = new DateTime(2011, 3, 1, 2, 0, 0); // email session 2am of 1 year ago (very long ago)
            var lastActivityOfUserDateTime = new DateTime(2012, 3, 1, 11, 59, 0); // user checked email 1 minute ago

            bool emailSessionNeeded = new MailServerReadyCheck().IsUserReadyToContactEmailServer(currentDateTime,
                lastActivityOfUserDateTime, lastEmailSessionDateTime, defaultSecondsForLastActivityTreshold,
                defaultSecondsBetweenEmailRetryOutsideThreshold,
                defaultSecondsBetweenEmailRetryInsideThreshold);

            Assert.IsTrue(emailSessionNeeded,
                          "user checked email  1 minute ago and email not been run for 1 year. should have run email again");
        }

        [TestMethod]
        public void UnitTestIsUserReadyToContactEmailServerRecentlyUserActive()
        {
            // let's use these parameters for every test
            // let's call this 30 minute threshhold. no contact within 30 minutes, than user is inactive
            const int defaultSecondsForLastActivityTreshold = 60 * 30;

            // if active user, check email every 2 minutes
            const int defaultSecondsBetweenEmailRetryInsideThreshold = 60 * 2;

            // if inactive user, check email every 20 minutes
            const int defaultSecondsBetweenEmailRetryOutsideThreshold = 60 * 20;

            // user checked email 1 minute ago and email has not been run for 3 hours
            var currentDateTime = new DateTime(2012, 3, 1, 12, 0, 0); // assume current time is 3/1/2012 at noon
            var lastEmailSessionDateTime = new DateTime(2012, 3, 1, 11, 50, 0); // email session 10 minutes ago
            var lastActivityOfUserDateTime = new DateTime(2012, 3, 1, 11, 59, 0); // user checked email 1 minute ago

            bool emailSessionNeeded = new MailServerReadyCheck().IsUserReadyToContactEmailServer(currentDateTime,
                lastActivityOfUserDateTime, lastEmailSessionDateTime, defaultSecondsForLastActivityTreshold,
                defaultSecondsBetweenEmailRetryOutsideThreshold,
                defaultSecondsBetweenEmailRetryInsideThreshold);

            Assert.IsTrue(emailSessionNeeded,
                          "active user, email checked 10 minutes ago but since active should check again");
        }

        [TestMethod]
        public void UnitTestIsUserReadyToContactEmailServerRecentlyUserInActive()
        {
            // let's use these parameters for every test
            // let's call this 30 minute threshhold. no contact within 30 minutes, than user is inactive
            const int defaultSecondsForLastActivityTreshold = 60 * 30;

            // if active user, check email every 2 minutes
            const int defaultSecondsBetweenEmailRetryInsideThreshold = 60 * 2;

            // if inactive user, check email every 20 minutes
            const int defaultSecondsBetweenEmailRetryOutsideThreshold = 60 * 20;

            // user checked email 1 minute ago and email has not been run for 3 hours
            var currentDateTime = new DateTime(2012, 3, 1, 12, 0, 0); // assume current time is 3/1/2012 at noon
            var lastEmailSessionDateTime = new DateTime(2012, 3, 1, 11, 50, 0); // email session 10 minutes ago
            var lastActivityOfUserDateTime = new DateTime(2011, 3, 1, 11, 59, 0); // user checked email 1 year ago

            bool emailSessionNeeded = new MailServerReadyCheck().IsUserReadyToContactEmailServer(currentDateTime,
                lastActivityOfUserDateTime, lastEmailSessionDateTime, defaultSecondsForLastActivityTreshold,
                defaultSecondsBetweenEmailRetryOutsideThreshold,
                defaultSecondsBetweenEmailRetryInsideThreshold);

            Assert.IsFalse(emailSessionNeeded,
                          "inactive user, but email checked very recently so should not be checking again");
        }

        [TestMethod]
        public void UnitTestIsUserReadyToContactEmailServerEmailLastSession10MinutesagoActive()
        {
            // let's use these parameters for every test
            // let's call this 30 minute threshhold. no contact within 30 minutes, than user is inactive
            const int defaultSecondsForLastActivityTreshold = 60 * 30;

            // if active user, check email every 2 minutes
            const int defaultSecondsBetweenEmailRetryInsideThreshold = 60 * 2;

            // if inactive user, check email every 20 minutes
            const int defaultSecondsBetweenEmailRetryOutsideThreshold = 60 * 20;

            // user checked email 1 minute ago and email has not been run for 3 hours
            var currentDateTime = new DateTime(2012, 3, 1, 12, 0, 0); // assume current time is 3/1/2012 at noon
            var lastEmailSessionDateTime = new DateTime(2012, 3, 1, 1, 11, 50); // email session 10 minutes ago
            var lastActivityOfUserDateTime = new DateTime(2011, 3, 1, 11, 59, 0); // user checked email 5 minutes ago

            bool emailSessionNeeded = new MailServerReadyCheck().IsUserReadyToContactEmailServer(currentDateTime,
                lastActivityOfUserDateTime, lastEmailSessionDateTime, defaultSecondsForLastActivityTreshold,
                defaultSecondsBetweenEmailRetryOutsideThreshold,
                defaultSecondsBetweenEmailRetryInsideThreshold);

            Assert.IsTrue(emailSessionNeeded,
                          "active user, but email checked very recently so should be checking again");
        }

    }
}

 

And the results of all tests running Smile

image

 

And, if you are still reading, I’ve got 100% of these two methods covered from these unit tests using Code Coverage.

 

image

 

 

 

I do not even want to admit how much time I spent today in a more complex application trying to get a button to respond to a tap event in SenchaTouch 2.0 Beta.  I did notice several people like me on the forums with similar issues, but I did not find one concrete example that made the simple “click a button application”.  Of course I’m building this in Microsoft Visual Studio 2010 and debugging with Chrome.  Let me start at the end.  When you are done, you will have a simple two button page that you can click on either button and have your MVC controller react to either button as well as trap the button hit inside the actual Panel.

 

image

 

And for those of you that have read enough, here is the source:  

 

 

The Nitty Gritty

Creating an SenchaTouch project with MVC is a little tricky to setup.  You need to get all the directories right.  My favorite way to do this is to use the Sencha Designer to create the project, then abandon it if I want to strike out on my own.  That is what I’ve done here.  I don’t even think you can tell.

Here is the file layout as seen from Visual Studio:

image

5 Files and 3 directories.

Let’s first take a look at the Panel that contains the buttons.  Here is the code:

Ext.define('MyApp.view.MyPanel', {
    extend: 'Ext.Panel',
    alias: 'widget.mypanel',
    config: {
        items: [
            {
                xtype: 'button',
                itemId: 'mybutton1',
                text: 'MyButton1',
                action: 'b1'
            },
            {
                xtype: 'button',
                itemId: 'mybutton2',
                text: 'MyButton2',
                action: 'b2'
            }
        ],

        listeners: [
            {
                fn: 'onMybutton1Tap',
                event: 'tap',
                delegate: '#mybutton1'
            }
        ]
    },
    onMybutton1Tap: function (button, e, options) {
        console.log('tap from mybutton1');
    }
});

Just a couple things to notice.  1) I’m defining an itemId which we will only be using in the local event (onMybutton1Tap).  If you notice the listener has a property delegate which looks for that.  I’m not sure if this is the best way to do this.  I’ve notice several forum people saying use the “on” syntax.  I did not find an example of that so this is what we have and it works.  Also notice the action property.  If you try and look that up on the SenchaTouch doc’s you will not find it.  I just made it up out of thin air (really!, well, I followed others examples).  I actually asked about this in the forums and I was told that is OK.  As a type safe language guy, it hurts, but I did it.

 

That’s it for the view.  Let’s move over to the controller.  Here is the source for that:

Ext.define('MyApp.controller.MyController', {
    extend: 'Ext.app.Controller',

    views: [
        'MyPanel'
    ],

    refs: [
        {
            ref: 'MyPanel',
            selector: 'mypanel'
        }],

    init: function () {

        this.control({
            'button[action=b1]': {
                tap: this.onButtonTap1
            },
            'button[action=b2]': {
                tap: this.onButtonTap2
            }
        });
    },

    onLaunch: function () {
        console.log('onLaunch');
    },

    onButtonTap1: function () {
        console.log('controller: onButtonTap1');
    },

    onButtonTap2: function () {
        console.log('controller: onButtonTap2');
    },

    config: {

    }
});

Basically, what this is doing is filtering all buttons, then looking at just the buttons that have an action of b1 or b2.  If this was a large application, we’d probably want to do some more fancy component querying, but for now, this is OK.  If you keep your controllers small, this should always work.

 

That’s it for now.  Download the source and run it.  I hope it saves you a ton of time. 

As always any experts want to comment and improve or correct what I’ve done, please feel free to comment. 


© 2012 PeterKellner.net. All Rights Reserved
Follow

Get every new post delivered to your Inbox

Join other followers: