Changes On Branch jsunit-port Вы: nobody
Вход

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  + * &lt;script type="text/javascript" src="/path/to/jsUnitCore.js"&gt;&lt;/script&gt;
           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  +}