Developing your own ExtJS components for your application is more fun and results into more resilient code if you write them hand-in-hand with test code. A solid test basis can also facilitate the task of refactoring your software.

Although, test driven development is easy for javascript code, how can ExtJS 3.4 components be tested? Which parts of our components should be tested to accomplish a successful refactoring?



First a glimpse at Ext JS’ component hierarchy might be worthwhile.

ExtJS 3.4 component hierarchy

Some of the most common components in an ExtJS application are panels. Their hierarchy looks like this:

First there’s the observable level that handles events and communication between components.

Second there’s the component level that’s responsible for a component’s rendering and it’s configuration.

And third there’s the container level that maintains the component layouting.

In summary, the component hierarchy points out the main testable areas of our code: events, configuration and structure.

What kind of tests make sense?

As we want to make our components stable for refactoring we should concentrate on testing their main features related to the above mentioned hierarchy levels. To write behavior driven tests, we follow the current ExtJS 4.x practice and use Jasmine as our test framework.

Example

For the accomplishment of the following task we used Karma as our test runner. First, let’s assume we have written a simple grid panel from xtype “mayday-gridpanel” which contains two columns: „id“ and „name“. Here’s our test setup:



describe("JsonGridPanel test", function () { var panel; beforeEach(function () { panel = Ext.create({ id: 'testGridPanel', xtype: 'mayday-gridpanel', title : 'test panel title', renderTo: Ext.getBody(), width: 500, height: 300 }); panel.doLayout(); }); afterEach(function () { panel.destroy(); }); });

beforeEach()

show()

doLayout()

Starting with the interesting part let’s have a look at theblock. Our tests are fine with a completely layouted component only. This ensures a fully built component including all children. For the actual rendering of the component just useinstead of

We begin testing if this panel has a certain project specific base class (“maydayGrid” in our example). This would be a test case for the component’s default configuration at it’s component level:



it('should have the correct base class', function () { expect(panel.baseCls).toBe('maydayGrid'); });

it('grid should have correct amount of columns', function () { expect(panel.getColumnModel().getColumnCount()).toBe(2); });

rowclick

it('row click event should be handled correctly', function () { //load data var jsonData = { rows: [ {recordId : 1, recordName : 'first_item'}, {recordId : 2, recordName : 'second_item'}, {recordId : 3, recordName : 'third_item'} ], totalCount: 3 }; panel.getStore().loadData(jsonData); //simulate event panel.fireEvent('rowclick', panel, 1, Ext.EventObject); expect(panel.getStore().getAt(1).get('name')).toBe('i was clicked'); });

Summary

The next thing we want to test is the structure of our grid panel. It should always have those two columns. Such a tests covers the behavior of the component’sFinally, we want to write a test for the. Let’s say that every time a row in the grid is clicked, we want to change the value of the name column to “i was clicked”. In the test we first need to load some fixture data to our grid. To simulate the row click, we simply fire the correspondingevent. Afterwards we check that the clicked row has the value “i was clicked” in it’s name column:

As you can see in the Jasmine documentation you can go as much into detail as you wish when you want to test your ExtJS components. But you always have to think twice if a certain test is really necessary for testing you component’s behavior, or if it just tests internal properties or methods that might be changed or removed in a refactoring.