*/
$wgJavaScriptTestConfig = array(
'qunit' => array(
+ // Page where documentation can be found relevant to the QUnit test suite being ran.
+ // Used in the intro paragraph on [[Special:JavaScriptTest/qunit]] for the
+ // documentation link in the "javascripttest-qunit-intro" message.
'documentation' => '//www.mediawiki.org/wiki/Manual:JavaScript_unit_testing',
+ // If you are submitting the QUnit test suite to a TestSwarm instance,
+ // point this to the "inject.js" script of that instance. This is was registers
+ // the QUnit hooks to extract the test results and push them back up into the
+ // TestSwarm database.
+ // @example 'http://localhost/testswarm/js/inject.js'
+ // @example '//integration.mediawiki.org/testswarm/js/inject.js'
+ 'testswarm-injectjs' => false,
),
);
HTML;
$out->addHtml( $this->wrapSummaryHtml( $summary, 'frameworkfound' ) . $baseHtml );
+ // This special page is disabled by default ($wgEnableJavaScriptTest), and contains
+ // no sensitive data. In order to allow TestSwarm to embed it into a test client window,
+ // we need to allow iframing of this page.
+ $out->allowClickjacking();
+
+ // Used in ./tests/qunit/data/testrunner.js, see also documentation of
+ // $wgJavaScriptTestConfig in DefaultSettings.php
+ $out->addJsConfigVars( 'QUnitTestSwarmInjectJSPath', $wgJavaScriptTestConfig['qunit']['testswarm-injectjs'] );
}
public function isListed(){
var $outputTypes = array(), $filterTypes = array();
+ /**
+ * The dependency-injected database to use.
+ *
+ * @var DatabaseBase|null
+ *
+ * @see self::setDb
+ */
+ protected $forcedDb = null;
+
/**
* @var LoadBalancer
*/
$table = ( $history == WikiExporter::CURRENT ) ? 'page' : 'revision';
$field = ( $history == WikiExporter::CURRENT ) ? 'page_id' : 'rev_id';
- $dbr = wfGetDB( DB_SLAVE );
+ $dbr = $this->forcedDb;
+ if ( $this->forcedDb === null ) {
+ $dbr = wfGetDB( DB_SLAVE );
+ }
$this->maxCount = $dbr->selectField( $table, "MAX($field)", '', __METHOD__ );
$this->startTime = wfTime();
$this->lastTime = $this->startTime;
* @return DatabaseBase
*/
function backupDb() {
+ if ( $this->forcedDb !== null ) {
+ return $this->forcedDb;
+ }
+
$this->lb = wfGetLBFactory()->newMainLB();
$db = $this->lb->getConnection( DB_SLAVE, 'backup' );
return $db;
}
+ /**
+ * Force the dump to use the provided database connection for database
+ * operations, wherever possible.
+ *
+ * @param $db DatabaseBase|null: (Optional) the database connection to
+ * use. If null, resort to use the globally provided ways to
+ * get database connections.
+ */
+ function setDb( DatabaseBase $db = null ) {
+ $this->forcedDb = $db;
+ }
+
function __destruct() {
if ( isset( $this->lb ) ) {
$this->lb->closeAll();
unset( $this->lb );
}
+ if ( $this->forcedDb !== null ) {
+ $this->db = $this->forcedDb;
+ return;
+ }
+
if ( isset( $this->db ) && $this->db->isOpen() ) {
throw new MWException( 'DB is set and has not been closed by the Load Balancer' );
}
}
- function initProgress( $history ) {
+ function initProgress( $history = WikiExporter::FULL ) {
parent::initProgress();
$this->timeOfCheckpoint = $this->startTime;
}
function dump( $history, $text = WikiExporter::TEXT ) {
- // This shouldn't happen if on console... ;)
- header( 'Content-type: text/html; charset=UTF-8' );
-
// Notice messages will foul up your XML output even if they're
// relatively harmless.
if ( ini_get( 'display_errors' ) )
return result === null ? null : [ result[0], result[2] ];
}
+ function templateWithOutReplacement() {
+ var result = sequence( [
+ templateName,
+ colon,
+ paramExpression
+ ] );
+ return result === null ? null : [ result[0], result[2] ];
+ }
+
var colon = makeStringParser(':');
var templateContents = choice( [
function() {
var res = sequence( [
- templateWithReplacement,
+ // templates can have placeholders for dynamic replacement eg: {{PLURAL:$1|one car|$1 cars}}
+ // or no placeholders eg: {{GRAMMAR:genitive|{{SITENAME}}}
+ choice( [ templateWithReplacement, templateWithOutReplacement ] ),
nOrMore( 0, templateParam )
] );
return res === null ? null : res[0].concat( res[1] );
templateContents
= twr:templateWithReplacement p:templateParam* { return twr.concat(p) }
+ / twr:templateWithOutReplacement p:templateParam* { return twr.concat(p) }
/ t:templateName p:templateParam* { return p.length ? [ t, p ] : [ t ] }
templateWithReplacement
= t:templateName ":" r:replacement { return [ t, r ] }
+templateWithOutReplacement
+ = t:templateName ":" p:paramExpression { return [ t, p ] }
+
templateParam
= "|" e:paramExpression* { return e.length > 1 ? [ "CONCAT" ].concat(e) : e[0]; }
//Selenium
'SeleniumTestConstants' => "$testFolder/selenium/SeleniumTestConstants.php",
+ //maintenance
+ 'DumpTestCase' => "$testFolder/phpunit/maintenance/DumpTestCase.php",
+
//Generic providers
'MediaWikiProvide' => "$testFolder/phpunit/includes/Providers.php",
);
'MediaWikiLangTestCase',
'MediaWikiTestCase',
'PHPUnit_Framework_TestCase',
+ 'DumpTestCase',
) );
$testClassRegex = "^class .* extends ($testClassRegex)";
$finder = "find $rootPath -name '*.php' '!' -name '*Test.php'" .
--- /dev/null
+<?php
+global $IP;
+require_once( "$IP/maintenance/backup.inc" );
+
+/**
+ * Base TestCase for dumps
+ */
+abstract class DumpTestCase extends MediaWikiTestCase {
+
+ /**
+ * exception to be rethrown once in sound PHPUnit surrounding
+ *
+ * As the current MediaWikiTestCase::run is not robust enough to recover
+ * from thrown exceptions directly, we cannot throw frow within
+ * self::addDBData, although it would be appropriate. Hence, we catch the
+ * exception and store it until we are in setUp and may finally rethrow
+ * the exception without crashing the test suite.
+ *
+ * @var Exception|null
+ */
+ protected $exceptionFromAddDBData = null;
+
+ /**
+ * Holds the xmlreader used for analyzing an xml dump
+ *
+ * @var XMLReader|null
+ */
+ protected $xml = null;
+
+ /**
+ * Adds a revision to a page, while returning the resuting revision's id
+ *
+ * @param $page WikiPage: page to add the revision to
+ * @param $text string: revisions text
+ * @param $text string: revisions summare
+ *
+ * @throws MWExcepion
+ */
+ protected function addRevision( Page $page, $text, $summary ) {
+ $status = $page->doEdit( $text, $summary );
+ if ( $status->isGood() ) {
+ $value = $status->getValue();
+ $revision = $value['revision'];
+ $revision_id = $revision->getId();
+ $text_id = $revision->getTextId();
+ if ( ( $revision_id > 0 ) && ( $text_id > 0 ) ) {
+ return array( $revision_id, $text_id );
+ }
+ }
+ throw new MWException( "Could not determine revision id (" . $status->getXML() . ")" );
+ }
+
+
+ /**
+ * gunzips the given file and stores the result in the original file name
+ *
+ * @param $fname string: filename to read the gzipped data from and stored
+ * the gunzipped data into
+ */
+ protected function gunzip( $fname ) {
+ $gzipped_contents = file_get_contents( $fname );
+ if ( $gzipped_contents === FALSE ) {
+ $this->fail( "Could not get contents of $fname" );
+ }
+ // We resort to use gzinflate instead of gzdecode, as gzdecode
+ // need not be available
+ $contents = gzinflate( substr( $gzipped_contents, 10, -8 ) );
+ $this->assertEquals( strlen( $contents ),
+ file_put_contents( $fname, $contents ), "# bytes written" );
+ }
+
+ /**
+ * obtains a new temporary file name
+ *
+ * The obtained filename is enlisted to be removed upon tearDown
+ *
+ * @returns string: absolute name of the temporary file
+ */
+ protected function getNewTempFile() {
+ $fname = tempnam( wfTempDir(), 'MW_PHPUnit_' . get_class( $this ) . '_' );
+ $this->tmpfiles[] = $fname;
+ return $fname;
+ }
+
+ /**
+ * Default set up function.
+ *
+ * Clears $wgUser, and reports errors from addDBData to PHPUnit
+ */
+ function setUp() {
+ global $wgUser;
+
+ parent::setUp();
+
+ // Check if any Exception is stored for rethrowing from addDBData
+ // @see self::exceptionFromAddDBData
+ if ( $this->exceptionFromAddDBData !== null ) {
+ throw $this->exceptionFromAddDBData;
+ }
+ $this->tmpfiles = array();
+
+ $wgUser = new User();
+ }
+
+ /**
+ * Default tear down function
+ *
+ * Removes all files that have been allocated via self::getNewTempFile, even if
+ * they turn out to be (empty or non-empty) directories now.
+ */
+ function tearDown() {
+ foreach ( $this->tmpfiles as $fname ) {
+ if ( is_file( $fname ) || ( is_link( $fname ) ) ) {
+ unlink( $fname );
+ } elseif ( is_dir( $fname ) ) {
+ wfRecursiveRemoveDir( $fname );
+ }
+ }
+ parent::tearDown();
+ }
+
+
+ /**
+ * Step the current XML reader until node end of given name is found.
+ *
+ * @param $name string: name of the closing element to look for
+ * (e.g.: "mediawiki" when looking for </mediawiki>)
+ *
+ * @return bool: true iff the end node could be found. false otherwise.
+ */
+ protected function skipToNodeEnd( $name ) {
+ while ( $this->xml->read() ) {
+ if ( $this->xml->nodeType == XMLReader::END_ELEMENT &&
+ $this->xml->name == $name ) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Step the current XML reader to the first element start after the node
+ * end of a given name.
+ *
+ * @param $name string: name of the closing element to look for
+ * (e.g.: "mediawiki" when looking for </mediawiki>)
+ *
+ * @return bool: true iff new element after the closing of $name could be
+ * found. false otherwise.
+ */
+ protected function skipPastNodeEnd( $name ) {
+ $this->assertTrue( $this->skipToNodeEnd( $name ),
+ "Skipping to end of $name" );
+ while ( $this->xml->read() ) {
+ if ( $this->xml->nodeType == XMLReader::ELEMENT ) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Opens an XML file to analyze and optionally skips past siteinfo.
+ *
+ * @param $fname string: name of file to analyze
+ * @param $skip_siteinfo bool: (optional) If true, step the xml reader
+ * to the first element after </siteinfo>
+ */
+ protected function assertDumpStart( $fname, $skip_siteinfo = true ) {
+ $this->xml = new XMLReader();
+ $this->assertTrue( $this->xml->open( $fname ),
+ "Opening temporary file $fname via XMLReader failed" );
+ if ( $skip_siteinfo ) {
+ $this->assertTrue( $this->skipPastNodeEnd( "siteinfo" ),
+ "Skipping past end of siteinfo" );
+ }
+ }
+
+ /**
+ * Asserts that the xml reader is at the final closing tag of an xml file and
+ * closes the reader.
+ *
+ * @param $tag string: (optional) the name of the final tag
+ * (e.g.: "mediawiki" for </mediawiki>)
+ */
+ protected function assertDumpEnd( $name = "mediawiki" ) {
+ $this->assertNodeEnd( $name, false );
+ if ( $this->xml->read() ) {
+ $this->skipWhitespace();
+ }
+ $this->assertEquals( $this->xml->nodeType, XMLReader::NONE,
+ "No proper entity left to parse" );
+ $this->xml->close();
+ }
+
+ /**
+ * Steps the xml reader over white space
+ */
+ protected function skipWhitespace() {
+ $cont = true;
+ while ( $cont && ( ( $this->xml->nodeType == XMLReader::WHITESPACE )
+ || ( $this->xml->nodeType == XMLReader::SIGNIFICANT_WHITESPACE ) ) ) {
+ $cont = $this->xml->read();
+ }
+ }
+
+ /**
+ * Asserts that the xml reader is at an element of given name, and optionally
+ * skips past it.
+ *
+ * @param $name string: the name of the element to check for
+ * (e.g.: "mediawiki" for <mediawiki>)
+ * @param $skip bool: (optional) if true, skip past the found element
+ */
+ protected function assertNodeStart( $name, $skip = true ) {
+ $this->assertEquals( $name, $this->xml->name, "Node name" );
+ $this->assertEquals( XMLReader::ELEMENT, $this->xml->nodeType, "Node type" );
+ if ( $skip ) {
+ $this->assertTrue( $this->xml->read(), "Skipping past start tag" );
+ }
+ }
+
+ /**
+ * Asserts that the xml reader is at an closing element of given name, and optionally
+ * skips past it.
+ *
+ * @param $name string: the name of the closing element to check for
+ * (e.g.: "mediawiki" for </mediawiki>)
+ * @param $skip bool: (optional) if true, skip past the found element
+ */
+ protected function assertNodeEnd( $name, $skip = true ) {
+ $this->assertEquals( $name, $this->xml->name, "Node name" );
+ $this->assertEquals( XMLReader::END_ELEMENT, $this->xml->nodeType, "Node type" );
+ if ( $skip ) {
+ $this->assertTrue( $this->xml->read(), "Skipping past end tag" );
+ }
+ }
+
+
+ /**
+ * Asserts that the xml reader is at an element of given tag that contains a given text,
+ * and skips over the element.
+ *
+ * @param $name string: the name of the element to check for
+ * (e.g.: "mediawiki" for <mediawiki>...</mediawiki>)
+ * @param $text string|false: If string, check if it equals the elements text.
+ * If false, ignore the element's text
+ * @param $skip_ws bool: (optional) if true, skip past white spaces that trail the
+ * closing element.
+ */
+ protected function assertTextNode( $name, $text, $skip_ws = true ) {
+ $this->assertNodeStart( $name );
+
+ if ( $text !== false ) {
+ $this->assertEquals( $text, $this->xml->value, "Text of node " . $name );
+ }
+ $this->assertTrue( $this->xml->read(), "Skipping past processed text of " . $name );
+ $this->assertNodeEnd( $name );
+
+ if ( $skip_ws ) {
+ $this->skipWhitespace();
+ }
+ }
+
+ /**
+ * Asserts that the xml reader is at the start of a page element and skips over the first
+ * tags, after checking them.
+ *
+ * Besides the opening page element, this function also checks for and skips over the
+ * title, ns, and id tags. Hence after this function, the xml reader is at the first
+ * revision of the current page.
+ *
+ * @param $id int: id of the page to assert
+ * @param $ns int: number of namespage to assert
+ * @param $name string: title of the current page
+ */
+ protected function assertPageStart( $id, $ns, $name ) {
+
+ $this->assertNodeStart( "page" );
+ $this->skipWhitespace();
+
+ $this->assertTextNode( "title", $name );
+ $this->assertTextNode( "ns", $ns );
+ $this->assertTextNode( "id", $id );
+
+ }
+
+ /**
+ * Asserts that the xml reader is at the page's closing element and skips to the next
+ * element.
+ */
+ protected function assertPageEnd() {
+ $this->assertNodeEnd( "page" );
+ $this->skipWhitespace();
+ }
+
+ /**
+ * Asserts that the xml reader is at a revision and checks its representation before
+ * skipping over it.
+ *
+ * @param $id int: id of the revision
+ * @param $summary string: summary of the revision
+ * @param $text_id int: id of the revision's text
+ * @param $text_bytes int: # of bytes in the revision's text
+ * @param $text_sha1 string: the base36 SHA-1 of the revision's text
+ * @param $text string|false: (optional) The revision's string, or false to check for a
+ * revision stub
+ */
+ protected function assertRevision( $id, $summary, $text_id, $text_bytes, $text_sha1, $text = false ) {
+
+ $this->assertNodeStart( "revision" );
+ $this->skipWhitespace();
+
+ $this->assertTextNode( "id", $id );
+ $this->assertTextNode( "timestamp", false );
+
+ $this->assertNodeStart( "contributor" );
+ $this->skipWhitespace();
+ $this->assertTextNode( "ip", false );
+ $this->assertNodeEnd( "contributor" );
+ $this->skipWhitespace();
+
+ $this->assertTextNode( "comment", $summary );
+
+ $this->assertNodeStart( "text", false );
+ if ( $text_bytes !== false ) {
+ $this->assertEquals( $this->xml->getAttribute( "bytes" ), $text_bytes,
+ "Attribute 'bytes' of revision " . $id );
+ }
+
+
+ if ( $text === false ) {
+ // Testing for a stub
+ $this->assertEquals( $this->xml->getAttribute( "id" ), $text_id,
+ "Text id of revision " . $id );
+ $this->assertFalse( $this->xml->hasValue, "Revision has text" );
+ $this->assertTrue( $this->xml->read(), "Skipping text start tag" );
+ if ( ( $this->xml->nodeType == XMLReader::END_ELEMENT )
+ && ( $this->xml->name == "text" ) ) {
+
+ $this->xml->read();
+ }
+ $this->skipWhitespace();
+ } else {
+ // Testing for a real dump
+ $this->assertTrue( $this->xml->read(), "Skipping text start tag" );
+ $this->assertEquals( $text, $this->xml->value, "Text of revision " . $id );
+ $this->assertTrue( $this->xml->read(), "Skipping past text" );
+ $this->assertNodeEnd( "text" );
+ $this->skipWhitespace();
+ }
+
+ $this->assertTextNode( "sha1", $text_sha1 );
+
+ $this->assertNodeEnd( "revision" );
+ $this->skipWhitespace();
+ }
+
+}
<testsuite name="skins">
<directory>skins</directory>
</testsuite>
+ <!-- As there is a class Maintenance, we cannot use the
+ name "maintenance" directly -->
+ <testsuite name="maintenance_suite">
+ <directory>maintenance</directory>
+ </testsuite>
<testsuite name="structure">
<file>StructureTest.php</file>
</testsuite>
'mediawiki.special.recentchanges',
'mediawiki.jqueryMsg',
),
+ 'position' => 'top',
)
);
/**
* Load TestSwarm agent
*/
-if ( QUnit.urlParams.swarmURL ) {
- document.write( "<scr" + "ipt src='" + QUnit.fixurl( mw.config.get( 'wgScriptPath' )
- + '/tests/qunit/data/testwarm.inject.js' ) + "'></scr" + "ipt>" );
+// Only if the current url indicates that there is a TestSwarm instance watching us
+// (TestSwarm appends swarmURL to the test suites url it loads in iframes).
+// Otherwise this is just a simple view of Special:JavaScriptTest/qunit directly,
+// no point in loading inject.js in that case. Also, make sure that this instance
+// of MediaWiki has actually been configured with the required url to that inject.js
+// script. By default it is false.
+if ( QUnit.urlParams.swarmURL && mw.config.get( 'QUnitTestSwarmInjectJSPath' ) ) {
+ document.write( "<scr" + "ipt src='" + QUnit.fixurl( mw.config.get( 'QUnitTestSwarmInjectJSPath' ) ) + "'></scr" + "ipt>" );
}
/**
+++ /dev/null
-/*
- Copyright (c) 2009 John Resig
-
- Permission is hereby granted, free of charge, to any person
- obtaining a copy of this software and associated documentation
- files (the "Software"), to deal in the Software without
- restriction, including without limitation the rights to use,
- copy, modify, merge, publish, distribute, sublicense, and/or sell
- copies of the Software, and to permit persons to whom the
- Software is furnished to do so, subject to the following
- conditions:
-
- The above copyright notice and this permission notice shall be
- included in all copies or substantial portions of the Software.
-
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
- OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
- HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- OTHER DEALINGS IN THE SOFTWARE.
-
-*/
-(function(){
-
- var DEBUG = false;
-
- var doPost = false;
-
- try {
- doPost = !!window.top.postMessage;
- } catch(e){}
-
- var search = window.location.search,
- url, index;
- if( ( index = search.indexOf( "swarmURL=" ) ) != -1 )
- url = decodeURIComponent( search.slice( index + 9 ) );
-
- if ( !DEBUG && (!url || url.indexOf("http") !== 0) ) {
- return;
- }
-
- var submitTimeout = 5;
-
- var curHeartbeat;
- var beatRate = 20;
-
- // Expose the TestSwarm API
- window.TestSwarm = {
- submit: submit,
- heartbeat: function(){
- if ( curHeartbeat ) {
- clearTimeout( curHeartbeat );
- }
-
- curHeartbeat = setTimeout(function(){
- submit({ fail: -1, total: -1 });
- }, beatRate * 1000);
- },
- serialize: function(){
- return trimSerialize();
- }
- };
-
- // Prevent careless things from executing
- window.print = window.confirm = window.alert = window.open = function(){};
-
- window.onerror = function(e){
- document.body.appendChild( document.createTextNode( "ERROR: " + e ));
- submit({ fail: 0, error: 1, total: 1 });
- return false;
- };
-
- // QUnit (jQuery)
- // http://docs.jquery.com/QUnit
- if ( typeof QUnit !== "undefined" ) {
- QUnit.done = function(results){
- submit({
- fail: results.failed,
- error: 0,
- total: results.total
- });
- };
-
- QUnit.log = window.TestSwarm.heartbeat;
- window.TestSwarm.heartbeat();
-
- window.TestSwarm.serialize = function(){
- // Clean up the HTML (remove any un-needed test markup)
- remove("nothiddendiv");
- remove("loadediframe");
- remove("dl");
- remove("main");
-
- // Show any collapsed results
- var ol = document.getElementsByTagName("ol");
- for ( var i = 0; i < ol.length; i++ ) {
- ol[i].style.display = "block";
- }
-
- return trimSerialize();
- };
-
- // UnitTestJS (Prototype, Scriptaculous)
- // http://github.com/tobie/unittest_js/tree/master
- } else if ( typeof Test !== "undefined" && Test && Test.Unit && Test.Unit.runners ) {
- var total_runners = Test.Unit.runners.length, cur_runners = 0;
- var total = 0, fail = 0, error = 0;
-
- for (var i = 0; i < Test.Unit.runners.length; i++) (function(i){
- var finish = Test.Unit.runners[i].finish;
- Test.Unit.runners[i].finish = function(){
- finish.call( this );
-
- var results = this.getResult();
- total += results.assertions;
- fail += results.failures;
- error += results.errors;
-
- if ( ++cur_runners === total_runners ) {
- submit({
- fail: fail,
- error: error,
- total: total
- });
- }
- };
- })(i);
-
- // JSSpec (MooTools)
- // http://jania.pe.kr/aw/moin.cgi/JSSpec
- } else if ( typeof JSSpec !== "undefined" && JSSpec && JSSpec.Logger ) {
- var onRunnerEnd = JSSpec.Logger.prototype.onRunnerEnd;
- JSSpec.Logger.prototype.onRunnerEnd = function(){
- onRunnerEnd.call(this);
-
- // Show any collapsed results
- var ul = document.getElementsByTagName("ul");
- for ( var i = 0; i < ul.length; i++ ) {
- ul[i].style.display = "block";
- }
-
- submit({
- fail: JSSpec.runner.getTotalFailures(),
- error: JSSpec.runner.getTotalErrors(),
- total: JSSpec.runner.totalExamples
- });
- };
-
- window.TestSwarm.serialize = function(){
- // Show any collapsed results
- var ul = document.getElementsByTagName("ul");
- for ( var i = 0; i < ul.length; i++ ) {
- ul[i].style.display = "block";
- }
-
- return trimSerialize();
- };
-
- // JSUnit
- // http://www.jsunit.net/
- // Note: Injection file must be included before the frames
- // are document.write()d into the page.
- } else if ( typeof JsUnitTestManager !== "undefined" ) {
- var _done = JsUnitTestManager.prototype._done;
- JsUnitTestManager.prototype._done = function(){
- _done.call(this);
-
- submit({
- fail: this.failureCount,
- error: this.errorCount,
- total: this.totalCount
- });
- };
-
- window.TestSwarm.serialize = function(){
- return "<pre>" + this.log.join("\n") + "</pre>";
- };
-
- // Selenium Core
- // http://seleniumhq.org/projects/core/
- } else if ( typeof SeleniumTestResult !== "undefined" && typeof LOG !== "undefined" ) {
- // Completely overwrite the postback
- SeleniumTestResult.prototype.post = function(){
- submit({
- fail: this.metrics.numCommandFailures,
- error: this.metrics.numCommandErrors,
- total: this.metrics.numCommandPasses + this.metrics.numCommandFailures + this.metrics.numCommandErrors
- });
- };
-
- window.TestSwarm.serialize = function(){
- var results = [];
- while ( LOG.pendingMessages.length ) {
- var msg = LOG.pendingMessages.shift();
- results.push( msg.type + ": " + msg.msg );
- }
-
- return "<pre>" + results.join("\n") + "</pre>";
- };
-
- // Dojo Objective Harness
- // http://docs.dojocampus.org/quickstart/doh
- } else if ( typeof doh !== "undefined" && doh._report ) {
- var _report = doh._report;
- doh._report = function(){
- _report.apply(this, arguments);
-
- submit({
- fail: doh._failureCount,
- error: doh._errorCount,
- total: doh._testCount
- });
- };
-
- window.TestSwarm.serialize = function(){
- return "<pre>" + document.getElementById("logBody").innerHTML + "</pre>";
- };
- // Screw.Unit
- // git://github.com/nathansobo/screw-unit.git
- } else if ( typeof Screw !== "undefined" && typeof jQuery !== 'undefined' && Screw && Screw.Unit ) {
- $(Screw).bind("after", function() {
- var passed = $('.passed').length;
- var failed = $('.failed').length;
- submit({
- fail: failed,
- error: 0,
- total: failed + passed
- });
- });
-
- $(Screw).bind("loaded", function() {
- $('.it')
- .bind("passed", window.TestSwarm.heartbeat)
- .bind("failed", window.TestSwarm.heartbeat);
- window.TestSwarm.heartbeat();
- });
-
- window.TestSwarm.serialize = function(){
- return trimSerialize();
- };
- }
-
- function trimSerialize(doc) {
- doc = doc || document;
-
- var scripts = doc.getElementsByTagName("script");
- while ( scripts.length ) {
- remove( scripts[0] );
- }
-
- var root = window.location.href.replace(/(https?:\/\/.*?)\/.*/, "$1");
- var cur = window.location.href.replace(/[^\/]*$/, "");
-
- var links = doc.getElementsByTagName("link");
- for ( var i = 0; i < links.length; i++ ) {
- var href = links[i].href;
- if ( href.indexOf("/") === 0 ) {
- href = root + href;
- } else if ( !/^https?:\/\//.test( href ) ) {
- href = cur + href;
- }
- links[i].href = href;
- }
-
- return ("<html>" + doc.documentElement.innerHTML + "</html>")
- .replace(/\s+/g, " ");
- }
-
- function remove(elem){
- if ( typeof elem === "string" ) {
- elem = document.getElementById( elem );
- }
-
- if ( elem ) {
- elem.parentNode.removeChild( elem );
- }
- }
-
- function submit(params){
- if ( curHeartbeat ) {
- clearTimeout( curHeartbeat );
- }
-
- var paramItems = (url.split("?")[1] || "").split("&");
-
- for ( var i = 0; i < paramItems.length; i++ ) {
- if ( paramItems[i] ) {
- var parts = paramItems[i].split("=");
- if ( !params[ parts[0] ] ) {
- params[ parts[0] ] = parts[1];
- }
- }
- }
-
- if ( !params.state ) {
- params.state = "saverun";
- }
-
- if ( !params.results ) {
- params.results = window.TestSwarm.serialize();
- }
-
- if ( doPost ) {
- // Build Query String
- var query = "";
-
- for ( var i in params ) {
- query += ( query ? "&" : "" ) + i + "=" +
- encodeURIComponent(params[i]);
- }
-
- if ( DEBUG ) {
- alert( query );
- } else {
- window.top.postMessage( query, "*" );
- }
-
- } else {
- var form = document.createElement("form");
- form.action = url;
- form.method = "POST";
-
- for ( var i in params ) {
- var input = document.createElement("input");
- input.type = "hidden";
- input.name = i;
- input.value = params[i];
- form.appendChild( input );
- }
-
- if ( DEBUG ) {
- alert( form.innerHTML );
- } else {
-
- // Watch for the result submission timing out
- setTimeout(function(){
- submit( params );
- }, submitTimeout * 1000);
-
- document.body.appendChild( form );
- form.submit();
- }
- }
- }
-
-})();
/* WikiPage specific */
mw.config.set({"wgCanonicalNamespace": "", "wgCanonicalSpecialPageName": false, "wgNamespaceNumber": 0, "wgPageName": "Sandbox", "wgTitle": "Sandbox", "wgCurRevisionId": 486, "wgArticleId": 84, "wgIsArticle": true, "wgAction": "view", "wgUserName": null, "wgUserGroups": ["*"], "wgCategories": [], "wgBreakFrames": false, "wgPageContentLanguage": "en", "wgSeparatorTransformTable": ["", ""], "wgDigitTransformTable": ["", ""], "wgRestrictionEdit": [], "wgRestrictionMove": [], "wgRedirectedFrom": "Sandbox"});
-
+
+ /* Special:JavaScriptTest/qunit specific */
+ mw.config.set({"QUnitTestSwarmInjectJSPath": false});
+
/**
* Fix wgScriptPath and the like to the real thing,
* instead of fake ones (for access to /tests/qunit/data/)