UNPKG

vide

Version:

Easy as hell jQuery plugin for video backgrounds.

810 lines (663 loc) 21.6 kB
// Don't load the HTML Reporter on non-browser environments if ( typeof window === "undefined" || !window.document ) { return; } // Deprecated QUnit.init - Ref #530 // Re-initialize the configuration options QUnit.init = function() { var config = QUnit.config; config.stats = { all: 0, bad: 0 }; config.moduleStats = { all: 0, bad: 0 }; config.started = 0; config.updateRate = 1000; config.blocking = false; config.autostart = true; config.autorun = false; config.filter = ""; config.queue = []; appendInterface(); }; var config = QUnit.config, document = window.document, collapseNext = false, hasOwn = Object.prototype.hasOwnProperty, unfilteredUrl = setUrl( { filter: undefined, module: undefined, moduleId: undefined, testId: undefined } ), defined = { sessionStorage: ( function() { var x = "qunit-test-string"; try { sessionStorage.setItem( x, x ); sessionStorage.removeItem( x ); return true; } catch ( e ) { return false; } }() ) }, modulesList = []; /** * Escape text for attribute or text content. */ function escapeText( s ) { if ( !s ) { return ""; } s = s + ""; // Both single quotes and double quotes (for attributes) return s.replace( /['"<>&]/g, function( s ) { switch ( s ) { case "'": return "&#039;"; case "\"": return "&quot;"; case "<": return "&lt;"; case ">": return "&gt;"; case "&": return "&amp;"; } } ); } /** * @param {HTMLElement} elem * @param {string} type * @param {Function} fn */ function addEvent( elem, type, fn ) { if ( elem.addEventListener ) { // Standards-based browsers elem.addEventListener( type, fn, false ); } else if ( elem.attachEvent ) { // Support: IE <9 elem.attachEvent( "on" + type, function() { var event = window.event; if ( !event.target ) { event.target = event.srcElement || document; } fn.call( elem, event ); } ); } } /** * @param {Array|NodeList} elems * @param {string} type * @param {Function} fn */ function addEvents( elems, type, fn ) { var i = elems.length; while ( i-- ) { addEvent( elems[ i ], type, fn ); } } function hasClass( elem, name ) { return ( " " + elem.className + " " ).indexOf( " " + name + " " ) >= 0; } function addClass( elem, name ) { if ( !hasClass( elem, name ) ) { elem.className += ( elem.className ? " " : "" ) + name; } } function toggleClass( elem, name, force ) { if ( force || typeof force === "undefined" && !hasClass( elem, name ) ) { addClass( elem, name ); } else { removeClass( elem, name ); } } function removeClass( elem, name ) { var set = " " + elem.className + " "; // Class name may appear multiple times while ( set.indexOf( " " + name + " " ) >= 0 ) { set = set.replace( " " + name + " ", " " ); } // Trim for prettiness elem.className = typeof set.trim === "function" ? set.trim() : set.replace( /^\s+|\s+$/g, "" ); } function id( name ) { return document.getElementById && document.getElementById( name ); } function getUrlConfigHtml() { var i, j, val, escaped, escapedTooltip, selection = false, urlConfig = config.urlConfig, urlConfigHtml = ""; for ( i = 0; i < urlConfig.length; i++ ) { // Options can be either strings or objects with nonempty "id" properties val = config.urlConfig[ i ]; if ( typeof val === "string" ) { val = { id: val, label: val }; } escaped = escapeText( val.id ); escapedTooltip = escapeText( val.tooltip ); if ( !val.value || typeof val.value === "string" ) { urlConfigHtml += "<input id='qunit-urlconfig-" + escaped + "' name='" + escaped + "' type='checkbox'" + ( val.value ? " value='" + escapeText( val.value ) + "'" : "" ) + ( config[ val.id ] ? " checked='checked'" : "" ) + " title='" + escapedTooltip + "' /><label for='qunit-urlconfig-" + escaped + "' title='" + escapedTooltip + "'>" + val.label + "</label>"; } else { urlConfigHtml += "<label for='qunit-urlconfig-" + escaped + "' title='" + escapedTooltip + "'>" + val.label + ": </label><select id='qunit-urlconfig-" + escaped + "' name='" + escaped + "' title='" + escapedTooltip + "'><option></option>"; if ( QUnit.is( "array", val.value ) ) { for ( j = 0; j < val.value.length; j++ ) { escaped = escapeText( val.value[ j ] ); urlConfigHtml += "<option value='" + escaped + "'" + ( config[ val.id ] === val.value[ j ] ? ( selection = true ) && " selected='selected'" : "" ) + ">" + escaped + "</option>"; } } else { for ( j in val.value ) { if ( hasOwn.call( val.value, j ) ) { urlConfigHtml += "<option value='" + escapeText( j ) + "'" + ( config[ val.id ] === j ? ( selection = true ) && " selected='selected'" : "" ) + ">" + escapeText( val.value[ j ] ) + "</option>"; } } } if ( config[ val.id ] && !selection ) { escaped = escapeText( config[ val.id ] ); urlConfigHtml += "<option value='" + escaped + "' selected='selected' disabled='disabled'>" + escaped + "</option>"; } urlConfigHtml += "</select>"; } } return urlConfigHtml; } // Handle "click" events on toolbar checkboxes and "change" for select menus. // Updates the URL with the new state of `config.urlConfig` values. function toolbarChanged() { var updatedUrl, value, tests, field = this, params = {}; // Detect if field is a select menu or a checkbox if ( "selectedIndex" in field ) { value = field.options[ field.selectedIndex ].value || undefined; } else { value = field.checked ? ( field.defaultValue || true ) : undefined; } params[ field.name ] = value; updatedUrl = setUrl( params ); // Check if we can apply the change without a page refresh if ( "hidepassed" === field.name && "replaceState" in window.history ) { QUnit.urlParams[ field.name ] = value; config[ field.name ] = value || false; tests = id( "qunit-tests" ); if ( tests ) { toggleClass( tests, "hidepass", value || false ); } window.history.replaceState( null, "", updatedUrl ); } else { window.location = updatedUrl; } } function setUrl( params ) { var key, arrValue, i, querystring = "?", location = window.location; params = QUnit.extend( QUnit.extend( {}, QUnit.urlParams ), params ); for ( key in params ) { // Skip inherited or undefined properties if ( hasOwn.call( params, key ) && params[ key ] !== undefined ) { // Output a parameter for each value of this key (but usually just one) arrValue = [].concat( params[ key ] ); for ( i = 0; i < arrValue.length; i++ ) { querystring += encodeURIComponent( key ); if ( arrValue[ i ] !== true ) { querystring += "=" + encodeURIComponent( arrValue[ i ] ); } querystring += "&"; } } } return location.protocol + "//" + location.host + location.pathname + querystring.slice( 0, -1 ); } function applyUrlParams() { var selectedModule, modulesList = id( "qunit-modulefilter" ), filter = id( "qunit-filter-input" ).value; selectedModule = modulesList ? decodeURIComponent( modulesList.options[ modulesList.selectedIndex ].value ) : undefined; window.location = setUrl( { module: ( selectedModule === "" ) ? undefined : selectedModule, filter: ( filter === "" ) ? undefined : filter, // Remove moduleId and testId filters moduleId: undefined, testId: undefined } ); } function toolbarUrlConfigContainer() { var urlConfigContainer = document.createElement( "span" ); urlConfigContainer.innerHTML = getUrlConfigHtml(); addClass( urlConfigContainer, "qunit-url-config" ); // For oldIE support: // * Add handlers to the individual elements instead of the container // * Use "click" instead of "change" for checkboxes addEvents( urlConfigContainer.getElementsByTagName( "input" ), "click", toolbarChanged ); addEvents( urlConfigContainer.getElementsByTagName( "select" ), "change", toolbarChanged ); return urlConfigContainer; } function toolbarLooseFilter() { var filter = document.createElement( "form" ), label = document.createElement( "label" ), input = document.createElement( "input" ), button = document.createElement( "button" ); addClass( filter, "qunit-filter" ); label.innerHTML = "Filter: "; input.type = "text"; input.value = config.filter || ""; input.name = "filter"; input.id = "qunit-filter-input"; button.innerHTML = "Go"; label.appendChild( input ); filter.appendChild( label ); filter.appendChild( button ); addEvent( filter, "submit", function( ev ) { applyUrlParams(); if ( ev && ev.preventDefault ) { ev.preventDefault(); } return false; } ); return filter; } function toolbarModuleFilterHtml() { var i, moduleFilterHtml = ""; if ( !modulesList.length ) { return false; } moduleFilterHtml += "<label for='qunit-modulefilter'>Module: </label>" + "<select id='qunit-modulefilter' name='modulefilter'><option value='' " + ( QUnit.urlParams.module === undefined ? "selected='selected'" : "" ) + ">< All Modules ></option>"; for ( i = 0; i < modulesList.length; i++ ) { moduleFilterHtml += "<option value='" + escapeText( encodeURIComponent( modulesList[ i ] ) ) + "' " + ( QUnit.urlParams.module === modulesList[ i ] ? "selected='selected'" : "" ) + ">" + escapeText( modulesList[ i ] ) + "</option>"; } moduleFilterHtml += "</select>"; return moduleFilterHtml; } function toolbarModuleFilter() { var toolbar = id( "qunit-testrunner-toolbar" ), moduleFilter = document.createElement( "span" ), moduleFilterHtml = toolbarModuleFilterHtml(); if ( !toolbar || !moduleFilterHtml ) { return false; } moduleFilter.setAttribute( "id", "qunit-modulefilter-container" ); moduleFilter.innerHTML = moduleFilterHtml; addEvent( moduleFilter.lastChild, "change", applyUrlParams ); toolbar.appendChild( moduleFilter ); } function appendToolbar() { var toolbar = id( "qunit-testrunner-toolbar" ); if ( toolbar ) { toolbar.appendChild( toolbarUrlConfigContainer() ); toolbar.appendChild( toolbarLooseFilter() ); toolbarModuleFilter(); } } function appendHeader() { var header = id( "qunit-header" ); if ( header ) { header.innerHTML = "<a href='" + escapeText( unfilteredUrl ) + "'>" + header.innerHTML + "</a> "; } } function appendBanner() { var banner = id( "qunit-banner" ); if ( banner ) { banner.className = ""; } } function appendTestResults() { var tests = id( "qunit-tests" ), result = id( "qunit-testresult" ); if ( result ) { result.parentNode.removeChild( result ); } if ( tests ) { tests.innerHTML = ""; result = document.createElement( "p" ); result.id = "qunit-testresult"; result.className = "result"; tests.parentNode.insertBefore( result, tests ); result.innerHTML = "Running...<br />&#160;"; } } function storeFixture() { var fixture = id( "qunit-fixture" ); if ( fixture ) { config.fixture = fixture.innerHTML; } } function appendFilteredTest() { var testId = QUnit.config.testId; if ( !testId || testId.length <= 0 ) { return ""; } return "<div id='qunit-filteredTest'>Rerunning selected tests: " + escapeText( testId.join( ", " ) ) + " <a id='qunit-clearFilter' href='" + escapeText( unfilteredUrl ) + "'>Run all tests</a></div>"; } function appendUserAgent() { var userAgent = id( "qunit-userAgent" ); if ( userAgent ) { userAgent.innerHTML = ""; userAgent.appendChild( document.createTextNode( "QUnit " + QUnit.version + "; " + navigator.userAgent ) ); } } function appendInterface() { var qunit = id( "qunit" ); if ( qunit ) { qunit.innerHTML = "<h1 id='qunit-header'>" + escapeText( document.title ) + "</h1>" + "<h2 id='qunit-banner'></h2>" + "<div id='qunit-testrunner-toolbar'></div>" + appendFilteredTest() + "<h2 id='qunit-userAgent'></h2>" + "<ol id='qunit-tests'></ol>"; } appendHeader(); appendBanner(); appendTestResults(); appendUserAgent(); appendToolbar(); } function appendTestsList( modules ) { var i, l, x, z, test, moduleObj; for ( i = 0, l = modules.length; i < l; i++ ) { moduleObj = modules[ i ]; for ( x = 0, z = moduleObj.tests.length; x < z; x++ ) { test = moduleObj.tests[ x ]; appendTest( test.name, test.testId, moduleObj.name ); } } } function appendTest( name, testId, moduleName ) { var title, rerunTrigger, testBlock, assertList, tests = id( "qunit-tests" ); if ( !tests ) { return; } title = document.createElement( "strong" ); title.innerHTML = getNameHtml( name, moduleName ); rerunTrigger = document.createElement( "a" ); rerunTrigger.innerHTML = "Rerun"; rerunTrigger.href = setUrl( { testId: testId } ); testBlock = document.createElement( "li" ); testBlock.appendChild( title ); testBlock.appendChild( rerunTrigger ); testBlock.id = "qunit-test-output-" + testId; assertList = document.createElement( "ol" ); assertList.className = "qunit-assert-list"; testBlock.appendChild( assertList ); tests.appendChild( testBlock ); } // HTML Reporter initialization and load QUnit.begin( function( details ) { var i, moduleObj, tests; // Sort modules by name for the picker for ( i = 0; i < details.modules.length; i++ ) { moduleObj = details.modules[ i ]; if ( moduleObj.name ) { modulesList.push( moduleObj.name ); } } modulesList.sort( function( a, b ) { return a.localeCompare( b ); } ); // Capture fixture HTML from the page storeFixture(); // Initialize QUnit elements appendInterface(); appendTestsList( details.modules ); tests = id( "qunit-tests" ); if ( tests && config.hidepassed ) { addClass( tests, "hidepass" ); } } ); QUnit.done( function( details ) { var i, key, banner = id( "qunit-banner" ), tests = id( "qunit-tests" ), html = [ "Tests completed in ", details.runtime, " milliseconds.<br />", "<span class='passed'>", details.passed, "</span> assertions of <span class='total'>", details.total, "</span> passed, <span class='failed'>", details.failed, "</span> failed." ].join( "" ); if ( banner ) { banner.className = details.failed ? "qunit-fail" : "qunit-pass"; } if ( tests ) { id( "qunit-testresult" ).innerHTML = html; } if ( config.altertitle && 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 = [ ( details.failed ? "\u2716" : "\u2714" ), document.title.replace( /^[\u2714\u2716] /i, "" ) ].join( " " ); } // Clear own sessionStorage items if all tests passed if ( config.reorder && defined.sessionStorage && details.failed === 0 ) { for ( i = 0; i < sessionStorage.length; i++ ) { key = sessionStorage.key( i++ ); if ( key.indexOf( "qunit-test-" ) === 0 ) { sessionStorage.removeItem( key ); } } } // Scroll back to top to show results if ( config.scrolltop && window.scrollTo ) { window.scrollTo( 0, 0 ); } } ); function getNameHtml( name, module ) { var nameHtml = ""; if ( module ) { nameHtml = "<span class='module-name'>" + escapeText( module ) + "</span>: "; } nameHtml += "<span class='test-name'>" + escapeText( name ) + "</span>"; return nameHtml; } QUnit.testStart( function( details ) { var running, testBlock, bad; testBlock = id( "qunit-test-output-" + details.testId ); if ( testBlock ) { testBlock.className = "running"; } else { // Report later registered tests appendTest( details.name, details.testId, details.module ); } running = id( "qunit-testresult" ); if ( running ) { bad = QUnit.config.reorder && defined.sessionStorage && +sessionStorage.getItem( "qunit-test-" + details.module + "-" + details.name ); running.innerHTML = ( bad ? "Rerunning previously failed test: <br />" : "Running: <br />" ) + getNameHtml( details.name, details.module ); } } ); function stripHtml( string ) { // Strip tags, html entity and whitespaces return string.replace( /<\/?[^>]+(>|$)/g, "" ).replace( /\&quot;/g, "" ).replace( /\s+/g, "" ); } QUnit.log( function( details ) { var assertList, assertLi, message, expected, actual, diff, showDiff = false, testItem = id( "qunit-test-output-" + details.testId ); if ( !testItem ) { return; } message = escapeText( details.message ) || ( details.result ? "okay" : "failed" ); message = "<span class='test-message'>" + message + "</span>"; message += "<span class='runtime'>@ " + details.runtime + " ms</span>"; // The pushFailure doesn't provide details.expected // when it calls, it's implicit to also not show expected and diff stuff // Also, we need to check details.expected existence, as it can exist and be undefined if ( !details.result && hasOwn.call( details, "expected" ) ) { if ( details.negative ) { expected = "NOT " + QUnit.dump.parse( details.expected ); } else { expected = QUnit.dump.parse( details.expected ); } actual = QUnit.dump.parse( details.actual ); message += "<table><tr class='test-expected'><th>Expected: </th><td><pre>" + escapeText( expected ) + "</pre></td></tr>"; if ( actual !== expected ) { message += "<tr class='test-actual'><th>Result: </th><td><pre>" + escapeText( actual ) + "</pre></td></tr>"; // Don't show diff if actual or expected are booleans if ( !( /^(true|false)$/.test( actual ) ) && !( /^(true|false)$/.test( expected ) ) ) { diff = QUnit.diff( expected, actual ); showDiff = stripHtml( diff ).length !== stripHtml( expected ).length + stripHtml( actual ).length; } // Don't show diff if expected and actual are totally different if ( showDiff ) { message += "<tr class='test-diff'><th>Diff: </th><td><pre>" + diff + "</pre></td></tr>"; } } else if ( expected.indexOf( "[object Array]" ) !== -1 || expected.indexOf( "[object Object]" ) !== -1 ) { message += "<tr class='test-message'><th>Message: </th><td>" + "Diff suppressed as the depth of object is more than current max depth (" + QUnit.config.maxDepth + ").<p>Hint: Use <code>QUnit.dump.maxDepth</code> to " + " run with a higher max depth or <a href='" + escapeText( setUrl( { maxDepth: -1 } ) ) + "'>" + "Rerun</a> without max depth.</p></td></tr>"; } else { message += "<tr class='test-message'><th>Message: </th><td>" + "Diff suppressed as the expected and actual results have an equivalent" + " serialization</td></tr>"; } if ( details.source ) { message += "<tr class='test-source'><th>Source: </th><td><pre>" + escapeText( details.source ) + "</pre></td></tr>"; } message += "</table>"; // This occurs when pushFailure is set and we have an extracted stack trace } else if ( !details.result && details.source ) { message += "<table>" + "<tr class='test-source'><th>Source: </th><td><pre>" + escapeText( details.source ) + "</pre></td></tr>" + "</table>"; } assertList = testItem.getElementsByTagName( "ol" )[ 0 ]; assertLi = document.createElement( "li" ); assertLi.className = details.result ? "pass" : "fail"; assertLi.innerHTML = message; assertList.appendChild( assertLi ); } ); QUnit.testDone( function( details ) { var testTitle, time, testItem, assertList, good, bad, testCounts, skipped, sourceName, tests = id( "qunit-tests" ); if ( !tests ) { return; } testItem = id( "qunit-test-output-" + details.testId ); assertList = testItem.getElementsByTagName( "ol" )[ 0 ]; good = details.passed; bad = details.failed; // Store result when possible if ( config.reorder && defined.sessionStorage ) { if ( bad ) { sessionStorage.setItem( "qunit-test-" + details.module + "-" + details.name, bad ); } else { sessionStorage.removeItem( "qunit-test-" + details.module + "-" + details.name ); } } if ( bad === 0 ) { // Collapse the passing tests addClass( assertList, "qunit-collapsed" ); } else if ( bad && config.collapse && !collapseNext ) { // Skip collapsing the first failing test collapseNext = true; } else { // Collapse remaining tests addClass( assertList, "qunit-collapsed" ); } // The testItem.firstChild is the test name testTitle = testItem.firstChild; testCounts = bad ? "<b class='failed'>" + bad + "</b>, " + "<b class='passed'>" + good + "</b>, " : ""; testTitle.innerHTML += " <b class='counts'>(" + testCounts + details.assertions.length + ")</b>"; if ( details.skipped ) { testItem.className = "skipped"; skipped = document.createElement( "em" ); skipped.className = "qunit-skipped-label"; skipped.innerHTML = "skipped"; testItem.insertBefore( skipped, testTitle ); } else { addEvent( testTitle, "click", function() { toggleClass( assertList, "qunit-collapsed" ); } ); testItem.className = bad ? "fail" : "pass"; time = document.createElement( "span" ); time.className = "runtime"; time.innerHTML = details.runtime + " ms"; testItem.insertBefore( time, assertList ); } // Show the source of the test when showing assertions if ( details.source ) { sourceName = document.createElement( "p" ); sourceName.innerHTML = "<strong>Source: </strong>" + details.source; addClass( sourceName, "qunit-source" ); if ( bad === 0 ) { addClass( sourceName, "qunit-collapsed" ); } addEvent( testTitle, "click", function() { toggleClass( sourceName, "qunit-collapsed" ); } ); testItem.appendChild( sourceName ); } } ); // Avoid readyState issue with phantomjs // Ref: #818 var notPhantom = ( function( p ) { return !( p && p.version && p.version.major > 0 ); } )( window.phantom ); if ( notPhantom && document.readyState === "complete" ) { QUnit.load(); } else { addEvent( window, "load", QUnit.load ); }