1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* ***** BEGIN LICENSE BLOCK *****
3 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
5 * The contents of this file are subject to the Mozilla Public License Version
6 * 1.1 (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 * http://www.mozilla.org/MPL/
10 * Software distributed under the License is distributed on an "AS IS" basis,
11 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 * for the specific language governing rights and limitations under the
15 * The Original Code is mozilla.org code.
17 * The Initial Developer of the Original Code is
18 * Netscape Communications Corporation.
19 * Portions created by the Initial Developer are Copyright (C) 1998
20 * the Initial Developer. All Rights Reserved.
23 * Bob Clary <http://bclary.com/>
25 * Alternatively, the contents of this file may be used under the terms of
26 * either the GNU General Public License Version 2 or later (the "GPL"), or
27 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
28 * in which case the provisions of the GPL or the LGPL are applicable instead
29 * of those above. If you wish to allow use of your version of this file only
30 * under the terms of either the GPL or the LGPL, and not to allow others to
31 * use your version of this file under the terms of the MPL, indicate your
32 * decision by deleting the provisions above and replace them with the notice
33 * and other provisions required by the GPL or the LGPL. If you do not delete
34 * the provisions above, a recipient may use your version of this file under
35 * the terms of any one of the MPL, the GPL or the LGPL.
37 * ***** END LICENSE BLOCK ***** */
40 var gTotalSelected
= 0;
42 function setCursor(aCursor
)
44 if (document
.body
&& document
.body
.style
)
46 document
.body
.style
.cursor
= aCursor
;
50 function selectAll(suiteName
, testDirName
)
54 suiteName
= suiteName
|| '';
55 testDirName
= testDirName
|| '';
57 setTimeout('_selectAll("' + suiteName
+ '", "' + testDirName
+ '")', 200);
60 function _selectAll(suiteName
, testDirName
)
64 for (suiteName
in suites
)
66 setAllDirs(suiteName
, true);
69 else if (!testDirName
)
71 setAllDirs(suiteName
, true);
75 setAllTests(suiteName
, testDirName
, true);
81 function selectNone(suiteName
, testDirName
)
85 suiteName
= suiteName
|| '';
86 testDirName
= testDirName
|| '';
88 setTimeout('_selectNone("' + suiteName
+ '", "' + testDirName
+ '")', 200);
91 function _selectNone(suiteName
, testDirName
)
95 for (suiteName
in suites
)
97 setAllDirs(suiteName
, false);
100 else if (!testDirName
)
102 setAllDirs(suiteName
, false);
106 setAllTests(suiteName
, testDirName
, false);
112 function updateCounts(suiteName
)
114 var suite
= suites
[suiteName
];
115 var pct
= parseInt((suite
.selected
/ suite
.count
) * 100);
119 document
.forms
.testCases
.elements
['SUMMARY_' + suiteName
].value
=
120 suite
.selected
+ '/' + suite
.count
+
121 ' (' + pct
+ '%) selected';
123 pct
= parseInt((gTotalSelected
/ gTotalCount
) * 100);
127 document
.forms
.testCases
.elements
['TOTAL'].value
=
128 gTotalSelected
+ '/' + gTotalCount
+ ' (' +
132 function onRadioClick(radio
)
134 var info
= radio
.id
.split(':');
135 var suiteName
= info
[0];
136 var suite
= suites
[suiteName
];
137 var incr
= (radio
.checked
? 1 : -1);
138 suite
.selected
+= incr
;
139 gTotalSelected
+= incr
;
141 updateCounts(suiteName
);
146 function updateTotals()
150 setTimeout('_updateTotals()', 200);
153 function _updateTotals()
158 for (var suiteName
in suites
)
160 gTotalCount
+= suites
[suiteName
].count
;
162 for (suiteName
in suites
)
164 updateCounts(suiteName
);
169 function setAllDirs(suiteName
, value
)
171 var testDirs
= suites
[suiteName
].testDirs
;
173 for (var testDirName
in testDirs
)
175 setAllTests(suiteName
, testDirName
, value
);
179 function setAllTests(suiteName
, testDirName
, value
)
181 var suite
= suites
[suiteName
];
182 var tests
= suite
.testDirs
[testDirName
].tests
;
183 var elements
= document
.forms
['testCases'].elements
;
186 for (var testName
in tests
)
188 var radioName
= tests
[testName
].id
;
189 var radio
= elements
[radioName
];
190 if (radio
.checked
&& !value
)
194 else if (!radio
.checked
&& value
)
198 radio
.checked
= value
;
201 suite
.selected
+= incr
;
202 gTotalSelected
+= incr
;
204 updateCounts(suiteName
);
207 function createList()
210 var elements
= document
.forms
['testCases'].elements
;
211 var win
= window
.open('about:blank', 'other_window');
212 var writer
= new CachedWriter(win
.document
);
215 writer
.writeln('<pre>');
217 writer
.writeln('# Created ' + new Date());
219 for (suiteName
in suites
)
221 writer
.writeln('# ' + suiteName
+ ': ' +
222 elements
['SUMMARY_' + suiteName
].value
);
225 writer
.writeln('# TOTAL: ' + elements
['TOTAL'].value
);
227 for (suiteName
in suites
)
229 var testDirs
= suites
[suiteName
].testDirs
;
230 for (var testDirName
in testDirs
)
232 var tests
= testDirs
[testDirName
].tests
;
233 for (var testName
in tests
)
235 var radioName
= tests
[testName
].id
;
236 var radio
= elements
[radioName
];
238 writer
.writeln(suiteName
+ '/' + testDirName
+ '/' + radio
.value
);
242 writer
.writeln('<\/pre>');
251 function executeList()
253 var elements
= document
.forms
['testCases'].elements
;
258 for (var suiteName
in suites
)
260 var testDirs
= suites
[suiteName
].testDirs
;
261 for (var testDirName
in testDirs
)
263 var tests
= testDirs
[testDirName
].tests
;
264 for (var testName
in tests
)
266 var test
= tests
[testName
];
267 var radioName
= test
.id
;
268 var radio
= elements
[radioName
];
269 delete test
.testCases
;
272 gTests
[gTests
.length
] = test
;
273 test
.path
= suiteName
+ '/' + testDirName
+ '/' + radio
.value
;
281 function runNextTest()
285 if (gTestNumber
!= -1)
287 // tests have already run in gWindow, collect the results
288 // for later reporting.
293 var test
= gTests
[gTestNumber
];
295 //test.testCases = test.testCases.concat(gWindow.gTestcases);
296 // note MSIE6 has a bug where instead of concating the new arrays
297 // it concats them to the first element. work around...
298 var origtestcases
= gWindow
.gTestcases
;
299 for (iTestCase
= 0; iTestCase
< origtestcases
.length
; iTestCase
++)
301 // test.testCases[test.testCases.length] = origtestcases[iTestCase];
302 var origtestcase
= origtestcases
[iTestCase
];
303 var testCase
= test
.testCases
[test
.testCases
.length
] = {};
304 testCase
.name
= new String(origtestcase
.name
);
305 testCase
.description
= new String(origtestcase
.description
);
306 testCase
.expect
= new String(origtestcase
.expect
);
307 testCase
.actual
= new String(origtestcase
.actual
);
308 testCase
.passed
= origtestcase
.passed
? true : false;
309 testCase
.reason
= new String(origtestcase
.reason
);
310 testCase
.bugnumber
= new String(origtestcase
.bugnumber
?origtestcase
.bugnumber
:'');
312 origtestcases
= origtestcase
= null;
322 if (gTestNumber
< gTests
.length
)
325 test
= gTests
[gTestNumber
];
327 gWindow
= window
.open('js-test-driver-' +
328 document
.forms
.testCases
.doctype
.value
+
332 document
.forms
.testCases
.language
.value
,
336 alert('This test suite requires popup windows.\n' +
337 'Please enable them for this site.');
340 else if (document
.forms
.testCases
.outputformat
.value
== 'html')
342 // all tests completed, display report
345 else if (document
.forms
.testCases
.outputformat
.value
== 'javascript')
347 // all tests completed, display report
353 function reportHTML()
355 var errorsOnly
= document
.forms
.testCases
.failures
.checked
;
356 var totalTestCases
= 0;
357 var totalTestCasesPassed
= 0;
358 var totalTestCasesFailed
= 0;
360 gWindow
.document
.close();
362 var writer
= new CachedWriter(gWindow
.document
);
364 writer
.writeln('<!DOCTYPE HTML PUBLIC ' +
365 '"-//W3C//DTD HTML 4.01 Transitional//EN" ' +
366 '"http://www.w3.org/TR/html4/loose.dtd">');
368 writer
.writeln('<html>');
369 writer
.writeln('<head>');
370 writer
.writeln('<title>JavaScript Tests Browser: ' +
371 navigator
.userAgent
+ ' Language: ' +
372 document
.forms
.testCases
.language
.value
+
374 writer
.writeln('<style type="text/css">');
375 writer
.writeln(' .passed { } .failed { background-color: red; }');
376 writer
.writeln('table {}');
377 writer
.writeln('th.description, th.actual, th.expect { width: 30em;}');
378 writer
.writeln('<\/style>');
380 writer
.writeln('<\/head>');
381 writer
.writeln('<body>');
382 writer
.writeln('<h2>JavaScript Tests Browser: ' +
383 navigator
.userAgent
+ ' Language: ' +
384 document
.forms
.testCases
.language
.value
+
387 writer
.writeln('<table border="1">');
388 writer
.writeln('<thead>');
389 writer
.writeln('<tr>');
390 writer
.writeln('<th>Suite<\/th>');
391 writer
.writeln('<th>Directory<\/th>');
392 writer
.writeln('<th>Test<\/th>');
393 writer
.writeln('<th>Passed<\/th>');
394 writer
.writeln('<th class="description">Description<\/th>');
395 writer
.writeln('<th class="actual">Actual<\/th>');
396 writer
.writeln('<th class="expect">Expect<\/th>');
397 writer
.writeln('<th>BugNumber<\/th>');
398 writer
.writeln('<th>Reason<\/th>');
399 writer
.writeln('<\/tr>');
400 writer
.writeln('<\/thead>');
401 writer
.writeln('<tbody>');
403 writer
.writeln('<\/tr>');
405 for (var suiteName
in suites
)
407 var suiteTotals
= {passed
: 0, failed
: 0};
408 var testDirs
= suites
[suiteName
].testDirs
;
410 for (var testDirName
in testDirs
)
412 var dirTotals
= {passed
: 0, failed
: 0};
413 var tests
= testDirs
[testDirName
].tests
;
415 for (var testName
in tests
)
417 var nameTotals
= {passed
: 0, failed
: 0};
418 var test
= tests
[testName
];
420 if (! ('testCases' in test
) )
426 var testCases
= test
.testCases
;
428 for (var iTestCase
= 0; iTestCase
< testCases
.length
; iTestCase
++)
430 var testCase
= testCases
[iTestCase
];
434 ++totalTestCasesPassed
;
437 ++suiteTotals
.passed
;
441 ++totalTestCasesFailed
;
444 ++suiteTotals
.failed
;
447 if (errorsOnly
&& testCase
.passed
)
452 writer
.writeln('<tr class="' +
453 (testCase
.passed
? 'passed' : 'failed') + '">' +
454 '<td title="Suite">' + suiteName
+ '<\/td>' +
455 '<td title="Directory">' + testDirName
+ '<\/td>' +
456 '<td title="Test">' + testName
+ '<\/td>' +
457 '<td title="Status">' +
458 (testCase
.passed
? 'Test Passed':'Test Failed') +
460 '<td title="Description">' +
461 splitString(testCase
.description
, '<br>', 30) +
463 '<td title="Actual">' +
464 splitString(testCase
.actual
, '<br>', 30) +
466 '<td title="Expected">' +
467 splitString(testCase
.expect
, '<br>', 30) +
470 (testCase
.bugnumber
?testCase
.bugnumber
:'') +
472 '<td title="Reason">' + testCase
.reason
+ '<\/td>' +
476 if (!errorsOnly
&& nameTotals
.passed
+ nameTotals
.failed
> 0)
478 writer
.writeln('<tr>' +
479 '<td>' + suiteName
+ '<\/td>' +
480 '<td>' + testDirName
+ '<\/td>' +
481 '<td colspan="7" style="font-weight:bold;">' +
483 'Passed = ' + nameTotals
.passed
.toString() + ' ' +
484 'Failed = ' + nameTotals
.failed
.toString() +
489 } // for (var testName in tests)
491 if (!errorsOnly
&& dirTotals
.passed
+ dirTotals
.failed
> 0)
493 writer
.writeln('<tr>' +
494 '<td>' + suiteName
+ '<\/td>' +
495 '<td colspan="8" style="font-weight:bold;">' +
497 'Passed = ' + dirTotals
.passed
.toString() + ' ' +
498 'Failed = ' + dirTotals
.failed
.toString() +
503 } // for (var testDirName in testDirs)
505 if (!errorsOnly
&& suiteTotals
.passed
+ suiteTotals
.failed
> 0)
507 writer
.writeln('<tr>' +
508 '<td colspan="9" style="font-weight:bold;">' +
510 'Passed = ' + suiteTotals
.passed
.toString() + ' ' +
511 'Failed = ' + suiteTotals
.failed
.toString() +
516 } // for (var suiteName in suites)
518 writer
.writeln('<\/tbody>');
519 writer
.writeln('<\/table>');
521 writer
.writeln('<p>Total TestCases = ' + totalTestCases
+
522 ', Passed = ' + totalTestCasesPassed
+
523 ', Failed = ' + totalTestCasesFailed
+
525 writer
.writeln('<\/body>');
526 writer
.writeln('<\/html>');
531 // return a string with delim inserted every pos characters
532 // if there are no spaces to break the line
533 function splitString(str
, delim
, pos
)
536 var length
= str
.length
;
538 if (str
.indexOf(' ') != -1)
542 for (var i
= 0; i
< length
; i
+= pos
)
544 newstr
+= str
.substr(i
, pos
) + delim
;
548 function reportJavaScript()
550 gWindow
.document
.close();
552 var errorsOnly
= document
.forms
.testCases
.failures
.checked
;
553 var writer
= new CachedWriter(gWindow
.document
);
555 writer
.writeln('<html>');
556 writer
.writeln('<head>');
557 writer
.writeln('<title>JavaScript Tests Browser: ' +
558 navigator
.userAgent
+ ' Language: ' +
559 document
.forms
.testCases
.language
.value
+
561 writer
.writeln('<script type="text/javascript">');
562 writer
.writeln('var global = window.parent;');
563 writer
.writeln('if (!global.gUAHash) {');
564 writer
.writeln(' global.gUAHash = {};');
565 writer
.writeln(' global.gUAList = {};');
566 writer
.writeln(' global.gUA_id = -1;');
567 writer
.writeln(' global.gTestResults = {};');
569 writer
.writeln('var gUA = "' + navigator
.userAgent
+ '";');
570 writer
.writeln('var gUA_id = global.gUAHash[gUA];');
571 writer
.writeln('if (typeof(gUA_id) != "number") {');
572 writer
.writeln(' gUA_id = global.gUAHash[gUA] = ++global.gUA_id;');
573 writer
.writeln(' global.gUAList[gUA_id] = gUA;');
575 writer
.writeln('var gTestResults = global.gTestResults;');
576 writer
.writeln('var gLanguage = \'' + document
.forms
.testCases
.language
.value
+ '\';');
577 writer
.writeln('var gResult;');
578 writer
.writeln('var gResultId;');
579 writer
.writeln('var gUAResult;');
580 writer
.writeln('var gJSResult;');
581 writer
.writeln('var gSuiteId;');
582 writer
.writeln('var gSuite;');
583 writer
.writeln('var gDirId;');
584 writer
.writeln('var gDir;');
585 writer
.writeln('var gTestId;');
586 writer
.writeln('var gTest;');
588 writer
.writeln('gUAResult = gTestResults[gUA_id];');
589 writer
.writeln('if (!gUAResult) {');
590 writer
.writeln(' gUAResult = gTestResults[gUA_id] = {};');
592 writer
.writeln('gJSResult = gUAResult[gLanguage];');
593 writer
.writeln('if (!gJSResult) {');
594 writer
.writeln(' gJSResult = gUAResult[gLanguage] = {};');
598 for (var suiteName
in suites
)
600 var suiteheader
= '';
602 suiteheader
+= 'gSuiteId = "' + suiteName
+ '";\n';
603 suiteheader
+= 'gSuite = gJSResult[gSuiteId];\n';
604 suiteheader
+= 'if (!gSuite) {\n';
605 suiteheader
+= ' gSuite = gJSResult[gSuiteId] = {};\n';
606 suiteheader
+= '}\n';
608 var testDirs
= suites
[suiteName
].testDirs
;
610 for (var testDirName
in testDirs
)
614 dirheader
+= 'gDirId = "' + testDirName
+ '";\n';
615 dirheader
+= 'gDir = gSuite[gDirId];\n';
616 dirheader
+= 'if (!gDir) {\n';
617 dirheader
+= ' gDir = gSuite[gDirId] = {};\n';
620 var tests
= testDirs
[testDirName
].tests
;
622 for (var testName
in tests
)
624 var test
= tests
[testName
];
626 if (! ('testCases' in test
) )
632 var testCases
= test
.testCases
;
633 var resultId
= suiteName
+ '/' + testDirName
+ '/' + testName
;
636 testheader
+= 'gTestId = "' + testName
+ '";\n';
637 testheader
+= 'gTest = gDir[gTestId];\n';
638 testheader
+= 'if (!gTest) {\n';
639 testheader
+= ' gTest = gDir[gTestId] = [];\n';
642 for (var iTestCase
= 0; iTestCase
< testCases
.length
; iTestCase
++)
644 var testCase
= testCases
[iTestCase
];
645 if (errorsOnly
&& testCase
.passed
)
652 writer
.writeln(suiteheader
);
657 writer
.writeln(dirheader
);
662 writer
.writeln(testheader
);
666 var name
= escape(testCase
.name
);
667 var desc
= escape(testCase
.description
);
668 var actual
= escape(testCase
.actual
);
669 var expect
= escape(testCase
.expect
);
670 var reason
= escape(testCase
.reason
);
674 buffer
+= 'gTest[gTest.length] = \n';
676 buffer
+= 'name: "' + name
+ '",\n';
677 buffer
+= 'description: "' + desc
+ '",\n';
678 buffer
+= 'expect: "' + expect
+ '",\n';
679 buffer
+= 'actual: "' + actual
+ '",\n';
680 buffer
+= 'passed: ' + testCase
.passed
+ ',\n';
681 buffer
+= 'reason: "' + reason
+ '",\n';
682 buffer
+= 'bugnumber: "' + (testCase
.bugnumber
?
683 testCase
.bugnumber
: '') + '"\n';
686 writer
.writeln(buffer
);
695 } // for (var suiteName in suites)
697 writer
.writeln('<\/script>');
698 writer
.writeln('<\/head>');
699 writer
.writeln('<body>');
700 writer
.writeln('<p>JavaScript Tests Browser: ' +
701 navigator
.userAgent
+ ' Language: ' +
702 document
.forms
.testCases
.language
.value
+
704 writer
.writeln('<\/body>')
705 writer
.writeln('<\/html>');
709 // improve IE's performance. Mozilla's is fine. ;-)
710 function CachedWriter(doc
, limit
)
713 this.pendingCount
= 0;
714 this.pendingLimit
= limit
? limit
: 100;
718 CachedWriter
.prototype.destroy
= function _cachedWriterDestroy()
720 this.document
= null;
721 this.pendingCount
= 0;
722 this.pendingLimit
= 0;
726 CachedWriter
.prototype.writeln
= function _cachedWriterWriteLine(s
)
728 this.lines
[this.lines
.length
] = s
;
729 if (++this.pendingCount
>= this.pendingLimit
)
735 CachedWriter
.prototype.flush
= function _cachedWriterFlush()
737 var s
= this.lines
.join('\n');
738 this.pendingCount
= 0;
742 for (var ibadchar
= 0; ibadchar
< 32; ++ibadchar
)
744 if (ibadchar
!= 10 && ibadchar
!= 13)
746 var badchar
= String
.fromCharCode(ibadchar
);
747 var badregx
= new RegExp(badchar
, 'mg');
748 var escchar
= '\\0x' + ibadchar
.toString(16);
749 s
= s
.replace(badregx
, escchar
);
753 this.document
.writeln(s
);
756 CachedWriter
.prototype.close
= function _cachedWriterClose()
759 this.document
.close();