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; }