Always use JSBool (not bool sometimes, JSBool others) as JSVAL_IS_BOOLEAN's native...
[mozilla-central.git] / js / tests / menuhead.js
blob97a2862e092860c3195c6f5ef000e7228aa58189
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
4  *
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/
9  *
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
13  * License.
14  *
15  * The Original Code is mozilla.org code.
16  *
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.
21  *
22  * Contributor(s):
23  *   Bob Clary <http://bclary.com/>
24  *
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.
36  *
37  * ***** END LICENSE BLOCK ***** */
39 var gTotalCount = 0;
40 var gTotalSelected  = 0;
42 function setCursor(aCursor)
44   if (document.body && document.body.style)
45   {
46     document.body.style.cursor = aCursor;
47   }
50 function selectAll(suiteName, testDirName)
52   setCursor('wait');
54   suiteName   = suiteName || '';
55   testDirName = testDirName || '';
57   setTimeout('_selectAll("' + suiteName + '", "' + testDirName + '")', 200);
60 function _selectAll(suiteName, testDirName)
62   if (!suiteName)
63   {
64     for (suiteName in suites)
65     {
66       setAllDirs(suiteName, true);
67     }
68   }
69   else if (!testDirName)
70   {
71     setAllDirs(suiteName, true);
72   }
73   else
74   {
75     setAllTests(suiteName, testDirName, true);
76   }
78   setCursor('auto');
81 function selectNone(suiteName, testDirName)
83   setCursor('wait');
85   suiteName   = suiteName || '';
86   testDirName = testDirName || '';
88   setTimeout('_selectNone("' + suiteName + '", "' + testDirName + '")', 200);
91 function _selectNone(suiteName, testDirName)
93   if (!suiteName)
94   {
95     for (suiteName in suites)
96     {
97       setAllDirs(suiteName, false);
98     }
99   }
100   else if (!testDirName)
101   {
102     setAllDirs(suiteName, false);
103   }
104   else
105   {
106     setAllTests(suiteName, testDirName, false);
107   }
109   setCursor('auto');
112 function updateCounts(suiteName)
114   var suite = suites[suiteName];
115   var pct = parseInt((suite.selected / suite.count) * 100);
116   if (isNaN(pct))
117     pct = 0;
118        
119   document.forms.testCases.elements['SUMMARY_' + suiteName].value =
120     suite.selected + '/' + suite.count +
121     ' (' + pct + '%) selected';
123   pct = parseInt((gTotalSelected / gTotalCount) * 100);
124   if (isNaN(pct))
125     pct = 0;
126        
127   document.forms.testCases.elements['TOTAL'].value =
128     gTotalSelected + '/' + gTotalCount + ' (' +
129     pct + '%) selected';
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);
143   return true;
145    
146 function updateTotals()
148   setCursor('wait');
150   setTimeout('_updateTotals()', 200);
153 function _updateTotals()
155   gTotalCount = 0;
156   gTotalSelected  = 0;
158   for (var suiteName in suites)
159   {
160     gTotalCount += suites[suiteName].count;
161   }
162   for (suiteName in suites)
163   {
164     updateCounts(suiteName);
165   }
166   setCursor('auto');
169 function setAllDirs(suiteName, value)
171   var testDirs = suites[suiteName].testDirs;
173   for (var testDirName in testDirs)
174   {
175     setAllTests(suiteName, testDirName, value);
176   }
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;
184   var incr = 0;
186   for (var testName in tests)
187   {
188     var radioName = tests[testName].id;
189     var radio     = elements[radioName];
190     if (radio.checked && !value)
191     {
192       incr--;
193     }
194     else if (!radio.checked && value)
195     {
196       incr++;
197     }
198     radio.checked = value;
199   }
201   suite.selected += incr;
202   gTotalSelected += incr;
204   updateCounts(suiteName);
207 function createList()
209   var suiteName;
210   var elements = document.forms['testCases'].elements;
211   var win      = window.open('about:blank', 'other_window');
212   var writer   = new CachedWriter(win.document);
214   win.document.open();
215   writer.writeln('<pre>');
216    
217   writer.writeln('# Created ' + new Date());
219   for (suiteName in suites)
220   {
221     writer.writeln('# ' + suiteName + ': ' +
222                    elements['SUMMARY_' + suiteName].value);
223   }
225   writer.writeln('# TOTAL: ' + elements['TOTAL'].value);
227   for (suiteName in suites)
228   {
229     var testDirs = suites[suiteName].testDirs;
230     for (var testDirName in testDirs)
231     {
232       var tests = testDirs[testDirName].tests;
233       for (var testName in tests)
234       { 
235         var radioName = tests[testName].id;
236         var radio     = elements[radioName];
237         if (radio.checked)
238           writer.writeln(suiteName + '/' + testDirName + '/' + radio.value);
239       }
240     }
241   }
242   writer.writeln('<\/pre>');
243    
244   writer.close();
247 var gTests;
248 var gTestNumber;
249 var gWindow;
251 function executeList()
253   var elements = document.forms['testCases'].elements;
255   gTests = [];
256   gTestNumber = -1;
258   for (var suiteName in suites)
259   {
260     var testDirs = suites[suiteName].testDirs;
261     for (var testDirName in testDirs)
262     {
263       var tests = testDirs[testDirName].tests;
264       for (var testName in tests)
265       { 
266         var test      = tests[testName];
267         var radioName = test.id;
268         var radio     = elements[radioName];
269         delete test.testCases;
270         if (radio.checked)
271         {
272           gTests[gTests.length] = test;
273           test.path = suiteName + '/' + testDirName + '/' + radio.value;
274         }
275       }
276     }
277   }
278   runNextTest();
281 function runNextTest()
283   var iTestCase;
285   if (gTestNumber != -1)
286   {
287     // tests have already run in gWindow, collect the results
288     // for later reporting.
290     var e;
291     try
292     {
293       var test  = gTests[gTestNumber];
294       test.testCases = [];
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++)
300       {
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:'');
311       }
312       origtestcases = origtestcase = null;
313     }
314     catch(e)
315     {
316       ;
317     }
318   }
320   ++gTestNumber;
322   if (gTestNumber < gTests.length)
323   {
324     // run test
325     test      = gTests[gTestNumber];
327     gWindow = window.open('js-test-driver-' +
328                           document.forms.testCases.doctype.value +
329                           '.html?test=' +
330                           test.path +
331                           ';language=' +
332                           document.forms.testCases.language.value,
333                           'output');
334     if (!gWindow)
335     {
336       alert('This test suite requires popup windows.\n' +
337             'Please enable them for this site.');
338     }
339   }
340   else if (document.forms.testCases.outputformat.value == 'html')
341   {
342     // all tests completed, display report
343     reportHTML();
344   }
345   else if (document.forms.testCases.outputformat.value == 'javascript')
346   {
347     // all tests completed, display report
348     reportJavaScript();
349   }
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 +
373                  '<\/title>');
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 +
385                  '<\/h2>');
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)
406   {
407     var suiteTotals = {passed: 0, failed: 0};
408     var testDirs = suites[suiteName].testDirs;
410     for (var testDirName in testDirs)
411     {
412       var dirTotals   = {passed: 0, failed: 0};
413       var tests = testDirs[testDirName].tests;
415       for (var testName in tests)
416       {
417         var nameTotals  = {passed: 0, failed: 0};
418         var test = tests[testName];
420         if (! ('testCases' in test) )
421         {
422           // test not run
423           continue;
424         }
426         var testCases = test.testCases;
428         for (var iTestCase = 0; iTestCase < testCases.length; iTestCase++)
429         {
430           var testCase = testCases[iTestCase];
431           ++totalTestCases;
432           if (testCase.passed)
433           {
434             ++totalTestCasesPassed;
435             ++nameTotals.passed;
436             ++dirTotals.passed;
437             ++suiteTotals.passed;
438           }
439           else
440           {
441             ++totalTestCasesFailed;
442             ++nameTotals.failed;
443             ++dirTotals.failed;
444             ++suiteTotals.failed;
445           }
447           if (errorsOnly && testCase.passed)
448           {
449             continue;
450           }
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') +
459                          '<\/td>' +
460                          '<td title="Description">' +
461                          splitString(testCase.description, '<br>', 30) +
462                          '<\/td>' +
463                          '<td title="Actual">' +
464                          splitString(testCase.actual, '<br>', 30) +
465                          '<\/td>' +
466                          '<td title="Expected">' +
467                          splitString(testCase.expect, '<br>', 30) +
468                          '<\/td>' +
469                          '<td title="Bug">' +
470                          (testCase.bugnumber?testCase.bugnumber:'') +
471                          '<\/td>' +
472                          '<td title="Reason">' + testCase.reason + '<\/td>' +
473                          '<\/tr>');
474         } // for iTestCase
476         if (!errorsOnly && nameTotals.passed + nameTotals.failed > 0)
477         {
478           writer.writeln('<tr>' +
479                          '<td>' + suiteName + '<\/td>' +
480                          '<td>' + testDirName   + '<\/td>' +
481                          '<td colspan="7" style="font-weight:bold;">' +
482                          testName + ' ' +
483                          'Passed = ' + nameTotals.passed.toString() + ' ' +
484                          'Failed = ' + nameTotals.failed.toString() +
485                          '<\/td>' +
486                          '<\/tr>');
487         }
489       } // for (var testName in tests)
491       if (!errorsOnly && dirTotals.passed + dirTotals.failed > 0)
492       {
493         writer.writeln('<tr>' +
494                        '<td>' + suiteName + '<\/td>' +
495                        '<td colspan="8" style="font-weight:bold;">' +
496                        testDirName  + ' ' +
497                        'Passed = ' + dirTotals.passed.toString() + ' ' +
498                        'Failed = ' + dirTotals.failed.toString() +
499                        '<\/td>' +
500                        '<\/tr>');
501       }
503     } // for (var testDirName in testDirs)
505     if (!errorsOnly && suiteTotals.passed + suiteTotals.failed > 0)
506     {
507       writer.writeln('<tr>' +
508                      '<td colspan="9" style="font-weight:bold;">' +
509                      suiteName + ' ' +
510                      'Passed = ' + suiteTotals.passed.toString() + ' ' +
511                      'Failed = ' + suiteTotals.failed.toString() +
512                      '<\/td>' +
513                      '<\/tr>');
514     }
516   } // for (var suiteName in suites)
518   writer.writeln('<\/tbody>');
519   writer.writeln('<\/table>');
520    
521   writer.writeln('<p>Total TestCases = ' + totalTestCases +
522                  ', Passed = ' + totalTestCasesPassed +
523                  ', Failed = ' + totalTestCasesFailed +
524                  '<\/p>');
525   writer.writeln('<\/body>');
526   writer.writeln('<\/html>');
528   writer.close();
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)
535   var newstr = '';
536   var length = str.length;
538   if (str.indexOf(' ') != -1)
539   {
540     return str;
541   }
542   for (var i = 0; i < length; i += pos)
543   {
544     newstr += str.substr(i, pos) + delim;
545   }
546   return newstr;
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 +
560                  '<\/title>');
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 = {};');
568   writer.writeln('}');
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;');
574   writer.writeln('}');
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] = {};');
591   writer.writeln('}');
592   writer.writeln('gJSResult = gUAResult[gLanguage];');
593   writer.writeln('if (!gJSResult) {');
594   writer.writeln('  gJSResult = gUAResult[gLanguage] = {};');
595   writer.writeln('}');
598   for (var suiteName in suites)
599   {
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)
611     {
612       var dirheader = '';
614       dirheader += 'gDirId = "' + testDirName + '";\n';
615       dirheader += 'gDir = gSuite[gDirId];\n';
616       dirheader += 'if (!gDir) {\n';
617       dirheader += '  gDir = gSuite[gDirId] = {};\n';
618       dirheader += '}\n';
620       var tests = testDirs[testDirName].tests;
622       for (var testName in tests)
623       {
624         var test = tests[testName];
626         if (! ('testCases' in test) )
627         {
628           // test not run
629           continue;
630         }
632         var testCases = test.testCases;
633         var resultId = suiteName + '/' + testDirName + '/' + testName;
635         var testheader = '';
636         testheader += 'gTestId = "' + testName + '";\n';
637         testheader += 'gTest  = gDir[gTestId];\n';
638         testheader += 'if (!gTest) {\n';
639         testheader += '  gTest = gDir[gTestId] = [];\n';
640         testheader += '}\n';
642         for (var iTestCase = 0; iTestCase < testCases.length; iTestCase++)
643         {
644           var testCase = testCases[iTestCase];
645           if (errorsOnly && testCase.passed)
646           {
647             continue;
648           }
650           if (suiteheader)
651           {
652             writer.writeln(suiteheader);
653             suiteheader = '';
654           }
655           if (dirheader)
656           {
657             writer.writeln(dirheader);
658             dirheader = '';
659           }
660           if (testheader)
661           {
662             writer.writeln(testheader);
663             testheader = '';
664           }
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);
671          
672           var buffer = '';
674           buffer += 'gTest[gTest.length] = \n';
675           buffer += '{\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';
684           buffer += '};\n';
686           writer.writeln(buffer);
687           buffer = '';
689         } // for iTestCase
691       }  // for testName
693     } // for testDirName
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 +
703                  '<\/p>');
704   writer.writeln('<\/body>')
705     writer.writeln('<\/html>');
706   writer.close();
708   
709 // improve IE's performance. Mozilla's is fine. ;-)
710 function CachedWriter(doc, limit)
712   this.document     = doc;
713   this.pendingCount = 0;
714   this.pendingLimit = limit ? limit : 100;
715   this.lines        = [];
718 CachedWriter.prototype.destroy = function _cachedWriterDestroy()
720   this.document     = null;
721   this.pendingCount = 0;
722   this.pendingLimit = 0;
723   this.lines        = null;
726   CachedWriter.prototype.writeln = function _cachedWriterWriteLine(s)
728   this.lines[this.lines.length] = s;
729   if (++this.pendingCount >= this.pendingLimit)
730   {
731     this.flush();
732   }
735 CachedWriter.prototype.flush = function _cachedWriterFlush()
737   var s = this.lines.join('\n');
738   this.pendingCount = 0;
739   this.lines = [];
740   if (!window.opera)
741   {
742     for (var ibadchar = 0; ibadchar < 32; ++ibadchar)
743     {
744       if (ibadchar != 10 && ibadchar != 13)
745       {
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);
750       }
751     }
752   }
753   this.document.writeln(s);
756   CachedWriter.prototype.close = function _cachedWriterClose()
758   this.flush();
759   this.document.close();
760   this.destroy();