]>
jfr.im git - z_archive/KronOS.git/blob - video/public/js/unittest.js
1 // script.aculo.us unittest.js v1.9.0, Thu Dec 23 16:54:48 -0500 2010
3 // Copyright (c) 2005-2010 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
4 // (c) 2005-2010 Jon Tirsen (http://www.tirsen.com)
5 // (c) 2005-2010 Michael Schuerig (http://www.schuerig.de/michael/)
7 // script.aculo.us is freely distributable under the terms of an MIT-style license.
8 // For details, see the script.aculo.us web site: http://script.aculo.us/
10 // experimental, Firefox-only
11 Event
. simulateMouse = function ( element
, eventName
) {
12 var options
= Object
. extend ({
20 }, arguments
[ 2 ] || {});
21 var oEvent
= document
. createEvent ( "MouseEvents" );
22 oEvent
. initMouseEvent ( eventName
, true , true , document
. defaultView
,
23 options
. buttons
, options
. pointerX
, options
. pointerY
, options
. pointerX
, options
. pointerY
,
24 options
. ctrlKey
, options
. altKey
, options
. shiftKey
, options
. metaKey
, 0 , $( element
));
26 if ( this . mark
) Element
. remove ( this . mark
);
27 this . mark
= document
. createElement ( 'div' );
28 this . mark
. appendChild ( document
. createTextNode ( " " ));
29 document
. body
. appendChild ( this . mark
);
30 this . mark
. style
. position
= 'absolute' ;
31 this . mark
. style
. top
= options
. pointerY
+ "px" ;
32 this . mark
. style
. left
= options
. pointerX
+ "px" ;
33 this . mark
. style
. width
= "5px" ;
34 this . mark
. style
. height
= "5px;" ;
35 this . mark
. style
. borderTop
= "1px solid red;" ;
36 this . mark
. style
. borderLeft
= "1px solid red;" ;
39 alert ( '[' + new Date (). getTime (). toString ()+ '] ' + eventName
+ '/' + Test
. Unit
. inspect ( options
));
41 $( element
). dispatchEvent ( oEvent
);
44 // Note: Due to a fix in Firefox 1.0.5/6 that probably fixed "too much", this doesn't work in 1.0.6 or DP2.
45 // You need to downgrade to 1.0.4 for now to get this working
46 // See https://bugzilla.mozilla.org/show_bug.cgi?id=289940 for the fix that fixed too much
47 Event
. simulateKey = function ( element
, eventName
) {
48 var options
= Object
. extend ({
55 }, arguments
[ 2 ] || {});
57 var oEvent
= document
. createEvent ( "KeyEvents" );
58 oEvent
. initKeyEvent ( eventName
, true , true , window
,
59 options
. ctrlKey
, options
. altKey
, options
. shiftKey
, options
. metaKey
,
60 options
. keyCode
, options
. charCode
);
61 $( element
). dispatchEvent ( oEvent
);
64 Event
. simulateKeys = function ( element
, command
) {
65 for ( var i
= 0 ; i
< command
. length
; i
++) {
66 Event
. simulateKey ( element
, 'keypress' ,{ charCode : command
. charCodeAt ( i
)});
73 // security exception workaround
74 Test
. Unit
. inspect
= Object
. inspect
;
76 Test
. Unit
. Logger
= Class
. create ();
77 Test
. Unit
. Logger
. prototype = {
78 initialize : function ( log
) {
81 this . _createLogTable ();
84 start : function ( testName
) {
85 if (! this . log
) return ;
86 this . testName
= testName
;
87 this . lastLogLine
= document
. createElement ( 'tr' );
88 this . statusCell
= document
. createElement ( 'td' );
89 this . nameCell
= document
. createElement ( 'td' );
90 this . nameCell
. className
= "nameCell" ;
91 this . nameCell
. appendChild ( document
. createTextNode ( testName
));
92 this . messageCell
= document
. createElement ( 'td' );
93 this . lastLogLine
. appendChild ( this . statusCell
);
94 this . lastLogLine
. appendChild ( this . nameCell
);
95 this . lastLogLine
. appendChild ( this . messageCell
);
96 this . loglines
. appendChild ( this . lastLogLine
);
98 finish : function ( status
, summary
) {
99 if (! this . log
) return ;
100 this . lastLogLine
. className
= status
;
101 this . statusCell
. innerHTML
= status
;
102 this . messageCell
. innerHTML
= this . _toHTML ( summary
);
103 this . addLinksToResults ();
105 message : function ( message
) {
106 if (! this . log
) return ;
107 this . messageCell
. innerHTML
= this . _toHTML ( message
);
109 summary : function ( summary
) {
110 if (! this . log
) return ;
111 this . logsummary
. innerHTML
= this . _toHTML ( summary
);
113 _createLogTable : function () {
115 '<div id="logsummary"></div>' +
116 '<table id="logtable">' +
117 '<thead><tr><th>Status</th><th>Test</th><th>Message</th></tr></thead>' +
118 '<tbody id="loglines"></tbody>' +
120 this . logsummary
= $( 'logsummary' );
121 this . loglines
= $( 'loglines' );
123 _toHTML : function ( txt
) {
124 return txt
. escapeHTML (). replace ( /\n/g , "<br/>" );
126 addLinksToResults : function (){
127 $$( "tr.failed .nameCell" ). each ( function ( td
){ // todo: limit to children of this.log
128 td
. title
= "Run only this test" ;
129 Event
. observe ( td
, 'click' , function (){ window
. location
. search
= "?tests=" + td
. innerHTML
;});
131 $$( "tr.passed .nameCell" ). each ( function ( td
){ // todo: limit to children of this.log
132 td
. title
= "Run all tests" ;
133 Event
. observe ( td
, 'click' , function (){ window
. location
. search
= "" ;});
138 Test
. Unit
. Runner
= Class
. create ();
139 Test
. Unit
. Runner
. prototype = {
140 initialize : function ( testcases
) {
141 this . options
= Object
. extend ({
143 }, arguments
[ 1 ] || {});
144 this . options
. resultsURL
= this . parseResultsURLQueryParameter ();
145 this . options
. tests
= this . parseTestsQueryParameter ();
146 if ( this . options
. testLog
) {
147 this . options
. testLog
= $( this . options
. testLog
) || null ;
149 if ( this . options
. tests
) {
151 for ( var i
= 0 ; i
< this . options
. tests
. length
; i
++) {
152 if ( /^test/ . test ( this . options
. tests
[ i
])) {
153 this . tests
. push ( new Test
. Unit
. Testcase ( this . options
. tests
[ i
], testcases
[ this . options
. tests
[ i
]], testcases
[ "setup" ], testcases
[ "teardown" ]));
157 if ( this . options
. test
) {
158 this . tests
= [ new Test
. Unit
. Testcase ( this . options
. test
, testcases
[ this . options
. test
], testcases
[ "setup" ], testcases
[ "teardown" ])];
161 for ( var testcase
in testcases
) {
162 if ( /^test/ . test ( testcase
)) {
164 new Test
. Unit
. Testcase (
165 this . options
. context
? ' -> ' + this . options
. titles
[ testcase
] : testcase
,
166 testcases
[ testcase
], testcases
[ "setup" ], testcases
[ "teardown" ]
172 this . currentTest
= 0 ;
173 this . logger
= new Test
. Unit
. Logger ( this . options
. testLog
);
174 setTimeout ( this . runTests
. bind ( this ), 1000 );
176 parseResultsURLQueryParameter : function () {
177 return window
. location
. search
. parseQuery ()[ "resultsURL" ];
179 parseTestsQueryParameter : function (){
180 if ( window
. location
. search
. parseQuery ()[ "tests" ]){
181 return window
. location
. search
. parseQuery ()[ "tests" ]. split ( ',' );
185 // "ERROR" if there was an error,
186 // "FAILURE" if there was a failure, or
187 // "SUCCESS" if there was neither
188 getResult : function () {
189 var hasFailure
= false ;
190 for ( var i
= 0 ; i
< this . tests
. length
; i
++) {
191 if ( this . tests
[ i
]. errors
> 0 ) {
194 if ( this . tests
[ i
]. failures
> 0 ) {
204 postResults : function () {
205 if ( this . options
. resultsURL
) {
206 new Ajax
. Request ( this . options
. resultsURL
,
207 { method : 'get' , parameters : 'result=' + this . getResult (), asynchronous : false });
210 runTests : function () {
211 var test
= this . tests
[ this . currentTest
];
215 this . logger
. summary ( this . summary ());
218 if (! test
. isWaiting
) {
219 this . logger
. start ( test
. name
);
223 this . logger
. message ( "Waiting for " + test
. timeToWait
+ "ms" );
224 setTimeout ( this . runTests
. bind ( this ), test
. timeToWait
|| 1000 );
226 this . logger
. finish ( test
. status (), test
. summary ());
228 // tail recursive, hopefully the browser will skip the stackframe
232 summary : function () {
237 for ( var i
= 0 ; i
< this . tests
. length
; i
++) {
238 assertions
+= this . tests
[ i
]. assertions
;
239 failures
+= this . tests
[ i
]. failures
;
240 errors
+= this . tests
[ i
]. errors
;
243 ( this . options
. context
? this . options
. context
+ ': ' : '' ) +
244 this . tests
. length
+ " tests, " +
245 assertions
+ " assertions, " +
246 failures
+ " failures, " +
251 Test
. Unit
. Assertions
= Class
. create ();
252 Test
. Unit
. Assertions
. prototype = {
253 initialize : function () {
259 summary : function () {
261 this . assertions
+ " assertions, " +
262 this . failures
+ " failures, " +
263 this . errors
+ " errors" + " \n " +
264 this . messages
. join ( " \n " ));
269 fail : function ( message
) {
271 this . messages
. push ( "Failure: " + message
);
273 info : function ( message
) {
274 this . messages
. push ( "Info: " + message
);
276 error : function ( error
) {
278 this . messages
. push ( error
. name
+ ": " + error
. message
+ "(" + Test
. Unit
. inspect ( error
) + ")" );
281 if ( this . failures
> 0 ) return 'failed' ;
282 if ( this . errors
> 0 ) return 'error' ;
285 assert : function ( expression
) {
286 var message
= arguments
[ 1 ] || 'assert: got "' + Test
. Unit
. inspect ( expression
) + '"' ;
287 try { expression
? this . pass () :
288 this . fail ( message
); }
289 catch ( e
) { this . error ( e
); }
291 assertEqual : function ( expected
, actual
) {
292 var message
= arguments
[ 2 ] || "assertEqual" ;
293 try { ( expected
== actual
) ? this . pass () :
294 this . fail ( message
+ ': expected "' + Test
. Unit
. inspect ( expected
) +
295 '", actual "' + Test
. Unit
. inspect ( actual
) + '"' ); }
296 catch ( e
) { this . error ( e
); }
298 assertInspect : function ( expected
, actual
) {
299 var message
= arguments
[ 2 ] || "assertInspect" ;
300 try { ( expected
== actual
. inspect ()) ? this . pass () :
301 this . fail ( message
+ ': expected "' + Test
. Unit
. inspect ( expected
) +
302 '", actual "' + Test
. Unit
. inspect ( actual
) + '"' ); }
303 catch ( e
) { this . error ( e
); }
305 assertEnumEqual : function ( expected
, actual
) {
306 var message
= arguments
[ 2 ] || "assertEnumEqual" ;
307 try { $ A ( expected
). length
== $ A ( actual
). length
&&
308 expected
. zip ( actual
). all ( function ( pair
) { return pair
[ 0 ] == pair
[ 1 ] }) ?
309 this . pass () : this . fail ( message
+ ': expected ' + Test
. Unit
. inspect ( expected
) +
310 ', actual ' + Test
. Unit
. inspect ( actual
)); }
311 catch ( e
) { this . error ( e
); }
313 assertNotEqual : function ( expected
, actual
) {
314 var message
= arguments
[ 2 ] || "assertNotEqual" ;
315 try { ( expected
!= actual
) ? this . pass () :
316 this . fail ( message
+ ': got "' + Test
. Unit
. inspect ( actual
) + '"' ); }
317 catch ( e
) { this . error ( e
); }
319 assertIdentical : function ( expected
, actual
) {
320 var message
= arguments
[ 2 ] || "assertIdentical" ;
321 try { ( expected
=== actual
) ? this . pass () :
322 this . fail ( message
+ ': expected "' + Test
. Unit
. inspect ( expected
) +
323 '", actual "' + Test
. Unit
. inspect ( actual
) + '"' ); }
324 catch ( e
) { this . error ( e
); }
326 assertNotIdentical : function ( expected
, actual
) {
327 var message
= arguments
[ 2 ] || "assertNotIdentical" ;
328 try { !( expected
=== actual
) ? this . pass () :
329 this . fail ( message
+ ': expected "' + Test
. Unit
. inspect ( expected
) +
330 '", actual "' + Test
. Unit
. inspect ( actual
) + '"' ); }
331 catch ( e
) { this . error ( e
); }
333 assertNull : function ( obj
) {
334 var message
= arguments
[ 1 ] || 'assertNull' ;
335 try { ( obj
== null ) ? this . pass () :
336 this . fail ( message
+ ': got "' + Test
. Unit
. inspect ( obj
) + '"' ); }
337 catch ( e
) { this . error ( e
); }
339 assertMatch : function ( expected
, actual
) {
340 var message
= arguments
[ 2 ] || 'assertMatch' ;
341 var regex
= new RegExp ( expected
);
342 try { ( regex
. exec ( actual
)) ? this . pass () :
343 this . fail ( message
+ ' : regex: "' + Test
. Unit
. inspect ( expected
) + ' did not match: ' + Test
. Unit
. inspect ( actual
) + '"' ); }
344 catch ( e
) { this . error ( e
); }
346 assertHidden : function ( element
) {
347 var message
= arguments
[ 1 ] || 'assertHidden' ;
348 this . assertEqual ( "none" , element
. style
. display
, message
);
350 assertNotNull : function ( object
) {
351 var message
= arguments
[ 1 ] || 'assertNotNull' ;
352 this . assert ( object
!= null , message
);
354 assertType : function ( expected
, actual
) {
355 var message
= arguments
[ 2 ] || 'assertType' ;
357 ( actual
. constructor == expected
) ? this . pass () :
358 this . fail ( message
+ ': expected "' + Test
. Unit
. inspect ( expected
) +
359 '", actual "' + ( actual
. constructor ) + '"' ); }
360 catch ( e
) { this . error ( e
); }
362 assertNotOfType : function ( expected
, actual
) {
363 var message
= arguments
[ 2 ] || 'assertNotOfType' ;
365 ( actual
. constructor != expected
) ? this . pass () :
366 this . fail ( message
+ ': expected "' + Test
. Unit
. inspect ( expected
) +
367 '", actual "' + ( actual
. constructor ) + '"' ); }
368 catch ( e
) { this . error ( e
); }
370 assertInstanceOf : function ( expected
, actual
) {
371 var message
= arguments
[ 2 ] || 'assertInstanceOf' ;
373 ( actual
instanceof expected
) ? this . pass () :
374 this . fail ( message
+ ": object was not an instance of the expected type" ); }
375 catch ( e
) { this . error ( e
); }
377 assertNotInstanceOf : function ( expected
, actual
) {
378 var message
= arguments
[ 2 ] || 'assertNotInstanceOf' ;
380 !( actual
instanceof expected
) ? this . pass () :
381 this . fail ( message
+ ": object was an instance of the not expected type" ); }
382 catch ( e
) { this . error ( e
); }
384 assertRespondsTo : function ( method
, obj
) {
385 var message
= arguments
[ 2 ] || 'assertRespondsTo' ;
387 ( obj
[ method
] && typeof obj
[ method
] == 'function' ) ? this . pass () :
388 this . fail ( message
+ ": object doesn't respond to [" + method
+ "]" ); }
389 catch ( e
) { this . error ( e
); }
391 assertReturnsTrue : function ( method
, obj
) {
392 var message
= arguments
[ 2 ] || 'assertReturnsTrue' ;
395 if (! m
) m
= obj
[ 'is' + method
. charAt ( 0 ). toUpperCase ()+ method
. slice ( 1 )];
397 this . fail ( message
+ ": method returned false" ); }
398 catch ( e
) { this . error ( e
); }
400 assertReturnsFalse : function ( method
, obj
) {
401 var message
= arguments
[ 2 ] || 'assertReturnsFalse' ;
404 if (! m
) m
= obj
[ 'is' + method
. charAt ( 0 ). toUpperCase ()+ method
. slice ( 1 )];
406 this . fail ( message
+ ": method returned true" ); }
407 catch ( e
) { this . error ( e
); }
409 assertRaise : function ( exceptionName
, method
) {
410 var message
= arguments
[ 2 ] || 'assertRaise' ;
413 this . fail ( message
+ ": exception expected but none was raised" ); }
415 (( exceptionName
== null ) || ( e
. name
== exceptionName
)) ? this . pass () : this . error ( e
);
418 assertElementsMatch : function () {
419 var expressions
= $ A ( arguments
), elements
= $ A ( expressions
. shift ());
420 if ( elements
. length
!= expressions
. length
) {
421 this . fail ( 'assertElementsMatch: size mismatch: ' + elements
. length
+ ' elements, ' + expressions
. length
+ ' expressions' );
424 elements
. zip ( expressions
). all ( function ( pair
, index
) {
425 var element
= $( pair
. first ()), expression
= pair
. last ();
426 if ( element
. match ( expression
)) return true ;
427 this . fail ( 'assertElementsMatch: (in index ' + index
+ ') expected ' + expression
. inspect () + ' but got ' + element
. inspect ());
428 }. bind ( this )) && this . pass ();
430 assertElementMatches : function ( element
, expression
) {
431 this . assertElementsMatch ([ element
], expression
);
433 benchmark : function ( operation
, iterations
) {
434 var startAt
= new Date ();
435 ( iterations
|| 1 ). times ( operation
);
436 var timeTaken
= (( new Date ())- startAt
);
437 this . info (( arguments
[ 2 ] || 'Operation' ) + ' finished ' +
438 iterations
+ ' iterations in ' + ( timeTaken
/ 1000 )+ 's' );
441 _isVisible : function ( element
) {
442 element
= $( element
);
443 if (! element
. parentNode
) return true ;
444 this . assertNotNull ( element
);
445 if ( element
. style
&& Element
. getStyle ( element
, 'display' ) == 'none' )
448 return this . _isVisible ( element
. parentNode
);
450 assertNotVisible : function ( element
) {
451 this . assert (! this . _isVisible ( element
), Test
. Unit
. inspect ( element
) + " was not hidden and didn't have a hidden parent either. " + ( "" || arguments
[ 1 ]));
453 assertVisible : function ( element
) {
454 this . assert ( this . _isVisible ( element
), Test
. Unit
. inspect ( element
) + " was not visible. " + ( "" || arguments
[ 1 ]));
456 benchmark : function ( operation
, iterations
) {
457 var startAt
= new Date ();
458 ( iterations
|| 1 ). times ( operation
);
459 var timeTaken
= (( new Date ())- startAt
);
460 this . info (( arguments
[ 2 ] || 'Operation' ) + ' finished ' +
461 iterations
+ ' iterations in ' + ( timeTaken
/ 1000 )+ 's' );
466 Test
. Unit
. Testcase
= Class
. create ();
467 Object
. extend ( Object
. extend ( Test
. Unit
. Testcase
. prototype , Test
. Unit
. Assertions
. prototype ), {
468 initialize : function ( name
, test
, setup
, teardown
) {
469 Test
. Unit
. Assertions
. prototype . initialize
. bind ( this )();
472 if ( typeof test
== 'string' ) {
473 test
= test
. gsub ( /(\.should[^\(]+\()/ , '#{0}this,' );
474 test
= test
. gsub ( /(\.should[^\(]+)\(this,\)/ , '#{1}(this)' );
475 this . test = function () {
476 eval ( 'with(this){' + test
+ '}' );
479 this . test
= test
|| function () {};
482 this . setup
= setup
|| function () {};
483 this . teardown
= teardown
|| function () {};
484 this . isWaiting
= false ;
485 this . timeToWait
= 1000 ;
487 wait : function ( time
, nextPart
) {
488 this . isWaiting
= true ;
489 this . test
= nextPart
;
490 this . timeToWait
= time
;
495 if (! this . isWaiting
) this . setup
. bind ( this )();
496 this . isWaiting
= false ;
497 this . test
. bind ( this )();
499 if (! this . isWaiting
) {
500 this . teardown
. bind ( this )();
504 catch ( e
) { this . error ( e
); }
508 // *EXPERIMENTAL* BDD-style testing to please non-technical folk
509 // This draws many ideas from RSpec http://rspec.rubyforge.org/
511 Test
. setupBDDExtensionMethods = function (){
513 shouldEqual : 'assertEqual' ,
514 shouldNotEqual : 'assertNotEqual' ,
515 shouldEqualEnum : 'assertEnumEqual' ,
516 shouldBeA : 'assertType' ,
517 shouldNotBeA : 'assertNotOfType' ,
518 shouldBeAn : 'assertType' ,
519 shouldNotBeAn : 'assertNotOfType' ,
520 shouldBeNull : 'assertNull' ,
521 shouldNotBeNull : 'assertNotNull' ,
523 shouldBe : 'assertReturnsTrue' ,
524 shouldNotBe : 'assertReturnsFalse' ,
525 shouldRespondTo : 'assertRespondsTo'
527 var makeAssertion = function ( assertion
, args
, object
) {
528 this [ assertion
]. apply ( this ,( args
|| []). concat ([ object
]));
531 Test
. BDDMethods
= {};
532 $ H ( METHODMAP
). each ( function ( pair
) {
533 Test
. BDDMethods
[ pair
. key
] = function () {
534 var args
= $ A ( arguments
);
535 var scope
= args
. shift ();
536 makeAssertion
. apply ( scope
, [ pair
. value
, args
, this ]); };
539 [ Array
. prototype , String
. prototype , Number
. prototype , Boolean
. prototype ]. each (
540 function ( p
){ Object
. extend ( p
, Test
. BDDMethods
) }
544 Test
. context = function ( name
, spec
, log
){
545 Test
. setupBDDExtensionMethods ();
547 var compiledSpec
= {};
549 for ( specName
in spec
) {
553 compiledSpec
[ specName
] = spec
[ specName
];
556 var testName
= 'test' + specName
. gsub ( /\s+/ , '-' ). camelize ();
557 var body
= spec
[ specName
]. toString (). split ( ' \n ' ). slice ( 1 );
558 if ( /^\{/ . test ( body
[ 0 ])) body
= body
. slice ( 1 );
560 body
= body
. map ( function ( statement
){
561 return statement
. strip ()
563 compiledSpec
[ testName
] = body
. join ( ' \n ' );
564 titles
[ testName
] = specName
;
567 new Test
. Unit
. Runner ( compiledSpec
, { titles : titles
, testLog : log
|| 'testlog' , context : name
});