From: Timo Tijhof Date: Sat, 20 Oct 2012 01:51:15 +0000 (+0200) Subject: Fix warnings and enforce conventions in ContentHandler tests. X-Git-Tag: 1.31.0-rc.0~21860 X-Git-Url: https://git.cyclocoop.org/%27.WWW_URL.%27admin/?a=commitdiff_plain;h=a4aef7d4952ce7b1887a4ba4f5c605e1c09cc770;p=lhc%2Fweb%2Fwiklou.git Fix warnings and enforce conventions in ContentHandler tests. Syntax: * Call parent setUp from setUp. * Set required globals for the test inside the test class instead of assuming the default settings. * Data providers are called statically and outside setUp/tearDown ("public static function") * Test function names should be prefixed with "test" ("testIsRedirect") * Marked 2 functions as unused. JavascriptContentTest has 2 data providers for tests that don't exist in it (nor in TextContentText) but do exist in WikitextContentTest. Style: * Single quotes * Remove odd comment "# =====" lines * Consistent tree wrapping with arrays. array( array( .. ) ); array( array( .. ) ); Some were closing on the previous line instead. Made it consistent now. * Remove odd indentation to make nested arrays line up: array( 'foo' => array( 'bar' => true, 'baz' => array() ) ) array( 'foo' => array( 'bar' => true, 'baz' => array() ) ) We don't do this kind of indentation because it is fragile and becomes outdates when any of the earlier keys ("foo") change. Converted to a regular tree instead. Also triggered git warnings for mixing spaces with tabs, which is almost always an detector for this style. * Not using @annotations in inline comments, reserved (and only parsed/meaningful) for block comments. Follows-up 8b568be5e2dfb889e1eeedbdca50b304864174f7 Change-Id: Ic55d539b9a58f448b550bcd98894d389764e0694 --- diff --git a/includes/AutoLoader.php b/includes/AutoLoader.php index d98556ee34..c97c95a965 100644 --- a/includes/AutoLoader.php +++ b/includes/AutoLoader.php @@ -1095,13 +1095,15 @@ $wgAutoloadLocalClasses = array( 'TestRecorder' => 'tests/testHelpers.inc', # tests/phpunit - 'DummyContentHandlerForTesting' => 'tests/phpunit/includes/ContentHandlerTest.php', - 'DummyContentForTesting' => 'tests/phpunit/includes/ContentHandlerTest.php', - 'JavascriptContentTest' => 'tests/phpunit/includes/JavascriptContentTest.php', 'RevisionStorageTest' => 'tests/phpunit/includes/RevisionStorageTest.php', - 'TextContentTest' => 'tests/phpunit/includes/TextContentTest.php', 'WikiPageTest' => 'tests/phpunit/includes/WikiPageTest.php', + # tests/phpunit/content + 'DummyContentHandlerForTesting' => 'tests/phpunit/includes/content/ContentHandlerTest.php', + 'DummyContentForTesting' => 'tests/phpunit/includes/content/ContentHandlerTest.php', + 'JavascriptContentTest' => 'tests/phpunit/includes/content/JavascriptContentTest.php', + 'TextContentTest' => 'tests/phpunit/includes/content/TextContentTest.php', + # tests/phpunit/includes 'GenericArrayObjectTest' => 'tests/phpunit/includes/libs/GenericArrayObjectTest.php', diff --git a/includes/DefaultSettings.php b/includes/DefaultSettings.php index cea63e07a3..c485b163a4 100644 --- a/includes/DefaultSettings.php +++ b/includes/DefaultSettings.php @@ -752,10 +752,14 @@ $wgMediaHandlers = array( * @since 1.21 */ $wgContentHandlers = array( - CONTENT_MODEL_WIKITEXT => 'WikitextContentHandler', // the usual case - CONTENT_MODEL_JAVASCRIPT => 'JavaScriptContentHandler', // dumb version, no syntax highlighting - CONTENT_MODEL_CSS => 'CssContentHandler', // dumb version, no syntax highlighting - CONTENT_MODEL_TEXT => 'TextContentHandler', // plain text, for use by extensions etc + // the usual case + CONTENT_MODEL_WIKITEXT => 'WikitextContentHandler', + // dumb version, no syntax highlighting + CONTENT_MODEL_JAVASCRIPT => 'JavaScriptContentHandler', + // dumb version, no syntax highlighting + CONTENT_MODEL_CSS => 'CssContentHandler', + // plain text, for use by extensions etc + CONTENT_MODEL_TEXT => 'TextContentHandler', ); /** diff --git a/tests/phpunit/MediaWikiTestCase.php b/tests/phpunit/MediaWikiTestCase.php index 5bc36edea6..258dfec463 100644 --- a/tests/phpunit/MediaWikiTestCase.php +++ b/tests/phpunit/MediaWikiTestCase.php @@ -250,7 +250,7 @@ abstract class MediaWikiTestCase extends PHPUnit_Framework_TestCase { throw new MWException( "MW global $name is not an array." ); } - //NOTE: do not use array_merge, it screws up for numeric keys. + // NOTE: do not use array_merge, it screws up for numeric keys. $merged = $GLOBALS[$name]; foreach ( $values as $k => $v ) { $merged[$k] = $v; diff --git a/tests/phpunit/includes/ContentHandlerTest.php b/tests/phpunit/includes/ContentHandlerTest.php deleted file mode 100644 index 797a3eedd8..0000000000 --- a/tests/phpunit/includes/ContentHandlerTest.php +++ /dev/null @@ -1,410 +0,0 @@ -resetNamespaces(); # reset namespace cache - } - - public function teardown() { - global $wgExtraNamespaces, $wgNamespaceContentModels, $wgContentHandlers, $wgContLang; - - unset( $wgExtraNamespaces[ 12312 ] ); - unset( $wgExtraNamespaces[ 12313 ] ); - - unset( $wgNamespaceContentModels[ 12312 ] ); - unset( $wgContentHandlers[ "testing" ] ); - - MWNamespace::getCanonicalNamespaces( true ); # reset namespace cache - $wgContLang->resetNamespaces(); # reset namespace cache - - parent::teardown(); - } - - public function dataGetDefaultModelFor() { - //NOTE: assume that the Help namespace default to wikitext content - return array( - array( 'Help:Foo', CONTENT_MODEL_WIKITEXT ), - array( 'Help:Foo.js', CONTENT_MODEL_WIKITEXT ), - array( 'Help:Foo/bar.js', CONTENT_MODEL_WIKITEXT ), - array( 'User:Foo', CONTENT_MODEL_WIKITEXT ), - array( 'User:Foo.js', CONTENT_MODEL_WIKITEXT ), - array( 'User:Foo/bar.js', CONTENT_MODEL_JAVASCRIPT ), - array( 'User:Foo/bar.css', CONTENT_MODEL_CSS ), - array( 'User talk:Foo/bar.css', CONTENT_MODEL_WIKITEXT ), - array( 'User:Foo/bar.js.xxx', CONTENT_MODEL_WIKITEXT ), - array( 'User:Foo/bar.xxx', CONTENT_MODEL_WIKITEXT ), - array( 'MediaWiki:Foo.js', CONTENT_MODEL_JAVASCRIPT ), - array( 'MediaWiki:Foo.css', CONTENT_MODEL_CSS ), - array( 'MediaWiki:Foo.JS', CONTENT_MODEL_WIKITEXT ), - array( 'MediaWiki:Foo.CSS', CONTENT_MODEL_WIKITEXT ), - array( 'MediaWiki:Foo.css.xxx', CONTENT_MODEL_WIKITEXT ), - ); - } - - /** - * @dataProvider dataGetDefaultModelFor - */ - public function testGetDefaultModelFor( $title, $expectedModelId ) { - $title = Title::newFromText( $title ); - $this->assertEquals( $expectedModelId, ContentHandler::getDefaultModelFor( $title ) ); - } - /** - * @dataProvider dataGetDefaultModelFor - */ - public function testGetForTitle( $title, $expectedContentModel ) { - $title = Title::newFromText( $title ); - $handler = ContentHandler::getForTitle( $title ); - $this->assertEquals( $expectedContentModel, $handler->getModelID() ); - } - - public function dataGetLocalizedName() { - return array( - array( null, null ), - array( "xyzzy", null ), - - array( CONTENT_MODEL_JAVASCRIPT, '/javascript/i' ), //XXX: depends on content language - ); - } - - /** - * @dataProvider dataGetLocalizedName - */ - public function testGetLocalizedName( $id, $expected ) { - $name = ContentHandler::getLocalizedName( $id ); - - if ( $expected ) { - $this->assertNotNull( $name, "no name found for content model $id" ); - $this->assertTrue( preg_match( $expected, $name ) > 0 , - "content model name for #$id did not match pattern $expected" ); - } else { - $this->assertEquals( $id, $name, "localization of unknown model $id should have " - . "fallen back to use the model id directly." ); - } - } - - public function dataGetPageLanguage() { - global $wgLanguageCode; - - return array( - array( "Main", $wgLanguageCode ), - array( "Dummy:Foo", $wgLanguageCode ), - array( "MediaWiki:common.js", 'en' ), - array( "User:Foo/common.js", 'en' ), - array( "MediaWiki:common.css", 'en' ), - array( "User:Foo/common.css", 'en' ), - array( "User:Foo", $wgLanguageCode ), - - array( CONTENT_MODEL_JAVASCRIPT, 'javascript' ), - ); - } - - /** - * @dataProvider dataGetPageLanguage - */ - public function testGetPageLanguage( $title, $expected ) { - if ( is_string( $title ) ) { - $title = Title::newFromText( $title ); - } - - $expected = wfGetLangObj( $expected ); - - $handler = ContentHandler::getForTitle( $title ); - $lang = $handler->getPageLanguage( $title ); - - $this->assertEquals( $expected->getCode(), $lang->getCode() ); - } - - public function testGetContentText_Null( ) { - global $wgContentHandlerTextFallback; - - $content = null; - - $wgContentHandlerTextFallback = 'fail'; - $text = ContentHandler::getContentText( $content ); - $this->assertEquals( '', $text ); - - $wgContentHandlerTextFallback = 'serialize'; - $text = ContentHandler::getContentText( $content ); - $this->assertEquals( '', $text ); - - $wgContentHandlerTextFallback = 'ignore'; - $text = ContentHandler::getContentText( $content ); - $this->assertEquals( '', $text ); - } - - public function testGetContentText_TextContent( ) { - global $wgContentHandlerTextFallback; - - $content = new WikitextContent( "hello world" ); - - $wgContentHandlerTextFallback = 'fail'; - $text = ContentHandler::getContentText( $content ); - $this->assertEquals( $content->getNativeData(), $text ); - - $wgContentHandlerTextFallback = 'serialize'; - $text = ContentHandler::getContentText( $content ); - $this->assertEquals( $content->serialize(), $text ); - - $wgContentHandlerTextFallback = 'ignore'; - $text = ContentHandler::getContentText( $content ); - $this->assertEquals( $content->getNativeData(), $text ); - } - - public function testGetContentText_NonTextContent( ) { - global $wgContentHandlerTextFallback; - - $content = new DummyContentForTesting( "hello world" ); - - $wgContentHandlerTextFallback = 'fail'; - - try { - $text = ContentHandler::getContentText( $content ); - - $this->fail( "ContentHandler::getContentText should have thrown an exception for non-text Content object" ); - } catch (MWException $ex) { - // as expected - } - - $wgContentHandlerTextFallback = 'serialize'; - $text = ContentHandler::getContentText( $content ); - $this->assertEquals( $content->serialize(), $text ); - - $wgContentHandlerTextFallback = 'ignore'; - $text = ContentHandler::getContentText( $content ); - $this->assertNull( $text ); - } - - #public static function makeContent( $text, Title $title, $modelId = null, $format = null ) - - public function dataMakeContent() { - //NOTE: assume the Help namespace defaults to wikitext content - return array( - array( 'hallo', 'Help:Test', null, null, CONTENT_MODEL_WIKITEXT, 'hallo', false ), - array( 'hallo', 'MediaWiki:Test.js', null, null, CONTENT_MODEL_JAVASCRIPT, 'hallo', false ), - array( serialize('hallo'), 'Dummy:Test', null, null, "testing", 'hallo', false ), - - array( 'hallo', 'Help:Test', null, CONTENT_FORMAT_WIKITEXT, CONTENT_MODEL_WIKITEXT, 'hallo', false ), - array( 'hallo', 'MediaWiki:Test.js', null, CONTENT_FORMAT_JAVASCRIPT, CONTENT_MODEL_JAVASCRIPT, 'hallo', false ), - array( serialize('hallo'), 'Dummy:Test', null, "testing", "testing", 'hallo', false ), - - array( 'hallo', 'Help:Test', CONTENT_MODEL_CSS, null, CONTENT_MODEL_CSS, 'hallo', false ), - array( 'hallo', 'MediaWiki:Test.js', CONTENT_MODEL_CSS, null, CONTENT_MODEL_CSS, 'hallo', false ), - array( serialize('hallo'), 'Dummy:Test', CONTENT_MODEL_CSS, null, CONTENT_MODEL_CSS, serialize('hallo'), false ), - - array( 'hallo', 'Help:Test', CONTENT_MODEL_WIKITEXT, "testing", null, null, true ), - array( 'hallo', 'MediaWiki:Test.js', CONTENT_MODEL_CSS, "testing", null, null, true ), - array( 'hallo', 'Dummy:Test', CONTENT_MODEL_JAVASCRIPT, "testing", null, null, true ), - ); - } - - /** - * @dataProvider dataMakeContent - */ - public function testMakeContent( $data, $title, $modelId, $format, $expectedModelId, $expectedNativeData, $shouldFail ) { - global $wgExtraNamespaces, $wgNamespaceContentModels, $wgContentHandlers; - - $title = Title::newFromText( $title ); - - try { - $content = ContentHandler::makeContent( $data, $title, $modelId, $format ); - - if ( $shouldFail ) $this->fail( "ContentHandler::makeContent should have failed!" ); - - $this->assertEquals( $expectedModelId, $content->getModel(), 'bad model id' ); - $this->assertEquals( $expectedNativeData, $content->getNativeData(), 'bads native data' ); - } catch ( MWException $ex ) { - if ( !$shouldFail ) $this->fail( "ContentHandler::makeContent failed unexpectedly: " . $ex->getMessage() ); - else $this->assertTrue( true ); // dummy, so we don't get the "test did not perform any assertions" message. - } - - } - - public function testSupportsSections() { - $this->markTestIncomplete( "not yet implemented" ); - } - - public function testRunLegacyHooks() { - Hooks::register( 'testRunLegacyHooks', __CLASS__ . '::dummyHookHandler' ); - - $content = new WikitextContent( 'test text' ); - $ok = ContentHandler::runLegacyHooks( 'testRunLegacyHooks', array( 'foo', &$content, 'bar' ), false ); - - $this->assertTrue( $ok, "runLegacyHooks should have returned true" ); - $this->assertEquals( "TEST TEXT", $content->getNativeData() ); - } - - public static function dummyHookHandler( $foo, &$text, $bar ) { - if ( $text === null || $text === false ) { - return false; - } - - $text = strtoupper( $text ); - - return true; - } -} - -class DummyContentHandlerForTesting extends ContentHandler { - - public function __construct( $dataModel ) { - parent::__construct( $dataModel, array( "testing" ) ); - } - - /** - * Serializes Content object of the type supported by this ContentHandler. - * - * @param Content $content the Content object to serialize - * @param null $format the desired serialization format - * @return String serialized form of the content - */ - public function serializeContent( Content $content, $format = null ) - { - return $content->serialize(); - } - - /** - * Unserializes a Content object of the type supported by this ContentHandler. - * - * @param $blob String serialized form of the content - * @param null $format the format used for serialization - * @return Content the Content object created by deserializing $blob - */ - public function unserializeContent( $blob, $format = null ) - { - $d = unserialize( $blob ); - return new DummyContentForTesting( $d ); - } - - /** - * Creates an empty Content object of the type supported by this ContentHandler. - * - */ - public function makeEmptyContent() - { - return new DummyContentForTesting( '' ); - } -} - -class DummyContentForTesting extends AbstractContent { - - public function __construct( $data ) { - parent::__construct( "testing" ); - - $this->data = $data; - } - - public function serialize( $format = null ) { - return serialize( $this->data ); - } - - /** - * @return String a string representing the content in a way useful for building a full text search index. - * If no useful representation exists, this method returns an empty string. - */ - public function getTextForSearchIndex() { - return ''; - } - - /** - * @return String the wikitext to include when another page includes this content, or false if the content is not - * includable in a wikitext page. - */ - public function getWikitextForTransclusion() { - return false; - } - - /** - * Returns a textual representation of the content suitable for use in edit summaries and log messages. - * - * @param int $maxlength maximum length of the summary text - * @return String the summary text - */ - public function getTextForSummary( $maxlength = 250 ) { - return ''; - } - - /** - * Returns native represenation of the data. Interpretation depends on the data model used, - * as given by getDataModel(). - * - * @return mixed the native representation of the content. Could be a string, a nested array - * structure, an object, a binary blob... anything, really. - */ - public function getNativeData() - { - return $this->data; - } - - /** - * returns the content's nominal size in bogo-bytes. - * - * @return int - */ - public function getSize() { - return strlen( $this->data ); - } - - /** - * Return a copy of this Content object. The following must be true for the object returned - * if $copy = $original->copy() - * - * * get_class($original) === get_class($copy) - * * $original->getModel() === $copy->getModel() - * * $original->equals( $copy ) - * - * If and only if the Content object is imutable, the copy() method can and should - * return $this. That is, $copy === $original may be true, but only for imutable content - * objects. - * - * @return Content. A copy of this object - */ - public function copy() { - return $this; - } - - /** - * Returns true if this content is countable as a "real" wiki page, provided - * that it's also in a countable location (e.g. a current revision in the main namespace). - * - * @param $hasLinks Bool: if it is known whether this content contains links, provide this information here, - * to avoid redundant parsing to find out. - * @return boolean - */ - public function isCountable( $hasLinks = null ) { - return false; - } - - /** - * @param Title $title - * @param null $revId - * @param null|ParserOptions $options - * @param Boolean $generateHtml whether to generate Html (default: true). If false, - * the result of calling getText() on the ParserOutput object returned by - * this method is undefined. - * - * @return ParserOutput - */ - public function getParserOutput( Title $title, $revId = null, ParserOptions $options = NULL, $generateHtml = true ) { - return new ParserOutput( $this->getNativeData() ); - } -} diff --git a/tests/phpunit/includes/CssContentTest.php b/tests/phpunit/includes/CssContentTest.php deleted file mode 100644 index b6e8d293c5..0000000000 --- a/tests/phpunit/includes/CssContentTest.php +++ /dev/null @@ -1,60 +0,0 @@ -\n", - "
\nhello <world>\n\n
" ), - - array( - "MediaWiki:Test.css", - null, - "/* hello [[world]] */\n", - "
\n/* hello [[world]] */\n\n
", - array( 'Links' => array( // NOTE: assumes default settings for $wgTextModelsToParse - array( 'World' => 0 ) ) ) ), - - // @todo: more...? - ); - } - - - # ================================================================================================================= - - public function testGetModel() { - $content = $this->newContent( "hello world." ); - - $this->assertEquals( CONTENT_MODEL_CSS, $content->getModel() ); - } - - public function testGetContentHandler() { - $content = $this->newContent( "hello world." ); - - $this->assertEquals( CONTENT_MODEL_CSS, $content->getContentHandler()->getModelID() ); - } - - public function dataEquals( ) { - return array( - array( new CssContent( "hallo" ), null, false ), - array( new CssContent( "hallo" ), new CssContent( "hallo" ), true ), - array( new CssContent( "hallo" ), new WikitextContent( "hallo" ), false ), - array( new CssContent( "hallo" ), new CssContent( "HALLO" ), false ), - ); - } - -} diff --git a/tests/phpunit/includes/JavascriptContentTest.php b/tests/phpunit/includes/JavascriptContentTest.php deleted file mode 100644 index d3810afd6d..0000000000 --- a/tests/phpunit/includes/JavascriptContentTest.php +++ /dev/null @@ -1,272 +0,0 @@ -\n", - "
\nhello <world>\n\n
" ), - - array( - "MediaWiki:Test.js", - null, - "hello(); // [[world]]\n", - "
\nhello(); // [[world]]\n\n
", - array( 'Links' => array( // NOTE: assumes default settings for $wgTextModelsToParse - array( 'World' => 0 ) ) ) ), - - // @todo: more...? - ); - } - - public function dataGetSection() { - return array( - array( WikitextContentTest::$sections, - "0", - null - ), - array( WikitextContentTest::$sections, - "2", - null - ), - array( WikitextContentTest::$sections, - "8", - null - ), - ); - } - - public function dataReplaceSection() { - return array( - array( WikitextContentTest::$sections, - "0", - "No more", - null, - null - ), - array( WikitextContentTest::$sections, - "", - "No more", - null, - null - ), - array( WikitextContentTest::$sections, - "2", - "== TEST ==\nmore fun", - null, - null - ), - array( WikitextContentTest::$sections, - "8", - "No more", - null, - null - ), - array( WikitextContentTest::$sections, - "new", - "No more", - "New", - null - ), - ); - } - - public function testAddSectionHeader( ) { - $content = $this->newContent( 'hello world' ); - $c = $content->addSectionHeader( 'test' ); - - $this->assertTrue( $content->equals( $c ) ); - } - - // XXX: currently, preSaveTransform is applied to scripts. this may change or become optional. - public function dataPreSaveTransform() { - return array( - array( 'hello this is ~~~', - "hello this is [[Special:Contributions/127.0.0.1|127.0.0.1]]", - ), - array( 'hello \'\'this\'\' is ~~~', - 'hello \'\'this\'\' is ~~~', - ), - array( " Foo \n ", - " Foo", - ), - ); - } - - public function dataPreloadTransform() { - return array( - array( 'hello this is ~~~', - "hello this is ~~~", - ), - array( 'hello \'\'this\'\' is foobar', - 'hello \'\'this\'\' is foobar', - ), - ); - } - - public function dataGetRedirectTarget() { - return array( - array( '#REDIRECT [[Test]]', - null, - ), - array( '#REDIRECT Test', - null, - ), - array( '* #REDIRECT [[Test]]', - null, - ), - ); - } - - /** - * @todo: test needs database! - */ - /* - public function getRedirectChain() { - $text = $this->getNativeData(); - return Title::newFromRedirectArray( $text ); - } - */ - - /** - * @todo: test needs database! - */ - /* - public function getUltimateRedirectTarget() { - $text = $this->getNativeData(); - return Title::newFromRedirectRecurse( $text ); - } - */ - - - public function dataIsCountable() { - return array( - array( '', - null, - 'any', - true - ), - array( 'Foo', - null, - 'any', - true - ), - array( 'Foo', - null, - 'comma', - false - ), - array( 'Foo, bar', - null, - 'comma', - false - ), - array( 'Foo', - null, - 'link', - false - ), - array( 'Foo [[bar]]', - null, - 'link', - false - ), - array( 'Foo', - true, - 'link', - false - ), - array( 'Foo [[bar]]', - false, - 'link', - false - ), - array( '#REDIRECT [[bar]]', - true, - 'any', - true - ), - array( '#REDIRECT [[bar]]', - true, - 'comma', - false - ), - array( '#REDIRECT [[bar]]', - true, - 'link', - false - ), - ); - } - - public function dataGetTextForSummary() { - return array( - array( "hello\nworld.", - 16, - 'hello world.', - ), - array( 'hello world.', - 8, - 'hello...', - ), - array( '[[hello world]].', - 8, - '[[hel...', - ), - ); - } - - public function testMatchMagicWord( ) { - $mw = MagicWord::get( "staticredirect" ); - - $content = $this->newContent( "#REDIRECT [[FOO]]\n__STATICREDIRECT__" ); - $this->assertFalse( $content->matchMagicWord( $mw ), "should not have matched magic word, since it's not wikitext" ); - } - - public function testUpdateRedirect( ) { - $target = Title::newFromText( "testUpdateRedirect_target" ); - - $content = $this->newContent( "#REDIRECT [[Someplace]]" ); - $newContent = $content->updateRedirect( $target ); - - $this->assertTrue( $content->equals( $newContent ), "content should be unchanged since it's not wikitext" ); - } - - # ================================================================================================================= - - public function testGetModel() { - $content = $this->newContent( "hello world." ); - - $this->assertEquals( CONTENT_MODEL_JAVASCRIPT, $content->getModel() ); - } - - public function testGetContentHandler() { - $content = $this->newContent( "hello world." ); - - $this->assertEquals( CONTENT_MODEL_JAVASCRIPT, $content->getContentHandler()->getModelID() ); - } - - public function dataEquals( ) { - return array( - array( new JavascriptContent( "hallo" ), null, false ), - array( new JavascriptContent( "hallo" ), new JavascriptContent( "hallo" ), true ), - array( new JavascriptContent( "hallo" ), new CssContent( "hallo" ), false ), - array( new JavascriptContent( "hallo" ), new JavascriptContent( "HALLO" ), false ), - ); - } - -} diff --git a/tests/phpunit/includes/TextContentTest.php b/tests/phpunit/includes/TextContentTest.php deleted file mode 100644 index b80af298d6..0000000000 --- a/tests/phpunit/includes/TextContentTest.php +++ /dev/null @@ -1,373 +0,0 @@ -setName( '127.0.0.1' ); - - $this->context = new RequestContext( new FauxRequest() ); - $this->context->setTitle( Title::newFromText( "Test" ) ); - $this->context->setUser( $wgUser ); - } - - public function newContent( $text ) { - return new TextContent( $text ); - } - - - public function dataGetParserOutput() { - return array( - array( - "TextContentTest_testGetParserOutput", - CONTENT_MODEL_TEXT, - "hello ''world'' & [[stuff]]\n", "hello ''world'' & [[stuff]]", - array( 'Links' => array() ) ), - // @todo: more...? - ); - } - - /** - * @dataProvider dataGetParserOutput - */ - public function testGetParserOutput( $title, $model, $text, $expectedHtml, $expectedFields = null ) { - $title = Title::newFromText( $title ); - $content = ContentHandler::makeContent( $text, $title, $model ); - - $po = $content->getParserOutput( $title ); - - $html = $po->getText(); - $html = preg_replace( '##sm', '', $html ); // strip comments - - $this->assertEquals( $expectedHtml, trim( $html ) ); - - if ( $expectedFields ) { - foreach ( $expectedFields as $field => $exp ) { - $f = 'get' . ucfirst( $field ); - $v = call_user_func( array( $po, $f ) ); - - if ( is_array( $exp ) ) { - $this->assertArrayEquals( $exp, $v ); - } else { - $this->assertEquals( $exp, $v ); - } - } - } - - // @todo: assert more properties - } - - public function dataPreSaveTransform() { - return array( - array( #0: no signature resolution - "hello this is ~~~", - "hello this is ~~~", - ), - array( #1: rtrim - " Foo \n ", - " Foo", - ), - ); - } - - /** - * @dataProvider dataPreSaveTransform - */ - public function testPreSaveTransform( $text, $expected ) { - global $wgContLang; - - $options = ParserOptions::newFromUserAndLang( $this->context->getUser(), $wgContLang ); - - $content = $this->newContent( $text ); - $content = $content->preSaveTransform( $this->context->getTitle(), $this->context->getUser(), $options ); - - $this->assertEquals( $expected, $content->getNativeData() ); - } - - public function dataPreloadTransform() { - return array( - array( 'hello this is ~~~', - "hello this is ~~~", - ), - ); - } - - /** - * @dataProvider dataPreloadTransform - */ - public function testPreloadTransform( $text, $expected ) { - global $wgContLang; - $options = ParserOptions::newFromUserAndLang( $this->context->getUser(), $wgContLang ); - - $content = $this->newContent( $text ); - $content = $content->preloadTransform( $this->context->getTitle(), $options ); - - $this->assertEquals( $expected, $content->getNativeData() ); - } - - public function dataGetRedirectTarget() { - return array( - array( '#REDIRECT [[Test]]', - null, - ), - ); - } - - /** - * @dataProvider dataGetRedirectTarget - */ - public function testGetRedirectTarget( $text, $expected ) { - $content = $this->newContent( $text ); - $t = $content->getRedirectTarget( ); - - if ( is_null( $expected ) ) { - $this->assertNull( $t, "text should not have generated a redirect target: $text" ); - } else { - $this->assertEquals( $expected, $t->getPrefixedText() ); - } - } - - /** - * @dataProvider dataGetRedirectTarget - */ - public function isRedirect( $text, $expected ) { - $content = $this->newContent( $text ); - - $this->assertEquals( !is_null($expected), $content->isRedirect() ); - } - - - /** - * @todo: test needs database! Should be done by a test class in the Database group. - */ - /* - public function getRedirectChain() { - $text = $this->getNativeData(); - return Title::newFromRedirectArray( $text ); - } - */ - - /** - * @todo: test needs database! Should be done by a test class in the Database group. - */ - /* - public function getUltimateRedirectTarget() { - $text = $this->getNativeData(); - return Title::newFromRedirectRecurse( $text ); - } - */ - - - public function dataIsCountable() { - return array( - array( '', - null, - 'any', - true - ), - array( 'Foo', - null, - 'any', - true - ), - array( 'Foo', - null, - 'comma', - false - ), - array( 'Foo, bar', - null, - 'comma', - false - ), - ); - } - - - /** - * @dataProvider dataIsCountable - * @group Database - */ - public function testIsCountable( $text, $hasLinks, $mode, $expected ) { - global $wgArticleCountMethod; - - $old = $wgArticleCountMethod; - $wgArticleCountMethod = $mode; - - $content = $this->newContent( $text ); - - $v = $content->isCountable( $hasLinks, $this->context->getTitle() ); - $wgArticleCountMethod = $old; - - $this->assertEquals( $expected, $v, "isCountable() returned unexpected value " . var_export( $v, true ) - . " instead of " . var_export( $expected, true ) . " in mode `$mode` for text \"$text\"" ); - } - - public function dataGetTextForSummary() { - return array( - array( "hello\nworld.", - 16, - 'hello world.', - ), - array( 'hello world.', - 8, - 'hello...', - ), - array( '[[hello world]].', - 8, - '[[hel...', - ), - ); - } - - /** - * @dataProvider dataGetTextForSummary - */ - public function testGetTextForSummary( $text, $maxlength, $expected ) { - $content = $this->newContent( $text ); - - $this->assertEquals( $expected, $content->getTextForSummary( $maxlength ) ); - } - - - public function testGetTextForSearchIndex( ) { - $content = $this->newContent( "hello world." ); - - $this->assertEquals( "hello world.", $content->getTextForSearchIndex() ); - } - - public function testCopy() { - $content = $this->newContent( "hello world." ); - $copy = $content->copy(); - - $this->assertTrue( $content->equals( $copy ), "copy must be equal to original" ); - $this->assertEquals( "hello world.", $copy->getNativeData() ); - } - - public function testGetSize( ) { - $content = $this->newContent( "hello world." ); - - $this->assertEquals( 12, $content->getSize() ); - } - - public function testGetNativeData( ) { - $content = $this->newContent( "hello world." ); - - $this->assertEquals( "hello world.", $content->getNativeData() ); - } - - public function testGetWikitextForTransclusion( ) { - $content = $this->newContent( "hello world." ); - - $this->assertEquals( "hello world.", $content->getWikitextForTransclusion() ); - } - - # ================================================================================================================= - - public function testGetModel() { - $content = $this->newContent( "hello world." ); - - $this->assertEquals( CONTENT_MODEL_TEXT, $content->getModel() ); - } - - public function testGetContentHandler() { - $content = $this->newContent( "hello world." ); - - $this->assertEquals( CONTENT_MODEL_TEXT, $content->getContentHandler()->getModelID() ); - } - - public function dataIsEmpty( ) { - return array( - array( '', true ), - array( ' ', false ), - array( '0', false ), - array( 'hallo welt.', false ), - ); - } - - /** - * @dataProvider dataIsEmpty - */ - public function testIsEmpty( $text, $empty ) { - $content = $this->newContent( $text ); - - $this->assertEquals( $empty, $content->isEmpty() ); - } - - public function dataEquals( ) { - return array( - array( new TextContent( "hallo" ), null, false ), - array( new TextContent( "hallo" ), new TextContent( "hallo" ), true ), - array( new TextContent( "hallo" ), new JavascriptContent( "hallo" ), false ), - array( new TextContent( "hallo" ), new WikitextContent( "hallo" ), false ), - array( new TextContent( "hallo" ), new TextContent( "HALLO" ), false ), - ); - } - - /** - * @dataProvider dataEquals - */ - public function testEquals( Content $a, Content $b = null, $equal = false ) { - $this->assertEquals( $equal, $a->equals( $b ) ); - } - - public function dataGetDeletionUpdates() { - return array( - array("TextContentTest_testGetSecondaryDataUpdates_1", - CONTENT_MODEL_TEXT, "hello ''world''\n", - array( ) - ), - array("TextContentTest_testGetSecondaryDataUpdates_2", - CONTENT_MODEL_TEXT, "hello [[world test 21344]]\n", - array( ) - ), - // @todo: more...? - ); - } - - /** - * @dataProvider dataGetDeletionUpdates - */ - public function testDeletionUpdates( $title, $model, $text, $expectedStuff ) { - $title = Title::newFromText( $title ); - $title->resetArticleID( 2342 ); //dummy id. fine as long as we don't try to execute the updates! - - $content = ContentHandler::makeContent( $text, $title, $model ); - - $updates = $content->getDeletionUpdates( WikiPage::factory( $title ) ); - - // make updates accessible by class name - foreach ( $updates as $update ) { - $class = get_class( $update ); - $updates[ $class ] = $update; - } - - if ( !$expectedStuff ) { - $this->assertTrue( true ); // make phpunit happy - return; - } - - foreach ( $expectedStuff as $class => $fieldValues ) { - $this->assertArrayHasKey( $class, $updates, "missing an update of type $class" ); - - $update = $updates[ $class ]; - - foreach ( $fieldValues as $field => $value ) { - $v = $update->$field; #if the field doesn't exist, just crash and burn - $this->assertEquals( $value, $v, "unexpected value for field $field in instance of $class" ); - } - } - } - -} diff --git a/tests/phpunit/includes/WikitextContentHandlerTest.php b/tests/phpunit/includes/WikitextContentHandlerTest.php deleted file mode 100644 index 8db96d1b56..0000000000 --- a/tests/phpunit/includes/WikitextContentHandlerTest.php +++ /dev/null @@ -1,197 +0,0 @@ -handler = ContentHandler::getForModelID( CONTENT_MODEL_WIKITEXT ); - } - - public function testSerializeContent( ) { - $content = new WikitextContent( 'hello world' ); - - $this->assertEquals( 'hello world', $this->handler->serializeContent( $content ) ); - $this->assertEquals( 'hello world', $this->handler->serializeContent( $content, CONTENT_FORMAT_WIKITEXT ) ); - - try { - $this->handler->serializeContent( $content, 'dummy/foo' ); - $this->fail( "serializeContent() should have failed on unknown format" ); - } catch ( MWException $e ) { - // ok, as expected - } - } - - public function testUnserializeContent( ) { - $content = $this->handler->unserializeContent( 'hello world' ); - $this->assertEquals( 'hello world', $content->getNativeData() ); - - $content = $this->handler->unserializeContent( 'hello world', CONTENT_FORMAT_WIKITEXT ); - $this->assertEquals( 'hello world', $content->getNativeData() ); - - try { - $this->handler->unserializeContent( 'hello world', 'dummy/foo' ); - $this->fail( "unserializeContent() should have failed on unknown format" ); - } catch ( MWException $e ) { - // ok, as expected - } - } - - public function testMakeEmptyContent() { - $content = $this->handler->makeEmptyContent(); - - $this->assertTrue( $content->isEmpty() ); - $this->assertEquals( '', $content->getNativeData() ); - } - - public function dataIsSupportedFormat( ) { - return array( - array( null, true ), - array( CONTENT_FORMAT_WIKITEXT, true ), - array( 99887766, false ), - ); - } - - /** - * @dataProvider dataIsSupportedFormat - */ - public function testIsSupportedFormat( $format, $supported ) { - $this->assertEquals( $supported, $this->handler->isSupportedFormat( $format ) ); - } - - public function dataMerge3( ) { - return array( - array( "first paragraph - - second paragraph\n", - - "FIRST paragraph - - second paragraph\n", - - "first paragraph - - SECOND paragraph\n", - - "FIRST paragraph - - SECOND paragraph\n", - ), - - array( "first paragraph - second paragraph\n", - - "Bla bla\n", - - "Blubberdibla\n", - - false, - ), - - ); - } - - /** - * @dataProvider dataMerge3 - */ - public function testMerge3( $old, $mine, $yours, $expected ) { - global $wgDiff3; - - if ( !$wgDiff3 ) { - $this->markTestSkipped( "Can't test merge3(), since \$wgDiff3 is not configured" ); - } - - if ( !file_exists( $wgDiff3 ) ) { - #XXX: this sucks, since it uses arcane internal knowledge about TextContentHandler::merge3 and wfMerge. - $this->markTestSkipped( "Can't test merge3(), since \$wgDiff3 is misconfigured: can't find $wgDiff3" ); - } - - // test merge - $oldContent = new WikitextContent( $old ); - $myContent = new WikitextContent( $mine ); - $yourContent = new WikitextContent( $yours ); - - $merged = $this->handler->merge3( $oldContent, $myContent, $yourContent ); - - $this->assertEquals( $expected, $merged ? $merged->getNativeData() : $merged ); - } - - public function dataGetAutosummary( ) { - return array( - array( - 'Hello there, world!', - '#REDIRECT [[Foo]]', - 0, - '/^Redirected page .*Foo/' - ), - - array( - null, - 'Hello world!', - EDIT_NEW, - '/^Created page .*Hello/' - ), - - array( - 'Hello there, world!', - '', - 0, - '/^Blanked/' - ), - - array( - 'Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut - labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et - ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.', - 'Hello world!', - 0, - '/^Replaced .*Hello/' - ), - - array( - 'foo', - 'bar', - 0, - '/^$/' - ), - ); - } - - /** - * @dataProvider dataGetAutoSummary - */ - public function testGetAutosummary( $old, $new, $flags, $expected ) { - global $wgLanguageCode, $wgContLang; - - $oldContent = is_null( $old ) ? null : new WikitextContent( $old ); - $newContent = is_null( $new ) ? null : new WikitextContent( $new ); - - $summary = $this->handler->getAutosummary( $oldContent, $newContent, $flags ); - - $this->assertTrue( (bool)preg_match( $expected, $summary ), "Autosummary didn't match expected pattern $expected: $summary" ); - } - - /** - * @todo Text case requires database, should be done by a test class in the Database group - */ - /* - public function testGetAutoDeleteReason( Title $title, &$hasHistory ) { - } - */ - - /** - * @todo Text case requires database, should be done by a test class in the Database group - */ - /* - public function testGetUndoContent( Revision $current, Revision $undo, Revision $undoafter = null ) { - } - */ - -} diff --git a/tests/phpunit/includes/WikitextContentTest.php b/tests/phpunit/includes/WikitextContentTest.php deleted file mode 100644 index c1332a6052..0000000000 --- a/tests/phpunit/includes/WikitextContentTest.php +++ /dev/null @@ -1,374 +0,0 @@ -hello world\n

"), - // @todo: more...? - ); - } - - public function dataGetSecondaryDataUpdates() { - return array( - array( "WikitextContentTest_testGetSecondaryDataUpdates_1", - CONTENT_MODEL_WIKITEXT, "hello ''world''\n", - array( 'LinksUpdate' => array( 'mRecursive' => true, - 'mLinks' => array() ) ) - ), - array( "WikitextContentTest_testGetSecondaryDataUpdates_2", - CONTENT_MODEL_WIKITEXT, "hello [[world test 21344]]\n", - array( 'LinksUpdate' => array( 'mRecursive' => true, - 'mLinks' => array( array( 'World_test_21344' => 0 ) ) ) ) - ), - // @todo: more...? - ); - } - - /** - * @dataProvider dataGetSecondaryDataUpdates - * @group Database - */ - public function testGetSecondaryDataUpdates( $title, $model, $text, $expectedStuff ) { - $title = Title::newFromText( $title ); - $title->resetArticleID( 2342 ); //dummy id. fine as long as we don't try to execute the updates! - - $content = ContentHandler::makeContent( $text, $title, $model ); - - $updates = $content->getSecondaryDataUpdates( $title ); - - // make updates accessible by class name - foreach ( $updates as $update ) { - $class = get_class( $update ); - $updates[$class] = $update; - } - - foreach ( $expectedStuff as $class => $fieldValues ) { - $this->assertArrayHasKey( $class, $updates, "missing an update of type $class" ); - - $update = $updates[$class]; - - foreach ( $fieldValues as $field => $value ) { - $v = $update->$field; #if the field doesn't exist, just crash and burn - $this->assertEquals( $value, $v, "unexpected value for field $field in instance of $class" ); - } - } - } - - - static $sections = - -"Intro - -== stuff == -hello world - -== test == -just a test - -== foo == -more stuff -"; - - public function dataGetSection() { - return array( - array( WikitextContentTest::$sections, - "0", - "Intro" - ), - array( WikitextContentTest::$sections, - "2", -"== test == -just a test" - ), - array( WikitextContentTest::$sections, - "8", - false - ), - ); - } - - /** - * @dataProvider dataGetSection - */ - public function testGetSection( $text, $sectionId, $expectedText ) { - $content = $this->newContent( $text ); - - $sectionContent = $content->getSection( $sectionId ); - if ( is_object( $sectionContent ) ) { - $sectionText = $sectionContent->getNativeData(); - } else { - $sectionText = $sectionContent; - } - - $this->assertEquals( $expectedText, $sectionText ); - } - - public function dataReplaceSection() { - return array( - array( WikitextContentTest::$sections, - "0", - "No more", - null, - trim( preg_replace( '/^Intro/sm', 'No more', WikitextContentTest::$sections ) ) - ), - array( WikitextContentTest::$sections, - "", - "No more", - null, - "No more" - ), - array( WikitextContentTest::$sections, - "2", - "== TEST ==\nmore fun", - null, - trim( preg_replace( '/^== test ==.*== foo ==/sm', "== TEST ==\nmore fun\n\n== foo ==", WikitextContentTest::$sections ) ) - ), - array( WikitextContentTest::$sections, - "8", - "No more", - null, - WikitextContentTest::$sections - ), - array( WikitextContentTest::$sections, - "new", - "No more", - "New", - trim( WikitextContentTest::$sections ) . "\n\n\n== New ==\n\nNo more" - ), - ); - } - - /** - * @dataProvider dataReplaceSection - */ - public function testReplaceSection( $text, $section, $with, $sectionTitle, $expected ) { - $content = $this->newContent( $text ); - $c = $content->replaceSection( $section, $this->newContent( $with ), $sectionTitle ); - - $this->assertEquals( $expected, is_null( $c ) ? null : $c->getNativeData() ); - } - - public function testAddSectionHeader( ) { - $content = $this->newContent( 'hello world' ); - $content = $content->addSectionHeader( 'test' ); - - $this->assertEquals( "== test ==\n\nhello world", $content->getNativeData() ); - } - - public function dataPreSaveTransform() { - return array( - array( 'hello this is ~~~', - "hello this is [[Special:Contributions/127.0.0.1|127.0.0.1]]", - ), - array( 'hello \'\'this\'\' is ~~~', - 'hello \'\'this\'\' is ~~~', - ), - array( // rtrim - " Foo \n ", - " Foo", - ), - ); - } - - public function dataPreloadTransform() { - return array( - array( 'hello this is ~~~', - "hello this is ~~~", - ), - array( 'hello \'\'this\'\' is foobar', - 'hello \'\'this\'\' is bar', - ), - ); - } - - public function dataGetRedirectTarget() { - return array( - array( '#REDIRECT [[Test]]', - 'Test', - ), - array( '#REDIRECT Test', - null, - ), - array( '* #REDIRECT [[Test]]', - null, - ), - ); - } - - public function dataGetTextForSummary() { - return array( - array( "hello\nworld.", - 16, - 'hello world.', - ), - array( 'hello world.', - 8, - 'hello...', - ), - array( '[[hello world]].', - 8, - 'hel...', - ), - ); - } - - /** - * @todo: test needs database! Should be done by a test class in the Database group. - */ - /* - public function getRedirectChain() { - $text = $this->getNativeData(); - return Title::newFromRedirectArray( $text ); - } - */ - - /** - * @todo: test needs database! Should be done by a test class in the Database group. - */ - /* - public function getUltimateRedirectTarget() { - $text = $this->getNativeData(); - return Title::newFromRedirectRecurse( $text ); - } - */ - - - public function dataIsCountable() { - return array( - array( '', - null, - 'any', - true - ), - array( 'Foo', - null, - 'any', - true - ), - array( 'Foo', - null, - 'comma', - false - ), - array( 'Foo, bar', - null, - 'comma', - true - ), - array( 'Foo', - null, - 'link', - false - ), - array( 'Foo [[bar]]', - null, - 'link', - true - ), - array( 'Foo', - true, - 'link', - true - ), - array( 'Foo [[bar]]', - false, - 'link', - false - ), - array( '#REDIRECT [[bar]]', - true, - 'any', - false - ), - array( '#REDIRECT [[bar]]', - true, - 'comma', - false - ), - array( '#REDIRECT [[bar]]', - true, - 'link', - false - ), - ); - } - - public function testMatchMagicWord( ) { - $mw = MagicWord::get( "staticredirect" ); - - $content = $this->newContent( "#REDIRECT [[FOO]]\n__STATICREDIRECT__" ); - $this->assertTrue( $content->matchMagicWord( $mw ), "should have matched magic word" ); - - $content = $this->newContent( "#REDIRECT [[FOO]]" ); - $this->assertFalse( $content->matchMagicWord( $mw ), "should not have matched magic word" ); - } - - public function testUpdateRedirect( ) { - $target = Title::newFromText( "testUpdateRedirect_target" ); - - // test with non-redirect page - $content = $this->newContent( "hello world." ); - $newContent = $content->updateRedirect( $target ); - - $this->assertTrue( $content->equals( $newContent ), "content should be unchanged" ); - - // test with actual redirect - $content = $this->newContent( "#REDIRECT [[Someplace]]" ); - $newContent = $content->updateRedirect( $target ); - - $this->assertFalse( $content->equals( $newContent ), "content should have changed" ); - $this->assertTrue( $newContent->isRedirect(), "new content should be a redirect" ); - - $this->assertEquals( $target->getFullText(), $newContent->getRedirectTarget()->getFullText() ); - } - - # ================================================================================================================= - - public function testGetModel() { - $content = $this->newContent( "hello world." ); - - $this->assertEquals( CONTENT_MODEL_WIKITEXT, $content->getModel() ); - } - - public function testGetContentHandler() { - $content = $this->newContent( "hello world." ); - - $this->assertEquals( CONTENT_MODEL_WIKITEXT, $content->getContentHandler()->getModelID() ); - } - - public function dataEquals( ) { - return array( - array( new WikitextContent( "hallo" ), null, false ), - array( new WikitextContent( "hallo" ), new WikitextContent( "hallo" ), true ), - array( new WikitextContent( "hallo" ), new JavascriptContent( "hallo" ), false ), - array( new WikitextContent( "hallo" ), new TextContent( "hallo" ), false ), - array( new WikitextContent( "hallo" ), new WikitextContent( "HALLO" ), false ), - ); - } - - public function dataGetDeletionUpdates() { - return array( - array("WikitextContentTest_testGetSecondaryDataUpdates_1", - CONTENT_MODEL_WIKITEXT, "hello ''world''\n", - array( 'LinksDeletionUpdate' => array( ) ) - ), - array("WikitextContentTest_testGetSecondaryDataUpdates_2", - CONTENT_MODEL_WIKITEXT, "hello [[world test 21344]]\n", - array( 'LinksDeletionUpdate' => array( ) ) - ), - // @todo: more...? - ); - } - -} diff --git a/tests/phpunit/includes/content/ContentHandlerTest.php b/tests/phpunit/includes/content/ContentHandlerTest.php new file mode 100644 index 0000000000..60baedc614 --- /dev/null +++ b/tests/phpunit/includes/content/ContentHandlerTest.php @@ -0,0 +1,423 @@ +setMwGlobals( array( + 'wgExtraNamespaces' => array( + 12312 => 'Dummy', + 12313 => 'Dummy_talk', + ), + // The below tests assume that namespaces not mentioned here (Help, User, MediaWiki, ..) + // default to CONTENT_MODEL_WIKITEXT. + 'wgNamespaceContentModels' => array( + 12312 => 'testing', + ), + 'wgContentHandlers' => array( + CONTENT_MODEL_WIKITEXT => 'WikitextContentHandler', + CONTENT_MODEL_JAVASCRIPT => 'JavaScriptContentHandler', + CONTENT_MODEL_CSS => 'CssContentHandler', + CONTENT_MODEL_TEXT => 'TextContentHandler', + 'testing' => 'DummyContentHandlerForTesting', + ), + ) ); + + // Reset namespace cache + MWNamespace::getCanonicalNamespaces( true ); + $wgContLang->resetNamespaces(); + } + + public function tearDown() { + global $wgContLang; + + // Reset namespace cache + MWNamespace::getCanonicalNamespaces( true ); + $wgContLang->resetNamespaces(); + + parent::tearDown(); + } + + public static function dataGetDefaultModelFor() { + return array( + array( 'Help:Foo', CONTENT_MODEL_WIKITEXT ), + array( 'Help:Foo.js', CONTENT_MODEL_WIKITEXT ), + array( 'Help:Foo/bar.js', CONTENT_MODEL_WIKITEXT ), + array( 'User:Foo', CONTENT_MODEL_WIKITEXT ), + array( 'User:Foo.js', CONTENT_MODEL_WIKITEXT ), + array( 'User:Foo/bar.js', CONTENT_MODEL_JAVASCRIPT ), + array( 'User:Foo/bar.css', CONTENT_MODEL_CSS ), + array( 'User talk:Foo/bar.css', CONTENT_MODEL_WIKITEXT ), + array( 'User:Foo/bar.js.xxx', CONTENT_MODEL_WIKITEXT ), + array( 'User:Foo/bar.xxx', CONTENT_MODEL_WIKITEXT ), + array( 'MediaWiki:Foo.js', CONTENT_MODEL_JAVASCRIPT ), + array( 'MediaWiki:Foo.css', CONTENT_MODEL_CSS ), + array( 'MediaWiki:Foo.JS', CONTENT_MODEL_WIKITEXT ), + array( 'MediaWiki:Foo.CSS', CONTENT_MODEL_WIKITEXT ), + array( 'MediaWiki:Foo.css.xxx', CONTENT_MODEL_WIKITEXT ), + ); + } + + /** + * @dataProvider dataGetDefaultModelFor + */ + public function testGetDefaultModelFor( $title, $expectedModelId ) { + $title = Title::newFromText( $title ); + $this->assertEquals( $expectedModelId, ContentHandler::getDefaultModelFor( $title ) ); + } + + /** + * @dataProvider dataGetDefaultModelFor + */ + public function testGetForTitle( $title, $expectedContentModel ) { + $title = Title::newFromText( $title ); + $handler = ContentHandler::getForTitle( $title ); + $this->assertEquals( $expectedContentModel, $handler->getModelID() ); + } + + public static function dataGetLocalizedName() { + return array( + array( null, null ), + array( "xyzzy", null ), + + // XXX: depends on content language + array( CONTENT_MODEL_JAVASCRIPT, '/javascript/i' ), + ); + } + + /** + * @dataProvider dataGetLocalizedName + */ + public function testGetLocalizedName( $id, $expected ) { + $name = ContentHandler::getLocalizedName( $id ); + + if ( $expected ) { + $this->assertNotNull( $name, "no name found for content model $id" ); + $this->assertTrue( preg_match( $expected, $name ) > 0 , + "content model name for #$id did not match pattern $expected" + ); + } else { + $this->assertEquals( $id, $name, "localization of unknown model $id should have " + . "fallen back to use the model id directly." + ); + } + } + + public static function dataGetPageLanguage() { + global $wgLanguageCode; + + return array( + array( "Main", $wgLanguageCode ), + array( "Dummy:Foo", $wgLanguageCode ), + array( "MediaWiki:common.js", 'en' ), + array( "User:Foo/common.js", 'en' ), + array( "MediaWiki:common.css", 'en' ), + array( "User:Foo/common.css", 'en' ), + array( "User:Foo", $wgLanguageCode ), + + array( CONTENT_MODEL_JAVASCRIPT, 'javascript' ), + ); + } + + /** + * @dataProvider dataGetPageLanguage + */ + public function testGetPageLanguage( $title, $expected ) { + if ( is_string( $title ) ) { + $title = Title::newFromText( $title ); + } + + $expected = wfGetLangObj( $expected ); + + $handler = ContentHandler::getForTitle( $title ); + $lang = $handler->getPageLanguage( $title ); + + $this->assertEquals( $expected->getCode(), $lang->getCode() ); + } + + public function testGetContentText_Null( ) { + global $wgContentHandlerTextFallback; + + $content = null; + + $wgContentHandlerTextFallback = 'fail'; + $text = ContentHandler::getContentText( $content ); + $this->assertEquals( '', $text ); + + $wgContentHandlerTextFallback = 'serialize'; + $text = ContentHandler::getContentText( $content ); + $this->assertEquals( '', $text ); + + $wgContentHandlerTextFallback = 'ignore'; + $text = ContentHandler::getContentText( $content ); + $this->assertEquals( '', $text ); + } + + public function testGetContentText_TextContent( ) { + global $wgContentHandlerTextFallback; + + $content = new WikitextContent( "hello world" ); + + $wgContentHandlerTextFallback = 'fail'; + $text = ContentHandler::getContentText( $content ); + $this->assertEquals( $content->getNativeData(), $text ); + + $wgContentHandlerTextFallback = 'serialize'; + $text = ContentHandler::getContentText( $content ); + $this->assertEquals( $content->serialize(), $text ); + + $wgContentHandlerTextFallback = 'ignore'; + $text = ContentHandler::getContentText( $content ); + $this->assertEquals( $content->getNativeData(), $text ); + } + + public function testGetContentText_NonTextContent( ) { + global $wgContentHandlerTextFallback; + + $content = new DummyContentForTesting( "hello world" ); + + $wgContentHandlerTextFallback = 'fail'; + + try { + $text = ContentHandler::getContentText( $content ); + + $this->fail( "ContentHandler::getContentText should have thrown an exception for non-text Content object" ); + } catch ( MWException $ex ) { + // as expected + } + + $wgContentHandlerTextFallback = 'serialize'; + $text = ContentHandler::getContentText( $content ); + $this->assertEquals( $content->serialize(), $text ); + + $wgContentHandlerTextFallback = 'ignore'; + $text = ContentHandler::getContentText( $content ); + $this->assertNull( $text ); + } + + /* + public static function makeContent( $text, Title $title, $modelId = null, $format = null ) {} + */ + + public static function dataMakeContent() { + return array( + array( 'hallo', 'Help:Test', null, null, CONTENT_MODEL_WIKITEXT, 'hallo', false ), + array( 'hallo', 'MediaWiki:Test.js', null, null, CONTENT_MODEL_JAVASCRIPT, 'hallo', false ), + array( serialize('hallo'), 'Dummy:Test', null, null, "testing", 'hallo', false ), + + array( 'hallo', 'Help:Test', null, CONTENT_FORMAT_WIKITEXT, CONTENT_MODEL_WIKITEXT, 'hallo', false ), + array( 'hallo', 'MediaWiki:Test.js', null, CONTENT_FORMAT_JAVASCRIPT, CONTENT_MODEL_JAVASCRIPT, 'hallo', false ), + array( serialize('hallo'), 'Dummy:Test', null, "testing", "testing", 'hallo', false ), + + array( 'hallo', 'Help:Test', CONTENT_MODEL_CSS, null, CONTENT_MODEL_CSS, 'hallo', false ), + array( 'hallo', 'MediaWiki:Test.js', CONTENT_MODEL_CSS, null, CONTENT_MODEL_CSS, 'hallo', false ), + array( serialize('hallo'), 'Dummy:Test', CONTENT_MODEL_CSS, null, CONTENT_MODEL_CSS, serialize('hallo'), false ), + + array( 'hallo', 'Help:Test', CONTENT_MODEL_WIKITEXT, "testing", null, null, true ), + array( 'hallo', 'MediaWiki:Test.js', CONTENT_MODEL_CSS, "testing", null, null, true ), + array( 'hallo', 'Dummy:Test', CONTENT_MODEL_JAVASCRIPT, "testing", null, null, true ), + ); + } + + /** + * @dataProvider dataMakeContent + */ + public function testMakeContent( $data, $title, $modelId, $format, $expectedModelId, $expectedNativeData, $shouldFail ) { + global $wgExtraNamespaces, $wgNamespaceContentModels, $wgContentHandlers; + + $title = Title::newFromText( $title ); + + try { + $content = ContentHandler::makeContent( $data, $title, $modelId, $format ); + + if ( $shouldFail ) { + $this->fail( "ContentHandler::makeContent should have failed!" ); + } + + $this->assertEquals( $expectedModelId, $content->getModel(), 'bad model id' ); + $this->assertEquals( $expectedNativeData, $content->getNativeData(), 'bads native data' ); + } catch ( MWException $ex ) { + if ( !$shouldFail ) $this->fail( "ContentHandler::makeContent failed unexpectedly: " . $ex->getMessage() ); + else $this->assertTrue( true ); // dummy, so we don't get the "test did not perform any assertions" message. + } + + } + + /* + public function testSupportsSections() { + $this->markTestIncomplete( "not yet implemented" ); + } + */ + + public function testRunLegacyHooks() { + Hooks::register( 'testRunLegacyHooks', __CLASS__ . '::dummyHookHandler' ); + + $content = new WikitextContent( 'test text' ); + $ok = ContentHandler::runLegacyHooks( 'testRunLegacyHooks', array( 'foo', &$content, 'bar' ), false ); + + $this->assertTrue( $ok, "runLegacyHooks should have returned true" ); + $this->assertEquals( "TEST TEXT", $content->getNativeData() ); + } + + public static function dummyHookHandler( $foo, &$text, $bar ) { + if ( $text === null || $text === false ) { + return false; + } + + $text = strtoupper( $text ); + + return true; + } +} + +class DummyContentHandlerForTesting extends ContentHandler { + + public function __construct( $dataModel ) { + parent::__construct( $dataModel, array( "testing" ) ); + } + + /** + * Serializes Content object of the type supported by this ContentHandler. + * + * @param Content $content the Content object to serialize + * @param null $format the desired serialization format + * @return String serialized form of the content + */ + public function serializeContent( Content $content, $format = null ) { + return $content->serialize(); + } + + /** + * Unserializes a Content object of the type supported by this ContentHandler. + * + * @param $blob String serialized form of the content + * @param null $format the format used for serialization + * @return Content the Content object created by deserializing $blob + */ + public function unserializeContent( $blob, $format = null ) { + $d = unserialize( $blob ); + return new DummyContentForTesting( $d ); + } + + /** + * Creates an empty Content object of the type supported by this ContentHandler. + * + */ + public function makeEmptyContent() { + return new DummyContentForTesting( '' ); + } +} + +class DummyContentForTesting extends AbstractContent { + + public function __construct( $data ) { + parent::__construct( "testing" ); + + $this->data = $data; + } + + public function serialize( $format = null ) { + return serialize( $this->data ); + } + + /** + * @return String a string representing the content in a way useful for building a full text search index. + * If no useful representation exists, this method returns an empty string. + */ + public function getTextForSearchIndex() { + return ''; + } + + /** + * @return String the wikitext to include when another page includes this content, or false if the content is not + * includable in a wikitext page. + */ + public function getWikitextForTransclusion() { + return false; + } + + /** + * Returns a textual representation of the content suitable for use in edit summaries and log messages. + * + * @param int $maxlength Maximum length of the summary text. + * @return string The summary text. + */ + public function getTextForSummary( $maxlength = 250 ) { + return ''; + } + + /** + * Returns native represenation of the data. Interpretation depends on the data model used, + * as given by getDataModel(). + * + * @return mixed the native representation of the content. Could be a string, a nested array + * structure, an object, a binary blob... anything, really. + */ + public function getNativeData() + { + return $this->data; + } + + /** + * returns the content's nominal size in bogo-bytes. + * + * @return int + */ + public function getSize() { + return strlen( $this->data ); + } + + /** + * Return a copy of this Content object. The following must be true for the object returned + * if $copy = $original->copy() + * + * * get_class($original) === get_class($copy) + * * $original->getModel() === $copy->getModel() + * * $original->equals( $copy ) + * + * If and only if the Content object is imutable, the copy() method can and should + * return $this. That is, $copy === $original may be true, but only for imutable content + * objects. + * + * @return Content. A copy of this object. + */ + public function copy() { + return $this; + } + + /** + * Returns true if this content is countable as a "real" wiki page, provided + * that it's also in a countable location (e.g. a current revision in the main namespace). + * + * @param boolean $hasLinks if it is known whether this content contains links, provide this information here, + * to avoid redundant parsing to find out. + * @return boolean + */ + public function isCountable( $hasLinks = null ) { + return false; + } + + /** + * @param Title $title + * @param null $revId + * @param null|ParserOptions $options + * @param boolean $generateHtml whether to generate Html (default: true). If false, + * the result of calling getText() on the ParserOutput object returned by + * this method is undefined. + * + * @return ParserOutput + */ + public function getParserOutput( Title $title, $revId = null, ParserOptions $options = NULL, $generateHtml = true ) { + return new ParserOutput( $this->getNativeData() ); + } +} diff --git a/tests/phpunit/includes/content/CssContentTest.php b/tests/phpunit/includes/content/CssContentTest.php new file mode 100644 index 0000000000..b08a468b51 --- /dev/null +++ b/tests/phpunit/includes/content/CssContentTest.php @@ -0,0 +1,81 @@ +setName( '127.0.0.1' ); + + $this->setMwGlobals( array( + 'wgUser' => $user, + 'wgTextModelsToParse' => array( + CONTENT_MODEL_CSS, + ) + ) ); + } + + public function newContent( $text ) { + return new CssContent( $text ); + } + + public static function dataGetParserOutput() { + return array( + array( + 'MediaWiki:Test.css', + null, + "hello \n", + "
\nhello <world>\n\n
" + ), + array( + 'MediaWiki:Test.css', + null, + "/* hello [[world]] */\n", + "
\n/* hello [[world]] */\n\n
", + array( + 'Links' => array( + array( 'World' => 0 ) + ) + ) + ), + + // TODO: more...? + ); + } + + public function testGetModel() { + $content = $this->newContent( 'hello world.' ); + + $this->assertEquals( CONTENT_MODEL_CSS, $content->getModel() ); + } + + public function testGetContentHandler() { + $content = $this->newContent( 'hello world.' ); + + $this->assertEquals( CONTENT_MODEL_CSS, $content->getContentHandler()->getModelID() ); + } + + public static function dataEquals( ) { + return array( + array( new CssContent( 'hallo' ), null, false ), + array( new CssContent( 'hallo' ), new CssContent( 'hallo' ), true ), + array( new CssContent( 'hallo' ), new WikitextContent( 'hallo' ), false ), + array( new CssContent( 'hallo' ), new CssContent( 'HALLO' ), false ), + ); + } + + /** + * @dataProvider dataEquals + */ + public function testEquals( Content $a, Content $b = null, $equal = false ) { + $this->assertEquals( $equal, $a->equals( $b ) ); + } + +} diff --git a/tests/phpunit/includes/content/JavascriptContentTest.php b/tests/phpunit/includes/content/JavascriptContentTest.php new file mode 100644 index 0000000000..e08252c5bd --- /dev/null +++ b/tests/phpunit/includes/content/JavascriptContentTest.php @@ -0,0 +1,273 @@ +\n", + "
\nhello <world>\n\n
" + ), + array( + 'MediaWiki:Test.js', + null, + "hello(); // [[world]]\n", + "
\nhello(); // [[world]]\n\n
", + array( + 'Links' => array( + array( 'World' => 0 ) + ) + ) + ), + + // TODO: more...? + ); + } + + // XXX: Unused function + public static function dataGetSection() { + return array( + array( WikitextContentTest::$sections, + '0', + null + ), + array( WikitextContentTest::$sections, + '2', + null + ), + array( WikitextContentTest::$sections, + '8', + null + ), + ); + } + + // XXX: Unused function + public static function dataReplaceSection() { + return array( + array( WikitextContentTest::$sections, + '0', + 'No more', + null, + null + ), + array( WikitextContentTest::$sections, + '', + 'No more', + null, + null + ), + array( WikitextContentTest::$sections, + '2', + "== TEST ==\nmore fun", + null, + null + ), + array( WikitextContentTest::$sections, + '8', + 'No more', + null, + null + ), + array( WikitextContentTest::$sections, + 'new', + 'No more', + 'New', + null + ), + ); + } + + public function testAddSectionHeader( ) { + $content = $this->newContent( 'hello world' ); + $c = $content->addSectionHeader( 'test' ); + + $this->assertTrue( $content->equals( $c ) ); + } + + // XXX: currently, preSaveTransform is applied to scripts. this may change or become optional. + public static function dataPreSaveTransform() { + return array( + array( 'hello this is ~~~', + "hello this is [[Special:Contributions/127.0.0.1|127.0.0.1]]", + ), + array( 'hello \'\'this\'\' is ~~~', + 'hello \'\'this\'\' is ~~~', + ), + array( " Foo \n ", + " Foo", + ), + ); + } + + public static function dataPreloadTransform() { + return array( + array( 'hello this is ~~~', + 'hello this is ~~~', + ), + array( 'hello \'\'this\'\' is foobar', + 'hello \'\'this\'\' is foobar', + ), + ); + } + + public static function dataGetRedirectTarget() { + return array( + array( '#REDIRECT [[Test]]', + null, + ), + array( '#REDIRECT Test', + null, + ), + array( '* #REDIRECT [[Test]]', + null, + ), + ); + } + + /** + * @todo: test needs database! + */ + /* + public function getRedirectChain() { + $text = $this->getNativeData(); + return Title::newFromRedirectArray( $text ); + } + */ + + /** + * @todo: test needs database! + */ + /* + public function getUltimateRedirectTarget() { + $text = $this->getNativeData(); + return Title::newFromRedirectRecurse( $text ); + } + */ + + public static function dataIsCountable() { + return array( + array( '', + null, + 'any', + true + ), + array( 'Foo', + null, + 'any', + true + ), + array( 'Foo', + null, + 'comma', + false + ), + array( 'Foo, bar', + null, + 'comma', + false + ), + array( 'Foo', + null, + 'link', + false + ), + array( 'Foo [[bar]]', + null, + 'link', + false + ), + array( 'Foo', + true, + 'link', + false + ), + array( 'Foo [[bar]]', + false, + 'link', + false + ), + array( '#REDIRECT [[bar]]', + true, + 'any', + true + ), + array( '#REDIRECT [[bar]]', + true, + 'comma', + false + ), + array( '#REDIRECT [[bar]]', + true, + 'link', + false + ), + ); + } + + public static function dataGetTextForSummary() { + return array( + array( "hello\nworld.", + 16, + 'hello world.', + ), + array( 'hello world.', + 8, + 'hello...', + ), + array( '[[hello world]].', + 8, + '[[hel...', + ), + ); + } + + public function testMatchMagicWord( ) { + $mw = MagicWord::get( "staticredirect" ); + + $content = $this->newContent( "#REDIRECT [[FOO]]\n__STATICREDIRECT__" ); + $this->assertFalse( $content->matchMagicWord( $mw ), "should not have matched magic word, since it's not wikitext" ); + } + + public function testUpdateRedirect( ) { + $target = Title::newFromText( "testUpdateRedirect_target" ); + + $content = $this->newContent( "#REDIRECT [[Someplace]]" ); + $newContent = $content->updateRedirect( $target ); + + $this->assertTrue( $content->equals( $newContent ), "content should be unchanged since it's not wikitext" ); + } + + public function testGetModel() { + $content = $this->newContent( "hello world." ); + + $this->assertEquals( CONTENT_MODEL_JAVASCRIPT, $content->getModel() ); + } + + public function testGetContentHandler() { + $content = $this->newContent( "hello world." ); + + $this->assertEquals( CONTENT_MODEL_JAVASCRIPT, $content->getContentHandler()->getModelID() ); + } + + public static function dataEquals( ) { + return array( + array( new JavascriptContent( "hallo" ), null, false ), + array( new JavascriptContent( "hallo" ), new JavascriptContent( "hallo" ), true ), + array( new JavascriptContent( "hallo" ), new CssContent( "hallo" ), false ), + array( new JavascriptContent( "hallo" ), new JavascriptContent( "HALLO" ), false ), + ); + } + +} diff --git a/tests/phpunit/includes/content/TextContentTest.php b/tests/phpunit/includes/content/TextContentTest.php new file mode 100644 index 0000000000..c867a83e2e --- /dev/null +++ b/tests/phpunit/includes/content/TextContentTest.php @@ -0,0 +1,381 @@ +setName( '127.0.0.1' ); + + $this->setMwGlobals( array( + 'wgUser' => $user, + 'wgTextModelsToParse' => array( + CONTENT_MODEL_WIKITEXT, + CONTENT_MODEL_CSS, + CONTENT_MODEL_JAVASCRIPT, + ) + ) ); + + $this->context = new RequestContext( new FauxRequest() ); + $this->context->setTitle( Title::newFromText( 'Test' ) ); + $this->context->setUser( $user ); + } + + public function newContent( $text ) { + return new TextContent( $text ); + } + + public static function dataGetParserOutput() { + return array( + array( + 'TextContentTest_testGetParserOutput', + CONTENT_MODEL_TEXT, + "hello ''world'' & [[stuff]]\n", "hello ''world'' & [[stuff]]", + array( + 'Links' => array() + ) + ), + // TODO: more...? + ); + } + + /** + * @dataProvider dataGetParserOutput + */ + public function testGetParserOutput( $title, $model, $text, $expectedHtml, $expectedFields = null ) { + $title = Title::newFromText( $title ); + $content = ContentHandler::makeContent( $text, $title, $model ); + + $po = $content->getParserOutput( $title ); + + $html = $po->getText(); + $html = preg_replace( '##sm', '', $html ); // strip comments + + $this->assertEquals( $expectedHtml, trim( $html ) ); + + if ( $expectedFields ) { + foreach ( $expectedFields as $field => $exp ) { + $f = 'get' . ucfirst( $field ); + $v = call_user_func( array( $po, $f ) ); + + if ( is_array( $exp ) ) { + $this->assertArrayEquals( $exp, $v ); + } else { + $this->assertEquals( $exp, $v ); + } + } + } + + // TODO: assert more properties + } + + public static function dataPreSaveTransform() { + return array( + array( + #0: no signature resolution + 'hello this is ~~~', + 'hello this is ~~~', + ), + array( + #1: rtrim + " Foo \n ", + ' Foo', + ), + ); + } + + /** + * @dataProvider dataPreSaveTransform + */ + public function testPreSaveTransform( $text, $expected ) { + global $wgContLang; + + $options = ParserOptions::newFromUserAndLang( $this->context->getUser(), $wgContLang ); + + $content = $this->newContent( $text ); + $content = $content->preSaveTransform( $this->context->getTitle(), $this->context->getUser(), $options ); + + $this->assertEquals( $expected, $content->getNativeData() ); + } + + public static function dataPreloadTransform() { + return array( + array( + 'hello this is ~~~', + 'hello this is ~~~', + ), + ); + } + + /** + * @dataProvider dataPreloadTransform + */ + public function testPreloadTransform( $text, $expected ) { + global $wgContLang; + $options = ParserOptions::newFromUserAndLang( $this->context->getUser(), $wgContLang ); + + $content = $this->newContent( $text ); + $content = $content->preloadTransform( $this->context->getTitle(), $options ); + + $this->assertEquals( $expected, $content->getNativeData() ); + } + + public static function dataGetRedirectTarget() { + return array( + array( '#REDIRECT [[Test]]', + null, + ), + ); + } + + /** + * @dataProvider dataGetRedirectTarget + */ + public function testGetRedirectTarget( $text, $expected ) { + $content = $this->newContent( $text ); + $t = $content->getRedirectTarget( ); + + if ( is_null( $expected ) ) { + $this->assertNull( $t, "text should not have generated a redirect target: $text" ); + } else { + $this->assertEquals( $expected, $t->getPrefixedText() ); + } + } + + /** + * @dataProvider dataGetRedirectTarget + */ + public function testIsRedirect( $text, $expected ) { + $content = $this->newContent( $text ); + + $this->assertEquals( !is_null($expected), $content->isRedirect() ); + } + + /** + * @todo: test needs database! Should be done by a test class in the Database group. + */ + /* + public function getRedirectChain() { + $text = $this->getNativeData(); + return Title::newFromRedirectArray( $text ); + } + */ + + /** + * @todo: test needs database! Should be done by a test class in the Database group. + */ + /* + public function getUltimateRedirectTarget() { + $text = $this->getNativeData(); + return Title::newFromRedirectRecurse( $text ); + } + */ + + public static function dataIsCountable() { + return array( + array( '', + null, + 'any', + true + ), + array( 'Foo', + null, + 'any', + true + ), + array( 'Foo', + null, + 'comma', + false + ), + array( 'Foo, bar', + null, + 'comma', + false + ), + ); + } + + + /** + * @dataProvider dataIsCountable + * @group Database + */ + public function testIsCountable( $text, $hasLinks, $mode, $expected ) { + global $wgArticleCountMethod; + + $old = $wgArticleCountMethod; + $wgArticleCountMethod = $mode; + + $content = $this->newContent( $text ); + + $v = $content->isCountable( $hasLinks, $this->context->getTitle() ); + $wgArticleCountMethod = $old; + + $this->assertEquals( $expected, $v, 'isCountable() returned unexpected value ' . var_export( $v, true ) + . ' instead of ' . var_export( $expected, true ) . " in mode `$mode` for text \"$text\"" ); + } + + public static function dataGetTextForSummary() { + return array( + array( "hello\nworld.", + 16, + 'hello world.', + ), + array( 'hello world.', + 8, + 'hello...', + ), + array( '[[hello world]].', + 8, + '[[hel...', + ), + ); + } + + /** + * @dataProvider dataGetTextForSummary + */ + public function testGetTextForSummary( $text, $maxlength, $expected ) { + $content = $this->newContent( $text ); + + $this->assertEquals( $expected, $content->getTextForSummary( $maxlength ) ); + } + + + public function testGetTextForSearchIndex( ) { + $content = $this->newContent( 'hello world.' ); + + $this->assertEquals( 'hello world.', $content->getTextForSearchIndex() ); + } + + public function testCopy() { + $content = $this->newContent( 'hello world.' ); + $copy = $content->copy(); + + $this->assertTrue( $content->equals( $copy ), 'copy must be equal to original' ); + $this->assertEquals( 'hello world.', $copy->getNativeData() ); + } + + public function testGetSize( ) { + $content = $this->newContent( 'hello world.' ); + + $this->assertEquals( 12, $content->getSize() ); + } + + public function testGetNativeData( ) { + $content = $this->newContent( 'hello world.' ); + + $this->assertEquals( 'hello world.', $content->getNativeData() ); + } + + public function testGetWikitextForTransclusion( ) { + $content = $this->newContent( 'hello world.' ); + + $this->assertEquals( 'hello world.', $content->getWikitextForTransclusion() ); + } + + public function testGetModel() { + $content = $this->newContent( "hello world." ); + + $this->assertEquals( CONTENT_MODEL_TEXT, $content->getModel() ); + } + + public function testGetContentHandler() { + $content = $this->newContent( "hello world." ); + + $this->assertEquals( CONTENT_MODEL_TEXT, $content->getContentHandler()->getModelID() ); + } + + public static function dataIsEmpty( ) { + return array( + array( '', true ), + array( ' ', false ), + array( '0', false ), + array( 'hallo welt.', false ), + ); + } + + /** + * @dataProvider dataIsEmpty + */ + public function testIsEmpty( $text, $empty ) { + $content = $this->newContent( $text ); + + $this->assertEquals( $empty, $content->isEmpty() ); + } + + public static function dataEquals( ) { + return array( + array( new TextContent( "hallo" ), null, false ), + array( new TextContent( "hallo" ), new TextContent( "hallo" ), true ), + array( new TextContent( "hallo" ), new JavascriptContent( "hallo" ), false ), + array( new TextContent( "hallo" ), new WikitextContent( "hallo" ), false ), + array( new TextContent( "hallo" ), new TextContent( "HALLO" ), false ), + ); + } + + /** + * @dataProvider dataEquals + */ + public function testEquals( Content $a, Content $b = null, $equal = false ) { + $this->assertEquals( $equal, $a->equals( $b ) ); + } + + public static function dataGetDeletionUpdates() { + return array( + array("TextContentTest_testGetSecondaryDataUpdates_1", + CONTENT_MODEL_TEXT, "hello ''world''\n", + array( ) + ), + array("TextContentTest_testGetSecondaryDataUpdates_2", + CONTENT_MODEL_TEXT, "hello [[world test 21344]]\n", + array( ) + ), + // TODO: more...? + ); + } + + /** + * @dataProvider dataGetDeletionUpdates + */ + public function testDeletionUpdates( $title, $model, $text, $expectedStuff ) { + $title = Title::newFromText( $title ); + $title->resetArticleID( 2342 ); //dummy id. fine as long as we don't try to execute the updates! + + $content = ContentHandler::makeContent( $text, $title, $model ); + + $updates = $content->getDeletionUpdates( WikiPage::factory( $title ) ); + + // make updates accessible by class name + foreach ( $updates as $update ) { + $class = get_class( $update ); + $updates[ $class ] = $update; + } + + if ( !$expectedStuff ) { + $this->assertTrue( true ); // make phpunit happy + return; + } + + foreach ( $expectedStuff as $class => $fieldValues ) { + $this->assertArrayHasKey( $class, $updates, "missing an update of type $class" ); + + $update = $updates[ $class ]; + + foreach ( $fieldValues as $field => $value ) { + $v = $update->$field; #if the field doesn't exist, just crash and burn + $this->assertEquals( $value, $v, "unexpected value for field $field in instance of $class" ); + } + } + } + +} diff --git a/tests/phpunit/includes/content/WikitextContentHandlerTest.php b/tests/phpunit/includes/content/WikitextContentHandlerTest.php new file mode 100644 index 0000000000..1ba85a91f2 --- /dev/null +++ b/tests/phpunit/includes/content/WikitextContentHandlerTest.php @@ -0,0 +1,196 @@ +handler = ContentHandler::getForModelID( CONTENT_MODEL_WIKITEXT ); + } + + public function testSerializeContent( ) { + $content = new WikitextContent( 'hello world' ); + + $this->assertEquals( 'hello world', $this->handler->serializeContent( $content ) ); + $this->assertEquals( 'hello world', $this->handler->serializeContent( $content, CONTENT_FORMAT_WIKITEXT ) ); + + try { + $this->handler->serializeContent( $content, 'dummy/foo' ); + $this->fail( "serializeContent() should have failed on unknown format" ); + } catch ( MWException $e ) { + // ok, as expected + } + } + + public function testUnserializeContent( ) { + $content = $this->handler->unserializeContent( 'hello world' ); + $this->assertEquals( 'hello world', $content->getNativeData() ); + + $content = $this->handler->unserializeContent( 'hello world', CONTENT_FORMAT_WIKITEXT ); + $this->assertEquals( 'hello world', $content->getNativeData() ); + + try { + $this->handler->unserializeContent( 'hello world', 'dummy/foo' ); + $this->fail( "unserializeContent() should have failed on unknown format" ); + } catch ( MWException $e ) { + // ok, as expected + } + } + + public function testMakeEmptyContent() { + $content = $this->handler->makeEmptyContent(); + + $this->assertTrue( $content->isEmpty() ); + $this->assertEquals( '', $content->getNativeData() ); + } + + public static function dataIsSupportedFormat( ) { + return array( + array( null, true ), + array( CONTENT_FORMAT_WIKITEXT, true ), + array( 99887766, false ), + ); + } + + /** + * @dataProvider dataIsSupportedFormat + */ + public function testIsSupportedFormat( $format, $supported ) { + $this->assertEquals( $supported, $this->handler->isSupportedFormat( $format ) ); + } + + public static function dataMerge3( ) { + return array( + array( "first paragraph + + second paragraph\n", + + "FIRST paragraph + + second paragraph\n", + + "first paragraph + + SECOND paragraph\n", + + "FIRST paragraph + + SECOND paragraph\n", + ), + + array( "first paragraph + second paragraph\n", + + "Bla bla\n", + + "Blubberdibla\n", + + false, + ), + + ); + } + + /** + * @dataProvider dataMerge3 + */ + public function testMerge3( $old, $mine, $yours, $expected ) { + global $wgDiff3; + + if ( !$wgDiff3 ) { + $this->markTestSkipped( "Can't test merge3(), since \$wgDiff3 is not configured" ); + } + + if ( !file_exists( $wgDiff3 ) ) { + #XXX: this sucks, since it uses arcane internal knowledge about TextContentHandler::merge3 and wfMerge. + $this->markTestSkipped( "Can't test merge3(), since \$wgDiff3 is misconfigured: can't find $wgDiff3" ); + } + + // test merge + $oldContent = new WikitextContent( $old ); + $myContent = new WikitextContent( $mine ); + $yourContent = new WikitextContent( $yours ); + + $merged = $this->handler->merge3( $oldContent, $myContent, $yourContent ); + + $this->assertEquals( $expected, $merged ? $merged->getNativeData() : $merged ); + } + + public static function dataGetAutosummary( ) { + return array( + array( + 'Hello there, world!', + '#REDIRECT [[Foo]]', + 0, + '/^Redirected page .*Foo/' + ), + + array( + null, + 'Hello world!', + EDIT_NEW, + '/^Created page .*Hello/' + ), + + array( + 'Hello there, world!', + '', + 0, + '/^Blanked/' + ), + + array( + 'Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut + labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et + ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.', + 'Hello world!', + 0, + '/^Replaced .*Hello/' + ), + + array( + 'foo', + 'bar', + 0, + '/^$/' + ), + ); + } + + /** + * @dataProvider dataGetAutosummary + */ + public function testGetAutosummary( $old, $new, $flags, $expected ) { + global $wgLanguageCode, $wgContLang; + + $oldContent = is_null( $old ) ? null : new WikitextContent( $old ); + $newContent = is_null( $new ) ? null : new WikitextContent( $new ); + + $summary = $this->handler->getAutosummary( $oldContent, $newContent, $flags ); + + $this->assertTrue( (bool)preg_match( $expected, $summary ), "Autosummary didn't match expected pattern $expected: $summary" ); + } + + /** + * @todo Text case requires database, should be done by a test class in the Database group + */ + /* + public function testGetAutoDeleteReason( Title $title, &$hasHistory ) {} + */ + + /** + * @todo Text case requires database, should be done by a test class in the Database group + */ + /* + public function testGetUndoContent( Revision $current, Revision $undo, Revision $undoafter = null ) {} + */ + +} diff --git a/tests/phpunit/includes/content/WikitextContentTest.php b/tests/phpunit/includes/content/WikitextContentTest.php new file mode 100644 index 0000000000..ceb6d485f9 --- /dev/null +++ b/tests/phpunit/includes/content/WikitextContentTest.php @@ -0,0 +1,385 @@ +hello world\n

" + ), + // TODO: more...? + ); + } + + public static function dataGetSecondaryDataUpdates() { + return array( + array( "WikitextContentTest_testGetSecondaryDataUpdates_1", + CONTENT_MODEL_WIKITEXT, "hello ''world''\n", + array( + 'LinksUpdate' => array( + 'mRecursive' => true, + 'mLinks' => array() + ) + ) + ), + array( "WikitextContentTest_testGetSecondaryDataUpdates_2", + CONTENT_MODEL_WIKITEXT, "hello [[world test 21344]]\n", + array( + 'LinksUpdate' => array( + 'mRecursive' => true, + 'mLinks' => array( + array( 'World_test_21344' => 0 ) + ) + ) + ) + ), + // TODO: more...? + ); + } + + /** + * @dataProvider dataGetSecondaryDataUpdates + * @group Database + */ + public function testGetSecondaryDataUpdates( $title, $model, $text, $expectedStuff ) { + $title = Title::newFromText( $title ); + $title->resetArticleID( 2342 ); //dummy id. fine as long as we don't try to execute the updates! + + $content = ContentHandler::makeContent( $text, $title, $model ); + + $updates = $content->getSecondaryDataUpdates( $title ); + + // make updates accessible by class name + foreach ( $updates as $update ) { + $class = get_class( $update ); + $updates[$class] = $update; + } + + foreach ( $expectedStuff as $class => $fieldValues ) { + $this->assertArrayHasKey( $class, $updates, "missing an update of type $class" ); + + $update = $updates[$class]; + + foreach ( $fieldValues as $field => $value ) { + $v = $update->$field; #if the field doesn't exist, just crash and burn + $this->assertEquals( $value, $v, "unexpected value for field $field in instance of $class" ); + } + } + } + + public static function dataGetSection() { + return array( + array( WikitextContentTest::$sections, + "0", + "Intro" + ), + array( WikitextContentTest::$sections, + "2", +"== test == +just a test" + ), + array( WikitextContentTest::$sections, + "8", + false + ), + ); + } + + /** + * @dataProvider dataGetSection + */ + public function testGetSection( $text, $sectionId, $expectedText ) { + $content = $this->newContent( $text ); + + $sectionContent = $content->getSection( $sectionId ); + if ( is_object( $sectionContent ) ) { + $sectionText = $sectionContent->getNativeData(); + } else { + $sectionText = $sectionContent; + } + + $this->assertEquals( $expectedText, $sectionText ); + } + + public static function dataReplaceSection() { + return array( + array( WikitextContentTest::$sections, + "0", + "No more", + null, + trim( preg_replace( '/^Intro/sm', 'No more', WikitextContentTest::$sections ) ) + ), + array( WikitextContentTest::$sections, + "", + "No more", + null, + "No more" + ), + array( WikitextContentTest::$sections, + "2", + "== TEST ==\nmore fun", + null, + trim( preg_replace( '/^== test ==.*== foo ==/sm', "== TEST ==\nmore fun\n\n== foo ==", WikitextContentTest::$sections ) ) + ), + array( WikitextContentTest::$sections, + "8", + "No more", + null, + WikitextContentTest::$sections + ), + array( WikitextContentTest::$sections, + "new", + "No more", + "New", + trim( WikitextContentTest::$sections ) . "\n\n\n== New ==\n\nNo more" + ), + ); + } + + /** + * @dataProvider dataReplaceSection + */ + public function testReplaceSection( $text, $section, $with, $sectionTitle, $expected ) { + $content = $this->newContent( $text ); + $c = $content->replaceSection( $section, $this->newContent( $with ), $sectionTitle ); + + $this->assertEquals( $expected, is_null( $c ) ? null : $c->getNativeData() ); + } + + public function testAddSectionHeader( ) { + $content = $this->newContent( 'hello world' ); + $content = $content->addSectionHeader( 'test' ); + + $this->assertEquals( "== test ==\n\nhello world", $content->getNativeData() ); + } + + public static function dataPreSaveTransform() { + return array( + array( 'hello this is ~~~', + "hello this is [[Special:Contributions/127.0.0.1|127.0.0.1]]", + ), + array( 'hello \'\'this\'\' is ~~~', + 'hello \'\'this\'\' is ~~~', + ), + array( // rtrim + " Foo \n ", + " Foo", + ), + ); + } + + public static function dataPreloadTransform() { + return array( + array( 'hello this is ~~~', + "hello this is ~~~", + ), + array( 'hello \'\'this\'\' is foobar', + 'hello \'\'this\'\' is bar', + ), + ); + } + + public static function dataGetRedirectTarget() { + return array( + array( '#REDIRECT [[Test]]', + 'Test', + ), + array( '#REDIRECT Test', + null, + ), + array( '* #REDIRECT [[Test]]', + null, + ), + ); + } + + public static function dataGetTextForSummary() { + return array( + array( "hello\nworld.", + 16, + 'hello world.', + ), + array( 'hello world.', + 8, + 'hello...', + ), + array( '[[hello world]].', + 8, + 'hel...', + ), + ); + } + + /** + * @todo: test needs database! Should be done by a test class in the Database group. + */ + /* + public function getRedirectChain() { + $text = $this->getNativeData(); + return Title::newFromRedirectArray( $text ); + } + */ + + /** + * @todo: test needs database! Should be done by a test class in the Database group. + */ + /* + public function getUltimateRedirectTarget() { + $text = $this->getNativeData(); + return Title::newFromRedirectRecurse( $text ); + } + */ + + public static function dataIsCountable() { + return array( + array( '', + null, + 'any', + true + ), + array( 'Foo', + null, + 'any', + true + ), + array( 'Foo', + null, + 'comma', + false + ), + array( 'Foo, bar', + null, + 'comma', + true + ), + array( 'Foo', + null, + 'link', + false + ), + array( 'Foo [[bar]]', + null, + 'link', + true + ), + array( 'Foo', + true, + 'link', + true + ), + array( 'Foo [[bar]]', + false, + 'link', + false + ), + array( '#REDIRECT [[bar]]', + true, + 'any', + false + ), + array( '#REDIRECT [[bar]]', + true, + 'comma', + false + ), + array( '#REDIRECT [[bar]]', + true, + 'link', + false + ), + ); + } + + public function testMatchMagicWord( ) { + $mw = MagicWord::get( "staticredirect" ); + + $content = $this->newContent( "#REDIRECT [[FOO]]\n__STATICREDIRECT__" ); + $this->assertTrue( $content->matchMagicWord( $mw ), "should have matched magic word" ); + + $content = $this->newContent( "#REDIRECT [[FOO]]" ); + $this->assertFalse( $content->matchMagicWord( $mw ), "should not have matched magic word" ); + } + + public function testUpdateRedirect( ) { + $target = Title::newFromText( "testUpdateRedirect_target" ); + + // test with non-redirect page + $content = $this->newContent( "hello world." ); + $newContent = $content->updateRedirect( $target ); + + $this->assertTrue( $content->equals( $newContent ), "content should be unchanged" ); + + // test with actual redirect + $content = $this->newContent( "#REDIRECT [[Someplace]]" ); + $newContent = $content->updateRedirect( $target ); + + $this->assertFalse( $content->equals( $newContent ), "content should have changed" ); + $this->assertTrue( $newContent->isRedirect(), "new content should be a redirect" ); + + $this->assertEquals( $target->getFullText(), $newContent->getRedirectTarget()->getFullText() ); + } + + public function testGetModel() { + $content = $this->newContent( "hello world." ); + + $this->assertEquals( CONTENT_MODEL_WIKITEXT, $content->getModel() ); + } + + public function testGetContentHandler() { + $content = $this->newContent( "hello world." ); + + $this->assertEquals( CONTENT_MODEL_WIKITEXT, $content->getContentHandler()->getModelID() ); + } + + public static function dataEquals( ) { + return array( + array( new WikitextContent( "hallo" ), null, false ), + array( new WikitextContent( "hallo" ), new WikitextContent( "hallo" ), true ), + array( new WikitextContent( "hallo" ), new JavascriptContent( "hallo" ), false ), + array( new WikitextContent( "hallo" ), new TextContent( "hallo" ), false ), + array( new WikitextContent( "hallo" ), new WikitextContent( "HALLO" ), false ), + ); + } + + public static function dataGetDeletionUpdates() { + return array( + array("WikitextContentTest_testGetSecondaryDataUpdates_1", + CONTENT_MODEL_WIKITEXT, "hello ''world''\n", + array( 'LinksDeletionUpdate' => array( ) ) + ), + array("WikitextContentTest_testGetSecondaryDataUpdates_2", + CONTENT_MODEL_WIKITEXT, "hello [[world test 21344]]\n", + array( 'LinksDeletionUpdate' => array( ) ) + ), + // @todo: more...? + ); + } + +}