Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Changes In Branch jsunit-port Excluding Merge-Ins
This is equivalent to a diff from 01e4c3bd57 to c8ab5e94db
2011-11-17
| ||
10:24 | Изменения эксперементальной ветки jsunit-port перенесены в trunk check-in: 1224326503 user: kuntashov tags: trunk | |
09:53 | Исправлены незначительные недочеты Leaf check-in: c8ab5e94db user: kuntashov tags: jsunit-port | |
2011-11-16
| ||
05:41 | Добавлена возможность перезагрузки тестов check-in: ef17cf47ba user: kuntashov tags: jsunit-port | |
2011-11-14
| ||
10:04 | Устранен форк check-in: e15e083d91 user: kuntashov tags: trunk | |
2011-11-10
| ||
20:22 | Синхронизировано с trunk check-in: ffed03ffd1 user: kuntashov tags: jsunit-port | |
12:57 | Начал скрипт для быстрого выбора в подсказке о параметрах check-in: 01e4c3bd57 user: orefkov tags: trunk | |
2011-11-07
| ||
14:17 | Мелкие изменения скрипта внешние файлы check-in: fef94c65e2 user: vladnet tags: trunk | |
Added DevTools/testrunner.js.
1 +$engine JScript 2 +$uname TestRunner 3 +$dname Менеджер юнит-тестов скриптов 4 +$addin SnegopatMainScript 5 +$addin global 6 +$addin stdlib 7 + 8 +global.connectGlobals(SelfScript) 9 + 10 +var jsUnitCore = stdlib.require("jsUnitCore.js"); 11 + 12 +/* Анонимный обработчик, который мы передаем, позволяет обойти проблему 13 +с отловом исключений, брошенных в контексте скрипта-библиотеки. */ 14 +jsUnitCore.SetErrorHandler(function (exception) { throw exception; }); 15 + 16 +OpenTestRunner(); 17 + 18 +//////////////////////////////////////////////////////////////////////////////////////// 19 +//// TestRunner 20 +//// 21 + 22 +function TestRunner() 23 +{ 24 + TestRunner._instance = this; 25 + 26 + this.errorCount = 0; 27 + this.successCount = 0; 28 + this.failureCount = 0; 29 + 30 + this.form = loadScriptForm("scripts\\DevTools\\testrunner.ssf", this) 31 + this.form.Открыть(); 32 + 33 + this.allTests = this.form.ЭлементыФормы.тпДеревоТестов.Значение; 34 + this.allTests.Колонки.Добавить("object"); 35 + 36 + this.loadedTestAddins = []; 37 + 38 + // Варианты состояний выполнения тестов 39 + this.STATE_NOT_RUN = 0; 40 + this.STATE_SUCCESS = 1; 41 + this.STATE_IGNORE = 2; 42 + this.STATE_FAILURE = 3; 43 + 44 + // Иконки состояний. 45 + this.StateIcons = { 46 + Gray : this.form.ЭлементыФормы.ПолеКартинкиСерый.Картинка, 47 + Green: this.form.ЭлементыФормы.ПолеКартинкиЗеленый.Картинка, 48 + Yellow: this.form.ЭлементыФормы.ПолеКартинкиЖелтый.Картинка, 49 + Red: this.form.ЭлементыФормы.ПолеКартинкиКрасный.Картинка 50 + } 51 +} 52 + 53 +TestRunner.prototype.resetCounters = function() 54 +{ 55 + this.errorCount = 0; 56 + this.successCount = 0; 57 + this.failureCount = 0; 58 + 59 + this.updateTotals(); 60 +} 61 + 62 +TestRunner.prototype.updateTotals = function () 63 +{ 64 + this.form.ЭлементыФормы.КоличествоТестовВсего.Значение = this.testsCount; 65 + this.form.ЭлементыФормы.КоличествоУспешныхТестов.Значение = this.successCount; 66 + this.form.ЭлементыФормы.КоличествоПроваленныхТестов.Значение = this.failureCount; 67 +} 68 + 69 +TestRunner.prototype.initProgressBar = function () 70 +{ 71 + this.switchProgressBar(true); 72 + this.form.ЭлементыФормы.ИндикаторВыполнения.МинимальноеЗначение = 0; 73 + this.form.ЭлементыФормы.ИндикаторВыполнения.МаксимальноеЗначение = this.testsCount; 74 + this.form.ЭлементыФормы.ИндикаторВыполнения.Шаг = 1; 75 + this.form.ЭлементыФормы.ИндикаторВыполнения.Значение = 0; 76 +} 77 + 78 +TestRunner.prototype.progressBarDoStep = function () 79 +{ 80 + this.form.ЭлементыФормы.ИндикаторВыполнения.Значение = this.form.ЭлементыФормы.ИндикаторВыполнения.Значение + 1; 81 +} 82 + 83 +TestRunner.prototype.switchProgressBar = function (progressBarVisible) 84 +{ 85 + this.form.ЭлементыФормы.НадписьВсего.Видимость = !progressBarVisible; 86 + this.form.ЭлементыФормы.КоличествоТестовВсего.Видимость = !progressBarVisible; 87 + this.form.ЭлементыФормы.НадписьУспешно.Видимость = !progressBarVisible; 88 + this.form.ЭлементыФормы.КоличествоУспешныхТестов.Видимость = !progressBarVisible; 89 + this.form.ЭлементыФормы.НадписьПровалено.Видимость = !progressBarVisible; 90 + this.form.ЭлементыФормы.КоличествоПроваленныхТестов.Видимость = !progressBarVisible; 91 + this.form.ЭлементыФормы.ИндикаторВыполнения.Видимость = !!progressBarVisible; 92 +} 93 + 94 +TestRunner.prototype.unloadAllTests = function () 95 +{ 96 + this.allTests.Строки.Очистить(); 97 + 98 + for (var i=0; i<this.loadedTestAddins.length; i++) 99 + { 100 + if (this.loadedTestAddins[i].uniqueName) 101 + addins.unloadAddin(this.loadedTestAddins[i]); 102 + } 103 + 104 + this.loadedTestAddins = []; 105 +} 106 + 107 +TestRunner.prototype.loadTests = function(path) 108 +{ 109 + this.unloadAllTests(); 110 + 111 + this.testsCount = 0; 112 + 113 + this.walkFilesAndLoad(path, this.allTests); 114 + 115 + if (this.allTests.Строки.Количество() == 0) 116 + { 117 + Message("В каталоге " + path + " тест-кейсов не найдено!"); 118 + return; 119 + } 120 + 121 + // Развернем все уровни дерева. 122 + for(var i=0; i<this.allTests.Строки.Количество(); i++) 123 + this.form.ЭлементыФормы.тпДеревоТестов.Развернуть(this.allTests.Строки.Получить(i), true); 124 + 125 + this.updateTotals(); 126 +} 127 + 128 +TestRunner.prototype.isTestAddinFile = function(file) 129 +{ 130 + // Имя тестового скрипта должно начинаться с префикса "test" 131 + if (!file.Name.match(/^test/i)) 132 + return false; 133 + 134 + // Поддерживаются пока только скрипты. 135 + if (!file.Extension.match(/js|vbs/i)) 136 + return false; 137 + 138 + return true; 139 +} 140 + 141 +TestRunner.prototype.walkFilesAndLoad = function(path, parentNode) 142 +{ 143 + var f = v8New("File", path); 144 + 145 + var files = f.IsFile() ? [ f ] : FindFiles(path, "*", false); 146 + 147 + for (var i=0; i<files.length; i++) 148 + { 149 + var Файл = files[i]; 150 + 151 + if (Файл.ЭтоКаталог()) 152 + { 153 + var newNode = this.addTestGroup(parentNode, Файл); 154 + this.walkFilesAndLoad(Файл.ПолноеИмя, newNode); 155 + 156 + // Пустые каталоги не показываем в дереве тестов. 157 + if (newNode.Rows.Count() == 0) 158 + parentNode.Rows.Delete(newNode); 159 + } 160 + else if (this.isTestAddinFile(Файл)) 161 + { 162 + try 163 + { 164 + var testAddin = this.loadTestAddin(Файл.ПолноеИмя); 165 + 166 + if (testAddin) 167 + { 168 + var newNode = this.addTestCase(parentNode, testAddin); 169 + 170 + if (newNode.Rows.Count() == 0) 171 + { 172 + jsUnitCore.warn("Скрипт не содержит макросов и не будет загружен: " + testAddin.fullPath); 173 + parentNode.Rows.Delete(newNode); 174 + 175 + addins.unloadAddin(testAddin); 176 + 177 + if(!testAddin.uniqueName.length) 178 + delete testAddin; 179 + } 180 + else 181 + { 182 + this.loadedTestAddins.push(testAddin); 183 + } 184 + } 185 + } 186 + catch (e) 187 + { 188 + jsUnitCore.warn("Ошибка загрузки скрипта: " + Файл.ПолноеИмя); 189 + // TODO: выводить информацию об ошибке подробнее. 190 + } 191 + } 192 + } 193 +} 194 + 195 +TestRunner.prototype.loadTestAddin = function(path) 196 +{ 197 + var fullLoadString = "script:" + path; 198 + 199 + var testAddin = addins.byFullPath(fullLoadString); 200 + 201 + if (!testAddin) 202 + { 203 + // Тест-аддины будем подгружать в группу "Подгружаемые библиотеки". 204 + libGroup = SnegopatMainScript.AddinsTreeGroups.LoadedLibs; 205 + 206 + // Загружаем тестовый аддин. 207 + try 208 + { 209 + testAddin = addins.loadAddin(fullLoadString, libGroup); 210 + } 211 + catch(e) 212 + { 213 + jsUnitCore("TestRunner::loadTestAddin: Тестовый скрипт не загружен: " + path); 214 + return null; 215 + } 216 + } 217 + 218 + return testAddin; 219 +} 220 + 221 +TestRunner.prototype.addTestGroup = function(parentNode, Файл) 222 +{ 223 + var newNode = parentNode.Строки.Добавить(); 224 + newNode.НазваниеТеста = Файл.Имя; 225 + newNode.ВремяВыполнения = 0; 226 + newNode.ПолныйПуть = Файл.ПолноеИмя; 227 + newNode.Состояние = this.STATE_NOT_RUN; 228 + newNode.object = null; 229 + return newNode; 230 +} 231 + 232 +TestRunner.prototype.addTestCase = function(parentNode, testAddin) 233 +{ 234 + var newNode = parentNode.Rows.Add(); 235 + newNode.НазваниеТеста = testAddin.uniqueName; 236 + newNode.ВремяВыполнения = 0; 237 + newNode.ПолныйПуть = testAddin.fullPath; 238 + newNode.Состояние = this.STATE_NOT_RUN; 239 + newNode.object = testAddin; 240 + 241 + // Добавим тест-методы. Тест-метод - это макросы с именами вида macrosTestИмяТеста. 242 + var macroses = new VBArray(testAddin.macroses()).toArray(); 243 + for(var m in macroses) 244 + if (macroses[m].match(/^Test/)) 245 + this.addTest(newNode, macroses[m], testAddin); 246 + 247 + return newNode; 248 +} 249 + 250 +TestRunner.prototype.addTest = function(parentNode, testName, testAddin) 251 +{ 252 + var newNode = parentNode.Строки.Добавить(); 253 + newNode.НазваниеТеста = testName; 254 + newNode.ВремяВыполнения = 0; 255 + newNode.ПолныйПуть = testAddin.fullPath; 256 + newNode.Состояние = this.STATE_NOT_RUN; 257 + newNode.object = new Test(testAddin, testName); 258 + 259 + this.testsCount++; 260 + 261 + return newNode; 262 +} 263 + 264 +TestRunner.prototype.runAllTests = function() 265 +{ 266 + for (var i = 0; i < this.allTests.Строки.Количество(); i++) 267 + { 268 + var ТекущаяСтрока = this.allTests.Строки.Получить(i); 269 + 270 + var beginTime = new Date(); 271 + 272 + ТекущаяСтрока.Состояние = this.runTest(ТекущаяСтрока); 273 + 274 + ТекущаяСтрока.ВремяВыполнения = (new Date() - beginTime) / 1000; 275 + } 276 +} 277 + 278 +TestRunner.prototype.runTest = function (СтрокаТестов) 279 +{ 280 + var Состояние = this.STATE_SUCCESS; 281 + 282 + if (СтрокаТестов.object && jsUnitCore.JsUnit._trueTypeOf(СтрокаТестов.object) == 'Test') 283 + { 284 + Состояние = this.executeTestFunction(СтрокаТестов); 285 + this.progressBarDoStep(); 286 + } 287 + else 288 + { 289 + if (СтрокаТестов.Строки.Количество() == 0) 290 + return this.STATE_IGNORE; 291 + 292 + for (var i = 0; i < СтрокаТестов.Строки.Количество(); i++) 293 + { 294 + var ТекущаяСтрока = СтрокаТестов.Строки.Получить(i); 295 + 296 + var beginTime = new Date(); 297 + 298 + ТекущаяСтрока.Состояние = this.runTest(ТекущаяСтрока); 299 + 300 + ТекущаяСтрока.ВремяВыполнения = (new Date() - beginTime) / 1000; 301 + 302 + if (ТекущаяСтрока.Состояние != this.STATE_SUCCESS) 303 + Состояние = this.STATE_FAILURE; 304 + 305 + } 306 + 307 + } 308 + 309 + return Состояние; 310 +} 311 + 312 +TestRunner.prototype.setTestStatus = function(test, excep) 313 +{ 314 + var message = 'Тест ' + test.fullTestName + ' '; 315 + 316 + if (excep == null) 317 + { 318 + test.status = this.STATE_SUCCESS; 319 + this.successCount++; 320 + message += 'выполнен успешно'; 321 + } 322 + else 323 + { 324 + test.exception = excep; 325 + 326 + if (!excep.isJsUnitFailure) 327 + { 328 + this.errorCount++; 329 + test.status = this.STATE_FAILURE; 330 + message += ' остановлен из-за ошибки в нем (exception or error)'; 331 + } 332 + else 333 + { 334 + //debugger; 335 + this.failureCount++; 336 + test.status = this.STATE_FAILURE; 337 + message += " провалился (assertion failed)" 338 + + (excep.comment ? "\n\t" + excep.comment : "") 339 + + (excep.jsUnitMessage ? "\n\t" + excep.jsUnitMessage : ""); 340 + } 341 + } 342 + 343 + test.message = message; 344 + 345 + Message(message); 346 + 347 + return test.status; 348 +} 349 + 350 +TestRunner.prototype.executeTestFunction = function(СтрокаТеста) 351 +{ 352 + var theTest = СтрокаТеста.object; 353 + var testAddin = theTest.addin; 354 + var testFunctionName = 'macros' + theTest.testName; 355 + 356 + var exception = null; 357 + var timeBefore = new Date(); 358 + 359 + try 360 + { 361 + if (testAddin.object.setUp !== jsUnitCore.JSUNIT_UNDEFINED_VALUE) 362 + testAddin.object.setUp(); 363 + 364 + testAddin.object[testFunctionName].call(null); 365 + } 366 + catch (e1) 367 + { 368 + exception = e1; 369 + } 370 + finally 371 + { 372 + try 373 + { 374 + if (testAddin.object.tearDown !== jsUnitCore.JSUNIT_UNDEFINED_VALUE) 375 + testAddin.object.tearDown(); 376 + } 377 + catch (e2) 378 + { 379 + //Unlike JUnit, only assign a tearDown exception to excep if there is not already an exception from the test body 380 + if (exception == null) 381 + exception = e2; 382 + } 383 + } 384 + 385 + СтрокаТеста.ВремяВыполнения = (new Date() - timeBefore) / 1000; 386 + 387 + return this.setTestStatus(theTest, exception); 388 +} 389 + 390 +TestRunner.prototype.getDefaultTestsDir = function() 391 +{ 392 + var mainFolder = profileRoot.getValue("Snegopat/MainFolder"); 393 + var f = v8New("Файл", mainFolder + "scripts\\Tests"); 394 + if (f.Существует() && f.ЭтоКаталог()) 395 + return f.ПолноеИмя; 396 + 397 + return mainFolder; 398 +} 399 + 400 +//////////////////////////////////////////////////////////////////////////////////////// 401 +//// ОБРАБОТЧИКИ СОБЫТИЙ ФОРМЫ И ЕЕ ЭЛЕМЕНТОВ. 402 +//// 403 + 404 +TestRunner.prototype.КнопкаЗагрузитьТестыНажатие = function(Элемент) 405 +{ 406 + var ВыборКаталога = v8New("ДиалогВыбораФайла", РежимДиалогаВыбораФайла.ВыборКаталога); 407 + ВыборКаталога.ПолноеИмяФайла = ""; 408 + ВыборКаталога.Заголовок = "Выберите каталог c тестами"; 409 + ВыборКаталога.Каталог = this.getDefaultTestsDir(); 410 + 411 + if (ВыборКаталога.Выбрать()) 412 + { 413 + this.form.Путь = ВыборКаталога.Каталог; 414 + this.loadTests(ВыборКаталога.Каталог); 415 + } 416 +} 417 + 418 +TestRunner.prototype.КнопкаЗагрузитьТестыЗагрузитьТестКейс = function (Элемент) 419 +{ 420 + var ВыборФайла = v8New("ДиалогВыбораФайла", РежимДиалогаВыбораФайла.Открытие); 421 + ВыборФайла.Заголовок = "Выберите тестовый скрипт"; 422 + ВыборФайла.Каталог = this.getDefaultTestsDir(); 423 + 424 + if (ВыборФайла.Выбрать()) 425 + { 426 + this.form.Путь = ВыборФайла.ПолноеИмяФайла; 427 + this.loadTests(ВыборФайла.ПолноеИмяФайла); 428 + } 429 +} 430 + 431 +TestRunner.prototype.КнопкаПерезагрузитьНажатие = function (Элемент) 432 +{ 433 + if (this.form.Путь == "") 434 + { 435 + Предупреждение("Сначала загрузите тесты!"); 436 + return; 437 + } 438 + 439 + this.switchProgressBar(false); 440 + this.resetCounters(); 441 + this.loadTests(this.form.Путь); 442 +} 443 + 444 +TestRunner.prototype.КнопкаВыполнитьВсеТестыНажатие = function (Элемент) 445 +{ 446 + this.resetCounters(); 447 + this.initProgressBar(); 448 + 449 + this.runAllTests(); 450 + 451 + this.updateTotals(); 452 + this.switchProgressBar(false); 453 +} 454 + 455 +TestRunner.prototype.КнопкаВыполнитьВыделенныйНажатие = function (Элемент) 456 +{ 457 + Message("Не реализовано"); 458 +} 459 + 460 +TestRunner.prototype.тпДеревоТестовПриВыводеСтроки = function(Элемент, ОформлениеСтроки, ДанныеСтроки) 461 +{ 462 + var Ячейки = ОформлениеСтроки.val.Ячейки; 463 + 464 + // Устанавливаем иконку состояния выполнения. 465 + var Состояние = ДанныеСтроки.val.Состояние; 466 + 467 + if (Состояние == this.STATE_SUCCESS) 468 + Ячейки.НазваниеТеста.УстановитьКартинку(this.StateIcons.Green) 469 + 470 + else if (Состояние == this.STATE_IGNORE) 471 + Ячейки.НазваниеТеста.УстановитьКартинку(this.StateIcons.Yellow) 472 + 473 + else if (Состояние == this.STATE_FAILURE) 474 + Ячейки.НазваниеТеста.УстановитьКартинку(this.StateIcons.Red) 475 + 476 + else 477 + Ячейки.НазваниеТеста.УстановитьКартинку(this.StateIcons.Gray) 478 + 479 +} 480 + 481 +TestRunner.prototype.ПриОткрытии = function () 482 +{ 483 + this.resetCounters(); 484 + this.switchProgressBar(false); 485 +} 486 + 487 +TestRunner.prototype.ПриЗакрытии = function () 488 +{ 489 + this.unloadAllTests(); 490 +} 491 +//////////////////////////////////////////////////////////////////////////////////////// 492 +//// ВСПОМОГАТЕЛЬНЫЕ ОБЪЕКТЫ И ФУНКЦИИ. 493 +//// 494 + 495 +function FindFiles(path, mask) 496 +{ 497 + // Из snegopat.js. 498 + // TODO: Перенести в библиотеку Utils. 499 + // На NT-системах порядок выдачи файлов в FindFirstFile/FindNextFile неопределен, те они НЕОБЯЗАТЕЛЬНО 500 + // выдаются отсортированными по именам, поэтому на разных машинах могут выдаваться в разном порядке. 501 + // Кроме того, каталоги и файлы могут выдаваться вперемешку. 502 + // Также в документации к НайтиФайлы нет никакого упоминания о порядке выдачи файлов. 503 + // В случае зависимости одного стандартного скрипта от другого (например, snegopatwnd.js при 504 + // загрузке сразу обращается к global_context.js) это может привести к проблемам. 505 + // Поэтом примем такой порядок загрузки: 506 + // Сначала загружаются все подкатологи, отсортированные по имени. 507 + // Затем загржаются все файлы, отсортированные по имени. 508 + 509 + var allFiles = new Array(); 510 + var files = new Array(); 511 + 512 + var filesArray = new Enumerator(globalContext("{22A21030-E1D6-46A0-9465-F0A5427BE011}").НайтиФайлы(path.replace(/\\/g, '/'), "*", false)); 513 + for ( ; !filesArray.atEnd(); filesArray.moveNext()) 514 + { 515 + var file = filesArray.item(); 516 + (file.ЭтоКаталог() ? allFiles : files).push(file); 517 + } 518 + 519 + var sortByNames = function (i1, i2) { 520 + return i1.Имя.toLowerCase().localeCompare(i2.Имя.toLowerCase()) 521 + }; 522 + 523 + allFiles.sort(sortByNames); 524 + files.sort(sortByNames); 525 + 526 + for (var i=0; i<files.length; i++) 527 + allFiles.push(files[i]); 528 + 529 + return allFiles; 530 +} 531 + 532 +function Test(addin, testName) 533 +{ 534 + this.addin = addin; 535 + this.fullTestName = addin.uniqueName + "::" + testName; 536 + this.testName = testName; 537 + this.exeption = null; 538 + this.message = ""; 539 +} 540 + 541 +function OpenTestRunner() 542 +{ 543 + if (!TestRunner._instance) 544 + new TestRunner(); 545 + 546 + return TestRunner._instance; 547 +} 548 + 549 + 550 + 551 +
Added DevTools/testrunner.ssf.
cannot compute difference between binary files
Added Libs/jsUnitCore.js.
1 +$engine JScript 2 +$uname jsUnitCore 3 +$dname Библиотека юнит-тестирования для JavaScript 4 +$addin global 5 + 6 +/** 7 + * @fileoverview 8 + * jsUnitCore.js contains the implementation of the core JsUnit functionality: assertions, JsUnitTestSuites, and JsUnit.Failure. 9 + * An HTML page is considered to be a JsUnit Test Page if it "includes" jsUnitCore.js, i.e. the following line is present: 10 + * <code> 11 + * <script type="text/javascript" src="/path/to/jsUnitCore.js"></script> 12 + * </code> 13 + * @author Edward Hieatt, edward@jsunit.net, http://www.jsunit.net 14 + */ 15 + 16 + /** 17 + * Порт библиотеки jsUnitCore.js (http://jsunit.net) для проекта "Снегопат" (http://snegopat.ru). 18 + * Автор порта: Александр Кунташов, kuntashov@gmail.com 19 + */ 20 + 21 +var JsUnit = {}; 22 + 23 +//Snegopat. 24 +// Обход проблемы перехвата в вызывающем методе исключений, 25 +// брошенных в методе другого скрипта. 26 +var _callerErrorHandler = null; 27 + 28 +function SetErrorHandler(errorHandler) 29 +{ 30 + if (_callerErrorHandler && errorHandler && _callerErrorHandler != errorHandler) 31 + { 32 + /* Пока поддерживаем только одного подписчика на ошибки. 33 + Чтобы исключить случайные выстрелы в ногу, исключим любые 34 + другие попытки установки обработчика. */ 35 + warn("jsUnitCore.js::GetInsance(): только один скрипт может установить обработчик ошибок!"); 36 + 37 + } 38 + else 39 + { 40 + _callerErrorHandler = errorHandler; 41 + } 42 +} 43 + 44 +function SnegopatThrowException(exception) 45 +{ 46 + if (_callerErrorHandler) 47 + _callerErrorHandler.call(null, exception); 48 + 49 + throw exception; 50 +} 51 +/////Snegopat. 52 + 53 +/** 54 + * The JsUnit version 55 + * @version 56 + */ 57 +JsUnit.VERSION = 2.2; 58 +var JSUNIT_VERSION = JsUnit.VERSION; 59 + 60 +/** 61 + * For convenience, a variable that equals "undefined" 62 + */ 63 +var JSUNIT_UNDEFINED_VALUE; 64 + 65 +/** 66 + * Whether or not the current test page has been (completely) loaded yet 67 + */ 68 +var isTestPageLoaded = false; 69 +/** 70 + * Predicate used for testing JavaScript == (i.e. equality excluding type) 71 + */ 72 +JsUnit.DOUBLE_EQUALITY_PREDICATE = function(var1, var2) {return var1 == var2;}; 73 + 74 +/** 75 + * Predicate used for testing JavaScript === (i.e. equality including type) 76 + */ 77 +JsUnit.TRIPLE_EQUALITY_PREDICATE = function(var1, var2) {return var1 === var2;}; 78 + 79 +/** 80 + * Predicate used for testing whether two obects' toStrings are equal 81 + */ 82 +JsUnit.TO_STRING_EQUALITY_PREDICATE = function(var1, var2) {return var1.toString() === var2.toString();}; 83 + 84 +/** 85 + * Hash of predicates for testing equality by primitive type 86 + */ 87 +JsUnit.PRIMITIVE_EQUALITY_PREDICATES = { 88 + 'String': JsUnit.DOUBLE_EQUALITY_PREDICATE, 89 + 'Number': JsUnit.DOUBLE_EQUALITY_PREDICATE, 90 + 'Boolean': JsUnit.DOUBLE_EQUALITY_PREDICATE, 91 + 'Date': JsUnit.TRIPLE_EQUALITY_PREDICATE, 92 + 'RegExp': JsUnit.TO_STRING_EQUALITY_PREDICATE, 93 + 'Function': JsUnit.TO_STRING_EQUALITY_PREDICATE 94 +} 95 + 96 +/** 97 + * Hack for NS62 bug 98 + * @private 99 + */ 100 +JsUnit._fixTop = function() { 101 + var tempTop = top; 102 + if (!tempTop) { 103 + tempTop = window; 104 + while (tempTop.parent) { 105 + tempTop = tempTop.parent; 106 + if (tempTop.top && tempTop.top.jsUnitTestSuite) { 107 + tempTop = tempTop.top; 108 + break; 109 + } 110 + } 111 + } 112 + try { 113 + window.top = tempTop; 114 + } catch (e) { 115 + } 116 +} 117 + 118 +//Snegopat. 119 +//JsUnit._fixTop(); 120 +/////Snegopat. 121 + 122 +/** 123 + * @param Any object 124 + * @return String - the type of the given object 125 + * @private 126 + */ 127 +JsUnit._trueTypeOf = function(something) { 128 + var result = typeof something; 129 + try { 130 + switch (result) { 131 + case 'string': 132 + break; 133 + case 'boolean': 134 + break; 135 + case 'number': 136 + break; 137 + case 'object': 138 + case 'function': 139 + switch (something.constructor) { 140 + case new String().constructor: 141 + result = 'String'; 142 + break; 143 + case new Boolean().constructor: 144 + result = 'Boolean'; 145 + break; 146 + case new Number().constructor: 147 + result = 'Number'; 148 + break; 149 + case new Array().constructor: 150 + result = 'Array'; 151 + break; 152 + case new RegExp().constructor: 153 + result = 'RegExp'; 154 + break; 155 + case new Date().constructor: 156 + result = 'Date'; 157 + break; 158 + case Function: 159 + result = 'Function'; 160 + break; 161 + default: 162 + if (something.constructor) 163 + { 164 + var m = something.constructor.toString().match(/function\s*([^( ]+)\(/); 165 + if (m) 166 + result = m[1]; 167 + else 168 + break; 169 + } 170 + else 171 + break; 172 + } 173 + break; 174 + } 175 + } 176 + finally { 177 + result = result.substr(0, 1).toUpperCase() + result.substr(1); 178 + return result; 179 + } 180 +} 181 + 182 +/** 183 + * @private 184 + */ 185 +JsUnit._displayStringForValue = function(aVar) { 186 + var result = '<' + aVar + '>'; 187 + if (!(aVar === null || aVar === JSUNIT_UNDEFINED_VALUE)) { 188 + result += ' (' + JsUnit._trueTypeOf(aVar) + ')'; 189 + } 190 + return result; 191 +} 192 + 193 +/** 194 + * @private 195 + */ 196 +JsUnit._argumentsIncludeComments = function(expectedNumberOfNonCommentArgs, args) { 197 + return args.length == expectedNumberOfNonCommentArgs + 1; 198 +} 199 +/** 200 + * @private 201 + */ 202 +JsUnit._commentArg = function(expectedNumberOfNonCommentArgs, args) { 203 + if (JsUnit._argumentsIncludeComments(expectedNumberOfNonCommentArgs, args)) 204 + return args[0]; 205 + 206 + return null; 207 +} 208 +/** 209 + * @private 210 + */ 211 +JsUnit._nonCommentArg = function(desiredNonCommentArgIndex, expectedNumberOfNonCommentArgs, args) { 212 + return JsUnit._argumentsIncludeComments(expectedNumberOfNonCommentArgs, args) ? 213 + args[desiredNonCommentArgIndex] : 214 + args[desiredNonCommentArgIndex - 1]; 215 +} 216 + 217 +/** 218 + * @private 219 + */ 220 +JsUnit._validateArguments = function(expectedNumberOfNonCommentArgs, args) { 221 + if (!( args.length == expectedNumberOfNonCommentArgs || 222 + (args.length == expectedNumberOfNonCommentArgs + 1 && (typeof(args[0]) == 'string') || args[0] == null))) 223 + throw new JsUnit.AssertionArgumentError('Incorrect arguments passed to assert function'); 224 +} 225 + 226 +/** 227 + * @private 228 + */ 229 +JsUnit._checkEquals = function(var1, var2) { 230 + return var1 === var2; 231 +} 232 + 233 +/** 234 + * @private 235 + */ 236 +JsUnit._checkNotUndefined = function(aVar) { 237 + return aVar !== JSUNIT_UNDEFINED_VALUE; 238 +} 239 + 240 +/** 241 + * @private 242 + */ 243 +JsUnit._checkNotNull = function(aVar) { 244 + return aVar !== null; 245 +} 246 + 247 +/** 248 + * All assertions ultimately go through this method. 249 + * @private 250 + */ 251 +JsUnit._assert = function(comment, booleanValue, failureMessage) { 252 + if (!booleanValue) 253 + SnegopatThrowException(new JsUnit.Failure(comment, failureMessage)); 254 + //throw new JsUnit.Failure(comment, failureMessage); 255 +} 256 + 257 +/** 258 + * Checks that the given boolean value is true. 259 + * @param comment optional, displayed in the case of failure 260 + * @value value that is expected to be true 261 + * @throws JsUnit.Failure if the given value is not true 262 + * @throws JsUnitInvalidAssertionArgument if the given value is not a boolean or if an incorrect number of arguments is passed 263 + */ 264 +function assert() { 265 + JsUnit._validateArguments(1, arguments); 266 + var booleanValue = JsUnit._nonCommentArg(1, 1, arguments); 267 + 268 + if (typeof(booleanValue) != 'boolean') 269 + SnegopatThrowException(new JsUnit.AssertionArgumentError('Bad argument to assert(boolean)')); 270 + //throw new JsUnit.AssertionArgumentError('Bad argument to assert(boolean)'); 271 + 272 + JsUnit._assert(JsUnit._commentArg(1, arguments), booleanValue === true, 'Call to assert(boolean) with false'); 273 +} 274 + 275 +/** 276 + * Synonym for assertTrue 277 + * @see #assert 278 + */ 279 +function assertTrue() { 280 + JsUnit._validateArguments(1, arguments); 281 + assert(JsUnit._commentArg(1, arguments), JsUnit._nonCommentArg(1, 1, arguments)); 282 +} 283 + 284 +/** 285 + * Checks that a boolean value is false. 286 + * @param comment optional, displayed in the case of failure 287 + * @value value that is expected to be false 288 + * @throws JsUnit.Failure if value is not false 289 + * @throws JsUnitInvalidAssertionArgument if the given value is not a boolean or if an incorrect number of arguments is passed 290 + */ 291 +function assertFalse() { 292 + JsUnit._validateArguments(1, arguments); 293 + var booleanValue = JsUnit._nonCommentArg(1, 1, arguments); 294 + 295 + if (typeof(booleanValue) != 'boolean') 296 + throw new JsUnit.AssertionArgumentError('Bad argument to assertFalse(boolean)'); 297 + 298 + JsUnit._assert(JsUnit._commentArg(1, arguments), booleanValue === false, 'Call to assertFalse(boolean) with true'); 299 +} 300 + 301 +/** 302 + * Checks that two values are equal (using ===) 303 + * @param comment optional, displayed in the case of failure 304 + * @param expected the expected value 305 + * @param actual the actual value 306 + * @throws JsUnit.Failure if the values are not equal 307 + * @throws JsUnitInvalidAssertionArgument if an incorrect number of arguments is passed 308 + */ 309 +function assertEquals() { 310 + JsUnit._validateArguments(2, arguments); 311 + var var1 = JsUnit._nonCommentArg(1, 2, arguments); 312 + var var2 = JsUnit._nonCommentArg(2, 2, arguments); 313 + JsUnit._assert(JsUnit._commentArg(2, arguments), JsUnit._checkEquals(var1, var2), 'Expected ' + JsUnit._displayStringForValue(var1) + ' but was ' + JsUnit._displayStringForValue(var2)); 314 +} 315 + 316 +/** 317 + * Checks that two values are not equal (using !==) 318 + * @param comment optional, displayed in the case of failure 319 + * @param value1 a value 320 + * @param value2 another value 321 + * @throws JsUnit.Failure if the values are equal 322 + * @throws JsUnitInvalidAssertionArgument if an incorrect number of arguments is passed 323 + */ 324 +function assertNotEquals() { 325 + JsUnit._validateArguments(2, arguments); 326 + var var1 = JsUnit._nonCommentArg(1, 2, arguments); 327 + var var2 = JsUnit._nonCommentArg(2, 2, arguments); 328 + JsUnit._assert(JsUnit._commentArg(2, arguments), var1 !== var2, 'Expected not to be ' + JsUnit._displayStringForValue(var2)); 329 +} 330 + 331 +/** 332 + * Checks that a value is null 333 + * @param comment optional, displayed in the case of failure 334 + * @param value the value 335 + * @throws JsUnit.Failure if the value is not null 336 + * @throws JsUnitInvalidAssertionArgument if an incorrect number of arguments is passed 337 + */ 338 +function assertNull() { 339 + JsUnit._validateArguments(1, arguments); 340 + var aVar = JsUnit._nonCommentArg(1, 1, arguments); 341 + JsUnit._assert(JsUnit._commentArg(1, arguments), aVar === null, 'Expected ' + JsUnit._displayStringForValue(null) + ' but was ' + JsUnit._displayStringForValue(aVar)); 342 +} 343 + 344 +/** 345 + * Checks that a value is not null 346 + * @param comment optional, displayed in the case of failure 347 + * @param value the value 348 + * @throws JsUnit.Failure if the value is null 349 + * @throws JsUnitInvalidAssertionArgument if an incorrect number of arguments is passed 350 + */ 351 +function assertNotNull() { 352 + JsUnit._validateArguments(1, arguments); 353 + var aVar = JsUnit._nonCommentArg(1, 1, arguments); 354 + JsUnit._assert(JsUnit._commentArg(1, arguments), JsUnit._checkNotNull(aVar), 'Expected not to be ' + JsUnit._displayStringForValue(null)); 355 +} 356 + 357 +/** 358 + * Checks that a value is undefined 359 + * @param comment optional, displayed in the case of failure 360 + * @param value the value 361 + * @throws JsUnit.Failure if the value is not undefined 362 + * @throws JsUnitInvalidAssertionArgument if an incorrect number of arguments is passed 363 + */ 364 +function assertUndefined() { 365 + JsUnit._validateArguments(1, arguments); 366 + var aVar = JsUnit._nonCommentArg(1, 1, arguments); 367 + JsUnit._assert(JsUnit._commentArg(1, arguments), aVar === JSUNIT_UNDEFINED_VALUE, 'Expected ' + JsUnit._displayStringForValue(JSUNIT_UNDEFINED_VALUE) + ' but was ' + JsUnit._displayStringForValue(aVar)); 368 +} 369 + 370 +/** 371 + * Checks that a value is not undefined 372 + * @param comment optional, displayed in the case of failure 373 + * @param value the value 374 + * @throws JsUnit.Failure if the value is undefined 375 + * @throws JsUnitInvalidAssertionArgument if an incorrect number of arguments is passed 376 + */ 377 +function assertNotUndefined() { 378 + JsUnit._validateArguments(1, arguments); 379 + var aVar = JsUnit._nonCommentArg(1, 1, arguments); 380 + JsUnit._assert(JsUnit._commentArg(1, arguments), JsUnit._checkNotUndefined(aVar), 'Expected not to be ' + JsUnit._displayStringForValue(JSUNIT_UNDEFINED_VALUE)); 381 +} 382 + 383 +/** 384 + * Checks that a value is NaN (Not a Number) 385 + * @param comment optional, displayed in the case of failure 386 + * @param value the value 387 + * @throws JsUnit.Failure if the value is a number 388 + * @throws JsUnitInvalidAssertionArgument if an incorrect number of arguments is passed 389 + */ 390 +function assertNaN() { 391 + JsUnit._validateArguments(1, arguments); 392 + var aVar = JsUnit._nonCommentArg(1, 1, arguments); 393 + JsUnit._assert(JsUnit._commentArg(1, arguments), isNaN(aVar), 'Expected NaN'); 394 +} 395 + 396 +/** 397 + * Checks that a value is not NaN (i.e. is a number) 398 + * @param comment optional, displayed in the case of failure 399 + * @param value the value 400 + * @throws JsUnit.Failure if the value is not a number 401 + * @throws JsUnitInvalidAssertionArgument if an incorrect number of arguments is passed 402 + */ 403 +function assertNotNaN() { 404 + JsUnit._validateArguments(1, arguments); 405 + var aVar = JsUnit._nonCommentArg(1, 1, arguments); 406 + JsUnit._assert(JsUnit._commentArg(1, arguments), !isNaN(aVar), 'Expected not NaN'); 407 +} 408 + 409 +/** 410 + * Checks that an object is equal to another using === for primitives and their object counterparts but also desceding 411 + * into collections and calling assertObjectEquals for each element 412 + * @param comment optional, displayed in the case of failure 413 + * @param value the expected value 414 + * @param value the actual value 415 + * @throws JsUnit.Failure if the actual value does not equal the expected value 416 + * @throws JsUnitInvalidAssertionArgument if an incorrect number of arguments is passed 417 + */ 418 +function assertObjectEquals() { 419 + JsUnit._validateArguments(2, arguments); 420 + var var1 = JsUnit._nonCommentArg(1, 2, arguments); 421 + var var2 = JsUnit._nonCommentArg(2, 2, arguments); 422 + var failureMessage = JsUnit._commentArg(2, arguments) ? JsUnit._commentArg(2, arguments) : ''; 423 + if (var1 === var2) 424 + return; 425 + 426 + var isEqual = false; 427 + 428 + var typeOfVar1 = JsUnit._trueTypeOf(var1); 429 + var typeOfVar2 = JsUnit._trueTypeOf(var2); 430 + 431 + if (typeOfVar1 == typeOfVar2) { 432 + var primitiveEqualityPredicate = JsUnit.PRIMITIVE_EQUALITY_PREDICATES[typeOfVar1]; 433 + if (primitiveEqualityPredicate) { 434 + isEqual = primitiveEqualityPredicate(var1, var2); 435 + } else { 436 + var expectedKeys = JsUnit.Util.getKeys(var1).sort().join(", "); 437 + var actualKeys = JsUnit.Util.getKeys(var2).sort().join(", "); 438 + if (expectedKeys != actualKeys) { 439 + JsUnit._assert(failureMessage, false, 'Expected keys "' + expectedKeys + '" but found "' + actualKeys + '"'); 440 + } 441 + for (var i in var1) { 442 + assertObjectEquals(failureMessage + ' found nested ' + typeOfVar1 + '@' + i + '\n', var1[i], var2[i]); 443 + } 444 + isEqual = true; 445 + } 446 + } 447 + JsUnit._assert(failureMessage, isEqual, 'Expected ' + JsUnit._displayStringForValue(var1) + ' but was ' + JsUnit._displayStringForValue(var2)); 448 +} 449 + 450 +/** 451 + * Checks that an array is equal to another by checking that both are arrays and then comparing their elements using assertObjectEquals 452 + * @param comment optional, displayed in the case of failure 453 + * @param value the expected array 454 + * @param value the actual array 455 + * @throws JsUnit.Failure if the actual value does not equal the expected value 456 + * @throws JsUnitInvalidAssertionArgument if an incorrect number of arguments is passed 457 + */ 458 +function assertArrayEquals() { 459 + JsUnit._validateArguments(2, arguments); 460 + var array1 = JsUnit._nonCommentArg(1, 2, arguments); 461 + var array2 = JsUnit._nonCommentArg(2, 2, arguments); 462 + if (JsUnit._trueTypeOf(array1) != 'Array' || JsUnit._trueTypeOf(array2) != 'Array') { 463 + throw new JsUnit.AssertionArgumentError('Non-array passed to assertArrayEquals'); 464 + } 465 + assertObjectEquals(JsUnit._commentArg(2, arguments), JsUnit._nonCommentArg(1, 2, arguments), JsUnit._nonCommentArg(2, 2, arguments)); 466 +} 467 + 468 +/** 469 + * Checks that a value evaluates to true in the sense that value == true 470 + * @param comment optional, displayed in the case of failure 471 + * @param value the value 472 + * @throws JsUnit.Failure if the actual value does not evaluate to true 473 + * @throws JsUnitInvalidAssertionArgument if an incorrect number of arguments is passed 474 + */ 475 +function assertEvaluatesToTrue() { 476 + JsUnit._validateArguments(1, arguments); 477 + var value = JsUnit._nonCommentArg(1, 1, arguments); 478 + if (!value) 479 + fail(JsUnit._commentArg(1, arguments)); 480 +} 481 + 482 +/** 483 + * Checks that a value evaluates to false in the sense that value == false 484 + * @param comment optional, displayed in the case of failure 485 + * @param value the value 486 + * @throws JsUnit.Failure if the actual value does not evaluate to true 487 + * @throws JsUnitInvalidAssertionArgument if an incorrect number of arguments is passed 488 + */ 489 +function assertEvaluatesToFalse() { 490 + JsUnit._validateArguments(1, arguments); 491 + var value = JsUnit._nonCommentArg(1, 1, arguments); 492 + if (value) 493 + fail(JsUnit._commentArg(1, arguments)); 494 +} 495 + 496 +/** 497 + * Checks that a value is the same as an HTML string by "standardizing" both and comparing the result for equality. 498 + * Standardizing is done by temporarily creating a DIV, setting the innerHTML of the DIV to the string, and asking for 499 + * the innerHTML back. 500 + * @param comment optional, displayed in the case of failure 501 + * @param value1 the expected HTML string 502 + * @param value2 the actual HTML string 503 + * @throws JsUnit.Failure if the standardized actual value does not equal the standardized expected value 504 + * @throws JsUnitInvalidAssertionArgument if an incorrect number of arguments is passed 505 + */ 506 +function assertHTMLEquals() { 507 + 508 + //Snegopat. 509 + JsUnit.error("assertHTMLEquals() не поддерживается в Снегопате."); 510 + 511 + //JsUnit._validateArguments(2, arguments); 512 + //var var1 = JsUnit._nonCommentArg(1, 2, arguments); 513 + //var var2 = JsUnit._nonCommentArg(2, 2, arguments); 514 + //var var1Standardized = JsUnit.Util.standardizeHTML(var1); 515 + //var var2Standardized = JsUnit.Util.standardizeHTML(var2); 516 + 517 + //JsUnit._assert(JsUnit._commentArg(2, arguments), var1Standardized === var2Standardized, 'Expected ' + JsUnit._displayStringForValue(var1Standardized) + ' but was ' + JsUnit._displayStringForValue(var2Standardized)); 518 + /////Snegopat. 519 +} 520 + 521 +/** 522 + * Checks that a hash is has the same contents as another by iterating over the expected hash and checking that each 523 + * key's value is present in the actual hash and calling assertEquals on the two values, and then checking that there is 524 + * no key in the actual hash that isn't present in the expected hash. 525 + * @param comment optional, displayed in the case of failure 526 + * @param value the expected hash 527 + * @param value the actual hash 528 + * @throws JsUnit.Failure if the actual hash does not evaluate to true 529 + * @throws JsUnitInvalidAssertionArgument if an incorrect number of arguments is passed 530 + */ 531 +function assertHashEquals() { 532 + JsUnit._validateArguments(2, arguments); 533 + var var1 = JsUnit._nonCommentArg(1, 2, arguments); 534 + var var2 = JsUnit._nonCommentArg(2, 2, arguments); 535 + for (var key in var1) { 536 + assertNotUndefined("Expected hash had key " + key + " that was not found", var2[key]); 537 + assertEquals( 538 + "Value for key " + key + " mismatch - expected = " + var1[key] + ", actual = " + var2[key], 539 + var1[key], var2[key] 540 + ); 541 + } 542 + for (var key in var2) { 543 + assertNotUndefined("Actual hash had key " + key + " that was not expected", var1[key]); 544 + } 545 +} 546 + 547 +/** 548 + * Checks that two value are within a tolerance of one another 549 + * @param comment optional, displayed in the case of failure 550 + * @param value1 a value 551 + * @param value1 another value 552 + * @param tolerance the tolerance 553 + * @throws JsUnit.Failure if the two values are not within tolerance of each other 554 + * @throws JsUnitInvalidAssertionArgument if an incorrect number of arguments is passed 555 + */ 556 +function assertRoughlyEquals() { 557 + JsUnit._validateArguments(3, arguments); 558 + var expected = JsUnit._nonCommentArg(1, 3, arguments); 559 + var actual = JsUnit._nonCommentArg(2, 3, arguments); 560 + var tolerance = JsUnit._nonCommentArg(3, 3, arguments); 561 + assertTrue( 562 + "Expected " + expected + ", but got " + actual + " which was more than " + tolerance + " away", 563 + Math.abs(expected - actual) < tolerance 564 + ); 565 +} 566 + 567 +/** 568 + * Checks that a collection contains a value by checking that collection.indexOf(value) is not -1 569 + * @param comment optional, displayed in the case of failure 570 + * @param collection the collection 571 + * @param value the value 572 + * @throws JsUnit.Failure if the collection does not contain the value 573 + * @throws JsUnitInvalidAssertionArgument if an incorrect number of arguments are passed 574 + */ 575 +function assertContains() { 576 + JsUnit._validateArguments(2, arguments); 577 + var value = JsUnit._nonCommentArg(1, 2, arguments); 578 + var collection = JsUnit._nonCommentArg(2, 2, arguments); 579 + assertTrue( 580 + "Expected '" + collection + "' to contain '" + value + "'", 581 + collection.indexOf(value) != -1 582 + ); 583 +} 584 + 585 +/** 586 + * Checks that two arrays have the same contents, ignoring the order of the contents 587 + * @param comment optional, displayed in the case of failure 588 + * @param array1 first array 589 + * @param array2 second array 590 + * @throws JsUnit.Failure if the two arrays contain different contents 591 + * @throws JsUnitInvalidAssertionArgument if an incorrect number of arguments are passed 592 + */ 593 +function assertArrayEqualsIgnoringOrder() { 594 + JsUnit._validateArguments(2, arguments); 595 + var var1 = JsUnit._nonCommentArg(1, 2, arguments); 596 + var var2 = JsUnit._nonCommentArg(2, 2, arguments); 597 + 598 + var notEqualsMessage = "Expected arrays " + JsUnit._displayStringForValue(var1) + " and " + JsUnit._displayStringForValue(var2) + " to be equal (ignoring order)"; 599 + var notArraysMessage = "Expected arguments " + JsUnit._displayStringForValue(var1) + " and " + JsUnit._displayStringForValue(var2) + " to be arrays"; 600 + 601 + JsUnit._assert(JsUnit._commentArg(2, arguments), JsUnit._checkNotNull(var1), notEqualsMessage); 602 + JsUnit._assert(JsUnit._commentArg(2, arguments), JsUnit._checkNotNull(var2), notEqualsMessage); 603 + 604 + JsUnit._assert(JsUnit._commentArg(2, arguments), JsUnit._checkNotUndefined(var1.length), notArraysMessage); 605 + JsUnit._assert(JsUnit._commentArg(2, arguments), JsUnit._checkNotUndefined(var1.join), notArraysMessage); 606 + JsUnit._assert(JsUnit._commentArg(2, arguments), JsUnit._checkNotUndefined(var2.length), notArraysMessage); 607 + JsUnit._assert(JsUnit._commentArg(2, arguments), JsUnit._checkNotUndefined(var2.join), notArraysMessage); 608 + 609 + JsUnit._assert(JsUnit._commentArg(1, arguments), JsUnit._checkEquals(var1.length, var2.length), notEqualsMessage); 610 + 611 + for (var i = 0; i < var1.length; i++) { 612 + var found = false; 613 + for (var j = 0; j < var2.length; j++) { 614 + try { 615 + assertObjectEquals(notEqualsMessage, var1[i], var2[j]); 616 + found = true; 617 + } catch (ignored) { 618 + } 619 + } 620 + JsUnit._assert(JsUnit._commentArg(2, arguments), found, notEqualsMessage); 621 + } 622 +} 623 + 624 +/** 625 + * Synonym for assertArrayEqualsIgnoringOrder 626 + * @see #assertArrayEqualsIgnoringOrder 627 + */ 628 +function assertEqualsIgnoringOrder() { 629 + JsUnit._validateArguments(2, arguments); 630 + assertArrayEqualsIgnoringOrder(JsUnit._commentArg(2, arguments), JsUnit._nonCommentArg(1, 2, arguments), JsUnit._nonCommentArg(2, 2, arguments)); 631 +} 632 + 633 +/** 634 + * Causes a failure 635 + * @param failureMessage the message for the failure 636 + */ 637 +function fail(failureMessage) { 638 + throw new JsUnit.Failure("Call to fail()", failureMessage); 639 +} 640 + 641 +/** 642 + * Causes an error 643 + * @param errorMessage the message for the error 644 + */ 645 +function error(errorMessage) { 646 + throw new JsUnitError(errorMessage); 647 +} 648 + 649 +/** 650 + * @class 651 + * A JsUnit.Failure represents an assertion failure (or a call to fail()) during the execution of a Test Function 652 + * @param comment an optional comment about the failure 653 + * @param message the reason for the failure 654 + */ 655 +JsUnit.Failure = function(comment, message) { 656 + /** 657 + * Declaration that this is a JsUnit.Failure 658 + * @ignore 659 + */ 660 + this.isJsUnitFailure = true; 661 + /** 662 + * An optional comment about the failure 663 + */ 664 + this.comment = comment; 665 + /** 666 + * The reason for the failure 667 + */ 668 + this.jsUnitMessage = message; 669 + /** 670 + * The stack trace at the point at which the failure was encountered 671 + */ 672 + this.stackTrace = JsUnit.Util.getStackTrace(); 673 +} 674 + 675 +/** 676 + * @deprecated 677 + */ 678 +JsUnitFailure = JsUnit.Failure; 679 + 680 +/** 681 + * @class 682 + * A JsUnitError represents an error (an exception or a call to error()) during the execution of a Test Function 683 + * @param description the reason for the failure 684 + */ 685 +JsUnit.Error = function(description) { 686 + /** 687 + * The description of the error 688 + */ 689 + this.description = description; 690 + /** 691 + * The stack trace at the point at which the error was encountered 692 + */ 693 + this.stackTrace = JsUnit.Util.getStackTrace(); 694 +} 695 + 696 +/** 697 + * @deprecated 698 + */ 699 +JsUnitError = JsUnit.Error; 700 + 701 +/** 702 + * @class 703 + * A JsUnitAssertionArgumentError represents an invalid call to an assertion function - either an invalid argument type 704 + * or an incorrect number of arguments 705 + * @param description a description of the argument error 706 + */ 707 +JsUnit.AssertionArgumentError = function(description) { 708 + /** 709 + * A description of the argument error 710 + */ 711 + this.description = description; 712 +} 713 + 714 +function isLoaded() { 715 + return isTestPageLoaded; 716 +} 717 + 718 +/** 719 + * @private 720 + */ 721 +function setUp() { 722 +} 723 + 724 +/** 725 + * @private 726 + */ 727 +function tearDown() { 728 +} 729 + 730 +//Snegopat. 731 +// TODO: реализовать полноценный трейсер/логгер. 732 +function SnegopatTrace(message, value, marker) 733 +{ 734 + var text = message; 735 + 736 + if (value) 737 + text += ': ' + JsUnit._displayStringForValue(value); 738 + 739 + Message(text, marker); 740 +} 741 +/////Snegopat. 742 + 743 +function warn() { 744 + SnegopatTrace(arguments[0], arguments[1], mExc1); 745 +} 746 + 747 +function inform() { 748 + SnegopatTrace(arguments[0], arguments[1], mInfo); 749 +} 750 + 751 +function info() { 752 + SnegopatTrace(arguments[0], arguments[1]); 753 +} 754 + 755 +function debug() { 756 + SnegopatTrace(arguments[0], arguments[1], mNone); 757 +} 758 + 759 +/** 760 + * @class 761 + * A JsUnitTestSuite represents a suite of JsUnit Test Pages. Test Pages and Test Suites can be added to a 762 + * JsUnitTestSuite 763 + * @constructor 764 + */ 765 +function JsUnitTestSuite() { 766 + /** 767 + * Declares that this object is a JsUnitTestSuite 768 + */ 769 + this.isJsUnitTestSuite = true; 770 + /** 771 + * @private 772 + */ 773 + this._testPages = Array(); 774 + /** 775 + * @private 776 + */ 777 + this._pageIndex = 0; 778 + 779 + for (var i = 0; i < arguments.length; i++) { 780 + if (arguments[i]._testPages) { 781 + this.addTestSuite(arguments[i]); 782 + } else { 783 + this.addTestPage(arguments[i]); 784 + } 785 + } 786 +} 787 + 788 +/** 789 + * Adds a Test Page to the suite 790 + * @param pageName the path to the Test Page 791 + */ 792 +JsUnitTestSuite.prototype.addTestPage = function (page) { 793 + this._testPages[this._testPages.length] = page; 794 +} 795 + 796 +/** 797 + * Adds a Test Suite to the suite 798 + * @param suite another JsUnitTestSuite object 799 + */ 800 + 801 +JsUnitTestSuite.prototype.addTestSuite = function (suite) { 802 + for (var i = 0; i < suite._testPages.length; i++) 803 + this.addTestPage(suite._testPages[i]); 804 +} 805 + 806 +/** 807 + * Whether the suite contains any Test Pages 808 + */ 809 +JsUnitTestSuite.prototype.containsTestPages = function () { 810 + return this._testPages.length > 0; 811 +} 812 + 813 +/** 814 + * Moves the suite on to its next Test Page 815 + */ 816 +JsUnitTestSuite.prototype.nextPage = function () { 817 + return this._testPages[this._pageIndex++]; 818 +} 819 + 820 +/** 821 + * Whether the suite has more Test Pages 822 + */ 823 +JsUnitTestSuite.prototype.hasMorePages = function () { 824 + return this._pageIndex < this._testPages.length; 825 +} 826 + 827 +/** 828 + * Produces a copy of the suite 829 + */ 830 +JsUnitTestSuite.prototype.clone = function () { 831 + var clone = new JsUnitTestSuite(); 832 + clone._testPages = this._testPages; 833 + return clone; 834 +} 835 + 836 +//For legacy support - JsUnitTestSuite used to be called jsUnitTestSuite 837 +//Snegopat. 838 +// По неизвестным мне причинам эта конструкция приводит к тому, что 839 +// движок Снегопата перестает видеть макросы. 840 +//var jsUnitTestSuite = JsUnitTestSuite; 841 +/////Snegopat. 842 + 843 +function setJsUnitTracer(aJsUnitTracer) { 844 + top.tracer = aJsUnitTracer; 845 +} 846 + 847 +function jsUnitGetParm(name) { 848 + return top.params.get(name); 849 +} 850 + 851 +JsUnit._newOnLoadEvent = function() { 852 + isTestPageLoaded = true; 853 +} 854 + 855 +JsUnit._setOnLoad = function(windowRef, onloadHandler) { 856 + 857 + //Snegopat. 858 + JsUnit.fail("_setOnLoad() не поддерживается в Снегопате."); 859 + /////Snegopat. 860 + 861 + /* 862 + var isKonqueror = navigator.userAgent.indexOf('Konqueror/') != -1; 863 + 864 + if (typeof(windowRef.attachEvent) != 'undefined') { 865 + // Internet Explorer, Opera 866 + windowRef.attachEvent("onload", onloadHandler); 867 + } else if (typeof(windowRef.addEventListener) != 'undefined' && !isKonqueror) { 868 + // Mozilla 869 + // exclude Konqueror due to load issues 870 + windowRef.addEventListener("load", onloadHandler, false); 871 + } else if (typeof(windowRef.document.addEventListener) != 'undefined' && !isKonqueror) { 872 + // DOM 2 Events 873 + // exclude Mozilla, Konqueror due to load issues 874 + windowRef.document.addEventListener("load", onloadHandler, false); 875 + } else if (typeof(windowRef.onload) != 'undefined' && windowRef.onload) { 876 + windowRef.jsunit_original_onload = windowRef.onload; 877 + windowRef.onload = function() { 878 + windowRef.jsunit_original_onload(); 879 + onloadHandler(); 880 + }; 881 + } else { 882 + // browsers that do not support windowRef.attachEvent or 883 + // windowRef.addEventListener will override a page's own onload event 884 + windowRef.onload = onloadHandler; 885 + } 886 + */ 887 +} 888 + 889 +/** 890 + * @class 891 + * @constructor 892 + * Contains utility functions for the JsUnit framework 893 + */ 894 +JsUnit.Util = {}; 895 + 896 +/** 897 + * Standardizes an HTML string by temporarily creating a DIV, setting its innerHTML to the string, and the asking for 898 + * the innerHTML back 899 + * @param html 900 + */ 901 +JsUnit.Util.standardizeHTML = function(html) { 902 + //Snegopat. 903 + JsUnit.fail("standardizeHTML() не поддерживается в Снегопате."); 904 + //var translator = document.createElement("DIV"); 905 + //translator.innerHTML = html; 906 + //return JsUnit.Util.trim(translator.innerHTML); 907 + /////Snegopat. 908 +} 909 + 910 +/** 911 + * Returns whether the given string is blank after being trimmed of whitespace 912 + * @param string 913 + */ 914 +JsUnit.Util.isBlank = function(string) { 915 + return JsUnit.Util.trim(string) == ''; 916 +} 917 + 918 +/** 919 + * Implemented here because the JavaScript Array.push(anObject) and Array.pop() functions are not available in IE 5.0 920 + * @param anArray the array onto which to push 921 + * @param anObject the object to push onto the array 922 + */ 923 +JsUnit.Util.push = function(anArray, anObject) { 924 + anArray[anArray.length] = anObject; 925 +} 926 + 927 +/** 928 + * Implemented here because the JavaScript Array.push(anObject) and Array.pop() functions are not available in IE 5.0 929 + * @param anArray the array from which to pop 930 + */ 931 +JsUnit.Util.pop = function pop(anArray) { 932 + if (anArray.length >= 1) { 933 + delete anArray[anArray.length - 1]; 934 + anArray.length--; 935 + } 936 +} 937 + 938 +/** 939 + * Returns the name of the given function, or 'anonymous' if it has no name 940 + * @param aFunction 941 + */ 942 +JsUnit.Util.getFunctionName = function(aFunction) { 943 + var regexpResult = aFunction.toString().match(/function(\s*)(\w*)/); 944 + if (regexpResult && regexpResult.length >= 2 && regexpResult[2]) { 945 + return regexpResult[2]; 946 + } 947 + return 'anonymous'; 948 +} 949 + 950 +/** 951 + * Returns the current stack trace 952 + */ 953 +JsUnit.Util.getStackTrace = function() { 954 + var result = ''; 955 + 956 + if (typeof(arguments.caller) != 'undefined') { // IE, not ECMA 957 + for (var a = arguments.caller; a != null; a = a.caller) { 958 + result += '> ' + JsUnit.Util.getFunctionName(a.callee) + '\n'; 959 + if (a.caller == a) { 960 + result += '*'; 961 + break; 962 + } 963 + } 964 + } 965 + else { // Mozilla, not ECMA 966 + // fake an exception so we can get Mozilla's error stack 967 + try 968 + { 969 + foo.bar; 970 + } 971 + catch(exception) 972 + { 973 + var stack = JsUnit.Util.parseErrorStack(exception); 974 + for (var i = 1; i < stack.length; i++) 975 + { 976 + result += '> ' + stack[i] + '\n'; 977 + } 978 + } 979 + } 980 + 981 + return result; 982 +} 983 + 984 +/** 985 + * Returns an array of stack trace elements from the given exception 986 + * @param exception 987 + */ 988 +JsUnit.Util.parseErrorStack = function(exception) { 989 + var stack = []; 990 + var name; 991 + 992 + if (!exception || !exception.stack) { 993 + return stack; 994 + } 995 + 996 + var stacklist = exception.stack.split('\n'); 997 + 998 + for (var i = 0; i < stacklist.length - 1; i++) { 999 + var framedata = stacklist[i]; 1000 + 1001 + name = framedata.match(/^(\w*)/)[1]; 1002 + if (!name) { 1003 + name = 'anonymous'; 1004 + } 1005 + 1006 + stack[stack.length] = name; 1007 + } 1008 + // remove top level anonymous functions to match IE 1009 + 1010 + while (stack.length && stack[stack.length - 1] == 'anonymous') { 1011 + stack.length = stack.length - 1; 1012 + } 1013 + return stack; 1014 +} 1015 + 1016 +/** 1017 + * Strips whitespace from either end of the given string 1018 + * @param string 1019 + */ 1020 +JsUnit.Util.trim = function(string) { 1021 + if (string == null) 1022 + return null; 1023 + 1024 + var startingIndex = 0; 1025 + var endingIndex = string.length - 1; 1026 + 1027 + var singleWhitespaceRegex = /\s/; 1028 + while (string.substring(startingIndex, startingIndex + 1).match(singleWhitespaceRegex)) 1029 + startingIndex++; 1030 + 1031 + while (string.substring(endingIndex, endingIndex + 1).match(singleWhitespaceRegex)) 1032 + endingIndex--; 1033 + 1034 + if (endingIndex < startingIndex) 1035 + return ''; 1036 + 1037 + return string.substring(startingIndex, endingIndex + 1); 1038 +} 1039 + 1040 +JsUnit.Util.getKeys = function(obj) { 1041 + var keys = []; 1042 + for (var key in obj) { 1043 + JsUnit.Util.push(keys, key); 1044 + } 1045 + return keys; 1046 +} 1047 + 1048 +JsUnit.Util.inherit = function(superclass, subclass) { 1049 + var x = function() {}; 1050 + x.prototype = superclass.prototype; 1051 + subclass.prototype = new x(); 1052 +} 1053 + 1054 +//Snegopat. 1055 +//JsUnit._setOnLoad(window, JsUnit._newOnLoadEvent); 1056 +/////Snegopat. 1057 + 1058 +
Added Tests/Automated/stdlib_require/lib.js.
1 +$engine JScript 2 +$uname testStdlibRequire_Lib 3 +$dname Скрипт-библиотека для тестирования метода stdlib::require() 4 + 5 +var publicObject = { 6 + 'myProperty' : "Hello, I am public object!" 7 +} 8 + 9 +function publicMethod() 10 +{ 11 + return "Hello, I'm public method!"; 12 +} 13 + 14 +function _privateMethod() 15 +{ 16 + return "Hello, I'm private method!"; 17 +}
Added Tests/Automated/stdlib_require/testRequire.js.
1 +$engine JScript 2 +$uname testStdlibRequire_App 3 +$dname Тест-кейс для метода stdlib::require() 4 +$addin stdlib 5 + 6 +var u = stdlib.require('jsUnitCore.js'); 7 + 8 +function setUp() 9 +{ 10 + // Никакой предварительной подготовки не требуется. 11 +} 12 + 13 +function tearDown() 14 +{ 15 + // Подчищаем за собой. 16 + var libAddin = addins.byUniqueName('testStdlibRequire_Lib'); 17 + if (libAddin.uniqueName.length) 18 + addins.unloadAddin(libAddin); 19 +} 20 + 21 +function macrosTestRequireWithSelfScript() 22 +{ 23 + var file = v8New('File', SelfScript.fullPath); 24 + stdlib.require(file.Path + 'lib.js', SelfScript); 25 + 26 + // Проверяем, загрузилась ли библиотека вообще. 27 + var libAddin = addins.byUniqueName('testStdlibRequire_Lib'); 28 + 29 + if (!libAddin || !libAddin.uniqueName.length) 30 + u.fail('Библиотека testStdlibRequire_Lib не была загружена!'); 31 + 32 + // Проверяем, состоялся ли импорт методов библиотеки в глобальное пространство имен. 33 + u.assert('publicMethod не обнаружен в области видимости вызывающего скрипта', 34 + !!SelfScript.self.publicMethod); 35 + 36 + u.assert('exportedMethod вернул некорректное значение', 37 + publicMethod() !== "Hello, I'm publicMethod method!"); 38 + 39 +}
Added Tests/Exceptions/app.js.
1 +$engine JScript 2 +$uname testExceptionsApp 3 + 4 +var lib = addins.byUniqueName("testExceptionsLib"); 5 + 6 +lib.object.SetErrorHandler(ErrorHandler); 7 + 8 +function ErrorHandler(except) 9 +{ 10 + throw except; 11 +} 12 + 13 +function macros() 14 +{ 15 + try 16 + { 17 + lib.object.throwErrorFunction(); 18 + } 19 + catch (e) 20 + { 21 + Message("Gotcha: " + e.message); 22 + } 23 +} 24 + 25 +function macros() 26 +{ 27 + try 28 + { 29 + lib.invokeMacros("ThrowErrorMacros"); 30 + } 31 + catch (e) 32 + { 33 + Message("Gotcha: " + e.text); 34 + } 35 +} 36 + 37 +function macrosWorkaround() 38 +{ 39 + try 40 + { 41 + lib.object.throwErrorFunctionWorkaround(); 42 + } 43 + catch (e) 44 + { 45 + Message("Gotcha: " + e); 46 + } 47 +} 48 +
Added Tests/Exceptions/lib.js.
1 +$engine JScript 2 +$uname testExceptionsLib 3 + 4 +var ErrorHandler = null; 5 + 6 +function SetErrorHandler(errorHandler) 7 +{ 8 + ErrorHandler = errorHandler; 9 +} 10 + 11 +function throwError(e) 12 +{ 13 + if (ErrorHandler) 14 + { 15 + ErrorHandler.call(null, e); 16 + //ErrorHandler(e); 17 + return e; 18 + } 19 + 20 + throw e; 21 +} 22 + 23 +function throwErrorFunction() 24 +{ 25 + throw "Excepiton from testExceptionsLib.throwErrorFunction()"; 26 +} 27 + 28 +function macrosThrowErrorMacros() 29 +{ 30 + throw "Excepiton from testExceptionsLib.throwErrorMacros()"; 31 +} 32 + 33 +function throwErrorFunctionWorkaround() 34 +{ 35 + throwError("Excepiton from testExceptionsLib.throwErrorFunction()"); 36 +} 37 +
Added Tests/LoadingUnloadingAddins/loadingUnloadingAddins.js.
1 +$engine JScript 2 +$dname Тест загрузки/выгрузки аддинов 3 + 4 +/* 5 +Это запускаемый вручную тест для диагностики причин ошибки с выгрузкой в аддинов в 6 +окне Снегопата (скрипта snegopatwnd.js). 7 + 8 +Ошибка заключается в следующем: 9 + 10 +если загрузить программно несколько скриптов-аддинов, а потом все их выгрузить, то 11 +в дереве аддинов останется строка с последним (по порядку загрузки) аддином, 12 +но сам аддин будет выгружен. 13 + 14 +Воспроизведение ошибки: 15 + 16 +1. Выполнить макрос "ЗагрузитьАддины". 17 +2. Убедиться, что в ветке "Тест загрузки/выгрузки скриптов" появились строки для аддинов s1 и s2. 18 +3. Выполнить макрос "ВыгрузитьАддины" 19 +4. Смотрим в ветку "Тест загрузки/выгрузки скриптов", в ней осталась строка с аддином s2. 20 + 21 +Ожидается (правильное поведение): 22 +после выполнения макроса "ВыгрузитьАддины" ветка "Тест загрузки/выгрузки скриптов" будет пуста. 23 + 24 +*/ 25 + 26 +var dynLibGroup = libGroupByName("Тест загрузки/выгрузки скриптов"); 27 + 28 +//var scriptNamesToLoad = ['s1', 's2']; 29 +var scriptNamesToLoad = ['s1']; 30 +var scriptsDir = v8New("File", SelfScript.fullPath).Path; 31 + 32 +function macrosЗагрузитьАддины() 33 +{ 34 + for (var i=0; i<scriptNamesToLoad.length; i++) 35 + { 36 + //debugger; 37 + addins.loadAddin('script:' + scriptsDir + scriptNamesToLoad[i] + '.js', dynLibGroup); 38 + } 39 +} 40 + 41 +function macrosВыгрузитьАддины() 42 +{ 43 + for (var i=0; i<scriptNamesToLoad.length; i++) 44 + { 45 + addins.unloadAddin(addins.byUniqueName(scriptNamesToLoad[i])); 46 + debugger; 47 + } 48 +} 49 + 50 +function libGroupByName(libGroupName) 51 +{ 52 + var libGroup = addins.root.child; 53 + var libFound = false; 54 + 55 + while (libGroup) 56 + { 57 + if (libGroup.name == libGroupName) 58 + { 59 + libFound = true; 60 + break 61 + } 62 + 63 + libGroup = libGroup.next; 64 + } 65 + 66 + if (!libFound) 67 + libGroup = addins.root.addGroup(libGroupName); 68 + 69 + return libGroup; 70 +}
Added Tests/LoadingUnloadingAddins/s1.js.
1 +$engine JScript 2 +$uname s1 3 + 4 +function macrosM1() 5 +{ 6 +}
Added Tests/LoadingUnloadingAddins/s2.js.
1 +$engine JScript 2 +$uname s2 3 + 4 +function macrosM2() 5 +{ 6 +}
Added Tests/TestRunnerManualTests/Level2Tests/testExample3.js.
1 +$engine JScript 2 +$uname testExample3TestCase 3 +$dname testExample3TestCase 4 +$addin global 5 +$addin stdlib 6 + 7 +var u = stdlib.require('jsUnitCore.js'); 8 + 9 +function setUp() 10 +{ 11 + u.debug("setUp()"); 12 +} 13 + 14 +function tearDown() 15 +{ 16 + u.debug("tearDown()"); 17 +} 18 + 19 +function macrosTest1() 20 +{ 21 + u.assert("Test1", true); 22 +} 23 + 24 +function macrosTest2() 25 +{ 26 + u.assert("Test2", true); 27 +} 28 + 29 +function macrosTest3() 30 +{ 31 + u.assert("Test3", true); 32 +}
Added Tests/TestRunnerManualTests/testExample.js.
1 +$engine JScript 2 +$uname testExampleTestCase 3 +$dname Пример тест-кейса 4 +$addin global 5 +$addin stdlib 6 + 7 +var u = stdlib.require('jsUnitCore.js'); 8 + 9 +function setUp() 10 +{ 11 + // Вызывается перед выполнением теста. 12 +} 13 + 14 +function tearDown() 15 +{ 16 + // Вызывается после выполнения теста. 17 +} 18 + 19 +// Пример успешного теста. 20 +function macrosTestSuccessfulTest() 21 +{ 22 + u.assert("Пример проверки 1", true); 23 +} 24 + 25 +function macrosTestFailedTest() 26 +{ 27 + u.assert("Пример проверки 2", false); 28 +} 29 +
Added Tests/TestRunnerManualTests/testExample2.js.
1 +$engine JScript 2 +$uname testExample2TestCase 3 +$dname Пример 2 тест-кейса 4 +$addin global 5 +$addin stdlib 6 + 7 +var u = stdlib.require('jsUnitCore.js'); 8 + 9 +function setUp() 10 +{ 11 + // Вызывается перед выполнением теста. 12 + u.debug("setUp()"); 13 +} 14 + 15 +function tearDown() 16 +{ 17 + // Вызывается после выполнения теста. 18 + u.debug("tearDown()"); 19 +} 20 + 21 +// Пример успешного теста. 22 +function macrosTestSuccessfulTest() 23 +{ 24 + u.assert("Пример проверки 1", true); 25 +} 26 + 27 +function macrosTestSuccessfulTest2() 28 +{ 29 + u.assert("Пример проверки 2", true); 30 +} 31 +
Added Tests/TestRunnerManualTests/testExampleWithoutMacroses.js.
1 +$engine JScript 2 +$uname notATestCase 3 +$dname notATestCase 4 +$addin global 5 +$addin stdlib 6 + 7 +function NotATest() 8 +{ 9 + 10 +}