qUnit Testing
Required Files
Sample test of an older version of Expander
/*
Logical FSM
state event new state
Expanded collapse Collapsed
Collapsed expand Expanded
Initial state = Collapsed
The machine simply toggles between the 2 states.
HTML Model of Logical FSM
1. The element with class expander-header is the sole component of the FSM.
2. States
Collapsed == hasClass('expander-header-collapsed')
Expanded == ! hasClass('expander-header-collapsed')
i.e. presence or absence of .expander-header-collapsed determines mcahine state.
3. Transisions
A 'click' on the element toggles the state of the machine.
Expanded + click fires a collapseEvent
Collapsed + click firea a expandEvent
*/
/* NOTE - this test checks both expander-header and expander-content */
test("initially collapsed", function() {
ok( $('.expander-header')
.hasClass('expander-collapsed'));
ok( expanderInvariant() );
});
test("Collapsed to Expanded transition", function() {
ok( expanderInvariant() );
// put element into Collapsed state
$('.expander-header').add('expander-content')
.addClass('expander-collapsed');
$('.expander-header')
.trigger('click');
// test for Expanded state. No need to test .expander-content since class
// invariant ensure that .expander-content matches .expander-header
ok( ! $('.expander-header')
.hasClass('expander-collapsed'));
ok( expanderInvariant() );
});
test("Expanded to Collapsed transition", function() {
ok( expanderInvariant() );
// put element into Expanded state
$('.expander-header').add('.expander-content')
.removeClass('expander-collapsed');
$('.expander-header')
.trigger('click');
// test for Collapsed state
ok( $('.expander-header').hasClass("expander-collapsed"));
ok( expanderInvariant() );
});
function expanderInvariant() {
// Each expander-header must be immediately followed by an expander-content
// (or have no next() sibling & either both expander-header and expander-content
// have class expander-collapsed or neither of them have it.
$('.expander-header').each( function() {
ok($(this).next().hasClass('expander-content'));
ok(iff($(this).hasClass('expander-collapsed')
,$(this).next().hasClass('expander-collapsed')));
});
return true;
};
// TODO - type checking. Expect boolean inputs.
function iff(p1,p2) {
if(p1) return p2;
return !p2;
}