Вход Регистрация
Файл: module-assets/admin/pagedown-bootstrap/demo/browser/bootstrap/js/tests/vendor/qunit.js
Строк: 1775
<?php
/**
 * QUnit - A JavaScript Unit Testing Framework
 *
 * http://docs.jquery.com/QUnit
 *
 * Copyright (c) 2012 John Resig, Jörn Zaefferer
 * Dual licensed under the MIT (MIT-LICENSE.txt)
 * or GPL (GPL-LICENSE.txt) licenses.
 */

(function(window) {

var 
defined = {
    
setTimeouttypeof window.setTimeout !== "undefined",
    
sessionStorage: (function() {
        try {
            return !!
sessionStorage.getItem;
        } catch(
e) {
            return 
false;
        }
    })()
};

var 
testId 0;

var 
Test = function(nametestNameexpectedtestEnvironmentArgasynccallback) {
    
this.name name;
    
this.testName testName;
    
this.expected expected;
    
this.testEnvironmentArg testEnvironmentArg;
    
this.async async;
    
this.callback callback;
    
this.assertions = [];
};
Test.prototype = {
    
init: function() {
        var 
tests id("qunit-tests");
        if (
tests) {
            var 
document.createElement("strong");
                
b.innerHTML "Running " this.name;
            var 
li document.createElement("li");
                
li.appendChild);
                
li.className "running";
                
li.id this.id "test-output" testId++;
            
tests.appendChildli );
        }
    },
    
setup: function() {
        if (
this.module != config.previousModule) {
            if ( 
config.previousModule ) {
                
QUnit.moduleDone( {
                    
nameconfig.previousModule,
                    
failedconfig.moduleStats.bad,
                    
passedconfig.moduleStats.all config.moduleStats.bad,
                    
totalconfig.moduleStats.all
                
} );
            }
            
config.previousModule this.module;
            
config.moduleStats = { all0bad};
            
QUnit.moduleStart( {
                
namethis.module
            
} );
        }

        
config.current this;
        
this.testEnvironment extend({
            
setup: function() {},
            
teardown: function() {}
        }, 
this.moduleTestEnvironment);
        if (
this.testEnvironmentArg) {
            
extend(this.testEnvironmentthis.testEnvironmentArg);
        }

        
QUnit.testStart( {
            
namethis.testName
        
} );

        
// allow utility functions to access the current test environment
        // TODO why??
        
QUnit.current_testEnvironment this.testEnvironment;

        try {
            if ( !
config.pollution ) {
                
saveGlobal();
            }

            
this.testEnvironment.setup.call(this.testEnvironment);
        } catch(
e) {
            
QUnit.okfalse"Setup failed on " this.testName ": " e.message );
        }
    },
    
run: function() {
        if ( 
this.async ) {
            
QUnit.stop();
        }

        if ( 
config.notrycatch ) {
            
this.callback.call(this.testEnvironment);
            return;
        }
        try {
            
this.callback.call(this.testEnvironment);
        } catch(
e) {
            
fail("Test " this.testName " died, exception and test follows"ethis.callback);
            
QUnit.okfalse"Died on test #" + (this.assertions.length 1) + ": " e.message " - " QUnit.jsDump.parse(e) );
            
// else next test will carry the responsibility
            
saveGlobal();

            
// Restart the tests if they're blocking
            
if ( config.blocking ) {
                
start();
            }
        }
    },
    
teardown: function() {
        try {
            
this.testEnvironment.teardown.call(this.testEnvironment);
            
checkPollution();
        } catch(
e) {
            
QUnit.okfalse"Teardown failed on " this.testName ": " e.message );
        }
    },
    
finish: function() {
        if ( 
this.expected && this.expected != this.assertions.length ) {
            
QUnit.okfalse"Expected " this.expected " assertions, but " this.assertions.length " were run" );
        }

        var 
good 0bad 0,
            
tests id("qunit-tests");

        
config.stats.all += this.assertions.length;
        
config.moduleStats.all += this.assertions.length;

        if ( 
tests ) {
            var 
ol document.createElement("ol");

            for ( var 
0this.assertions.lengthi++ ) {
                var 
assertion this.assertions[i];

                var 
li document.createElement("li");
                
li.className assertion.result "pass" "fail";
                
li.innerHTML assertion.message || (assertion.result "okay" "failed");
                
ol.appendChildli );

                if ( 
assertion.result ) {
                    
good++;
                } else {
                    
bad++;
                    
config.stats.bad++;
                    
config.moduleStats.bad++;
                }
            }

            
// store result when possible
            
if ( QUnit.config.reorder && defined.sessionStorage ) {
                if (
bad) {
                    
sessionStorage.setItem("qunit-" this.module "-" this.testNamebad);
                } else {
                    
sessionStorage.removeItem("qunit-" this.module "-" this.testName);
                }
            }

            if (
bad == 0) {
                
ol.style.display "none";
            }

            var 
document.createElement("strong");
            
b.innerHTML this.name " <b class='counts'>(<b class='failed'>" bad "</b>, <b class='passed'>" good "</b>, " this.assertions.length ")</b>";

            var 
document.createElement("a");
            
a.innerHTML "Rerun";
            
a.href QUnit.url({ filtergetText([b]).replace(/([^)]+)$/, "").replace(/(^s*|s*$)/g"") });

            
addEvent(b"click", function() {
                var 
next b.nextSibling.nextSibling,
                    
display next.style.display;
                
next.style.display display === "none" "block" "none";
            });

            
addEvent(b"dblclick", function(e) {
                var 
target && e.target e.target window.event.srcElement;
                if ( 
target.nodeName.toLowerCase() == "span" || target.nodeName.toLowerCase() == "b" ) {
                    
target target.parentNode;
                }
                if ( 
window.location && target.nodeName.toLowerCase() === "strong" ) {
                    
window.location QUnit.url({ filtergetText([target]).replace(/([^)]+)$/, "").replace(/(^s*|s*$)/g"") });
                }
            });

            var 
li id(this.id);
            
li.className bad "fail" "pass";
            
li.removeChildli.firstChild );
            
li.appendChild);
            
li.appendChild);
            
li.appendChildol );

        } else {
            for ( var 
0this.assertions.lengthi++ ) {
                if ( !
this.assertions[i].result ) {
                    
bad++;
                    
config.stats.bad++;
                    
config.moduleStats.bad++;
                }
            }
        }

        try {
            
QUnit.reset();
        } catch(
e) {
            
fail("reset() failed, following Test " this.testName ", exception and reset fn follows"eQUnit.reset);
        }

        
QUnit.testDone( {
            
namethis.testName,
            
failedbad,
            
passedthis.assertions.length bad,
            
totalthis.assertions.length
        
} );
    },

    
queue: function() {
        var 
test this;
        
synchronize(function() {
            
test.init();
        });
        function 
run() {
            
// each of these can by async
            
synchronize(function() {
                
test.setup();
            });
            
synchronize(function() {
                
test.run();
            });
            
synchronize(function() {
                
test.teardown();
            });
            
synchronize(function() {
                
test.finish();
            });
        }
        
// defer when previous test run passed, if storage is available
        
var bad QUnit.config.reorder && defined.sessionStorage && +sessionStorage.getItem("qunit-" this.module "-" this.testName);
        if (
bad) {
            
run();
        } else {
            
synchronize(run);
        };
    }

};

var 
QUnit = {

    
// call on start of module test to prepend name to all tests
    
module: function(nametestEnvironment) {
        
config.currentModule name;
        
config.currentModuleTestEnviroment testEnvironment;
    },

    
asyncTest: function(testNameexpectedcallback) {
        if ( 
arguments.length === ) {
            
callback expected;
            
expected 0;
        }

        
QUnit.test(testNameexpectedcallbacktrue);
    },

    
test: function(testNameexpectedcallbackasync) {
        var 
name '<span class="test-name">' testName '</span>'testEnvironmentArg;

        if ( 
arguments.length === ) {
            
callback expected;
            
expected null;
        }
        
// is 2nd argument a testEnvironment?
        
if ( expected && typeof expected === 'object') {
            
testEnvironmentArg expected;
            
expected null;
        }

        if ( 
config.currentModule ) {
            
name '<span class="module-name">' config.currentModule "</span>: " name;
        }

        if ( !
validTest(config.currentModule ": " testName) ) {
            return;
        }

        var 
test = new Test(nametestNameexpectedtestEnvironmentArgasynccallback);
        
test.module config.currentModule;
        
test.moduleTestEnvironment config.currentModuleTestEnviroment;
        
test.queue();
    },

    
/**
     * Specify the number of expected assertions to gurantee that failed test (no assertions are run at all) don't slip through.
     */
    
expect: function(asserts) {
        
config.current.expected asserts;
    },

    
/**
     * Asserts true.
     * @example ok( "asdfasdf".length > 5, "There must be at least 5 chars" );
     */
    
ok: function(amsg) {
        
= !!a;
        var 
details = {
            
resulta,
            
messagemsg
        
};
        
msg escapeHtml(msg);
        
QUnit.log(details);
        
config.current.assertions.push({
            
resulta,
            
messagemsg
        
});
    },

    
/**
     * Checks that the first two arguments are equal, with an optional message.
     * Prints out both actual and expected values.
     *
     * Prefered to ok( actual == expected, message )
     *
     * @example equal( format("Received {0} bytes.", 2), "Received 2 bytes." );
     *
     * @param Object actual
     * @param Object expected
     * @param String message (optional)
     */
    
equal: function(actualexpectedmessage) {
        
QUnit.push(expected == actualactualexpectedmessage);
    },

    
notEqual: function(actualexpectedmessage) {
        
QUnit.push(expected != actualactualexpectedmessage);
    },

    
deepEqual: function(actualexpectedmessage) {
        
QUnit.push(QUnit.equiv(actualexpected), actualexpectedmessage);
    },

    
notDeepEqual: function(actualexpectedmessage) {
        
QUnit.push(!QUnit.equiv(actualexpected), actualexpectedmessage);
    },

    
strictEqual: function(actualexpectedmessage) {
        
QUnit.push(expected === actualactualexpectedmessage);
    },

    
notStrictEqual: function(actualexpectedmessage) {
        
QUnit.push(expected !== actualactualexpectedmessage);
    },

    
raises: function(blockexpectedmessage) {
        var 
actualok false;

        if (
typeof expected === 'string') {
            
message expected;
            
expected null;
        }

        try {
            
block();
        } catch (
e) {
            
actual e;
        }

        if (
actual) {
            
// we don't want to validate thrown error
            
if (!expected) {
                
ok true;
            
// expected is a regexp
            
} else if (QUnit.objectType(expected) === "regexp") {
                
ok expected.test(actual);
            
// expected is a constructor
            
} else if (actual instanceof expected) {
                
ok true;
            
// expected is a validation function which returns true is validation passed
            
} else if (expected.call({}, actual) === true) {
                
ok true;
            }
        }

        
QUnit.ok(okmessage);
    },

    
start: function() {
        
config.semaphore--;
        if (
config.semaphore 0) {
            
// don't start until equal number of stop-calls
            
return;
        }
        if (
config.semaphore 0) {
            
// ignore if start is called more often then stop
            
config.semaphore 0;
        }
        
// A slight delay, to avoid any current callbacks
        
if ( defined.setTimeout ) {
            
window.setTimeout(function() {
                if (
config.semaphore 0) {
                    return;
                }
                if ( 
config.timeout ) {
                    
clearTimeout(config.timeout);
                }

                
config.blocking false;
                
process();
            }, 
13);
        } else {
            
config.blocking false;
            
process();
        }
    },

    
stop: function(timeout) {
        
config.semaphore++;
        
config.blocking true;

        if ( 
timeout && defined.setTimeout ) {
            
clearTimeout(config.timeout);
            
config.timeout window.setTimeout(function() {
                
QUnit.okfalse"Test timed out" );
                
QUnit.start();
            }, 
timeout);
        }
    }
};

// Backwards compatibility, deprecated
QUnit.equals QUnit.equal;
QUnit.same QUnit.deepEqual;

// Maintain internal state
var config = {
    
// The queue of tests to run
    
queue: [],

    
// block until document ready
    
blockingtrue,

    
// when enabled, show only failing tests
    // gets persisted through sessionStorage and can be changed in UI via checkbox
    
hidepassedfalse,

    
// by default, run previously failed tests first
    // very useful in combination with "Hide passed tests" checked
    
reordertrue,

    
// by default, modify document.title when suite is done
    
altertitletrue,

    
urlConfig: ['noglobals''notrycatch']
};

// Load paramaters
(function() {
    var 
location window.location || { search""protocol"file:" },
        
params location.search.slice).split"&" ),
        
length params.length,
        
urlParams = {},
        
current;

    if ( 
params] ) {
        for ( var 
0lengthi++ ) {
            
current params].split"=" );
            
current] = decodeURIComponentcurrent] );
            
// allow just a key to turn on a flag, e.g., test.html?noglobals
            
current] = current] ? decodeURIComponentcurrent] ) : true;
            
urlParamscurrent] ] = current];
        }
    }

    
QUnit.urlParams urlParams;
    
config.filter urlParams.filter;

    
// Figure out if we're running the tests from a server or not
    
QUnit.isLocal = !!(location.protocol === 'file:');
})();

// Expose the API as global variables, unless an 'exports'
// object exists, in that case we assume we're in CommonJS
if ( typeof exports === "undefined" || typeof require === "undefined" ) {
    
extend(windowQUnit);
    
window.QUnit QUnit;
} else {
    
extend(exportsQUnit);
    
exports.QUnit QUnit;
}

// define these after exposing globals to keep them in these QUnit namespace only
extend(QUnit, {
    
configconfig,

    
// Initialize the configuration options
    
init: function() {
        
extend(config, {
            
stats: { all0bad},
            
moduleStats: { all0bad},
            
started: +new Date,
            
updateRate1000,
            
blockingfalse,
            
autostarttrue,
            
autorunfalse,
            
filter"",
            
queue: [],
            
semaphore0
        
});

        var 
tests id"qunit-tests" ),
            
banner id"qunit-banner" ),
            
result id"qunit-testresult" );

        if ( 
tests ) {
            
tests.innerHTML "";
        }

        if ( 
banner ) {
            
banner.className "";
        }

        if ( 
result ) {
            
result.parentNode.removeChildresult );
        }

        if ( 
tests ) {
            
result document.createElement"p" );
            
result.id "qunit-testresult";
            
result.className "result";
            
tests.parentNode.insertBeforeresulttests );
            
result.innerHTML 'Running...<br/>&nbsp;';
        }
    },

    
/**
     * Resets the test setup. Useful for tests that modify the DOM.
     *
     * If jQuery is available, uses jQuery's html(), otherwise just innerHTML.
     */
    
reset: function() {
        if ( 
window.jQuery ) {
            
jQuery"#qunit-fixture" ).htmlconfig.fixture );
        } else {
            var 
main id'qunit-fixture' );
            if ( 
main ) {
                
main.innerHTML config.fixture;
            }
        }
    },

    
/**
     * Trigger an event on an element.
     *
     * @example triggerEvent( document.body, "click" );
     *
     * @param DOMElement elem
     * @param String type
     */
    
triggerEvent: function( elemtypeevent ) {
        if ( 
document.createEvent ) {
            
event document.createEvent("MouseEvents");
            
event.initMouseEvent(typetruetrueelem.ownerDocument.defaultView,
                
00000falsefalsefalsefalse0null);
            
elem.dispatchEventevent );

        } else if ( 
elem.fireEvent ) {
            
elem.fireEvent("on"+type);
        }
    },

    
// Safe object type checking
    
is: function( typeobj ) {
        return 
QUnit.objectTypeobj ) == type;
    },

    
objectType: function( obj ) {
        if (
typeof obj === "undefined") {
                return 
"undefined";

        
// consider: typeof null === object
        
}
        if (
obj === null) {
                return 
"null";
        }

        var 
type Object.prototype.toString.callobj )
            .
match(/^[objects(.*)]$/)[1] || '';

        switch (
type) {
                case 
'Number':
                        if (
isNaN(obj)) {
                                return 
"nan";
                        } else {
                                return 
"number";
                        }
                case 
'String':
                case 
'Boolean':
                case 
'Array':
                case 
'Date':
                case 
'RegExp':
                case 
'Function':
                        return 
type.toLowerCase();
        }
        if (
typeof obj === "object") {
                return 
"object";
        }
        return 
undefined;
    },

    
push: function(resultactualexpectedmessage) {
        var 
details = {
            
resultresult,
            
messagemessage,
            
actualactual,
            
expectedexpected
        
};

        
message escapeHtml(message) || (result "okay" "failed");
        
message '<span class="test-message">' message "</span>";
        
expected escapeHtml(QUnit.jsDump.parse(expected));
        
actual escapeHtml(QUnit.jsDump.parse(actual));
        var 
output message '<table><tr class="test-expected"><th>Expected: </th><td><pre>' expected '</pre></td></tr>';
        if (
actual != expected) {
            
output += '<tr class="test-actual"><th>Result: </th><td><pre>' actual '</pre></td></tr>';
            
output += '<tr class="test-diff"><th>Diff: </th><td><pre>' QUnit.diff(expectedactual) +'</pre></td></tr>';
        }
        if (!
result) {
            var 
source sourceFromStacktrace();
            if (
source) {
                
details.source source;
                
output += '<tr class="test-source"><th>Source: </th><td><pre>' escapeHtml(source) + '</pre></td></tr>';
            }
        }
        
output += "</table>";

        
QUnit.log(details);

        
config.current.assertions.push({
            
result: !!result,
            
messageoutput
        
});
    },

    
url: function( params ) {
        
params extendextend( {}, QUnit.urlParams ), params );
        var 
querystring "?",
            
key;
        for ( 
key in params ) {
            
querystring += encodeURIComponentkey ) + "=" +
                
encodeURIComponentparamskey ] ) + "&";
        }
        return 
window.location.pathname querystring.slice0, -);
    },

    
extendextend,
    
idid,
    
addEventaddEvent,

    
// Logging callbacks; all receive a single argument with the listed properties
    // run test/logs.html for any related changes
    
begin: function() {},
    
// done: { failed, passed, total, runtime }
    
done: function() {},
    
// log: { result, actual, expected, message }
    
log: function() {},
    
// testStart: { name }
    
testStart: function() {},
    
// testDone: { name, failed, passed, total }
    
testDone: function() {},
    
// moduleStart: { name }
    
moduleStart: function() {},
    
// moduleDone: { name, failed, passed, total }
    
moduleDone: function() {}
});

if ( 
typeof document === "undefined" || document.readyState === "complete" ) {
    
config.autorun true;
}

QUnit.load = function() {
    
QUnit.begin({});

    
// Initialize the config, saving the execution queue
    
var oldconfig extend({}, config);
    
QUnit.init();
    
extend(configoldconfig);

    
config.blocking false;

    var 
urlConfigHtml ''len config.urlConfig.length;
    for ( var 
0vallenval config.urlConfig[i]; i++ ) {
        
config[val] = QUnit.urlParams[val];
        
urlConfigHtml += '<label><input name="' val '" type="checkbox"' + ( config[val] ? ' checked="checked"' '' ) + '>' val '</label>';
    }

    var 
userAgent id("qunit-userAgent");
    if ( 
userAgent ) {
        
userAgent.innerHTML navigator.userAgent;
    }
    var 
banner id("qunit-header");
    if ( 
banner ) {
        
banner.innerHTML '<a href="' QUnit.url({ filterundefined }) + '"> ' banner.innerHTML '</a> ' urlConfigHtml;
        
addEventbanner"change", function( event ) {
            var 
params = {};
            
paramsevent.target.name ] = event.target.checked true undefined;
            
window.location QUnit.urlparams );
        });
    }

    var 
toolbar id("qunit-testrunner-toolbar");
    if ( 
toolbar ) {
        var 
filter document.createElement("input");
        
filter.type "checkbox";
        
filter.id "qunit-filter-pass";
        
addEventfilter"click", function() {
            var 
ol document.getElementById("qunit-tests");
            if ( 
filter.checked ) {
                
ol.className ol.className " hidepass";
            } else {
                var 
tmp " " ol.className.replace( /[ntr]/g" " ) + " ";
                
ol.className tmp.replace(/ hidepass /, " ");
            }
            if ( 
defined.sessionStorage ) {
                if (
filter.checked) {
                    
sessionStorage.setItem("qunit-filter-passed-tests""true");
                } else {
                    
sessionStorage.removeItem("qunit-filter-passed-tests");
                }
            }
        });
        if ( 
config.hidepassed || defined.sessionStorage && sessionStorage.getItem("qunit-filter-passed-tests") ) {
            
filter.checked true;
            var 
ol document.getElementById("qunit-tests");
            
ol.className ol.className " hidepass";
        }
        
toolbar.appendChildfilter );

        var 
label document.createElement("label");
        
label.setAttribute("for""qunit-filter-pass");
        
label.innerHTML "Hide passed tests";
        
toolbar.appendChildlabel );
    }

    var 
main id('qunit-fixture');
    if ( 
main ) {
        
config.fixture main.innerHTML;
    }

    if (
config.autostart) {
        
QUnit.start();
    }
};

addEvent(window"load"QUnit.load);

function 
done() {
    
config.autorun true;

    
// Log the last module results
    
if ( config.currentModule ) {
        
QUnit.moduleDone( {
            
nameconfig.currentModule,
            
failedconfig.moduleStats.bad,
            
passedconfig.moduleStats.all config.moduleStats.bad,
            
totalconfig.moduleStats.all
        
} );
    }

    var 
banner id("qunit-banner"),
        
tests id("qunit-tests"),
        
runtime = +new Date config.started,
        
passed config.stats.all config.stats.bad,
        
html = [
            
'Tests completed in ',
            
runtime,
            
' milliseconds.<br/>',
            
'<span class="passed">',
            
passed,
            
'</span> tests of <span class="total">',
            
config.stats.all,
            
'</span> passed, <span class="failed">',
            
config.stats.bad,
            
'</span> failed.'
        
].join('');

    if ( 
banner ) {
        
banner.className = (config.stats.bad "qunit-fail" "qunit-pass");
    }

    if ( 
tests ) {
        
id"qunit-testresult" ).innerHTML html;
    }

    if ( 
config.altertitle && typeof document !== "undefined" && document.title ) {
        
// show ✖ for good, ✔ for bad suite result in title
        // use escape sequences in case file gets loaded with non-utf-8-charset
        
document.title = [
            (
config.stats.bad "u2716" "u2714"),
            
document.title.replace(/^[u2714u2716] /i"")
        ].
join(" ");
    }

    
QUnit.done( {
        
failedconfig.stats.bad,
        
passedpassed,
        
totalconfig.stats.all,
        
runtimeruntime
    
} );
}

function 
validTestname ) {
    var 
filter config.filter,
        
run false;

    if ( !
filter ) {
        return 
true;
    }

    var 
not filter.charAt) === "!";
    if ( 
not ) {
        
filter filter.slice);
    }

    if ( 
name.indexOffilter ) !== -) {
        return !
not;
    }

    if ( 
not ) {
        
run true;
    }

    return 
run;
}

// so far supports only Firefox, Chrome and Opera (buggy)
// could be extended in the future to use something like https://github.com/csnover/TraceKit
function sourceFromStacktrace() {
    try {
        throw new 
Error();
    } catch ( 
) {
        if (
e.stacktrace) {
            
// Opera
            
return e.stacktrace.split("n")[6];
        } else if (
e.stack) {
            
// Firefox, Chrome
            
return e.stack.split("n")[4];
        } else if (
e.sourceURL) {
            
// Safari, PhantomJS
            // TODO sourceURL points at the 'throw new Error' line above, useless
            //return e.sourceURL + ":" + e.line;
        
}
    }
}

function 
escapeHtml(s) {
    if (!
s) {
        return 
"";
    }
    
"";
    return 
s.replace(/[&"<>\]/g, function(s) {
        switch(s) {
            case "
&": return "&amp;";
            case "
\": return "\\";
            case '"': return '"';
            case "
<": return "&lt;";
            case "
>": return "&gt;";
            default: return s;
        }
    });
}

function synchronize( callback ) {
    config.queue.push( callback );

    if ( config.autorun && !config.blocking ) {
        process();
    }
}

function process() {
    var start = (new Date()).getTime();

    while ( config.queue.length && !config.blocking ) {
        if ( config.updateRate <= 0 || (((new Date()).getTime() - start) < config.updateRate) ) {
            config.queue.shift()();
        } else {
            window.setTimeout( process, 13 );
            break;
        }
    }
    if (!config.blocking && !config.queue.length) {
        done();
    }
}

function saveGlobal() {
    config.pollution = [];

    if ( config.noglobals ) {
        for ( var key in window ) {
            config.pollution.push( key );
        }
    }
}

function checkPollution( name ) {
    var old = config.pollution;
    saveGlobal();

    var newGlobals = diff( config.pollution, old );
    if ( newGlobals.length > 0 ) {
        ok( false, "
Introduced global variable(s): " + newGlobals.join("") );
    }

    var deletedGlobals = diff( old, config.pollution );
    if ( deletedGlobals.length > 0 ) {
        ok( false, "
Deleted global variable(s): " + deletedGlobals.join("") );
    }
}

// returns a new Array with the elements that are in a but not in b
function diff( a, b ) {
    var result = a.slice();
    for ( var i = 0; i < result.length; i++ ) {
        for ( var j = 0; j < b.length; j++ ) {
            if ( result[i] === b[j] ) {
                result.splice(i, 1);
                i--;
                break;
            }
        }
    }
    return result;
}

function fail(message, exception, callback) {
    if ( typeof console !== "
undefined" && console.error && console.warn ) {
        console.error(message);
        console.error(exception);
        console.warn(callback.toString());

    } else if ( window.opera && opera.postError ) {
        opera.postError(message, exception, callback.toString);
    }
}

function extend(a, b) {
    for ( var prop in b ) {
        if ( b[prop] === undefined ) {
            delete a[prop];
        } else {
            a[prop] = b[prop];
        }
    }

    return a;
}

function addEvent(elem, type, fn) {
    if ( elem.addEventListener ) {
        elem.addEventListener( type, fn, false );
    } else if ( elem.attachEvent ) {
        elem.attachEvent( "
on" + type, fn );
    } else {
        fn();
    }
}

function id(name) {
    return !!(typeof document !== "
undefined" && document && document.getElementById) &&
        document.getElementById( name );
}

// Test for equality any JavaScript type.
// Discussions and reference: http://philrathe.com/articles/equiv
// Test suites: http://philrathe.com/tests/equiv
// Author: Philippe Rathé <prathe@gmail.com>
QUnit.equiv = function () {

    var innerEquiv; // the real equiv function
    var callers = []; // stack to decide between skip/abort functions
    var parents = []; // stack to avoiding loops from circular referencing

    // Call the o related callback with the given arguments.
    function bindCallbacks(o, callbacks, args) {
        var prop = QUnit.objectType(o);
        if (prop) {
            if (QUnit.objectType(callbacks[prop]) === "
function") {
                return callbacks[prop].apply(callbacks, args);
            } else {
                return callbacks[prop]; // or undefined
            }
        }
    }

    var callbacks = function () {

        // for string, boolean, number and null
        function useStrictEquality(b, a) {
            if (b instanceof a.constructor || a instanceof b.constructor) {
                // to catch short annotaion VS 'new' annotation of a
                // declaration
                // e.g. var i = 1;
                // var j = new Number(1);
                return a == b;
            } else {
                return a === b;
            }
        }

        return {
            "
string" : useStrictEquality,
            "
boolean" : useStrictEquality,
            "
number" : useStrictEquality,
            "
null" : useStrictEquality,
            "
undefined" : useStrictEquality,

            "
nan" : function(b) {
                return isNaN(b);
            },

            "
date" : function(b, a) {
                return QUnit.objectType(b) === "
date"
                        && a.valueOf() === b.valueOf();
            },

            "
regexp" : function(b, a) {
                return QUnit.objectType(b) === "
regexp"
                        && a.source === b.source && // the regex itself
                        a.global === b.global && // and its modifers
                                                    // (gmi) ...
                        a.ignoreCase === b.ignoreCase
                        && a.multiline === b.multiline;
            },

            // - skip when the property is a method of an instance (OOP)
            // - abort otherwise,
            // initial === would have catch identical references anyway
            "
function" : function() {
                var caller = callers[callers.length - 1];
                return caller !== Object && typeof caller !== "
undefined";
            },

            "
array" : function(b, a) {
                var i, j, loop;
                var len;

                // b could be an object literal here
                if (!(QUnit.objectType(b) === "
array")) {
                    return false;
                }

                len = a.length;
                if (len !== b.length) { // safe and faster
                    return false;
                }

                // track reference to avoid circular references
                parents.push(a);
                for (i = 0; i < len; i++) {
                    loop = false;
                    for (j = 0; j < parents.length; j++) {
                        if (parents[j] === a[i]) {
                            loop = true;// dont rewalk array
                        }
                    }
                    if (!loop && !innerEquiv(a[i], b[i])) {
                        parents.pop();
                        return false;
                    }
                }
                parents.pop();
                return true;
            },

            "
object" : function(b, a) {
                var i, j, loop;
                var eq = true; // unless we can proove it
                var aProperties = [], bProperties = []; // collection of
                                                        // strings

                // comparing constructors is more strict than using
                // instanceof
                if (a.constructor !== b.constructor) {
                    return false;
                }

                // stack constructor before traversing properties
                callers.push(a.constructor);
                // track reference to avoid circular references
                parents.push(a);

                for (i in a) { // be strict: don't ensures hasOwnProperty
                                // and go deep
                    loop = false;
                    for (j = 0; j < parents.length; j++) {
                        if (parents[j] === a[i])
                            loop = true; // don't go down the same path
                                            // twice
                    }
                    aProperties.push(i); // collect a's properties

                    if (!loop && !innerEquiv(a[i], b[i])) {
                        eq = false;
                        break;
                    }
                }

                callers.pop(); // unstack, we are done
                parents.pop();

                for (i in b) {
                    bProperties.push(i); // collect b's properties
                }

                // Ensures identical properties name
                return eq
                        && innerEquiv(aProperties.sort(), bProperties
                                .sort());
            }
        };
    }();

    innerEquiv = function() { // can take multiple arguments
        var args = Array.prototype.slice.apply(arguments);
        if (args.length < 2) {
            return true; // end transition
        }

        return (function(a, b) {
            if (a === b) {
                return true; // catch the most you can
            } else if (a === null || b === null || typeof a === "
undefined"
                    || typeof b === "
undefined"
                    || QUnit.objectType(a) !== QUnit.objectType(b)) {
                return false; // don't lose time with error prone cases
            } else {
                return bindCallbacks(a, callbacks, [ b, a ]);
            }

            // apply transition with (1..n) arguments
        })(args[0], args[1])
                && arguments.callee.apply(this, args.splice(1,
                        args.length - 1));
    };

    return innerEquiv;

}();

/**
 * jsDump Copyright (c) 2008 Ariel Flesler - aflesler(at)gmail(dot)com |
 * http://flesler.blogspot.com Licensed under BSD
 * (http://www.opensource.org/licenses/bsd-license.php) Date: 5/15/2008
 *
 * @projectDescription Advanced and extensible data dumping for Javascript.
 * @version 1.0.0
 * @author Ariel Flesler
 * @link {http://flesler.blogspot.com/2008/05/jsdump-pretty-dump-of-any-javascript.html}
 */
QUnit.jsDump = (function() {
    function quote( str ) {
        return '"' + str.toString().replace(/"/g, '
\"') + '"';
    };
    function literal( o ) {
        return o + '';
    };
    function join( pre, arr, post ) {
        var s = jsDump.separator(),
            base = jsDump.indent(),
            inner = jsDump.indent(1);
        if ( arr.join )
            arr = arr.join( '
,' + s + inner );
        if ( !arr )
            return pre + post;
        return [ pre, inner + arr, base + post ].join(s);
    };
    function array( arr, stack ) {
        var i = arr.length, ret = Array(i);
        this.up();
        while ( i-- )
            ret[i] = this.parse( arr[i] , undefined , stack);
        this.down();
        return join( '
[', ret, ']' );
    };

    var reName = /^function (w+)/;

    var jsDump = {
        parse:function( obj, type, stack ) { //type is used mostly internally, you can fix a (custom)type in advance
            stack = stack || [ ];
            var parser = this.parsers[ type || this.typeOf(obj) ];
            type = typeof parser;
            var inStack = inArray(obj, stack);
            if (inStack != -1) {
                return '
recursion('+(inStack - stack.length)+')';
            }
            //else
            if (type == '
function')  {
                    stack.push(obj);
                    var res = parser.call( this, obj, stack );
                    stack.pop();
                    return res;
            }
            // else
            return (type == '
string') ? parser : this.parsers.error;
        },
        typeOf:function( obj ) {
            var type;
            if ( obj === null ) {
                type = "null";
            } else if (typeof obj === "undefined") {
                type = "undefined";
            } else if (QUnit.is("RegExp", obj)) {
                type = "regexp";
            } else if (QUnit.is("Date", obj)) {
                type = "date";
            } else if (QUnit.is("Function", obj)) {
                type = "function";
            } else if (typeof obj.setInterval !== undefined && typeof obj.document !== "undefined" && typeof obj.nodeType === "undefined") {
                type = "window";
            } else if (obj.nodeType === 9) {
                type = "document";
            } else if (obj.nodeType) {
                type = "node";
            } else if (typeof obj === "object" && typeof obj.length === "number" && obj.length >= 0) {
                type = "array";
            } else {
                type = typeof obj;
            }
            return type;
        },
        separator:function() {
            return this.multiline ?    this.HTML ? '
<br />' : 'n' : this.HTML ? '&nbsp;' : ' ';
        },
        indent:function( extra ) {// extra can be a number, shortcut for increasing-calling-decreasing
            if ( !this.multiline )
                return '';
            var chr = this.indentChar;
            if ( this.HTML )
                chr = chr.replace(/t/g,'   ').replace(/ /g,'
&nbsp;');
            return Array( this._depth_ + (extra||0) ).join(chr);
        },
        up:function( a ) {
            this._depth_ += a || 1;
        },
        down:function( a ) {
            this._depth_ -= a || 1;
        },
        setParser:function( name, parser ) {
            this.parsers[name] = parser;
        },
        // The next 3 are exposed so you can use them
        quote:quote,
        literal:literal,
        join:join,
        //
        _depth_: 1,
        // This is the list of parsers, to modify them, use jsDump.setParser
        parsers:{
            window: '
[Window]',
            document: '
[Document]',
            error:'
[ERROR]', //when no parser is found, shouldn't happen
            unknown
'[Unknown]',
            
'null':'null',
            
'undefined':'undefined',
            
'function':function( fn ) {
                var 
ret 'function',
                    
name 'name' in fn fn.name : (reName.exec(fn)||[])[1];//functions never have name in IE
                
if ( name )
                    
ret += ' ' name;
                
ret += '(';

                
ret = [ retQUnit.jsDump.parsefn'functionArgs' ), '){'].join('');
                return 
joinretQUnit.jsDump.parse(fn,'functionCode'), '}' );
            },
            array: array,
            
nodelist: array,
            
arguments: array,
            
object:function( mapstack ) {
                var 
ret = [ ];
                
QUnit.jsDump.up();
                for ( var 
key in map ) {
                    var 
val map[key];
                    
ret.pushQUnit.jsDump.parse(key,'key') + ': ' QUnit.jsDump.parse(valundefinedstack));
                }
                
QUnit.jsDump.down();
                return 
join'{'ret'}' );
            },
            
node:function( node ) {
                var 
open QUnit.jsDump.HTML '&lt;' '<',
                    
close QUnit.jsDump.HTML '&gt;' '>';

                var 
tag node.nodeName.toLowerCase(),
                    
ret open tag;

                for ( var 
a in QUnit.jsDump.DOMAttrs ) {
                    var 
val node[QUnit.jsDump.DOMAttrs[a]];
                    if ( 
val )
                        
ret += ' ' '=' QUnit.jsDump.parseval'attribute' );
                }
                return 
ret close open '/' tag close;
            },
            
functionArgs:function( fn ) {//function calls it internally, it's the arguments part of the function
                
var fn.length;
                if ( !
) return '';

                var 
args = Array(l);
                while ( 
l-- )
                    
args[l] = String.fromCharCode(97+l);//97 is 'a'
                
return ' ' args.join(', ') + ' ';
            },
            
key:quote//object calls it internally, the key part of an item in a map
            
functionCode:'[code]'//function calls it internally, it's the content of the function
            
attribute:quote//node calls it internally, it's an html attribute value
            
string:quote,
            
date:quote,
            
regexp:literal//regex
            
number:literal,
            
'boolean':literal
        
},
        
DOMAttrs:{//attributes to dump from nodes, name=>realName
            
id:'id',
            
name:'name',
            
'class':'className'
        
},
        
HTML:false,//if true, entities are escaped ( <, >, t, space and n )
        
indentChar:'  ',//indentation unit
        
multiline:true //if true, items in a collection, are separated by a n, else just a space.
    
};

    return 
jsDump;
})();

// from Sizzle.js
function getTextelems ) {
    var 
ret ""elem;

    for ( var 
0elems[i]; i++ ) {
        
elem elems[i];

        
// Get the text from text nodes and CDATA nodes
        
if ( elem.nodeType === || elem.nodeType === ) {
            
ret += elem.nodeValue;

        
// Traverse everything else, except comment nodes
        
} else if ( elem.nodeType !== ) {
            
ret += getTextelem.childNodes );
        }
    }

    return 
ret;
};

//from jquery.js
function inArrayelem, array ) {
    if ( array.
indexOf ) {
        return array.
indexOfelem );
    }

    for ( var 
0length = array.lengthlengthi++ ) {
        if ( array[ 
] === elem ) {
            return 
i;
        }
    }

    return -
1;
}

/*
 * Javascript Diff Algorithm
 *  By John Resig (http://ejohn.org/)
 *  Modified by Chu Alan "sprite"
 *
 * Released under the MIT license.
 *
 * More Info:
 *  http://ejohn.org/projects/javascript-diff-algorithm/
 *
 * Usage: QUnit.diff(expected, actual)
 *
 * QUnit.diff("the quick brown fox jumped over", "the quick fox jumps over") == "the  quick <del>brown </del> fox <del>jumped </del><ins>jumps </ins> over"
 */
QUnit.diff = (function() {
    function 
diff(on) {
        var 
ns = {};
        var 
os = {};

        for (var 
0n.lengthi++) {
            if (
ns[n[i]] == null)
                
ns[n[i]] = {
                    
rows: [],
                    
onull
                
};
            
ns[n[i]].rows.push(i);
        }

        for (var 
0o.lengthi++) {
            if (
os[o[i]] == null)
                
os[o[i]] = {
                    
rows: [],
                    
nnull
                
};
            
os[o[i]].rows.push(i);
        }

        for (var 
i in ns) {
            if (
ns[i].rows.length == && typeof(os[i]) != "undefined" && os[i].rows.length == 1) {
                
n[ns[i].rows[0]] = {
                    
textn[ns[i].rows[0]],
                    
rowos[i].rows[0]
                };
                
o[os[i].rows[0]] = {
                    
texto[os[i].rows[0]],
                    
rowns[i].rows[0]
                };
            }
        }

        for (var 
0n.length 1i++) {
            if (
n[i].text != null && n[1].text == null && n[i].row o.length && o[n[i].row 1].text == null &&
            
n[1] == o[n[i].row 1]) {
                
n[1] = {
                    
textn[1],
                    
rown[i].row 1
                
};
                
o[n[i].row 1] = {
                    
texto[n[i].row 1],
                    
row1
                
};
            }
        }

        for (var 
n.length 10i--) {
            if (
n[i].text != null && n[1].text == null && n[i].row && o[n[i].row 1].text == null &&
            
n[1] == o[n[i].row 1]) {
                
n[1] = {
                    
textn[1],
                    
rown[i].row 1
                
};
                
o[n[i].row 1] = {
                    
texto[n[i].row 1],
                    
row1
                
};
            }
        }

        return {
            
oo,
            
nn
        
};
    }

    return function(
on) {
        
o.replace(/s+$/, '');
        
n.replace(/s+$/, '');
        var 
out diff(== "" ? [] : o.split(/s+/), == "" ? [] : n.split(/s+/));

        var 
str "";

        var 
oSpace o.match(/s+/g);
        if (
oSpace == null) {
            
oSpace = [" "];
        }
        else {
            
oSpace.push(" ");
        }
        var 
nSpace n.match(/s+/g);
        if (
nSpace == null) {
            
nSpace = [" "];
        }
        else {
            
nSpace.push(" ");
        }

        if (
out.n.length == 0) {
            for (var 
0out.o.lengthi++) {
                
str += '<del>' out.o[i] + oSpace[i] + "</del>";
            }
        }
        else {
            if (
out.n[0].text == null) {
                for (
0out.o.length && out.o[n].text == nulln++) {
                    
str += '<del>' out.o[n] + oSpace[n] + "</del>";
                }
            }

            for (var 
0out.n.lengthi++) {
                if (
out.n[i].text == null) {
                    
str += '<ins>' out.n[i] + nSpace[i] + "</ins>";
                }
                else {
                    var 
pre "";

                    for (
out.n[i].row 1out.o.length && out.o[n].text == nulln++) {
                        
pre += '<del>' out.o[n] + oSpace[n] + "</del>";
                    }
                    
str += " " out.n[i].text nSpace[i] + pre;
                }
            }
        }

        return 
str;
    };
})();

})(
this);
?>
Онлайн: 1
Реклама