Hey all, I'm working on a unit testing framework for unit testing javascript abstractions that run in browsers: domunit.
https://github.com/GarrettS/ape-javascript-library/downloads The framework uses declarative style object literals for testing; each test is property name that starts with "test". A test case has an optional setUp and tearDown. After incljuding domunit.js, you write a test case, like so: var testCase = { setUp : function() { }, tearDown : function() {}, "test Number.prototype.valueOf" : function() { var actual = new Number(1).valueOf(); TestRunner.assert( Constraints.areSame(actual, 1) ); } }; And then: runTests( testCase ); - or - runTests( [testCase1, testCase2, testCas3] ); Each test requires at least one call to TestRunner.assert unless you call `TestRunner.exitEarly`. TestRunner.exitEarly is intended to provide results to the reports. The TestReporter doesn't currently report early exits, but the idea is that when you have a test that needs to verify a condition that exists in certain environments, that you can expect one assertion, but in environment that don't support whatever it is you want to test, you can exit early. testSrcElement : function() { var srcElement; function clickHandler() { srcElement = window.event && window.event.srcElement || null; } document.onclick = clickHandler; Mouse.click( document ); if(! ev ) { TestRunner.exitEarly( "window.event.srcElement not supported in this environment."); } TestRunner.assert( Constraints.areSame(srcElement, document) ); } TestRunner.assert takes a function. So for example, `Constraints.isTrue( true )` is a function call that returns a function. This way, you can write as many of your own constraints as you want, e.g. `TestRunner.assert( Canvas.hasImage( img ) );` `TestRunner.assert` will call the constraint function that it is passed. If that constraint function returns a non-empty string, then it is treated as an error message and `assert` throws, causing the test to fail. TestRunner also has `wait` and `waitForCondition` methods. testCrap : function() { TestRunner.wait( function() { TestRunner.assert( Constraints.isTrue( true ) ); }, 10); }, ... "test ajax response correct" : function() { var done; ajax.oncomplete = function() { done = true; }; function ajaxDone() { return done; } function verifyResponse() { TestRunner.assert(Constraints.areSame( ajax.responseText, "1") ); } TestRunner.waitForCondition( ajaxDone, verifyResponse ); }, Additionally, there's ways to simulate mouse events using declarative style: Mouse.click( document, {clientX : 10, shiftKey : true } ) - with sensible defaults, e.g. when `altKey` is omitted, it is `false`, when `bubbles` is omitted, `bubbles` is true, etc. Though `event.button` has a sensible default `0`, that propagates a w3c mistake of event.button === 0 being specified to mean that the left mouse button is depressed -- but there is no code for when no button is depressed. When no button is depressed, `event.button` returns `0`, which is the same value used to indicate left button. So `event.button === 0` means either left button or no button. Seems like a glaring oversight to me. There is also the sore spot of not being able to set the `toElement` or `fromElement in MSIE. I already posted about that on the jsmentors mailing list, when it was a good mailing list, and before the whole thing moved to GG. Anyway, there's other complexities that I was able to solve nicely. domunit's free to download and use. Go download it and start testing.I hope you like it. -- Garrett -- To view archived discussions from the original JSMentors Mailman list: http://www.mail-archive.com/[email protected]/ To search via a non-Google archive, visit here: http://www.mail-archive.com/[email protected]/ To unsubscribe from this group, send email to [email protected]
