From a1789ddde42033f1b05cc4929491214ee6e79383 Mon Sep 17 00:00:00 2001 From: Pierre Schmitz Date: Thu, 17 Dec 2015 09:15:42 +0100 Subject: Update to MediaWiki 1.26.0 --- tests/TestsAutoLoader.php | 13 +- tests/browser/environments.yml | 4 +- tests/browser/features/create_account.feature | 5 + .../step_definitions/create_account_steps.rb | 8 + .../features/support/pages/create_account_page.rb | 1 + tests/browser/features/support/pages/main_page.rb | 6 +- .../support/pages/preferences_appearance_page.rb | 2 +- .../features/support/pages/view_history_page.rb | 4 +- tests/parser/parserTest.inc | 9 +- tests/parser/parserTests.txt | 4327 +++++++++++++++----- .../parser/preprocess/All_system_messages.expected | 6 +- tests/parser/preprocess/All_system_messages.txt | 6 +- tests/parserTests.php | 2 +- tests/phpunit/LessFileCompilationTest.php | 6 +- tests/phpunit/Makefile | 1 - tests/phpunit/MediaWikiTestCase.php | 30 +- tests/phpunit/README | 17 +- tests/phpunit/ResourceLoaderTestCase.php | 44 +- tests/phpunit/data/css/comments.css | 7 + tests/phpunit/data/helpers/WellProtectedClass.php | 29 +- .../data/import/ImportLinkCacheIntegrationTest.xml | 43 + .../data/less/common/test.common.mixins.less | 1 - tests/phpunit/data/less/module/styles.css | 3 +- tests/phpunit/data/media/2_webp_a.webp | Bin 0 -> 17128 bytes tests/phpunit/data/media/2_webp_ll.webp | Bin 0 -> 29360 bytes tests/phpunit/data/media/srgb.jpg | Bin 0 -> 7738 bytes tests/phpunit/data/media/tinyrgb.icc | Bin 0 -> 524 bytes tests/phpunit/data/media/tinyrgb.jpg | Bin 0 -> 5118 bytes tests/phpunit/data/media/webp_animated.webp | Bin 0 -> 380850 bytes tests/phpunit/data/templates/bad_partial.mustache | 1 + tests/phpunit/data/templates/has_partial.mustache | 1 + tests/phpunit/includes/BlockTest.php | 114 +- .../includes/ConsecutiveParametersMatcher.php | 123 + tests/phpunit/includes/EditPageTest.php | 55 + tests/phpunit/includes/ExtraParserTest.php | 3 +- tests/phpunit/includes/FauxRequestTest.php | 43 +- tests/phpunit/includes/FauxResponseTest.php | 7 + .../includes/GlobalFunctions/GlobalTest.php | 103 +- .../includes/GlobalFunctions/wfArrayPlus2dTest.php | 94 + .../includes/GlobalFunctions/wfTimestampTest.php | 1 + .../includes/GlobalFunctions/wfUrlencodeTest.php | 2 + .../includes/ImportLinkCacheIntegrationTest.php | 112 + tests/phpunit/includes/LinkFilterTest.php | 12 +- tests/phpunit/includes/LinkerTest.php | 66 +- tests/phpunit/includes/MediaWikiTest.php | 157 + tests/phpunit/includes/MessageTest.php | 33 + tests/phpunit/includes/MimeMagicTest.php | 2 +- tests/phpunit/includes/MovePageTest.php | 2 +- tests/phpunit/includes/OutputPageTest.php | 168 +- tests/phpunit/includes/PrefixSearchTest.php | 5 + tests/phpunit/includes/SanitizerTest.php | 12 +- .../includes/SanitizerValidateEmailTest.php | 2 +- tests/phpunit/includes/StatusTest.php | 4 +- tests/phpunit/includes/TemplateParserTest.php | 15 +- tests/phpunit/includes/TestingAccessWrapper.php | 34 +- .../phpunit/includes/TestingAccessWrapperTest.php | 18 + .../phpunit/includes/TitleArrayFromResultTest.php | 2 +- tests/phpunit/includes/TitlePermissionTest.php | 22 +- tests/phpunit/includes/TitleTest.php | 101 +- tests/phpunit/includes/UserTest.php | 130 +- tests/phpunit/includes/WikiMapTest.php | 108 + tests/phpunit/includes/WikiReferenceTest.php | 80 + tests/phpunit/includes/XmlJsTest.php | 2 +- tests/phpunit/includes/XmlTest.php | 6 +- tests/phpunit/includes/api/ApiBlockTest.php | 6 +- tests/phpunit/includes/api/ApiEditPageTest.php | 113 +- tests/phpunit/includes/api/ApiLoginTest.php | 4 +- tests/phpunit/includes/api/ApiMainTest.php | 171 +- tests/phpunit/includes/api/ApiMessageTest.php | 20 +- .../phpunit/includes/api/ApiQueryAllPagesTest.php | 6 +- tests/phpunit/includes/api/ApiResultTest.php | 194 +- .../phpunit/includes/api/ApiRevisionDeleteTest.php | 4 +- tests/phpunit/includes/api/ApiTestCase.php | 1 + tests/phpunit/includes/api/ApiUnblockTest.php | 4 +- tests/phpunit/includes/api/ApiUploadTest.php | 36 +- .../includes/api/format/ApiFormatDumpTest.php | 63 - .../includes/api/format/ApiFormatWddxTest.php | 80 - .../api/query/ApiQueryContinueTestBase.php | 5 +- tests/phpunit/includes/api/query/ApiQueryTest.php | 2 +- .../includes/api/query/ApiQueryTestBase.php | 14 +- tests/phpunit/includes/cache/MessageCacheTest.php | 29 +- .../phpunit/includes/changes/RecentChangeTest.php | 327 +- tests/phpunit/includes/config/HashConfigTest.php | 2 +- .../includes/content/ContentHandlerTest.php | 179 +- .../includes/content/CssContentHandlerTest.php | 30 + tests/phpunit/includes/content/CssContentTest.php | 45 +- .../content/JavaScriptContentHandlerTest.php | 30 + .../includes/content/JavaScriptContentTest.php | 53 +- tests/phpunit/includes/content/JsonContentTest.php | 2 +- .../includes/content/TextContentHandlerTest.php | 12 + tests/phpunit/includes/content/TextContentTest.php | 8 +- .../content/WikitextContentHandlerTest.php | 5 + .../phpunit/includes/db/DatabaseMysqlBaseTest.php | 2 +- tests/phpunit/includes/db/DatabaseSqliteTest.php | 25 +- tests/phpunit/includes/db/ORMTableTest.php | 19 - tests/phpunit/includes/debug/MWDebugTest.php | 4 +- .../includes/debug/logger/LegacyLoggerTest.php | 175 + .../includes/debug/logger/MonologSpiTest.php | 136 + .../debug/logger/monolog/AvroFormatterTest.php | 64 + .../debug/logger/monolog/KafkaHandlerTest.php | 207 + .../debug/logger/monolog/LineFormatterTest.php | 75 + .../includes/debug/logging/LegacyLoggerTest.php | 122 - .../includes/deferred/DeferredUpdatesTest.php | 37 +- .../includes/diff/ArrayDiffFormatterTest.php | 4 +- tests/phpunit/includes/exception/HttpErrorTest.php | 65 + .../phpunit/includes/exception/MWExceptionTest.php | 2 +- .../includes/filebackend/FileBackendTest.php | 52 +- .../includes/filebackend/SwiftFileBackendTest.php | 148 + .../filerepo/FileBackendDBRepoWrapperTest.php | 138 + .../filerepo/MigrateFileRepoLayoutTest.php | 114 + .../htmlform/HTMLAutoCompleteSelectFieldTest.php | 2 +- tests/phpunit/includes/json/FormatJsonTest.php | 10 +- tests/phpunit/includes/libs/ArrayUtilsTest.php | 12 +- tests/phpunit/includes/libs/CSSMinTest.php | 57 +- tests/phpunit/includes/libs/IEUrlExtensionTest.php | 33 + tests/phpunit/includes/libs/IPSetTest.php | 252 -- .../includes/libs/JavaScriptMinifierTest.php | 19 +- tests/phpunit/includes/libs/ObjectFactoryTest.php | 41 +- .../phpunit/includes/libs/ProcessCacheLRUTest.php | 2 +- .../includes/libs/SamplingStatsdClientTest.php | 43 + tests/phpunit/includes/libs/XhprofTest.php | 16 +- .../includes/libs/composer/ComposerLockTest.php | 61 + .../includes/logging/BlockLogFormatterTest.php | 372 ++ .../includes/logging/DeleteLogFormatterTest.php | 527 +++ .../phpunit/includes/logging/LogFormatterTest.php | 321 +- .../includes/logging/LogFormatterTestCase.php | 65 + .../includes/logging/MergeLogFormatterTest.php | 67 + .../includes/logging/MoveLogFormatterTest.php | 270 ++ .../includes/logging/NewUsersLogFormatterTest.php | 207 + .../includes/logging/PageLangLogFormatterTest.php | 53 + .../includes/logging/PatrolLogFormatterTest.php | 118 + .../includes/logging/ProtectLogFormatterTest.php | 63 + .../includes/logging/RightsLogFormatterTest.php | 157 + .../includes/logging/UploadLogFormatterTest.php | 166 + tests/phpunit/includes/media/ExifBitmapTest.php | 39 +- .../phpunit/includes/media/FormatMetadataTest.php | 33 - tests/phpunit/includes/media/WebPTest.php | 127 + tests/phpunit/includes/media/XMPValidateTest.php | 5 +- .../phpunit/includes/objectcache/BagOStuffTest.php | 34 +- .../objectcache/MultiWriteBagOStuffTest.php | 55 + .../objectcache/ReplicatedBagOStuffTest.php | 62 + .../includes/objectcache/WANObjectCacheTest.php | 292 ++ .../phpunit/includes/parser/MagicVariableTest.php | 2 + .../includes/parser/MediaWikiParserTest.php | 2 +- tests/phpunit/includes/parser/NewParserTest.php | 10 +- .../phpunit/includes/parser/ParserMethodsTest.php | 4 + tests/phpunit/includes/parser/TagHooksTest.php | 7 +- tests/phpunit/includes/parser/TidyTest.php | 3 +- .../includes/password/PasswordPolicyChecksTest.php | 136 + .../includes/password/UserPasswordPolicyTest.php | 234 ++ .../registration/CoreVersionCheckerTest.php | 38 + .../registration/ExtensionProcessorTest.php | 16 +- .../registration/ExtensionRegistryTest.php | 2 + .../DerivativeResourceLoaderContextTest.php | 78 + .../ResourceLoaderFileModuleTest.php | 22 +- .../resourceloader/ResourceLoaderImageTest.php | 3 - .../resourceloader/ResourceLoaderModuleTest.php | 58 +- .../ResourceLoaderStartUpModuleTest.php | 74 +- .../includes/resourceloader/ResourceLoaderTest.php | 11 +- .../ResourceLoaderWikiModuleTest.php | 49 +- .../phpunit/includes/site/CachingSiteStoreTest.php | 8 +- tests/phpunit/includes/site/DBSiteStoreTest.php | 24 + tests/phpunit/includes/site/HashSiteStoreTest.php | 2 +- tests/phpunit/includes/site/SiteExporterTest.php | 4 +- tests/phpunit/includes/site/SiteImporterTest.php | 12 +- .../includes/specials/SpecialBlankPageTest.php | 25 + .../includes/specials/SpecialPageTestBase.php | 165 + .../includes/specials/SpecialPreferencesTest.php | 3 +- .../includes/specials/SpecialSearchTest.php | 106 +- tests/phpunit/includes/title/ForeignTitleTest.php | 4 +- .../title/MediaWikiPageLinkRendererTest.php | 2 +- tests/phpunit/includes/upload/UploadStashTest.php | 2 +- tests/phpunit/includes/utils/AvroValidatorTest.php | 96 + .../phpunit/includes/utils/BatchRowUpdateTest.php | 243 ++ tests/phpunit/includes/utils/IPTest.php | 273 +- tests/phpunit/includes/utils/MWFunctionTest.php | 34 - tests/phpunit/includes/utils/UIDGeneratorTest.php | 10 +- tests/phpunit/languages/LanguageTest.php | 100 +- .../phpunit/languages/classes/LanguageArqTest.php | 2 +- tests/phpunit/maintenance/backupTextPassTest.php | 8 +- tests/phpunit/mocks/MockWebRequest.php | 26 + .../mocks/content/DummyContentForTesting.php | 121 + .../content/DummyContentHandlerForTesting.php | 42 + .../phpunit/mocks/content/DummyNonTextContent.php | 121 + .../mocks/content/DummyNonTextContentHandler.php | 46 + tests/phpunit/phpunit.php | 35 +- tests/phpunit/structure/AutoLoaderTest.php | 4 +- tests/phpunit/structure/AvailableRightsTest.php | 4 +- tests/phpunit/structure/ResourcesTest.php | 52 +- tests/phpunit/suites/UploadFromUrlTestSuite.php | 4 +- tests/qunit/QUnitTestResources.php | 15 +- tests/qunit/data/generateJqueryMsgData.php | 3 +- tests/qunit/data/mediawiki.jqueryMsg.data.js | 3 +- tests/qunit/data/testrunner.js | 99 +- .../resources/jquery/jquery.accessKeyLabel.test.js | 40 +- .../resources/jquery/jquery.autoEllipsis.test.js | 4 +- .../suites/resources/jquery/jquery.color.test.js | 2 +- .../resources/jquery/jquery.colorUtil.test.js | 36 +- .../suites/resources/jquery/jquery.hidpi.test.js | 16 + .../resources/jquery/jquery.localize.test.js | 14 +- .../jquery/jquery.makeCollapsible.test.js | 18 + .../resources/jquery/jquery.mwExtension.test.js | 15 +- .../resources/jquery/jquery.placeholder.test.js | 172 +- .../jquery/jquery.tablesorter.parsers.test.js | 220 +- .../resources/jquery/jquery.tablesorter.test.js | 413 +- .../resources/jquery/jquery.textSelection.test.js | 33 +- .../mediawiki.api/mediawiki.ForeignApi.test.js | 39 + .../resources/mediawiki.api/mediawiki.api.test.js | 346 +- .../mediawiki.api/mediawiki.api.upload.test.js | 35 + .../mediawiki.api/mediawiki.api.watch.test.js | 6 +- .../resources/mediawiki/mediawiki.RegExp.test.js | 38 + .../resources/mediawiki/mediawiki.Title.test.js | 171 +- .../resources/mediawiki/mediawiki.Uri.test.js | 10 +- .../resources/mediawiki/mediawiki.cldr.test.js | 6 +- .../resources/mediawiki/mediawiki.cookie.test.js | 4 +- .../mediawiki/mediawiki.errorLogger.test.js | 2 +- .../mediawiki/mediawiki.experiments.test.js | 63 + .../mediawiki/mediawiki.jqueryMsg.test.js | 269 +- .../resources/mediawiki/mediawiki.jscompat.test.js | 2 +- .../resources/mediawiki/mediawiki.language.test.js | 14 +- .../mediawiki.messagePoster.factory.test.js | 2 +- .../resources/mediawiki/mediawiki.storage.test.js | 36 + .../suites/resources/mediawiki/mediawiki.test.js | 283 +- .../resources/mediawiki/mediawiki.toc.test.js | 2 +- .../resources/mediawiki/mediawiki.track.test.js | 18 + .../resources/mediawiki/mediawiki.util.test.js | 127 +- tests/qunit/suites/resources/startup.test.js | 4 +- tests/testHelpers.inc | 2 +- 228 files changed, 13779 insertions(+), 3759 deletions(-) create mode 100644 tests/phpunit/data/css/comments.css create mode 100644 tests/phpunit/data/import/ImportLinkCacheIntegrationTest.xml create mode 100644 tests/phpunit/data/media/2_webp_a.webp create mode 100644 tests/phpunit/data/media/2_webp_ll.webp create mode 100644 tests/phpunit/data/media/srgb.jpg create mode 100644 tests/phpunit/data/media/tinyrgb.icc create mode 100644 tests/phpunit/data/media/tinyrgb.jpg create mode 100644 tests/phpunit/data/media/webp_animated.webp create mode 100644 tests/phpunit/data/templates/bad_partial.mustache create mode 100644 tests/phpunit/data/templates/has_partial.mustache create mode 100644 tests/phpunit/includes/ConsecutiveParametersMatcher.php create mode 100644 tests/phpunit/includes/GlobalFunctions/wfArrayPlus2dTest.php create mode 100644 tests/phpunit/includes/ImportLinkCacheIntegrationTest.php create mode 100644 tests/phpunit/includes/MediaWikiTest.php create mode 100644 tests/phpunit/includes/WikiMapTest.php create mode 100644 tests/phpunit/includes/WikiReferenceTest.php delete mode 100644 tests/phpunit/includes/api/format/ApiFormatDumpTest.php delete mode 100644 tests/phpunit/includes/api/format/ApiFormatWddxTest.php create mode 100644 tests/phpunit/includes/content/CssContentHandlerTest.php create mode 100644 tests/phpunit/includes/content/JavaScriptContentHandlerTest.php create mode 100644 tests/phpunit/includes/content/TextContentHandlerTest.php create mode 100644 tests/phpunit/includes/debug/logger/LegacyLoggerTest.php create mode 100644 tests/phpunit/includes/debug/logger/MonologSpiTest.php create mode 100644 tests/phpunit/includes/debug/logger/monolog/AvroFormatterTest.php create mode 100644 tests/phpunit/includes/debug/logger/monolog/KafkaHandlerTest.php create mode 100644 tests/phpunit/includes/debug/logger/monolog/LineFormatterTest.php delete mode 100644 tests/phpunit/includes/debug/logging/LegacyLoggerTest.php create mode 100644 tests/phpunit/includes/exception/HttpErrorTest.php create mode 100644 tests/phpunit/includes/filebackend/SwiftFileBackendTest.php create mode 100644 tests/phpunit/includes/filerepo/FileBackendDBRepoWrapperTest.php create mode 100644 tests/phpunit/includes/filerepo/MigrateFileRepoLayoutTest.php delete mode 100644 tests/phpunit/includes/libs/IPSetTest.php create mode 100644 tests/phpunit/includes/libs/SamplingStatsdClientTest.php create mode 100644 tests/phpunit/includes/logging/BlockLogFormatterTest.php create mode 100644 tests/phpunit/includes/logging/DeleteLogFormatterTest.php create mode 100644 tests/phpunit/includes/logging/LogFormatterTestCase.php create mode 100644 tests/phpunit/includes/logging/MergeLogFormatterTest.php create mode 100644 tests/phpunit/includes/logging/MoveLogFormatterTest.php create mode 100644 tests/phpunit/includes/logging/NewUsersLogFormatterTest.php create mode 100644 tests/phpunit/includes/logging/PageLangLogFormatterTest.php create mode 100644 tests/phpunit/includes/logging/PatrolLogFormatterTest.php create mode 100644 tests/phpunit/includes/logging/ProtectLogFormatterTest.php create mode 100644 tests/phpunit/includes/logging/RightsLogFormatterTest.php create mode 100644 tests/phpunit/includes/logging/UploadLogFormatterTest.php create mode 100644 tests/phpunit/includes/media/WebPTest.php create mode 100644 tests/phpunit/includes/objectcache/MultiWriteBagOStuffTest.php create mode 100644 tests/phpunit/includes/objectcache/ReplicatedBagOStuffTest.php create mode 100644 tests/phpunit/includes/objectcache/WANObjectCacheTest.php create mode 100644 tests/phpunit/includes/password/PasswordPolicyChecksTest.php create mode 100644 tests/phpunit/includes/password/UserPasswordPolicyTest.php create mode 100644 tests/phpunit/includes/registration/CoreVersionCheckerTest.php create mode 100644 tests/phpunit/includes/resourceloader/DerivativeResourceLoaderContextTest.php create mode 100644 tests/phpunit/includes/specials/SpecialBlankPageTest.php create mode 100644 tests/phpunit/includes/specials/SpecialPageTestBase.php create mode 100644 tests/phpunit/includes/utils/AvroValidatorTest.php create mode 100644 tests/phpunit/includes/utils/BatchRowUpdateTest.php delete mode 100644 tests/phpunit/includes/utils/MWFunctionTest.php create mode 100644 tests/phpunit/mocks/MockWebRequest.php create mode 100644 tests/phpunit/mocks/content/DummyContentForTesting.php create mode 100644 tests/phpunit/mocks/content/DummyContentHandlerForTesting.php create mode 100644 tests/phpunit/mocks/content/DummyNonTextContent.php create mode 100644 tests/phpunit/mocks/content/DummyNonTextContentHandler.php create mode 100644 tests/qunit/suites/resources/mediawiki.api/mediawiki.ForeignApi.test.js create mode 100644 tests/qunit/suites/resources/mediawiki.api/mediawiki.api.upload.test.js create mode 100644 tests/qunit/suites/resources/mediawiki/mediawiki.RegExp.test.js create mode 100644 tests/qunit/suites/resources/mediawiki/mediawiki.experiments.test.js create mode 100644 tests/qunit/suites/resources/mediawiki/mediawiki.storage.test.js (limited to 'tests') diff --git a/tests/TestsAutoLoader.php b/tests/TestsAutoLoader.php index def23dad..8a81a644 100644 --- a/tests/TestsAutoLoader.php +++ b/tests/TestsAutoLoader.php @@ -66,8 +66,10 @@ $wgAutoloadClasses += array( 'TestRecentChangesHelper' => "$testDir/phpunit/includes/changes/TestRecentChangesHelper.php", # tests/phpunit/includes/content - 'DummyContentHandlerForTesting' => "$testDir/phpunit/includes/content/ContentHandlerTest.php", - 'DummyContentForTesting' => "$testDir/phpunit/includes/content/ContentHandlerTest.php", + 'DummyContentHandlerForTesting' => "$testDir/phpunit/mocks/content/DummyContentHandlerForTesting.php", + 'DummyContentForTesting' => "$testDir/phpunit/mocks/content/DummyContentForTesting.php", + 'DummyNonTextContentHandler' => "$testDir/phpunit/mocks/content/DummyNonTextContentHandler.php", + 'DummyNonTextContent' => "$testDir/phpunit/mocks/content/DummyNonTextContent.php", 'ContentHandlerTest' => "$testDir/phpunit/includes/content/ContentHandlerTest.php", 'JavaScriptContentTest' => "$testDir/phpunit/includes/content/JavaScriptContentTest.php", 'TextContentTest' => "$testDir/phpunit/includes/content/TextContentTest.php", @@ -82,6 +84,9 @@ $wgAutoloadClasses += array( # tests/phpunit/includes/diff 'FakeDiffOp' => "$testDir/phpunit/includes/diff/FakeDiffOp.php", + # tests/phpunit/includes/logging + 'LogFormatterTestCase' => "$testDir/phpunit/includes/logging/LogFormatterTestCase.php", + # tests/phpunit/includes/password 'PasswordTestCase' => "$testDir/phpunit/includes/password/PasswordTestCase.php", @@ -89,6 +94,9 @@ $wgAutoloadClasses += array( 'ResourceLoaderImageModuleTest' => "$testDir/phpunit/includes/resourceloader/ResourceLoaderImageModuleTest.php", 'ResourceLoaderImageModuleTestable' => "$testDir/phpunit/includes/resourceloader/ResourceLoaderImageModuleTest.php", + # tests/phpunit/includes/specials + 'SpecialPageTestBase' => "$testDir/phpunit/includes/specials/SpecialPageTestBase.php", + # tests/phpunit/languages 'LanguageClassesTestCase' => "$testDir/phpunit/languages/LanguageClassesTestCase.php", @@ -109,6 +117,7 @@ $wgAutoloadClasses += array( 'MockImageHandler' => "$testDir/phpunit/mocks/media/MockImageHandler.php", 'MockSvgHandler' => "$testDir/phpunit/mocks/media/MockSvgHandler.php", 'MockDjVuHandler' => "$testDir/phpunit/mocks/media/MockDjVuHandler.php", + 'MockWebRequest' => "$testDir/phpunit/mocks/MockWebRequest.php", # tests/parser 'NewParserTest' => "$testDir/phpunit/includes/parser/NewParserTest.php", diff --git a/tests/browser/environments.yml b/tests/browser/environments.yml index 8f8381ed..b2232e62 100644 --- a/tests/browser/environments.yml +++ b/tests/browser/environments.yml @@ -14,7 +14,7 @@ # export MEDIAWIKI_USER=Selenium_user2 # bundle exec cucumber # -mw-vagrant-host: +mw-vagrant-host: &default mediawiki_url: http://127.0.0.1:8080/wiki/ mediawiki_user: Selenium_user mediawiki_password: vagrant @@ -33,3 +33,5 @@ test2: mediawiki_url: http://test2.wikipedia.org/wiki/ mediawiki_user: Selenium_user # mediawiki_password: SET THIS IN THE ENVIRONMENT! + +default: *default diff --git a/tests/browser/features/create_account.feature b/tests/browser/features/create_account.feature index 0b4e83a5..35df8b4b 100644 --- a/tests/browser/features/create_account.feature +++ b/tests/browser/features/create_account.feature @@ -10,3 +10,8 @@ Feature: Create account | Special:CreateAccount | | Special:UserLogin/signup | | Special:UserLogin?type=signup | + + Scenario: If no username is entered then an error is displayed + Given I go to Create account page at Special:CreateAccount + When I submit the form + Then an error message is displayed diff --git a/tests/browser/features/step_definitions/create_account_steps.rb b/tests/browser/features/step_definitions/create_account_steps.rb index 03bff66f..98e0f2cb 100644 --- a/tests/browser/features/step_definitions/create_account_steps.rb +++ b/tests/browser/features/step_definitions/create_account_steps.rb @@ -16,3 +16,11 @@ end Then(/^form has Create account button$/) do expect(on(CreateAccountPage).create_account_element).to exist end + +When(/^I submit the form$/) do + on(CreateAccountPage).create_account +end + +Then(/^an error message is displayed$/) do + expect(on(CreateAccountPage).error_message_element.class_name).to eq 'errorbox' +end diff --git a/tests/browser/features/support/pages/create_account_page.rb b/tests/browser/features/support/pages/create_account_page.rb index 98b893a6..9aa00cd2 100644 --- a/tests/browser/features/support/pages/create_account_page.rb +++ b/tests/browser/features/support/pages/create_account_page.rb @@ -15,4 +15,5 @@ class CreateAccountPage page_url '<%=params[:page_title]%>' button(:create_account, id: 'wpCreateaccount') + div(:error_message, id: 'mw-createacct-status-area') end diff --git a/tests/browser/features/support/pages/main_page.rb b/tests/browser/features/support/pages/main_page.rb index 6d76b01c..3092ab5c 100644 --- a/tests/browser/features/support/pages/main_page.rb +++ b/tests/browser/features/support/pages/main_page.rb @@ -3,16 +3,16 @@ class MainPage page_url '' - a(:edit_link, href: /action=edit/) + a(:edit_link, css: '#ca-edit a') li(:help_link, id: 'n-help') div(:page_content, id: 'content') li(:page_information_link, id: 't-info') li(:permanent_link_link, id: 't-permalink') - a(:printable_version_link, href: /printable=yes/) + a(:printable_version_link, css: '#t-print a') li(:random_page_link, id: 'n-randompage') li(:recent_changes_link, id: 'n-recentchanges') li(:related_changes_link, id: 't-recentchangeslinked') li(:special_pages_link, id: 't-specialpages') - a(:view_history_link, href: /action=history/) + a(:view_history_link, css: '#ca-history a') li(:what_links_here_link, id: 't-whatlinkshere') end diff --git a/tests/browser/features/support/pages/preferences_appearance_page.rb b/tests/browser/features/support/pages/preferences_appearance_page.rb index 83c3952f..1e5ffaa1 100644 --- a/tests/browser/features/support/pages/preferences_appearance_page.rb +++ b/tests/browser/features/support/pages/preferences_appearance_page.rb @@ -27,7 +27,7 @@ class PreferencesAppearancePage radio_button(:monobook, id: 'mw-input-wpskin-monobook') radio_button(:no_preference_radio, id: 'mw-input-wpdate-default') text_field(:other_offset, id: 'mw-input-wptimecorrection-other') - a(:restore_default_link, href: /reset/) + a(:restore_default_link, id: 'mw-prefs-restoreprefs') select_list(:size_select, id: 'mw-input-wpimagesize') select_list(:threshold_select, id: 'mw-input-wpstubthreshold') select_list(:time_offset_select, id: 'mw-input-wptimecorrection') diff --git a/tests/browser/features/support/pages/view_history_page.rb b/tests/browser/features/support/pages/view_history_page.rb index bb9c5862..ee4d757a 100644 --- a/tests/browser/features/support/pages/view_history_page.rb +++ b/tests/browser/features/support/pages/view_history_page.rb @@ -1,6 +1,6 @@ class ViewHistoryPage include PageObject - a(:view_history_link, href: /action=history/) - a(:old_version_link, href: /oldid=/) + a(:view_history_link, css: '#ca-history a') + a(:old_version_link, css: '#pagehistory a.mw-changeslist-date') end diff --git a/tests/parser/parserTest.inc b/tests/parser/parserTest.inc index 1cffa20c..f429c30a 100644 --- a/tests/parser/parserTest.inc +++ b/tests/parser/parserTest.inc @@ -155,7 +155,7 @@ class ParserTest { static function setUp() { global $wgParser, $wgParserConf, $IP, $messageMemc, $wgMemc, - $wgUser, $wgLang, $wgOut, $wgRequest, $wgStyleDirectory, $wgEnableParserCache, + $wgUser, $wgLang, $wgOut, $wgRequest, $wgStyleDirectory, $wgExtraNamespaces, $wgNamespaceAliases, $wgNamespaceProtection, $wgLocalFileRepo, $wgExtraInterlanguageLinkPrefixes, $wgLocalInterwikis, $parserMemc, $wgThumbnailScriptPath, $wgScriptPath, @@ -211,7 +211,6 @@ class ParserTest { $wgParserCacheType = CACHE_NONE; } - $wgEnableParserCache = false; DeferredUpdates::clearPendingUpdates(); $wgMemc = wfGetMainCache(); // checks $wgMainCacheType $messageMemc = wfGetMessageCacheStorage(); @@ -890,9 +889,9 @@ class ParserTest { 'wgDisableTitleConversion' => false, // Tidy options. 'wgUseTidy' => isset( $opts['tidy'] ), - 'wgAlwaysUseTidy' => false, + 'wgTidyConfig' => null, 'wgDebugTidy' => false, - 'wgTidyConf' => $IP . '/includes/tidy.conf', + 'wgTidyConf' => $IP . '/includes/tidy/tidy.conf', 'wgTidyOpts' => '', 'wgTidyInternal' => $this->tidySupport->isInternal(), ); @@ -937,6 +936,7 @@ class ParserTest { $wgHooks['ParserGetVariableValueTs'][] = 'ParserTest::getFakeTimestamp'; MagicWord::clearCache(); + MWTidy::destroySingleton(); return $context; } @@ -1219,6 +1219,7 @@ class ParserTest { FileBackendGroup::destroySingleton(); LockManagerGroup::destroySingletons(); LinkCache::singleton()->clear(); + MWTidy::destroySingleton(); foreach ( $this->savedGlobals as $var => $val ) { $GLOBALS[$var] = $val; diff --git a/tests/parser/parserTests.txt b/tests/parser/parserTests.txt index e9653529..c8c63f39 100644 --- a/tests/parser/parserTests.txt +++ b/tests/parser/parserTests.txt @@ -118,6 +118,13 @@ Template:echo_with_div
{{{1}}}
!! endarticle +!! article +Template:blank_param +!! text +{{{1}}} +{{{}}} +!! endarticle + !! article Template:table_attribs !! text @@ -153,6 +160,22 @@ Template:table_attribs_5 |style="color:red;"||Bar !! endarticle +!! article +Template:table_attribs_6 +!! text +style="background: + + +red;" | +!! endarticle + +!! article +Template:table_attribs_7 +!! text + +|style{{=}}"background:#f9f9f9;"|Foofoo +!! endarticle + !! article Template:table_header_cells !! text @@ -165,6 +188,13 @@ Template:table_cells {{table_attribs}}||style='color:red;'|''Bar''||style='color:brown;'|''Foo'' and Baz !! endarticle +!! article +Template:PartialTable +!! text +{| +|- +!! endarticle + !! article Template:image_attribs !! text @@ -808,15 +838,12 @@ parsoid=wt2html !!end # same html as previous, but wikitext adjusted to match parsoid html2wt -# skipping wt2html and html2html because it wants to put before !! test Italics and bold: 5-quote opening sequence: (5,2+3) -!! options -parsoid=wt2wt,html2wt !! wikitext '''''foo''''' -!! html -

foo +!! html/* +

foo

!! end @@ -1300,7 +1327,7 @@ Non-word characters don't terminate tag names + tidy Non-word characters are valid in extension tags (T19663) !! wikitext tåg -!! html +!! html/php
 'tåg'
 array (
@@ -1311,11 +1338,15 @@ array (
 
 !! test
 Isolated close tags should be treated as literal text (bug 52760)
+!! options
+parsoid=wt2html
 !! wikitext
 
 
 s
-!! html+tidy
+!! html/php+tidy
+

<s.foo>s

+!! html/parsoid

<s.foo>s

!! end @@ -1349,9 +1380,11 @@ Bare pipe character from a template (bug 52363) unordered list !! wikitext * This is not an unordered list item. -!! html +!! html/php

* This is not an unordered list item.

+!! html/parsoid +

* This is not an unordered list item.

!! end !! test @@ -1364,7 +1397,7 @@ sed abit. :and a colon
-!! html +!! html/php

Lorem ipsum dolor sed abit. @@ -1373,6 +1406,14 @@ sed abit. :and a colon

+!! html/parsoid +

Lorem ipsum dolor + +sed abit. + sed nullum. + +:and a colon +

!! end !! test @@ -1386,7 +1427,7 @@ nowiki 3 *There is not nowiki. *There is nowiki. -!! html +!! html/php
There is not nowiki.
There is nowiki.
  1. There is not nowiki.
  2. @@ -1394,6 +1435,15 @@ nowiki 3
    • There is not nowiki.
    • There is nowiki.
    +!! html/parsoid +
    There is not nowiki.
    +
    There is nowiki.
    + +
    1. There is not nowiki.
    2. +
    3. There is nowiki.
    + +
    • There is not nowiki.
    • +
    • There is nowiki.
    !! end !! test @@ -1407,11 +1457,11 @@ Entities inside !! test Entities inside template parameters -!! options -parsoid !! wikitext {{echo|–}} -!! html +!! html/php+tidy +

    +!! html/parsoid

    !! end @@ -1419,17 +1469,27 @@ parsoid Properly escape nowiki when combined with other wiki markup !! options parsoid=html2wt -!! html +!! html/parsoid

    * </nowiki> tag

    !! wikitext -* </nowiki> tag +* </nowiki> tag +!! end + +!! test +T93824: Put escaped HTML tags inside nowiki +!! options +parsoid=html2wt +!! html/parsoid +

    <h2>foo</h2>

    +!! wikitext +

    foo

    !! end !! test T71950: 1. Put nowiki as close to cause as possible, even with non-quote escapable chars !! options parsoid=html2wt -!! html +!! html/parsoid

    This text: L'Foo This text: L''Foo This text: L'''Foo''

    @@ -1444,7 +1504,7 @@ This text: L'''[[Foo]]'' T71950: 2. Put nowiki as close to cause as possible, after ' :' !! options parsoid=html2wt -!! html +!! html/parsoid

    This text : L''Foo

    !! wikitext @@ -1483,6 +1543,30 @@ parsoid=html2wt {{echo|a }}} !! end +!! test +Cases where "!!" needs nowiki protection +!! options +parsoid=html2wt +!! html/parsoid + + +
    this needs protection !! here
    + + + +
    this does not need +protection !! here
    +!! wikitext +{| +!this needs protection !! here +|} + +{| +!this does not need +protection !! here +|} +!! end + ### ### Comments ### @@ -1587,8 +1671,10 @@ Comment whitespace Comment semantics and delimiters !! wikitext -!! html +!! html/php +!! html/parsoid + !! end !! test @@ -1596,8 +1682,11 @@ Comment semantics and delimiters, redux !! wikitext -!! html +!! html/php +!! html/parsoid + !! end !! test @@ -1607,39 +1696,68 @@ Comment semantics and delimiters: directors cut everything starting with < followed by !-- until the first -- and > we see, that wouldn't be valid XML however, since in XML -- has to terminate a comment -->--> -!! html +!! html/php

    -->

    +!! html/parsoid +

    -->

    !! end !! test Comment semantics: nesting !! wikitext --> -!! html +!! html/php

    -->

    +!! html/parsoid +

    -->

    !! end +# Parsoid closes the unclosed comment, even if it means a slight +# round-trip diff. !! test Comment semantics: unclosed comment at end +!! options +parsoid=wt2html,html2html !! wikitext !! end -# Bug 58184: document parsoid's behaviour !! test -Suppress comment closing tag in lenient browsers -!! options -parsoid=wt2html,html2html +Comment semantics: normalize comments to play nice with XML and browsers !! wikitext - think this is closed --> + think this is closed --> + This would normally be text --> + As would this --> + + +But this is not a comment. !! html/php +

    But this is not a comment. +

    +!! html/parsoid + + + + + +

    But this is not a comment.

    +!! end +!! test +Comment semantics: round-trip even text which contains encoded --> +!! wikitext + !! html/parsoid - + !! end !! test @@ -1682,10 +1800,15 @@ parsoid=wt2html,wt2wt !! wikitext *a *b -!! html -
      +!! html/php +
      • a
      • +
      • b
      + +!! html/parsoid +
      • a
      • +
      • b
      @@ -1894,7 +2017,7 @@ a [[Category:A1]] [[Category:A2]] [[Category:A4]] !! html/parsoid

      a

      - + !! end !! test @@ -1904,7 +2027,7 @@ parsoid=wt2html !! wikitext [[Category:A1]]a !! html/parsoid -

      a

      +

      a

      !! end ### @@ -1934,13 +2057,28 @@ Tabs don't trigger preformatted text preformatted text. This is preformatted text. So is this. -!! html +!! html/php

      This is not preformatted text.

      This is preformatted text.
       	So is this.
       
      +!! html/parsoid +

      This is not + preformatted text.

      +
      This is preformatted text.
      +	So is this.
      +!! end + +!! test +Space before tab needs nowiki pre protection +!! options +parsoid=html2wt +!! html/parsoid +

      a

      +!! wikitext + a !! end !! test @@ -2140,7 +2278,7 @@ Entities inside
       
       
      -!! html +!! html/php
       <nowiki>
       
      @@ -2153,6 +2291,18 @@ Entities inside
       
       </pre>
       

      +!! html/parsoid +
      <nowiki>
      +
      +

      </nowiki> +</pre>

      + +

      +<pre> +<nowiki> +</pre> + +</pre>

      !! end !! test @@ -2209,13 +2359,17 @@ HTML pre followed by indent-pre
      !! end +# Note that tidy removes the empty

      tags from the start and end. +# Parsoid does not, by design. !!test Block tag pre -!!options -parsoid !! wikitext

      foo

      -!! html +!! html/php+tidy +
      +foo
      +
      +!! html/parsoid

      foo

      !!end @@ -2338,6 +2492,19 @@ Templates: Indent-Pre: 1f: Wrapping should be based on expanded content
!!end +!! test +Pres with newline attributes +!! wikitext +
hi
+!! html/php +
hi
+ +!! html/parsoid +
hi
+!! end + !! test Things that look like
 tags aren't treated as such
 !! wikitext
@@ -2377,7 +2544,10 @@ Parsoid: handle pre with space after attribute
 parsoid=wt2html
 !! wikitext
 
{{echo|foo}}
-!! html +!! html/php +
{{echo|foo}}
+ +!! html/parsoid
{{echo|foo}}
!! end @@ -2583,32 +2753,32 @@ Templates: Other wikitext in parameter names (bug 67657) #-------------------------------------------------------------------- !! test Templates: Parsoid parameter escaping test 1 -!! options -parsoid !! wikitext {{echo|[foo]|{{echo|[bar]}}}} -!! html +!! html/php+tidy +

[foo]

+!! html/parsoid

[foo]

!! end !! test Parsoid: Pipes in external links in template parameter -!! options -parsoid !! wikitext {{echo|[{{echo|http://example.com}} link]}} -!! html +!! html/php+tidy +

link

+!! html/parsoid

link

!! end !! test Parsoid: pipe in transclusion parameter -!! options -parsoid !! wikitext {{echo|http://foo.com/a|b}} -!! html +!! html/php+tidy +

http://foo.com/a%7Cb

+!! html/parsoid

http://foo.com/a|b

@@ -2620,7 +2790,9 @@ Parsoid: Pipe in external link target and content in template parameter parsoid=html2wt,wt2wt !! wikitext {{echo|[http://foo.com/a|b a|b]}} -!! html +!! html/php+tidy +

a|b

+!! html/parsoid

|bar"}},"i":0}}]}'}'>foo|bar <div> @@ -2659,19 +2833,21 @@ Templates: '=' char in nested transclusions should not trigger nowiki escapes or parsoid=html2wt,wt2wt !! wikitext {{echo|{{echo|1=bar}}}} -!! html +!! html/php+tidy +

bar

+!! html/parsoid

bar

!! end ## Bug 56733 !! test Templates parameters with special tokenizing behavior dont get modified because of arg escaping -!! options -parsoid !! wikitext {{echo|a : b}} -!! html -

a : b

+!! html/php+tidy +

a : b

+!! html/parsoid +

a : b

!! end ## Bug T73412 @@ -2679,13 +2855,23 @@ parsoid Templates: Preserve blank parameter names !! wikitext {{echo|=foo}} -!! html/php -

{{{1}}} -

+!! html/php+tidy +

{{{1}}}

!! html/parsoid

{{{1}}}

!! end +!! test +Templates: Preserve blank parameter names in other positions +!! wikitext +{{blank_param|bar|=foo}} +!! html/php+tidy +

bar foo

+!! html/parsoid +

bar +foo

+!! end + ### ### Parsoid-centric tests for testing RT edge cases for pre ### @@ -3136,9 +3322,10 @@ parsoid=wt2html,wt2wt !! wikitext [[Category:foo]] {{echo| [[Category:foo]]}} -!! html - - +!! html/php+tidy +!! html/parsoid + + !! end !! test @@ -3149,9 +3336,22 @@ parsoid=wt2html,wt2wt [[Category:foo]] a [[Category:foo]] {{echo|b}} !! html -
- a
- b
+
 a
+  b
+!! end + +!! test +Indent-Pre: Newlines in comments shouldn't affect sol state +!! wikitext +a b +!! html/php+tidy +

a b

+!! html/parsoid +

a b

!! end ### @@ -3177,8 +3377,10 @@ foo foo
-!! html -
foo
+!! html/php+tidy +
+foo
+
 foo
 
@@ -3191,7 +3393,6 @@ foo foo - !! html/parsoid
foo
@@ -3230,7 +3431,7 @@ haha -!! html +!! html/php+tidy
 
 
@@ -3247,7 +3448,6 @@ haha
 
 
 
- !! html/parsoid
 
@@ -3290,7 +3490,7 @@ HTML-pre: 3: other wikitext
 '' no-italic ''
 [[ NoLink ]]
 
-!! html +!! html/php
 * foo
 # bar
@@ -3299,6 +3499,13 @@ HTML-pre: 3: other wikitext
 [[ NoLink ]]
 
+!! html/parsoid +
* foo
+# bar
+= no-h =
+'' no-italic ''
+[[ NoLink ]]
+
!!end ### @@ -3570,20 +3777,26 @@ Definition Lists: Hacky use to indent tables, with comment before table !! end -# Bug 52473 +# The trailing whitespace in this test is to catch a regression in +# Parsoid after T54473. !! test Definition Lists: Hacky use to indent tables (WS-insensitive) -!! options -parsoid !! wikitext : {| |a |} -!! html -
-
a
-
+!! html/php +
+ +
a +
+ +!! html/parsoid +
+ +
a
!! end + ## The PHP parser treats : items (dd) without a corresponding ; item (dt) ## as an empty dt item. It also ignores all but the last ";" when followed ## by ":" later on. So, ";" are not ignored in ";;;t3" but are ignored in @@ -3616,7 +3829,7 @@ parsoid ## ## All Parsoid only definition list tests have this difference. ## -## See also: https://bugzilla.wikimedia.org/show_bug.cgi?id=6569 +## See also: https://phabricator.wikimedia.org/T8569 ## and http://lists.wikimedia.org/pipermail/wikitext-l/2011-November/000483.html !! test @@ -3706,12 +3919,19 @@ parsoid !! test Definition Lists: Nesting: Test 2 (Parsoid only) -!! options -parsoid !! wikitext ;t1 ::d2 -!! html +!! html/php+tidy +
+
t1
+
+
+
d2
+
+
+
+!! html/parsoid
t1
@@ -3726,12 +3946,27 @@ parsoid !! test Definition Lists: Nesting: Test 3 (Parsoid only) -!! options -parsoid !! wikitext :;t1 ::::d2 -!! html +!! html/php+tidy +
+
+
+
t1
+
+
+
+
+
d2
+
+
+
+
+
+
+
+!! html/parsoid
@@ -4006,6 +4241,9 @@ Definition Lists: Mixed Lists: Test 11 # Another case where tidy converts a
to a
(but Parsoid doesn't). +# From whitelist: +# * The test is wrong, there are two colons where there should be :; +# * The PHP parser is wrong to close the
after the
containing the
    . !! test Definition Lists: Weird Ones: Test 1 !! wikitext @@ -4063,7 +4301,7 @@ Definition Lists: Weird Ones: Test 1
    -
    foo 
    +
    foo 
    bar (who uses this?)
@@ -4120,6 +4358,17 @@ Definition Lists: colons occurring in tags
+!! html/parsoid +
a
b
+
a:b
+
a:b
+
a:b
+
a:b
+
a
+
b
+
a:b
+
a:b +
a:b
!! end !! test @@ -4440,6 +4689,25 @@ http://example.com/url_with_entity<
http://example.com/url_with_entity<

!! end +!! test +External links: Lone protocols are never linked (T105697) +!! wikitext +http:// +http://; +(http://) +bitcoin: +bitcoin:; +(bitcoin:) +!! html +

http:// +http://; +(http://) +bitcoin: +bitcoin:; +(bitcoin:) +

+!! end + !! test External links: No preceding word characters allowed (bug 65278) !! wikitext @@ -4981,38 +5249,6 @@ External link containing a single quote. (bug 63947)

bang

!! end - -!! test -External link containing a period in the anchor. (bug 63947) -!! wikitext -[//foo.org/bar#baz. bang] - -[//foo.org/bar. bang] -!! html/php -

bang -

bang -

-!! html/parsoid -

bang

-

bang

-!! end - -!! test -External link containing a single quote. (bug 63947) -!! wikitext -[//foo.org/bar'baz] - -[//foo.org/bar'baz bang] -!! html/php -

[1] -

bang -

-!! html/parsoid -

-

bang

-!! end - - !! test External link containing double-single-quotes in text '' (bug 4598 sanity check) !! wikitext @@ -5048,9 +5284,22 @@ External link containing double-single-quotes with no space separating the url f External link with comments in link text !! wikitext [http://www.google.com Google ] -!! html +!! html/php

Google

+!! html/parsoid +

Google

+!! end + +!! test +External link to bare IPv4 address +!! wikitext +[http://192.168.0.1 Link] +!! html/php +

Link +

+!! html/parsoid +

Link

!! end !! test @@ -5088,14 +5337,129 @@ http://example.com/index.php?foozoid[]=bar !! end !! test -IPv6 urls (bug 21261) -!! options -disabled +IPv6 urls, autolink format (T23261) !! wikitext http://[2404:130:0:1000::187:2]/index.php -!! html + +Examples from RFC 2373, section 2.2: +* http://[1080::8:800:200C:417A]/unicast +* http://[FF01::101]/multicast +* http://[::1]/loopback +* http://[::]/unspecified +* http://[::13.1.68.3]/ipv4compat +* http://[::FFFF:129.144.52.38]/ipv4compat + +Examples from RFC 2732, section 2: +* http://[FEDC:BA98:7654:3210:FEDC:BA98:7654:3210]:80/index.html +* http://[1080:0:0:0:8:800:200C:417A]/index.html +* http://[3ffe:2a00:100:7031::1] +* http://[1080::8:800:200C:417A]/foo +* http://[::192.9.5.5]/ipng +* http://[::FFFF:129.144.52.38]:80/index.html +* http://[2010:836B:4179::836B:4179] + +!! html/php

http://[2404:130:0:1000::187:2]/index.php -

+

Examples from RFC 2373, section 2.2: +

+ +

Examples from RFC 2732, section 2: +

+ + +!! html/parsoid +

http://[2404:130:0:1000::187:2]/index.php

+ +

Examples from RFC 2373, section 2.2:

+ + +

Examples from RFC 2732, section 2:

+ +!! end + +!! test +IPv6 urls, bracketed format (T23261) +!! wikitext +[http://[2404:130:0:1000::187:2]/index.php test] + +Examples from RFC 2373, section 2.2: +* [http://[1080::8:800:200C:417A] unicast] +* [http://[FF01::101] multicast] +* [http://[::1]/ loopback] +* [http://[::] unspecified] +* [http://[::13.1.68.3] ipv4compat] +* [http://[::FFFF:129.144.52.38] ipv4compat] + +Examples from RFC 2732, section 2: +* [http://[FEDC:BA98:7654:3210:FEDC:BA98:7654:3210]:80/index.html 1] +* [http://[1080:0:0:0:8:800:200C:417A]/index.html 2] +* [http://[3ffe:2a00:100:7031::1] 3] +* [http://[1080::8:800:200C:417A]/foo 4] +* [http://[::192.9.5.5]/ipng 5] +* [http://[::FFFF:129.144.52.38]:80/index.html 6] +* [http://[2010:836B:4179::836B:4179] 7] + +!! html/php +

test +

Examples from RFC 2373, section 2.2: +

+ +

Examples from RFC 2732, section 2: +

+ + +!! html/parsoid +

test

+ +

Examples from RFC 2373, section 2.2:

+ + +

Examples from RFC 2732, section 2:

+ !! end !! test @@ -5113,7 +5477,8 @@ Non-extlinks in brackets [{{echo|foo}}l's errand] [url={{echo|foo}}] [url=http://example.com] -!! html +[http:// bare protocols don't count] +!! html/php

[foo] [foo bar] [foo bar] @@ -5126,7 +5491,22 @@ Non-extlinks in brackets [fool's errand] [url=foo] [url=http://example.com] +[http:// bare protocols don't count]

+!! html/parsoid +

[foo] +[foo bar] +[foo bar] +[fool's] errand +[fool's errand] +[foo] +[foo bar] +[foo bar] +[fool's] errand +[fool's errand] +[url=foo] +[url=http://example.com] +[http:// bare protocols don't count]

!! end !! test @@ -5208,15 +5588,55 @@ Parenthesis in external links, w/ transclusion or comment !! end !! test -Replace invalid link targets when serializing +Serialize tags with invalid link targets as plain text !! options parsoid=html2wt -!! html -Manual +!! html/parsoid +text +*text +[[foo]] +*a [[foo]] +!! wikitext +text +*text +[[foo]] +*a [[foo]] +!! end + +!! test +mw:ExtLink -vs- mw:WikiLink (T94723) +!! options +parsoid=html2wt +!! html/parsoid +Bar +Bar +Bar +Bar +

+European Robin +European Robin +

+!! wikitext +[[Foo|Bar]] +[[Foo|Bar]] +[[wikipedia:Foo|Bar]] +[[wikipedia:Foo|Bar]] + +[[wikipedia:European_Robin|European Robin]] +[[wikipedia:European_Robin|European Robin]] +!! end + +!! test +mw:ExtLink linking to a interwiki URL can be round-tripped losslessly (T94723) +!! options +parsoid=wt2wt !! wikitext -[[MediaWiki:Badtitletext|Manual]] +[http://en.wikipedia.org/wiki/European_Robin European Robin] +!! html/parsoid +THIS SECTION IS NOT USED (but Parsoid won't run the test without it) !! end + ### ### Quotes ### @@ -5280,7 +5700,9 @@ Plain ''italic'''s plain

Bold tag left open

Italic tag left open

Normal text. -

This year's election should beat last year's. +

+ +

This year's election should beat last year's.

Toms car is bigger than Susans.

Plain italic's plain

@@ -5480,6 +5902,7 @@ Simple table but with multiple dashes for row wikitext !! end + !! test Multiplication table !! wikitext @@ -5600,6 +6023,69 @@ Accept "||" in indented table headings !! end +!! test +Accept "!!" in templates +!! wikitext +{| +!a {{echo|b!!c}} +|} +!! html/php + + + +
a bc +
+ +!! html/parsoid + + +!! end + +!! test +Accept "!!" in table headings after newline +!! wikitext +{| +!a +b!!c +|} +!! html/php +
a bc
+ +
a +

b!!c +

+
+ +!! html/parsoid + + +
a +

b!!c

+!! end + +!! test +Accept "!!" in table data of mixed wikitext / html syntax +!! wikitext +{| +!a +b!!c +|} +!! html+tidy + + + + + + + +
a
b!!c
+!! html/parsoid + + + +
a
b!!c
+!! end + !! test Accept empty attributes in td/th cells (td/th cells starting with leading ||) !! wikitext @@ -5746,10 +6232,37 @@ Invalid attributes in table cell (bug 1830) !! end -# The "|}" to close the table is missing from the input, so parsoid's -# *2wt modes will fail. !! test -Table security: embedded pipes (http://lists.wikimedia.org/mailman/htdig/wikitech-l/2006-April/022293.html) +Table cell attributes: Pipes protected by nowikis should be treated as a plain character +!! wikitext +{| +| title="foo" |bar +| title="foo|" |bar +| title="foo|" bar +|} +!! html/php + + + + +
bar +bar + title="foo|" bar +
+ +!! html/parsoid + + + + +
barbar title="foo|" bar
+!! end + +# See: http://lists.wikimedia.org/mailman/htdig/wikitech-l/2006-April/022293.html +# N.B. The "|}" to close the table is missing from the input, so parsoid's +# *2wt modes will fail. +!! test +Table security: embedded pipes !! options parsoid=wt2html,html2html !! wikitext @@ -5767,12 +6280,14 @@ parsoid=wt2html,html2html !! html/parsoid -
" onmouseover="alert(document.cookie)">test
+" onmouseover="alert(document.cookie)">test !! end -# FIXME: The php output is broken. +# FIXME: The output seems broken. Filed as T110268. !! test ! and || in td attributes should not be parsed as / +!! options +parsoid=wt2html !! wikitext {| | style="color: red !important;" data-contrived="put this here ||" | foo @@ -5786,7 +6301,7 @@ parsoid=wt2html,html2html !! html/parsoid - +
foo
style="color: red !important;" data-contrived="put this here foo
!! end @@ -5892,6 +6407,50 @@ Indented table markup mixed with indented pre content (proposed in bug 6200) !! end +!! test +4. Template-generated table cell attributes and cell content inside a templated table +!! wikitext +{{tbl-start}} +!align=center {{table_header_cells}} +|- +|align=center {{table_cells}} +{{tbl-end}} +!! html/php + + + + + + + + +
FooBarFoo and Baz +
FooBarFoo and Baz +
+ +!! html/parsoid + + + + +
FooBarFoo and Baz
FooBarFoo and Baz
+!! end + +## Edge case fix to prevent future regressions +!! test +T107652: s in templates that also generate table cell attributes should be rendered properly +!! wikitext +{| +|{{table_attribs_7}} +|} + +!! html/parsoid + + +
Foo[1]
+
  1. foo
+!! end + !! test Table with row followed by newlines and table heading !! wikitext @@ -6305,7 +6864,7 @@ parsoid=wt2html,wt2wt Parsoid: Default to a newline after tables in new content (bug 51219) !! options parsoid=html2wt -!! html +!! html/parsoid
foo
bar @@ -6325,7 +6884,7 @@ parsoid=html2wt Parsoid: newline inducing block nodes don't suppress !! options parsoid=html2wt -!! html +!! html/parsoid a

foo

!! wikitext a @@ -6359,9 +6918,6 @@ parsoid=wt2html,wt2wt
!! end - -# PHP throws away the (semi-broken) "foo" class here; Parsoid -# preserves it. !!test Parsoid: Recover better from broken table attributes !!options @@ -6372,7 +6928,7 @@ parsoid=wt2html foo |} !!html/php+tidy - +

foo

@@ -6387,11 +6943,28 @@ foo
!!end +!! test +Tables: Digest broken attributes on table and tr tag +!! options +parsoid=wt2html +!! wikitext +{| || |} ++ +|- || || ++ -- +|- > [ +|} +!! html + + + + +
+!! end + !! test Strip unsupported table tags !! options parsoid=html2wt -!! html +!! html/parsoid @@ -6597,8 +7170,10 @@ Link with HTML entity in suffix / tail Link with 3 brackets !! wikitext [[[Main Page]]] +Foo [[[Main Page]]] !! html

[[[Main Page]]] +Foo [[[Main Page]]]

!! end @@ -6696,7 +7271,7 @@ Namespace takes precedence over interwiki link (bug 51680) Link to namespace preferred over interwiki with correct rel attribute !! options parsoid=html2wt,html2html -!! html +!! html/parsoid

MemoryAlpha:AlphaTest

!! wikitext [[MemoryAlpha:AlphaTest]] @@ -6810,7 +7385,7 @@ Link containing a tilde !! wikitext [[Foo~bar]] !! html/php -

Foo~bar +

Foo~bar

!! html/parsoid

Foo~bar

@@ -6884,10 +7459,10 @@ Broken image links with HTML captions (bug 39700) abc

!! html/parsoid -

- - -

+

+ + +

!! end !! test @@ -7125,7 +7700,7 @@ title=[[User:test/123]]

b

!! html/parsoid -

b

+

b

!! end !! test @@ -7204,7 +7779,7 @@ mótmælenda[[söfnuður|söfnuðir]]xxx Parsoid link trail escaping !! options parsoid=html2wt,html2html -!! html +!! html/parsoid

apples

!! wikitext [[apple]]s @@ -7215,7 +7790,7 @@ Parsoid link prefix escaping !! options language=is parsoid=html2wt,html2html -!! html +!! html/parsoid

Aðrir mótmælendasöfnuður

!! wikitext Aðrir mótmælenda[[söfnuður]] @@ -7515,7 +8090,6 @@ Blah blah blah [[ es :Spanish]] [[ ZH :Chinese]] [[es:Foo_bar]] -[[es:Foo bar]] !! html/php

Blah blah blah

@@ -7524,7 +8098,21 @@ Blah blah blah - +!! end + +!! test +Space and question mark encoding in interlanguage links (T95473) +!! options +parsoid=wt2html,wt2wt,html2html +!! wikitext +Blah blah blah +[[es:Foo bar?]] +!! html/php +

Blah blah blah +

+!! html/parsoid +

Blah blah blah

+ !! end !! test @@ -7587,7 +8175,7 @@ language=ln Parsoid bug 53221: Wikilinks should be properly entity-escaped !! options parsoid=html2wt -!! html +!! html/parsoid

He&nbsp;llo He&nbsp;llo

He&nbsp;llo He&nbsp;llo

!! wikitext @@ -7693,7 +8281,7 @@ Blah blah blah

!! html/parsoid

Blah blah blah -mi:Template:Foo

+mi:Template:Foo

!! end ### @@ -7702,12 +8290,10 @@ Blah blah blah !! test 1. Simple redirect to page -!! options -parsoid !! wikitext #REDIRECT [[Main Page]] -!! html - +!! html/parsoid + !! end !! test @@ -7718,12 +8304,22 @@ parsoid !! end +# Not a valid redirect in PHP (although perhaps it was, once upon a time) +# This tests the Parsoid bail-out code. !! test 3. Other redirect variants !! wikitext #REDIRECT [[[[Bar]]]] !! html/parsoid - +
  1. REDIRECT [[[[Bar]]]]
+!! end + +!! test +4. Redirect to a templated destination +!! wikitext +#REDIRECT [[{{echo|Foo}}bar]] +!! html/parsoid + !! end !! test @@ -7732,7 +8328,7 @@ Empty redirect parsoid=wt2html,wt2wt !! wikitext #REDIRECT [[]] -!! html +!! html/parsoid
  1. REDIRECT [[]]
!! end @@ -7745,8 +8341,8 @@ Optional colon in #REDIRECT parsoid=wt2html,html2html !! wikitext #REDIRECT:[[Main Page]] -!! html - +!! html/parsoid + !! end !! test @@ -7761,8 +8357,8 @@ parsoid=wt2html,html2html #REDIRECT : [[Main Page]] -!! html - +!! html/parsoid + !! end !! test @@ -7773,89 +8369,90 @@ Piped link in #REDIRECT parsoid=wt2html !! wikitext #REDIRECT [[Main Page|bar]] -!! html - +!! html/parsoid + !! end !! test -Redirect to category +Redirect to category (T104502) !! options -parsoid=wt2wt,wt2html +parsoid=wt2html,wt2wt !! wikitext #REDIRECT [[Category:Foo]] -!! html - +!! html/parsoid + !! end !! test -Redirect to category with URL encoding +Redirect to category with URL encoding (T104502) !! options parsoid=wt2html !! wikitext #REDIRECT [[Category%3AFoo]] -!! html - +!! html/parsoid + !! end !! test Redirect to category page -!! options -parsoid !! wikitext #REDIRECT [[:Category:Foo]] -!! html - +!! html/parsoid + !! end !! test Redirect to image page (1) -!! options -parsoid !! wikitext #REDIRECT [[File:Wiki.png]] -!! html - +!! html/parsoid + !! end !! test Redirect to image page (2) -!! options -parsoid !! wikitext #REDIRECT [[Image:Wiki.png]] -!! html - +!! html/parsoid + !! end +# html2wt disabled because wts serializes as "#REDIRECT [[:en:File:Wiki.png]]" +# Next test confirms this. !! test -Redirect to language +Redirect to language (1) (T104918) !! options -parsoid +parsoid=wt2html,wt2wt,html2html !! wikitext #REDIRECT [[en:File:Wiki.png]] -!! html - +!! html/parsoid + !! end !! test -Redirect to interwiki -!! options -parsoid +Redirect to language (2) (T104918) +!! wikitext +#REDIRECT [[:en:File:Wiki.png]] +!! html/parsoid + +!! end + +!! test +Redirect to interwiki (T104918) !! wikitext #REDIRECT [[meatball:File:Wiki.png]] -!! html - +!! html/parsoid + !! end !! test Non-English #REDIRECT !! options -parsoid language=is !! wikitext #TILVÍSUN [[Main Page]] -!! html - +!! html/parsoid + !! end !! test @@ -7874,8 +8471,8 @@ some text New redirect !! options parsoid=html2wt -!! html -

Foo

+!! html/parsoid +

Foo

!! wikitext Foo #REDIRECT [[Foo]] @@ -7980,8 +8577,8 @@ Handling html with a br self-closing tag

!! html/php -


-
+


+



@@ -8225,7 +8822,7 @@ parsoid !! wikitext * !! html/parsoid -

    +
      !! end !! test @@ -8258,11 +8855,15 @@ List items are not parsed correctly following a
       block (bug 785)
       * 
      foo
      *
      bar
      * zar -!! html +!! html/php
      • foo
      • bar
      • zar
      +!! html/parsoid +
      • foo
      • +
      • bar
      • +
      • zar
      !! end !! test @@ -9306,7 +9907,7 @@ hi+world%3F%21 Magic Word: prioritize type info over data-parsoid !! options parsoid=html2wt -!! html +!! html/parsoid !! wikitext __FORCETOC__ @@ -9320,7 +9921,7 @@ parsoid=wt2wt,html2wt foo __NOTOC__ bar -!! html +!! html/parsoid foobar !! end @@ -9331,10 +9932,19 @@ parsoid=wt2wt language=de !! wikitext __NOEDITSECTION__ -!! html +!! html/parsoid !! end +!!test +__proto__ is treated as normal wikitext (T105997) +!!wikitext +__proto__ +!!html +

      __proto__ +

      +!!end + ### ### Magic links ### @@ -9342,27 +9952,33 @@ __NOEDITSECTION__ Magic links: internal link to RFC (bug 479) !! wikitext [[RFC 123]] -!! html +!! html/php

      RFC 123

      +!! html/parsoid +

      RFC 123

      !! end !! test Magic links: RFC (bug 479) !! wikitext RFC 822 -!! html +!! html/php

      RFC 822

      +!! html/parsoid +

      RFC 822

      !! end !! test Magic links: RFC (bug 65278) !! wikitext This is RFC 822 but thisRFC 822 is not RFC 822linked. -!! html +!! html/php

      This is RFC 822 but thisRFC 822 is not RFC 822linked.

      +!! html/parsoid +

      This is RFC 822 but thisRFC 822 is not RFC 822linked.

      !! end !! test @@ -9371,20 +9987,26 @@ Magic links: RFC (w/ non-newline whitespace, bug 28950/29025) RFC       822 RFC 822 -!! html +!! html/php

      RFC 822 RFC 822

      +!! html/parsoid +

      RFC       822 +RFC +822

      !! end !! test Magic links: ISBN (bug 1937) !! wikitext ISBN 0-306-40615-2 -!! html +!! html/php

      ISBN 0-306-40615-2

      +!! html/parsoid +

      ISBN 0-306-40615-2

      !! end !! test @@ -9395,7 +10017,7 @@ This is ISBN 978-0-316-09811-3 but thisISBN 978-0-316-09811-3 is not ISBN 978-0-

      This is ISBN 978-0-316-09811-3 but thisISBN 978-0-316-09811-3 is not ISBN 978-0-316-09811-3linked.

      !! html/parsoid -

      This is ISBN 978-0-316-09811-3 but thisISBN 978-0-316-09811-3 is not ISBN 978-0-316-09811-3linked.

      +

      This is ISBN 978-0-316-09811-3 but thisISBN 978-0-316-09811-3 is not ISBN 978-0-316-09811-3linked.

      !! end !! test @@ -9406,31 +10028,41 @@ ISBN 9780316098113 ISBN 978 0316098113 -!! html +!! html/php

      ISBN 978 0 316 09811 3 ISBN 9780316098113 ISBN 978 0316098113

      +!! html/parsoid +

      ISBN       978 0 316 09811 3 +ISBN +9780316098113 +ISBN 978 +0316098113

      !! end !! test Magic links: PMID incorrectly converts space to underscore !! wikitext PMID 1234 -!! html +!! html/php

      PMID 1234

      +!! html/parsoid +

      PMID 1234

      !! end !! test Magic links: PMID (bug 65278) !! wikitext This is PMID 1234 but thisPMID 1234 is not PMID 1234linked. -!! html +!! html/php

      This is PMID 1234 but thisPMID 1234 is not PMID 1234linked.

      +!! html/parsoid +

      This is PMID 1234 but thisPMID 1234 is not PMID 1234linked.

      !! end !! test @@ -9439,11 +10071,15 @@ Magic links: PMID (w/ non-newline whitespace, bug 28950/29025) PMID       1234 PMID 1234 -!! html +!! html/php

      PMID 1234 PMID 1234

      +!! html/parsoid +

      PMID       1234 +PMID +1234

      !! end ### @@ -9642,9 +10278,11 @@ Template with default value (value set) Template redirect !! wikitext {{templateredirect}} -!! html +!! html/php

      (test)

      +!! html/parsoid + !! end !! test @@ -9882,6 +10520,24 @@ Template with targets containing wikilinks

      !! end +!! article +Template:'' +!! text +bar +!! endarticle + +!! test +Templates: Double quotes as template target +!! wikitext +foo {{''}} baz +!! html/php +

      foo bar baz +

      +!! html/parsoid +

      foo bar baz +

      +!! end + !! article Template:MSGNW test !! text @@ -9892,6 +10548,7 @@ Template:MSGNW test File:Foobar.jpg + !! endarticle # hmm, fix this or just deprecate msgnw and document its behavior? @@ -9899,7 +10556,7 @@ File:Foobar.jpg msgnw keyword !! wikitext {{msgnw:MSGNW test}} -!! html +!! html/php

      ''None'' of '''this''' should be * interpreted but rather passed unmodified @@ -9907,6 +10564,7 @@ msgnw keyword <gallery> File:Foobar.jpg </gallery> +<!-- comment -->

      !! end @@ -9919,6 +10577,15 @@ int keyword

      !! end +!! test +int keyword - non-existing message +!! wikitext +{{int:var}} +!! html +

      <var> +

      +!! end + !! article Template:Includes !! text @@ -10160,7 +10827,7 @@ b}} !! end !! test -Parsoid: Merge double tds (bug 50603) +Parsoid: Merge double tds (T52603) !! options parsoid !! wikitext @@ -10174,7 +10841,7 @@ parsoid !! end !! test -Parsoid: Merge double tds in nested transclusion content (bug 50603) +Parsoid: Merge double tds in nested transclusion content (T52603) !! options parsoid !! wikitext @@ -10669,6 +11336,43 @@ Templates: Support for templates generating attributes and content
      !! end +!! test +3. Entities and nowikis inside templated attributes should be handled correctly inside templated tables +!! wikitext +{{tbl-start}} +|{{table_attribs_3}} +{{tbl-end}} +!! html/php + + +
      Foo +
      + +!! html/parsoid + + +
      Foo
      +!! end + +# T107622 +!! test +4. Entities and nowikis inside templated attributes should be handled correctly inside templated tables +!! wikitext +{| +| {{table_attribs_6}} hi +|} +!! html/php + + +
      hi +
      + +!! html/parsoid + + +
      hi
      +!! end + !!test Templates: HTML Tables: 1. Generating start of a HTML table !! wikitext @@ -10896,6 +11600,46 @@ Templates: Wiki Tables: 6. Templated tags, templated td-tags !!end +## This test case is very specific to Parsoid's internals +## and is hence only tested for Parsoid's code. Parsoid uses +## a marker tag for tags and they are expanded +## much later. We are verifying that this tag usage +## doesn't prevent foster parenting. +!!test +Templates: Wiki Tables: 7. Fosterable s should get fostered +!!wikitext +{{PartialTable}}foo +|} + + +!!html/parsoid +[1] + +
      + +
      1. foo
      +!!end + +!! test +Templates: Wiki Tables: 8. Fosterable meta-tags should get fostered +!! wikitext +{{echo| +{{{!}} +{{!}}-}} + +|foo + +{{!}}} +!! html/parsoid + + + + + +
      foo +
      +!! end + !!test Templates: Lists: Multi-line list-items via templates !! wikitext @@ -11093,41 +11837,40 @@ Parser Functions: 2. Nested use (only outermost should be marked up) !! test pre-save transform: subst: !! options -PST +pst !! wikitext {{subst:test}} -!! html +!! html/php This is a test template !! end !! test pre-save transform: normal template !! options -PST +pst !! wikitext {{test}} -!! html +!! html/php {{test}} !! end !! test pre-save transform: nonexistent template !! options -PST +pst !! wikitext {{thistemplatedoesnotexist}} -!! html +!! html/php {{thistemplatedoesnotexist}} !! end - !! test pre-save transform: subst magic variables !! options -PST +pst !! wikitext {{subst:SITENAME}} -!! html +!! html/php MediaWiki !! end @@ -11138,7 +11881,7 @@ pre-save transform: subst: templates with parameters pst !! wikitext {{subst:paramtest|param="something else"}} -!! html +!! html/php This is a test template with parameter "something else" !! end @@ -11154,11 +11897,10 @@ pre-save transform: nowiki in subst (bug 1188) pst !! wikitext {{subst:nowikitest}} -!! html +!! html/php '''not wiki''' !! end - !! article Template:commenttest !! text @@ -11171,7 +11913,7 @@ pre-save transform: comment in subst (bug 1936) pst !! wikitext {{subst:commenttest}} -!! html +!! html/php This template has in it. !! end @@ -11181,7 +11923,7 @@ pre-save transform: unclosed tag pst noxml !! wikitext '''not wiki''' -!! html +!! html/php '''not wiki''' !! end @@ -11191,7 +11933,7 @@ pre-save transform: mixed tag case pst noxml !! wikitext '''not wiki''' -!! html +!! html/php '''not wiki''' !! end @@ -11201,7 +11943,7 @@ pre-save transform: unclosed comment in pst noxml !! wikitext wikinowiki -!! html +!! html/php !!end @@ -11239,7 +11981,7 @@ pre-save transform: comment containing extension pst !! wikitext -!! html +!! html/php !!end @@ -11249,7 +11991,7 @@ pre-save transform: comment containing nowiki pst !! wikitext -!! html +!! html/php !!end @@ -11259,7 +12001,7 @@ pre-save transform: in subst (bug 3298) pst !! wikitext {{subst:Includes}} -!! html +!! html/php Foobar !! end @@ -11269,7 +12011,7 @@ pre-save transform: in subst (bug 3298) pst !! wikitext {{subst:Includes2}} -!! html +!! html/php Foo !! end @@ -11291,7 +12033,7 @@ bug 22297: safesubst: works during PST pst !! wikitext {{subst:SafeSubstTest}}{{safesubst:SubstTest}} -!! html +!! html/php FoobarFoobar !! end @@ -11327,7 +12069,7 @@ pst [[|Article (context)]] [[Bar:X (Y) Z|]] [[:Bar:X (Y) Z|]] -!! html +!! html/php [[Article (context)|Article]] [[Bar:Article|Article]] [[:Bar:Article|Article]] @@ -11348,7 +12090,7 @@ pst [[:interwiki:Article|]] [[interwiki:Bar:Article|]] [[:interwiki:Bar:Article|]] -!! html +!! html/php [[interwiki:Article|Article]] [[:interwiki:Article|Article]] [[interwiki:Bar:Article|Bar:Article]] @@ -11361,7 +12103,7 @@ pre-save transform: context links ("pipe trick") with parens in title pst title=[[Somearticle (context)]] !! wikitext [[|Article]] -!! html +!! html/php [[Article (context)|Article]] !! end @@ -11373,7 +12115,7 @@ pst title=[[Someplace, Somewhere]] [[|Otherplace]] [[Otherplace, Elsewhere|]] [[Otherplace, Elsewhere, Anywhere|]] -!! html +!! html/php [[Otherplace, Somewhere|Otherplace]] [[Otherplace, Elsewhere|Otherplace]] [[Otherplace, Elsewhere, Anywhere|Otherplace]] @@ -11386,7 +12128,7 @@ pst title=[[Someplace (IGNORED), Somewhere]] !! wikitext [[|Otherplace]] [[Otherplace (place), Elsewhere|]] -!! html +!! html/php [[Otherplace, Somewhere|Otherplace]] [[Otherplace (place), Elsewhere|Otherplace]] !! end @@ -11398,7 +12140,7 @@ pst title=[[Who, me? (context)]] !! wikitext [[|Yes, you.]] [[Me, Myself, and I (1937 song)|]] -!! html +!! html/php [[Yes, you. (context)|Yes, you.]] [[Me, Myself, and I (1937 song)|Me, Myself, and I]] !! end @@ -11409,7 +12151,7 @@ pre-save transform: context links ("pipe trick") with namespace pst title=[[Ns:Somearticle]] !! wikitext [[|Article]] -!! html +!! html/php [[Ns:Article|Article]] !! end @@ -11419,7 +12161,7 @@ pre-save transform: context links ("pipe trick") with namespace and parens pst title=[[Ns:Somearticle (context)]] !! wikitext [[|Article]] -!! html +!! html/php [[Ns:Article (context)|Article]] !! end @@ -11429,7 +12171,7 @@ pre-save transform: context links ("pipe trick") with namespace and comma pst title=[[Ns:Somearticle, Context, Whatever]] !! wikitext [[|Article]] -!! html +!! html/php [[Ns:Article, Context, Whatever|Article]] !! end @@ -11439,7 +12181,7 @@ pre-save transform: context links ("pipe trick") with namespace, comma and paren pst title=[[Ns:Somearticle, Context (context)]] !! wikitext [[|Article]] -!! html +!! html/php [[Ns:Article (context)|Article]] !! end @@ -11449,7 +12191,7 @@ pre-save transform: context links ("pipe trick") with namespace, parens and comm pst title=[[Ns:Somearticle (IGNORED), Context]] !! wikitext [[|Article]] -!! html +!! html/php [[Ns:Article, Context|Article]] !! end @@ -11464,7 +12206,7 @@ pst [[|Article(context)]] [[Bar:X(Y)Z|]] [[:Bar:X(Y)Z|]] -!! html +!! html/php [[Article(context)|Article]] [[Bar:Article(context)|Article]] [[:Bar:Article(context)|Article]] @@ -11484,7 +12226,7 @@ pst [[|Article (context)]] [[Bar:X (Y) Z|]] [[:Bar:X (Y) Z|]] -!! html +!! html/php [[Article (context)|Article]] [[Bar:Article (context)|Article]] [[:Bar:Article (context)|Article]] @@ -11504,7 +12246,7 @@ pst [[|Article(context)]] [[Bar:X(Y)Z|]] [[:Bar:X(Y)Z|]] -!! html +!! html/php [[Article(context)|Article]] [[Bar:Article(context)|Article]] [[:Bar:Article(context)|Article]] @@ -11524,7 +12266,7 @@ pst [[Bar:Article (context),context|]] [[:Bar:Article (context), context|]] [[:Bar:Article (context),context|]] -!! html +!! html/php [[Article (context), context|Article]] [[Article (context),context|Article]] [[Bar:Article (context), context|Article]] @@ -11543,7 +12285,7 @@ Empty lines are trimmed -!! html +!! html/php Empty lines are trimmed !! end @@ -11556,7 +12298,7 @@ pst * ~~~ * ~~~ * ~~~ -!! html +!! html/php * [[Special:Contributions/127.0.0.1|127.0.0.1]] * [[Special:Contributions/127.0.0.1|127.0.0.1]] * [[Special:Contributions/127.0.0.1|127.0.0.1]] @@ -11587,7 +12329,7 @@ As well as inside noinclude/onlyinclude But not inside includeonly {{subst:Foo}} -!! html +!! html/php Shall not expand: ~~~~ @@ -11642,7 +12384,7 @@ parsoid=wt2html Parsoid: Escape nowiki with trailing space in tags !! options parsoid=html2wt -!! html +!! html/parsoid

      <nowiki > foo </nowiki >

      a<nowiki />b

      c<nowiki/ >d

      @@ -11658,7 +12400,7 @@ c<nowiki/ >d Parsoid: Escape weird noWikI capitalizations !! options parsoid=html2wt -!! html +!! html/parsoid

      <noWikI > foo </NoWikI >

      !! wikitext <noWikI > foo </NoWikI > @@ -11921,7 +12663,7 @@ parsoid=wt2html,wt2wt,html2html
      This is a caption
      !! html/parsoid -
      This is a caption
      +
      This is a caption
      !! end !! test @@ -11932,7 +12674,7 @@ parsoid=wt2html,wt2wt,html2html
      This is a caption
      !! html/parsoid -
      This is a caption
      +
      This is a caption
      !! end !! test @@ -11989,7 +12731,7 @@ thumbsize=220 !! html/parsoid

      123456

      123

      456

      -

      123

      456

      +

      123

      456

      !! end !! test @@ -12011,7 +12753,7 @@ Image with multiple widths -- use last

      caption

      !! html/parsoid -

      +

      !! end !! test @@ -12027,7 +12769,7 @@ thumbsize=220

      caption

      !! html/parsoid -
      caption
      +
      caption

      !! end @@ -12043,9 +12785,9 @@ Image with width attribute at different positions
      Caption
      !! html/parsoid -
      Caption
      -
      Caption
      -
      Caption
      +
      Caption
      +
      Caption
      +
      Caption
      !! end # a sad bit of backward-compatibility @@ -12061,7 +12803,7 @@ parsoid=wt2html,wt2wt,html2html Foobar.jpg

      !! html/parsoid -

      +

      !! end !! test @@ -12100,7 +12842,22 @@ Image with link parameter, protocol-less URL target !! end !! test -Image with link parameter, wgExternalLinkTarget +Escaping non-block captions (T107435) +!! options +parsoid={ + "modes": ["wt2wt"], + "changes": [ + ["[typeof~='mw:Image']", "attr", "data-mw", "{\"caption\": \"|\"}"] + ] +} +!! wikitext +[[Image:Foobar.jpg|caption]] +!! wikitext/edited +[[Image:Foobar.jpg||]] +!! end + +!! test +Image with link parameter, wgExternalLinkTarget !! wikitext [[Image:foobar.jpg|link=http://example.com/]] !! config @@ -12187,7 +12944,7 @@ parsoid=wt2html,wt2wt,html2html
      Title
      !! html/parsoid -
      Title
      +
      Title
      !! end !! test @@ -12287,8 +13044,6 @@ parsoid=wt2html,wt2wt,html2html !! test Image with wiki markup in implicit alt -!! options -parsoid=wt2html,wt2wt,html2html !! wikitext [[Image:Foobar.jpg|testing '''bold''' in alt]] @@ -12298,8 +13053,8 @@ parsoid=wt2html,wt2wt,html2html

      testing bold in alt

      !! html/parsoid -

      -

      testing bold in alt

      +

      +

      testing bold in alt

      !! end !! test @@ -12334,9 +13089,9 @@ parsoid=wt2html,wt2wt,html2html

      caption

      !! html/parsoid -

      -

      -

      +

      +

      +

      !! end !! test @@ -12372,15 +13127,15 @@ parsoid=wt2html,wt2wt,html2html
      caption
      !! html/parsoid -
      caption
      -
      caption
      -
      caption
      +
      caption
      +
      caption
      +
      caption
      !! end ################### # Image sizing. # See https://www.mediawiki.org/wiki/Help:Images#Size_and_frame -# and https://bugzilla.wikimedia.org/show_bug.cgi?id=62258 +# and https://phabricator.wikimedia.org/T64258 # Foobar has actual size of 1941x220 # 1. Thumbs & frameless always reduce, can't be enlarged unless it's # a scalable format. @@ -12401,8 +13156,8 @@ parsoid=wt2html,wt2wt,html2html

      Foobar.jpg

      !! html/parsoid -

      -

      +

      +

      !! end !! test @@ -12418,8 +13173,8 @@ parsoid=wt2html,wt2wt,html2html

      Foobar.jpg

      !! html/parsoid -

      -

      +

      +

      !! end !! test @@ -12432,7 +13187,7 @@ parsoid=wt2html,wt2wt,html2html
      Foobar.jpg
      !! html/parsoid -
      +
      !! end !! test @@ -12448,8 +13203,8 @@ parsoid=wt2html,wt2wt,html2html
      Foobar.svg
      !! html/parsoid -
      -
      +
      +
      !! end !! test @@ -12462,7 +13217,7 @@ parsoid=wt2html,wt2wt,html2html

      Foobar.jpg

      !! html/parsoid -

      +

      !! end !! test @@ -12478,8 +13233,8 @@ parsoid=wt2html,wt2wt,html2html

      Foobar.svg

      !! html/parsoid -

      -

      +

      +

      !! end !! test @@ -12537,7 +13292,7 @@ Frameless image caption with a free URL

      http://example.com

      !! html/parsoid -

      +

      !! end !! test @@ -12550,7 +13305,7 @@ thumbsize=220 !! html/parsoid -
      http://example.com
      +
      http://example.com
      !! end !! test @@ -12564,7 +13319,7 @@ parsoid=wt2html,wt2wt,html2html !! html/parsoid -
      Alteration
      http://example.com
      +
      Alteration
      http://example.com
      !! end !! test @@ -12576,7 +13331,7 @@ SVG thumbnails with no language set
      caption
      !! html/parsoid -
      caption
      +
      caption
      !! end !! test @@ -12589,7 +13344,7 @@ parsoid=wt2html,wt2wt,html2html
      caption
      !! html/parsoid -
      caption
      +
      caption
      !! end !! test @@ -12613,7 +13368,7 @@ BUG 1887: A ISBN with a thumbnail !! html/parsoid -
      ISBN 1235467890
      +
      ISBN 1235467890
      !! end !! test @@ -12624,7 +13379,7 @@ BUG 1887: A RFC with a thumbnail
      This is RFC 12354
      !! html/parsoid -
      This is RFC 12354
      +
      This is RFC 12354
      !! end !! test @@ -12635,7 +13390,7 @@ BUG 1887: A mailto link with a thumbnail !! html/parsoid -
      Please mailto:nobody@example.com
      +
      Please mailto:nobody@example.com
      !! end # Pending resolution to bug 368 @@ -12647,7 +13402,7 @@ BUG 648: Frameless image caption with a link

      text with a link in it

      !! html/parsoid -

      +

      !! end !! test @@ -12658,7 +13413,7 @@ BUG 648: Frameless image caption with a link (suffix)

      text with a linkfoo in it

      !! html/parsoid -

      +

      !! end !! test @@ -12669,7 +13424,7 @@ BUG 648: Frameless image caption with an interwiki link

      text with a MeatBall:Link in it

      !! html/parsoid -

      +

      !! end !! test @@ -12680,7 +13435,15 @@ BUG 648: Frameless image caption with a piped interwiki link

      text with a link in it

      !! html/parsoid -

      +

      +!! end + +!! test +T107474: Frameless image caption with +!! wikitext +[[File:Foobar.jpg|text with a [[MeatBall:Link|link]] in it]] +!! html/parsoid +

      !! end !! test @@ -12691,7 +13454,7 @@ Escape HTML special chars in image alt text

      & < > "

      !! html/parsoid -

      +

      !! end !! test @@ -12702,7 +13465,7 @@ BUG 499: Alt text should have Ӓ, not &1234;

      ♀

      !! html/parsoid -

      +

      !! end !! test @@ -12726,7 +13489,7 @@ Image caption containing another image
      This is a caption with another image inside it!
      !! html/parsoid -
      This is a caption with another inside it!
      +
      This is a caption with another inside it!
      !! end !! test @@ -12750,7 +13513,7 @@ Image: caption containing leading space
      bar
      !! html/parsoid -
      bar
      +
      bar
      !!end !! test @@ -12769,7 +13532,7 @@ and some more text.]]
      This is an example image thumbnail caption with a table
      Foo Bar
      Foo1 Bar1
      and some more text.
      !! html/parsoid -
      This is an example image thumbnail caption with a table +
      This is an example image thumbnail caption with a table @@ -12786,7 +13549,7 @@ Bug 3090: External links other than http: in image captions
      This caption has irc and Secure ext links in it.
      !! html/parsoid -
      This caption has irc and Secure ext links in it.
      +
      This caption has irc and Secure ext links in it.
      !! end !! test @@ -12828,7 +13591,7 @@ language=es
      caption
      !! html/parsoid -
      caption
      +
      caption
      !! end !! test @@ -12842,7 +13605,7 @@ parsoid=wt2html,wt2wt,html2html

      caption

      !! html/parsoid -

      +

      !! end # Note that 'right' is the default alignment, despite the misspelled 'righ' below @@ -12863,9 +13626,9 @@ parsoid=wt2html,wt2wt,html2html
      caption
      !! html/parsoid -
      caption
      -
      caption
      -
      caption
      +
      caption
      +
      caption
      +
      caption
      !! end !! article @@ -12910,7 +13673,7 @@ Parsoid-specific image handling - simple image with size and middle alignment !! wikitext [[File:Foobar.jpg|middle|50px]] !! html/parsoid -

      +

      !! end !! test @@ -12921,7 +13684,7 @@ parsoid=wt2wt,wt2html,html2html !! wikitext [[Image:Foobar.jpg|middle|50px]] !! html/parsoid -

      +

      !! end !! test @@ -12930,7 +13693,7 @@ Parsoid-specific image handling - simple image with size and middle alignment !! wikitext [[File:Foobar.jpg|50px|middle]] !! html/parsoid -

      +

      !! end !! test @@ -12941,7 +13704,7 @@ parsoid=wt2html,wt2wt,html2html !! wikitext [[Image:Foobar.jpg|50px|middle]] !! html/parsoid -

      +

      !! end !! test @@ -12965,7 +13728,7 @@ Parsoid-specific image handling - thumbnail with halign, valign, and caption !! wikitext [[File:Foobar.jpg|left|baseline|thumb|caption content]] !! html/parsoid -
      caption content
      +
      caption content
      !! end !! test @@ -12974,7 +13737,7 @@ Parsoid-specific image handling - thumbnail with halign, valign, and caption !! wikitext [[File:Foobar.jpg|thumb|left|baseline|caption content]] !! html/parsoid -
      caption content
      +
      caption content
      !! end !! test @@ -12982,7 +13745,7 @@ Parsoid-specific image handling - thumbnail with specific size, halign, valign, !! wikitext [[Image:Foobar.jpg|right|middle|thumb|50x50px|caption]] !! html/parsoid -
      caption
      +
      caption
      !! end !! test @@ -13029,7 +13792,7 @@ Parsoid-specific image handling - simple image with a formatted caption !! wikitext [[File:Foobar.jpg|
      Foo Bar
      ab
      c
      ]] !! html/parsoid -

      +

      !! end !! test @@ -13050,7 +13813,7 @@ foo bar !! html/parsoid

      foo

      -
      This caption has a
      unbalanced tag in it.
      +
      This caption has a
      unbalanced tag in it.

      bar

      !! end @@ -13061,7 +13824,7 @@ parsoid=wt2html,wt2wt !! wikitext [[File:Foobar.jpg|thumb|]] !! html/parsoid -
      +
      !! end # empty captions don't get serialized unless we're in the "round trip" case @@ -13088,7 +13851,7 @@ Parsoid-specific image handling - whitespace caption !! wikitext [[File:Foobar.jpg|thumb| ]] !! html/parsoid -
      +
      !! end !! test @@ -13103,6 +13866,42 @@ bar bar

      !! end +## Edge case bugs in Parsoid from T93580 +!! test +T93580: 1. Templated inside block images +!! wikitext +[[File:Foobar.jpg|thumb|Caption with templated ref: {{echo|foo}}]] + + +!! html/parsoid +
      Caption with templated ref: [1]
      + +
      1. foo
      +!! end + +!! test +T93580: 2. inside inline images +!! wikitext +[[File:Foobar.jpg|Undisplayed caption in inline image with ref: foo]] + + +!! html/parsoid +

      + +
      1. foo
      +!! end + +!! test +T93580: 3. Templated inside inline images +!! wikitext +[[File:Foobar.jpg|Undisplayed caption in inline image with ref: {{echo|{{echo|foo}}}}]] + + +!! html/parsoid +

      + +
      1. foo
      +!! end ### ### Subpages @@ -13435,6 +14234,152 @@ Bar

      !! end +## The whitespace on the empty line is part of the test. Please do not delete +!! test +1. Categories and newlines: All preceding newlines should be suppressed (courtesy bug 87) +!! options +parsoid=wt2html,wt2wt +!! wikitext +This + +[[Category:Foo]] and this should be part of same paragraph (not an indent-pre) + +{{echo|[[Category:Foo]] and so should this!}} +!! html +

      This and this should be part of same paragraph (not an indent-pre) and so should this! +

      +!! html/parsoid +

      This + + and this should be part of same paragraph (not an indent-pre) + + and so should this!

      +!! end + +## Parsoid will not try to wt2wt this while preserving newlines because +## it suppresses excess newlines within list items -- and we don't want to +## introduce a special case just for categories, which is, in reality somewhat +## odd behavior -- categories are unlikely to be used in list items like this +## in top-level pages and are only likely to show up in template-generated +## list items where this RT-ing is a non-issue. +## +## The whitespace on the empty line is part of the test. Please do not delete +!! test +2. Categories and newlines: All preceding newlines should be suppressed (courtesy bug 87) +!! options +parsoid=wt2html +!! wikitext +* This + +[[Category:Foo]] and this should be part of the same list item +* So should this + +{{echo|[[Category:Foo]] and this should be part of the same list item}} +!! html +
      • This and this should be part of the same list item
      • +
      • So should this and this should be part of the same list item
      +!! html/parsoid +
        +
      • This and this should be part of the same list item
      • +
      • So should this and this should be part of the same list item
      • +
      +!! end + +## Newlines and categories that follow the last item of a list +## are treated differently because this (list followed by categories) +## is an extremely common pattern on wikis. +!! test +3. Categories and newlines: newline suppression for last list item should RT properly +!! wikitext +* a +* b + +[[Category:Foo]] + +[[Category:Bar]] +[[Category:Baz]] +!! html/parsoid +
      • a
      • +
      • b
      + + + + + +!! end + +!! test +4. Categories and newlines: newline suppression for last list item should RT properly +!! wikitext +* a +**** b + +[[Category:Foo]] +!! html/parsoid +
      • a +
            • b
      + + +!! end + +## only wt2html for this to make sure the algo only applies to the rightmost path +!! test +5. Categories and newlines: migrateTrailingCategories dom pass should only run on the rightmost path of nested lists +!! options +parsoid=wt2html +!! wikitext +* a +** b +[[Category:Foo]] +* c +** d +[[Category:Foo]] +!! html/parsoid +
      • a +
        • b +
      • +
      • c +
        • d
      + +!! end + +!! test +6. Categories and newlines: migrateTrailingCategories dom pass should not migrate categories not preceded by newlines +!! wikitext +* a [[Category:Foo]] +!! html/parsoid +
      • a
      +!! end + +# This test also demonstrates because of newline+category tunneling +# through the list hander, template wrapping doesn't expand to the +# containing list when the list item swallows the category. +!! test +7. Categories and newlines: migrateTrailingCategories dom pass should leave template content alone +!! wikitext +* {{echo|a +[[Category:Foo]]}} +!! html/parsoid +
      • a +
      +!! end + +!! test +8. Categories and newlines: migrateTrailingCategories dom pass should not get tripped by intervening templates +!! wikitext +* a + +{{echo|[[Category:Foo]] +[[Category:Bar]]}} +[[Category:Baz]] +!! html/parsoid +
      • a
      + + + + +!! end + !! test Parsoid: Serialize link to category page with colon escape !! options @@ -13445,20 +14390,26 @@ parsoid [[:Category:Foo|Bar]] !! html

      -Category:Foo -Bar +Category:Foo +Bar

      !! end +# html2wt localizes the "Category" namespace. +# XXX the element needs an empty data-parsoid attribute, or +# else the html2html test fails because spaces are inserted. !! test -Parsoid: Link prefix/suffixes aren't applied to category links +Link prefix/suffixes aren't applied to category links !! options parsoid=wt2html,wt2wt,html2html language=is !! wikitext x[[Category:Foo]]y -!! html -

      xy

      +!! html/php +

      xy +

      +!! html/parsoid +

      xy

      !! end !! test @@ -13484,15 +14435,15 @@ parsoid [[Category:Foo]] [[Category:Foo|Bar]] !! html - - + + !! end !! test Normalize hrefs properly before testing for invalid link targets (bug 70894) !! options parsoid=html2wt -!! html +!! html/parsoid !! wikitext [[Category:Toxine bactérienne]] @@ -13630,7 +14581,7 @@ __FORCETOC__ == Headline == == Headline 2 == == Headline == -!! html +!! html/php

      Contents

      • 1 Headline 2
      • @@ -13744,6 +14695,22 @@ TOC regression (T11764) !! end +!! test +TOC for heading containing (T96153) +!! wikitext +__FORCETOC__ +==New title== +!! html/php +

        Contents

        + +
        + +

        New title[edit]

        + +!! end + !! test TOC with wgMaxTocLevel=3 (bug 6204) !! options @@ -14376,11 +15343,8 @@ I always thought &xacute; was a cute letter.

        !! end -# TODO: generalize to PHP parser? !! test HTML5 tags -!! options -parsoid !! wikitext five @@ -14388,7 +15352,8 @@ parsoid !! html

        five -This highlighted text

        +This highlighted text +

        !! end !! test @@ -14628,13 +15593,19 @@ Attribute test: unquoted but illegal value (hash)

        !! end +# Parsoid does not serialize to empty attribute syntax, +# so wt2wt and html2wt cases are skipped !! test -Attribute test: no value +Attribute test: no value (T54330) +!! options +parsoid=wt2html,html2html !! wikitext foo -!! html -

        foo +!! html/php +

        foo

        +!! html/parsoid +

        foo

        !! end !! test @@ -14932,6 +15903,7 @@ MSIE 6 CSS safety test: sup/sub script (bug 55332) !! end +# FIXME: Parsoid fails to sanitize this! See T58846. !! test Opera -o-link CSS !! wikitext @@ -15006,7 +15978,7 @@ CSS line continuation 2 !! wikitext
        !! html -
        +
        !! end @@ -15063,7 +16035,7 @@ evil -wiki-tags without Extension:Math enabled Parser hook: empty input !! wikitext -!! html +!! html/php
         ''
         array (
        @@ -15076,7 +16048,7 @@ array (
         Parser hook: empty input using terminated empty elements
         !! wikitext
         
        -!! html
        +!! html/php
         
         NULL
         array (
        @@ -15089,7 +16061,7 @@ array (
         Parser hook: empty input using terminated empty elements (space before)
         !! wikitext
         
        -!! html
        +!! html/php
         
         NULL
         array (
        @@ -15102,7 +16074,7 @@ array (
         Parser hook: basic input
         !! wikitext
         input
        -!! html
        +!! html/php
         
         'input'
         array (
        @@ -15116,7 +16088,7 @@ array (
         Parser hook: case insensitive
         !! wikitext
         input
        -!! html
        +!! html/php
         
         'input'
         array (
        @@ -15130,7 +16102,7 @@ array (
         Parser hook: case insensitive, redux
         !! wikitext
         input
        -!! html
        +!! html/php
         
         'input'
         array (
        @@ -15145,7 +16117,7 @@ Parser hook: nested tags
         noxml
         !! wikitext
         
        -!! html
        +!! html/php
         
         ''
         array (
        @@ -15158,14 +16130,14 @@ array (
         Parser hook: basic arguments
         !! wikitext
         
        -!! html
        +!! html/php
         
         ''
         array (
           'width' => '200',
           'height' => '100',
           'depth' => '50',
        -  'square' => 'square',
        +  'square' => '',
         )
         
        @@ -15175,7 +16147,7 @@ array ( Parser hook: argument containing a forward slash (bug 5344) !! wikitext -!! html +!! html/php
         ''
         array (
        @@ -15189,7 +16161,7 @@ array (
         Parser hook: empty input using terminated empty elements (bug 2374)
         !! wikitext
         text
        -!! html
        +!! html/php
         
         NULL
         array (
        @@ -15206,14 +16178,14 @@ Parser hook: basic arguments using terminated empty elements (bug 2374)
         
         other stuff
         
        -!! html
        +!! html/php
         
         NULL
         array (
           'width' => '200',
           'height' => '100',
           'depth' => '50',
        -  'square' => 'square',
        +  'square' => '',
         )
         

        other stuff @@ -15230,7 +16202,7 @@ Parser hook: static parser hook not inside a comment !! wikitext hello, world -!! html +!! html/php

        hello, world

        !! end @@ -15241,7 +16213,7 @@ Parser hook: static parser hook inside a comment !! wikitext -!! html +!! html/php


        !! end @@ -15300,20 +16272,24 @@ Sanitizer: Closing of open but not closed tags !! test Sanitizer: Closing of closed but not open tags +!! options +parsoid=wt2html !! wikitext -!! html -

        </s> -

        +!! html/php+tidy +!! html/parsoid !! end !! test Sanitizer: Closing of closed but not open table tags +!! options +parsoid=wt2html !! wikitext Table not started -!! html -

        Table not started</td></tr></table> -

        +!! html/php+tidy +

        Table not started

        +!! html/parsoid +

        Table not started

        !! end !! test @@ -15360,7 +16336,7 @@ Sanitizer: Validating that and work, but only for Microdata
      !! html -
      +

      <meta http-equiv="refresh" content="5"> @@ -16112,7 +17088,7 @@ start ===bc=== ==c== ===ca=== -!! html +!! html/php start !! end @@ -16132,7 +17108,7 @@ start ===bc=== ==c== ===ca=== -!! html +!! html/php ==a== ===aa=== ====aaa==== @@ -16154,7 +17130,7 @@ start ===bc=== ==c== ===ca=== -!! html +!! html/php ===aa=== ====aaa==== !! end @@ -16175,7 +17151,7 @@ start ===bc=== ==c== ===ca=== -!! html +!! html/php ====aaa==== !! end @@ -16195,7 +17171,7 @@ start ===bc=== ==c== ===ca=== -!! html +!! html/php ==b== ===ba=== ===bb=== @@ -16219,7 +17195,7 @@ start ===bc=== ==c== ===ca=== -!! html +!! html/php ===ba=== !! end @@ -16239,7 +17215,7 @@ start ===bc=== ==c== ===ca=== -!! html +!! html/php ===bb=== ====bba==== !! end @@ -16260,7 +17236,7 @@ start ===bc=== ==c== ===ca=== -!! html +!! html/php ====bba==== !! end @@ -16280,7 +17256,7 @@ start ===bc=== ==c== ===ca=== -!! html +!! html/php ===bc=== !! end @@ -16300,7 +17276,7 @@ start ===bc=== ==c== ===ca=== -!! html +!! html/php ==c== ===ca=== !! end @@ -16321,7 +17297,7 @@ start ===bc=== ==c== ===ca=== -!! html +!! html/php ===ca=== !! end @@ -16341,7 +17317,7 @@ start ===bc=== ==c== ===ca=== -!! html +!! html/php !! end !! test @@ -16352,7 +17328,7 @@ section=1 ==a== ==bogus== not a legal section ==b== -!! html +!! html/php ==a== ==bogus== not a legal section !! end @@ -16365,7 +17341,7 @@ section=2 ==a== ==bogus== not a legal section ==b== -!! html +!! html/php ==b== !! end @@ -16377,7 +17353,7 @@ section=1 ==a== ==b== ==c== -!! html +!! html/php ==a== !! end @@ -16389,7 +17365,7 @@ section=2 ==a== ==b== ==c== -!! html +!! html/php ==b== !! end @@ -16401,7 +17377,7 @@ section=1 ==a== ==bogus== not a legal section ==b== -!! html +!! html/php ==a== ==bogus== not a legal section !! end @@ -16414,11 +17390,10 @@ section=2 ==a== ==bogus== not a legal section ==b== -!! html +!! html/php ==b== !! end - # Formerly testing for bug 2587, now resolved by the use of unmarked sections # instead of respecting commented sections !! test @@ -16428,7 +17403,7 @@ section=1 !! wikitext ==sec1== ==sec2== -!! html +!! html/php ==sec2== !!end @@ -16439,11 +17414,10 @@ section=2 !! wikitext ==sec1== ==sec2== -!! html +!! html/php !!end - # Formerly testing for bug 2607, now resolved by the use of unmarked sections # instead of respecting HTML-style headings !! test @@ -16457,7 +17431,7 @@ unmarked one ==2== two -!! html +!! html/php ==1== one !! end @@ -16473,7 +17447,7 @@ unmarked one ==2== two -!! html +!! html/php ==2== two !! end @@ -16487,7 +17461,7 @@ section=1 !! wikitext ==unmarked== ==marked== -!! html +!! html/php ==marked== !!end @@ -16502,7 +17476,7 @@ The line above must have a trailing space === But just in case it doesn't... -!! html +!! html/php === But just in case it doesn't... @@ -16524,7 +17498,7 @@ start ===bc=== ==c== ===ca=== -!! html +!! html/php xxx ==a== @@ -16555,7 +17529,7 @@ start ===bc=== ==c== ===ca=== -!! html +!! html/php start xxx @@ -16584,7 +17558,7 @@ start ===bc=== ==c== ===ca=== -!! html +!! html/php start ==a== xxx @@ -16614,7 +17588,7 @@ start ===bc=== ==c== ===ca=== -!! html +!! html/php start ==a== ===aa=== @@ -16645,7 +17619,7 @@ start ===bc=== ==c== ===ca=== -!! html +!! html/php start ==a== ===aa=== @@ -16672,7 +17646,7 @@ start ===bc=== ==c== ===ca=== -!! html +!! html/php start ==a== ===aa=== @@ -16703,7 +17677,7 @@ start ===bc=== ==c== ===ca=== -!! html +!! html/php start ==a== ===aa=== @@ -16733,7 +17707,7 @@ start ===bc=== ==c== ===ca=== -!! html +!! html/php start ==a== ===aa=== @@ -16764,7 +17738,7 @@ start ===bc=== ==c== ===ca=== -!! html +!! html/php start ==a== ===aa=== @@ -16795,7 +17769,7 @@ start ===bc=== ==c== ===ca=== -!! html +!! html/php start ==a== ===aa=== @@ -16824,7 +17798,7 @@ start ===bc=== ==c== ===ca=== -!! html +!! html/php start ==a== ===aa=== @@ -16846,7 +17820,7 @@ replace=2,"xxx" Preformatted initial line ==a== ===a=== -!! html +!! html/php Preformatted initial line ==a== xxx @@ -16860,7 +17834,7 @@ section=1 !! wikitext ==a== a -!! html +!! html/php ==a== a !! end @@ -16872,7 +17846,7 @@ section=1 !! wikitext ==a== a -!! html +!! html/php ==a== a !! end @@ -16890,7 +17864,7 @@ noxml section=2 == Section Two == stuff -!! html +!! html/php == Section Two == stuff !! end @@ -16907,7 +17881,7 @@ noxml replace=2,"xxx" == Section Two == stuff -!! html +!! html/php == Section One ==

       =======
      @@ -16917,7 +17891,6 @@ xxx
       !! end
       
       
      -
       !! test
       Handling of 
       in URLs
       !! wikitext
      @@ -17338,12 +18311,44 @@ parsoid=wt2html,wt2wt,html2html
       

      îî

      !! end +# See: http://www.w3.org/TR/html5/syntax.html#character-references +# Note that U+000C (form feed) is not a valid XML character, so +# it is banned even though allowed in HTML5. +!! test +Illegal character references (T106578) +!! wikitext +; Null: � +; FF: +; CR: +; Control (low):  +; Control (high):  Ÿ +; Surrogate: �� +; This is an okay astral character: 💩 +!! html+tidy +
      +
      Null
      +
      &#00;
      +
      FF
      +
      &#xC;
      +
      CR
      +
      &#xD;
      +
      Control (low)
      +
      &#8;
      +
      Control (high)
      +
      &#x7F; &#x9F;
      +
      Surrogate
      +
      &#xD83D;&#xDCA9;
      +
      This is an okay astral character
      +
      💩
      +
      +!! end + !! test __FORCETOC__ override !! wikitext __NEWSECTIONLINK__ __FORCETOC__ -!! html +!! html/php


      !! end @@ -17358,7 +18363,7 @@ ISBN 978-0-1234-56 789 !! html+tidy

      ISBN 978-0-1234-56 789

      !! html/parsoid -

      ISBN 978-0-1234-56 789

      +

      ISBN 978-0-1234-56 789

      !! end !! test @@ -17378,24 +18383,34 @@ ISBN ISBN 1234567890

      ISBN ISBN 1234567890

      !! html/parsoid -

      ISBN ISBN 1234567890

      +

      ISBN ISBN 1234567890

      !! end +# Uppercase X and lowercase x as well !! test ISBN with an X !! wikitext ISBN 3-462-04561-X +ISBN 3-462-04561-x ISBN 080442957X +ISBN 080442957x ISBN 978080442957X +ISBN 978080442957x !! html/php

      ISBN 3-462-04561-X +ISBN 3-462-04561-x ISBN 080442957X +ISBN 080442957x ISBN 978080442957X +ISBN 978080442957x

      !! html/parsoid -

      ISBN 3-462-04561-X -ISBN 080442957X -ISBN 978080442957X

      +

      ISBN 3-462-04561-X +ISBN 3-462-04561-x +ISBN 080442957X +ISBN 080442957x +ISBN 978080442957X +ISBN 978080442957x

      !! end !! test @@ -17406,7 +18421,7 @@ ISBN 1234567890

      ISBN 1234567890

      !! html/parsoid -

      ISBN 1234567890

      +

      ISBN 1234567890

      !! end !! test @@ -17417,7 +18432,7 @@ Bug 22905: followed by ISBN followed by

      (fr) ISBN 2753300917 example.com

      !! html/parsoid -

      (fr) ISBN 2753300917 example.com

      +

      (fr) ISBN 2753300917 example.com

      !! end !! test @@ -17548,7 +18563,7 @@ Images with the "|" character in the comment
      An external URL
      !! html/parsoid -
      An external URL
      +
      An external URL
      !! end !! test @@ -17704,7 +18719,7 @@ Don't fall for the self-closing div MSGNW magic word !! wikitext {{MSGNW:msg}} -!! html +!! html/php

      [[:Template:Msg]]

      !! end @@ -18293,6 +19308,61 @@ Raw: -{R|zh:China;zh-tw:Taiwan}-

      !! end +!! test +Strings evaluating false shouldn't be ignored by Language converter (T51072) +!! options +language=zh variant=zh-cn +!! input +-{zh-cn:0;zh-sg:1;zh-tw:2;zh-hk:3}- +!! result +

      0 +

      +!! end + +!! test +Conversion rules from [numeric-only string] to [something else] (T48634) +!! options +language=zh variant=zh-cn +!! input +-{H|0=>zh-cn:B}--{H|0=>zh-cn:C;0=>zh-cn:D}--{H|0=>zh-hans:A}-012345-{A|zh-tw:0;zh-cn:E;}-012345 +!! result +

      D12345EE12345 +

      +!! end + +!! test +Bidirectional converter rule entries with an empty value should be ignored (T53551) +!! options +language=zh variant=zh-cn +!! input +-{H|zh-cn:foo;zh-tw:;}-foobar +!! result +

      foobar +

      +!! end + +!! test +Unidirectional converter rule entries with an empty "from" string should be ignored (T53551) +!! options +language=zh variant=zh-cn +!! input +-{H|=>zh-cn:foo;}-foobar +!! result +

      foobar +

      +!! end + +!! test +Empty converter rule entries shouldn't be inserted into the conversion table (T53551) +!! options +language=zh variant=zh-cn +!! input +-{H|}-foobar +!! result +

      foobar +

      +!! end + !! test Nested using of manual convert syntax !! options @@ -19038,7 +20108,7 @@ percent-encoding and + signs in comments (Bug 26410) comment !! wikitext [[ABC%33D% ++]] [[ABC%33D% ++|+%20]] -!! html +!! html/php ABC3D% ++ +%20 !! end @@ -19082,7 +20152,7 @@ wgAllowDisplayTitle=true wgRestrictDisplayTitle=false !! wikitext this is not the the title -!! html +!! html/php Parser test

      this is not the the title

      @@ -19099,7 +20169,7 @@ wgRestrictDisplayTitle=false !! wikitext this is not the the title {{DISPLAYTITLE:whatever}} -!! html +!! html/php whatever

      this is not the the title

      @@ -19116,7 +20186,7 @@ wgRestrictDisplayTitle=true !! wikitext this is not the the title {{DISPLAYTITLE:whatever}} -!! html +!! html/php Screen

      this is not the the title

      @@ -19133,7 +20203,7 @@ wgRestrictDisplayTitle=true !! wikitext this is not the the title {{DISPLAYTITLE:screen}} -!! html +!! html/php screen

      this is not the the title

      @@ -19149,7 +20219,7 @@ wgAllowDisplayTitle=false !! wikitext this is not the the title {{DISPLAYTITLE:screen}} -!! html +!! html/php Screen

      this is not the the title Template:DISPLAYTITLE:screen @@ -19165,7 +20235,7 @@ title=[[Screen]] wgAllowDisplayTitle=false !! wikitext this is not the the title -!! html +!! html/php Screen

      this is not the the title

      @@ -19182,7 +20252,7 @@ wgRestrictDisplayTitle=true !! wikitext this is not the the title {{DISPLAYTITLE:screen}} -!! html +!! html/php screen

      this is not the the title

      @@ -19199,7 +20269,7 @@ wgRestrictDisplayTitle=true !! wikitext this is not the the title {{DISPLAYTITLE:screen}} -!! html +!! html/php screen

      this is not the the title

      @@ -19224,7 +20294,7 @@ Page status indicators: Weird syntaxes that are okay showindicators !! wikitext - + !! html empty= name= @@ -19287,7 +20357,7 @@ preload: check and preload !! wikitext Hello cruelkind world. -!! html +!! html/php Hello kind world. !! end @@ -19297,7 +20367,7 @@ preload: check preload !! wikitext Goodbye Hello world -!! html +!! html/php Hello world !! end @@ -19307,7 +20377,7 @@ preload: can pass tags through if we want to preload !! wikitext <includeonly>Hello world</includeonly> -!! html +!! html/php Hello world !! end @@ -19317,7 +20387,7 @@ preload: check that it doesn't try to do tricks preload !! wikitext * ''{{world}}'' {{subst:How are you}}{{ {{{|safesubst:}}} #if:1|2|3}} -!! html +!! html/php * ''{{world}}'' {{subst:How are you}}{{ {{{|safesubst:}}} #if:1|2|3}} !! end @@ -19368,7 +20438,10 @@ percent-encoding and + signs in internal links (Bug 26410) 3E 3E+

      !! html/parsoid -

      User:+% Page+title% %+ %20 %+ %+r % + 3E 3E+

      +

      User:+% Page+title% +%+ %20 %+ %+r +% + +3E 3E+

      !! end !! test @@ -19382,7 +20455,7 @@ Special characters in embedded file links (bug 27679)

      !! html/parsoid

      -

      +

      !! end !! test @@ -19653,14 +20726,18 @@ __TOC__

      [edit]

      !! end +# Don't expect Parsoid to roundtrip this until the php parser comes closer to +# html5 tag parsing. !! test Tags with parameters in TOC +!! options +parsoid=wt2html !! wikitext __TOC__ == Hello == == Evilbye == -!! html +!! html/php

      Contents

      • 1 Hello
      • @@ -19669,8 +20746,13 @@ __TOC__

      Hello[edit]

      -

      b">Evilbye[edit]

      +

      b">Evilbye[edit]

      + +!! html/parsoid + +

      Hello

      +

      b">Evilbye

      !! end !! test @@ -19775,10 +20857,12 @@ Strip marker in urlencode {{urlencode:xy}} {{urlencode:xy|wiki}} {{urlencode:xy|path}} +{{urlencode:x
      two
      y}} !! html

      xy xy xy +xy

      !! end @@ -20137,10 +21221,35 @@ parsoid=wt2html,wt2wt [[Image:Foobar.jpg|right|300px]] !! html/parsoid +

      foo

      -
      caption
      +
      caption

      bar

      -
      +
      +!! end + +!! test +3. Bad treebuilder fixup of formatting elt is cleaned up +!! options +parsoid=wt2html,wt2wt +!! wikitext +'''foo[[File:Foobar.jpg|thumb|caption]]bar''' +!! html/parsoid +

      foo

      +
      caption
      +

      bar

      +!! end + +!! test +4. Bad treebuilder fixup of formatting elt is cleaned up: formatting tags around captionless images are ignored +!! options +parsoid=wt2html,wt2wt +!! wikitext +'''[[Image:Foobar.jpg|right|300px]]''' +!! html/parsoid +

      +
      +

      !! end #### ---------------------------------------------------------------- @@ -20159,13 +21268,13 @@ B foo C !! html -

      A [1] -B [2] -C [3]

      -
        -
      1. foo
      2. -
      3. foo
      4. -
      5. +

        A [1] +B [2] +C [3]

        +
          +
        1. foo
        2. +
        3. foo
        4. +
        !!end @@ -20178,10 +21287,10 @@ A foo B !! html -

        A [1] -B [1]

        -
          -
        1. 1.0 1.1 foo
        2. +

          A [1] +B [1]

          +
            +
          1. 1 2 foo
          !!end @@ -20195,11 +21304,11 @@ B C !! html -

          A [1] -B [1] -C [1]

          -
            -
          1. 1.0 1.1 1.2 foo
          2. +

            A [1] +B [1] +C [1]

            +
              +
            1. 1 2 3 foo
            !!end @@ -20212,9 +21321,9 @@ parsoid A foo !! html -

            A [1]

            -
              -
            1. foo
            2. +

              A [1]

              +
                +
              1. foo
              !!end @@ -20229,10 +21338,10 @@ A !! html -

              A [1]

              +

              A [1]

              -
                -
              1. This is a bolded link and this is a transclusion +
                  +
                1. This is a bolded link and this is a transclusion
                !!end @@ -20250,10 +21359,10 @@ A !! html -

                A [1]

                +

                A [1]

                -
                  -
                1. foo +
                    +
                  1. foo bar baz
                  2. @@ -20280,10 +21389,10 @@ booz !! html -

                    A [1]

                    +

                    A [1]

                    -
                      -
                    1. foo +
                        +
                      1. foo bar @@ -20306,9 +21415,9 @@ A foo {{echo| B C}} !! html -

                        A [1] B C}}

                        -
                          -
                        1. foo {{echo|
                        2. +

                          A [1] B C}}

                          +
                            +
                          1. foo {{echo|
                          !!end @@ -20320,9 +21429,9 @@ parsoid A foo +

                          A [1] B C

                          +
                            +
                          1. foo
                          !!end @@ -20335,11 +21444,11 @@ A foo B C !! html -

                          A [1] B C

                          +

                          A [1] B C

                          -
                            -
                          1. foo
                          2. +
                              +
                            1. foo
                            !!end @@ -20352,37 +21461,35 @@ A foo B C bar D !! html -

                            A [1] B -C [2] D

                            -
                              -
                            1. foo
                            2. -
                            3. bar
                            4. +

                              A [1] B +C [2] D

                              +
                                +
                              1. foo
                              2. +
                              3. bar
                              !!end !!test Ref: 12. ref-tags act as trailing newline migration barrier -!!options -parsoid !! wikitext -a +a -b +b c -!! html -

                              a

                              +!! html/parsoid +

                              a

                              -

                              b [1] -[2]

                              +

                              b [1] +[2]

                              c

                              -
                                -
                              1. -
                              +
                                +
                              1. +
                              !!end !!test @@ -20395,11 +21502,11 @@ parsoid
                              B !! html -

                              [1] A -[2] B

                              -
                                -
                              1. foo
                              2. -
                              3. bar +

                                [1] A +[2] B

                                +
                                  +
                                1. foo
                                2. +
                                3. bar
                                !!end @@ -20413,10 +21520,10 @@ parsoid !! html -

                                [1] +

                                [1]

                                -
                                  -
                                1. foo <ref>bar</ref> baz
                                2. +
                                    +
                                  1. foo <ref>bar</ref> baz
                                  !!end @@ -20430,10 +21537,10 @@ B1 B2 bar !! html -

                                  A1 [1] A2 [1] -B1 [2] B2 [2]

                                  +

                                  A1 [1] A2 [1] +B1 [2] B2 [2]

                                  -
                                  1. 1.0 1.1 foo
                                  2. 2.0 2.1 bar
                                  3. +
                                    1. 1 2 foo
                                    2. 1 2 bar
                                    !!end @@ -20447,9 +21554,9 @@ A foo !! html -

                                    A [1]

                                    -
                                      -
                                    1. foo
                                    +

                                    A [1]

                                    +
                                      +
                                    1. foo
                                    !!end !!test @@ -20461,11 +21568,11 @@ parsoid !!html -

                                    [1] +

                                    [1]

                                    -
                                      -
                                    1. foo
                                    2. +
                                        +
                                      1. foo
                                      !!end @@ -20478,11 +21585,11 @@ parsoid !!html -

                                      [1] +

                                      [1]

                                      -
                                        -
                                      1. foo
                                      2. +
                                          +
                                        1. foo
                                        !!end @@ -20495,10 +21602,10 @@ parsoid !! html -

                                        1 [1] 2 [1] +

                                        1 [1] 2 [1]

                                        -
                                          -
                                        1. 1.0 1.1 foo
                                        2. +
                                            +
                                          1. 1 2 foo
                                          !!end @@ -20513,28 +21620,24 @@ C !! html -

                                          A [1] -B [1] -C [1]

                                          +

                                          A [1] +B [1] +C [1]

                                          -
                                          1. 1.0 1.1 1.2 Foo one
                                          2. +
                                            1. 1 2 3 Foo one
                                            !!end !!test References: 1. references tag without any refs should be handled properly -!!options -parsoid !! wikitext -!! html -
                                              +!! html/parsoid +
                                                !!end !!test References: 2. references tag with group only outputs references from that group -!!options -parsoid !! wikitext A foo B bar @@ -20543,26 +21646,24 @@ C baz -!! html -

                                                A [a 1] -B [b 1] -C [1]

                                                +!! html/parsoid +

                                                A [a 1] +B [b 1] +C [1]

                                                -
                                                  -
                                                1. foo
                                                2. +
                                                    +
                                                  1. foo
                                                  -
                                                    -
                                                  1. baz
                                                  2. +
                                                      +
                                                    1. baz
                                                    -
                                                      -
                                                    1. bar
                                                    2. +
                                                        +
                                                      1. bar
                                                      !!end !!test References: 3. ref list should be cleared after processing references -!!options -parsoid !! wikitext A foo @@ -20571,23 +21672,21 @@ A foo B bar -!! html -

                                                      A [1]

                                                      +!! html/parsoid +

                                                      A [1]

                                                      -
                                                      1. foo
                                                      2. +
                                                        1. foo
                                                        -

                                                        B [1]

                                                        +

                                                        B [1]

                                                        -
                                                          -
                                                        1. bar
                                                        2. +
                                                            +
                                                          1. bar
                                                          !!end !!test References: 4. only referenced group should be cleared after processing references -!!options -parsoid !! wikitext A afoo B bfoo @@ -20597,23 +21696,21 @@ B bfoo C cfoo -!! html -

                                                          A [a 1] -B [1]

                                                          +!! html/parsoid +

                                                          A [a 1] +B [1]

                                                          -
                                                          1. afoo
                                                          2. +
                                                            1. afoo
                                                            -

                                                            C [2]

                                                            +

                                                            C [2]

                                                            -
                                                            1. bfoo
                                                            2. cfoo
                                                            3. +
                                                              1. bfoo
                                                              2. cfoo
                                                              !!end !!test References: 5. ref tags in references should be processed while ignoring all other content -!!options -parsoid !! wikitext A B bar @@ -20622,30 +21719,26 @@ B bar foo This should just get lost. -!! html -

                                                              A [1] -B [2]

                                                              +!! html/parsoid +

                                                              A [1] +B [2]

                                                              -
                                                              1. foo
                                                              2. bar
                                                              3. +
                                                                1. foo
                                                                2. bar
                                                                !!end !!test References: 6. from a transclusion -!!options -parsoid !! wikitext Foo {{echo|}} -!! html -

                                                                [1]

                                                                1. Foo
                                                                2. +!! html/parsoid +

                                                                  [1]

                                                                  1. Foo
                                                                  !!end !! test References: 7. Multiple references tags (one without and one with nested refs) should be correctly handled -!! options -parsoid !! wikitext A foo bar for a B @@ -20655,30 +21748,28 @@ B foo -!! html -

                                                                  A [1] -B [X 1] +!! html/parsoid +

                                                                  A [1] +B [X 1]

                                                                  -
                                                                    -
                                                                  1. foo bar for a
                                                                  2. +
                                                                      +
                                                                    1. foo bar for a
                                                                    -
                                                                      -
                                                                    1. foo
                                                                    2. +
                                                                        +
                                                                      1. foo
                                                                      !! end !! test References: 8. T88019: Remove s from templates inside that's itself inside a template -!! options -parsoid !! wikitext X{{echo|foo {{echo|bar}} and {{echo|baz}} boo}} -!! html -

                                                                      X[1]

                                                                      -
                                                                      1. foo bar and baz boo
                                                                      2. +!! html/parsoid +

                                                                        X[1]

                                                                        +
                                                                        1. foo bar and baz boo
                                                                        !!end @@ -20688,18 +21779,16 @@ X{{echo|foo {{echo|bar}} and {{echo|baz}} boo}} # wt2wt. !! test References: 9. Generate missing references list at the end -!! options -parsoid !! wikitext A foo B bar -!! html -

                                                                        A [1] B [inexistent 1]

                                                                        -
                                                                          -
                                                                        1. foo
                                                                        2. +!! html/parsoid +

                                                                          A [1] B [inexistent 1]

                                                                          +
                                                                            +
                                                                          1. foo
                                                                          -
                                                                            -
                                                                          1. bar
                                                                          2. +
                                                                              +
                                                                            1. bar
                                                                            !! end @@ -20721,15 +21810,13 @@ A foo !! test Entities in ref name -!! options -parsoid !! wikitext hi -!! html -

                                                                            [1]

                                                                            -
                                                                              -
                                                                            1. hi
                                                                            2. +!! html/parsoid +

                                                                              [1]

                                                                              +
                                                                                +
                                                                              1. hi
                                                                              !! end @@ -20743,10 +21830,10 @@ parsoid=wt2html afoo -!! html -

                                                                              a[1]

                                                                              -
                                                                                -
                                                                              1. foo
                                                                              +!! html/parsoid +

                                                                              a[1]

                                                                              +
                                                                                +
                                                                              1. foo
                                                                              !! end !! test @@ -20756,8 +21843,8 @@ parsoid=wt2wt,html2wt !! wikitext foo -!! html -foo
                                                                                +!! html/parsoid +foo
                                                                                  !! end #### ---------------------------------------------------------------- @@ -20864,23 +21951,23 @@ Empty TR nodes should not be stripped if they have any attributes set !! test Headings: 0. Unnested !! options -parsoid +parsoid=html2wt +!! html/parsoid +

                                                                                  =foo=

                                                                                  + +

                                                                                  =foo= + +=foo=

                                                                                  + +

                                                                                  =fooa=

                                                                                  !! wikitext =foo= - =foo= + =foo= =foo= =foo''a''= -!! html -

                                                                                  =foo=

                                                                                  - -

                                                                                  =foo= - -=foo=

                                                                                  - -

                                                                                  =fooa=

                                                                                  !!end # New headings and existing headings are handled differently @@ -20888,7 +21975,7 @@ parsoid Headings: 1. Nested inside html !! options parsoid=html2wt -!! html +!! html/parsoid

                                                                                  =foo=

                                                                                  =foo=

                                                                                  =foo=

                                                                                  @@ -20919,7 +22006,7 @@ parsoid=html2wt Headings: 2. Outside heading nest on a single line

                                                                                  foo

                                                                                  *bar !! options parsoid=html2wt -!! html +!! html/parsoid

                                                                                  foo

                                                                                  *bar

                                                                                  foo

                                                                                  =bar

                                                                                  foo

                                                                                  =bar= @@ -20937,15 +22024,26 @@ parsoid=html2wt !! test Headings: 3. Nested inside html with wikitext split by html tags !! options -parsoid=html2wt,wt2wt -!! wikitext -= ='''bold'''foo= = +parsoid=html2wt !! html/parsoid

                                                                                  =boldfoo=

                                                                                  +!! wikitext += ='''bold'''foo= = !!end !! test Headings: 4a. No escaping needed (testing just h1 and h2) +!! options +parsoid=html2wt +!! html/parsoid +

                                                                                  =foo

                                                                                  +

                                                                                  foo=

                                                                                  +

                                                                                  =foo=

                                                                                  +

                                                                                  =foo= bar

                                                                                  +

                                                                                  =foo

                                                                                  +

                                                                                  foo=

                                                                                  +

                                                                                  =

                                                                                  +

                                                                                  =foo=

                                                                                  !! wikitext = =foo = @@ -20962,22 +22060,13 @@ Headings: 4a. No escaping needed (testing just h1 and h2) = = = = ''=''foo= = -!! html/parsoid -

                                                                                  =foo

                                                                                  -

                                                                                  foo=

                                                                                  -

                                                                                  =foo=

                                                                                  -

                                                                                  =foo= bar

                                                                                  -

                                                                                  =foo

                                                                                  -

                                                                                  foo=

                                                                                  -

                                                                                  =

                                                                                  -

                                                                                  =foo=

                                                                                  !!end !! test Headings: 4b. No escaping needed (inside p-tags) !! options parsoid=html2wt -!! html +!! html/parsoid

                                                                                  === =foo= x =foo= @@ -20991,7 +22080,19 @@ parsoid=html2wt !! test Headings: 5. Empty headings !! options -parsoid +parsoid=html2wt +!! html/parsoid +

                                                                                  + +

                                                                                  + +

                                                                                  + +

                                                                                  + +
                                                                                  + +
                                                                                  !! wikitext == @@ -21004,92 +22105,81 @@ parsoid ========== ============ -!! html -

                                                                                  -

                                                                                  -

                                                                                  -

                                                                                  -
                                                                                  -
                                                                                  !!end !! test Headings: 6a. Heading chars in SOL context (with trailing spaces) !! options -parsoid +parsoid=html2wt +!! html/parsoid +

                                                                                  =a=

                                                                                  + +

                                                                                  =a=

                                                                                  + +

                                                                                  =a=

                                                                                  !! wikitext =a= =a= =a= - -=a= -!! html -

                                                                                  =a=

                                                                                  -

                                                                                  =a=

                                                                                  -

                                                                                  =a=

                                                                                  -

                                                                                  =a=

                                                                                  !!end !! test Headings: 6b. Heading chars in SOL context (with trailing newlines) !! options -parsoid -!! wikitext -=a= -b - -=a= -b - -=a= -b - -=a= -b -!! html +parsoid=html2wt +!! html/parsoid

                                                                                  =a= b

                                                                                  +

                                                                                  =a= b

                                                                                  +

                                                                                  =a= b

                                                                                  -

                                                                                  =a= -b

                                                                                  -

                                                                                  +!! wikitext +=a= +b + +=a= +b + +=a= +b !!end !! test Headings: 6c. Heading chars in SOL context (leading newline break) !! options -parsoid +parsoid=html2wt +!! html/parsoid +

                                                                                  a +=b=

                                                                                  !! wikitext a =b= -!! html -

                                                                                  a -=b=

                                                                                  !!end !! test Headings: 6d. Heading chars in SOL context (with interspersed comments) !! options -parsoid +parsoid=html2wt +!! html/parsoid +

                                                                                  =a=

                                                                                  + +

                                                                                  =a=

                                                                                  !! wikitext =a= =a= -!! html -

                                                                                  =a=

                                                                                  -

                                                                                  =a=

                                                                                  !!end !! test Headings: 6d. Heading chars in SOL context (No escaping needed) !! options parsoid=html2wt -!! html +!! html/parsoid =a=
                                                                                  b
                                                                                  !! wikitext =a=
                                                                                  b
                                                                                  @@ -21099,11 +22189,11 @@ parsoid=html2wt Headings: 7. Insert a newline between new content and headings !! options parsoid=html2wt -!! html +!! html/parsoid

                                                                                  NEW

                                                                                  new

                                                                                  -

                                                                                  A

                                                                                  -

                                                                                  a

                                                                                  +

                                                                                  A

                                                                                  +

                                                                                  a

                                                                                  !! wikitext == NEW == new @@ -21126,23 +22216,38 @@ a !! test Lists: 0. Outside nests +!! options +parsoid=html2wt +!! html/parsoid +

                                                                                  *foo

                                                                                  + +

                                                                                  #foo

                                                                                  + +

                                                                                  ;Foo:bar

                                                                                  !! wikitext *foo #foo -;Foo:bar -!! html -

                                                                                  *foo -

                                                                                  #foo -

                                                                                  ;Foo:bar -

                                                                                  +;Foo:bar !!end !! test Lists: 1. Nested inside html -!! wikitext -**foo +!! options +parsoid=html2wt +!! html/parsoid +
                                                                                  • *foo
                                                                                  +
                                                                                  • #foo
                                                                                  +
                                                                                  • :foo
                                                                                  +
                                                                                  • ;foo
                                                                                  +
                                                                                  1. *foo
                                                                                  +
                                                                                  1. #foo
                                                                                  +
                                                                                  1. :foo
                                                                                  +
                                                                                  1. ;foo
                                                                                  + +!! wikitext +**foo *#foo @@ -21157,20 +22262,19 @@ Lists: 1. Nested inside html #:foo #;foo -!! html -
                                                                                  • *foo
                                                                                  -
                                                                                  • #foo
                                                                                  -
                                                                                  • :foo
                                                                                  -
                                                                                  • ;foo
                                                                                  -
                                                                                  1. *foo
                                                                                  -
                                                                                  1. #foo
                                                                                  -
                                                                                  1. :foo
                                                                                  -
                                                                                  1. ;foo
                                                                                  - !!end !! test Lists: 2. Inside definition lists +!! options +parsoid=html2wt +!! html/parsoid +
                                                                                  ;foo
                                                                                  +
                                                                                  :foo
                                                                                  +
                                                                                  :foo
                                                                                  +
                                                                                  bar
                                                                                  +
                                                                                  :foo
                                                                                  + !! wikitext ;;foo @@ -21180,40 +22284,27 @@ Lists: 2. Inside definition lists :bar ::foo -!! html -
                                                                                  ;foo
                                                                                  -
                                                                                  :foo
                                                                                  -
                                                                                  :foo
                                                                                  -
                                                                                  bar
                                                                                  -
                                                                                  :foo
                                                                                  - !!end !! test Lists: 3. Only bullets at start of text should be escaped +!! options +parsoid=html2wt +!! html/parsoid +
                                                                                  • *foo*bar
                                                                                  +
                                                                                  • *fooit*bar
                                                                                  + !! wikitext **foo*bar **foo''it''*bar -!! html -
                                                                                  • *foo*bar
                                                                                  -
                                                                                  • *fooit*bar
                                                                                  - !!end !! test Lists: 4. No escapes needed !! options -parsoid -!! wikitext -*foo*bar - -*''foo''*bar - -*[[Foo]]: bar - -*[[Foo]]*bar -!! html +parsoid=html2wt +!! html/parsoid
                                                                                  • foo*bar
                                                                                  • @@ -21230,10 +22321,29 @@ parsoid
                                                                                  • Foo*bar
                                                                                  +!! wikitext +*foo*bar + +*''foo''*bar + +*[[Foo]]: bar + +*[[Foo]]*bar !!end !! test Lists: 5. No unnecessary escapes +!! options +parsoid=html2wt +!! html/parsoid +
                                                                                  • bar [[foo]]
                                                                                  +
                                                                                  • =bar [[foo]]
                                                                                  +
                                                                                  • [[bar [[foo]]
                                                                                  +
                                                                                  • ]]bar [[foo]]
                                                                                  +
                                                                                  • =bar foo]]=
                                                                                  +
                                                                                  • : a
                                                                                  +
                                                                                  • * foo
                                                                                  + !! wikitext * bar [[foo]] @@ -21248,22 +22358,13 @@ Lists: 5. No unnecessary escapes * : a * ''* foo'' -!! html -
                                                                                  • bar [[foo]]
                                                                                  -
                                                                                  • =bar [[foo]]
                                                                                  -
                                                                                  • [[bar [[foo]]
                                                                                  -
                                                                                  • ]]bar [[foo]]
                                                                                  -
                                                                                  • =bar foo]]=
                                                                                  -
                                                                                  • : a
                                                                                  -
                                                                                  • * foo
                                                                                  - !!end !! test Lists: 6. Escape bullets in SOL position !! options parsoid=html2wt -!! html +!! html/parsoid

                                                                                  *foo

                                                                                  !! wikitext *foo @@ -21271,20 +22372,22 @@ parsoid=html2wt !! test Lists: 7. Escape bullets in a multi-line context -!! wikitext -a -*b -!! html +!! options +parsoid=html2wt +!! html/parsoid

                                                                                  a *b

                                                                                  +!! wikitext +a +*b !!end !! test Lists: 8. Escape colons only if not present in tags !! options parsoid=html2wt -!! html +!! html/parsoid
                                                                                  a:bc:d
                                                                                  !! wikitext ; a:b''c:d'' @@ -21296,17 +22399,16 @@ parsoid=html2wt !! test HRs: 1. Single line +!! options +parsoid=html2wt +!! html/parsoid +
                                                                                  ---- +
                                                                                  =foo= +
                                                                                  *foo !! wikitext -------- ----=foo= ----*foo -!! html+tidy -
                                                                                  -

                                                                                  ----

                                                                                  -
                                                                                  -

                                                                                  =foo=

                                                                                  -
                                                                                  -

                                                                                  *foo

                                                                                  !! end #### --------------- Tables --------------- @@ -21330,40 +22432,48 @@ HRs: 1. Single line !! test Tables: 1a. Simple example -!! wikitext -{| -|} -!! html +!! options +parsoid=html2wt +!! html/parsoid

                                                                                  {| |}

                                                                                  +!! wikitext +{| +|} !! end !! test Tables: 1b. No escaping needed -!! wikitext -!foo -!! html +!! options +parsoid=html2wt +!! html/parsoid

                                                                                  !foo

                                                                                  +!! wikitext +!foo !! end !! test Tables: 1c. No escaping needed -!! wikitext -|foo -!! html +!! options +parsoid=html2wt +!! html/parsoid

                                                                                  |foo

                                                                                  +!! wikitext +|foo !! end !! test Tables: 1d. No escaping needed -!! wikitext -|}foo -!! html +!! options +parsoid=html2wt +!! html/parsoid

                                                                                  |}foo

                                                                                  +!! wikitext +|}foo !! end !! test @@ -21424,11 +22534,8 @@ parsoid=html2wt !! test Tables: 2c. Nested in td -- no escaping needed -!! wikitext -{| - -|foo!!bar -|} +!! options +parsoid=html2wt !! html/* @@ -21436,15 +22543,17 @@ Tables: 2c. Nested in td -- no escaping needed
                                                                                  foo!!bar
                                                                                  -!! end - -!! test -Tables: 3a. Nested in th !! wikitext {| -!foo!bar +|foo!!bar |} +!! end + +!! test +Tables: 3a. Nested in th +!! options +parsoid=html2wt !! html/* @@ -21452,6 +22561,11 @@ Tables: 3a. Nested in th
                                                                                  foo!bar
                                                                                  +!! wikitext +{| + +!foo!bar +|} !! end !! test @@ -21560,6 +22674,19 @@ parsoid=html2wt !! test Tables: 4c. No escaping needed +!! options +parsoid=html2wt +!! html/parsoid + + + + + +
                                                                                  foo-barfoo+bar
                                                                                  foo-barfoo+bar
                                                                                  foo +

                                                                                  bar|baz ++bar +-bar

                                                                                  x +
                                                                                  a|b
                                                                                  !! wikitext {| |foo-bar @@ -21600,21 +22727,18 @@ bar|baz
                                                                                  a|b
                                                                                  -!! html/parsoid - - - - - -
                                                                                  foo-barfoo+bar
                                                                                  foo-barfoo+bar
                                                                                  foo -

                                                                                  bar|baz -+bar --bar

                                                                                  x -
                                                                                  a|b
                                                                                  !! end !! test Tables: 4d. No escaping needed +!! options +parsoid=html2wt +!! html/parsoid + + + + +
                                                                                  Foo-bar+1-2
                                                                                  !! wikitext {| |[[Foo]]-bar @@ -21631,29 +22755,42 @@ Tables: 4d. No escaping needed -2 +!! end + +!! test +T97430: Don't emit empty nowiki pairs around marker meta tags +!! options +parsoid=html2wt !! html/parsoid - - - - -
                                                                                  Foo-bar+1-2
                                                                                  +

                                                                                  *This is a long sentence here that will make the nowiki algo split up the nowikis into multiple pairs +|** Make this another long long long sentence forcing the nowiki algo to split up the nowikis.

                                                                                  +!! wikitext +*This is a long sentence here that will make the nowiki algo split up the nowikis into multiple pairs +|** Make this another long long long sentence forcing the nowiki algo to split up the nowikis. !! end !! test -Tables: Digest broken attributes on table and tr tag +Unclosed xmlish element in table line shouldn't eat end delimiters !! options -parsoid=wt2html +parsoid=html2wt +!! html/parsoid + + + +
                                                                                  <foo bar>
                                                                                  !! wikitext -{| || |} ++ -|- || || ++ -- -|- > [ +{| +| |} -!! html +!! html/php - - - -
                                                                                  + + <foo + + bar> + + !! end #### --------------- Links ---------------- @@ -21665,6 +22802,12 @@ parsoid=wt2html #### -------------------------------------- !! test Links 1. WikiLinks: No escapes needed +!! options +parsoid=html2wt +!! html/parsoid +

                                                                                  Fooboo +[Foobar] +x [Foobar] x

                                                                                  !! wikitext [[Foo|Foo''boo'']] [[Foo|[Foobar]]] @@ -21674,10 +22817,6 @@ Links 1. WikiLinks: No escapes needed [Foobar] x [Foobar] x

                                                                                  -!! html/parsoid -

                                                                                  Fooboo -[Foobar] -x [Foobar] x

                                                                                  !! end !! test @@ -21722,6 +22861,11 @@ parsoid=html2wt !! test Links 3. WikiLinks: No escapes needed +!! options +parsoid=html2wt +!! html/parsoid +

                                                                                  [Foobar +foo|bar

                                                                                  !! wikitext [[Foo|[Foobar]] [[Foo|foo|bar]] @@ -21729,9 +22873,6 @@ Links 3. WikiLinks: No escapes needed

                                                                                  [Foobar foo|bar

                                                                                  -!! html/parsoid -

                                                                                  [Foobar -foo|bar

                                                                                  !! end !! test @@ -21761,18 +22902,22 @@ parsoid=html2wt !! test Links 5. ExtLinks: No escapes needed +!! options +parsoid=html2wt +!! html/parsoid +

                                                                                  [google

                                                                                  !! wikitext [http://google.com [google] !! html/php

                                                                                  [google

                                                                                  -!! html/parsoid -

                                                                                  [google

                                                                                  !! end !! test Links 6. Add s between text-nodes and url-links when required (bug 64300) -!! html/parsoid +!! options +parsoid=html2wt +!! html/parsoid

                                                                                  xhttp://example.comy http://example.com?x http://example.com&x @@ -21805,6 +22950,8 @@ http://example.com(x) !! test Links 7a. Don't add spurious s between text-nodes and url-links (bug 64300) +!! options +parsoid=html2wt !! html/parsoid

                                                                                  x http://example.com @@ -21838,6 +22985,8 @@ y !! test Links 7b. Don't add spurious s between text-nodes and url-links (bug 64300) +!! options +parsoid=html2wt !! html/parsoid

                                                                                  http://example.com.,;:!?\ -http://example.com:

                                                                                  @@ -21852,6 +23001,8 @@ http://example.com.,;:!?\ !! test Links 8. Add s between text-nodes and RFC-links when required (bug 64300) +!! options +parsoid=html2wt !! html/parsoid

                                                                                  RFC 1234 RFC 123y @@ -21864,6 +23015,8 @@ XRFC 123y !! test Links 9. Don't add spurious s between text-nodes and RFC-links (bug 64300) +!! options +parsoid=html2wt !! html/parsoid

                                                                                  RFC 123?foo RFC 123&foo @@ -21882,6 +23035,8 @@ RFC 123&foo !! test Links 10. Add s between text-nodes and PMID-links when required (bug 64300) +!! options +parsoid=html2wt !! html/parsoid

                                                                                  PMID 1234 PMID 123y @@ -21894,6 +23049,8 @@ XPMID 123y !! test Links 11. Don't add spurious s between text-nodes and PMID-links (bug 64300) +!! options +parsoid=html2wt !! html/parsoid

                                                                                  PMID 123?foo PMID 123&foo @@ -21912,10 +23069,12 @@ PMID 123&foo !! test Links 12. Add s between text-nodes and ISBN-links when required (bug 64300) +!! options +parsoid=html2wt !! html/parsoid -

                                                                                  ISBN 12345678901 -ISBN 1234567890x -aISBN 1234567890b +

                                                                                  ISBN 12345678901 +ISBN 1234567890x +aISBN 1234567890b

                                                                                  !! wikitext ISBN 12345678901 @@ -21925,8 +23084,10 @@ aISBN 1234567890b !! test Links 13. Don't add spurious s between text-nodes and ISBN-links (bug 64300) +!! options +parsoid=html2wt !! html/parsoid -

                                                                                  -ISBN 1234567890's +

                                                                                  -ISBN 1234567890's !! wikitext -ISBN 1234567890's !! html/php @@ -21942,20 +23103,21 @@ parsoid=html2wt

                                                                                  this is not a link: http://example.com

                                                                                  !! wikitext -this is not a link: http://example.com +this is not a link: http://example.com !! end !! test Links 15. Link trails can't become link prefixes. !! options language=is +parsoid=html2wt +!! html/parsoid +

                                                                                  Söfnuður-00

                                                                                  !! wikitext [[Söfnuður]]-[[00]] !! html/php

                                                                                  Söfnuður-00

                                                                                  -!! html/parsoid -

                                                                                  Söfnuður-00

                                                                                  !! end #### --------------- Quotes --------------- @@ -21967,28 +23129,7 @@ language=is !! test 1a. Quotes inside and !! options -parsoid=html2wt,wt2wt -!! wikitext -'''foo''' -''''foo'''' -'''''foo''''' -''foo'''s -''''foo'''' -'''''foo''''' -''''''foo'''''' -'''foo'''bar'''baz''' -'''foo''''s -'''foo'' -''foo''' -''foo'''' -'''foo''' -''''foo''' -'''foo'''' -''''foo'''' -''fools' errand'' -''fool's errand'' -'''foo'' bar '''baz'' -a|!*#-:;+-~[]{}b'''x'' +parsoid=html2wt !! html/*

                                                                                  'foo' ''foo'' @@ -22011,12 +23152,44 @@ a|!*#-:;+-~[]{}b'''x'' 'foo bar 'baz a|!*#-:;+-~[]{}b'x

                                                                                  +!! wikitext +'''foo''' +''''foo'''' +'''''foo''''' +''foo'''s +''''foo'''' +'''''foo''''' +''''''foo'''''' +'''foo'''bar'''baz''' +'''foo''''s +'''foo'' +''foo''' +''foo'''' +'''foo''' +''''foo''' +'''foo'''' +''''foo'''' +''fools' errand'' +''fool's errand'' +'''foo'' bar '''baz'' +a|!*#-:;+-~[]{}b'''x'' !! end !! test 1b. Quotes inside and with other tags on same line !! options -parsoid=html2wt,wt2wt +parsoid=html2wt +!! html/parsoid +'a foo bar +a' foo bar +a' foo bar +foo x'bar +'foo [1] +'foo
                                                                                  test
                                                                                  +'foo and
                                                                                  bar +
                                                                                    +
                                                                                  1. test
                                                                                  2. +
                                                                                  !! wikitext '''a'' foo ''[[bar]]'' ''a''' foo ''[[bar]]'' @@ -22026,56 +23199,49 @@ parsoid=html2wt,wt2wt '''foo''
                                                                                  test
                                                                                  '''foo'' and
                                                                                  bar -!! html -'a foo bar -a' foo bar -a' foo bar -foo x'bar -'foo [1] -'foo
                                                                                  test
                                                                                  -'foo and
                                                                                  bar -
                                                                                    -
                                                                                  1. test
                                                                                  2. -
                                                                                  !! end !! test 2. Link fragments separated by and tags +!! options +parsoid=html2wt +!! html/parsoid +

                                                                                  [[foohello]]

                                                                                  +

                                                                                  [[foohello]]

                                                                                  !! wikitext [[''foo''hello]] [['''foo'''hello]] -!! html -

                                                                                  [[foohello]] -

                                                                                  [[foohello]] -

                                                                                  !! end # FIXME: Escaping one or both of [[ and ]] is also acceptable -- # this is one of the shortcomings of this format !! test 3. Link fragments inside and +!! options +parsoid=html2wt +!! html/parsoid +

                                                                                  [[foo]]

                                                                                  +

                                                                                  [[foo]]

                                                                                  !! wikitext ''[[foo'']] '''[[foo''']] -!! html -

                                                                                  [[foo]] -

                                                                                  [[foo]] -

                                                                                  !! end !! test 4. No escaping needed -!! wikitext -'''bar''' -''''bar'''' -'a:b'foo -!! html +!! options +options=html2wt +!! html/parsoid

                                                                                  'bar' 'bar' 'a:b'foo

                                                                                  +!! wikitext +'''bar''' +''''bar'''' +'a:b'foo !! end #### ----------- Paragraphs --------------- @@ -22084,6 +23250,15 @@ parsoid=html2wt,wt2wt !! test 1. No unnecessary escapes +!! options +parsoid=html2wt +!! html/parsoid +

                                                                                  bar [[foo]] +

                                                                                  =bar [[foo]] +

                                                                                  [[bar [[foo]] +

                                                                                  ]]bar [[foo]] +

                                                                                  =bar foo]]= +

                                                                                  !! wikitext bar [[foo]] @@ -22094,13 +23269,6 @@ bar [[foo]] ]]bar [[foo]] =bar foo]]= -!! html -

                                                                                  bar [[foo]] -

                                                                                  =bar [[foo]] -

                                                                                  [[bar [[foo]] -

                                                                                  ]]bar [[foo]] -

                                                                                  =bar foo]]= -

                                                                                  !!end #### ----------------------- PRE -------------------------- @@ -22109,101 +23277,136 @@ bar [[foo]] !! test 1. Leading whitespace in SOL context should be escaped !! options -parsoid +parsoid=html2wt +!! html/parsoid +

                                                                                  a

                                                                                  + +

                                                                                  a

                                                                                  + +

                                                                                  a(tab)

                                                                                  + +

                                                                                  a + + a

                                                                                  + +

                                                                                  a + b

                                                                                  + +

                                                                                  a + b

                                                                                  + +

                                                                                  a + b

                                                                                  !! wikitext a a - a(tab) + a(tab) a - a + a a b a - b + b a - b -!! html -

                                                                                  a

                                                                                  -

                                                                                  a

                                                                                  -

                                                                                  a(tab)

                                                                                  -

                                                                                  a

                                                                                  -

                                                                                  a

                                                                                  -

                                                                                  a - b

                                                                                  -

                                                                                  a - b

                                                                                  -

                                                                                  a - b

                                                                                  + b +!! html/php +

                                                                                  a +

                                                                                  a +

                                                                                  a(tab) +

                                                                                  a + a +

                                                                                  a + b +

                                                                                  a + b +

                                                                                  a + b +

                                                                                  !! end !! test 2. Leading whitespace in non-indent-pre contexts should not be escaped !! options -parsoid +parsoid=htm2wt +!! html/parsoid +

                                                                                  foo [1]

                                                                                  +
                                                                                    +
                                                                                  1. a + b
                                                                                  2. +
                                                                                  !! wikitext foo ''a'' b -!! html -

                                                                                  foo [1]

                                                                                  -
                                                                                    -
                                                                                  1. a - b
                                                                                  2. -
                                                                                  !! end !! test 3. Leading whitespace in indent-pre suppressing contexts should not be escaped !! options -parsoid -!! wikitext +parsoid=html2wt +!! html/parsoid
                                                                                  +

                                                                                  a b - c + c

                                                                                  -!! html +!! wikitext
                                                                                  -

                                                                                  a b - c

                                                                                  + c
                                                                                  !! end !! test 4. Leading whitespace in indent-pre suppressing contexts should not be escaped !! options -parsoid +options=html2wt +!! html/parsoid +
                                                                                  caption
                                                                                  !! wikitext [[File:Foobar.jpg|thumb|caption]] -!! html/parsoid -
                                                                                  caption
                                                                                  !! end !! test 5. Nowiki escaping should account for indent-pres !! options parsoid=html2wt -!! html +!! html/parsoid
                                                                                  ==foo==
                                                                                  !! wikitext ==foo== !! end +!!test +T95794: nowiki escaping should account for leading space at start-of-line in an indent-pre block +!! options +parsoid=html2wt +!! html/parsoid +
                                                                                  +* foo
                                                                                  +* bar
                                                                                  +
                                                                                  +!! wikitext + * foo + * bar +!! end + #### --------------- Behavior Switches -------------------- + !! test 1. Valid behavior switches should be escaped !! options parsoid=html2wt -!! html +!! html/parsoid __TOC__ __TOC__ !! wikitext @@ -22215,7 +23418,7 @@ __TOC__ 2. Invalid behavior switches should not be escaped !! options parsoid=html2wt -!! html +!! html/parsoid __TOO__ __|__ !! wikitext @@ -22223,6 +23426,31 @@ __TOO__ __|__ !! end +# We use indent-pre as an indirect way to test for sol-transparent behavior. +!! test +Behavior switches should be SOL-transparent +!! options +parsoid=html2wt +!! html/parsoid + + + +
                                                                                  __TOO__
                                                                                  + +
                                                                                   foo
                                                                                  + +
                                                                                  bar
                                                                                  +!! wikitext + __TOC__ + + + __TOO__ + + __TOC__ foo + +__TOC__ bar +!! end + #### --------------- HTML tags --------------- #### 1. a tags #### 2. other tags @@ -22232,75 +23460,85 @@ __|__ !! test 1. a tags !! options -parsoid +parsoid=html2wt +!! html/parsoid +<a href="http://google.com">google</a> !! wikitext google -!! html -<a href="http://google.com">google</a> !! end !! test 2. other tags -!! wikitext -*
                                                                                  foo
                                                                                  -*
                                                                                  foo
                                                                                  -* -!! html +!! options +parsoid=html2wt +!! html/parsoid
                                                                                  • <div>foo</div>
                                                                                  • <div style="color:red">foo</div>
                                                                                  • <td>
                                                                                  +!! wikitext +*
                                                                                  foo
                                                                                  +*
                                                                                  foo
                                                                                  +* !! end !! test 3. multi-line html tag -!! wikitext -
                                                                                  foo
                                                                                  -!! html +!! options +parsoid=html2wt +!! html/parsoid

                                                                                  <div >foo</div >

                                                                                  +!! wikitext +
                                                                                  foo
                                                                                  !! end !! test 4. extension tags +!! options +parsoid=html2wt +!! html/parsoid +

                                                                                  <ref>foo</ref> +

                                                                                  <ref>bar +

                                                                                  baz</ref> +

                                                                                  !! wikitext foo bar baz -!! html -

                                                                                  <ref>foo</ref> -

                                                                                  <ref>bar -

                                                                                  baz</ref> -

                                                                                  !! end #### --------------- Others --------------- !! test Escaping nowikis -!! wikitext -<nowiki>foo</nowiki> -!! html +!! options +parsoid=html2wt +!! html/parsoid

                                                                                  <nowiki>foo</nowiki>

                                                                                  +!! wikitext +<nowiki>foo</nowiki> !! end ## The quote-char in the input is necessary for triggering the bug !! test (Bug 52035) Nowiki-escaping should not get tripped by " :" in text !! options -parsoid=wt2wt,html2wt +parsoid=html2wt +!! html/parsoid +

                                                                                  foo's bar :

                                                                                  !! wikitext foo's bar : -!! html -

                                                                                  foo's bar :

                                                                                  !! end +#----------- End of wikitext escaping tests -------------- + !! test Tag-like HTML structures are passed through as text @@ -22352,20 +23590,9 @@ HTML tag with broken attribute value quoting !! wikitext Foo

                                                                                  -!! end - -!! test -Parsoid-only: HTML tag with broken attribute value quoting -!! options -parsoid -!! wikitext -Foo

                                                                                  !! end @@ -22379,7 +23606,7 @@ Table with broken attribute value quoting !! html/php -
                                                                                  Foo +Foo
                                                                                  !! html/parsoid @@ -22400,9 +23627,9 @@ Table with broken attribute value quoting on consecutive lines !! html/php - -
                                                                                  Foo +Foo Bar +Bar
                                                                                  !! html/parsoid @@ -22415,7 +23642,7 @@ Table with broken attribute value quoting on consecutive lines !! end !! test -Parsoid-only: Don't wrap broken template tags in on wt2wt (Bug 42353) +2. Parsoid-only: Don't wrap broken template tags in on wt2wt (Bug 42353) !! options parsoid !! wikitext @@ -22425,7 +23652,7 @@ parsoid !! end !! test -Parsoid-only: Don't wrap broken template tags in on wt2wt (Bug 42353) +1. Parsoid-only: Don't wrap broken template tags in on wt2wt (Bug 42353) !! options parsoid !! wikitext @@ -22544,6 +23771,8 @@ bar !!end +# Note that the "style" attribute is really a template parameter here. +# The = would have to be {{=}} if you wanted the literal. !!test Empty TD followed by TD with tpl-generated attribute !! wikitext @@ -22704,7 +23933,7 @@ Multi-line image caption generated by templates with/without trailing newlines New element inserted (without intervening newlines) after an old sol-transparent node should serialize correctly !! options parsoid=html2wt -!! html +!! html/parsoid

                                                                                  new para

                                                                                  new heading

                                                                                  @@ -22721,12 +23950,10 @@ new para ## a Parsoid serializer test, marking this Parsoid only !!test Improperly nested inline or quotes tags with whitespace in between -!!options -parsoid !! wikitext x ''' ''x''' '' -!! html +!! html/parsoid

                                                                                  x x

                                                                                  @@ -22734,12 +23961,10 @@ parsoid !!test Encapsulate protected attributes from wt -!!options -parsoid !! wikitext -
                                                                                  foo
                                                                                  -!! html -
                                                                                  foo
                                                                                  +
                                                                                  foo
                                                                                  +!! html/parsoid +
                                                                                  foo
                                                                                  !!end @@ -22752,7 +23977,7 @@ Ensure ParagraphWrapper can deal with stray closing pre tags parsoid=wt2html !! wikitext plain text
              -!! html +!! html/parsoid plain text !!end @@ -22762,7 +23987,7 @@ plain text parsoid=wt2html !! wikitext hi
              ho
              -!! html +!! html/parsoid

              hi

              ho

              @@ -22778,7 +24003,7 @@ parsoid=wt2html,wt2wt || || a -!! html +!! html/parsoid

              || ||

              @@ -22791,7 +24016,7 @@ Encapsulation properly handles null DSR information from foster box parsoid=wt2html,wt2wt !! wikitext {{echo|
              a
              foo
              bar
              }} -!! html +!! html/parsoid foo
              bar
              !!end @@ -22801,7 +24026,7 @@ parsoid=wt2html,wt2wt parsoid=wt2wt,wt2html !! wikitext {{echo|foo}}
              bar
              -!! html +!! html/parsoid

              foo

              @@ -22817,7 +24042,7 @@ parsoid=wt2wt,wt2html parsoid=wt2wt,wt2html !! wikitext
              {{echo|foo}}
              bar
              -!! html +!! html/parsoid
              foo
              @@ -22834,7 +24059,7 @@ parsoid=wt2wt,wt2html parsoid=wt2wt,wt2html !! wikitext

              {{echo|foo

              }}bar
              -!! html +!! html/parsoid

              foo

              @@ -22853,7 +24078,7 @@ parsoid=wt2wt,wt2html parsoid=wt2wt,wt2html !! wikitext

              {{echo|foo

              }}bar
              -!! html +!! html/parsoid

              foo

              @@ -22872,7 +24097,7 @@ parsoid=wt2wt,wt2html parsoid=wt2wt,wt2html !! wikitext foo}}

              {{echo|foo

              -!! html +!! html/parsoid

              foo

              @@ -22893,7 +24118,7 @@ parsoid=wt2wt,wt2html parsoid=wt2wt,wt2html !! wikitext
              foo

              {{echo|foo

              }}

              ok

              -!! html +!! html/parsoid

              foo

              @@ -22915,7 +24140,7 @@ parsoid=wt2wt,wt2html parsoid=wt2wt,wt2html !! wikitext
              {{echo|

              foo

              }}
              bar
              -!! html +!! html/parsoid

              foo

              @@ -22926,6 +24151,8 @@ parsoid=wt2wt,wt2html
              !!end +# Note that the wt is broken on purpose: the = should be {{=}} if you +# don't want it to be a template parameter key. !!test 8. Encapsulate foster-parented transclusion content !!options @@ -22936,8 +24163,11 @@ parsoid=wt2wt,wt2html |- |b |} -!! html -

              a

              {{{1}}}

              +!! html/parsoid +

              a

              + +

              {{{1}}}

              +
              @@ -22952,7 +24182,7 @@ parsoid=wt2wt,wt2html parsoid=wt2wt,wt2html !! wikitext
              b
              {{echo|hi
              hello}} -!! html +!! html/parsoid

              hi

              hello

              !!end @@ -22967,7 +24197,7 @@ parsoid=wt2html,wt2wt |}
              |} -!! html +!! html/parsoid
              @@ -22995,7 +24225,7 @@ Properly encapsulate empty-content transclusions in fosterable positions Support element with .data attribute !!options parsoid=html2wt -!! html +!! html/parsoid !! wikitext @@ -23024,7 +24254,7 @@ Don't block XML namespace declaration Serialize interwiki links pointing to the current wiki as plain wiki links (bug 65869) !! options parsoid=html2wt -!! html +!! html/parsoid

              Foo

              !! wikitext [[Foo]] @@ -23035,7 +24265,7 @@ parsoid=html2wt New wikilinks should be serialized properly !! options parsoid=html2wt -!! html +!! html/parsoid Foo Foo !! wikitext @@ -23047,7 +24277,7 @@ parsoid=html2wt New wiki links (href variations) !! options parsoid=html2wt -!! html +!! html/parsoid Foo_bar Foo_bar Foo_bar @@ -23063,7 +24293,7 @@ parsoid=html2wt New wiki links (content string variations) !! options parsoid=html2wt -!! html +!! html/parsoid Foo_bar Foo bar ./Foo_bar @@ -23077,7 +24307,7 @@ parsoid=html2wt New category links (href variations) !! options parsoid=html2wt -!! html +!! html/parsoid @@ -23092,7 +24322,7 @@ New sol transparent links don't need indent-pre nowiki protection !! options parsoid=html2wt language=de -!! html +!! html/parsoid @@ -23106,7 +24336,7 @@ language=de New interlanguage links (href variations) !! options parsoid=html2wt -!! html +!! html/parsoid @@ -23253,16 +24483,17 @@ parsoid
              bar
              !! end -#!! test -#Image: new attributes should be serialized in wiki's language for RTL languages (bug 51852) -#!! options -#parsoid=html2wt -#language=ar -#!! html -#
              -#!! wikitext -#[[Imagen:Foobar.jpg|derecha|miniaturadeimagen]] -#!! end +!! test +Image: new attributes should be serialized in wiki's language for RTL languages (bug 51852) +!! options +parsoid=html2wt +language=ar +disabled +!! html/parsoid +
              +!! wikitext +[[Imagen:Foobar.jpg|derecha|miniaturadeimagen]] +!! end !! test Image: Block level image should have \n before and after @@ -23272,7 +24503,7 @@ Image: Block level image should have \n before and after 456 !! html/parsoid

              123

              -
              +

              456

              !!end @@ -23290,26 +24521,22 @@ Image: New block level image should have \n before and after (existing content) !! test Image: upright option (parsoid) -!! options -parsoid !! wikitext [[File:Foobar.jpg|thumb|upright|caption]] [[File:Foobar.jpg|thumb|upright=0.5|caption]] [[File:Foobar.jpg|thumb|500x500px|upright=0.5|caption]] -!! html -
              caption
              -
              caption
              -
              caption
              +!! html/parsoid +
              caption
              +
              caption
              +
              caption
              !!end !! test Image: upright option is ignored on inline and frame images (parsoid) -!! options -parsoid !! wikitext [[File:Foobar.jpg|500x500px|upright=0.5|caption]] -!! html -

              +!! html/parsoid +

              !!end !! test @@ -23358,7 +24585,7 @@ parsoid=html2wt Lists: Serialize correctly even when list content is wrapped in p-tags (like VE does) !! options parsoid=html2wt -!! html +!! html/parsoid
              • foo

              @@ -23370,7 +24597,7 @@ parsoid=html2wt Lists: Serialize correctly even when list tags has unneeded whitespace between tags !! options parsoid=html2wt -!! html +!! html/parsoid
              • foo
              !! wikitext * foo @@ -23380,7 +24607,7 @@ parsoid=html2wt Don't strip leading whitespace when handling indent-pre suppressing tags !! options parsoid=html2wt -!! html +!! html/parsoid
              indented row
              @@ -23413,55 +24640,39 @@ foo Nowiki-wrap leading whitespace when handling indent-pre inducing tags !! options parsoid=html2wt -!! wikitext -foo - bar +!! html/parsoid +

              foo

              + bar foo2 - bar2 + bar2
              foo
              - bar + bar
              - foo + foo
              -!! html -

              foo

              - bar +!! wikitext +foo + bar foo2 - bar2 + bar2
              foo
              - bar + bar
              - foo + foo
              !! end -!! test -Lists: Add space after bullets -!! options -parsoid=html2wt -!! html -
                -
              • foo
              • -
              • bar
              • -
              • baz
              • -
              -!! wikitext -* foo -* bar -* baz -!! end - !! test Lists: Dont insert newlines in a serialized list item. !! options parsoid=html2wt -!! html +!! html/parsoid
              • a
                b
              • c
              !! wikitext * a
              b @@ -23469,49 +24680,106 @@ parsoid=html2wt !! end !! test -Headings: Add space before/after == (Bug 51744) +1. Headings: Force sol-transparent links and behavior switches to serialize before/after !! options -parsoid=html2wt -!! html -

              foo

              -

              bar

              -

              baz

              -

              baz

              +parsoid={ + "modes": ["html2wt"], + "scrubWikitext": false +} +!! html/parsoid +

              hello there

              +

              hi pal

              + +

              how goes it

              +

              it goes well

              + +

              howdy

              + +

              ok

              !! wikitext -== foo == +== hello there [[Category:A1]] == -== bar == +== [[Category:A2]] hi pal == -== baz == +== [[Category:A3]] how goes it == -== baz == +== it goes well [[Category:A4]] == + +==howdy [[Category:A5]] == + +== __TOC__ ok == !! end !! test -Headings: Force metas to serialize before/after +2. Headings: Force sol-transparent links and behavior switches to serialize before/after !! options -parsoid=html2wt -!! html -

              hello there

              -

              hi pal

              +parsoid={ + "modes": ["html2wt"], + "scrubWikitext": true +} +!! html/parsoid +

              hello there

              +

              hi pal

              + +

              how goes it

              +

              it goes well

              -

              how goes it

              +

              ok

              !! wikitext == hello there == [[Category:A1]] - [[Category:A2]] + == hi pal == [[Category:A3]] + == how goes it == + +== it goes well == +[[Category:A4]] + +__TOC__ + +== ok == +!! end + +!! test +Headings: Don't hoist metas that come from templates +!! options +parsoid={ + "modes": ["html2wt"], + "scrubWikitext": true +} +!! html/parsoid +

              foo

              +!! wikitext +== {{echo|foo [[Category:Foo]]}} == +!! end + +!! test +Headings: Category in ref isn't hoisted +!! options +parsoid={ + "modes": ["html2wt"], + "scrubWikitext": true +} +!! html/parsoid +

              foo [1]

              + +
              1. bar
              +!! wikitext +== foo bar +[[Category:Baz]] == + + !! end !! test Parsoid: Serialize positional parameters with = in them as named parameter !! options parsoid=html2wt -!! html +!! html/parsoid

              foo

              @@ -23535,7 +24803,7 @@ data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"}, Parsoid: Serialize positional parameters with = in extlink as named parameter !! options parsoid=html2wt -!! html +!! html/parsoid

              http://stuff?is=ok

              !! wikitext {{echo|1 = http://stuff?is=ok}} @@ -23545,7 +24813,7 @@ parsoid=html2wt Parsoid: Correctly serialize block-node children when they are a combination of text and p-nodes !! options parsoid=html2wt -!! html +!! html/parsoid
              a

              b

              a

              b

              @@ -23570,7 +24838,7 @@ b Substrings resembling wikitext in hrefs should not get nowiki escapes !! options parsoid=html2wt -!! html +!! html/parsoid Foo''bar''baz !! wikitext [[Foo''bar''baz]] @@ -23580,27 +24848,89 @@ parsoid=html2wt Enforce single-line context in the serializer !! options parsoid=html2wt -!! html +!! html/parsoid

              testing 123

              +

              hi there +you

              + +

              foo [1]

              + +
              1. hello +there
              +
              • asd sdf
              + +
              • foo +bar +baz
              • +
              • foo bar +baz
              + +
              hi +ho
              hi +ho
              + +
              + +
              ha +ha +ha
              !! wikitext == testing 123 == +== hi {{bogus|there +you}} == + +== foo hello +there == + + + * asd sdf + +* foo bar baz +* foo '''bar''' baz + +; hi ho : hi ho + +: {| +| ha +ha +ha +|} +!! end + +!! test +Serialize new placeholder space without spans +!! options +parsoid=html2wt +!! html/parsoid +

              foo : bar

              + +

              foo : bar

              + +[1]ok

              +!! wikitext +foo : bar + +foo : bar + +foo : barok !! end -#----------------------------- -# I/B quote minimization tests -#----------------------------- + +#----------------------- +# Tag minimization tests +#----------------------- !! test 1. I/B quote minimization: wikitext-only tags should be combined !! options parsoid=html2wt -!! html +!! html/parsoid

              AB

              AB

              AB

              @@ -23631,7 +24961,7 @@ parsoid=html2wt 2. I/B quote minimization: wikitext and html tags should not be combined !! options parsoid=html2wt -!! html +!! html/parsoid

              AB

              AB

              !! wikitext @@ -23644,7 +24974,7 @@ parsoid=html2wt 3. I/B quote minimization: templated content stops minimization !! options parsoid=html2wt -!! html +!! html/parsoid

              AB

              AB !! wikitext @@ -23657,7 +24987,7 @@ parsoid=html2wt 4. I/B quote minimization: new content should be mimimized with adjacent old content !! options parsoid=html2wt -!! html +!! html/parsoid

              AB

              AB

              AB

              @@ -23699,28 +25029,71 @@ parsoid={ ''ac'' !! end -#------------------------------------ -# End of I/B quote minimization tests -#------------------------------------ - -!!test -Bug 54262: New entities +!! test +1. Merge adjacent link nodes as long as at least one element is new !! options -parsoid=html2wt +parsoid={ + "modes": ["html2wt"], + "scrubWikitext": true +} +!! html/parsoid +Football +Football +Football !! wikitext -  -!! html -  +[[Football]] +[[Football]] +[[Football|Foot]][[Football|ball]] !! end -## Note that there is no wikitext output for 'unknownproperty' ## -## Unknown magic words are silently dropped ## - !! test -Magic words +2. Merge adjacent link nodes and enable additional normalizations +!! options +parsoid={ + "modes": ["html2wt"], + "scrubWikitext": true +} +!! html/parsoid +Football +!! wikitext +[[Football|''Football'']] +!! end + +!! test +3. Don't merge adjacent link nodes if scrubWikitext is false +!! options +parsoid={ + "modes": ["html2wt"], + "scrubWikitext": false +} +!! html/parsoid +Football +!! wikitext +[[Football|Foot]][[Football|ball]] +!! end + +#------------------------------ +# End of tag minimization tests +#------------------------------ + +!!test +Bug 54262: New entities !! options parsoid=html2wt -!! html +!! html/parsoid +  +!! wikitext +  +!! end + +## Note that there is no wikitext output for 'unknownproperty' ## +## Unknown magic words are silently dropped ## + +!! test +Magic words +!! options +parsoid=html2wt +!! html/parsoid @@ -23747,7 +25120,7 @@ __NOCONTENTCONVERT__ Consecutive
              s should not get merged
               !! options
               parsoid=html2wt,html2html
              -!! html
              +!! html/parsoid
               
              a
              b
              c
              @@ -23779,8 +25152,8 @@ f
              Edited ISBN links not serializable as ISBN links should serialize as wikilinks !! options parsoid=html2wt -!! html -ISBN 1234567895 +!! html/parsoid +ISBN 1234567895 !! wikitext [[Special:BookSources/1234567890|ISBN 1234567895]] !! end @@ -23789,7 +25162,7 @@ parsoid=html2wt Edited RFC links not serializable as RFC links should serialize as extlinks !! options parsoid=html2wt -!! html +!! html/parsoid New RFC !! wikitext [//tools.ietf.org/html/rfc123 New RFC] @@ -23799,7 +25172,7 @@ parsoid=html2wt Edited PMID links not serializable as PMID links should serialize as extlinks !! options parsoid=html2wt -!! html +!! html/parsoid New PMID !! wikitext [//www.ncbi.nlm.nih.gov/pubmed/123?dopt=Abstract New PMID] @@ -23855,11 +25228,132 @@ xhttp://cscott.netx xhttp://cscott.netx !! end +!! test +WTS of edited autolink-like text (T103364) +!! options +parsoid={ + "modes": ["wt2wt"], + "changes": [ + [ "span[typeof]", "removeAttr", "typeof" ] + ] +} +!! wikitext +Not a link: http://example.com. +!! wikitext/edited +Not a link: http://example.com. +!! end + +!! test +WTS of newly-authored autolink-like text (T103364) +!! options +parsoid=html2wt +!! html/parsoid +

              http://example.com is not a link.

              +!! wikitext +http://example.com is not a link. +!! end + +!! test +WTS of autolink-like text after an autolink (T108563) +!! options +parsoid=html2wt +!! html/parsoid +

              http://example.com http://example.com is not a link.

              +!! wikitext +http://example.com http://example.com is not a link. +!! end + +!! test +Magic links inside links (not autolinked) +!! wikitext +[[Foo|http://example.com]] +[[Foo|RFC 1234]] +[[Foo|PMID 1234]] +[[Foo|ISBN 123456789x]] + +[http://foo.com http://example.com] +[http://foo.com RFC 1234] +[http://foo.com PMID 1234] +[http://foo.com ISBN 123456789x] +!! html+tidy +

              http://example.com RFC 1234 PMID 1234 ISBN 123456789x

              +

              http://example.com RFC 1234 PMID 1234 ISBN 123456789x

              +!! html/parsoid +

              http://example.com +RFC 1234 +PMID 1234 +ISBN 123456789x

              + +

              http://example.com +RFC 1234 +PMID 1234 +ISBN 123456789x

              +!! end + +!! test +Magic links inside image captions (autolinked) +!! wikitext +[[File:Foobar.jpg|thumb|http://example.com]] +[[File:Foobar.jpg|thumb|RFC 1234]] +[[File:Foobar.jpg|thumb|PMID 1234]] +[[File:Foobar.jpg|thumb|ISBN 123456789x]] +!! html+tidy +
              + +
              +
              +
              + +
              +
              +
              +
              + +
              +
              +
              + +
              +!! html/parsoid +
              http://example.com
              +
              RFC 1234
              +
              PMID 1234
              +
              ISBN 123456789x
              +!! end + +!! test +WTS of magic word text (T109371) +!! options +parsoid=html2wt +!! html/parsoid +

              RFC 1234

              +

              RFC 1234

              +

              RFC 1234

              +!! wikitext +RFC 1234 + +[http://foo.com RFC 1234] + +[[Foo|RFC 1234]] +!! end + !! test Edited Redirect link should emit a non-piped wikitext link !! options parsoid=html2wt -!! html +!! html/parsoid !! wikitext #REDIRECT [[Bar]] @@ -23869,7 +25363,7 @@ parsoid=html2wt T75121: Infer extension name from typeOf if data-mw is not present !! options parsoid=html2wt -!! html +!! html/parsoid
              !! wikitext @@ -23929,7 +25423,7 @@ parsoid=html2wt,wt2wt HTML id attribute with Parsoid-like element ids should not be serialized to wikitext !! options parsoid=html2wt -!! html +!! html/parsoid @@ -23945,7 +25439,7 @@ parsoid=html2wt Parsoid-like element ids should not be serialized to wikitext unless shadowed !! options parsoid=html2wt -!! html +!! html/parsoid
              ok
              !! wikitext
              ok
              @@ -23972,67 +25466,708 @@ parsoid={ Never serialize a-tag as html, regardless of what data-parsoid has to say !! options parsoid=html2wt -!! html +!! html/parsoid Foo !! wikitext [[Foo]] !! end -# ----------------------------------------------------------------- -# End of section for Parsoid-only html2wt tests for serialization -# of new content -# ----------------------------------------------------------------- +## SSS FIXME: This is broken output nevertheless. +## What might be a reasonable non-broken output for this? +## This is an edge case unlikely to be seen in production +## that I am not wasting more time on this right now. +!! test +Never serialize a-tag as html, no matter what attributes it has +!! options +parsoid=html2wt +!! html/parsoid + +!! wikitext +[http://boo.org http://boohoo.org] +!! end -# ----------------------------------------------------------------- -# The following section of tests are primarily to spec behavior of -# the selective serializer. All these tests have manual selser -# changes. The automated selser changes for all tests handle the -# wide variation of changes, but these tests here capture specs -# deterministically. -# ---------------------------------------------------------------- +# Misnested is an indication that selser can reuse the source but these have +# shown to sneak through on occasion. See T101768. +# The original wikitext here is: [http://test.com [[one]] two three] +!! test +Strip span tags added to mark as misnested +!! options +parsoid=html2wt +!! html/parsoid +

              one two three

              +!! wikitext +[http://test.com][[one]] two three +!! end + +# -------------------------------------------- +# Tests spec'ing wikitext serialization norms | +# -------------------------------------------- + +!! test +Lists: Add space after bullets +!! options +parsoid=html2wt +!! html/parsoid +
                +
              • foo
              • +
              • bar
              • +
              • baz
              • +
              +!! wikitext +* foo +* bar +* baz +!! end + +!! test +1. Headings: Add space before/after == (T53744) +!! options +parsoid=html2wt +!! html/parsoid +

              foo

              +

              bar

              +

              baz

              +

              baz

              +!! wikitext +== foo == + +== bar == + +== baz == + +== baz == +!! end + +!! test +2. Headings: Add space before/after == even after hoisted content +!! options +parsoid={ + "modes": ["html2wt"], + "scrubWikitext": true +} +!! html/parsoid +

              ok

              +!! wikitext + [[Category:A2]] + +== ok == +!! end + +!! test +1. Headings: suppress newly created empty headings +!! options +parsoid={ + "modes": ["html2wt"], + "scrubWikitext": true +} +!! html/parsoid +

              +!! wikitext +!! end + +!! test +2. Headings: don't suppress empty headings if scrubWikitext is false +!! options +parsoid=html2wt +!! html/parsoid +

              +!! wikitext +==== +!! end -## T90517 !! test -1. Selser: New comments should not be lost +3. Headings: suppress empty headings on edits !! options parsoid={ "modes": ["selser"], + "scrubWikitext": true, "changes": [ - [ "#a", "after", "" ], - [ "#b", "before", "" ] + [ "#x", "remove"] ] } !! wikitext -a - -b +==foo== !! wikitext/edited -a +!! end -b +!! test +1. WT Quote Tags: suppress newly created empty style tags +!! options +parsoid={ + "modes": ["html2wt"], + "scrubWikitext": true +} +!! html/parsoid + +!! wikitext +!! end + +!! test +2. WT Quote Tags: don't suppress empty style tags if scrubWikitext is false +!! options +parsoid=html2wt +!! html/parsoid + +!! wikitext +'''''''''' !! end -## T89383 !! test -2. Selser: Check for validity of DSR before using it +3. WT Quote Tags: suppress empty style tags on edits !! options parsoid={ "modes": ["selser"], + "scrubWikitext": true, "changes": [ - [ "#a", "before", "" ] + [ "#x", "remove"] ] } !! wikitext -a +'''foo''' !! wikitext/edited -{{DISPLAYTITLE:foo}} -a !! end +!! test +1. Anchors: suppress newly created empty anchors +!! options +parsoid={ + "modes": ["html2wt"], + "scrubWikitext": true +} +!! html/parsoid + +!! wikitext +!! end + +!! test +2. Anchors: don't suppress empty anchors if scrubWikitext is false +!! options +parsoid={ + "modes": ["html2wt"], + "scrubWikitext": false +} +!! html/parsoid + +!! wikitext +[[Test|]] +!! end -TODO: -more images -more tables -character entities -and much more -Try for 100% code coverage +!! test +3. Anchors: suppress empty anchors on edits +!! options +parsoid={ + "modes": ["selser"], + "scrubWikitext": true, + "changes": [ + [ "#x", "remove"] + ] +} +!! wikitext +[[Test|foo]] +!! wikitext/edited +!! end + +!! test +3a. Anchors: do not suppress numbered extlinks +!! options +parsoid={ + "modes": ["wt2wt"], + "scrubWikitext": true +} +!! wikitext +[http://foo.com] +!! html/parsoid + +!! end + +!! test +3b. Anchors: do not suppress numbered extlinks +!! options +parsoid={ + "modes": ["wt2wt"], + "scrubWikitext": true, + "changes": [ + [ "#x", "remove"] + ] +} +!! wikitext +[http://foo.com foo] +!! wikitext/edited +[http://foo.com] +!! end + +!!test +Normalizations should be restricted to edited content +!!options +parsoid={ + "modes": ["selser"], + "scrubWikitext": true, + "changes": [ + [ "h1", "before", ""] + ] +} +!!wikitext +a += = +b +!!wikitext/edited +a += = +b +!!end + +!! test +1. Multiple normalizations (html2wt) +!! options +parsoid={ + "modes": ["html2wt"], + "scrubWikitext": true +} +!! html +

              +

              foo + x

              +!! wikitext + +[[foo]] +x + +!! end + +!! test +2. Multiple normalizations (selser) +!! options +parsoid={ + "modes": ["selser"], + "scrubWikitext": true, + "changes": [ + [ "#x", "after", "

              \n

              x

              "] + ] +} +!! wikitext +foo +!! wikitext/edited +foo + +x +!! end + +!! test +1. Indent Pre Nowiki: suppress whitespace at the start of new paragraph +!! options +parsoid={ + "modes": ["html2wt"], + "scrubWikitext": true +} +!! html/parsoid +

              hi

              +

              hello

              +!! wikitext +hi + +hello +!! end + +!! test +2. Indent Pre Nowiki: don't suppress whitespace at the start of new paragraph if scrubWikitext is false +!! options +parsoid=html2wt +!! html/parsoid +

              hi

              +

              hello

              +!! wikitext + hi + + hello +!! end + +!! test +3. Indent Pre Nowiki: suppress whitespace after newlines in new paragraph or table cell +!! options +parsoid={ + "modes": ["html2wt"], + "scrubWikitext": true +} +!! html/parsoid +

              Foo + bar +baz

              + +
              foo bar
              Foo + bar + baz bang
              + +

              foo + bar

              + +

              foo + barboo

              +!! wikitext +Foo +bar +baz + +{| +|Foo +bar +baz bang +|} + +foo +bar + +foo +barboo +!! end + +!! test +4. Indent Pre Nowiki: suppress leading whitespace in edited paragraphs +!! options +parsoid={ + "modes": ["selser"], + "scrubWikitext": true, + "changes": [ + [ "p", "html", " a\n b" ] + ] +} +!! wikitext +xyz +!! wikitext/edited +a +b +!! end + +!! test +1. New links that end in spaces +!! options +parsoid={ + "modes": ["html2wt"], + "scrubWikitext": false +} +!! html/parsoid +

              Berlin is the capital of Germany.

              +

              Foo bar

              +

              Boston is a city.

              +!! wikitext +[[Berlin ]]is the capital of Germany. + +[[Foo ]]'''bar''' + +[[Boston ]] is a city. +!! end + +!! test +2. New links that end in spaces +!! options +parsoid={ + "modes": ["html2wt"], + "scrubWikitext": true +} +!! html/parsoid +

              Berlin is the capital of Germany.

              +

              Foo bar

              +

              Boston is a city.

              +!! wikitext +[[Berlin]] is the capital of Germany. + +[[Foo]] '''bar''' + +[[Boston]] is a city. +!! end + +!! test +1. Table cells with escapable prefixes +!! options +parsoid={ + "modes": ["html2wt"], + "scrubWikitext": false +} +!! html + + + + +
              a
              -
              +
              +!! wikitext +{| +|a +|- +|- +|- +|+ +|} +!! end + +!! test +2. Table cells with escapable prefixes +!! options +parsoid={ + "modes": ["html2wt"], + "scrubWikitext": true +} +!! html + + + + +
              a
              -
              +
              +!! wikitext +{| +|a +|- +| - +|- +| + +|} +!! end + +!! test +3a. Table cells with escapable prefixes after edits +!! options +parsoid={ + "modes": ["selser"], + "scrubWikitext": true, + "changes": [ + [ "table tbody tr:first-child td:first-child", "remove"] + ] +} +!! wikitext +{| +|a||- +|} +!! wikitext/edited +{| +| - +|} +!! end + +!! test +3b. Table cells with escapable prefixes after edits +!! options +parsoid={ + "modes": ["selser"], + "scrubWikitext": true, + "changes": [ + [ "table tbody tr:first-child td:first-child", "html", "-" ], + [ "#x", "remove" ] + ] +} +!! wikitext +{| +|pqr +|foo+ +|} +!! wikitext/edited +{| +| - +| + +|} +!! end + +# FIXME: This test will fail because +# normalization doesn't realize that the id attribute +# will eliminate the escapable scenario +!! test +4a. Table cells without escapable prefixes after edits +!! options +parsoid={ + "modes": ["selser"], + "scrubWikitext": true, + "changes": [ + [ "#x", "html", "-" ] + ] +} +!! wikitext +{| +| id="x" |abcd +|} +!! wikitext/edited +{| +| id="x" |- +|} +!! end + +## This tests normalizer's ability to discriminate between +## cells having identical content. +!! test +4b. Table cells without escapable prefixes after edits +!! options +parsoid={ + "modes": ["selser"], + "scrubWikitext": true, + "changes": [ + [ "td", "html", "-" ] + ] +} +!! wikitext +{| +|a||b +|} +!! wikitext/edited +{| +| -||- +|} +!! end + +## This tests normalizer's ability to not be tripped by +## comments (and whitespace) +!! test +4c. Table cells without escapable prefixes after edits +!! options +parsoid={ + "modes": ["selser"], + "scrubWikitext": true, + "changes": [ + [ "table tbody tr td:first-child", "remove" ] + ] +} +!! wikitext +{| +|- + |a||- +|} +!! wikitext/edited +{| +|- + | - +|} +!! end + +## This tests normalizer's ability to handle HTML cells +!! test +4d. Table cells without escapable prefixes after edits +!! options +parsoid={ + "modes": ["selser"], + "scrubWikitext": true, + "changes": [ + [ "td", "html", "-" ] + ] +} +!! wikitext + + +
              a
              +!! wikitext/edited + + +
              -
              +!! end + +!! test +Escape nowiki DOM elements +!! options +parsoid=html2wt +!! html/parsoid +foo +!! wikitext +<nowiki>''foo''</nowiki> +!! end + +# --------------------------------------------------- +# End of tests spec'ing wikitext serialization norms | +# --------------------------------------------------- + +# ----------------------------------------------------------------- +# End of section for Parsoid-only html2wt tests for serialization +# of new content +# ----------------------------------------------------------------- + +# ----------------------------------------------------------------- +# The following section of tests are primarily to spec behavior of +# the selective serializer. All these tests have manual selser +# changes. The automated selser changes for all tests handle the +# wide variation of changes, but these tests here capture specs +# deterministically. +# ---------------------------------------------------------------- + +## T90517 +!! test +Selser: New comments should not be lost +!! options +parsoid={ + "modes": ["selser"], + "changes": [ + [ "#a", "after", "" ], + [ "#b", "before", "" ] + ] +} +!! wikitext +a + +b +!! wikitext/edited +a + +b +!! end + +## T89383 +!! test +Selser: Check for validity of DSR before using it +!! options +parsoid={ + "modes": ["selser"], + "changes": [ + [ "#a", "before", "" ] + ] +} +!! wikitext +a +!! wikitext/edited +{{DISPLAYTITLE:foo}} +a +!! end + +!! test +1. DOMDiff: Changes to content should be looked up using id +!! options +parsoid={ + "modes": ["selser"], + "changes": [ + ["#X", "after", "bar"], + ["#Y", "after", "baz"] + ] +} +!! wikitext +X foo +Y + +foo + +!! wikitext/edited +X foobar +Y + +foobaz + +!! end + +!! test +2. DOMDiff: Changes to content should be looked up using id +!! options +parsoid={ + "modes": ["selser"], + "changes": [ + ["#Z", "after", "bar"] + ] +} +!! wikitext +A foo bar for a +B + + + + +foo + +!! wikitext/edited +A foo bar for a +B + + + + +foobar + +!! end diff --git a/tests/parser/preprocess/All_system_messages.expected b/tests/parser/preprocess/All_system_messages.expected index 3665e3c1..57223da6 100644 --- a/tests/parser/preprocess/All_system_messages.expected +++ b/tests/parser/preprocess/All_system_messages.expected @@ -1370,12 +1370,12 @@ Message </td><td> </td></tr><tr><td> -[http://tl.wiktionary.org/w/wiki.phtml?title=MediaWiki:Emailpage&action=edit emailpage]<br> -[[MediaWiki_talk:Emailpage|Talk]] +[http://tl.wiktionary.org/w/wiki.phtml?title=MediaWiki:Emailuser&action=edit emailuser]<br> +[[MediaWiki_talk:Emailuser|Talk]] </td><td> E-mail user </td><td> - + </td></tr><tr><td> [http://tl.wiktionary.org/w/wiki.phtml?title=MediaWiki:Emailpagetext&action=edit emailpagetext]<br> [[MediaWiki_talk:Emailpagetext|Talk]] diff --git a/tests/parser/preprocess/All_system_messages.txt b/tests/parser/preprocess/All_system_messages.txt index c619df7b..cdc223a9 100644 --- a/tests/parser/preprocess/All_system_messages.txt +++ b/tests/parser/preprocess/All_system_messages.txt @@ -1370,12 +1370,12 @@ Message {{int:Emailmessage}} -[http://tl.wiktionary.org/w/wiki.phtml?title=MediaWiki:Emailpage&action=edit emailpage]
              -[[MediaWiki_talk:Emailpage|Talk]] +[http://tl.wiktionary.org/w/wiki.phtml?title=MediaWiki:Emailuser&action=edit emailuser]
              +[[MediaWiki_talk:Emailuser|Talk]] E-mail user -{{int:Emailpage}} +{{int:Emailuser}} [http://tl.wiktionary.org/w/wiki.phtml?title=MediaWiki:Emailpagetext&action=edit emailpagetext]
              [[MediaWiki_talk:Emailpagetext|Talk]] diff --git a/tests/parserTests.php b/tests/parserTests.php index 5d21319b..4d84025b 100644 --- a/tests/parserTests.php +++ b/tests/parserTests.php @@ -80,7 +80,7 @@ if ( isset( $options['file'] ) ) { } # Print out software version to assist with locating regressions -$version = SpecialVersion::getVersion(); +$version = SpecialVersion::getVersion( 'nodb' ); echo "This is MediaWiki version {$version}.\n\n"; if ( isset( $options['fuzz'] ) ) { diff --git a/tests/phpunit/LessFileCompilationTest.php b/tests/phpunit/LessFileCompilationTest.php index df4690a4..eec02edc 100644 --- a/tests/phpunit/LessFileCompilationTest.php +++ b/tests/phpunit/LessFileCompilationTest.php @@ -45,11 +45,7 @@ class LessFileCompilationTest extends ResourceLoaderTestCase { $method->setAccessible( true ); $compiler = $method->invoke( $this->module, $rlContext ); - $this->assertNotNull( $compiler->compileFile( $this->file ) ); - } - - public function getName( $withDataSet = true ) { - return $this->toString(); + $this->assertNotNull( $compiler->parseFile( $this->file )->getCss() ); } public function toString() { diff --git a/tests/phpunit/Makefile b/tests/phpunit/Makefile index a33b86a3..e1537bf5 100644 --- a/tests/phpunit/Makefile +++ b/tests/phpunit/Makefile @@ -73,7 +73,6 @@ help: # # Targets: # phpunit (default) Run all the tests with phpunit - # install Install PHPUnit from phpunit.de # tap Run the tests individually through Test::Harness's prove(1) # help You're looking at it! # coverage Run the tests and generates an HTML code coverage report diff --git a/tests/phpunit/MediaWikiTestCase.php b/tests/phpunit/MediaWikiTestCase.php index 72cac051..7dc7027a 100644 --- a/tests/phpunit/MediaWikiTestCase.php +++ b/tests/phpunit/MediaWikiTestCase.php @@ -204,13 +204,11 @@ abstract class MediaWikiTestCase extends PHPUnit_Framework_TestCase { while ( $this->db->trxLevel() > 0 ) { $this->db->rollback(); } - - // don't ignore DB errors - $this->db->ignoreErrors( false ); } DeferredUpdates::clearPendingUpdates(); + ob_start( 'MediaWikiTestCase::wfResetOutputBuffersBarrier' ); } protected function addTmpFiles( $files ) { @@ -218,6 +216,11 @@ abstract class MediaWikiTestCase extends PHPUnit_Framework_TestCase { } protected function tearDown() { + $status = ob_get_status(); + if ( isset( $status['name'] ) && $status['name'] === 'MediaWikiTestCase::wfResetOutputBuffersBarrier' ) { + ob_end_flush(); + } + $this->called['tearDown'] = true; // Cleaning up temporary files foreach ( $this->tmpFiles as $fileName ) { @@ -233,9 +236,6 @@ abstract class MediaWikiTestCase extends PHPUnit_Framework_TestCase { while ( $this->db->trxLevel() > 0 ) { $this->db->rollback(); } - - // don't ignore DB errors - $this->db->ignoreErrors( false ); } // Restore mw globals @@ -716,9 +716,9 @@ abstract class MediaWikiTestCase extends PHPUnit_Framework_TestCase { * @param string $function */ public function hideDeprecated( $function ) { - wfSuppressWarnings(); + MediaWiki\suppressWarnings(); wfDeprecated( $function ); - wfRestoreWarnings(); + MediaWiki\restoreWarnings(); } /** @@ -1002,9 +1002,9 @@ abstract class MediaWikiTestCase extends PHPUnit_Framework_TestCase { # This check may also protect against code injection in # case of broken installations. - wfSuppressWarnings(); + MediaWiki\suppressWarnings(); $haveDiff3 = $wgDiff3 && file_exists( $wgDiff3 ); - wfRestoreWarnings(); + MediaWiki\restoreWarnings(); if ( !$haveDiff3 ) { $this->markTestSkipped( "Skip test, since diff3 is not configured" ); @@ -1117,7 +1117,7 @@ abstract class MediaWikiTestCase extends PHPUnit_Framework_TestCase { // of tidy. In that case however, we can not reliably detect whether a failing validation // is due to malformed HTML, or caused by tidy not being installed as a command line tool. // That would cause all HTML assertions to fail on a system that has no tidy installed. - if ( !$GLOBALS['wgTidyInternal'] ) { + if ( !$GLOBALS['wgTidyInternal'] || !MWTidy::isEnabled() ) { $this->markTestSkipped( 'Tidy extension not installed' ); } @@ -1180,4 +1180,12 @@ abstract class MediaWikiTestCase extends PHPUnit_Framework_TestCase { self::assertFalse( self::tagMatch( $matcher, $actual, $isHtml ), $message ); } + + /** + * Used as a marker to prevent wfResetOutputBuffers from breaking PHPUnit. + * @return string + */ + public static function wfResetOutputBuffersBarrier( $buffer ) { + return $buffer; + } } diff --git a/tests/phpunit/README b/tests/phpunit/README index 0a32ba17..f555812d 100644 --- a/tests/phpunit/README +++ b/tests/phpunit/README @@ -14,16 +14,13 @@ TO RETAIN YOUR DATA. == Installation == -If PHPUnit is not installed, follow the installation instructions in the -PHPUnit Manual at: - - http://www.phpunit.de/manual/current/en/installation.html +If you used composer to install MediaWiki's dependencies PHPUnit will already be available, unless +you explicitly specified the --no-dev flag during the install. In this case just run "composer update". -- or - - -On Unix-like operating systems, run: +Otherwise follow the installation instructions in the +PHPUnit Manual at: - make install + https://phpunit.de/manual/current/en/installation.html == Running tests == @@ -47,7 +44,7 @@ On Windows-family operating systems, run the 'run-tests.bat' batch file. === Writing tests === -A guide to writing unit tests for MediaWiki can be found at: +A guide to writing PHP unit tests for MediaWiki can be found at: - http://mediawiki.org/wiki/Unit_Testing + https://www.mediawiki.org/wiki/Manual:PHP_unit_testing diff --git a/tests/phpunit/ResourceLoaderTestCase.php b/tests/phpunit/ResourceLoaderTestCase.php index deecb31e..325b20ee 100644 --- a/tests/phpunit/ResourceLoaderTestCase.php +++ b/tests/phpunit/ResourceLoaderTestCase.php @@ -25,27 +25,35 @@ abstract class ResourceLoaderTestCase extends MediaWikiTestCase { return $ctx; } - protected function setUp() { - parent::setUp(); - - ResourceLoader::clearCache(); - - $this->setMwGlobals( array( + public static function getSettings() { + return array( // For ResourceLoader::inDebugMode since it doesn't have context - 'wgResourceLoaderDebug' => true, + 'ResourceLoaderDebug' => true, // Avoid influence from wgInvalidateCacheOnLocalSettingsChange - 'wgCacheEpoch' => '20140101000000', + 'CacheEpoch' => '20140101000000', // For ResourceLoader::__construct() - 'wgResourceLoaderSources' => array(), + 'ResourceLoaderSources' => array(), // For wfScript() - 'wgScriptPath' => '/w', - 'wgScriptExtension' => '.php', - 'wgScript' => '/w/index.php', - 'wgLoadScript' => '/w/load.php', - ) ); + 'ScriptPath' => '/w', + 'ScriptExtension' => '.php', + 'Script' => '/w/index.php', + 'LoadScript' => '/w/load.php', + ); + } + + protected function setUp() { + parent::setUp(); + + ResourceLoader::clearCache(); + + $globals = array(); + foreach ( self::getSettings() as $key => $value ) { + $globals['wg' . $key] = $value; + } + $this->setMwGlobals( $globals ); } } @@ -68,14 +76,14 @@ class ResourceLoaderTestModule extends ResourceLoaderModule { } public function getScript( ResourceLoaderContext $context ) { - return $this->script; + return $this->validateScriptFile( 'input', $this->script ); } public function getStyles( ResourceLoaderContext $context ) { return array( '' => $this->styles ); } - public function getDependencies() { + public function getDependencies( ResourceLoaderContext $context = null ) { return $this->dependencies; } @@ -94,6 +102,10 @@ class ResourceLoaderTestModule extends ResourceLoaderModule { public function isRaw() { return $this->isRaw; } + + public function enableModuleContentVersion() { + return true; + } } class ResourceLoaderFileModuleTestModule extends ResourceLoaderFileModule { diff --git a/tests/phpunit/data/css/comments.css b/tests/phpunit/data/css/comments.css new file mode 100644 index 00000000..744a14c7 --- /dev/null +++ b/tests/phpunit/data/css/comments.css @@ -0,0 +1,7 @@ +/* url expressions in comments should be ignored */ + +.selector { /*@noflip*/ background-image: /*@embed*/ url(not-commented.gif); } + +/* +.selector { background-image: url(commented-out.gif); } +*/ diff --git a/tests/phpunit/data/helpers/WellProtectedClass.php b/tests/phpunit/data/helpers/WellProtectedClass.php index 99c7f642..a45cfbbf 100644 --- a/tests/phpunit/data/helpers/WellProtectedClass.php +++ b/tests/phpunit/data/helpers/WellProtectedClass.php @@ -1,20 +1,47 @@ privateParentProperty = 9000; + } + + private function incrementPrivateParentPropertyValue() { + $this->privateParentProperty++; + } + + public function getPrivateParentProperty() { + return $this->privateParentProperty; + } +} + +class WellProtectedClass extends WellProtectedParentClass { protected $property; + private $privateProperty; public function __construct() { + parent::__construct(); $this->property = 1; + $this->privateProperty = 42; } protected function incrementPropertyValue() { $this->property++; } + private function incrementPrivatePropertyValue() { + $this->privateProperty++; + } + public function getProperty() { return $this->property; } + public function getPrivateProperty() { + return $this->privateProperty; + } + protected function whatSecondArg( $a, $b = false ) { return $b; } diff --git a/tests/phpunit/data/import/ImportLinkCacheIntegrationTest.xml b/tests/phpunit/data/import/ImportLinkCacheIntegrationTest.xml new file mode 100644 index 00000000..8949f406 --- /dev/null +++ b/tests/phpunit/data/import/ImportLinkCacheIntegrationTest.xml @@ -0,0 +1,43 @@ + + + MW-19 + http://localhost:8080/w/index.php/Main_Page + MediaWiki 1.19.7 + first-letter + + + Lorem ipsum + 0 + 493 + 94lztkh4kgb0mvjr87iyjfq4iv7ltlh + + 1358 + 2014-04-04T22:55:04Z + + Tester + 1 + + [[Has text::Lorem ipsum dolor sit amet consectetuer Maecenas adipiscing Pellentesque id sem]]. [[Has page::Elit Aliquam urna interdum]] morbi faucibus id tellus ipsum semper wisi. [[Has page::Platea enim hendrerit]] pellentesque consectetuer scelerisque Sed est felis felis quis. Auctor Proin In dolor id et ipsum vel at vitae ut. Praesent elit convallis Praesent aliquet pellentesque vel dolor pellentesque lacinia vitae. At tortor lacus Sed In interdum pulvinar et. + +[[Has number::1001]] [[Has quantity::10.25 km²]] [[Has date::1 Jan 2014]] [[Has Url::http://loremipsum.org/]] [[Has annotation uri::http://loremipsum.org/foaf.rdf]] [[Has email::Lorem@ipsum.org]] [[Has temperature::100 °C]] [[Has boolean::true]] + +[[Category:Lorem ipsum]] + + + + Category:Lorem ipsum + 14 + 496 + sir97j6uzt9ev2uyhaz1aj4i3spogih + + 1355 + 2014-04-04T22:29:18Z + + Tester + 1 + + [[Category:Main]] + + + + diff --git a/tests/phpunit/data/less/common/test.common.mixins.less b/tests/phpunit/data/less/common/test.common.mixins.less index 2fbe9b79..40647291 100644 --- a/tests/phpunit/data/less/common/test.common.mixins.less +++ b/tests/phpunit/data/less/common/test.common.mixins.less @@ -1,5 +1,4 @@ .test-mixin (@value) { color: @value; border: @foo solid @Foo; - line-height: test-sum(@bar, 10, 20); } diff --git a/tests/phpunit/data/less/module/styles.css b/tests/phpunit/data/less/module/styles.css index b78780a9..bac695b9 100644 --- a/tests/phpunit/data/less/module/styles.css +++ b/tests/phpunit/data/less/module/styles.css @@ -1,6 +1,5 @@ /* @noflip */ .unit-tests { - color: green; + color: #008000; border: 2px solid #eeeeee; - line-height: 35; } diff --git a/tests/phpunit/data/media/2_webp_a.webp b/tests/phpunit/data/media/2_webp_a.webp new file mode 100644 index 00000000..8764f066 Binary files /dev/null and b/tests/phpunit/data/media/2_webp_a.webp differ diff --git a/tests/phpunit/data/media/2_webp_ll.webp b/tests/phpunit/data/media/2_webp_ll.webp new file mode 100644 index 00000000..5794bbf2 Binary files /dev/null and b/tests/phpunit/data/media/2_webp_ll.webp differ diff --git a/tests/phpunit/data/media/srgb.jpg b/tests/phpunit/data/media/srgb.jpg new file mode 100644 index 00000000..b965dc4f Binary files /dev/null and b/tests/phpunit/data/media/srgb.jpg differ diff --git a/tests/phpunit/data/media/tinyrgb.icc b/tests/phpunit/data/media/tinyrgb.icc new file mode 100644 index 00000000..eab973f5 Binary files /dev/null and b/tests/phpunit/data/media/tinyrgb.icc differ diff --git a/tests/phpunit/data/media/tinyrgb.jpg b/tests/phpunit/data/media/tinyrgb.jpg new file mode 100644 index 00000000..12a8e09f Binary files /dev/null and b/tests/phpunit/data/media/tinyrgb.jpg differ diff --git a/tests/phpunit/data/media/webp_animated.webp b/tests/phpunit/data/media/webp_animated.webp new file mode 100644 index 00000000..25c6a4dd Binary files /dev/null and b/tests/phpunit/data/media/webp_animated.webp differ diff --git a/tests/phpunit/data/templates/bad_partial.mustache b/tests/phpunit/data/templates/bad_partial.mustache new file mode 100644 index 00000000..d2767f0f --- /dev/null +++ b/tests/phpunit/data/templates/bad_partial.mustache @@ -0,0 +1 @@ +Partial {{>nonexistenttemplate}} in here diff --git a/tests/phpunit/data/templates/has_partial.mustache b/tests/phpunit/data/templates/has_partial.mustache new file mode 100644 index 00000000..504387a4 --- /dev/null +++ b/tests/phpunit/data/templates/has_partial.mustache @@ -0,0 +1 @@ +Partial {{>foobar_args}} in here diff --git a/tests/phpunit/includes/BlockTest.php b/tests/phpunit/includes/BlockTest.php index 19741621..7b0de866 100644 --- a/tests/phpunit/includes/BlockTest.php +++ b/tests/phpunit/includes/BlockTest.php @@ -38,9 +38,13 @@ class BlockTest extends MediaWikiLangTestCase { $oldBlock->delete(); } - $this->block = new Block( 'UTBlockee', $user->getID(), 0, - 'Parce que', 0, false, time() + 100500 + $blockOptions = array( + 'address' => 'UTBlockee', + 'user' => $user->getID(), + 'reason' => 'Parce que', + 'expiry' => time() + 100500, ); + $this->block = new Block( $blockOptions ); $this->madeAt = wfTimestamp( TS_MW ); $this->block->insert(); @@ -151,22 +155,19 @@ class BlockTest extends MediaWikiLangTestCase { ); // Foreign perspective (blockee not on current wiki)... - $block = new Block( - /* $address */ $username, - /* $user */ 14146, - /* $by */ 0, - /* $reason */ 'crosswiki block...', - /* $timestamp */ wfTimestampNow(), - /* $auto */ false, - /* $expiry */ $this->db->getInfinity(), - /* anonOnly */ false, - /* $createAccount */ true, - /* $enableAutoblock */ true, - /* $hideName (ipb_deleted) */ true, - /* $blockEmail */ true, - /* $allowUsertalk */ false, - /* $byName */ 'MetaWikiUser' + $blockOptions = array( + 'address' => $username, + 'user' => 14146, + 'reason' => 'crosswiki block...', + 'timestamp' => wfTimestampNow(), + 'expiry' => $this->db->getInfinity(), + 'createAccount' => true, + 'enableAutoblock' => true, + 'hideName' => true, + 'blockEmail' => true, + 'byText' => 'MetaWikiUser', ); + $block = new Block( $blockOptions ); $block->insert(); // Reload block from DB @@ -208,22 +209,19 @@ class BlockTest extends MediaWikiLangTestCase { $this->db->update( 'user', array( 'user_id' => 14146 ), array( 'user_id' => $user->getId() ) ); // Foreign perspective (blockee not on current wiki)... - $block = new Block( - /* $address */ 'UserOnForeignWiki', - /* $user */ 14146, - /* $by */ 0, - /* $reason */ 'crosswiki block...', - /* $timestamp */ wfTimestampNow(), - /* $auto */ false, - /* $expiry */ $this->db->getInfinity(), - /* anonOnly */ false, - /* $createAccount */ true, - /* $enableAutoblock */ true, - /* $hideName (ipb_deleted) */ true, - /* $blockEmail */ true, - /* $allowUsertalk */ false, - /* $byName */ 'MetaWikiUser' + $blockOptions = array( + 'address' => 'UserOnForeignWiki', + 'user' => 14146, + 'reason' => 'crosswiki block...', + 'timestamp' => wfTimestampNow(), + 'expiry' => $this->db->getInfinity(), + 'createAccount' => true, + 'enableAutoblock' => true, + 'hideName' => true, + 'blockEmail' => true, + 'byText' => 'MetaWikiUser', ); + $block = new Block( $blockOptions ); $res = $block->insert( $this->db ); $this->assertTrue( (bool)$res['id'], 'Block succeeded' ); @@ -367,4 +365,56 @@ class BlockTest extends MediaWikiLangTestCase { $block = Block::chooseBlock( $xffblocks, $list ); $this->assertEquals( $exResult, $block->mReason, 'Correct block type for XFF header ' . $xff ); } + + public function testDeprecatedConstructor() { + $this->hideDeprecated( 'Block::__construct with multiple arguments' ); + $username = 'UnthinkablySecretRandomUsername'; + $reason = 'being irrational'; + + # Set up the target + $u = User::newFromName( $username ); + if ( $u->getID() == 0 ) { + $u->setPassword( 'TotallyObvious' ); + $u->addToDatabase(); + } + unset( $u ); + + # Make sure the user isn't blocked + $this->assertNull( + Block::newFromTarget( $username ), + "$username should not be blocked" + ); + + # Perform the block + $block = new Block( + /* address */ $username, + /* user */ 0, + /* by */ 0, + /* reason */ $reason, + /* timestamp */ 0, + /* auto */ false, + /* expiry */ 0 + ); + $block->insert(); + + # Check target + $this->assertEquals( + $block->getTarget()->getName(), + $username, + "Target should be set properly" + ); + + # Check supplied parameter + $this->assertEquals( + $block->mReason, + $reason, + "Reason should be non-default" + ); + + # Check default parameter + $this->assertFalse( + (bool)$block->prevents( 'createaccount' ), + "Account creation should not be blocked by default" + ); + } } diff --git a/tests/phpunit/includes/ConsecutiveParametersMatcher.php b/tests/phpunit/includes/ConsecutiveParametersMatcher.php new file mode 100644 index 00000000..adf74bb4 --- /dev/null +++ b/tests/phpunit/includes/ConsecutiveParametersMatcher.php @@ -0,0 +1,123 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +/** + * Invocation matcher which looks for sets of specific parameters in the invocations. + * + * Checks the parameters of the incoming invocations, the parameter list is + * checked against the defined constraints in $parameters. If the constraint + * is met it will return true in matches(). + * + * It takes a list of match groups and and increases a call index after each invocation. + * So the first invocation uses the first group of constraints, the second the next and so on. + */ +class PHPUnit_Framework_MockObject_Matcher_ConsecutiveParameters extends PHPUnit_Framework_MockObject_Matcher_StatelessInvocation +{ + /** + * @var array + */ + private $_parameterGroups = array(); + + /** + * @var array + */ + private $_invocations = array(); + + /** + * @param array $parameterGroups + */ + public function __construct(array $parameterGroups) + { + foreach ($parameterGroups as $index => $parameters) { + foreach ($parameters as $parameter) { + if (!($parameter instanceof \PHPUnit_Framework_Constraint)) { + $parameter = new \PHPUnit_Framework_Constraint_IsEqual($parameter); + } + $this->_parameterGroups[$index][] = $parameter; + } + } + } + + /** + * @return string + */ + public function toString() + { + $text = 'with consecutive parameters'; + + return $text; + } + + /** + * @param PHPUnit_Framework_MockObject_Invocation $invocation + * @return bool + */ + public function matches(PHPUnit_Framework_MockObject_Invocation $invocation) + { + $this->_invocations[] = $invocation; + $callIndex = count($this->_invocations) - 1; + $this->verifyInvocation($invocation, $callIndex); + + return false; + } + + public function verify() + { + foreach ($this->_invocations as $callIndex => $invocation) { + $this->verifyInvocation($invocation, $callIndex); + } + } + + /** + * Verify a single invocation + * + * @param PHPUnit_Framework_MockObject_Invocation $invocation + * @param int $callIndex + * @throws PHPUnit_Framework_ExpectationFailedException + */ + private function verifyInvocation(PHPUnit_Framework_MockObject_Invocation $invocation, $callIndex) + { + + if (isset($this->_parameterGroups[$callIndex])) { + $parameters = $this->_parameterGroups[$callIndex]; + } else { + // no parameter assertion for this call index + return; + } + + if ($invocation === null) { + throw new PHPUnit_Framework_ExpectationFailedException( + 'Mocked method does not exist.' + ); + } + + if (count($invocation->parameters) < count($parameters)) { + throw new PHPUnit_Framework_ExpectationFailedException( + sprintf( + 'Parameter count for invocation %s is too low.', + $invocation->toString() + ) + ); + } + + foreach ($parameters as $i => $parameter) { + $parameter->evaluate( + $invocation->parameters[$i], + sprintf( + 'Parameter %s for invocation #%d %s does not match expected ' . + 'value.', + $i, + $callIndex, + $invocation->toString() + ) + ); + } + } +} diff --git a/tests/phpunit/includes/EditPageTest.php b/tests/phpunit/includes/EditPageTest.php index 15778e40..27959b1d 100644 --- a/tests/phpunit/includes/EditPageTest.php +++ b/tests/phpunit/includes/EditPageTest.php @@ -11,6 +11,28 @@ */ class EditPageTest extends MediaWikiLangTestCase { + protected function setUp() { + global $wgExtraNamespaces, $wgNamespaceContentModels, $wgContentHandlers, $wgContLang; + + parent::setUp(); + + $this->setMwGlobals( array( + 'wgExtraNamespaces' => $wgExtraNamespaces, + 'wgNamespaceContentModels' => $wgNamespaceContentModels, + 'wgContentHandlers' => $wgContentHandlers, + 'wgContLang' => $wgContLang, + ) ); + + $wgExtraNamespaces[12312] = 'Dummy'; + $wgExtraNamespaces[12313] = 'Dummy_talk'; + + $wgNamespaceContentModels[12312] = "testing"; + $wgContentHandlers["testing"] = 'DummyContentHandlerForTesting'; + + MWNamespace::getCanonicalNamespaces( true ); # reset namespace cache + $wgContLang->resetNamespaces(); # reset namespace cache + } + /** * @dataProvider provideExtractSectionTitle * @covers EditPage::extractSectionTitle @@ -499,4 +521,37 @@ hello $this->assertEdit( 'EditPageTest_testAutoMerge', null, 'Berta', $bertasEdit, $expectedCode, $expectedText, $message ); } + + /** + * @depends testAutoMerge + */ + public function testCheckDirectEditingDisallowed_forNonTextContent() { + $title = Title::newFromText( 'Dummy:NonTextPageForEditPage' ); + $page = WikiPage::factory( $title ); + + $article = new Article( $title ); + $article->getContext()->setTitle( $title ); + $ep = new EditPage( $article ); + $ep->setContextTitle( $title ); + + $user = $GLOBALS['wgUser']; + + $edit = array( + 'wpTextbox1' => serialize( 'non-text content' ), + 'wpEditToken' => $user->getEditToken(), + 'wpEdittime' => '', + 'wpStarttime' => wfTimestampNow() + ); + + $req = new FauxRequest( $edit, true ); + $ep->importFormData( $req ); + + $this->setExpectedException( + 'MWException', + 'This content model is not supported: testing' + ); + + $ep->internalAttemptSave( $result, false ); + } + } diff --git a/tests/phpunit/includes/ExtraParserTest.php b/tests/phpunit/includes/ExtraParserTest.php index 4a4130e0..7b60fb3f 100644 --- a/tests/phpunit/includes/ExtraParserTest.php +++ b/tests/phpunit/includes/ExtraParserTest.php @@ -2,6 +2,8 @@ /** * Parser-related tests that don't suit for parserTests.txt + * + * @group Database */ class ExtraParserTest extends MediaWikiTestCase { @@ -20,7 +22,6 @@ class ExtraParserTest extends MediaWikiTestCase { 'wgContLang' => $contLang, 'wgLang' => Language::factory( 'en' ), 'wgMemc' => new EmptyBagOStuff, - 'wgAlwaysUseTidy' => false, 'wgCleanSignatures' => true, ) ); diff --git a/tests/phpunit/includes/FauxRequestTest.php b/tests/phpunit/includes/FauxRequestTest.php index 745a5b42..07214b21 100644 --- a/tests/phpunit/includes/FauxRequestTest.php +++ b/tests/phpunit/includes/FauxRequestTest.php @@ -6,13 +6,46 @@ class FauxRequestTest extends MediaWikiTestCase { * @covers FauxRequest::getHeader */ public function testGetSetHeader() { - $value = 'test/test'; + $value = 'text/plain, text/html'; $request = new FauxRequest(); - $request->setHeader( 'Content-Type', $value ); + $request->setHeader( 'Accept', $value ); - $this->assertEquals( $request->getHeader( 'Content-Type' ), $value ); - $this->assertEquals( $request->getHeader( 'CONTENT-TYPE' ), $value ); - $this->assertEquals( $request->getHeader( 'content-type' ), $value ); + $this->assertEquals( $request->getHeader( 'Nonexistent' ), false ); + $this->assertEquals( $request->getHeader( 'Accept' ), $value ); + $this->assertEquals( $request->getHeader( 'ACCEPT' ), $value ); + $this->assertEquals( $request->getHeader( 'accept' ), $value ); + $this->assertEquals( + $request->getHeader( 'Accept', WebRequest::GETHEADER_LIST ), + array( 'text/plain', 'text/html' ) + ); + } + + /** + * @covers FauxRequest::getAllHeaders + */ + public function testGetAllHeaders() { + $_SERVER['HTTP_TEST'] = 'Example'; + + $request = new FauxRequest(); + + $this->assertEquals( + array(), + $request->getAllHeaders() + ); + } + + /** + * @covers FauxRequest::getHeader + */ + public function testGetHeader() { + $_SERVER['HTTP_TEST'] = 'Example'; + + $request = new FauxRequest(); + + $this->assertEquals( + false, + $request->getHeader( 'test' ) + ); } } diff --git a/tests/phpunit/includes/FauxResponseTest.php b/tests/phpunit/includes/FauxResponseTest.php index 4a974ba2..39a0effa 100644 --- a/tests/phpunit/includes/FauxResponseTest.php +++ b/tests/phpunit/includes/FauxResponseTest.php @@ -108,6 +108,13 @@ class FauxResponseTest extends MediaWikiTestCase { 'Third parameter overrides the HTTP/... header' ); + $this->response->statusHeader( 210 ); + $this->assertEquals( + 210, + $this->response->getStatusCode(), + 'Handle statusHeader method' + ); + $this->response->header( 'Location: http://localhost/', false, 206 ); $this->assertEquals( 206, diff --git a/tests/phpunit/includes/GlobalFunctions/GlobalTest.php b/tests/phpunit/includes/GlobalFunctions/GlobalTest.php index 1e30273e..e89e36f6 100644 --- a/tests/phpunit/includes/GlobalFunctions/GlobalTest.php +++ b/tests/phpunit/includes/GlobalFunctions/GlobalTest.php @@ -666,9 +666,9 @@ class GlobalTest extends MediaWikiTestCase { public function testWfMkdirParents() { // Should not return true if file exists instead of directory $fname = $this->getNewTempFile(); - wfSuppressWarnings(); + MediaWiki\suppressWarnings(); $ok = wfMkdirParents( $fname ); - wfRestoreWarnings(); + MediaWiki\restoreWarnings(); $this->assertFalse( $ok ); } @@ -687,6 +687,105 @@ class GlobalTest extends MediaWikiTestCase { $this->assertEquals( $expected, $actual, $description ); } + public function wfWikiID() { + $this->setMwGlobals( array( + 'wgDBname' => 'example', + 'wgDBprefix' => '', + ) ); + $this->assertEquals( + wfWikiID(), + 'example' + ); + + $this->setMwGlobals( array( + 'wgDBname' => 'example', + 'wgDBprefix' => 'mw_', + ) ); + $this->assertEquals( + wfWikiID(), + 'example-mw_' + ); + } + + public function testWfMemcKey() { + // Just assert the exact output so we can catch unintentional changes to key + // construction, which would effectively invalidate all existing cache. + + $this->setMwGlobals( array( + 'wgCachePrefix' => false, + 'wgDBname' => 'example', + 'wgDBprefix' => '', + ) ); + $this->assertEquals( + wfMemcKey( 'foo', '123', 'bar' ), + 'example:foo:123:bar' + ); + + $this->setMwGlobals( array( + 'wgCachePrefix' => false, + 'wgDBname' => 'example', + 'wgDBprefix' => 'mw_', + ) ); + $this->assertEquals( + wfMemcKey( 'foo', '123', 'bar' ), + 'example-mw_:foo:123:bar' + ); + + $this->setMwGlobals( array( + 'wgCachePrefix' => 'custom', + 'wgDBname' => 'example', + 'wgDBprefix' => 'mw_', + ) ); + $this->assertEquals( + wfMemcKey( 'foo', '123', 'bar' ), + 'custom:foo:123:bar' + ); + } + + public function testWfForeignMemcKey() { + $this->setMwGlobals( array( + 'wgCachePrefix' => false, + 'wgDBname' => 'example', + 'wgDBprefix' => '', + ) ); + $local = wfMemcKey( 'foo', 'bar' ); + + $this->setMwGlobals( array( + 'wgDBname' => 'other', + 'wgDBprefix' => 'mw_', + ) ); + $this->assertEquals( + wfForeignMemcKey( 'example', '', 'foo', 'bar' ), + $local, + 'Match output of wfMemcKey from local wiki' + ); + } + + public function testWfGlobalCacheKey() { + $this->setMwGlobals( array( + 'wgCachePrefix' => 'ignored', + 'wgDBname' => 'example', + 'wgDBprefix' => '' + ) ); + $one = wfGlobalCacheKey( 'some', 'thing' ); + $this->assertEquals( + $one, + 'global:some:thing' + ); + + $this->setMwGlobals( array( + 'wgDBname' => 'other', + 'wgDBprefix' => 'mw_' + ) ); + $two = wfGlobalCacheKey( 'some', 'thing' ); + + $this->assertEquals( + $one, + $two, + 'Not fragmented by wiki id' + ); + } + public static function provideWfShellWikiCmdList() { global $wgPhpCli; diff --git a/tests/phpunit/includes/GlobalFunctions/wfArrayPlus2dTest.php b/tests/phpunit/includes/GlobalFunctions/wfArrayPlus2dTest.php new file mode 100644 index 00000000..88875bb0 --- /dev/null +++ b/tests/phpunit/includes/GlobalFunctions/wfArrayPlus2dTest.php @@ -0,0 +1,94 @@ +assertEquals( + $expected, + wfArrayPlus2d( $baseArray, $newValues ), + $testName + ); + } + + /** + * Provider for testing wfArrayPlus2d + * + * @return array + */ + public static function provideArrays() { + return array( + // target array, new values array, expected result + array( + array( 0 => '1dArray' ), + array( 1 => '1dArray' ), + array( 0 => '1dArray', 1 => '1dArray' ), + "Test simple union of two arrays with different keys", + ), + array( + array( + 0 => array( 0 => '2dArray' ), + ), + array( + 0 => array( 1 => '2dArray' ), + ), + array( + 0 => array( 0 => '2dArray', 1 => '2dArray' ), + ), + "Test union of 2d arrays with different keys in the value array", + ), + array( + array( + 0 => array( 0 => '2dArray' ), + ), + array( + 0 => array( 0 => '1dArray' ), + ), + array( + 0 => array( 0 => '2dArray' ), + ), + "Test union of 2d arrays with same keys in the value array", + ), + array( + array( + 0 => array( 0 => array( 0 => '3dArray' ) ), + ), + array( + 0 => array( 0 => array( 1 => '2dArray' ) ), + ), + array( + 0 => array( 0 => array( 0 => '3dArray' ) ), + ), + "Test union of 3d array with different keys", + ), + array( + array( + 0 => array( 0 => array( 0 => '3dArray' ) ), + ), + array( + 0 => array( 1 => array( 0 => '2dArray' ) ), + ), + array( + 0 => array( 0 => array( 0 => '3dArray' ), 1 => array( 0 => '2dArray' ) ), + ), + "Test union of 3d array with different keys in the value array", + ), + array( + array( + 0 => array( 0 => array( 0 => '3dArray' ) ), + ), + array( + 0 => array( 0 => array( 0 => '2dArray' ) ), + ), + array( + 0 => array( 0 => array( 0 => '3dArray' ) ), + ), + "Test union of 3d array with same keys in the value array", + ), + ); + } +} diff --git a/tests/phpunit/includes/GlobalFunctions/wfTimestampTest.php b/tests/phpunit/includes/GlobalFunctions/wfTimestampTest.php index bea496c4..4ce51c6a 100644 --- a/tests/phpunit/includes/GlobalFunctions/wfTimestampTest.php +++ b/tests/phpunit/includes/GlobalFunctions/wfTimestampTest.php @@ -21,6 +21,7 @@ class WfTimestampTest extends MediaWikiTestCase { array( -30281104, TS_MW, '19690115123456', 'Negative TS_UNIX to TS_MW' ), array( $t, TS_UNIX, 979562096, 'TS_UNIX to TS_UNIX' ), array( $t, TS_DB, '2001-01-15 12:34:56', 'TS_UNIX to TS_DB' ), + array( $t + .01, TS_MW, '20010115123456', 'TS_UNIX float to TS_MW' ), array( $t, TS_ISO_8601_BASIC, '20010115T123456Z', 'TS_ISO_8601_BASIC to TS_DB' ), diff --git a/tests/phpunit/includes/GlobalFunctions/wfUrlencodeTest.php b/tests/phpunit/includes/GlobalFunctions/wfUrlencodeTest.php index d11668b7..d4df7b00 100644 --- a/tests/phpunit/includes/GlobalFunctions/wfUrlencodeTest.php +++ b/tests/phpunit/includes/GlobalFunctions/wfUrlencodeTest.php @@ -112,6 +112,8 @@ class WfUrlencodeTest extends MediaWikiTestCase { ### Other tests // slash remain unchanged. %2F seems to break things array( '/', '/' ), + // T105265 + array( '~', '~' ), // Other 'funnies' chars array( '[]', '%5B%5D' ), diff --git a/tests/phpunit/includes/ImportLinkCacheIntegrationTest.php b/tests/phpunit/includes/ImportLinkCacheIntegrationTest.php new file mode 100644 index 00000000..1433b898 --- /dev/null +++ b/tests/phpunit/includes/ImportLinkCacheIntegrationTest.php @@ -0,0 +1,112 @@ +importStreamSource = ImportStreamSource::newFromFile( $file ); + + if ( !$this->importStreamSource->isGood() ) { + throw new Exception( "Import source for {$file} failed" ); + } + } + + public function testImportForImportSource() { + + $this->doImport( $this->importStreamSource ); + + // Imported title + $loremIpsum = Title::newFromText( 'Lorem ipsum' ); + + $this->assertSame( + $loremIpsum->getArticleID(), + $loremIpsum->getArticleID( Title::GAID_FOR_UPDATE ) + ); + + $categoryLoremIpsum = Title::newFromText( 'Category:Lorem ipsum' ); + + $this->assertSame( + $categoryLoremIpsum->getArticleID(), + $categoryLoremIpsum->getArticleID( Title::GAID_FOR_UPDATE ) + ); + + $page = new WikiPage( $loremIpsum ); + $page->doDeleteArticle( 'import test: delete page' ); + + $page = new WikiPage( $categoryLoremIpsum ); + $page->doDeleteArticle( 'import test: delete page' ); + } + + /** + * @depends testImportForImportSource + */ + public function testReImportForImportSource() { + + $this->doImport( $this->importStreamSource ); + + // ReImported title + $loremIpsum = Title::newFromText( 'Lorem ipsum' ); + + $this->assertSame( + $loremIpsum->getArticleID(), + $loremIpsum->getArticleID( Title::GAID_FOR_UPDATE ) + ); + + $categoryLoremIpsum = Title::newFromText( 'Category:Lorem ipsum' ); + + $this->assertSame( + $categoryLoremIpsum->getArticleID(), + $categoryLoremIpsum->getArticleID( Title::GAID_FOR_UPDATE ) + ); + } + + private function doImport( $importStreamSource ) { + + $importer = new WikiImporter( + $importStreamSource->value, + ConfigFactory::getDefaultInstance()->makeConfig( 'main' ) + ); + $importer->setDebug( true ); + + $reporter = new ImportReporter( + $importer, + false, + '', + false + ); + + $reporter->setContext( new RequestContext() ); + $reporter->open(); + $exception = false; + + try { + $importer->doImport(); + } catch ( Exception $e ) { + $exception = $e; + } + + $result = $reporter->close(); + + $this->assertFalse( + $exception + ); + + $this->assertTrue( + $result->isGood() + ); + } + +} diff --git a/tests/phpunit/includes/LinkFilterTest.php b/tests/phpunit/includes/LinkFilterTest.php index f2c9cb43..68081059 100644 --- a/tests/phpunit/includes/LinkFilterTest.php +++ b/tests/phpunit/includes/LinkFilterTest.php @@ -76,7 +76,7 @@ class LinkFilterTest extends MediaWikiLangTestCase { array( 'https://', '*.com', 'https://name:pass@secure.com/index.html' ), array( 'http://', 'name:pass@test.com', 'http://test.com' ), array( 'http://', 'test.com', 'http://name:pass@test.com' ), - array( 'http://', '*.test.com', 'http://a.b.c.test.com/dir/dir/file?a=6'), + array( 'http://', '*.test.com', 'http://a.b.c.test.com/dir/dir/file?a=6' ), array( null, 'http://*.test.com', 'http://www.test.com' ), array( 'mailto:', 'name@mail.test123.com', 'mailto:name@mail.test123.com' ), array( '', @@ -122,8 +122,8 @@ class LinkFilterTest extends MediaWikiLangTestCase { array( '', 'git://github.com/prwef/abc-def.git', 'git://github.com/prwef/abc-def.git' ), array( 'git://', 'github.com/', 'git://github.com/prwef/abc-def.git' ), array( 'git://', '*.github.com/', 'git://a.b.c.d.e.f.github.com/prwef/abc-def.git' ), - array( '', 'gopher://*.test.com/', 'gopher://gopher.test.com/0/v2/vstat'), - array( 'telnet://', '*.test.com', 'telnet://shell.test.com/~home/'), + array( '', 'gopher://*.test.com/', 'gopher://gopher.test.com/0/v2/vstat' ), + array( 'telnet://', '*.test.com', 'telnet://shell.test.com/~home/' ), // // The following only work in PHP >= 5.3.7, due to a bug in parse_url which eats @@ -243,10 +243,10 @@ class LinkFilterTest extends MediaWikiLangTestCase { array( 'http://*.test.*' ), array( 'http://*test.com' ), array( 'https://*' ), - array( '*://test.com'), + array( '*://test.com' ), array( 'mailto:name:pass@t*est.com' ), - array( 'http://*:888/'), - array( '*http://'), + array( 'http://*:888/' ), + array( '*http://' ), array( 'test.com/*/index' ), array( 'test.com/dir/index?arg=*' ), ); diff --git a/tests/phpunit/includes/LinkerTest.php b/tests/phpunit/includes/LinkerTest.php index 823c9330..a3efbb8d 100644 --- a/tests/phpunit/includes/LinkerTest.php +++ b/tests/phpunit/includes/LinkerTest.php @@ -93,12 +93,26 @@ class LinkerTest extends MediaWikiLangTestCase { * @covers Linker::formatAutocomments * @covers Linker::formatLinksInComment */ - public function testFormatComment( $expected, $comment, $title = false, $local = false ) { + public function testFormatComment( $expected, $comment, $title = false, $local = false, $wikiId = null ) { + $conf = new SiteConfiguration(); + $conf->settings = array( + 'wgServer' => array( + 'enwiki' => '//en.example.org', + 'dewiki' => '//de.example.org', + ), + 'wgArticlePath' => array( + 'enwiki' => '/w/$1', + 'dewiki' => '/w/$1', + ), + ); + $conf->suffixes = array( 'wiki' ); + $this->setMwGlobals( array( 'wgScript' => '/wiki/index.php', 'wgArticlePath' => '/wiki/$1', 'wgWellFormedXml' => true, 'wgCapitalLinks' => true, + 'wgConf' => $conf, ) ); if ( $title === false ) { @@ -108,11 +122,13 @@ class LinkerTest extends MediaWikiLangTestCase { $this->assertEquals( $expected, - Linker::formatComment( $comment, $title, $local ) + Linker::formatComment( $comment, $title, $local, $wikiId ) ); } - public static function provideCasesForFormatComment() { + public function provideCasesForFormatComment() { + $wikiId = 'enwiki'; // $wgConf has a fake entry for this + return array( // Linker::formatComment array( @@ -127,6 +143,10 @@ class LinkerTest extends MediaWikiLangTestCase { "'''not bolded'''", "'''not bolded'''", ), + array( + "try <script>evil</scipt> things", + "try */" + ), array( 'autocomment', "/* autocomment */", @@ -166,6 +194,16 @@ class LinkerTest extends MediaWikiLangTestCase { "/* autocomment */", null ), + array( + 'autocomment', + "/* autocomment */", + false, false + ), + array( + 'autocomment', + "/* autocomment */", + false, false, $wikiId + ), // Linker::formatLinksInComment array( 'abc link def', @@ -191,6 +229,28 @@ class LinkerTest extends MediaWikiLangTestCase { 'abc /subpage def', "abc [[/subpage]] def", ), + array( + 'abc "evil!" def', + "abc [[\"evil!\"]] def", + ), + array( + 'abc [[<script>very evil</script>]] def', + "abc [[]] def", + ), + array( + 'abc [[|]] def', + "abc [[|]] def", + ), + array( + 'abc link def', + "abc [[link]] def", + false, false + ), + array( + 'abc link def', + "abc [[link]] def", + false, false, $wikiId + ) ); } diff --git a/tests/phpunit/includes/MediaWikiTest.php b/tests/phpunit/includes/MediaWikiTest.php new file mode 100644 index 00000000..e1962436 --- /dev/null +++ b/tests/phpunit/includes/MediaWikiTest.php @@ -0,0 +1,157 @@ +setMwGlobals( array( + 'wgServer' => 'http://example.org', + 'wgScriptPath' => '/w', + 'wgScript' => '/w/index.php', + 'wgArticlePath' => '/wiki/$1', + 'wgActionPaths' => array(), + ) ); + } + + public static function provideTryNormaliseRedirect() { + return array( + array( + // View: Canonical + 'url' => 'http://example.org/wiki/Foo_Bar', + 'query' => array(), + 'title' => 'Foo_Bar', + 'redirect' => false, + ), + array( + // View: Escaped title + 'url' => 'http://example.org/wiki/Foo%20Bar', + 'query' => array(), + 'title' => 'Foo_Bar', + 'redirect' => 'http://example.org/wiki/Foo_Bar', + ), + array( + // View: Script path + 'url' => 'http://example.org/w/index.php?title=Foo_Bar', + 'query' => array( 'title' => 'Foo_Bar' ), + 'title' => 'Foo_Bar', + 'redirect' => 'http://example.org/wiki/Foo_Bar', + ), + array( + // View: Script path with implicit title from page id + 'url' => 'http://example.org/w/index.php?curid=123', + 'query' => array( 'curid' => '123' ), + 'title' => 'Foo_Bar', + 'redirect' => false, + ), + array( + // View: Script path with implicit title from revision id + 'url' => 'http://example.org/w/index.php?oldid=123', + 'query' => array( 'oldid' => '123' ), + 'title' => 'Foo_Bar', + 'redirect' => false, + ), + array( + // View: Script path without title + 'url' => 'http://example.org/w/index.php', + 'query' => array(), + 'title' => 'Main_Page', + 'redirect' => 'http://example.org/wiki/Main_Page', + ), + array( + // View: Script path with empty title + 'url' => 'http://example.org/w/index.php?title=', + 'query' => array( 'title' => '' ), + 'title' => 'Main_Page', + 'redirect' => 'http://example.org/wiki/Main_Page', + ), + array( + // View: Index with escaped title + 'url' => 'http://example.org/w/index.php?title=Foo%20Bar', + 'query' => array( 'title' => 'Foo Bar' ), + 'title' => 'Foo_Bar', + 'redirect' => 'http://example.org/wiki/Foo_Bar', + ), + array( + // View: Script path with escaped title + 'url' => 'http://example.org/w/?title=Foo_Bar', + 'query' => array( 'title' => 'Foo_Bar' ), + 'title' => 'Foo_Bar', + 'redirect' => 'http://example.org/wiki/Foo_Bar', + ), + array( + // View: Root path with escaped title + 'url' => 'http://example.org/?title=Foo_Bar', + 'query' => array( 'title' => 'Foo_Bar' ), + 'title' => 'Foo_Bar', + 'redirect' => 'http://example.org/wiki/Foo_Bar', + ), + array( + // View: Canonical with redundant query + 'url' => 'http://example.org/wiki/Foo_Bar?action=view', + 'query' => array( 'action' => 'view' ), + 'title' => 'Foo_Bar', + 'redirect' => 'http://example.org/wiki/Foo_Bar', + ), + array( + // Edit: Canonical view url with action query + 'url' => 'http://example.org/wiki/Foo_Bar?action=edit', + 'query' => array( 'action' => 'edit' ), + 'title' => 'Foo_Bar', + 'redirect' => false, + ), + array( + // View: Index with action query + 'url' => 'http://example.org/w/index.php?title=Foo_Bar&action=view', + 'query' => array( 'title' => 'Foo_Bar', 'action' => 'view' ), + 'title' => 'Foo_Bar', + 'redirect' => 'http://example.org/wiki/Foo_Bar', + ), + array( + // Edit: Index with action query + 'url' => 'http://example.org/w/index.php?title=Foo_Bar&action=edit', + 'query' => array( 'title' => 'Foo_Bar', 'action' => 'edit' ), + 'title' => 'Foo_Bar', + 'redirect' => false, + ), + ); + } + + /** + * @dataProvider provideTryNormaliseRedirect + * @covers MediaWiki::tryNormaliseRedirect + */ + public function testTryNormaliseRedirect( $url, $query, $title, $expectedRedirect = false ) { + // Set SERVER because interpolateTitle() doesn't use getRequestURL(), + // whereas tryNormaliseRedirect does(). + $_SERVER['REQUEST_URI'] = $url; + + $req = new FauxRequest( $query ); + $req->setRequestURL( $url ); + // This adds a virtual 'title' query parameter. Normally called from Setup.php + $req->interpolateTitle(); + + $titleObj = Title::newFromText( $title ); + + // Set global context since some involved code paths don't yet have context + $context = RequestContext::getMain(); + $context->setRequest( $req ); + $context->setTitle( $titleObj ); + + $mw = new MediaWiki( $context ); + + $method = new ReflectionMethod( $mw, 'tryNormaliseRedirect' ); + $method->setAccessible( true ); + $ret = $method->invoke( $mw, $titleObj ); + + $this->assertEquals( + $expectedRedirect !== false, + $ret, + 'Return true only when redirecting' + ); + + $this->assertEquals( + $expectedRedirect ?: '', + $context->getOutput()->getRedirect() + ); + } +} diff --git a/tests/phpunit/includes/MessageTest.php b/tests/phpunit/includes/MessageTest.php index 99ec2e42..9c953a6d 100644 --- a/tests/phpunit/includes/MessageTest.php +++ b/tests/phpunit/includes/MessageTest.php @@ -21,6 +21,17 @@ class MessageTest extends MediaWikiLangTestCase { $this->assertEquals( $key, $message->getKey() ); $this->assertEquals( $params, $message->getParams() ); $this->assertEquals( $expectedLang, $message->getLanguage() ); + + $messageSpecifier = $this->getMockForAbstractClass( 'MessageSpecifier' ); + $messageSpecifier->expects( $this->any() ) + ->method( 'getKey' )->will( $this->returnValue( $key ) ); + $messageSpecifier->expects( $this->any() ) + ->method( 'getParams' )->will( $this->returnValue( $params ) ); + $message = new Message( $messageSpecifier, array(), $language ); + + $this->assertEquals( $key, $message->getKey() ); + $this->assertEquals( $params, $message->getParams() ); + $this->assertEquals( $expectedLang, $message->getLanguage() ); } public static function provideConstructor() { @@ -548,4 +559,26 @@ class MessageTest extends MediaWikiLangTestCase { public function testInLanguageThrows() { wfMessage( 'foo' )->inLanguage( 123 ); } + + /** + * @covers Message::serialize + * @covers Message::unserialize + */ + public function testSerialization() { + $msg = new Message( 'parentheses' ); + $msg->rawParams( 'foo' ); + $msg->title( Title::newFromText( 'Testing' ) ); + $this->assertEquals( '(foo)', $msg->parse(), 'Sanity check' ); + $msg = unserialize( serialize( $msg ) ); + $this->assertEquals( '(foo)', $msg->parse() ); + $title = TestingAccessWrapper::newFromObject( $msg )->title; + $this->assertInstanceOf( 'Title', $title ); + $this->assertEquals( 'Testing', $title->getFullText() ); + + $msg = new Message( 'mainpage' ); + $msg->inLanguage( 'de' ); + $this->assertEquals( 'Hauptseite', $msg->plain(), 'Sanity check' ); + $msg = unserialize( serialize( $msg ) ); + $this->assertEquals( 'Hauptseite', $msg->plain() ); + } } diff --git a/tests/phpunit/includes/MimeMagicTest.php b/tests/phpunit/includes/MimeMagicTest.php index 742d3827..3c45f305 100644 --- a/tests/phpunit/includes/MimeMagicTest.php +++ b/tests/phpunit/includes/MimeMagicTest.php @@ -1,5 +1,5 @@ getRevision() ); $this->assertNotNull( - WikiPage::factory( $newTitle)->getRevision() + WikiPage::factory( $newTitle )->getRevision() ); } } diff --git a/tests/phpunit/includes/OutputPageTest.php b/tests/phpunit/includes/OutputPageTest.php index 6c6d95ee..f0d905e5 100644 --- a/tests/phpunit/includes/OutputPageTest.php +++ b/tests/phpunit/includes/OutputPageTest.php @@ -141,53 +141,36 @@ class OutputPageTest extends MediaWikiTestCase { // Load module script only array( array( 'test.foo', ResourceLoaderModule::TYPE_SCRIPTS ), - ' -' + "" ), array( // Don't condition wrap raw modules (like the startup module) array( 'test.raw', ResourceLoaderModule::TYPE_SCRIPTS ), - ' -' + '' ), // Load module styles only // This also tests the order the modules are put into the url array( array( array( 'test.baz', 'test.foo', 'test.bar' ), ResourceLoaderModule::TYPE_STYLES ), - ' -' + + '' ), // Load private module (only=scripts) array( array( 'test.quux', ResourceLoaderModule::TYPE_SCRIPTS ), - ' -' + "" ), // Load private module (combined) array( array( 'test.quux', ResourceLoaderModule::TYPE_COMBINED ), - ' -' - ), - // Load module script with ESI - array( - array( 'test.foo', ResourceLoaderModule::TYPE_SCRIPTS, true ), - ' -' - ), - // Load module styles with ESI - array( - array( 'test.foo', ResourceLoaderModule::TYPE_STYLES, true ), - ' -', + "" ), // Load no modules array( @@ -197,19 +180,17 @@ mw.loader.implement("test.quux",function($,jQuery){mw.test.baz({token:123});},{" // noscript group array( array( 'test.noscript', ResourceLoaderModule::TYPE_STYLES ), - ' -' + '' ), // Load two modules in separate groups array( array( array( 'test.group.foo', 'test.group.bar' ), ResourceLoaderModule::TYPE_COMBINED ), - ' - -' + "\n" + . "" ), ); } @@ -226,7 +207,6 @@ document.write("\u003Cscript src=\"http://127.0.0.1:8080/w/load.php?debug=false\ public function testMakeResourceLoaderLink( $args, $expectedHtml ) { $this->setMwGlobals( array( 'wgResourceLoaderDebug' => false, - 'wgResourceLoaderUseESI' => true, 'wgLoadScript' => 'http://127.0.0.1:8080/w/load.php', // Affects whether CDATA is inserted 'wgWellFormedXml' => false, @@ -244,63 +224,141 @@ document.write("\u003Cscript src=\"http://127.0.0.1:8080/w/load.php?debug=false\ 'test.foo' => new ResourceLoaderTestModule( array( 'script' => 'mw.test.foo( { a: true } );', 'styles' => '.mw-test-foo { content: "style"; }', - )), + ) ), 'test.bar' => new ResourceLoaderTestModule( array( 'script' => 'mw.test.bar( { a: true } );', 'styles' => '.mw-test-bar { content: "style"; }', - )), + ) ), 'test.baz' => new ResourceLoaderTestModule( array( 'script' => 'mw.test.baz( { a: true } );', 'styles' => '.mw-test-baz { content: "style"; }', - )), + ) ), 'test.quux' => new ResourceLoaderTestModule( array( 'script' => 'mw.test.baz( { token: 123 } );', 'styles' => '/* pref-animate=off */ .mw-icon { transition: none; }', 'group' => 'private', - )), + ) ), 'test.raw' => new ResourceLoaderTestModule( array( 'script' => 'mw.test.baz( { token: 123 } );', 'isRaw' => true, - )), + ) ), 'test.noscript' => new ResourceLoaderTestModule( array( 'styles' => '.mw-test-noscript { content: "style"; }', 'group' => 'noscript', - )), + ) ), 'test.group.bar' => new ResourceLoaderTestModule( array( 'styles' => '.mw-group-bar { content: "style"; }', 'group' => 'bar', - )), + ) ), 'test.group.foo' => new ResourceLoaderTestModule( array( 'styles' => '.mw-group-foo { content: "style"; }', 'group' => 'foo', - )), + ) ), ) ); $links = $method->invokeArgs( $out, $args ); - // Strip comments to avoid variation due to wgDBname in WikiID and cache key - $actualHtml = preg_replace( '#/\*[^*]+\*/#', '', $links['html'] ); + $actualHtml = implode( "\n", $links['html'] ); $this->assertEquals( $expectedHtml, $actualHtml ); } + + /** + * @dataProvider provideVaryHeaders + * @covers OutputPage::addVaryHeader + * @covers OutputPage::getVaryHeader + * @covers OutputPage::getXVO + */ + public function testVaryHeaders( $calls, $vary, $xvo ) { + // get rid of default Vary fields + $outputPage = $this->getMockBuilder( 'OutputPage' ) + ->setConstructorArgs( array( new RequestContext() ) ) + ->setMethods( array( 'getCacheVaryCookies' ) ) + ->getMock(); + $outputPage->expects( $this->any() ) + ->method( 'getCacheVaryCookies' ) + ->will( $this->returnValue( array() ) ); + TestingAccessWrapper::newFromObject( $outputPage )->mVaryHeader = array(); + + foreach ( $calls as $call ) { + call_user_func_array( array( $outputPage, 'addVaryHeader' ), $call ); + } + $this->assertEquals( $vary, $outputPage->getVaryHeader(), 'Vary:' ); + $this->assertEquals( $xvo, $outputPage->getXVO(), 'X-Vary-Options:' ); + } + + public function provideVaryHeaders() { + // note: getXVO() automatically adds Vary: Cookie + return array( + array( // single header + array( + array( 'Cookie' ), + ), + 'Vary: Cookie', + 'X-Vary-Options: Cookie', + ), + array( // non-unique headers + array( + array( 'Cookie' ), + array( 'Accept-Language' ), + array( 'Cookie' ), + ), + 'Vary: Cookie, Accept-Language', + 'X-Vary-Options: Cookie,Accept-Language', + ), + array( // two headers with single options + array( + array( 'Cookie', array( 'string-contains=phpsessid' ) ), + array( 'Accept-Language', array( 'string-contains=en' ) ), + ), + 'Vary: Cookie, Accept-Language', + 'X-Vary-Options: Cookie;string-contains=phpsessid,Accept-Language;string-contains=en', + ), + array( // one header with multiple options + array( + array( 'Cookie', array( 'string-contains=phpsessid', 'string-contains=userId' ) ), + ), + 'Vary: Cookie', + 'X-Vary-Options: Cookie;string-contains=phpsessid;string-contains=userId', + ), + array( // Duplicate option + array( + array( 'Cookie', array( 'string-contains=phpsessid' ) ), + array( 'Cookie', array( 'string-contains=phpsessid' ) ), + array( 'Accept-Language', array( 'string-contains=en', 'string-contains=en' ) ), + + + ), + 'Vary: Cookie, Accept-Language', + 'X-Vary-Options: Cookie;string-contains=phpsessid,Accept-Language;string-contains=en', + ), + array( // Same header, different options + array( + array( 'Cookie', array( 'string-contains=phpsessid' ) ), + array( 'Cookie', array( 'string-contains=userId' ) ), + ), + 'Vary: Cookie', + 'X-Vary-Options: Cookie;string-contains=phpsessid;string-contains=userId', + ), + ); + } } /** * MessageBlobStore that doesn't do anything */ class NullMessageBlobStore extends MessageBlobStore { - public function get ( ResourceLoader $resourceLoader, $modules, $lang ) { + public function get( ResourceLoader $resourceLoader, $modules, $lang ) { return array(); } - public function insertMessageBlob ( $name, ResourceLoaderModule $module, $lang ) { + public function insertMessageBlob( $name, ResourceLoaderModule $module, $lang ) { return false; } - public function updateModule ( $name, ResourceLoaderModule $module, $lang ) { + public function updateModule( $name, ResourceLoaderModule $module, $lang ) { return; } - public function updateMessage ( $key ) { + public function updateMessage( $key ) { } public function clear() { } } - diff --git a/tests/phpunit/includes/PrefixSearchTest.php b/tests/phpunit/includes/PrefixSearchTest.php index d63541b7..afd10e9a 100644 --- a/tests/phpunit/includes/PrefixSearchTest.php +++ b/tests/phpunit/includes/PrefixSearchTest.php @@ -6,6 +6,11 @@ class PrefixSearchTest extends MediaWikiLangTestCase { public function addDBData() { + if ( !$this->isWikitextNS( NS_MAIN ) ) { + // tests are skipped if NS_MAIN is not wikitext + return; + } + $this->insertPage( 'Sandbox' ); $this->insertPage( 'Bar' ); $this->insertPage( 'Example' ); diff --git a/tests/phpunit/includes/SanitizerTest.php b/tests/phpunit/includes/SanitizerTest.php index c615c460..d3dc512b 100644 --- a/tests/phpunit/includes/SanitizerTest.php +++ b/tests/phpunit/includes/SanitizerTest.php @@ -6,6 +6,11 @@ */ class SanitizerTest extends MediaWikiTestCase { + protected function tearDown() { + MWTidy::destroySingleton(); + parent::tearDown(); + } + /** * @covers Sanitizer::decodeCharReferences */ @@ -93,9 +98,7 @@ class SanitizerTest extends MediaWikiTestCase { * @param bool $escaped Whether sanitizer let the tag in or escape it (ie: '<video>') */ public function testRemovehtmltagsOnHtml5Tags( $tag, $escaped ) { - $this->setMwGlobals( array( - 'wgUseTidy' => false - ) ); + MWTidy::setInstance( false ); if ( $escaped ) { $this->assertEquals( "<$tag>", @@ -157,7 +160,7 @@ class SanitizerTest extends MediaWikiTestCase { * @covers Sanitizer::removeHTMLtags */ public function testRemoveHTMLtags( $input, $output, $msg = null ) { - $GLOBALS['wgUseTidy'] = false; + MWTidy::setInstance( false ); $this->assertEquals( $output, Sanitizer::removeHTMLtags( $input ), $msg ); } @@ -360,5 +363,4 @@ class SanitizerTest extends MediaWikiTestCase { array( '<script>foo</script>', '' ), ); } - } diff --git a/tests/phpunit/includes/SanitizerValidateEmailTest.php b/tests/phpunit/includes/SanitizerValidateEmailTest.php index 14911f04..f47e74e2 100644 --- a/tests/phpunit/includes/SanitizerValidateEmailTest.php +++ b/tests/phpunit/includes/SanitizerValidateEmailTest.php @@ -5,7 +5,7 @@ * @todo all test methods in this class should be refactored and... * use a single test method and a single data provider... */ -class SanitizerValidateEmailTest extends MediaWikiTestCase { +class SanitizerValidateEmailTest extends PHPUnit_Framework_TestCase { private function checkEmail( $addr, $expected = true, $msg = '' ) { if ( $msg == '' ) { diff --git a/tests/phpunit/includes/StatusTest.php b/tests/phpunit/includes/StatusTest.php index c013f4fc..291ed315 100644 --- a/tests/phpunit/includes/StatusTest.php +++ b/tests/phpunit/includes/StatusTest.php @@ -372,7 +372,7 @@ class StatusTest extends MediaWikiLangTestCase { ); $status = new Status(); - $status->warning( new Message( 'fooBar!', array( 'foo', 'bar' ) ) ); + $status->warning( new Message( 'fooBar!', array( 'foo', 'bar' ) ) ); $testCases['1MessageWarning'] = array( $status, "", @@ -449,7 +449,7 @@ class StatusTest extends MediaWikiLangTestCase { // ); $status = new Status(); - $status->warning( new Message( 'fooBar!', array( 'foo', 'bar' ) ) ); + $status->warning( new Message( 'fooBar!', array( 'foo', 'bar' ) ) ); $testCases['1MessageWarning'] = array( $status, array( 'foo', 'bar' ), diff --git a/tests/phpunit/includes/TemplateParserTest.php b/tests/phpunit/includes/TemplateParserTest.php index 81854ff3..3b37f4a4 100644 --- a/tests/phpunit/includes/TemplateParserTest.php +++ b/tests/phpunit/includes/TemplateParserTest.php @@ -57,7 +57,20 @@ class TemplateParserTest extends MediaWikiTestCase { array(), false, 'RuntimeException', - ) + ), + array( + 'has_partial', + array( + 'planet' => 'world', + ), + "Partial hello world!\n in here\n", + ), + array( + 'bad_partial', + array(), + false, + 'Exception', + ), ); } } diff --git a/tests/phpunit/includes/TestingAccessWrapper.php b/tests/phpunit/includes/TestingAccessWrapper.php index 84c0f9b5..63d89719 100644 --- a/tests/phpunit/includes/TestingAccessWrapper.php +++ b/tests/phpunit/includes/TestingAccessWrapper.php @@ -34,16 +34,42 @@ class TestingAccessWrapper { return $methodReflection->invokeArgs( $this->object, $args ); } - public function __set( $name, $value ) { + /** + * ReflectionClass::getProperty() fails if the private property is defined + * in a parent class. This works more like ReflectionClass::getMethod(). + */ + private function getProperty( $name ) { $classReflection = new ReflectionClass( $this->object ); - $propertyReflection = $classReflection->getProperty( $name ); + try { + return $classReflection->getProperty( $name ); + } catch ( ReflectionException $ex ) { + while ( true ) { + $classReflection = $classReflection->getParentClass(); + if ( !$classReflection ) { + throw $ex; + } + try { + $propertyReflection = $classReflection->getProperty( $name ); + } catch ( ReflectionException $ex2 ) { + continue; + } + if ( $propertyReflection->isPrivate() ) { + return $propertyReflection; + } else { + throw $ex; + } + } + } + } + + public function __set( $name, $value ) { + $propertyReflection = $this->getProperty( $name ); $propertyReflection->setAccessible( true ); $propertyReflection->setValue( $this->object, $value ); } public function __get( $name ) { - $classReflection = new ReflectionClass( $this->object ); - $propertyReflection = $classReflection->getProperty( $name ); + $propertyReflection = $this->getProperty( $name ); $propertyReflection->setAccessible( true ); return $propertyReflection->getValue( $this->object ); } diff --git a/tests/phpunit/includes/TestingAccessWrapperTest.php b/tests/phpunit/includes/TestingAccessWrapperTest.php index 7e5b91a1..fc54afae 100644 --- a/tests/phpunit/includes/TestingAccessWrapperTest.php +++ b/tests/phpunit/includes/TestingAccessWrapperTest.php @@ -14,18 +14,36 @@ class TestingAccessWrapperTest extends MediaWikiTestCase { function testGetProperty() { $this->assertSame( 1, $this->wrapped->property ); + $this->assertSame( 42, $this->wrapped->privateProperty ); + $this->assertSame( 9000, $this->wrapped->privateParentProperty ); } function testSetProperty() { $this->wrapped->property = 10; $this->assertSame( 10, $this->wrapped->property ); $this->assertSame( 10, $this->raw->getProperty() ); + + $this->wrapped->privateProperty = 11; + $this->assertSame( 11, $this->wrapped->privateProperty ); + $this->assertSame( 11, $this->raw->getPrivateProperty() ); + + $this->wrapped->privateParentProperty = 12; + $this->assertSame( 12, $this->wrapped->privateParentProperty ); + $this->assertSame( 12, $this->raw->getPrivateParentProperty() ); } function testCallMethod() { $this->wrapped->incrementPropertyValue(); $this->assertSame( 2, $this->wrapped->property ); $this->assertSame( 2, $this->raw->getProperty() ); + + $this->wrapped->incrementPrivatePropertyValue(); + $this->assertSame( 43, $this->wrapped->privateProperty ); + $this->assertSame( 43, $this->raw->getPrivateProperty() ); + + $this->wrapped->incrementPrivateParentPropertyValue(); + $this->assertSame( 9001, $this->wrapped->privateParentProperty ); + $this->assertSame( 9001, $this->raw->getPrivateParentProperty() ); } function testCallMethodTwoArgs() { diff --git a/tests/phpunit/includes/TitleArrayFromResultTest.php b/tests/phpunit/includes/TitleArrayFromResultTest.php index 0f7069ae..6654a5b6 100644 --- a/tests/phpunit/includes/TitleArrayFromResultTest.php +++ b/tests/phpunit/includes/TitleArrayFromResultTest.php @@ -4,7 +4,7 @@ * @author Adam Shorland * @covers TitleArrayFromResult */ -class TitleArrayFromResultTest extends MediaWikiTestCase { +class TitleArrayFromResultTest extends PHPUnit_Framework_TestCase { private function getMockResultWrapper( $row = null, $numRows = 1 ) { $resultWrapper = $this->getMockBuilder( 'ResultWrapper' ) diff --git a/tests/phpunit/includes/TitlePermissionTest.php b/tests/phpunit/includes/TitlePermissionTest.php index 022c7d53..f588ed63 100644 --- a/tests/phpunit/includes/TitlePermissionTest.php +++ b/tests/phpunit/includes/TitlePermissionTest.php @@ -664,7 +664,7 @@ class TitlePermissionTest extends MediaWikiLangTestCase { $this->setTitle( NS_MAIN, "test page" ); $this->title->mTitleProtection['permission'] = ''; $this->title->mTitleProtection['user'] = $this->user->getID(); - $this->title->mTitleProtection['expiry'] = wfGetDB( DB_SLAVE )->getInfinity(); + $this->title->mTitleProtection['expiry'] = 'infinity'; $this->title->mTitleProtection['reason'] = 'test'; $this->title->mCascadeRestriction = false; @@ -753,8 +753,14 @@ class TitlePermissionTest extends MediaWikiLangTestCase { $prev = time(); $now = time() + 120; $this->user->mBlockedby = $this->user->getId(); - $this->user->mBlock = new Block( '127.0.8.1', 0, $this->user->getId(), - 'no reason given', $prev + 3600, 1, 0 ); + $this->user->mBlock = new Block( array( + 'address' => '127.0.8.1', + 'by' => $this->user->getId(), + 'reason' => 'no reason given', + 'timestamp' => $prev + 3600, + 'auto' => true, + 'expiry' => 0 + ) ); $this->user->mBlock->mTimestamp = 0; $this->assertEquals( array( array( 'autoblockedtext', '[[User:Useruser|Useruser]]', 'no reason given', '127.0.0.1', @@ -770,8 +776,14 @@ class TitlePermissionTest extends MediaWikiLangTestCase { global $wgLocalTZoffset; $wgLocalTZoffset = -60; $this->user->mBlockedby = $this->user->getName(); - $this->user->mBlock = new Block( '127.0.8.1', 0, $this->user->getId(), - 'no reason given', $now, 0, 10 ); + $this->user->mBlock = new Block( array( + 'address' => '127.0.8.1', + 'by' => $this->user->getId(), + 'reason' => 'no reason given', + 'timestamp' => $now, + 'auto' => false, + 'expiry' => 10, + ) ); $this->assertEquals( array( array( 'blockedtext', '[[User:Useruser|Useruser]]', 'no reason given', '127.0.0.1', 'Useruser', null, '23:00, 31 December 1969', '127.0.8.1', diff --git a/tests/phpunit/includes/TitleTest.php b/tests/phpunit/includes/TitleTest.php index d55f958b..a2c6f23d 100644 --- a/tests/phpunit/includes/TitleTest.php +++ b/tests/phpunit/includes/TitleTest.php @@ -1,6 +1,7 @@ B' ), - array( 'A | B' ), + array( 'A [ B', 'title-invalid-characters' ), + array( 'A ] B', 'title-invalid-characters' ), + array( 'A { B', 'title-invalid-characters' ), + array( 'A } B', 'title-invalid-characters' ), + array( 'A < B', 'title-invalid-characters' ), + array( 'A > B', 'title-invalid-characters' ), + array( 'A | B', 'title-invalid-characters' ), // URL encoding - array( 'A%20B' ), - array( 'A%23B' ), - array( 'A%2523B' ), + array( 'A%20B', 'title-invalid-characters' ), + array( 'A%23B', 'title-invalid-characters' ), + array( 'A%2523B', 'title-invalid-characters' ), // XML/HTML character entity references // Note: Commented out because they are not marked invalid by the PHP test as // Title::newFromText runs Sanitizer::decodeCharReferencesAndNormalize first. @@ -102,29 +103,30 @@ class TitleTest extends MediaWikiTestCase { //'A é B', //'A é B', // Subject of NS_TALK does not roundtrip to NS_MAIN - array( 'Talk:File:Example.svg' ), + array( 'Talk:File:Example.svg', 'title-invalid-talk-namespace' ), // Directory navigation - array( '.' ), - array( '..' ), - array( './Sandbox' ), - array( '../Sandbox' ), - array( 'Foo/./Sandbox' ), - array( 'Foo/../Sandbox' ), - array( 'Sandbox/.' ), - array( 'Sandbox/..' ), + array( '.', 'title-invalid-relative' ), + array( '..', 'title-invalid-relative' ), + array( './Sandbox', 'title-invalid-relative' ), + array( '../Sandbox', 'title-invalid-relative' ), + array( 'Foo/./Sandbox', 'title-invalid-relative' ), + array( 'Foo/../Sandbox', 'title-invalid-relative' ), + array( 'Sandbox/.', 'title-invalid-relative' ), + array( 'Sandbox/..', 'title-invalid-relative' ), // Tilde - array( 'A ~~~ Name' ), - array( 'A ~~~~ Signature' ), - array( 'A ~~~~~ Timestamp' ), - array( str_repeat( 'x', 256 ) ), + array( 'A ~~~ Name', 'title-invalid-magic-tilde' ), + array( 'A ~~~~ Signature', 'title-invalid-magic-tilde' ), + array( 'A ~~~~~ Timestamp', 'title-invalid-magic-tilde' ), + // Length + array( str_repeat( 'x', 256 ), 'title-invalid-too-long' ), // Namespace prefix without actual title - array( 'Talk:' ), - array( 'Talk:#' ), - array( 'Category: ' ), - array( 'Category: #bar' ), + array( 'Talk:', 'title-invalid-empty' ), + array( 'Talk:#', 'title-invalid-empty' ), + array( 'Category: ', 'title-invalid-empty' ), + array( 'Category: #bar', 'title-invalid-empty' ), // interwiki prefix - array( 'localtestiw: Talk: # anchor' ), - array( 'localtestiw: Talk:' ) + array( 'localtestiw: Talk: # anchor', 'title-invalid-empty' ), + array( 'localtestiw: Talk:', 'title-invalid-empty' ) ); } @@ -143,7 +145,7 @@ class TitleTest extends MediaWikiTestCase { } ) ) - )); + ) ); } /** @@ -163,9 +165,14 @@ class TitleTest extends MediaWikiTestCase { * @dataProvider provideInvalidSecureAndSplit * @note This mainly tests MediaWikiTitleCodec::parseTitle(). */ - public function testSecureAndSplitInvalid( $text ) { + public function testSecureAndSplitInvalid( $text, $expectedErrorMessage ) { $this->secureAndSplitGlobals(); - $this->assertNull( Title::newFromText( $text ), "Invalid: $text" ); + try { + Title::newFromTextThrow( $text ); // should throw + $this->assertTrue( false, "Invalid: $text" ); + } catch ( MalformedTitleException $ex ) { + $this->assertEquals( $expectedErrorMessage, $ex->getErrorMessage(), "Invalid: $text" ); + } } public static function provideConvertByteClassToUnicodeClass() { @@ -631,4 +638,26 @@ class TitleTest extends MediaWikiTestCase { $title = Title::makeTitle( NS_MAIN, 'Interwiki link', '', 'externalwiki' ); $this->assertTrue( $title->isAlwaysKnown() ); } + + /** + * @covers Title::exists + */ + public function testExists() { + $title = Title::makeTitle( NS_PROJECT, 'New page' ); + $linkCache = LinkCache::singleton(); + + $article = new Article( $title ); + $page = $article->getPage(); + $page->doEditContent( new WikitextContent( 'Some [[link]]' ), 'summary' ); + + // Tell Title it doesn't know whether it exists + $title->mArticleID = -1; + + // Tell the link cache it doesn't exists when it really does + $linkCache->clearLink( $title ); + $linkCache->addBadLinkObj( $title ); + + $this->assertEquals( false, $title->exists(), 'exists() should rely on link cache unless GAID_FOR_UPDATE is used' ); + $this->assertEquals( true, $title->exists( Title::GAID_FOR_UPDATE ), 'exists() should re-query database when GAID_FOR_UPDATE is used' ); + } } diff --git a/tests/phpunit/includes/UserTest.php b/tests/phpunit/includes/UserTest.php index b74a7ead..77132bbb 100644 --- a/tests/phpunit/includes/UserTest.php +++ b/tests/phpunit/includes/UserTest.php @@ -307,9 +307,30 @@ class UserTest extends MediaWikiTestCase { */ public function testCheckPasswordValidity() { $this->setMwGlobals( array( - 'wgMinimalPasswordLength' => 6, - 'wgMaximalPasswordLength' => 30, + 'wgPasswordPolicy' => array( + 'policies' => array( + 'sysop' => array( + 'MinimalPasswordLength' => 8, + 'MinimumPasswordLengthToLogin' => 1, + 'PasswordCannotMatchUsername' => 1, + ), + 'default' => array( + 'MinimalPasswordLength' => 6, + 'PasswordCannotMatchUsername' => true, + 'PasswordCannotMatchBlacklist' => true, + 'MaximalPasswordLength' => 30, + ), + ), + 'checks' => array( + 'MinimalPasswordLength' => 'PasswordPolicyChecks::checkMinimalPasswordLength', + 'MinimumPasswordLengthToLogin' => 'PasswordPolicyChecks::checkMinimumPasswordLengthToLogin', + 'PasswordCannotMatchUsername' => 'PasswordPolicyChecks::checkPasswordCannotMatchUsername', + 'PasswordCannotMatchBlacklist' => 'PasswordPolicyChecks::checkPasswordCannotMatchBlacklist', + 'MaximalPasswordLength' => 'PasswordPolicyChecks::checkMaximalPasswordLength', + ), + ), ) ); + $user = User::newFromName( 'Useruser' ); // Sanity $this->assertTrue( $user->isValidPassword( 'Password1234' ) ); @@ -425,4 +446,109 @@ class UserTest extends MediaWikiTestCase { $this->assertFalse( $user->isLoggedIn() ); $this->assertTrue( $user->isAnon() ); } + + /** + * @covers User::checkAndSetTouched + */ + public function testCheckAndSetTouched() { + $user = TestingAccessWrapper::newFromObject( User::newFromName( 'UTSysop' ) ); + $this->assertTrue( $user->isLoggedIn() ); + + $touched = $user->getDBTouched(); + $this->assertTrue( + $user->checkAndSetTouched(), "checkAndSetTouched() succeded" ); + $this->assertGreaterThan( + $touched, $user->getDBTouched(), "user_touched increased with casOnTouched()" ); + + $touched = $user->getDBTouched(); + $this->assertTrue( + $user->checkAndSetTouched(), "checkAndSetTouched() succeded #2" ); + $this->assertGreaterThan( + $touched, $user->getDBTouched(), "user_touched increased with casOnTouched() #2" ); + } + + public static function setExtendedLoginCookieDataProvider() { + $data = array(); + $now = time(); + + $secondsInDay = 86400; + + // Arbitrary durations, in units of days, to ensure it chooses the + // right one. There is a 5-minute grace period (see testSetExtendedLoginCookie) + // to work around slow tests, since we're not currently mocking time() for PHP. + + $durationOne = $secondsInDay * 5; + $durationTwo = $secondsInDay * 29; + $durationThree = $secondsInDay * 17; + + // If $wgExtendedLoginCookieExpiration is null, then the expiry passed to + // set cookie is time() + $wgCookieExpiration + $data[] = array( + null, + $durationOne, + $now + $durationOne, + ); + + // If $wgExtendedLoginCookieExpiration isn't null, then the expiry passed to + // set cookie is $now + $wgExtendedLoginCookieExpiration + $data[] = array( + $durationTwo, + $durationThree, + $now + $durationTwo, + ); + + return $data; + } + + /** + * @dataProvider setExtendedLoginCookieDataProvider + * @covers User::getRequest + * @covers User::setCookie + * @backupGlobals enabled + */ + public function testSetExtendedLoginCookie( + $extendedLoginCookieExpiration, + $cookieExpiration, + $expectedExpiry + ) { + $this->setMwGlobals( array( + 'wgExtendedLoginCookieExpiration' => $extendedLoginCookieExpiration, + 'wgCookieExpiration' => $cookieExpiration, + ) ); + + $response = $this->getMock( 'WebResponse' ); + $setcookieSpy = $this->any(); + $response->expects( $setcookieSpy ) + ->method( 'setcookie' ); + + $request = new MockWebRequest( $response ); + $user = new UserProxy( User::newFromSession( $request ) ); + $user->setExtendedLoginCookie( 'name', 'value', true ); + + $setcookieInvocations = $setcookieSpy->getInvocations(); + $setcookieInvocation = end( $setcookieInvocations ); + $actualExpiry = $setcookieInvocation->parameters[ 2 ]; + + // TODO: ± 300 seconds compensates for + // slow-running tests. However, the dependency on the time + // function should be removed. This requires some way + // to mock/isolate User->setExtendedLoginCookie's call to time() + $this->assertEquals( $expectedExpiry, $actualExpiry, '', 300 ); + } +} + +class UserProxy extends User { + + /** + * @var User + */ + protected $user; + + public function __construct( User $user ) { + $this->user = $user; + } + + public function setExtendedLoginCookie( $name, $value, $secure ) { + $this->user->setExtendedLoginCookie( $name, $value, $secure ); + } } diff --git a/tests/phpunit/includes/WikiMapTest.php b/tests/phpunit/includes/WikiMapTest.php new file mode 100644 index 00000000..9233416c --- /dev/null +++ b/tests/phpunit/includes/WikiMapTest.php @@ -0,0 +1,108 @@ +settings = array( + 'wgServer' => array( + 'enwiki' => 'http://en.example.org', + 'ruwiki' => '//ru.example.org', + ), + 'wgArticlePath' => array( + 'enwiki' => '/w/$1', + 'ruwiki' => '/wiki/$1', + ), + ); + $conf->suffixes = array( 'wiki' ); + $this->setMwGlobals( array( + 'wgConf' => $conf, + ) ); + } + + public function provideGetWiki() { + $enwiki = new WikiReference( 'wiki', 'en', 'http://en.example.org', '/w/$1' ); + $ruwiki = new WikiReference( 'wiki', 'ru', '//ru.example.org', '/wiki/$1' ); + + return array( + 'unknown' => array( false, 'xyzzy' ), + 'enwiki' => array( $enwiki, 'enwiki' ), + 'ruwiki' => array( $ruwiki, 'ruwiki' ), + ); + } + + /** + * @dataProvider provideGetWiki + */ + public function testGetWiki( $expected, $wikiId ) { + $this->assertEquals( $expected, WikiMap::getWiki( $wikiId ) ); + } + + public function provideGetWikiName() { + return array( + 'unknown' => array( 'xyzzy', 'xyzzy' ), + 'enwiki' => array( 'en.example.org', 'enwiki' ), + 'ruwiki' => array( 'ru.example.org', 'ruwiki' ), + ); + } + + /** + * @dataProvider provideGetWikiName + */ + public function testGetWikiName( $expected, $wikiId ) { + $this->assertEquals( $expected, WikiMap::getWikiName( $wikiId ) ); + } + + public function provideMakeForeignLink() { + return array( + 'unknown' => array( false, 'xyzzy', 'Foo' ), + 'enwiki' => array( 'Foo', 'enwiki', 'Foo', ), + 'ruwiki' => array( 'вар', 'ruwiki', 'Фу', 'вар' ), + ); + } + + /** + * @dataProvider provideMakeForeignLink + */ + public function testMakeForeignLink( $expected, $wikiId, $page, $text = null ) { + $this->assertEquals( $expected, WikiMap::makeForeignLink( $wikiId, $page, $text ) ); + } + + public function provideForeignUserLink() { + return array( + 'unknown' => array( false, 'xyzzy', 'Foo' ), + 'enwiki' => array( 'User:Foo', 'enwiki', 'Foo', ), + 'ruwiki' => array( 'вар', 'ruwiki', 'Фу', 'вар' ), + ); + } + + /** + * @dataProvider provideForeignUserLink + */ + public function testForeignUserLink( $expected, $wikiId, $user, $text = null ) { + $this->assertEquals( $expected, WikiMap::foreignUserLink( $wikiId, $user, $text ) ); + } + + public function provideGetForeignURL() { + return array( + 'unknown' => array( false, 'xyzzy', 'Foo' ), + 'enwiki' => array( 'http://en.example.org/w/Foo', 'enwiki', 'Foo', ), + 'ruwiki with fragement' => array( '//ru.example.org/wiki/%D0%A4%D1%83#%D0%B2%D0%B0%D1%80', 'ruwiki', 'Фу', 'вар' ), + ); + } + + /** + * @dataProvider provideGetForeignURL + */ + public function testGetForeignURL( $expected, $wikiId, $page, $fragment = null ) { + $this->assertEquals( $expected, WikiMap::getForeignURL( $wikiId, $page, $fragment ) ); + } + +} + diff --git a/tests/phpunit/includes/WikiReferenceTest.php b/tests/phpunit/includes/WikiReferenceTest.php new file mode 100644 index 00000000..4fe2e855 --- /dev/null +++ b/tests/phpunit/includes/WikiReferenceTest.php @@ -0,0 +1,80 @@ + array( 'foo.bar', 'http://foo.bar' ), + 'https' => array( 'foo.bar', 'http://foo.bar' ), + + // apparently, this is the expected behavior + 'invalid' => array( 'purple kittens', 'purple kittens' ), + ); + } + + /** + * @dataProvider provideGetDisplayName + */ + public function testGetDisplayName( $expected, $canonicalServer ) { + $reference = new WikiReference( 'wiki', 'xx', $canonicalServer, '/wiki/$1' ); + $this->assertEquals( $expected, $reference->getDisplayName() ); + } + + public function testGetCanonicalServer() { + $reference = new WikiReference( 'wiki', 'xx', 'https://acme.com', '/wiki/$1', '//acme.com' ); + $this->assertEquals( 'https://acme.com', $reference->getCanonicalServer() ); + } + + public function provideGetCanonicalUrl() { + return array( + 'no fragement' => array( 'https://acme.com/wiki/Foo', 'https://acme.com', '//acme.com', '/wiki/$1', 'Foo', null ), + 'empty fragement' => array( 'https://acme.com/wiki/Foo', 'https://acme.com', '//acme.com', '/wiki/$1', 'Foo', '' ), + 'fragment' => array( 'https://acme.com/wiki/Foo#Bar', 'https://acme.com', '//acme.com', '/wiki/$1', 'Foo', 'Bar' ), + 'double fragment' => array( 'https://acme.com/wiki/Foo#Bar%23Xus', 'https://acme.com', '//acme.com', '/wiki/$1', 'Foo', 'Bar#Xus' ), + 'escaped fragement' => array( 'https://acme.com/wiki/Foo%23Bar', 'https://acme.com', '//acme.com', '/wiki/$1', 'Foo#Bar', null ), + 'empty path' => array( 'https://acme.com/Foo', 'https://acme.com', '//acme.com', '/$1', 'Foo', null ), + ); + } + + /** + * @dataProvider provideGetCanonicalUrl + */ + public function testGetCanonicalUrl( $expected, $canonicalServer, $server, $path, $page, $fragmentId ) { + $reference = new WikiReference( 'wiki', 'xx', $canonicalServer, $path, $server ); + $this->assertEquals( $expected, $reference->getCanonicalUrl( $page, $fragmentId ) ); + } + + /** + * @dataProvider provideGetCanonicalUrl + * @note getUrl is an alias for getCanonicalUrl + */ + public function testGetUrl( $expected, $canonicalServer, $server, $path, $page, $fragmentId ) { + $reference = new WikiReference( 'wiki', 'xx', $canonicalServer, $path, $server ); + $this->assertEquals( $expected, $reference->getUrl( $page, $fragmentId ) ); + } + + public function provideGetFullUrl() { + return array( + 'no fragement' => array( '//acme.com/wiki/Foo', 'https://acme.com', '//acme.com', '/wiki/$1', 'Foo', null ), + 'empty fragement' => array( '//acme.com/wiki/Foo', 'https://acme.com', '//acme.com', '/wiki/$1', 'Foo', '' ), + 'fragment' => array( '//acme.com/wiki/Foo#Bar', 'https://acme.com', '//acme.com', '/wiki/$1', 'Foo', 'Bar' ), + 'double fragment' => array( '//acme.com/wiki/Foo#Bar%23Xus', 'https://acme.com', '//acme.com', '/wiki/$1', 'Foo', 'Bar#Xus' ), + 'escaped fragement' => array( '//acme.com/wiki/Foo%23Bar', 'https://acme.com', '//acme.com', '/wiki/$1', 'Foo#Bar', null ), + 'empty path' => array( '//acme.com/Foo', 'https://acme.com', '//acme.com', '/$1', 'Foo', null ), + ); + } + + /** + * @dataProvider provideGetFullUrl + */ + public function testGetFullUrl( $expected, $canonicalServer, $server, $path, $page, $fragmentId ) { + $reference = new WikiReference( 'wiki', 'xx', $canonicalServer, $path, $server ); + $this->assertEquals( $expected, $reference->getFullUrl( $page, $fragmentId ) ); + } + +} + diff --git a/tests/phpunit/includes/XmlJsTest.php b/tests/phpunit/includes/XmlJsTest.php index 0dbb0109..21819b7e 100644 --- a/tests/phpunit/includes/XmlJsTest.php +++ b/tests/phpunit/includes/XmlJsTest.php @@ -3,7 +3,7 @@ /** * @group Xml */ -class XmlJs extends MediaWikiTestCase { +class XmlJs extends PHPUnit_Framework_TestCase { /** * @covers XmlJsCode::__construct diff --git a/tests/phpunit/includes/XmlTest.php b/tests/phpunit/includes/XmlTest.php index 382e3d89..bea338de 100644 --- a/tests/phpunit/includes/XmlTest.php +++ b/tests/phpunit/includes/XmlTest.php @@ -154,7 +154,7 @@ class XmlTest extends MediaWikiTestCase { ' ' . ' ' . ' ' . - '' . '' . "\n" . '' . "\n" . '' . "\n" . @@ -175,7 +175,7 @@ class XmlTest extends MediaWikiTestCase { ' ' . ' ' . ' ' . - '' . '' . "\n" . '' . "\n" . '' . "\n" . @@ -209,7 +209,7 @@ class XmlTest extends MediaWikiTestCase { ' ' . ' ' . ' ' . - '' . '' . "\n" . '' . "\n" . '' . "\n" . diff --git a/tests/phpunit/includes/api/ApiBlockTest.php b/tests/phpunit/includes/api/ApiBlockTest.php index d98eec6a..575efd6d 100644 --- a/tests/phpunit/includes/api/ApiBlockTest.php +++ b/tests/phpunit/includes/api/ApiBlockTest.php @@ -53,7 +53,7 @@ class ApiBlockTest extends ApiTestCase { 'action' => 'block', 'user' => 'UTApiBlockee', 'reason' => 'Some reason', - 'token' => $tokens['blocktoken'] ), null, false, self::$users['sysop']->user ); + 'token' => $tokens['blocktoken'] ), null, false, self::$users['sysop']->getUser() ); $block = Block::newFromTarget( 'UTApiBlockee' ); @@ -68,7 +68,7 @@ class ApiBlockTest extends ApiTestCase { * @expectedException UsageException * @expectedExceptionMessage The token parameter must be set */ - public function testBlockingActionWithNoToken( ) { + public function testBlockingActionWithNoToken() { $this->doApiRequest( array( 'action' => 'block', @@ -77,7 +77,7 @@ class ApiBlockTest extends ApiTestCase { ), null, false, - self::$users['sysop']->user + self::$users['sysop']->getUser() ); } } diff --git a/tests/phpunit/includes/api/ApiEditPageTest.php b/tests/phpunit/includes/api/ApiEditPageTest.php index 3179a452..61a8ad11 100644 --- a/tests/phpunit/includes/api/ApiEditPageTest.php +++ b/tests/phpunit/includes/api/ApiEditPageTest.php @@ -27,9 +27,14 @@ class ApiEditPageTest extends ApiTestCase { $wgExtraNamespaces[12312] = 'Dummy'; $wgExtraNamespaces[12313] = 'Dummy_talk'; + $wgExtraNamespaces[12314] = 'DummyNonText'; + $wgExtraNamespaces[12315] = 'DummyNonText_talk'; $wgNamespaceContentModels[12312] = "testing"; + $wgNamespaceContentModels[12314] = "testing-nontext"; + $wgContentHandlers["testing"] = 'DummyContentHandlerForTesting'; + $wgContentHandlers["testing-nontext"] = 'DummyNonTextContentHandler'; MWNamespace::getCanonicalNamespaces( true ); # reset namespace cache $wgContLang->resetNamespaces(); # reset namespace cache @@ -96,33 +101,6 @@ class ApiEditPageTest extends ApiTestCase { ); } - public function testNonTextEdit() { - $name = 'Dummy:ApiEditPageTest_testNonTextEdit'; - $data = serialize( 'some bla bla text' ); - - // -- test new page -------------------------------------------- - $apiResult = $this->doApiRequestWithToken( array( - 'action' => 'edit', - 'title' => $name, - 'text' => $data, ) ); - $apiResult = $apiResult[0]; - - // Validate API result data - $this->assertArrayHasKey( 'edit', $apiResult ); - $this->assertArrayHasKey( 'result', $apiResult['edit'] ); - $this->assertEquals( 'Success', $apiResult['edit']['result'] ); - - $this->assertArrayHasKey( 'new', $apiResult['edit'] ); - $this->assertArrayNotHasKey( 'nochange', $apiResult['edit'] ); - - $this->assertArrayHasKey( 'pageid', $apiResult['edit'] ); - - // validate resulting revision - $page = WikiPage::factory( Title::newFromText( $name ) ); - $this->assertEquals( "testing", $page->getContentModel() ); - $this->assertEquals( $data, $page->getContent()->serialize() ); - } - /** * @return array */ @@ -240,7 +218,7 @@ class ApiEditPageTest extends ApiTestCase { 'section' => 'new', 'text' => 'test', 'summary' => 'header', - )); + ) ); $this->assertEquals( 'Success', $re['edit']['result'] ); // Check the page text is correct @@ -257,7 +235,7 @@ class ApiEditPageTest extends ApiTestCase { 'section' => 'new', 'text' => 'test', 'summary' => 'header', - )); + ) ); $this->assertEquals( 'Success', $re2['edit']['result'] ); $text = WikiPage::factory( Title::newFromText( $name ) ) @@ -284,18 +262,18 @@ class ApiEditPageTest extends ApiTestCase { // base edit for content $page->doEditContent( new WikitextContent( "Foo" ), - "testing 1", EDIT_NEW, false, self::$users['sysop']->user ); + "testing 1", EDIT_NEW, false, self::$users['sysop']->getUser() ); $this->forceRevisionDate( $page, '20120101000000' ); $baseTime = $page->getRevision()->getTimestamp(); // base edit for redirect $rpage->doEditContent( new WikitextContent( "#REDIRECT [[$name]]" ), - "testing 1", EDIT_NEW, false, self::$users['sysop']->user ); + "testing 1", EDIT_NEW, false, self::$users['sysop']->getUser() ); $this->forceRevisionDate( $rpage, '20120101000000' ); // conflicting edit to redirect $rpage->doEditContent( new WikitextContent( "#REDIRECT [[$name]]\n\n[[Category:Test]]" ), - "testing 2", EDIT_UPDATE, $page->getLatest(), self::$users['uploader']->user ); + "testing 2", EDIT_UPDATE, $page->getLatest(), self::$users['uploader']->getUser() ); $this->forceRevisionDate( $rpage, '20120101020202' ); // try to save edit, following the redirect @@ -306,7 +284,7 @@ class ApiEditPageTest extends ApiTestCase { 'basetimestamp' => $baseTime, 'section' => 'new', 'redirect' => true, - ), null, self::$users['sysop']->user ); + ), null, self::$users['sysop']->getUser() ); $this->assertEquals( 'Success', $re['edit']['result'], "no problems expected when following redirect" ); @@ -330,18 +308,18 @@ class ApiEditPageTest extends ApiTestCase { // base edit for content $page->doEditContent( new WikitextContent( "Foo" ), - "testing 1", EDIT_NEW, false, self::$users['sysop']->user ); + "testing 1", EDIT_NEW, false, self::$users['sysop']->getUser() ); $this->forceRevisionDate( $page, '20120101000000' ); $baseTime = $page->getRevision()->getTimestamp(); // base edit for redirect $rpage->doEditContent( new WikitextContent( "#REDIRECT [[$name]]" ), - "testing 1", EDIT_NEW, false, self::$users['sysop']->user ); + "testing 1", EDIT_NEW, false, self::$users['sysop']->getUser() ); $this->forceRevisionDate( $rpage, '20120101000000' ); // conflicting edit to redirect $rpage->doEditContent( new WikitextContent( "#REDIRECT [[$name]]\n\n[[Category:Test]]" ), - "testing 2", EDIT_UPDATE, $page->getLatest(), self::$users['uploader']->user ); + "testing 2", EDIT_UPDATE, $page->getLatest(), self::$users['uploader']->getUser() ); $this->forceRevisionDate( $rpage, '20120101020202' ); // try to save edit, following the redirect but without creating a section @@ -352,7 +330,7 @@ class ApiEditPageTest extends ApiTestCase { 'text' => 'nix bar!', 'basetimestamp' => $baseTime, 'redirect' => true, - ), null, self::$users['sysop']->user ); + ), null, self::$users['sysop']->getUser() ); $this->fail( 'redirect-appendonly error expected' ); } catch ( UsageException $ex ) { @@ -372,13 +350,13 @@ class ApiEditPageTest extends ApiTestCase { // base edit $page->doEditContent( new WikitextContent( "Foo" ), - "testing 1", EDIT_NEW, false, self::$users['sysop']->user ); + "testing 1", EDIT_NEW, false, self::$users['sysop']->getUser() ); $this->forceRevisionDate( $page, '20120101000000' ); $baseTime = $page->getRevision()->getTimestamp(); // conflicting edit $page->doEditContent( new WikitextContent( "Foo bar" ), - "testing 2", EDIT_UPDATE, $page->getLatest(), self::$users['uploader']->user ); + "testing 2", EDIT_UPDATE, $page->getLatest(), self::$users['uploader']->getUser() ); $this->forceRevisionDate( $page, '20120101020202' ); // try to save edit, expect conflict @@ -388,7 +366,7 @@ class ApiEditPageTest extends ApiTestCase { 'title' => $name, 'text' => 'nix bar!', 'basetimestamp' => $baseTime, - ), null, self::$users['sysop']->user ); + ), null, self::$users['sysop']->getUser() ); $this->fail( 'edit conflict expected' ); } catch ( UsageException $ex ) { @@ -411,13 +389,13 @@ class ApiEditPageTest extends ApiTestCase { // base edit $page->doEditContent( new WikitextContent( "Foo" ), - "testing 1", EDIT_NEW, false, self::$users['sysop']->user ); + "testing 1", EDIT_NEW, false, self::$users['sysop']->getUser() ); $this->forceRevisionDate( $page, '20120101000000' ); $baseTime = $page->getRevision()->getTimestamp(); // conflicting edit $page->doEditContent( new WikitextContent( "Foo bar" ), - "testing 2", EDIT_UPDATE, $page->getLatest(), self::$users['uploader']->user ); + "testing 2", EDIT_UPDATE, $page->getLatest(), self::$users['uploader']->getUser() ); $this->forceRevisionDate( $page, '20120101020202' ); // try to save edit, expect no conflict @@ -427,7 +405,7 @@ class ApiEditPageTest extends ApiTestCase { 'text' => 'nix bar!', 'basetimestamp' => $baseTime, 'section' => 'new', - ), null, self::$users['sysop']->user ); + ), null, self::$users['sysop']->getUser() ); $this->assertEquals( 'Success', $re['edit']['result'], "no edit conflict expected here" ); @@ -454,17 +432,17 @@ class ApiEditPageTest extends ApiTestCase { // base edit for content $page->doEditContent( new WikitextContent( "Foo" ), - "testing 1", EDIT_NEW, false, self::$users['sysop']->user ); + "testing 1", EDIT_NEW, false, self::$users['sysop']->getUser() ); $this->forceRevisionDate( $page, '20120101000000' ); // base edit for redirect $rpage->doEditContent( new WikitextContent( "#REDIRECT [[$name]]" ), - "testing 1", EDIT_NEW, false, self::$users['sysop']->user ); + "testing 1", EDIT_NEW, false, self::$users['sysop']->getUser() ); $this->forceRevisionDate( $rpage, '20120101000000' ); // new edit to content $page->doEditContent( new WikitextContent( "Foo bar" ), - "testing 2", EDIT_UPDATE, $page->getLatest(), self::$users['uploader']->user ); + "testing 2", EDIT_UPDATE, $page->getLatest(), self::$users['uploader']->getUser() ); $this->forceRevisionDate( $rpage, '20120101020202' ); // try to save edit; should work, following the redirect. @@ -474,7 +452,7 @@ class ApiEditPageTest extends ApiTestCase { 'text' => 'nix bar!', 'section' => 'new', 'redirect' => true, - ), null, self::$users['sysop']->user ); + ), null, self::$users['sysop']->getUser() ); $this->assertEquals( 'Success', $re['edit']['result'], "no edit conflict expected here" ); @@ -493,4 +471,45 @@ class ApiEditPageTest extends ApiTestCase { $page->clear(); } + + public function testCheckDirectApiEditingDisallowed_forNonTextContent() { + $this->setExpectedException( + 'UsageException', + 'Direct editing via API is not supported for content model testing used by Dummy:ApiEditPageTest_nonTextPageEdit' + ); + + $this->doApiRequestWithToken( array( + 'action' => 'edit', + 'title' => 'Dummy:ApiEditPageTest_nonTextPageEdit', + 'text' => '{"animals":["kittens!"]}' + ) ); + } + + public function testSupportsDirectApiEditing_withContentHandlerOverride() { + $name = 'DummyNonText:ApiEditPageTest_testNonTextEdit'; + $data = serialize( 'some bla bla text' ); + + $result = $this->doApiRequestWithToken( array( + 'action' => 'edit', + 'title' => $name, + 'text' => $data, + ) ); + + $apiResult = $result[0]; + + // Validate API result data + $this->assertArrayHasKey( 'edit', $apiResult ); + $this->assertArrayHasKey( 'result', $apiResult['edit'] ); + $this->assertEquals( 'Success', $apiResult['edit']['result'] ); + + $this->assertArrayHasKey( 'new', $apiResult['edit'] ); + $this->assertArrayNotHasKey( 'nochange', $apiResult['edit'] ); + + $this->assertArrayHasKey( 'pageid', $apiResult['edit'] ); + + // validate resulting revision + $page = WikiPage::factory( Title::newFromText( $name ) ); + $this->assertEquals( "testing-nontext", $page->getContentModel() ); + $this->assertEquals( $data, $page->getContent()->serialize() ); + } } diff --git a/tests/phpunit/includes/api/ApiLoginTest.php b/tests/phpunit/includes/api/ApiLoginTest.php index 88a99e9b..7dfd14f3 100644 --- a/tests/phpunit/includes/api/ApiLoginTest.php +++ b/tests/phpunit/includes/api/ApiLoginTest.php @@ -23,7 +23,7 @@ class ApiLoginTest extends ApiTestCase { global $wgServer; $user = self::$users['sysop']; - $user->user->logOut(); + $user->getUser()->logOut(); if ( !isset( $wgServer ) ) { $this->markTestIncomplete( 'This test needs $wgServer to be set in LocalSettings.php' ); @@ -68,7 +68,7 @@ class ApiLoginTest extends ApiTestCase { } $user = self::$users['sysop']; - $user->user->logOut(); + $user->getUser()->logOut(); $ret = $this->doApiRequest( array( "action" => "login", diff --git a/tests/phpunit/includes/api/ApiMainTest.php b/tests/phpunit/includes/api/ApiMainTest.php index e8ef1804..94b741dc 100644 --- a/tests/phpunit/includes/api/ApiMainTest.php +++ b/tests/phpunit/includes/api/ApiMainTest.php @@ -71,7 +71,7 @@ class ApiMainTest extends ApiTestCase { new FauxRequest( array( 'action' => 'query', 'meta' => 'siteinfo' ) ) ); $modules = $api->getModuleManager()->getNamesWithClasses(); - foreach( $modules as $name => $class ) { + foreach ( $modules as $name => $class ) { $this->assertArrayHasKey( $class, $classes, @@ -79,4 +79,173 @@ class ApiMainTest extends ApiTestCase { ); } } + + /** + * Test HTTP precondition headers + * + * @covers ApiMain::checkConditionalRequestHeaders + * @dataProvider provideCheckConditionalRequestHeaders + * @param array $headers HTTP headers + * @param array $conditions Return data for ApiBase::getConditionalRequestData + * @param int $status Expected response status + * @param bool $post Request is a POST + */ + public function testCheckConditionalRequestHeaders( $headers, $conditions, $status, $post = false ) { + $request = new FauxRequest( array( 'action' => 'query', 'meta' => 'siteinfo' ), $post ); + $request->setHeaders( $headers ); + $request->response()->statusHeader( 200 ); // Why doesn't it default? + + $api = new ApiMain( $request ); + $priv = TestingAccessWrapper::newFromObject( $api ); + $priv->mInternalMode = false; + + $module = $this->getMockBuilder( 'ApiBase' ) + ->setConstructorArgs( array( $api, 'mock' ) ) + ->setMethods( array( 'getConditionalRequestData' ) ) + ->getMockForAbstractClass(); + $module->expects( $this->any() ) + ->method( 'getConditionalRequestData' ) + ->will( $this->returnCallback( function ( $condition ) use ( $conditions ) { + return isset( $conditions[$condition] ) ? $conditions[$condition] : null; + } ) ); + + $ret = $priv->checkConditionalRequestHeaders( $module ); + + $this->assertSame( $status, $request->response()->getStatusCode() ); + $this->assertSame( $status === 200, $ret ); + } + + public static function provideCheckConditionalRequestHeaders() { + $now = time(); + + return array( + // Non-existing from module is ignored + array( array( 'If-None-Match' => '"foo", "bar"' ), array(), 200 ), + array( array( 'If-Modified-Since' => 'Tue, 18 Aug 2015 00:00:00 GMT' ), array(), 200 ), + + // No headers + array( + array(), + array( + 'etag' => '""', + 'last-modified' => '20150815000000', + ), + 200 + ), + + // Basic If-None-Match + array( array( 'If-None-Match' => '"foo", "bar"' ), array( 'etag' => '"bar"' ), 304 ), + array( array( 'If-None-Match' => '"foo", "bar"' ), array( 'etag' => '"baz"' ), 200 ), + array( array( 'If-None-Match' => '"foo"' ), array( 'etag' => 'W/"foo"' ), 304 ), + array( array( 'If-None-Match' => 'W/"foo"' ), array( 'etag' => '"foo"' ), 304 ), + array( array( 'If-None-Match' => 'W/"foo"' ), array( 'etag' => 'W/"foo"' ), 304 ), + + // Pointless, but supported + array( array( 'If-None-Match' => '*' ), array(), 304 ), + + // Basic If-Modified-Since + array( array( 'If-Modified-Since' => wfTimestamp( TS_RFC2822, $now ) ), + array( 'last-modified' => wfTimestamp( TS_MW, $now - 1 ) ), 304 ), + array( array( 'If-Modified-Since' => wfTimestamp( TS_RFC2822, $now ) ), + array( 'last-modified' => wfTimestamp( TS_MW, $now ) ), 304 ), + array( array( 'If-Modified-Since' => wfTimestamp( TS_RFC2822, $now ) ), + array( 'last-modified' => wfTimestamp( TS_MW, $now + 1 ) ), 200 ), + + // If-Modified-Since ignored when If-None-Match is given too + array( array( 'If-None-Match' => '""', 'If-Modified-Since' => wfTimestamp( TS_RFC2822, $now ) ), + array( 'etag' => '"x"', 'last-modified' => wfTimestamp( TS_MW, $now - 1 ) ), 200 ), + array( array( 'If-None-Match' => '""', 'If-Modified-Since' => wfTimestamp( TS_RFC2822, $now ) ), + array( 'last-modified' => wfTimestamp( TS_MW, $now - 1 ) ), 304 ), + + // Ignored for POST + array( array( 'If-None-Match' => '"foo", "bar"' ), array( 'etag' => '"bar"' ), 200, true ), + array( array( 'If-Modified-Since' => wfTimestamp( TS_RFC2822, $now ) ), + array( 'last-modified' => wfTimestamp( TS_MW, $now - 1 ) ), 200, true ), + + // Other date formats allowed by the RFC + array( array( 'If-Modified-Since' => gmdate( 'l, d-M-y H:i:s', $now ) . ' GMT' ), + array( 'last-modified' => wfTimestamp( TS_MW, $now - 1 ) ), 304 ), + array( array( 'If-Modified-Since' => gmdate( 'D M j H:i:s Y', $now ) ), + array( 'last-modified' => wfTimestamp( TS_MW, $now - 1 ) ), 304 ), + + // Old browser extension to HTTP/1.0 + array( array( 'If-Modified-Since' => wfTimestamp( TS_RFC2822, $now ) . '; length=123' ), + array( 'last-modified' => wfTimestamp( TS_MW, $now - 1 ) ), 304 ), + + // Invalid date formats should be ignored + array( array( 'If-Modified-Since' => gmdate( 'Y-m-d H:i:s', $now ) . ' GMT' ), + array( 'last-modified' => wfTimestamp( TS_MW, $now - 1 ) ), 200 ), + ); + } + + /** + * Test conditional headers output + * @dataProvider provideConditionalRequestHeadersOutput + * @param array $conditions Return data for ApiBase::getConditionalRequestData + * @param array $headers Expected output headers + * @param bool $isError $isError flag + * @param bool $post Request is a POST + */ + public function testConditionalRequestHeadersOutput( $conditions, $headers, $isError = false, $post = false ) { + $request = new FauxRequest( array( 'action' => 'query', 'meta' => 'siteinfo' ), $post ); + $response = $request->response(); + + $api = new ApiMain( $request ); + $priv = TestingAccessWrapper::newFromObject( $api ); + $priv->mInternalMode = false; + + $module = $this->getMockBuilder( 'ApiBase' ) + ->setConstructorArgs( array( $api, 'mock' ) ) + ->setMethods( array( 'getConditionalRequestData' ) ) + ->getMockForAbstractClass(); + $module->expects( $this->any() ) + ->method( 'getConditionalRequestData' ) + ->will( $this->returnCallback( function ( $condition ) use ( $conditions ) { + return isset( $conditions[$condition] ) ? $conditions[$condition] : null; + } ) ); + $priv->mModule = $module; + + $priv->sendCacheHeaders( $isError ); + + foreach ( array( 'Last-Modified', 'ETag' ) as $header ) { + $this->assertEquals( + isset( $headers[$header] ) ? $headers[$header] : null, + $response->getHeader( $header ), + $header + ); + } + } + + public static function provideConditionalRequestHeadersOutput() { + return array( + array( + array(), + array() + ), + array( + array( 'etag' => '"foo"' ), + array( 'ETag' => '"foo"' ) + ), + array( + array( 'last-modified' => '20150818000102' ), + array( 'Last-Modified' => 'Tue, 18 Aug 2015 00:01:02 GMT' ) + ), + array( + array( 'etag' => '"foo"', 'last-modified' => '20150818000102' ), + array( 'ETag' => '"foo"', 'Last-Modified' => 'Tue, 18 Aug 2015 00:01:02 GMT' ) + ), + array( + array( 'etag' => '"foo"', 'last-modified' => '20150818000102' ), + array(), + true, + ), + array( + array( 'etag' => '"foo"', 'last-modified' => '20150818000102' ), + array(), + false, + true, + ), + ); + } + } diff --git a/tests/phpunit/includes/api/ApiMessageTest.php b/tests/phpunit/includes/api/ApiMessageTest.php index 6c3ce60d..08a984eb 100644 --- a/tests/phpunit/includes/api/ApiMessageTest.php +++ b/tests/phpunit/includes/api/ApiMessageTest.php @@ -14,9 +14,13 @@ class ApiMessageTest extends MediaWikiTestCase { $msg = TestingAccessWrapper::newFromObject( $msg ); $msg2 = TestingAccessWrapper::newFromObject( $msg2 ); - foreach ( array( 'interface', 'useDatabase', 'title' ) as $key ) { - $this->assertSame( $msg->$key, $msg2->$key, $key ); - } + $this->assertSame( $msg->interface, $msg2->interface, 'interface' ); + $this->assertSame( $msg->useDatabase, $msg2->useDatabase, 'useDatabase' ); + $this->assertSame( + $msg->title ? $msg->title->getFullText() : null, + $msg2->title ? $msg2->title->getFullText() : null, + 'title' + ); } /** @@ -30,6 +34,11 @@ class ApiMessageTest extends MediaWikiTestCase { $this->assertEquals( 'code', $msg2->getApiCode() ); $this->assertEquals( array( 'data' ), $msg2->getApiData() ); + $msg2 = unserialize( serialize( $msg2 ) ); + $this->compareMessages( $msg, $msg2 ); + $this->assertEquals( 'code', $msg2->getApiCode() ); + $this->assertEquals( array( 'data' ), $msg2->getApiData() ); + $msg = new Message( array( 'foo', 'bar' ), array( 'baz' ) ); $msg2 = new ApiMessage( array( array( 'foo', 'bar' ), 'baz' ), 'code', array( 'data' ) ); $this->compareMessages( $msg, $msg2 ); @@ -63,6 +72,11 @@ class ApiMessageTest extends MediaWikiTestCase { $this->assertEquals( 'code', $msg2->getApiCode() ); $this->assertEquals( array( 'data' ), $msg2->getApiData() ); + $msg2 = unserialize( serialize( $msg2 ) ); + $this->compareMessages( $msg, $msg2 ); + $this->assertEquals( 'code', $msg2->getApiCode() ); + $this->assertEquals( array( 'data' ), $msg2->getApiData() ); + $msg = new RawMessage( 'foo', array( 'baz' ) ); $msg2 = new ApiRawMessage( array( 'foo', 'baz' ), 'code', array( 'data' ) ); $this->compareMessages( $msg, $msg2 ); diff --git a/tests/phpunit/includes/api/ApiQueryAllPagesTest.php b/tests/phpunit/includes/api/ApiQueryAllPagesTest.php index 124988f3..0ac00eea 100644 --- a/tests/phpunit/includes/api/ApiQueryAllPagesTest.php +++ b/tests/phpunit/includes/api/ApiQueryAllPagesTest.php @@ -13,9 +13,11 @@ class ApiQueryAllPagesTest extends ApiTestCase { } /** - * @todo give this test a real name explaining what is being tested here + *Test bug 25702 + *Prefixes of API search requests are not handled with case sensitivity and may result + *in wrong search results */ - public function testBug25702() { + public function testPrefixNormalizationSearchBug() { $title = Title::newFromText( 'Category:Template:xyz' ); $page = WikiPage::factory( $title ); $page->doEdit( 'Some text', 'inserting content' ); diff --git a/tests/phpunit/includes/api/ApiResultTest.php b/tests/phpunit/includes/api/ApiResultTest.php index f0d84552..2f31677e 100644 --- a/tests/phpunit/includes/api/ApiResultTest.php +++ b/tests/phpunit/includes/api/ApiResultTest.php @@ -181,6 +181,19 @@ class ApiResultTest extends MediaWikiTestCase { ); } + ApiResult::setValue( $arr, null, NAN, ApiResult::NO_VALIDATE ); + + try { + ApiResult::setValue( $arr, null, NAN, ApiResult::NO_SIZE_CHECK ); + $this->fail( 'Expected exception not thrown' ); + } catch ( InvalidArgumentException $ex ) { + $this->assertSame( + 'Cannot add non-finite floats to ApiResult', + $ex->getMessage(), + 'Expected exception' + ); + } + $arr = array(); $result2 = new ApiResult( 8388608 ); $result2->addValue( null, 'foo', 'bar' ); @@ -408,6 +421,19 @@ class ApiResultTest extends MediaWikiTestCase { ); } + $result->addValue( null, null, NAN, ApiResult::NO_VALIDATE ); + + try { + $result->addValue( null, null, NAN, ApiResult::NO_SIZE_CHECK ); + $this->fail( 'Expected exception not thrown' ); + } catch ( InvalidArgumentException $ex ) { + $this->assertSame( + 'Cannot add non-finite floats to ApiResult', + $ex->getMessage(), + 'Expected exception' + ); + } + $result->reset(); $result->addParsedLimit( 'foo', 12 ); $this->assertSame( array( @@ -444,6 +470,12 @@ class ApiResultTest extends MediaWikiTestCase { $result->removeValue( null, 'foo' ); $this->assertTrue( $result->addValue( null, 'foo', '1' ) ); + $result = new ApiResult( 10 ); + $obj = new ApiResultTestSerializableObject( 'ok' ); + $obj->foobar = 'foobaz'; + $this->assertTrue( $result->addValue( null, 'foo', $obj ) ); + $this->assertSame( 2, $result->getSize() ); + $result = new ApiResult( 8388608 ); $result2 = new ApiResult( 8388608 ); $result2->addValue( null, 'foo', 'bar' ); @@ -674,6 +706,10 @@ class ApiResultTest extends MediaWikiTestCase { ApiResult::META_TYPE => 'BCkvp', ApiResult::META_KVP_KEY_NAME => 'key', ), + 'kvpmerge' => array( 'x' => 'a', 'y' => array( 'b' ), 'z' => array( 'c' => 'd' ), + ApiResult::META_TYPE => 'kvp', + ApiResult::META_KVP_MERGE => true, + ), 'emptyDefault' => array( '_dummy' => 1 ), 'emptyAssoc' => array( '_dummy' => 1, ApiResult::META_TYPE => 'assoc' ), '_dummy' => 1, @@ -858,6 +894,13 @@ class ApiResultTest extends MediaWikiTestCase { ApiResult::META_TYPE => 'assoc', ApiResult::META_KVP_KEY_NAME => 'key', ), + 'kvpmerge' => array( + 'x' => 'a', + 'y' => array( 'b', ApiResult::META_TYPE => 'array' ), + 'z' => array( 'c' => 'd', ApiResult::META_TYPE => 'assoc' ), + ApiResult::META_TYPE => 'assoc', + ApiResult::META_KVP_MERGE => true, + ), 'emptyDefault' => array( '_dummy' => 1, ApiResult::META_TYPE => 'array' ), 'emptyAssoc' => array( '_dummy' => 1, ApiResult::META_TYPE => 'assoc' ), '_dummy' => 1, @@ -871,8 +914,12 @@ class ApiResultTest extends MediaWikiTestCase { array( 'Types' => array( 'AssocAsObject' => true ) ), (object)array( 'defaultArray' => array( 'b', 'c', 'a', ApiResult::META_TYPE => 'array' ), - 'defaultAssoc' => (object)array( 'x' => 'a', 1 => 'b', 0 => 'c', ApiResult::META_TYPE => 'assoc' ), - 'defaultAssoc2' => (object)array( 2 => 'a', 3 => 'b', 0 => 'c', ApiResult::META_TYPE => 'assoc' ), + 'defaultAssoc' => (object)array( 'x' => 'a', + 1 => 'b', 0 => 'c', ApiResult::META_TYPE => 'assoc' + ), + 'defaultAssoc2' => (object)array( 2 => 'a', 3 => 'b', + 0 => 'c', ApiResult::META_TYPE => 'assoc' + ), 'array' => array( 'a', 'c', 'b', ApiResult::META_TYPE => 'array' ), 'BCarray' => array( 'a', 'c', 'b', ApiResult::META_TYPE => 'array' ), 'BCassoc' => (object)array( 'a', 'b', 'c', ApiResult::META_TYPE => 'assoc' ), @@ -885,6 +932,13 @@ class ApiResultTest extends MediaWikiTestCase { ApiResult::META_TYPE => 'assoc', ApiResult::META_KVP_KEY_NAME => 'key', ), + 'kvpmerge' => (object)array( + 'x' => 'a', + 'y' => array( 'b', ApiResult::META_TYPE => 'array' ), + 'z' => (object)array( 'c' => 'd', ApiResult::META_TYPE => 'assoc' ), + ApiResult::META_TYPE => 'assoc', + ApiResult::META_KVP_MERGE => true, + ), 'emptyDefault' => array( '_dummy' => 1, ApiResult::META_TYPE => 'array' ), 'emptyAssoc' => (object)array( '_dummy' => 1, ApiResult::META_TYPE => 'assoc' ), '_dummy' => 1, @@ -916,6 +970,13 @@ class ApiResultTest extends MediaWikiTestCase { ApiResult::META_TYPE => 'array', ApiResult::META_KVP_KEY_NAME => 'key', ), + 'kvpmerge' => array( + $kvp( 'name', 'x', 'value', 'a' ), + $kvp( 'name', 'y', 'value', array( 'b', ApiResult::META_TYPE => 'array' ) ), + array( 'name' => 'z', 'c' => 'd', ApiResult::META_TYPE => 'assoc', ApiResult::META_PRESERVE_KEYS => array( 'name' ) ), + ApiResult::META_TYPE => 'array', + ApiResult::META_KVP_MERGE => true, + ), 'emptyDefault' => array( '_dummy' => 1, ApiResult::META_TYPE => 'array' ), 'emptyAssoc' => array( '_dummy' => 1, ApiResult::META_TYPE => 'assoc' ), '_dummy' => 1, @@ -947,6 +1008,13 @@ class ApiResultTest extends MediaWikiTestCase { ApiResult::META_TYPE => 'array', ApiResult::META_KVP_KEY_NAME => 'key', ), + 'kvpmerge' => array( + $kvp( 'name', 'x', '*', 'a' ), + $kvp( 'name', 'y', '*', array( 'b', ApiResult::META_TYPE => 'array' ) ), + array( 'name' => 'z', 'c' => 'd', ApiResult::META_TYPE => 'assoc', ApiResult::META_PRESERVE_KEYS => array( 'name' ) ), + ApiResult::META_TYPE => 'array', + ApiResult::META_KVP_MERGE => true, + ), 'emptyDefault' => array( '_dummy' => 1, ApiResult::META_TYPE => 'array' ), 'emptyAssoc' => array( '_dummy' => 1, ApiResult::META_TYPE => 'assoc' ), '_dummy' => 1, @@ -960,8 +1028,12 @@ class ApiResultTest extends MediaWikiTestCase { array( 'Types' => array( 'ArmorKVP' => 'name', 'AssocAsObject' => true ) ), (object)array( 'defaultArray' => array( 'b', 'c', 'a', ApiResult::META_TYPE => 'array' ), - 'defaultAssoc' => (object)array( 'x' => 'a', 1 => 'b', 0 => 'c', ApiResult::META_TYPE => 'assoc' ), - 'defaultAssoc2' => (object)array( 2 => 'a', 3 => 'b', 0 => 'c', ApiResult::META_TYPE => 'assoc' ), + 'defaultAssoc' => (object)array( 'x' => 'a', 1 => 'b', + 0 => 'c', ApiResult::META_TYPE => 'assoc' + ), + 'defaultAssoc2' => (object)array( 2 => 'a', 3 => 'b', + 0 => 'c', ApiResult::META_TYPE => 'assoc' + ), 'array' => array( 'a', 'c', 'b', ApiResult::META_TYPE => 'array' ), 'BCarray' => array( 'a', 'c', 'b', ApiResult::META_TYPE => 'array' ), 'BCassoc' => (object)array( 'a', 'b', 'c', ApiResult::META_TYPE => 'assoc' ), @@ -978,6 +1050,13 @@ class ApiResultTest extends MediaWikiTestCase { ApiResult::META_TYPE => 'array', ApiResult::META_KVP_KEY_NAME => 'key', ), + 'kvpmerge' => array( + (object)$kvp( 'name', 'x', 'value', 'a' ), + (object)$kvp( 'name', 'y', 'value', array( 'b', ApiResult::META_TYPE => 'array' ) ), + (object)array( 'name' => 'z', 'c' => 'd', ApiResult::META_TYPE => 'assoc', ApiResult::META_PRESERVE_KEYS => array( 'name' ) ), + ApiResult::META_TYPE => 'array', + ApiResult::META_KVP_MERGE => true, + ), 'emptyDefault' => array( '_dummy' => 1, ApiResult::META_TYPE => 'array' ), 'emptyAssoc' => (object)array( '_dummy' => 1, ApiResult::META_TYPE => 'assoc' ), '_dummy' => 1, @@ -1017,6 +1096,11 @@ class ApiResultTest extends MediaWikiTestCase { (object)array( 'key' => 'x', 'value' => 'a' ), (object)array( 'key' => 'y', 'value' => 'b' ), ), + 'kvpmerge' => array( + (object)array( 'name' => 'x', 'value' => 'a' ), + (object)array( 'name' => 'y', 'value' => array( 'b' ) ), + (object)array( 'name' => 'z', 'c' => 'd' ), + ), 'emptyDefault' => array(), 'emptyAssoc' => (object)array(), '_dummy' => 1, @@ -1124,6 +1208,76 @@ class ApiResultTest extends MediaWikiTestCase { $data[ApiResult::META_CONTENT] = 'bar'; } + /** + * @covers ApiResult + */ + public function testAddMetadataToResultVars() { + $arr = array( + 'a' => "foo", + 'b' => false, + 'c' => 10, + 'sequential_numeric_keys' => array( 'a', 'b', 'c' ), + 'non_sequential_numeric_keys' => array( 'a', 'b', 4 => 'c' ), + 'string_keys' => array( + 'one' => 1, + 'two' => 2 + ), + 'object_sequential_keys' => (object)array( 'a', 'b', 'c' ), + '_type' => "should be overwritten in result", + ); + $this->assertSame( array( + ApiResult::META_TYPE => 'kvp', + ApiResult::META_KVP_KEY_NAME => 'key', + ApiResult::META_PRESERVE_KEYS => array( + 'a', 'b', 'c', + 'sequential_numeric_keys', 'non_sequential_numeric_keys', + 'string_keys', 'object_sequential_keys' + ), + ApiResult::META_BC_BOOLS => array( 'b' ), + ApiResult::META_INDEXED_TAG_NAME => 'var', + 'a' => "foo", + 'b' => false, + 'c' => 10, + 'sequential_numeric_keys' => array( + ApiResult::META_TYPE => 'array', + ApiResult::META_BC_BOOLS => array(), + ApiResult::META_INDEXED_TAG_NAME => 'value', + 0 => 'a', + 1 => 'b', + 2 => 'c', + ), + 'non_sequential_numeric_keys' => array( + ApiResult::META_TYPE => 'kvp', + ApiResult::META_KVP_KEY_NAME => 'key', + ApiResult::META_PRESERVE_KEYS => array( 0, 1, 4 ), + ApiResult::META_BC_BOOLS => array(), + ApiResult::META_INDEXED_TAG_NAME => 'var', + 0 => 'a', + 1 => 'b', + 4 => 'c', + ), + 'string_keys' => array( + ApiResult::META_TYPE => 'kvp', + ApiResult::META_KVP_KEY_NAME => 'key', + ApiResult::META_PRESERVE_KEYS => array( 'one', 'two' ), + ApiResult::META_BC_BOOLS => array(), + ApiResult::META_INDEXED_TAG_NAME => 'var', + 'one' => 1, + 'two' => 2, + ), + 'object_sequential_keys' => array( + ApiResult::META_TYPE => 'kvp', + ApiResult::META_KVP_KEY_NAME => 'key', + ApiResult::META_PRESERVE_KEYS => array( 0, 1, 2 ), + ApiResult::META_BC_BOOLS => array(), + ApiResult::META_INDEXED_TAG_NAME => 'var', + 0 => 'a', + 1 => 'b', + 2 => 'c', + ), + ), ApiResult::addMetadataToResultVars( $arr ) ); + } + /** * @covers ApiResult */ @@ -1133,7 +1287,8 @@ class ApiResultTest extends MediaWikiTestCase { if ( preg_match( '/Use of ApiResult::\S+ was deprecated in MediaWiki \d+.\d+\./', $errstr ) ) { return true; } - if ( preg_match( '/Use of ApiMain to ApiResult::__construct was deprecated in MediaWiki \d+.\d+\./', $errstr ) ) { + if ( preg_match( '/Use of ApiMain to ApiResult::__construct ' . + 'was deprecated in MediaWiki \d+.\d+\./', $errstr ) ) { return true; } return false; @@ -1166,17 +1321,6 @@ class ApiResultTest extends MediaWikiTestCase { ), '*' => 'content', ), $result->getData() ); - $result->setRawMode(); - $this->assertSame( array( - 'foo' => array( - 'bar' => array( - '*' => 'content', - ), - ), - '*' => 'content', - '_element' => 'itn', - '_subelements' => array( 'sub' ), - ), $result->getData() ); $arr = array(); ApiResult::setContent( $arr, 'value' ); @@ -1451,7 +1595,8 @@ class ApiResultTest extends MediaWikiTestCase { $result = new ApiResult( 8388608 ); $result->setMainForContinuation( $main ); - $result->beginContinuation( '||mock2', array_slice( $allModules, 0, 2 ), array( 'mock1', 'mock2' ) ); + $result->beginContinuation( '||mock2', array_slice( $allModules, 0, 2 ), + array( 'mock1', 'mock2' ) ); try { $result->setContinueParam( $allModules[1], 'm2continue', 1 ); $this->fail( 'Expected exception not thrown' ); @@ -1467,7 +1612,8 @@ class ApiResultTest extends MediaWikiTestCase { $this->fail( 'Expected exception not thrown' ); } catch ( UnexpectedValueException $ex ) { $this->assertSame( - 'Module \'mocklist\' called ApiContinuationManager::addContinueParam but was not passed to ApiContinuationManager::__construct', + 'Module \'mocklist\' called ApiContinuationManager::addContinueParam ' . + 'but was not passed to ApiContinuationManager::__construct', $ex->getMessage(), 'Expected exception' ); @@ -1495,13 +1641,14 @@ class ApiResultTest extends MediaWikiTestCase { try { $arr = array(); - ApiResult::setValue( $arr, 'foo', new ApiResultTestSerializableObject( + ApiResult::setValue( $arr, 'foo', new ApiResultTestSerializableObject( new ApiResultTestStringifiableObject() ) ); $this->fail( 'Expected exception not thrown' ); } catch ( UnexpectedValueException $ex ) { $this->assertSame( - 'ApiResultTestSerializableObject::serializeForApiResult() returned an object of class ApiResultTestStringifiableObject', + 'ApiResultTestSerializableObject::serializeForApiResult() ' . + 'returned an object of class ApiResultTestStringifiableObject', $ex->getMessage(), 'Expected exception' ); @@ -1509,18 +1656,19 @@ class ApiResultTest extends MediaWikiTestCase { try { $arr = array(); - ApiResult::setValue( $arr, 'foo', new ApiResultTestSerializableObject( NAN ) ); + ApiResult::setValue( $arr, 'foo', new ApiResultTestSerializableObject( NAN ) ); $this->fail( 'Expected exception not thrown' ); } catch ( UnexpectedValueException $ex ) { $this->assertSame( - 'ApiResultTestSerializableObject::serializeForApiResult() returned an invalid value: Cannot add non-finite floats to ApiResult', + 'ApiResultTestSerializableObject::serializeForApiResult() ' . + 'returned an invalid value: Cannot add non-finite floats to ApiResult', $ex->getMessage(), 'Expected exception' ); } $arr = array(); - ApiResult::setValue( $arr, 'foo', new ApiResultTestSerializableObject( + ApiResult::setValue( $arr, 'foo', new ApiResultTestSerializableObject( array( 'one' => new ApiResultTestStringifiableObject( '1' ), 'two' => new ApiResultTestSerializableObject( 2 ), diff --git a/tests/phpunit/includes/api/ApiRevisionDeleteTest.php b/tests/phpunit/includes/api/ApiRevisionDeleteTest.php index b03836eb..362d647f 100644 --- a/tests/phpunit/includes/api/ApiRevisionDeleteTest.php +++ b/tests/phpunit/includes/api/ApiRevisionDeleteTest.php @@ -25,7 +25,7 @@ class ApiRevisionDeleteTest extends ApiTestCase { } public function testHidingRevisions() { - $user = self::$users['sysop']->user; + $user = self::$users['sysop']->getUser(); $revid = array_shift( $this->revs ); $out = $this->doApiRequest( array( 'action' => 'revisiondelete', @@ -80,7 +80,7 @@ class ApiRevisionDeleteTest extends ApiTestCase { } public function testUnhidingOutput() { - $user = self::$users['sysop']->user; + $user = self::$users['sysop']->getUser(); $revid = array_shift( $this->revs ); // Hide revisions $this->doApiRequest( array( diff --git a/tests/phpunit/includes/api/ApiTestCase.php b/tests/phpunit/includes/api/ApiTestCase.php index da62bb0a..21345ac1 100644 --- a/tests/phpunit/includes/api/ApiTestCase.php +++ b/tests/phpunit/includes/api/ApiTestCase.php @@ -105,6 +105,7 @@ abstract class ApiTestCase extends MediaWikiLangTestCase { $wgRequest = new FauxRequest( $params, true, $session ); RequestContext::getMain()->setRequest( $wgRequest ); + RequestContext::getMain()->setUser( $wgUser ); // set up local environment $context = $this->apiContext->newTestContext( $wgRequest, $wgUser ); diff --git a/tests/phpunit/includes/api/ApiUnblockTest.php b/tests/phpunit/includes/api/ApiUnblockTest.php index 2c2370a8..a374f094 100644 --- a/tests/phpunit/includes/api/ApiUnblockTest.php +++ b/tests/phpunit/includes/api/ApiUnblockTest.php @@ -16,7 +16,7 @@ class ApiUnblockTest extends ApiTestCase { /** * @expectedException UsageException */ - public function testWithNoToken( ) { + public function testWithNoToken() { $this->doApiRequest( array( 'action' => 'unblock', @@ -25,7 +25,7 @@ class ApiUnblockTest extends ApiTestCase { ), null, false, - self::$users['sysop']->user + self::$users['sysop']->getUser() ); } } diff --git a/tests/phpunit/includes/api/ApiUploadTest.php b/tests/phpunit/includes/api/ApiUploadTest.php index f74fc354..c852d72b 100644 --- a/tests/phpunit/includes/api/ApiUploadTest.php +++ b/tests/phpunit/includes/api/ApiUploadTest.php @@ -80,7 +80,7 @@ class ApiUploadTest extends ApiTestCaseUpload { try { $this->doApiRequestWithToken( array( 'action' => 'upload', - ), $session, self::$users['uploader']->user ); + ), $session, self::$users['uploader']->getUser() ); } catch ( UsageException $e ) { $exception = true; $this->assertEquals( "One of the parameters filekey, file, url, statuskey is required", @@ -126,7 +126,7 @@ class ApiUploadTest extends ApiTestCaseUpload { $exception = false; try { list( $result, , ) = $this->doApiRequestWithToken( $params, $session, - self::$users['uploader']->user ); + self::$users['uploader']->getUser() ); } catch ( UsageException $e ) { $exception = true; } @@ -165,7 +165,7 @@ class ApiUploadTest extends ApiTestCaseUpload { $exception = false; try { - $this->doApiRequestWithToken( $params, $session, self::$users['uploader']->user ); + $this->doApiRequestWithToken( $params, $session, self::$users['uploader']->getUser() ); } catch ( UsageException $e ) { $this->assertContains( 'The file you submitted was empty', $e->getMessage() ); $exception = true; @@ -215,7 +215,7 @@ class ApiUploadTest extends ApiTestCaseUpload { $exception = false; try { list( $result, , $session ) = $this->doApiRequestWithToken( $params, $session, - self::$users['uploader']->user ); + self::$users['uploader']->getUser() ); } catch ( UsageException $e ) { $exception = true; } @@ -232,7 +232,7 @@ class ApiUploadTest extends ApiTestCaseUpload { $exception = false; try { list( $result, , ) = $this->doApiRequestWithToken( $params, $session, - self::$users['uploader']->user ); // FIXME: leaks a temporary file + self::$users['uploader']->getUser() ); // FIXME: leaks a temporary file } catch ( UsageException $e ) { $exception = true; } @@ -286,7 +286,7 @@ class ApiUploadTest extends ApiTestCaseUpload { $exception = false; try { list( $result, , $session ) = $this->doApiRequestWithToken( $params, $session, - self::$users['uploader']->user ); + self::$users['uploader']->getUser() ); } catch ( UsageException $e ) { $exception = true; } @@ -311,7 +311,7 @@ class ApiUploadTest extends ApiTestCaseUpload { $exception = false; try { list( $result ) = $this->doApiRequestWithToken( $params, $session, - self::$users['uploader']->user ); // FIXME: leaks a temporary file + self::$users['uploader']->getUser() ); // FIXME: leaks a temporary file } catch ( UsageException $e ) { $exception = true; } @@ -331,7 +331,7 @@ class ApiUploadTest extends ApiTestCaseUpload { */ public function testUploadStash( $session ) { $this->setMwGlobals( array( - 'wgUser' => self::$users['uploader']->user, // @todo FIXME: still used somewhere + 'wgUser' => self::$users['uploader']->getUser(), // @todo FIXME: still used somewhere ) ); $extension = 'png'; @@ -368,7 +368,7 @@ class ApiUploadTest extends ApiTestCaseUpload { $exception = false; try { list( $result, , $session ) = $this->doApiRequestWithToken( $params, $session, - self::$users['uploader']->user ); // FIXME: leaks a temporary file + self::$users['uploader']->getUser() ); // FIXME: leaks a temporary file } catch ( UsageException $e ) { $exception = true; } @@ -397,7 +397,7 @@ class ApiUploadTest extends ApiTestCaseUpload { $exception = false; try { list( $result ) = $this->doApiRequestWithToken( $params, $session, - self::$users['uploader']->user ); + self::$users['uploader']->getUser() ); } catch ( UsageException $e ) { $exception = true; } @@ -415,7 +415,7 @@ class ApiUploadTest extends ApiTestCaseUpload { public function testUploadChunks( $session ) { $this->setMwGlobals( array( // @todo FIXME: still used somewhere - 'wgUser' => self::$users['uploader']->user, + 'wgUser' => self::$users['uploader']->getUser(), ) ); $chunkSize = 1048576; @@ -451,9 +451,9 @@ class ApiUploadTest extends ApiTestCaseUpload { $chunkSessionKey = false; $resultOffset = 0; // Open the file: - wfSuppressWarnings(); + MediaWiki\suppressWarnings(); $handle = fopen( $filePath, "r" ); - wfRestoreWarnings(); + MediaWiki\restoreWarnings(); if ( $handle === false ) { $this->markTestIncomplete( "could not open file: $filePath" ); @@ -461,9 +461,9 @@ class ApiUploadTest extends ApiTestCaseUpload { while ( !feof( $handle ) ) { // Get the current chunk - wfSuppressWarnings(); + MediaWiki\suppressWarnings(); $chunkData = fread( $handle, $chunkSize ); - wfRestoreWarnings(); + MediaWiki\restoreWarnings(); // Upload the current chunk into the $_FILE object: $this->fakeUploadChunk( 'chunk', 'blob', $mimeType, $chunkData ); @@ -473,7 +473,7 @@ class ApiUploadTest extends ApiTestCaseUpload { // Upload fist chunk ( and get the session key ) try { list( $result, , $session ) = $this->doApiRequestWithToken( $params, $session, - self::$users['uploader']->user ); + self::$users['uploader']->getUser() ); } catch ( UsageException $e ) { $this->markTestIncomplete( $e->getMessage() ); } @@ -501,7 +501,7 @@ class ApiUploadTest extends ApiTestCaseUpload { // Upload current chunk try { list( $result, , $session ) = $this->doApiRequestWithToken( $params, $session, - self::$users['uploader']->user ); + self::$users['uploader']->getUser() ); } catch ( UsageException $e ) { $this->markTestIncomplete( $e->getMessage() ); } @@ -541,7 +541,7 @@ class ApiUploadTest extends ApiTestCaseUpload { $exception = false; try { list( $result ) = $this->doApiRequestWithToken( $params, $session, - self::$users['uploader']->user ); + self::$users['uploader']->getUser() ); } catch ( UsageException $e ) { $exception = true; } diff --git a/tests/phpunit/includes/api/format/ApiFormatDumpTest.php b/tests/phpunit/includes/api/format/ApiFormatDumpTest.php deleted file mode 100644 index c0f67f8d..00000000 --- a/tests/phpunit/includes/api/format/ApiFormatDumpTest.php +++ /dev/null @@ -1,63 +0,0 @@ - true ) ), - ); - } - - $warning = "\n [\"warnings\"]=>\n array(1) {\n [\"dump\"]=>\n array(1) {\n [\"*\"]=>\n" . - " string(64) \"format=dump has been deprecated. Please use format=json instead.\"\n" . - " }\n }"; - - return array( - // Basic types - array( array( null ), "array(2) {{$warning}\n [0]=>\n NULL\n}\n" ), - array( array( true ), "array(2) {{$warning}\n [0]=>\n string(0) \"\"\n}\n" ), - array( array( false ), "array(1) {{$warning}\n}\n" ), - array( array( true, ApiResult::META_BC_BOOLS => array( 0 ) ), - "array(2) {{$warning}\n [0]=>\n bool(true)\n}\n" ), - array( array( false, ApiResult::META_BC_BOOLS => array( 0 ) ), - "array(2) {{$warning}\n [0]=>\n bool(false)\n}\n" ), - array( array( 42 ), "array(2) {{$warning}\n [0]=>\n int(42)\n}\n" ), - array( array( 42.5 ), "array(2) {{$warning}\n [0]=>\n float(42.5)\n}\n" ), - array( array( 1e42 ), "array(2) {{$warning}\n [0]=>\n float(1.0E+42)\n}\n" ), - array( array( 'foo' ), "array(2) {{$warning}\n [0]=>\n string(3) \"foo\"\n}\n" ), - array( array( 'fóo' ), "array(2) {{$warning}\n [0]=>\n string(4) \"fóo\"\n}\n" ), - - // Arrays - array( array( array() ), "array(2) {{$warning}\n [0]=>\n array(0) {\n }\n}\n" ), - array( array( array( 1 ) ), "array(2) {{$warning}\n [0]=>\n array(1) {\n [0]=>\n int(1)\n }\n}\n" ), - array( array( array( 'x' => 1 ) ), "array(2) {{$warning}\n [0]=>\n array(1) {\n [\"x\"]=>\n int(1)\n }\n}\n" ), - array( array( array( 2 => 1 ) ), "array(2) {{$warning}\n [0]=>\n array(1) {\n [2]=>\n int(1)\n }\n}\n" ), - array( array( (object)array() ), "array(2) {{$warning}\n [0]=>\n array(0) {\n }\n}\n" ), - array( array( array( 1, ApiResult::META_TYPE => 'assoc' ) ), "array(2) {{$warning}\n [0]=>\n array(1) {\n [0]=>\n int(1)\n }\n}\n" ), - array( array( array( 'x' => 1, ApiResult::META_TYPE => 'array' ) ), "array(2) {{$warning}\n [0]=>\n array(1) {\n [0]=>\n int(1)\n }\n}\n" ), - array( array( array( 'x' => 1, ApiResult::META_TYPE => 'kvp' ) ), "array(2) {{$warning}\n [0]=>\n array(1) {\n [\"x\"]=>\n int(1)\n }\n}\n" ), - array( array( array( 'x' => 1, ApiResult::META_TYPE => 'BCkvp', ApiResult::META_KVP_KEY_NAME => 'key' ) ), - "array(2) {{$warning}\n [0]=>\n array(1) {\n [0]=>\n array(2) {\n [\"key\"]=>\n string(1) \"x\"\n [\"*\"]=>\n int(1)\n }\n }\n}\n" ), - array( array( array( 'x' => 1, ApiResult::META_TYPE => 'BCarray' ) ), "array(2) {{$warning}\n [0]=>\n array(1) {\n [\"x\"]=>\n int(1)\n }\n}\n" ), - array( array( array( 'a', 'b', ApiResult::META_TYPE => 'BCassoc' ) ), "array(2) {{$warning}\n [0]=>\n array(2) {\n [0]=>\n string(1) \"a\"\n [1]=>\n string(1) \"b\"\n }\n}\n" ), - - // Content - array( array( 'content' => 'foo', ApiResult::META_CONTENT => 'content' ), - "array(2) {{$warning}\n [\"*\"]=>\n string(3) \"foo\"\n}\n" ), - - // BC Subelements - array( array( 'foo' => 'foo', ApiResult::META_BC_SUBELEMENTS => array( 'foo' ) ), - "array(2) {{$warning}\n [\"foo\"]=>\n array(1) {\n [\"*\"]=>\n string(3) \"foo\"\n }\n}\n" ), - ); - } - -} diff --git a/tests/phpunit/includes/api/format/ApiFormatWddxTest.php b/tests/phpunit/includes/api/format/ApiFormatWddxTest.php deleted file mode 100644 index 07111300..00000000 --- a/tests/phpunit/includes/api/format/ApiFormatWddxTest.php +++ /dev/null @@ -1,80 +0,0 @@ - true ) ) - ); - } - return self::provideEncoding(); - } - - public static function provideEncoding() { - $p = '
              format=wddx has been deprecated. Please use format=json instead.'; - $s = ''; - - return array( - // Basic types - array( array( null ), "{$p}{$s}" ), - array( array( true ), "{$p}{$s}" ), - array( array( false ), "{$p}{$s}" ), - array( array( true, ApiResult::META_BC_BOOLS => array( 0 ) ), - "{$p}{$s}" ), - array( array( false, ApiResult::META_BC_BOOLS => array( 0 ) ), - "{$p}{$s}" ), - array( array( 42 ), "{$p}42{$s}" ), - array( array( 42.5 ), "{$p}42.5{$s}" ), - array( array( 1e42 ), "{$p}1.0E+42{$s}" ), - array( array( 'foo' ), "{$p}foo{$s}" ), - array( array( 'fóo' ), "{$p}fóo{$s}" ), - - // Arrays and objects - array( array( array() ), "{$p}{$s}" ), - array( array( array( 1 ) ), "{$p}1{$s}" ), - array( array( array( 'x' => 1 ) ), "{$p}1{$s}" ), - array( array( array( 2 => 1 ) ), "{$p}1{$s}" ), - array( array( (object)array() ), "{$p}{$s}" ), - array( array( array( 1, ApiResult::META_TYPE => 'assoc' ) ), "{$p}1{$s}" ), - array( array( array( 'x' => 1, ApiResult::META_TYPE => 'array' ) ), "{$p}1{$s}" ), - array( array( array( 'x' => 1, ApiResult::META_TYPE => 'kvp' ) ), "{$p}1{$s}" ), - array( array( array( 'x' => 1, ApiResult::META_TYPE => 'BCkvp', ApiResult::META_KVP_KEY_NAME => 'key' ) ), - "{$p}x1{$s}" ), - array( array( array( 'x' => 1, ApiResult::META_TYPE => 'BCarray' ) ), "{$p}1{$s}" ), - array( array( array( 'a', 'b', ApiResult::META_TYPE => 'BCassoc' ) ), "{$p}ab{$s}" ), - - // Content - array( array( 'content' => 'foo', ApiResult::META_CONTENT => 'content' ), - "{$p}foo{$s}" ), - - // BC Subelements - array( array( 'foo' => 'foo', ApiResult::META_BC_SUBELEMENTS => array( 'foo' ) ), - "{$p}foo{$s}" ), - ); - } - - /** - * @dataProvider provideEncoding - */ - public function testSlowEncoding( array $data, $expect, array $params = array() ) { - // Adjust expectation for differences between fast and slow printers. - $expect = str_replace( '\'', '"', $expect ); - $expect = str_replace( '/>', ' />', $expect ); - $expect = '' . $expect; - - $this->assertSame( $expect, $this->encodeData( $params, $data, 'ApiFormatWddxTest_SlowWddx' ) ); - } -} - -class ApiFormatWddxTest_SlowWddx extends ApiFormatWddx { - public static function useSlowPrinter() { - return true; - } -} diff --git a/tests/phpunit/includes/api/query/ApiQueryContinueTestBase.php b/tests/phpunit/includes/api/query/ApiQueryContinueTestBase.php index ce2f70de..db61bc80 100644 --- a/tests/phpunit/includes/api/query/ApiQueryContinueTestBase.php +++ b/tests/phpunit/includes/api/query/ApiQueryContinueTestBase.php @@ -57,10 +57,9 @@ abstract class ApiQueryContinueTestBase extends ApiQueryTestBase { } else { $params['action'] = 'query'; } - if ( $useContinue && !isset( $params['continue'] ) ) { + // Silence warning + if ( !isset( $params['continue'] ) ) { $params['continue'] = ''; - } else { - $params['rawcontinue'] = '1'; } $count = 0; $result = array(); diff --git a/tests/phpunit/includes/api/query/ApiQueryTest.php b/tests/phpunit/includes/api/query/ApiQueryTest.php index 5f061b50..61b992ba 100644 --- a/tests/phpunit/includes/api/query/ApiQueryTest.php +++ b/tests/phpunit/includes/api/query/ApiQueryTest.php @@ -131,7 +131,7 @@ class ApiQueryTest extends ApiTestCase { ); $queryApi = new ApiQuery( $api, 'query' ); $modules = $queryApi->getModuleManager()->getNamesWithClasses(); - foreach( $modules as $name => $class ) { + foreach ( $modules as $name => $class ) { $this->assertArrayHasKey( $class, $classes, diff --git a/tests/phpunit/includes/api/query/ApiQueryTestBase.php b/tests/phpunit/includes/api/query/ApiQueryTestBase.php index dabf72e0..d5fa4542 100644 --- a/tests/phpunit/includes/api/query/ApiQueryTestBase.php +++ b/tests/phpunit/includes/api/query/ApiQueryTestBase.php @@ -56,12 +56,12 @@ STR; * @return array */ private function validateRequestExpectedPair( $v ) { - $this->assertType( 'array', $v, self::PARAM_ASSERT ); + $this->assertInternalType( 'array', $v, self::PARAM_ASSERT ); $this->assertEquals( 2, count( $v ), self::PARAM_ASSERT ); $this->assertArrayHasKey( 0, $v, self::PARAM_ASSERT ); $this->assertArrayHasKey( 1, $v, self::PARAM_ASSERT ); - $this->assertType( 'array', $v[0], self::PARAM_ASSERT ); - $this->assertType( 'array', $v[1], self::PARAM_ASSERT ); + $this->assertInternalType( 'array', $v[0], self::PARAM_ASSERT ); + $this->assertInternalType( 'array', $v[1], self::PARAM_ASSERT ); return $v; } @@ -87,6 +87,7 @@ STR; /** * Checks that the request's result matches the expected results. + * Assumes no rawcontinue and a complete batch. * @param array $values Array is a two element array( request, expected_results ) * @param array $session * @param bool $appendModule @@ -99,8 +100,9 @@ STR; if ( !array_key_exists( 'action', $req ) ) { $req['action'] = 'query'; } - if ( !array_key_exists( 'continue', $req ) ) { - $req['rawcontinue'] = '1'; + // Silence warning + if ( !isset( $params['continue'] ) ) { + $params['continue'] = ''; } foreach ( $req as &$val ) { if ( is_array( $val ) ) { @@ -108,7 +110,7 @@ STR; } } $result = $this->doApiRequest( $req, $session, $appendModule, $user ); - $this->assertResult( array( 'query' => $exp ), $result[0], $req ); + $this->assertResult( array( 'batchcomplete' => true, 'query' => $exp ), $result[0], $req ); } protected function assertResult( $exp, $result, $message = '' ) { diff --git a/tests/phpunit/includes/cache/MessageCacheTest.php b/tests/phpunit/includes/cache/MessageCacheTest.php index 442e9f9f..5302b363 100644 --- a/tests/phpunit/includes/cache/MessageCacheTest.php +++ b/tests/phpunit/includes/cache/MessageCacheTest.php @@ -52,7 +52,7 @@ class MessageCacheTest extends MediaWikiLangTestCase { $this->makePage( 'MessageCacheTest-FullKeyTest', 'ru' ); // In content language -- get base if no derivative - $this->makePage( 'FallbackLanguageTest-NoDervContLang', 'de', 'de/none', false ); + $this->makePage( 'FallbackLanguageTest-NoDervContLang', 'de', 'de/none' ); } /** @@ -61,15 +61,14 @@ class MessageCacheTest extends MediaWikiLangTestCase { * @param string $title Title of page to be created * @param string $lang Language and content of the created page * @param string|null $content Content of the created page, or null for a generic string - * @param bool $createSubPage Set to false if a root page should be created */ - protected function makePage( $title, $lang, $content = null, $createSubPage = true ) { + protected function makePage( $title, $lang, $content = null ) { global $wgContLang; if ( $content === null ) { $content = $lang; } - if ( $lang !== $wgContLang->getCode() || $createSubPage ) { + if ( $lang !== $wgContLang->getCode() ) { $title = "$title/$lang"; } @@ -125,4 +124,26 @@ class MessageCacheTest extends MediaWikiLangTestCase { ); } + /** + * @dataProvider provideNormalizeKey + */ + public function testNormalizeKey( $key, $expected ) { + $actual = MessageCache::normalizeKey( $key ); + $this->assertEquals( $expected, $actual ); + } + + public function provideNormalizeKey() { + return array( + array( 'Foo', 'foo' ), + array( 'foo', 'foo' ), + array( 'fOo', 'fOo' ), + array( 'FOO', 'fOO' ), + array( 'Foo bar', 'foo_bar' ), + array( 'Ćab', 'ćab' ), + array( 'Ćab_e 3', 'ćab_e_3' ), + array( 'ĆAB', 'ćAB' ), + array( 'ćab', 'ćab' ), + array( 'ćaB', 'ćaB' ), + ); + } } diff --git a/tests/phpunit/includes/changes/RecentChangeTest.php b/tests/phpunit/includes/changes/RecentChangeTest.php index b3cb7b52..4d1a936e 100644 --- a/tests/phpunit/includes/changes/RecentChangeTest.php +++ b/tests/phpunit/includes/changes/RecentChangeTest.php @@ -10,8 +10,8 @@ class RecentChangeTest extends MediaWikiTestCase { protected $user_comment; protected $context; - public function __construct() { - parent::__construct(); + public function setUp() { + parent::setUp(); $this->title = Title::newFromText( 'SomeTitle' ); $this->target = Title::newFromText( 'TestTarget' ); @@ -21,6 +21,26 @@ class RecentChangeTest extends MediaWikiTestCase { $this->context = RequestContext::newExtraneousContext( $this->title ); } + /** + * @covers RecentChange::newFromRow + * @covers RecentChange::loadFromRow + */ + public function testNewFromRow() { + $row = new stdClass(); + $row->rc_foo = 'AAA'; + $row->rc_timestamp = '20150921134808'; + $row->rc_deleted = 'bar'; + + $rc = RecentChange::newFromRow( $row ); + + $expected = array( + 'rc_foo' => 'AAA', + 'rc_timestamp' => '20150921134808', + 'rc_deleted' => 'bar', + ); + $this->assertEquals( $expected, $rc->getAttributes() ); + } + /** * The testIrcMsgForAction* tests are supposed to cover the hacky * LogFormatter::getIRCActionText / bug 34508 @@ -46,6 +66,7 @@ class RecentChangeTest extends MediaWikiTestCase { * - protect/protect * - protect/modifyprotect * - protect/unprotect + * - protect/move_prot * - upload/upload * - merge/merge * - import/upload @@ -59,289 +80,95 @@ class RecentChangeTest extends MediaWikiTestCase { */ /** - * @covers LogFormatter::getIRCActionText - */ - public function testIrcMsgForLogTypeBlock() { - $sep = $this->context->msg( 'colon-separator' )->text(); - - # block/block - $this->assertIRCComment( - $this->context->msg( 'blocklogentry', 'SomeTitle', 'duration', '(flags)' )->plain() - . $sep . $this->user_comment, - 'block', 'block', - array( - '5::duration' => 'duration', - '6::flags' => 'flags', - ), - $this->user_comment - ); - # block/unblock - $this->assertIRCComment( - $this->context->msg( 'unblocklogentry', 'SomeTitle' )->plain() . $sep . $this->user_comment, - 'block', 'unblock', - array(), - $this->user_comment - ); - # block/reblock - $this->assertIRCComment( - $this->context->msg( 'reblock-logentry', 'SomeTitle', 'duration', '(flags)' )->plain() - . $sep . $this->user_comment, - 'block', 'reblock', - array( - '5::duration' => 'duration', - '6::flags' => 'flags', - ), - $this->user_comment - ); - } - - /** - * @covers LogFormatter::getIRCActionText - */ - public function testIrcMsgForLogTypeDelete() { - $sep = $this->context->msg( 'colon-separator' )->text(); - - # delete/delete - $this->assertIRCComment( - $this->context->msg( 'deletedarticle', 'SomeTitle' )->plain() . $sep . $this->user_comment, - 'delete', 'delete', - array(), - $this->user_comment - ); - - # delete/restore - $this->assertIRCComment( - $this->context->msg( 'undeletedarticle', 'SomeTitle' )->plain() . $sep . $this->user_comment, - 'delete', 'restore', - array(), - $this->user_comment - ); - } - - /** - * @covers LogFormatter::getIRCActionText - */ - public function testIrcMsgForLogTypeNewusers() { - $this->assertIRCComment( - 'New user account', - 'newusers', 'newusers', - array() - ); - $this->assertIRCComment( - 'New user account', - 'newusers', 'create', - array() - ); - $this->assertIRCComment( - 'created new account SomeTitle', - 'newusers', 'create2', - array() - ); - $this->assertIRCComment( - 'Account created automatically', - 'newusers', 'autocreate', - array() - ); - } - - /** - * @covers LogFormatter::getIRCActionText - */ - public function testIrcMsgForLogTypeMove() { - $move_params = array( - '4::target' => $this->target->getPrefixedText(), - '5::noredir' => 0, - ); - $sep = $this->context->msg( 'colon-separator' )->text(); - - # move/move - $this->assertIRCComment( - $this->context->msg( '1movedto2', 'SomeTitle', 'TestTarget' ) - ->plain() . $sep . $this->user_comment, - 'move', 'move', - $move_params, - $this->user_comment - ); - - # move/move_redir - $this->assertIRCComment( - $this->context->msg( '1movedto2_redir', 'SomeTitle', 'TestTarget' ) - ->plain() . $sep . $this->user_comment, - 'move', 'move_redir', - $move_params, - $this->user_comment - ); - } - - /** - * @covers LogFormatter::getIRCActionText + * @covers RecentChange::parseParams */ - public function testIrcMsgForLogTypePatrol() { - # patrol/patrol - $this->assertIRCComment( - $this->context->msg( 'patrol-log-line', 'revision 777', '[[SomeTitle]]', '' )->plain(), - 'patrol', 'patrol', - array( - '4::curid' => '777', - '5::previd' => '666', - '6::auto' => 0, + public function testParseParams() { + $params = array( + 'root' => array( + 'A' => 1, + 'B' => 'two' ) ); - } - /** - * @covers LogFormatter::getIRCActionText - */ - public function testIrcMsgForLogTypeProtect() { - $protectParams = array( - '[edit=sysop] (indefinite) ‎[move=sysop] (indefinite)' + $this->assertParseParams( + $params, + 'a:1:{s:4:"root";a:2:{s:1:"A";i:1;s:1:"B";s:3:"two";}}' ); - $sep = $this->context->msg( 'colon-separator' )->text(); - # protect/protect - $this->assertIRCComment( - $this->context->msg( 'protectedarticle', 'SomeTitle ' . $protectParams[0] ) - ->plain() . $sep . $this->user_comment, - 'protect', 'protect', - $protectParams, - $this->user_comment + $this->assertParseParams( + null, + null ); - # protect/unprotect - $this->assertIRCComment( - $this->context->msg( 'unprotectedarticle', 'SomeTitle' )->plain() . $sep . $this->user_comment, - 'protect', 'unprotect', - array(), - $this->user_comment + $this->assertParseParams( + null, + serialize( false ) ); - # protect/modify - $this->assertIRCComment( - $this->context->msg( 'modifiedarticleprotection', 'SomeTitle ' . $protectParams[0] ) - ->plain() . $sep . $this->user_comment, - 'protect', 'modify', - $protectParams, - $this->user_comment + $this->assertParseParams( + null, + 'not-an-array' ); } /** - * @covers LogFormatter::getIRCActionText + * @param array $expectedParseParams + * @param string|null $rawRcParams */ - public function testIrcMsgForLogTypeUpload() { - $sep = $this->context->msg( 'colon-separator' )->text(); + protected function assertParseParams( $expectedParseParams, $rawRcParams ) { + $rc = new RecentChange; + $rc->setAttribs( array( 'rc_params' => $rawRcParams ) ); - # upload/upload - $this->assertIRCComment( - $this->context->msg( 'uploadedimage', 'SomeTitle' )->plain() . $sep . $this->user_comment, - 'upload', 'upload', - array(), - $this->user_comment - ); + $actualParseParams = $rc->parseParams(); - # upload/overwrite - $this->assertIRCComment( - $this->context->msg( 'overwroteimage', 'SomeTitle' )->plain() . $sep . $this->user_comment, - 'upload', 'overwrite', - array(), - $this->user_comment - ); + $this->assertEquals( $expectedParseParams, $actualParseParams ); } /** - * @covers LogFormatter::getIRCActionText + * 50 mins and 100 mins are used here as the tests never take that long! + * @return array */ - public function testIrcMsgForLogTypeMerge() { - $sep = $this->context->msg( 'colon-separator' )->text(); - - # merge/merge - $this->assertIRCComment( - $this->context->msg( 'pagemerge-logentry', 'SomeTitle', 'Dest', 'timestamp' )->plain() - . $sep . $this->user_comment, - 'merge', 'merge', - array( - '4::dest' => 'Dest', - '5::mergepoint' => 'timestamp', - ), - $this->user_comment + public function provideIsInRCLifespan() { + return array( + array( 6000, time() - 3000, 0, true ), + array( 3000, time() - 6000, 0, false ), + array( 6000, time() - 3000, 6000, true ), + array( 3000, time() - 6000, 6000, true ), ); } /** - * @covers LogFormatter::getIRCActionText + * @covers RecentChange::isInRCLifespan + * @dataProvider provideIsInRCLifespan */ - public function testIrcMsgForLogTypeImport() { - $sep = $this->context->msg( 'colon-separator' )->text(); - - # import/upload - $this->assertIRCComment( - $this->context->msg( 'import-logentry-upload', 'SomeTitle' )->plain() . $sep . $this->user_comment, - 'import', 'upload', - array(), - $this->user_comment - ); + public function testIsInRCLifespan( $maxAge, $timestamp, $tolerance, $expected ) { + $this->setMwGlobals( 'wgRCMaxAge', $maxAge ); + $this->assertEquals( $expected, RecentChange::isInRCLifespan( $timestamp, $tolerance ) ); + } - # import/interwiki - $this->assertIRCComment( - $this->context->msg( 'import-logentry-interwiki', 'SomeTitle' )->plain() . $sep . $this->user_comment, - 'import', 'interwiki', - array(), - $this->user_comment + public function provideRCTypes() { + return array( + array( RC_EDIT, 'edit' ), + array( RC_NEW, 'new' ), + array( RC_LOG, 'log' ), + array( RC_EXTERNAL, 'external' ), ); } /** - * @todo Emulate these edits somehow and extract - * raw edit summary from RecentChange object - * -- + * @dataProvider provideRCTypes + * @covers RecentChange::parseFromRCType */ - /* - public function testIrcMsgForBlankingAES() { - // $this->context->msg( 'autosumm-blank', .. ); - } - - public function testIrcMsgForReplaceAES() { - // $this->context->msg( 'autosumm-replace', .. ); - } - - public function testIrcMsgForRollbackAES() { - // $this->context->msg( 'revertpage', .. ); + public function testParseFromRCType( $rcType, $type ) { + $this->assertEquals( $type, RecentChange::parseFromRCType( $rcType ) ); } - public function testIrcMsgForUndoAES() { - // $this->context->msg( 'undo-summary', .. ); - } - */ - /** - * @param string $expected Expected IRC text without colors codes - * @param string $type Log type (move, delete, suppress, patrol ...) - * @param string $action A log type action - * @param array $params - * @param string $comment (optional) A comment for the log action - * @param string $msg (optional) A message for PHPUnit :-) + * @dataProvider provideRCTypes + * @covers RecentChange::parseToRCType */ - protected function assertIRCComment( $expected, $type, $action, $params, - $comment = null, $msg = '' - ) { - $logEntry = new ManualLogEntry( $type, $action ); - $logEntry->setPerformer( $this->user ); - $logEntry->setTarget( $this->title ); - if ( $comment !== null ) { - $logEntry->setComment( $comment ); - } - $logEntry->setParameters( $params ); - - $formatter = LogFormatter::newFromEntry( $logEntry ); - $formatter->setContext( $this->context ); - - // Apply the same transformation as done in IRCColourfulRCFeedFormatter::getLine for rc_comment - $ircRcComment = IRCColourfulRCFeedFormatter::cleanupForIRC( $formatter->getIRCActionComment() ); - - $this->assertEquals( - $expected, - $ircRcComment, - $msg - ); + public function testParseToRCType( $rcType, $type ) { + $this->assertEquals( $rcType, RecentChange::parseToRCType( $type ) ); } + } diff --git a/tests/phpunit/includes/config/HashConfigTest.php b/tests/phpunit/includes/config/HashConfigTest.php index 06973b09..4aa3e30c 100644 --- a/tests/phpunit/includes/config/HashConfigTest.php +++ b/tests/phpunit/includes/config/HashConfigTest.php @@ -30,7 +30,7 @@ class HashConfigTest extends MediaWikiTestCase { public function testGet() { $conf = new HashConfig( array( 'one' => '1', - )); + ) ); $this->assertEquals( '1', $conf->get( 'one' ) ); $this->setExpectedException( 'ConfigException', 'HashConfig::get: undefined option' ); $conf->get( 'two' ); diff --git a/tests/phpunit/includes/content/ContentHandlerTest.php b/tests/phpunit/includes/content/ContentHandlerTest.php index 988a59ee..8178c12e 100644 --- a/tests/phpunit/includes/content/ContentHandlerTest.php +++ b/tests/phpunit/includes/content/ContentHandlerTest.php @@ -22,6 +22,7 @@ class ContentHandlerTest extends MediaWikiTestCase { 'wgContentHandlers' => array( CONTENT_MODEL_WIKITEXT => 'WikitextContentHandler', CONTENT_MODEL_JAVASCRIPT => 'JavaScriptContentHandler', + CONTENT_MODEL_JSON => 'JsonContentHandler', CONTENT_MODEL_CSS => 'CssContentHandler', CONTENT_MODEL_TEXT => 'TextContentHandler', 'testing' => 'DummyContentHandlerForTesting', @@ -51,19 +52,27 @@ class ContentHandlerTest extends MediaWikiTestCase { return array( array( 'Help:Foo', CONTENT_MODEL_WIKITEXT ), array( 'Help:Foo.js', CONTENT_MODEL_WIKITEXT ), + array( 'Help:Foo.css', CONTENT_MODEL_WIKITEXT ), + array( 'Help:Foo.json', 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.css', CONTENT_MODEL_WIKITEXT ), + array( 'User:Foo.json', CONTENT_MODEL_WIKITEXT ), array( 'User:Foo/bar.js', CONTENT_MODEL_JAVASCRIPT ), array( 'User:Foo/bar.css', CONTENT_MODEL_CSS ), + array( 'User:Foo/bar.json', CONTENT_MODEL_JSON ), + array( 'User:Foo/bar.json.nope', CONTENT_MODEL_WIKITEXT ), 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', CONTENT_MODEL_CSS ), array( 'MediaWiki:Foo.css.xxx', CONTENT_MODEL_WIKITEXT ), + array( 'MediaWiki:Foo.CSS', CONTENT_MODEL_WIKITEXT ), + array( 'MediaWiki:Foo.json', CONTENT_MODEL_JSON ), + array( 'MediaWiki:Foo.JSON', CONTENT_MODEL_WIKITEXT ), ); } @@ -338,6 +347,11 @@ class ContentHandlerTest extends MediaWikiTestCase { } */ + public function testSupportsDirectEditing() { + $handler = new DummyContentHandlerForTesting( CONTENT_MODEL_JSON ); + $this->assertFalse( $handler->supportsDirectEditing(), 'direct editing is not supported' ); + } + /** * @covers ContentHandler::runLegacyHooks */ @@ -365,164 +379,3 @@ class ContentHandlerTest extends MediaWikiTestCase { return true; } } - -class DummyContentHandlerForTesting extends ContentHandler { - - public function __construct( $dataModel ) { - parent::__construct( $dataModel, array( "testing" ) ); - } - - /** - * @see ContentHandler::serializeContent - * - * @param Content $content - * @param string $format - * - * @return string - */ - public function serializeContent( Content $content, $format = null ) { - return $content->serialize(); - } - - /** - * @see ContentHandler::unserializeContent - * - * @param string $blob - * @param string $format Unused. - * - * @return Content - */ - 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|bool 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 bool $hasLinks If it is known whether this content contains links, - * provide this information here, to avoid redundant parsing to find out. - * @return bool - */ - public function isCountable( $hasLinks = null ) { - return false; - } - - /** - * @param Title $title - * @param int $revId Unused. - * @param null|ParserOptions $options - * @param bool $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() ); - } - - /** - * @see AbstractContent::fillParserOutput() - * - * @param Title $title Context title for parsing - * @param int|null $revId Revision ID (for {{REVISIONID}}) - * @param ParserOptions $options Parser options - * @param bool $generateHtml Whether or not to generate HTML - * @param ParserOutput &$output The output object to fill (reference). - */ - protected function fillParserOutput( Title $title, $revId, - ParserOptions $options, $generateHtml, ParserOutput &$output ) { - $output = new ParserOutput( $this->getNativeData() ); - } -} diff --git a/tests/phpunit/includes/content/CssContentHandlerTest.php b/tests/phpunit/includes/content/CssContentHandlerTest.php new file mode 100644 index 00000000..e1785a96 --- /dev/null +++ b/tests/phpunit/includes/content/CssContentHandlerTest.php @@ -0,0 +1,30 @@ +setMwGlobals( array( + 'wgServer' => '//example.org', + 'wgScript' => '/w/index.php', + ) ); + $ch = new CssContentHandler(); + $content = $ch->makeRedirectContent( Title::newFromText( $title ) ); + $this->assertInstanceOf( 'CssContent', $content ); + $this->assertEquals( $expected, $content->serialize( CONTENT_FORMAT_CSS ) ); + } + + /** + * Keep this in sync with CssContentTest::provideGetRedirectTarget() + */ + public static function provideMakeRedirectContent() { + return array( + array( 'MediaWiki:MonoBook.css', "/* #REDIRECT */@import url(//example.org/w/index.php?title=MediaWiki:MonoBook.css&action=raw&ctype=text/css);" ), + array( 'User:FooBar/common.css', "/* #REDIRECT */@import url(//example.org/w/index.php?title=User:FooBar/common.css&action=raw&ctype=text/css);" ), + array( 'Gadget:FooBaz.css', "/* #REDIRECT */@import url(//example.org/w/index.php?title=Gadget:FooBaz.css&action=raw&ctype=text/css);" ), + ); + } +} diff --git a/tests/phpunit/includes/content/CssContentTest.php b/tests/phpunit/includes/content/CssContentTest.php index 40484d3a..c4d87c24 100644 --- a/tests/phpunit/includes/content/CssContentTest.php +++ b/tests/phpunit/includes/content/CssContentTest.php @@ -4,6 +4,8 @@ * @group ContentHandler * @group Database * ^--- needed, because we do need the database to test link updates + * + * @FIXME this should not extend JavaScriptContentTest. */ class CssContentTest extends JavaScriptContentTest { @@ -68,7 +70,48 @@ class CssContentTest extends JavaScriptContentTest { $this->assertEquals( CONTENT_MODEL_CSS, $content->getContentHandler()->getModelID() ); } - public static function dataEquals() { + /** + * Redirects aren't supported + */ + public static function provideUpdateRedirect() { + return array( + array( + '#REDIRECT [[Someplace]]', + '#REDIRECT [[Someplace]]', + ), + ); + } + + /** + * @dataProvider provideGetRedirectTarget + */ + public function testGetRedirectTarget( $title, $text ) { + $this->setMwGlobals( array( + 'wgServer' => '//example.org', + 'wgScriptPath' => '/w', + 'wgScript' => '/w/index.php', + ) ); + $content = new CssContent( $text ); + $target = $content->getRedirectTarget(); + $this->assertEquals( $title, $target ? $target->getPrefixedText() : null ); + } + + /** + * Keep this in sync with CssContentHandlerTest::provideMakeRedirectContent() + */ + public static function provideGetRedirectTarget() { + return array( + array( 'MediaWiki:MonoBook.css', "/* #REDIRECT */@import url(//example.org/w/index.php?title=MediaWiki:MonoBook.css&action=raw&ctype=text/css);" ), + array( 'User:FooBar/common.css', "/* #REDIRECT */@import url(//example.org/w/index.php?title=User:FooBar/common.css&action=raw&ctype=text/css);" ), + array( 'Gadget:FooBaz.css', "/* #REDIRECT */@import url(//example.org/w/index.php?title=Gadget:FooBaz.css&action=raw&ctype=text/css);" ), + # No #REDIRECT comment + array( null, "@import url(//example.org/w/index.php?title=Gadget:FooBaz.css&action=raw&ctype=text/css);" ), + # Wrong domain + array( null, "/* #REDIRECT */@import url(//example.com/w/index.php?title=Gadget:FooBaz.css&action=raw&ctype=text/css);" ), + ); + } + + public static function dataEquals() { return array( array( new CssContent( 'hallo' ), null, false ), array( new CssContent( 'hallo' ), new CssContent( 'hallo' ), true ), diff --git a/tests/phpunit/includes/content/JavaScriptContentHandlerTest.php b/tests/phpunit/includes/content/JavaScriptContentHandlerTest.php new file mode 100644 index 00000000..0f41020f --- /dev/null +++ b/tests/phpunit/includes/content/JavaScriptContentHandlerTest.php @@ -0,0 +1,30 @@ +setMwGlobals( array( + 'wgServer' => '//example.org', + 'wgScript' => '/w/index.php', + ) ); + $ch = new JavaScriptContentHandler(); + $content = $ch->makeRedirectContent( Title::newFromText( $title ) ); + $this->assertInstanceOf( 'JavaScriptContent', $content ); + $this->assertEquals( $expected, $content->serialize( CONTENT_FORMAT_JAVASCRIPT ) ); + } + + /** + * Keep this in sync with JavaScriptContentTest::provideGetRedirectTarget() + */ + public static function provideMakeRedirectContent() { + return array( + array( 'MediaWiki:MonoBook.js', '/* #REDIRECT */mw.loader.load("//example.org/w/index.php?title=MediaWiki:MonoBook.js\u0026action=raw\u0026ctype=text/javascript");' ), + array( 'User:FooBar/common.js', '/* #REDIRECT */mw.loader.load("//example.org/w/index.php?title=User:FooBar/common.js\u0026action=raw\u0026ctype=text/javascript");' ), + array( 'Gadget:FooBaz.js', '/* #REDIRECT */mw.loader.load("//example.org/w/index.php?title=Gadget:FooBaz.js\u0026action=raw\u0026ctype=text/javascript");' ), + ); + } +} diff --git a/tests/phpunit/includes/content/JavaScriptContentTest.php b/tests/phpunit/includes/content/JavaScriptContentTest.php index 7193ec9f..0ee27129 100644 --- a/tests/phpunit/includes/content/JavaScriptContentTest.php +++ b/tests/phpunit/includes/content/JavaScriptContentTest.php @@ -251,16 +251,31 @@ class JavaScriptContentTest extends TextContentTest { /** * @covers JavaScriptContent::updateRedirect + * @dataProvider provideUpdateRedirect */ - public function testUpdateRedirect() { + public function testUpdateRedirect( $oldText, $expectedText) { + $this->setMwGlobals( array( + 'wgServer' => '//example.org', + 'wgScriptPath' => '/w/index.php', + ) ); $target = Title::newFromText( "testUpdateRedirect_target" ); - $content = $this->newContent( "#REDIRECT [[Someplace]]" ); + $content = new JavaScriptContent( $oldText ); $newContent = $content->updateRedirect( $target ); - $this->assertTrue( - $content->equals( $newContent ), - "content should be unchanged since it's not wikitext" + $this->assertEquals( $expectedText, $newContent->getNativeData() ); + } + + public static function provideUpdateRedirect() { + return array( + array( + '#REDIRECT [[Someplace]]', + '#REDIRECT [[Someplace]]', + ), + array( + '/* #REDIRECT */mw.loader.load("//example.org/w/index.php?title=MediaWiki:MonoBook.js\u0026action=raw\u0026ctype=text/javascript");', + '/* #REDIRECT */mw.loader.load("//example.org/w/index.php?title=TestUpdateRedirect_target\u0026action=raw\u0026ctype=text/javascript");' + ) ); } @@ -290,4 +305,32 @@ class JavaScriptContentTest extends TextContentTest { array( new JavaScriptContent( "hallo" ), new JavaScriptContent( "HALLO" ), false ), ); } + + /** + * @dataProvider provideGetRedirectTarget + */ + public function testGetRedirectTarget( $title, $text ) { + $this->setMwGlobals( array( + 'wgServer' => '//example.org', + 'wgScriptPath' => '/w/index.php', + ) ); + $content = new JavaScriptContent( $text ); + $target = $content->getRedirectTarget(); + $this->assertEquals( $title, $target ? $target->getPrefixedText() : null ); + } + + /** + * Keep this in sync with JavaScriptContentHandlerTest::provideMakeRedirectContent() + */ + public static function provideGetRedirectTarget() { + return array( + array( 'MediaWiki:MonoBook.js', '/* #REDIRECT */mw.loader.load("//example.org/w/index.php?title=MediaWiki:MonoBook.js\u0026action=raw\u0026ctype=text/javascript");' ), + array( 'User:FooBar/common.js', '/* #REDIRECT */mw.loader.load("//example.org/w/index.php?title=User:FooBar/common.js\u0026action=raw\u0026ctype=text/javascript");' ), + array( 'Gadget:FooBaz.js', '/* #REDIRECT */mw.loader.load("//example.org/w/index.php?title=Gadget:FooBaz.js\u0026action=raw\u0026ctype=text/javascript");' ), + // No #REDIRECT comment + array( null, 'mw.loader.load("//example.org/w/index.php?title=MediaWiki:NoRedirect.js\u0026action=raw\u0026ctype=text/javascript");' ), + // Different domain + array( null, '/* #REDIRECT */mw.loader.load("//example.com/w/index.php?title=MediaWiki:OtherWiki.js\u0026action=raw\u0026ctype=text/javascript");' ), + ); + } } diff --git a/tests/phpunit/includes/content/JsonContentTest.php b/tests/phpunit/includes/content/JsonContentTest.php index cccfe7b1..8a9d2ab0 100644 --- a/tests/phpunit/includes/content/JsonContentTest.php +++ b/tests/phpunit/includes/content/JsonContentTest.php @@ -138,7 +138,7 @@ class JsonContentTest extends MediaWikiLangTestCase { '0"bar"' ), array( - (object)array( ''), + (object)array( '' ), '
              0"' . '<script>alert("evil!")</script>"' . '
              ', diff --git a/tests/phpunit/includes/content/TextContentHandlerTest.php b/tests/phpunit/includes/content/TextContentHandlerTest.php new file mode 100644 index 00000000..492fec6b --- /dev/null +++ b/tests/phpunit/includes/content/TextContentHandlerTest.php @@ -0,0 +1,12 @@ +assertTrue( $handler->supportsDirectEditing(), 'direct editing is supported' ); + } + +} diff --git a/tests/phpunit/includes/content/TextContentTest.php b/tests/phpunit/includes/content/TextContentTest.php index dd61f85b..fe263756 100644 --- a/tests/phpunit/includes/content/TextContentTest.php +++ b/tests/phpunit/includes/content/TextContentTest.php @@ -27,10 +27,16 @@ class TextContentTest extends MediaWikiLangTestCase { CONTENT_MODEL_JAVASCRIPT, ), 'wgUseTidy' => false, - 'wgAlwaysUseTidy' => false, 'wgCapitalLinks' => true, 'wgHooks' => array(), // bypass hook ContentGetParserOutput that force custom rendering ) ); + + MWTidy::destroySingleton(); + } + + protected function tearDown() { + MWTidy::destroySingleton(); + parent::tearDown(); } public function newContent( $text ) { diff --git a/tests/phpunit/includes/content/WikitextContentHandlerTest.php b/tests/phpunit/includes/content/WikitextContentHandlerTest.php index 38fb5733..361238b7 100644 --- a/tests/phpunit/includes/content/WikitextContentHandlerTest.php +++ b/tests/phpunit/includes/content/WikitextContentHandlerTest.php @@ -115,6 +115,11 @@ class WikitextContentHandlerTest extends MediaWikiLangTestCase { $this->assertEquals( $supported, $this->handler->isSupportedFormat( $format ) ); } + public function testSupportsDirectEditing() { + $handler = new WikiTextContentHandler(); + $this->assertTrue( $handler->supportsDirectEditing(), 'direct editing is supported' ); + } + public static function dataMerge3() { return array( array( diff --git a/tests/phpunit/includes/db/DatabaseMysqlBaseTest.php b/tests/phpunit/includes/db/DatabaseMysqlBaseTest.php index b4292a60..42ea58e5 100644 --- a/tests/phpunit/includes/db/DatabaseMysqlBaseTest.php +++ b/tests/phpunit/includes/db/DatabaseMysqlBaseTest.php @@ -181,7 +181,7 @@ class DatabaseMysqlBaseTest extends MediaWikiTestCase { array( 'Tables_in_' => 'view2' ), array( 'Tables_in_' => 'myview' ), false # no more rows - )); + ) ); return $db; } /** diff --git a/tests/phpunit/includes/db/DatabaseSqliteTest.php b/tests/phpunit/includes/db/DatabaseSqliteTest.php index 645baf1f..3db9172a 100644 --- a/tests/phpunit/includes/db/DatabaseSqliteTest.php +++ b/tests/phpunit/includes/db/DatabaseSqliteTest.php @@ -1,12 +1,13 @@ markTestSkipped( 'No SQLite support detected' ); } - $this->db = MockDatabaseSqlite::newInstance(); + $this->db = DatabaseSqliteMock::newInstance(); if ( version_compare( $this->db->getServerVersion(), '3.6.0', '<' ) ) { $this->markTestSkipped( "SQLite at least 3.6 required, {$this->db->getServerVersion()} found" ); } @@ -188,18 +189,34 @@ class DatabaseSqliteTest extends MediaWikiTestCase { public function testDuplicateTableStructure() { $db = DatabaseSqlite::newStandaloneInstance( ':memory:' ); $db->query( 'CREATE TABLE foo(foo, barfoo)' ); + $db->query( 'CREATE INDEX index1 ON foo(foo)' ); + $db->query( 'CREATE UNIQUE INDEX index2 ON foo(barfoo)' ); $db->duplicateTableStructure( 'foo', 'bar' ); $this->assertEquals( 'CREATE TABLE "bar"(foo, barfoo)', $db->selectField( 'sqlite_master', 'sql', array( 'name' => 'bar' ) ), 'Normal table duplication' ); + $indexList = $db->query( 'PRAGMA INDEX_LIST("bar")' ); + $index = $indexList->next(); + $this->assertEquals( 'bar_index1', $index->name ); + $this->assertEquals( '0', $index->unique ); + $index = $indexList->next(); + $this->assertEquals( 'bar_index2', $index->name ); + $this->assertEquals( '1', $index->unique ); $db->duplicateTableStructure( 'foo', 'baz', true ); $this->assertEquals( 'CREATE TABLE "baz"(foo, barfoo)', $db->selectField( 'sqlite_temp_master', 'sql', array( 'name' => 'baz' ) ), 'Creation of temporary duplicate' ); + $indexList = $db->query( 'PRAGMA INDEX_LIST("baz")' ); + $index = $indexList->next(); + $this->assertEquals( 'baz_index1', $index->name ); + $this->assertEquals( '0', $index->unique ); + $index = $indexList->next(); + $this->assertEquals( 'baz_index2', $index->name ); + $this->assertEquals( '1', $index->unique ); $this->assertEquals( 0, $db->selectField( 'sqlite_master', 'COUNT(*)', array( 'name' => 'baz' ) ), 'Create a temporary duplicate only' diff --git a/tests/phpunit/includes/db/ORMTableTest.php b/tests/phpunit/includes/db/ORMTableTest.php index 338d931f..764560d5 100644 --- a/tests/phpunit/includes/db/ORMTableTest.php +++ b/tests/phpunit/includes/db/ORMTableTest.php @@ -68,25 +68,6 @@ class ORMTableTest extends MediaWikiTestCase { $this->assertInstanceOf( $class, $class::singleton() ); $this->assertTrue( $class::singleton() === $class::singleton() ); } - - /** - * @since 1.21 - */ - public function testIgnoreErrorsOverride() { - $table = $this->getTable(); - - $db = $table->getReadDbConnection(); - $db->ignoreErrors( true ); - - try { - $table->rawSelect( "this is invalid" ); - $this->fail( "An invalid query should trigger a DBQueryError even if ignoreErrors is enabled." ); - } catch ( DBQueryError $ex ) { - $this->assertTrue( true, "just making phpunit happy" ); - } - - $db->ignoreErrors( false ); - } } /** diff --git a/tests/phpunit/includes/debug/MWDebugTest.php b/tests/phpunit/includes/debug/MWDebugTest.php index 1abb47e7..7280a97b 100644 --- a/tests/phpunit/includes/debug/MWDebugTest.php +++ b/tests/phpunit/includes/debug/MWDebugTest.php @@ -12,11 +12,11 @@ class MWDebugTest extends MediaWikiTestCase { } /** Clear log before each test */ MWDebug::clearLog(); - wfSuppressWarnings(); + MediaWiki\suppressWarnings(); } protected function tearDown() { - wfRestoreWarnings(); + MediaWiki\restoreWarnings(); parent::tearDown(); } diff --git a/tests/phpunit/includes/debug/logger/LegacyLoggerTest.php b/tests/phpunit/includes/debug/logger/LegacyLoggerTest.php new file mode 100644 index 00000000..1b3ce2ca --- /dev/null +++ b/tests/phpunit/includes/debug/logger/LegacyLoggerTest.php @@ -0,0 +1,175 @@ +assertEquals( + $expect, LegacyLogger::interpolate( $message, $context ) ); + } + + public function provideInterpolate() { + $e = new \Exception( 'boom!' ); + $d = new \DateTime(); + return array( + array( + 'no-op', + array(), + 'no-op', + ), + array( + 'Hello {world}!', + array( + 'world' => 'World', + ), + 'Hello World!', + ), + array( + '{greeting} {user}', + array( + 'greeting' => 'Goodnight', + 'user' => 'Moon', + ), + 'Goodnight Moon', + ), + array( + 'Oops {key_not_set}', + array(), + 'Oops {key_not_set}', + ), + array( + '{ not interpolated }', + array( + 'not interpolated' => 'This should NOT show up in the message', + ), + '{ not interpolated }', + ), + array( + '{null}', + array( + 'null' => null, + ), + '[Null]', + ), + array( + '{bool}', + array( + 'bool' => true, + ), + 'true', + ), + array( + '{float}', + array( + 'float' => 1.23, + ), + '1.23', + ), + array( + '{array}', + array( + 'array' => array( 1, 2, 3 ), + ), + '[Array(3)]', + ), + array( + '{exception}', + array( + 'exception' => $e, + ), + '[Exception ' . get_class( $e ) . '( ' . + $e->getFile() . ':' . $e->getLine() . ') ' . + $e->getMessage() . ']', + ), + array( + '{datetime}', + array( + 'datetime' => $d, + ), + $d->format( 'c' ), + ), + array( + '{object}', + array( + 'object' => new \stdClass, + ), + '[Object stdClass]', + ), + ); + } + + /** + * @covers LegacyLogger::shouldEmit + * @dataProvider provideShouldEmit + */ + public function testShouldEmit( $level, $config, $expected ) { + $this->setMwGlobals( 'wgDebugLogGroups', array( 'fakechannel' => $config ) ); + $this->assertEquals( + $expected, + LegacyLogger::shouldEmit( 'fakechannel', 'some message', $level, array() ) + ); + } + + public static function provideShouldEmit() { + $dest = array( 'destination' => 'foobar' ); + $tests = array( + array( + LogLevel::DEBUG, + $dest, + true + ), + array( + LogLevel::WARNING, + $dest + array( 'level' => LogLevel::INFO ), + true, + ), + array( + LogLevel::INFO, + $dest + array( 'level' => LogLevel::CRITICAL ), + false, + ), + ); + + if ( class_exists( '\Monolog\Logger' ) ) { + $tests[] = array( + \Monolog\Logger::INFO, + $dest + array( 'level' => LogLevel::INFO ), + true, + ); + $tests[] = array( + \Monolog\Logger::WARNING, + $dest + array( 'level' => LogLevel::EMERGENCY ), + false, + ); + } + + return $tests; + } + +} diff --git a/tests/phpunit/includes/debug/logger/MonologSpiTest.php b/tests/phpunit/includes/debug/logger/MonologSpiTest.php new file mode 100644 index 00000000..aa0a54ff --- /dev/null +++ b/tests/phpunit/includes/debug/logger/MonologSpiTest.php @@ -0,0 +1,136 @@ + array( + '@default' => array( + 'processors' => array( 'constructor' ), + 'handlers' => array( 'constructor' ), + ), + ), + 'processors' => array( + 'constructor' => array( + 'class' => 'constructor', + ), + ), + 'handlers' => array( + 'constructor' => array( + 'class' => 'constructor', + 'formatter' => 'constructor', + ), + ), + 'formatters' => array( + 'constructor' => array( + 'class' => 'constructor', + ), + ), + ); + + $fixture = new MonologSpi( $base ); + $this->assertSame( + $base, + TestingAccessWrapper::newFromObject( $fixture )->config + ); + + $fixture->mergeConfig( array( + 'loggers' => array( + 'merged' => array( + 'processors' => array( 'merged' ), + 'handlers' => array( 'merged' ), + ), + ), + 'processors' => array( + 'merged' => array( + 'class' => 'merged', + ), + ), + 'magic' => array( + 'idkfa' => array( 'xyzzy' ), + ), + 'handlers' => array( + 'merged' => array( + 'class' => 'merged', + 'formatter' => 'merged', + ), + ), + 'formatters' => array( + 'merged' => array( + 'class' => 'merged', + ), + ), + ) ); + $this->assertSame( + array( + 'loggers' => array( + '@default' => array( + 'processors' => array( 'constructor' ), + 'handlers' => array( 'constructor' ), + ), + 'merged' => array( + 'processors' => array( 'merged' ), + 'handlers' => array( 'merged' ), + ), + ), + 'processors' => array( + 'constructor' => array( + 'class' => 'constructor', + ), + 'merged' => array( + 'class' => 'merged', + ), + ), + 'handlers' => array( + 'constructor' => array( + 'class' => 'constructor', + 'formatter' => 'constructor', + ), + 'merged' => array( + 'class' => 'merged', + 'formatter' => 'merged', + ), + ), + 'formatters' => array( + 'constructor' => array( + 'class' => 'constructor', + ), + 'merged' => array( + 'class' => 'merged', + ), + ), + 'magic' => array( + 'idkfa' => array( 'xyzzy' ), + ), + ), + TestingAccessWrapper::newFromObject( $fixture )->config + ); + } + +} diff --git a/tests/phpunit/includes/debug/logger/monolog/AvroFormatterTest.php b/tests/phpunit/includes/debug/logger/monolog/AvroFormatterTest.php new file mode 100644 index 00000000..44242ed2 --- /dev/null +++ b/tests/phpunit/includes/debug/logger/monolog/AvroFormatterTest.php @@ -0,0 +1,64 @@ +markTestSkipped( 'Avro is required for the AvroFormatterTest' ); + } + parent::setUp(); + } + + public function testSchemaNotAvailable() { + $formatter = new AvroFormatter( array() ); + $this->setExpectedException( 'PHPUnit_Framework_Error_Notice', "The schema for channel 'marty' is not available" ); + $formatter->format( array( 'channel' => 'marty' ) ); + } + + public function testSchemaNotAvailableReturnValue() { + $formatter = new AvroFormatter( array() ); + $noticeEnabled = PHPUnit_Framework_Error_Notice::$enabled; + // disable conversion of notices + PHPUnit_Framework_Error_Notice::$enabled = false; + // have to keep the user notice from being output + wfSuppressWarnings(); + $res = $formatter->format( array( 'channel' => 'marty' ) ); + wfRestoreWarnings(); + PHPUnit_Framework_Error_Notice::$enabled = $noticeEnabled; + $this->assertNull( $res ); + } + + public function testDoesSomethingWhenSchemaAvailable() { + $formatter = new AvroFormatter( array( 'string' => array( 'type' => 'string' ) ) ); + $res = $formatter->format( array( + 'channel' => 'string', + 'context' => 'better to be', + ) ); + $this->assertNotNull( $res ); + // basically just tell us if avro changes its string encoding + $this->assertEquals( base64_decode( 'GGJldHRlciB0byBiZQ==' ), $res ); + } +} diff --git a/tests/phpunit/includes/debug/logger/monolog/KafkaHandlerTest.php b/tests/phpunit/includes/debug/logger/monolog/KafkaHandlerTest.php new file mode 100644 index 00000000..090f439e --- /dev/null +++ b/tests/phpunit/includes/debug/logger/monolog/KafkaHandlerTest.php @@ -0,0 +1,207 @@ +markTestSkipped( 'Monolog and Kafka are required for the KafkaHandlerTest' ); + } + + parent::setUp(); + } + + public function topicNamingProvider() { + return array( + array( array(), 'monolog_foo' ), + array( array( 'alias' => array( 'foo' => 'bar' ) ), 'bar' ) + ); + } + + /** + * @dataProvider topicNamingProvider + */ + public function testTopicNaming( $options, $expect ) { + $produce = $this->getMockBuilder( 'Kafka\Produce' ) + ->disableOriginalConstructor() + ->getMock(); + $produce->expects($this->any()) + ->method('getAvailablePartitions') + ->will($this->returnValue( array( 'A' ) ) ); + $produce->expects($this->once()) + ->method( 'setMessages' ) + ->with( $expect, $this->anything(), $this->anything() ); + + $handler = new KafkaHandler( $produce, $options ); + $handler->handle( array( + 'channel' => 'foo', + 'level' => Logger::EMERGENCY, + 'extra' => array(), + ) ); + } + + public function swallowsExceptionsWhenRequested() { + return array( + // defaults to false + array( array(), true ), + // also try false explicitly + array( array( 'swallowExceptions' => false ), true ), + // turn it on + array( array( 'swallowExceptions' => true ), false ), + ); + } + + /** + * @dataProvider swallowsExceptionsWhenRequested + */ + public function testGetAvailablePartitionsException( $options, $expectException ) { + $produce = $this->getMockBuilder( 'Kafka\Produce' ) + ->disableOriginalConstructor() + ->getMock(); + $produce->expects( $this->any() ) + ->method( 'getAvailablePartitions' ) + ->will( $this->throwException( new \Kafka\Exception ) ); + + if ( $expectException ) { + $this->setExpectedException( 'Kafka\Exception' ); + } + + $handler = new KafkaHandler( $produce, $options ); + $handler->handle( array( + 'channel' => 'foo', + 'level' => Logger::EMERGENCY, + 'extra' => array(), + ) ); + + if ( !$expectException ) { + $this->assertTrue( true, 'no exception was thrown' ); + } + } + + /** + * @dataProvider swallowsExceptionsWhenRequested + */ + public function testSendException( $options, $expectException ) { + $produce = $this->getMockBuilder( 'Kafka\Produce' ) + ->disableOriginalConstructor() + ->getMock(); + $produce->expects( $this->any() ) + ->method( 'getAvailablePartitions' ) + ->will( $this->returnValue( array( 'A' ) ) ); + $produce->expects( $this->any() ) + ->method( 'send' ) + ->will( $this->throwException( new \Kafka\Exception ) ); + + if ( $expectException ) { + $this->setExpectedException( 'Kafka\Exception' ); + } + + $handler = new KafkaHandler( $produce, $options ); + $handler->handle( array( + 'channel' => 'foo', + 'level' => Logger::EMERGENCY, + 'extra' => array(), + ) ); + + if ( !$expectException ) { + $this->assertTrue( true, 'no exception was thrown' ); + } + } + + public function testHandlesNullFormatterResult() { + $produce = $this->getMockBuilder( 'Kafka\Produce' ) + ->disableOriginalConstructor() + ->getMock(); + $produce->expects( $this->any() ) + ->method( 'getAvailablePartitions' ) + ->will( $this->returnValue( array( 'A' ) ) ); + $mockMethod = $produce->expects( $this->exactly( 2 ) ) + ->method( 'setMessages' ); + // evil hax + \TestingAccessWrapper::newFromObject( $mockMethod )->matcher->parametersMatcher = + new \PHPUnit_Framework_MockObject_Matcher_ConsecutiveParameters( array( + array( $this->anything(), $this->anything(), array( 'words' ) ), + array( $this->anything(), $this->anything(), array( 'lines' ) ) + ) ); + + $formatter = $this->getMock( 'Monolog\Formatter\FormatterInterface' ); + $formatter->expects( $this->any() ) + ->method( 'format' ) + ->will( $this->onConsecutiveCalls( 'words', null, 'lines' ) ); + + $handler = new KafkaHandler( $produce, array() ); + $handler->setFormatter( $formatter ); + for ( $i = 0; $i < 3; ++$i ) { + $handler->handle( array( + 'channel' => 'foo', + 'level' => Logger::EMERGENCY, + 'extra' => array(), + ) ); + } + } + + + public function testBatchHandlesNullFormatterResult() { + $produce = $this->getMockBuilder( 'Kafka\Produce' ) + ->disableOriginalConstructor() + ->getMock(); + $produce->expects( $this->any() ) + ->method( 'getAvailablePartitions' ) + ->will( $this->returnValue( array( 'A' ) ) ); + $produce->expects( $this->once() ) + ->method( 'setMessages' ) + ->with( $this->anything(), $this->anything(), array( 'words', 'lines' ) ); + + $formatter = $this->getMock( 'Monolog\Formatter\FormatterInterface' ); + $formatter->expects( $this->any() ) + ->method( 'format' ) + ->will( $this->onConsecutiveCalls( 'words', null, 'lines' ) ); + + $handler = new KafkaHandler( $produce, array() ); + $handler->setFormatter( $formatter ); + $handler->handleBatch( array( + array( + 'channel' => 'foo', + 'level' => Logger::EMERGENCY, + 'extra' => array(), + ), + array( + 'channel' => 'foo', + 'level' => Logger::EMERGENCY, + 'extra' => array(), + ), + array( + 'channel' => 'foo', + 'level' => Logger::EMERGENCY, + 'extra' => array(), + ), + ) ); + } +} diff --git a/tests/phpunit/includes/debug/logger/monolog/LineFormatterTest.php b/tests/phpunit/includes/debug/logger/monolog/LineFormatterTest.php new file mode 100644 index 00000000..be23c4a2 --- /dev/null +++ b/tests/phpunit/includes/debug/logger/monolog/LineFormatterTest.php @@ -0,0 +1,75 @@ +markTestSkipped( 'This test requires monolog to be installed' ); + } + parent::setUp(); + } + + /** + * @covers LineFormatter::normalizeException + */ + public function testNormalizeExceptionNoTrace() { + $fixture = new LineFormatter(); + $fixture->includeStacktraces( false ); + $fixture = TestingAccessWrapper::newFromObject( $fixture ); + $boom = new InvalidArgumentException( 'boom', 0, + new LengthException( 'too long', 0, + new LogicException( 'Spock wuz here' ) + ) + ); + $out = $fixture->normalizeException( $boom ); + $this->assertContains( "\n[Exception InvalidArgumentException]", $out ); + $this->assertContains( "\nCaused by: [Exception LengthException]", $out ); + $this->assertContains( "\nCaused by: [Exception LogicException]", $out ); + $this->assertNotContains( "\n #0", $out ); + } + + /** + * @covers LineFormatter::normalizeException + */ + public function testNormalizeExceptionTrace() { + $fixture = new LineFormatter(); + $fixture->includeStacktraces( true ); + $fixture = TestingAccessWrapper::newFromObject( $fixture ); + $boom = new InvalidArgumentException( 'boom', 0, + new LengthException( 'too long', 0, + new LogicException( 'Spock wuz here' ) + ) + ); + $out = $fixture->normalizeException( $boom ); + $this->assertContains( "\n[Exception InvalidArgumentException]", $out ); + $this->assertContains( "\nCaused by: [Exception LengthException]", $out ); + $this->assertContains( "\nCaused by: [Exception LogicException]", $out ); + $this->assertContains( "\n #0", $out ); + } +} diff --git a/tests/phpunit/includes/debug/logging/LegacyLoggerTest.php b/tests/phpunit/includes/debug/logging/LegacyLoggerTest.php deleted file mode 100644 index 415fa045..00000000 --- a/tests/phpunit/includes/debug/logging/LegacyLoggerTest.php +++ /dev/null @@ -1,122 +0,0 @@ -assertEquals( - $expect, LegacyLogger::interpolate( $message, $context ) ); - } - - public function provideInterpolate() { - return array( - array( - 'no-op', - array(), - 'no-op', - ), - array( - 'Hello {world}!', - array( - 'world' => 'World', - ), - 'Hello World!', - ), - array( - '{greeting} {user}', - array( - 'greeting' => 'Goodnight', - 'user' => 'Moon', - ), - 'Goodnight Moon', - ), - array( - 'Oops {key_not_set}', - array(), - 'Oops {key_not_set}', - ), - array( - '{ not interpolated }', - array( - 'not interpolated' => 'This should NOT show up in the message', - ), - '{ not interpolated }', - ), - ); - } - - /** - * @covers LegacyLogger::shouldEmit - * @dataProvider provideShouldEmit - */ - public function testShouldEmit( $level, $config, $expected ) { - $this->setMwGlobals( 'wgDebugLogGroups', array( 'fakechannel' => $config ) ); - $this->assertEquals( - $expected, - LegacyLogger::shouldEmit( 'fakechannel', 'some message', $level, array() ) - ); - } - - public static function provideShouldEmit() { - $dest = array( 'destination' => 'foobar' ); - $tests = array( - array( - LogLevel::DEBUG, - $dest, - true - ), - array( - LogLevel::WARNING, - $dest + array( 'level' => LogLevel::INFO ), - true, - ), - array( - LogLevel::INFO, - $dest + array( 'level' => LogLevel::CRITICAL ), - false, - ), - ); - - if ( class_exists( '\Monolog\Logger' ) ) { - $tests[] = array( - \Monolog\Logger::INFO, - $dest + array( 'level' => LogLevel::INFO ), - true, - ); - $tests[] = array( - \Monolog\Logger::WARNING, - $dest + array( 'level' => LogLevel::EMERGENCY ), - false, - ); - } - - return $tests; - } - -} diff --git a/tests/phpunit/includes/deferred/DeferredUpdatesTest.php b/tests/phpunit/includes/deferred/DeferredUpdatesTest.php index 5348c854..df4213ab 100644 --- a/tests/phpunit/includes/deferred/DeferredUpdatesTest.php +++ b/tests/phpunit/includes/deferred/DeferredUpdatesTest.php @@ -1,8 +1,9 @@ setMwGlobals( 'wgCommandLineMode', false ); - public function testDoUpdates() { $updates = array( '1' => 'deferred update 1', '2' => 'deferred update 2', @@ -35,4 +36,38 @@ class DeferredUpdatesTest extends MediaWikiTestCase { DeferredUpdates::doUpdates(); } + public function testDoUpdatesCLI() { + $this->setMwGlobals( 'wgCommandLineMode', true ); + + $updates = array( + '1' => 'deferred update 1', + '2' => 'deferred update 2', + '2-1' => 'deferred update 1 within deferred update 2', + '3' => 'deferred update 3', + ); + DeferredUpdates::addCallableUpdate( + function () use ( $updates ) { + echo $updates['1']; + } + ); + DeferredUpdates::addCallableUpdate( + function () use ( $updates ) { + echo $updates['2']; + DeferredUpdates::addCallableUpdate( + function () use ( $updates ) { + echo $updates['2-1']; + } + ); + } + ); + DeferredUpdates::addCallableUpdate( + function () use ( $updates ) { + echo $updates[3]; + } + ); + + $this->expectOutputString( implode( '', $updates ) ); + + DeferredUpdates::doUpdates(); + } } diff --git a/tests/phpunit/includes/diff/ArrayDiffFormatterTest.php b/tests/phpunit/includes/diff/ArrayDiffFormatterTest.php index 3bea9b31..a546bec1 100644 --- a/tests/phpunit/includes/diff/ArrayDiffFormatterTest.php +++ b/tests/phpunit/includes/diff/ArrayDiffFormatterTest.php @@ -69,11 +69,11 @@ class ArrayDiffFormatterTest extends MediaWikiTestCase { $otherTestCases = array(); $otherTestCases[] = array( - $this->getMockDiff( array( $this->getMockDiffOp( 'add', array( ), array( 'a1' ) ) ) ), + $this->getMockDiff( array( $this->getMockDiffOp( 'add', array(), array( 'a1' ) ) ) ), array( array( 'action' => 'add', 'new' => 'a1', 'newline' => 1 ) ), ); $otherTestCases[] = array( - $this->getMockDiff( array( $this->getMockDiffOp( 'add', array( ), array( 'a1', 'a2' ) ) ) ), + $this->getMockDiff( array( $this->getMockDiffOp( 'add', array(), array( 'a1', 'a2' ) ) ) ), array( array( 'action' => 'add', 'new' => 'a1', 'newline' => 1 ), array( 'action' => 'add', 'new' => 'a2', 'newline' => 2 ), diff --git a/tests/phpunit/includes/exception/HttpErrorTest.php b/tests/phpunit/includes/exception/HttpErrorTest.php new file mode 100644 index 00000000..66fe90c9 --- /dev/null +++ b/tests/phpunit/includes/exception/HttpErrorTest.php @@ -0,0 +1,65 @@ +assertFalse( $httpError->isLoggable(), 'http error is not loggable' ); + } + + public function testGetStatusCode() { + $httpError = new HttpError( 500, 'server error!' ); + $this->assertEquals( 500, $httpError->getStatusCode() ); + } + + /** + * @dataProvider getHtmlProvider + */ + public function testGetHtml( array $expected, $content, $header ) { + $httpError = new HttpError( 500, $content, $header ); + $errorHtml = $httpError->getHtml(); + + foreach ( $expected as $key => $html ) { + $this->assertContains( $html, $errorHtml, $key ); + } + } + + public function getHtmlProvider() { + return array( + array( + array( + 'head html' => 'Server Error 123', + 'body html' => '

              Server Error 123

              ' + . '

              a server error!

              ' + ), + 'a server error!', + 'Server Error 123' + ), + array( + array( + 'head html' => 'loginerror', + 'body html' => '

              loginerror

              ' + . '

              suspicious-userlogout

              ' + ), + new RawMessage( 'suspicious-userlogout' ), + new RawMessage( 'loginerror' ) + ), + array( + array( + 'head html' => 'Internal Server Error', + 'body html' => '

              Internal Server Error

              ' + . '

              a server error!

              ' + ), + 'a server error!', + null + ) + ); + } + + +} diff --git a/tests/phpunit/includes/exception/MWExceptionTest.php b/tests/phpunit/includes/exception/MWExceptionTest.php index ef0f2a9e..f11fda32 100644 --- a/tests/phpunit/includes/exception/MWExceptionTest.php +++ b/tests/phpunit/includes/exception/MWExceptionTest.php @@ -178,7 +178,7 @@ class MWExceptionTest extends MediaWikiTestCase { $this->setMwGlobals( array( 'wgLogExceptionBacktrace' => true ) ); $json = json_decode( - MWExceptionHandler::jsonSerializeException( new $exClass()) + MWExceptionHandler::jsonSerializeException( new $exClass() ) ); $this->assertObjectHasAttribute( $key, $json, "JSON serialized exception is missing key '$key'" diff --git a/tests/phpunit/includes/filebackend/FileBackendTest.php b/tests/phpunit/includes/filebackend/FileBackendTest.php index bfca75ad..2e4942f0 100644 --- a/tests/phpunit/includes/filebackend/FileBackendTest.php +++ b/tests/phpunit/includes/filebackend/FileBackendTest.php @@ -2376,7 +2376,7 @@ class FileBackendTest extends MediaWikiTestCase { $status = Status::newGood(); $sl = $this->backend->getScopedFileLocks( $paths, LockManager::LOCK_EX, $status ); - $this->assertType( 'ScopedLock', $sl, + $this->assertInstanceOf( 'ScopedLock', $sl, "Scoped locking of files succeeded ($backendName)." ); $this->assertEquals( array(), $status->errors, "Scoped locking of files succeeded ($backendName)." ); @@ -2392,6 +2392,56 @@ class FileBackendTest extends MediaWikiTestCase { "Scoped unlocking of files succeeded with OK status ($backendName)." ); } + public function testReadAffinity() { + $be = TestingAccessWrapper::newFromObject( + new FileBackendMultiWrite( array( + 'name' => 'localtesting', + 'wikiId' => wfWikiId() . mt_rand(), + 'backends' => array( + array( // backend 0 + 'name' => 'multitesting0', + 'class' => 'MemoryFileBackend', + 'isMultiMaster' => false, + 'readAffinity' => true + ), + array( // backend 1 + 'name' => 'multitesting1', + 'class' => 'MemoryFileBackend', + 'isMultiMaster' => true + ) + ) + ) ) + ); + + $this->assertEquals( + 1, + $be->getReadIndexFromParams( array( 'latest' => 1 ) ), + 'Reads with "latest" flag use backend 1' + ); + $this->assertEquals( + 0, + $be->getReadIndexFromParams( array( 'latest' => 0 ) ), + 'Reads without "latest" flag use backend 0' + ); + + $p = 'container/test-cont/file.txt'; + $be->backends[0]->quickCreate( array( + 'dst' => "mwstore://multitesting0/$p", 'content' => 'cattitude' ) ); + $be->backends[1]->quickCreate( array( + 'dst' => "mwstore://multitesting1/$p", 'content' => 'princess of power' ) ); + + $this->assertEquals( + 'cattitude', + $be->getFileContents( array( 'src' => "mwstore://localtesting/$p" ) ), + "Non-latest read came from backend 0" + ); + $this->assertEquals( + 'princess of power', + $be->getFileContents( array( 'src' => "mwstore://localtesting/$p", 'latest' => 1 ) ), + "Latest read came from backend1" + ); + } + // helper function private function listToArray( $iter ) { return is_array( $iter ) ? $iter : iterator_to_array( $iter ); diff --git a/tests/phpunit/includes/filebackend/SwiftFileBackendTest.php b/tests/phpunit/includes/filebackend/SwiftFileBackendTest.php new file mode 100644 index 00000000..a618889c --- /dev/null +++ b/tests/phpunit/includes/filebackend/SwiftFileBackendTest.php @@ -0,0 +1,148 @@ +backend = TestingAccessWrapper::newFromObject( + new SwiftFileBackend( array( + 'name' => 'local-swift-testing', + 'class' => 'SwiftFileBackend', + 'wikiId' => 'unit-testing', + 'lockManager' => LockManagerGroup::singleton()->get( 'fsLockManager' ), + 'swiftAuthUrl' => 'http://127.0.0.1:8080/auth', // unused + 'swiftUser' => 'test:tester', + 'swiftKey' => 'testing', + 'swiftTempUrlKey' => 'b3968d0207b54ece87cccc06515a89d4' // unused + ) ) + ); + } + + /** + * @dataProvider provider_testSanitzeHdrs + * @covers SwiftFileBackend::sanitzeHdrs + * @covers SwiftFileBackend::getCustomHeaders + */ + public function testSanitzeHdrs( $raw, $sanitized ) { + $hdrs = $this->backend->sanitizeHdrs( array( 'headers' => $raw ) ); + + $this->assertEquals( $hdrs, $sanitized, 'sanitizeHdrs() has expected result' ); + } + + public static function provider_testSanitzeHdrs() { + return array( + array( + array( + 'content-length' => 345, + 'content-type' => 'image+bitmap/jpeg', + 'content-disposition' => 'inline', + 'content-duration' => 35.6363, + 'content-Custom' => 'hello', + 'x-content-custom' => 'hello' + ), + array( + 'content-disposition' => 'inline', + 'content-duration' => 35.6363, + 'content-custom' => 'hello', + 'x-content-custom' => 'hello' + ) + ), + array( + array( + 'content-length' => 345, + 'content-type' => 'image+bitmap/jpeg', + 'content-Disposition' => 'inline; filename=xxx; ' . str_repeat( 'o', 1024 ), + 'content-duration' => 35.6363, + 'content-custom' => 'hello', + 'x-content-custom' => 'hello' + ), + array( + 'content-disposition' => 'inline;filename=xxx', + 'content-duration' => 35.6363, + 'content-custom' => 'hello', + 'x-content-custom' => 'hello' + ) + ), + array( + array( + 'content-length' => 345, + 'content-type' => 'image+bitmap/jpeg', + 'content-disposition' => 'filename='. str_repeat( 'o', 1024 ) . ';inline', + 'content-duration' => 35.6363, + 'content-custom' => 'hello', + 'x-content-custom' => 'hello' + ), + array( + 'content-disposition' => '', + 'content-duration' => 35.6363, + 'content-custom' => 'hello', + 'x-content-custom' => 'hello' + ) + ) + ); + } + + /** + * @dataProvider provider_testGetMetadataHeaders + * @covers SwiftFileBackend::getMetadataHeaders + */ + public function testGetMetadataHeaders( $raw, $sanitized ) { + $hdrs = $this->backend->getMetadataHeaders( $raw ); + + $this->assertEquals( $hdrs, $sanitized, 'getMetadataHeaders() has expected result' ); + } + + public static function provider_testGetMetadataHeaders() { + return array( + array( + array( + 'content-length' => 345, + 'content-custom' => 'hello', + 'x-content-custom' => 'hello', + 'x-object-meta-custom' => 5, + 'x-object-meta-sha1Base36' => 'a3deadfg...', + ), + array( + 'x-object-meta-custom' => 5, + 'x-object-meta-sha1base36' => 'a3deadfg...', + ) + ) + ); + } + + /** + * @dataProvider provider_testGetMetadata + * @covers SwiftFileBackend::getMetadata + */ + public function testGetMetadata( $raw, $sanitized ) { + $hdrs = $this->backend->getMetadata( $raw ); + + $this->assertEquals( $hdrs, $sanitized, 'getMetadata() has expected result' ); + } + + public static function provider_testGetMetadata() { + return array( + array( + array( + 'content-length' => 345, + 'content-custom' => 'hello', + 'x-content-custom' => 'hello', + 'x-object-meta-custom' => 5, + 'x-object-meta-sha1Base36' => 'a3deadfg...', + ), + array( + 'custom' => 5, + 'sha1base36' => 'a3deadfg...', + ) + ) + ); + } +} \ No newline at end of file diff --git a/tests/phpunit/includes/filerepo/FileBackendDBRepoWrapperTest.php b/tests/phpunit/includes/filerepo/FileBackendDBRepoWrapperTest.php new file mode 100644 index 00000000..681e3681 --- /dev/null +++ b/tests/phpunit/includes/filerepo/FileBackendDBRepoWrapperTest.php @@ -0,0 +1,138 @@ +expects( $dbReadsExpected ) + ->method( 'selectField' ) + ->will( $this->returnValue( $dbReturnValue ) ); + + $newPaths = $wrapperMock->getBackendPaths( array( $originalPath ), $latest ); + + $this->assertEquals( + $expectedBackendPath, + $newPaths[0], + $message ); + } + + public function getBackendPathsProvider() { + $prefix = 'mwstore://' . $this->backendName . '/' . $this->repoName; + $mocksForCaching = $this->getMocks(); + + return array( + array( + $mocksForCaching, + false, + $this->once(), + '96246614d75ba1703bdfd5d7660bb57407aaf5d9', + $prefix . '-public/f/o/foobar.jpg', + $prefix . '-original/9/6/2/96246614d75ba1703bdfd5d7660bb57407aaf5d9', + 'Public path translated correctly', + ), + array( + $mocksForCaching, + false, + $this->never(), + '96246614d75ba1703bdfd5d7660bb57407aaf5d9', + $prefix . '-public/f/o/foobar.jpg', + $prefix . '-original/9/6/2/96246614d75ba1703bdfd5d7660bb57407aaf5d9', + 'LRU cache leveraged', + ), + array( + $this->getMocks(), + true, + $this->once(), + '96246614d75ba1703bdfd5d7660bb57407aaf5d9', + $prefix . '-public/f/o/foobar.jpg', + $prefix . '-original/9/6/2/96246614d75ba1703bdfd5d7660bb57407aaf5d9', + 'Latest obtained', + ), + array( + $this->getMocks(), + true, + $this->never(), + '96246614d75ba1703bdfd5d7660bb57407aaf5d9', + $prefix . '-deleted/f/o/foobar.jpg', + $prefix . '-original/f/o/o/foobar', + 'Deleted path translated correctly', + ), + array( + $this->getMocks(), + true, + $this->once(), + null, + $prefix . '-public/b/a/baz.jpg', + $prefix . '-public/b/a/baz.jpg', + 'Path left untouched if no sha1 can be found', + ), + ); + } + + /** + * @covers FileBackendDBRepoWrapper::getFileContentsMulti + */ + public function testGetFileContentsMulti() { + list( $dbMock, $backendMock, $wrapperMock ) = $this->getMocks(); + + $sha1Path = 'mwstore://' . $this->backendName . '/' . $this->repoName + . '-original/9/6/2/96246614d75ba1703bdfd5d7660bb57407aaf5d9'; + $filenamePath = 'mwstore://' . $this->backendName . '/' . $this->repoName + . '-public/f/o/foobar.jpg'; + + $dbMock->expects( $this->once() ) + ->method( 'selectField' ) + ->will( $this->returnValue( '96246614d75ba1703bdfd5d7660bb57407aaf5d9' ) ); + + $backendMock->expects( $this->once() ) + ->method( 'getFileContentsMulti') + ->will( $this->returnValue( array( $sha1Path => 'foo' ) ) ); + + $result = $wrapperMock->getFileContentsMulti( array( 'srcs' => array( $filenamePath ) ) ); + + $this->assertEquals( + array( $filenamePath => 'foo' ), + $result, + 'File contents paths translated properly' + ); + } + + protected function getMocks() { + $dbMock = $this->getMockBuilder( 'DatabaseMysql' ) + ->disableOriginalConstructor() + ->getMock(); + + $backendMock = $this->getMock( 'FSFileBackend', + array(), + array( array( + 'name' => $this->backendName, + 'wikiId' => wfWikiId() + ) ) ); + + $wrapperMock = $this->getMock( 'FileBackendDBRepoWrapper', + array( 'getDB' ), + array( array( + 'backend' => $backendMock, + 'repoName' => $this->repoName, + 'dbHandleFactory' => null + ) ) ); + + $wrapperMock->expects( $this->any() )->method( 'getDB' )->will( $this->returnValue( $dbMock ) ); + + return array( $dbMock, $backendMock, $wrapperMock ); + } +} diff --git a/tests/phpunit/includes/filerepo/MigrateFileRepoLayoutTest.php b/tests/phpunit/includes/filerepo/MigrateFileRepoLayoutTest.php new file mode 100644 index 00000000..551d3a76 --- /dev/null +++ b/tests/phpunit/includes/filerepo/MigrateFileRepoLayoutTest.php @@ -0,0 +1,114 @@ +tmpPrefix = wfTempDir() . '/migratefilelayout-test-' . time() . '-' . mt_rand(); + + $backend = new FSFileBackend( array( + 'name' => 'local-migratefilerepolayouttest', + 'wikiId' => wfWikiID(), + 'containerPaths' => array( + 'migratefilerepolayouttest-original' => "{$this->tmpPrefix}-original", + 'migratefilerepolayouttest-public' => "{$this->tmpPrefix}-public", + 'migratefilerepolayouttest-thumb' => "{$this->tmpPrefix}-thumb", + 'migratefilerepolayouttest-temp' => "{$this->tmpPrefix}-temp", + 'migratefilerepolayouttest-deleted' => "{$this->tmpPrefix}-deleted", + ) + ) ); + + $dbMock = $this->getMockBuilder( 'DatabaseMysql' ) + ->disableOriginalConstructor() + ->getMock(); + + $imageRow = new stdClass; + $imageRow->img_name = $filename; + $imageRow->img_sha1 = sha1( $this->text ); + + $dbMock->expects( $this->any() ) + ->method( 'select' ) + ->will( $this->onConsecutiveCalls( + new FakeResultWrapper( array( $imageRow ) ), // image + new FakeResultWrapper( array() ), // image + new FakeResultWrapper( array() ) // filearchive + ) ); + + $repoMock = $this->getMock( 'LocalRepo', + array( 'getMasterDB' ), + array( array( + 'name' => 'migratefilerepolayouttest', + 'backend' => $backend + ) ) ); + + $repoMock->expects( $this->any() )->method( 'getMasterDB' )->will( $this->returnValue( $dbMock ) ); + + $this->migratorMock = $this->getMock( 'MigrateFileRepoLayout', array( 'getRepo' ) ); + $this->migratorMock->expects( $this->any() )->method( 'getRepo' )->will( $this->returnValue( $repoMock ) ); + + $this->tmpFilepath = TempFSFile::factory( 'migratefilelayout-test-', 'png' )->getPath(); + + file_put_contents( $this->tmpFilepath, $this->text ); + + $hashPath = $repoMock->getHashPath( $filename ); + + $status = $repoMock->store( $this->tmpFilepath, 'public', $hashPath . $filename, FileRepo::OVERWRITE ); + } + + protected function deleteFilesRecursively( $directory ) { + foreach ( glob( $directory . '/*' ) as $file ) { + if ( is_dir( $file ) ) { + $this->deleteFilesRecursively( $file ); + } else { + unlink( $file ); + } + } + + rmdir( $directory ); + } + + protected function tearDown() { + foreach ( glob( $this->tmpPrefix . '*' ) as $directory ) { + $this->deleteFilesRecursively( $directory ); + } + + unlink( $this->tmpFilepath ); + + parent::tearDown(); + } + + public function testMigration() { + $this->migratorMock->loadParamsAndArgs( null, array( 'oldlayout' => 'name', 'newlayout' => 'sha1' ) ); + + ob_start(); + + $this->migratorMock->execute(); + + ob_end_clean(); + + $sha1 = sha1( $this->text ); + + $expectedOriginalFilepath = $this->tmpPrefix + . '-original/' + . substr( $sha1, 0, 1 ) + . '/' + . substr( $sha1, 1, 1 ) + . '/' + . substr( $sha1, 2, 1 ) + . '/' + . $sha1 ; + + $this->assertEquals( file_get_contents( $expectedOriginalFilepath ), $this->text, 'New sha1 file should be exist and have the right contents' ); + + $expectedPublicFilepath = $this->tmpPrefix . '-public/f/f8/Foo.png'; + + $this->assertEquals( file_get_contents( $expectedPublicFilepath ), $this->text, 'Existing name file should still and have the right contents' ); + } +} diff --git a/tests/phpunit/includes/htmlform/HTMLAutoCompleteSelectFieldTest.php b/tests/phpunit/includes/htmlform/HTMLAutoCompleteSelectFieldTest.php index 2c7f50c9..3b5347cd 100644 --- a/tests/phpunit/includes/htmlform/HTMLAutoCompleteSelectFieldTest.php +++ b/tests/phpunit/includes/htmlform/HTMLAutoCompleteSelectFieldTest.php @@ -6,7 +6,7 @@ */ class HtmlAutoCompleteSelectFieldTest extends MediaWikiTestCase { - var $options = array( + public $options = array( 'Bulgaria' => 'BGR', 'Burkina Faso' => 'BFA', 'Burundi' => 'BDI', diff --git a/tests/phpunit/includes/json/FormatJsonTest.php b/tests/phpunit/includes/json/FormatJsonTest.php index f0ac6acc..8bca3331 100644 --- a/tests/phpunit/includes/json/FormatJsonTest.php +++ b/tests/phpunit/includes/json/FormatJsonTest.php @@ -159,12 +159,12 @@ class FormatJsonTest extends MediaWikiTestCase { $this->assertJson( $json ); $st = FormatJson::parse( $json ); - $this->assertType( 'Status', $st ); + $this->assertInstanceOf( 'Status', $st ); $this->assertTrue( $st->isGood() ); $this->assertEquals( $expected, $st->getValue() ); $st = FormatJson::parse( $json, FormatJson::FORCE_ASSOC ); - $this->assertType( 'Status', $st ); + $this->assertInstanceOf( 'Status', $st ); $this->assertTrue( $st->isGood() ); $this->assertEquals( $value, $st->getValue() ); } @@ -230,7 +230,7 @@ class FormatJsonTest extends MediaWikiTestCase { } $st = FormatJson::parse( $value, FormatJson::TRY_FIXING ); - $this->assertType( 'Status', $st ); + $this->assertInstanceOf( 'Status', $st ); if ( $expected === false ) { $this->assertFalse( $st->isOK(), 'Expected isOK() == false' ); } else { @@ -256,7 +256,7 @@ class FormatJsonTest extends MediaWikiTestCase { */ public function testParseErrors( $value ) { $st = FormatJson::parse( $value ); - $this->assertType( 'Status', $st ); + $this->assertInstanceOf( 'Status', $st ); $this->assertFalse( $st->isOK() ); } @@ -313,7 +313,7 @@ class FormatJsonTest extends MediaWikiTestCase { */ public function testParseStripComments( $json, $expect ) { $st = FormatJson::parse( $json, FormatJson::STRIP_COMMENTS ); - $this->assertType( 'Status', $st ); + $this->assertInstanceOf( 'Status', $st ); $this->assertTrue( $st->isGood() ); $this->assertEquals( $expect, $st->getValue() ); } diff --git a/tests/phpunit/includes/libs/ArrayUtilsTest.php b/tests/phpunit/includes/libs/ArrayUtilsTest.php index b5ea7b72..32b150c7 100644 --- a/tests/phpunit/includes/libs/ArrayUtilsTest.php +++ b/tests/phpunit/includes/libs/ArrayUtilsTest.php @@ -23,11 +23,11 @@ class ArrayUtilsTest extends PHPUnit_Framework_TestCase { } function provideFindLowerBound() { - $self = $this; - $indexValueCallback = function ( $size ) use ( $self ) { - return function ( $val ) use ( $self, $size ) { - $self->assertTrue( $val >= 0 ); - $self->assertTrue( $val < $size ); + $that = $this; + $indexValueCallback = function ( $size ) use ( $that ) { + return function ( $val ) use ( $that, $size ) { + $that->assertTrue( $val >= 0 ); + $that->assertTrue( $val < $size ); return $val; }; }; @@ -212,7 +212,7 @@ class ArrayUtilsTest extends PHPUnit_Framework_TestCase { array(), array( 1 => 1 ), array( 1 ), - array( 1 => 1), + array( 1 => 1 ), ), array( array(), diff --git a/tests/phpunit/includes/libs/CSSMinTest.php b/tests/phpunit/includes/libs/CSSMinTest.php index 6142f967..7841f30f 100644 --- a/tests/phpunit/includes/libs/CSSMinTest.php +++ b/tests/phpunit/includes/libs/CSSMinTest.php @@ -102,12 +102,12 @@ class CSSMinTest extends MediaWikiTestCase { array( 'Without trailing slash', array( 'foo { prop: url(../bar.png); }', false, 'http://example.org/quux', false ), - 'foo { prop: url(http://example.org/quux/../bar.png); }', + 'foo { prop: url(http://example.org/bar.png); }', ), array( 'With trailing slash on remote (bug 27052)', array( 'foo { prop: url(../bar.png); }', false, 'http://example.org/quux/', false ), - 'foo { prop: url(http://example.org/quux/../bar.png); }', + 'foo { prop: url(http://example.org/bar.png); }', ), array( 'Guard against stripping double slashes from query', @@ -133,12 +133,7 @@ class CSSMinTest extends MediaWikiTestCase { $remotePath = 'http://localhost/w/'; $realOutput = CSSMin::remap( $input, $localPath, $remotePath ); - - $this->assertEquals( - $expectedOutput, - preg_replace( '/\d+-\d+-\d+T\d+:\d+:\d+Z/', 'timestamp', $realOutput ), - "CSSMin::remap: $message" - ); + $this->assertEquals( $expectedOutput, $realOutput, "CSSMin::remap: $message" ); } public static function provideIsRemoteUrl() { @@ -197,7 +192,7 @@ class CSSMinTest extends MediaWikiTestCase { array( 'Regular file', 'foo { background: url(red.gif); }', - 'foo { background: url(http://localhost/w/red.gif?timestamp); }', + 'foo { background: url(http://localhost/w/red.gif?34ac6); }', ), array( 'Regular file (missing)', @@ -242,12 +237,12 @@ class CSSMinTest extends MediaWikiTestCase { array( 'Embedded file', 'foo { /* @embed */ background: url(red.gif); }', - "foo { background: url($red); background: url(http://localhost/w/red.gif?timestamp)!ie; }", + "foo { background: url($red); background: url(http://localhost/w/red.gif?34ac6)!ie; }", ), array( 'Embedded file, other comments before the rule', "foo { /* Bar. */ /* @embed */ background: url(red.gif); }", - "foo { /* Bar. */ background: url($red); /* Bar. */ background: url(http://localhost/w/red.gif?timestamp)!ie; }", + "foo { /* Bar. */ background: url($red); /* Bar. */ background: url(http://localhost/w/red.gif?34ac6)!ie; }", ), array( 'Can not re-embed data: URIs', @@ -268,12 +263,12 @@ class CSSMinTest extends MediaWikiTestCase { 'Embedded file (inline @embed)', 'foo { background: /* @embed */ url(red.gif); }', "foo { background: url($red); " - . "background: url(http://localhost/w/red.gif?timestamp)!ie; }", + . "background: url(http://localhost/w/red.gif?34ac6)!ie; }", ), array( 'Can not embed large files', 'foo { /* @embed */ background: url(large.png); }', - "foo { background: url(http://localhost/w/large.png?timestamp); }", + "foo { background: url(http://localhost/w/large.png?e3d1f); }", ), array( 'SVG files are embedded without base64 encoding and unnecessary IE 6 and 7 fallback', @@ -283,55 +278,55 @@ class CSSMinTest extends MediaWikiTestCase { array( 'Two regular files in one rule', 'foo { background: url(red.gif), url(green.gif); }', - 'foo { background: url(http://localhost/w/red.gif?timestamp), ' - . 'url(http://localhost/w/green.gif?timestamp); }', + 'foo { background: url(http://localhost/w/red.gif?34ac6), ' + . 'url(http://localhost/w/green.gif?13651); }', ), array( 'Two embedded files in one rule', 'foo { /* @embed */ background: url(red.gif), url(green.gif); }', "foo { background: url($red), url($green); " - . "background: url(http://localhost/w/red.gif?timestamp), " - . "url(http://localhost/w/green.gif?timestamp)!ie; }", + . "background: url(http://localhost/w/red.gif?34ac6), " + . "url(http://localhost/w/green.gif?13651)!ie; }", ), array( 'Two embedded files in one rule (inline @embed)', 'foo { background: /* @embed */ url(red.gif), /* @embed */ url(green.gif); }', "foo { background: url($red), url($green); " - . "background: url(http://localhost/w/red.gif?timestamp), " - . "url(http://localhost/w/green.gif?timestamp)!ie; }", + . "background: url(http://localhost/w/red.gif?34ac6), " + . "url(http://localhost/w/green.gif?13651)!ie; }", ), array( 'Two embedded files in one rule (inline @embed), one too large', 'foo { background: /* @embed */ url(red.gif), /* @embed */ url(large.png); }', - "foo { background: url($red), url(http://localhost/w/large.png?timestamp); " - . "background: url(http://localhost/w/red.gif?timestamp), " - . "url(http://localhost/w/large.png?timestamp)!ie; }", + "foo { background: url($red), url(http://localhost/w/large.png?e3d1f); " + . "background: url(http://localhost/w/red.gif?34ac6), " + . "url(http://localhost/w/large.png?e3d1f)!ie; }", ), array( 'Practical example with some noise', 'foo { /* @embed */ background: #f9f9f9 url(red.gif) 0 0 no-repeat; }', "foo { background: #f9f9f9 url($red) 0 0 no-repeat; " - . "background: #f9f9f9 url(http://localhost/w/red.gif?timestamp) 0 0 no-repeat!ie; }", + . "background: #f9f9f9 url(http://localhost/w/red.gif?34ac6) 0 0 no-repeat!ie; }", ), array( 'Does not mess with other properties', 'foo { color: red; background: url(red.gif); font-size: small; }', - 'foo { color: red; background: url(http://localhost/w/red.gif?timestamp); font-size: small; }', + 'foo { color: red; background: url(http://localhost/w/red.gif?34ac6); font-size: small; }', ), array( 'Spacing and miscellanea not changed (1)', 'foo { background: url(red.gif); }', - 'foo { background: url(http://localhost/w/red.gif?timestamp); }', + 'foo { background: url(http://localhost/w/red.gif?34ac6); }', ), array( 'Spacing and miscellanea not changed (2)', 'foo {background:url(red.gif)}', - 'foo {background:url(http://localhost/w/red.gif?timestamp)}', + 'foo {background:url(http://localhost/w/red.gif?34ac6)}', ), array( 'Spaces within url() parentheses are ignored', 'foo { background: url( red.gif ); }', - 'foo { background: url(http://localhost/w/red.gif?timestamp); }', + 'foo { background: url(http://localhost/w/red.gif?34ac6); }', ), array( '@import rule to local file (should we remap this?)', @@ -351,22 +346,22 @@ class CSSMinTest extends MediaWikiTestCase { array( 'Simple case with comments after url', 'foo { prop: url(red.gif)/* some {funny;} comment */ ; }', - 'foo { prop: url(http://localhost/w/red.gif?timestamp)/* some {funny;} comment */ ; }', + 'foo { prop: url(http://localhost/w/red.gif?34ac6)/* some {funny;} comment */ ; }', ), array( 'Embedded file with comment before url', 'foo { /* @embed */ background: /* some {funny;} comment */ url(red.gif); }', - "foo { background: /* some {funny;} comment */ url($red); background: /* some {funny;} comment */ url(http://localhost/w/red.gif?timestamp)!ie; }", + "foo { background: /* some {funny;} comment */ url($red); background: /* some {funny;} comment */ url(http://localhost/w/red.gif?34ac6)!ie; }", ), array( 'Embedded file with comments inside and outside the rule', 'foo { /* @embed */ background: url(red.gif) /* some {foo;} comment */; /* some {bar;} comment */ }', - "foo { background: url($red) /* some {foo;} comment */; background: url(http://localhost/w/red.gif?timestamp) /* some {foo;} comment */!ie; /* some {bar;} comment */ }", + "foo { background: url($red) /* some {foo;} comment */; background: url(http://localhost/w/red.gif?34ac6) /* some {foo;} comment */!ie; /* some {bar;} comment */ }", ), array( 'Embedded file with comment outside the rule', 'foo { /* @embed */ background: url(red.gif); /* some {funny;} comment */ }', - "foo { background: url($red); background: url(http://localhost/w/red.gif?timestamp)!ie; /* some {funny;} comment */ }", + "foo { background: url($red); background: url(http://localhost/w/red.gif?34ac6)!ie; /* some {funny;} comment */ }", ), array( 'Rule with two urls, each with comments', diff --git a/tests/phpunit/includes/libs/IEUrlExtensionTest.php b/tests/phpunit/includes/libs/IEUrlExtensionTest.php index e96953ee..57668e50 100644 --- a/tests/phpunit/includes/libs/IEUrlExtensionTest.php +++ b/tests/phpunit/includes/libs/IEUrlExtensionTest.php @@ -170,4 +170,37 @@ class IEUrlExtensionTest extends PHPUnit_Framework_TestCase { 'Two dots' ); } + + /** + * @covers IEUrlExtension::findIE6Extension + */ + public function testScriptQuery() { + $this->assertEquals( + 'php', + IEUrlExtension::findIE6Extension( 'example.php?foo=a&bar=b' ), + 'Script with query' + ); + } + + /** + * @covers IEUrlExtension::findIE6Extension + */ + public function testEscapedScriptQuery() { + $this->assertEquals( + '', + IEUrlExtension::findIE6Extension( 'example%2Ephp?foo=a&bar=b' ), + 'Script with urlencoded dot and query' + ); + } + + /** + * @covers IEUrlExtension::findIE6Extension + */ + public function testEscapedScriptQueryDot() { + $this->assertEquals( + 'y', + IEUrlExtension::findIE6Extension( 'example%2Ephp?foo=a.x&bar=b.y' ), + 'Script with urlencoded dot and query with dot' + ); + } } diff --git a/tests/phpunit/includes/libs/IPSetTest.php b/tests/phpunit/includes/libs/IPSetTest.php deleted file mode 100644 index 5bbacef4..00000000 --- a/tests/phpunit/includes/libs/IPSetTest.php +++ /dev/null @@ -1,252 +0,0 @@ - expected (boolean) result against the config dataset. - */ - public static function provideIPSets() { - return array( - array( - 'old_list_subset', - array( - '208.80.152.162', - '10.64.0.123', - '10.64.0.124', - '10.64.0.125', - '10.64.0.126', - '10.64.0.127', - '10.64.0.128', - '10.64.0.129', - '10.64.32.104', - '10.64.32.105', - '10.64.32.106', - '10.64.32.107', - '91.198.174.45', - '91.198.174.46', - '91.198.174.47', - '91.198.174.57', - '2620:0:862:1:A6BA:DBFF:FE30:CFB3', - '91.198.174.58', - '2620:0:862:1:A6BA:DBFF:FE38:FFDA', - '208.80.152.16', - '208.80.152.17', - '208.80.152.18', - '208.80.152.19', - '91.198.174.102', - '91.198.174.103', - '91.198.174.104', - '91.198.174.105', - '91.198.174.106', - '91.198.174.107', - '91.198.174.81', - '2620:0:862:1:26B6:FDFF:FEF5:B2D4', - '91.198.174.82', - '2620:0:862:1:26B6:FDFF:FEF5:ABB4', - '10.20.0.113', - '2620:0:862:102:26B6:FDFF:FEF5:AD9C', - '10.20.0.114', - '2620:0:862:102:26B6:FDFF:FEF5:7C38', - ), - array( - '0.0.0.0' => false, - '255.255.255.255' => false, - '10.64.0.122' => false, - '10.64.0.123' => true, - '10.64.0.124' => true, - '10.64.0.129' => true, - '10.64.0.130' => false, - '91.198.174.81' => true, - '91.198.174.80' => false, - '0::0' => false, - 'ffff:ffff:ffff:ffff:FFFF:FFFF:FFFF:FFFF' => false, - '2001:db8::1234' => false, - '2620:0:862:1:26b6:fdff:fef5:abb3' => false, - '2620:0:862:1:26b6:fdff:fef5:abb4' => true, - '2620:0:862:1:26b6:fdff:fef5:abb5' => false, - ), - ), - array( - 'new_cidr_set', - array( - '208.80.154.0/26', - '2620:0:861:1::/64', - '208.80.154.128/26', - '2620:0:861:2::/64', - '208.80.154.64/26', - '2620:0:861:3::/64', - '208.80.155.96/27', - '2620:0:861:4::/64', - '10.64.0.0/22', - '2620:0:861:101::/64', - '10.64.16.0/22', - '2620:0:861:102::/64', - '10.64.32.0/22', - '2620:0:861:103::/64', - '10.64.48.0/22', - '2620:0:861:107::/64', - '91.198.174.0/25', - '2620:0:862:1::/64', - '10.20.0.0/24', - '2620:0:862:102::/64', - '10.128.0.0/24', - '2620:0:863:101::/64', - '10.2.4.26', - ), - array( - '0.0.0.0' => false, - '255.255.255.255' => false, - '10.2.4.25' => false, - '10.2.4.26' => true, - '10.2.4.27' => false, - '10.20.0.255' => true, - '10.128.0.0' => true, - '10.64.17.55' => true, - '10.64.20.0' => false, - '10.64.27.207' => false, - '10.64.31.255' => false, - '0::0' => false, - 'ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff' => false, - '2001:DB8::1' => false, - '2620:0:861:106::45' => false, - '2620:0:862:103::' => false, - '2620:0:862:102:10:20:0:113' => true, - ), - ), - array( - 'empty_set', - array(), - array( - '0.0.0.0' => false, - '255.255.255.255' => false, - '10.2.4.25' => false, - '10.2.4.26' => false, - '10.2.4.27' => false, - '10.20.0.255' => false, - '10.128.0.0' => false, - '10.64.17.55' => false, - '10.64.20.0' => false, - '10.64.27.207' => false, - '10.64.31.255' => false, - '0::0' => false, - 'ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff' => false, - '2001:DB8::1' => false, - '2620:0:861:106::45' => false, - '2620:0:862:103::' => false, - '2620:0:862:102:10:20:0:113' => false, - ), - ), - array( - 'edge_cases', - array( - '0.0.0.0', - '255.255.255.255', - '::', - 'ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff', - '10.10.10.10/25', // host bits intentional - ), - array( - '0.0.0.0' => true, - '255.255.255.255' => true, - '10.2.4.25' => false, - '10.2.4.26' => false, - '10.2.4.27' => false, - '10.20.0.255' => false, - '10.128.0.0' => false, - '10.64.17.55' => false, - '10.64.20.0' => false, - '10.64.27.207' => false, - '10.64.31.255' => false, - '0::0' => true, - 'ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff' => true, - '2001:DB8::1' => false, - '2620:0:861:106::45' => false, - '2620:0:862:103::' => false, - '2620:0:862:102:10:20:0:113' => false, - '10.10.9.255' => false, - '10.10.10.0' => true, - '10.10.10.1' => true, - '10.10.10.10' => true, - '10.10.10.126' => true, - '10.10.10.127' => true, - '10.10.10.128' => false, - '10.10.10.177' => false, - '10.10.10.255' => false, - '10.10.11.0' => false, - ), - ), - array( - 'exercise_optimizer', - array( - 'ffff:ffff:ffff:ffff:ffff:ffff:ffff:0/112', - 'ffff:ffff:ffff:ffff:ffff:ffff:fffe:0/112', - 'ffff:ffff:ffff:ffff:ffff:ffff:fffd:0/112', - 'ffff:ffff:ffff:ffff:ffff:ffff:fffc:0/112', - 'ffff:ffff:ffff:ffff:ffff:ffff:fffb:0/112', - 'ffff:ffff:ffff:ffff:ffff:ffff:fffa:0/112', - 'ffff:ffff:ffff:ffff:ffff:ffff:fff9:8000/113', - 'ffff:ffff:ffff:ffff:ffff:ffff:fff9:0/113', - 'ffff:ffff:ffff:ffff:ffff:ffff:fff8:0/112', - 'ffff:ffff:ffff:ffff:ffff:ffff:fff7:0/112', - 'ffff:ffff:ffff:ffff:ffff:ffff:fff6:0/112', - 'ffff:ffff:ffff:ffff:ffff:ffff:fff5:0/112', - 'ffff:ffff:ffff:ffff:ffff:ffff:fff4:0/112', - 'ffff:ffff:ffff:ffff:ffff:ffff:fff3:0/112', - 'ffff:ffff:ffff:ffff:ffff:ffff:fff2:0/112', - 'ffff:ffff:ffff:ffff:ffff:ffff:fff1:0/112', - 'ffff:ffff:ffff:ffff:ffff:ffff:fff0:0/112', - 'ffff:ffff:ffff:ffff:ffff:ffff:ffef:0/112', - 'ffff:ffff:ffff:ffff:ffff:ffff:ffee:0/112', - 'ffff:ffff:ffff:ffff:ffff:ffff:ffec:0/111', - 'ffff:ffff:ffff:ffff:ffff:ffff:ffeb:0/112', - 'ffff:ffff:ffff:ffff:ffff:ffff:ffea:0/112', - 'ffff:ffff:ffff:ffff:ffff:ffff:ffe9:0/112', - 'ffff:ffff:ffff:ffff:ffff:ffff:ffe8:0/112', - 'ffff:ffff:ffff:ffff:ffff:ffff:ffe7:0/112', - 'ffff:ffff:ffff:ffff:ffff:ffff:ffe6:0/112', - 'ffff:ffff:ffff:ffff:ffff:ffff:ffe5:0/112', - 'ffff:ffff:ffff:ffff:ffff:ffff:ffe4:0/112', - 'ffff:ffff:ffff:ffff:ffff:ffff:ffe3:0/112', - 'ffff:ffff:ffff:ffff:ffff:ffff:ffe2:0/112', - 'ffff:ffff:ffff:ffff:ffff:ffff:ffe1:0/112', - 'ffff:ffff:ffff:ffff:ffff:ffff:ffe0:0/110', - 'ffff:ffff:ffff:ffff:ffff:ffff:ffc0:0/107', - 'ffff:ffff:ffff:ffff:ffff:ffff:ffa0:0/107', - ), - array( - '0.0.0.0' => false, - '255.255.255.255' => false, - '::' => false, - 'ffff:ffff:ffff:ffff:ffff:ffff:ff9f:ffff' => false, - 'ffff:ffff:ffff:ffff:ffff:ffff:ffa0:0' => true, - 'ffff:ffff:ffff:ffff:ffff:ffff:ffc0:1234' => true, - 'ffff:ffff:ffff:ffff:ffff:ffff:ffed:ffff' => true, - 'ffff:ffff:ffff:ffff:ffff:ffff:fff4:4444' => true, - 'ffff:ffff:ffff:ffff:ffff:ffff:fff9:8080' => true, - 'ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff' => true, - ), - ), - ); - } - - /** - * Validates IPSet loading and matching code - * - * @covers IPSet - * @dataProvider provideIPSets - */ - public function testIPSet( $desc, array $cfg, array $tests ) { - $ipset = new IPSet( $cfg ); - foreach ( $tests as $ip => $expected ) { - $result = $ipset->match( $ip ); - $this->assertEquals( $expected, $result, "Incorrect match() result for $ip in dataset $desc" ); - } - } -} diff --git a/tests/phpunit/includes/libs/JavaScriptMinifierTest.php b/tests/phpunit/includes/libs/JavaScriptMinifierTest.php index 149a28c1..d23534ed 100644 --- a/tests/phpunit/includes/libs/JavaScriptMinifierTest.php +++ b/tests/phpunit/includes/libs/JavaScriptMinifierTest.php @@ -140,6 +140,13 @@ class JavaScriptMinifierTest extends PHPUnit_Framework_TestCase { array( "5..toString();", "5..toString();" ), array( "5...toString();", false ), array( "5.\n.toString();", '5..toString();' ), + + // Boolean minification (!0 / !1) + array( "var a = { b: true };", "var a={b:!0};" ), + array( "var a = { true: 12 };", "var a={true:12};", false ), + array( "a.true = 12;", "a.true=12;", false ), + array( "a.foo = true;", "a.foo=!0;" ), + array( "a.foo = false;", "a.foo=!1;" ), ); } @@ -147,15 +154,17 @@ class JavaScriptMinifierTest extends PHPUnit_Framework_TestCase { * @dataProvider provideCases * @covers JavaScriptMinifier::minify */ - public function testJavaScriptMinifierOutput( $code, $expectedOutput ) { + public function testJavaScriptMinifierOutput( $code, $expectedOutput, $expectedValid = true ) { $minified = JavaScriptMinifier::minify( $code ); // JSMin+'s parser will throw an exception if output is not valid JS. // suppression of warnings needed for stupid crap - wfSuppressWarnings(); - $parser = new JSParser(); - wfRestoreWarnings(); - $parser->parse( $minified, 'minify-test.js', 1 ); + if ( $expectedValid ) { + MediaWiki\suppressWarnings(); + $parser = new JSParser(); + MediaWiki\restoreWarnings(); + $parser->parse( $minified, 'minify-test.js', 1 ); + } $this->assertEquals( $expectedOutput, diff --git a/tests/phpunit/includes/libs/ObjectFactoryTest.php b/tests/phpunit/includes/libs/ObjectFactoryTest.php index 92207325..aea037e0 100644 --- a/tests/phpunit/includes/libs/ObjectFactoryTest.php +++ b/tests/phpunit/includes/libs/ObjectFactoryTest.php @@ -26,11 +26,20 @@ class ObjectFactoryTest extends PHPUnit_Framework_TestCase { public function testClosureExpansionDisabled() { $obj = ObjectFactory::getObjectFromSpec( array( 'class' => 'ObjectFactoryTest_Fixture', - 'args' => array( function (){ return 'unwrapped'; }, ), + 'args' => array( function() { + return 'unwrapped'; + }, ), + 'calls' => array( + 'setter' => array( function() { + return 'unwrapped'; + }, ), + ), 'closure_expansion' => false, ) ); $this->assertInstanceOf( 'Closure', $obj->args[0] ); $this->assertSame( 'unwrapped', $obj->args[0]() ); + $this->assertInstanceOf( 'Closure', $obj->setterArgs[0] ); + $this->assertSame( 'unwrapped', $obj->setterArgs[0]() ); } /** @@ -39,22 +48,46 @@ class ObjectFactoryTest extends PHPUnit_Framework_TestCase { public function testClosureExpansionEnabled() { $obj = ObjectFactory::getObjectFromSpec( array( 'class' => 'ObjectFactoryTest_Fixture', - 'args' => array( function (){ return 'unwrapped'; }, ), + 'args' => array( function() { + return 'unwrapped'; + }, ), + 'calls' => array( + 'setter' => array( function() { + return 'unwrapped'; + }, ), + ), 'closure_expansion' => true, ) ); $this->assertInternalType( 'string', $obj->args[0] ); $this->assertSame( 'unwrapped', $obj->args[0] ); + $this->assertInternalType( 'string', $obj->setterArgs[0] ); + $this->assertSame( 'unwrapped', $obj->setterArgs[0] ); $obj = ObjectFactory::getObjectFromSpec( array( 'class' => 'ObjectFactoryTest_Fixture', - 'args' => array( function (){ return 'unwrapped'; }, ), + 'args' => array( function() { + return 'unwrapped'; + }, ), + 'calls' => array( + 'setter' => array( function() { + return 'unwrapped'; + }, ), + ), ) ); $this->assertInternalType( 'string', $obj->args[0] ); $this->assertSame( 'unwrapped', $obj->args[0] ); + $this->assertInternalType( 'string', $obj->setterArgs[0] ); + $this->assertSame( 'unwrapped', $obj->setterArgs[0] ); } } class ObjectFactoryTest_Fixture { public $args; - public function __construct( /*...*/ ) { $this->args = func_get_args(); } + public $setterArgs; + public function __construct( /*...*/ ) { + $this->args = func_get_args(); + } + public function setter( /*...*/ ) { + $this->setterArgs = func_get_args(); + } } diff --git a/tests/phpunit/includes/libs/ProcessCacheLRUTest.php b/tests/phpunit/includes/libs/ProcessCacheLRUTest.php index 43001979..cec662a9 100644 --- a/tests/phpunit/includes/libs/ProcessCacheLRUTest.php +++ b/tests/phpunit/includes/libs/ProcessCacheLRUTest.php @@ -70,7 +70,7 @@ class ProcessCacheLRUTest extends PHPUnit_Framework_TestCase { /** * @dataProvider provideInvalidConstructorArg - * @expectedException UnexpectedValueException + * @expectedException Wikimedia\Assert\ParameterAssertionException * @covers ProcessCacheLRU::__construct */ public function testConstructorGivenInvalidValue( $maxSize ) { diff --git a/tests/phpunit/includes/libs/SamplingStatsdClientTest.php b/tests/phpunit/includes/libs/SamplingStatsdClientTest.php new file mode 100644 index 00000000..be6732d5 --- /dev/null +++ b/tests/phpunit/includes/libs/SamplingStatsdClientTest.php @@ -0,0 +1,43 @@ +getMock( 'Liuggio\StatsdClient\Sender\SenderInterface' ); + $sender->expects( $this->any() )->method( 'open' )->will( $this->returnValue( true ) ); + if ( $expectWrite ) { + $sender->expects( $this->once() )->method( 'write' ) + ->with( $this->anything(), $this->equalTo( $data ) ); + } else { + $sender->expects( $this->never() )->method( 'write' ); + } + mt_srand( $seed ); + $client = new SamplingStatsdClient( $sender ); + $client->send( $data, $sampleRate ); + } + + public function samplingDataProvider() { + $unsampled = new StatsdData(); + $unsampled->setKey( 'foo' ); + $unsampled->setValue( 1 ); + + $sampled = new StatsdData(); + $sampled->setKey( 'foo' ); + $sampled->setValue( 1 ); + $sampled->setSampleRate( '0.1' ); + + return array( + // $data, $sampleRate, $seed, $expectWrite + array( $unsampled, 1, 0 /*0.44*/, $unsampled ), + array( $sampled, 1, 0 /*0.44*/, null ), + array( $sampled, 1, 4 /*0.03*/, $sampled ), + array( $unsampled, 0.1, 4 /*0.03*/, $sampled ), + array( $sampled, 0.5, 0 /*0.44*/, null ), + array( $sampled, 0.5, 4 /*0.03*/, $sampled ), + ); + } +} diff --git a/tests/phpunit/includes/libs/XhprofTest.php b/tests/phpunit/includes/libs/XhprofTest.php index 2440fc08..77b188cf 100644 --- a/tests/phpunit/includes/libs/XhprofTest.php +++ b/tests/phpunit/includes/libs/XhprofTest.php @@ -255,43 +255,43 @@ class XhprofTest extends PHPUnit_Framework_TestCase { */ protected function getXhprofFixture( array $opts = array() ) { $xhprof = new Xhprof( $opts ); - $xhprof->loadRawData( array ( - 'foo==>bar' => array ( + $xhprof->loadRawData( array( + 'foo==>bar' => array( 'ct' => 2, 'wt' => 57, 'cpu' => 92, 'mu' => 1896, 'pmu' => 0, ), - 'foo==>strlen' => array ( + 'foo==>strlen' => array( 'ct' => 2, 'wt' => 21, 'cpu' => 141, 'mu' => 752, 'pmu' => 0, ), - 'bar==>bar@1' => array ( + 'bar==>bar@1' => array( 'ct' => 1, 'wt' => 18, 'cpu' => 19, 'mu' => 752, 'pmu' => 0, ), - 'main()==>foo' => array ( + 'main()==>foo' => array( 'ct' => 1, 'wt' => 304, 'cpu' => 307, 'mu' => 4008, 'pmu' => 0, ), - 'main()==>xhprof_disable' => array ( + 'main()==>xhprof_disable' => array( 'ct' => 1, 'wt' => 8, 'cpu' => 10, 'mu' => 768, 'pmu' => 392, ), - 'main()' => array ( + 'main()' => array( 'ct' => 1, 'wt' => 353, 'cpu' => 351, @@ -311,7 +311,7 @@ class XhprofTest extends PHPUnit_Framework_TestCase { */ protected function assertArrayStructure( $struct, $actual, $label = null ) { $this->assertInternalType( 'array', $actual, $label ); - $this->assertCount( count($struct), $actual, $label ); + $this->assertCount( count( $struct ), $actual, $label ); foreach ( $struct as $key => $type ) { $this->assertArrayHasKey( $key, $actual ); $this->assertInternalType( $type, $actual[$key] ); diff --git a/tests/phpunit/includes/libs/composer/ComposerLockTest.php b/tests/phpunit/includes/libs/composer/ComposerLockTest.php index b5fd5f6e..cac3b101 100644 --- a/tests/phpunit/includes/libs/composer/ComposerLockTest.php +++ b/tests/phpunit/includes/libs/composer/ComposerLockTest.php @@ -27,34 +27,95 @@ class ComposerLockTest extends MediaWikiTestCase { 'wikimedia/cdb' => array( 'version' => '1.0.1', 'type' => 'library', + 'licenses' => array( 'GPL-2.0' ), + 'authors' => array( + array( + 'name' => 'Tim Starling', + 'email' => 'tstarling@wikimedia.org', + ), + array( + 'name' => 'Chad Horohoe', + 'email' => 'chad@wikimedia.org', + ), + ), + 'description' => 'Constant Database (CDB) wrapper library for PHP. Provides pure-PHP fallback when dba_* functions are absent.', ), 'cssjanus/cssjanus' => array( 'version' => '1.1.1', 'type' => 'library', + 'licenses' => array( 'Apache-2.0' ), + 'authors' => array(), + 'description' => 'Convert CSS stylesheets between left-to-right and right-to-left.', ), 'leafo/lessphp' => array( 'version' => '0.5.0', 'type' => 'library', + 'licenses' => array( 'MIT', 'GPL-3.0' ), + 'authors' => array( + array( + 'name' => 'Leaf Corcoran', + 'email' => 'leafot@gmail.com', + 'homepage' => 'http://leafo.net', + ), + ), + 'description' => 'lessphp is a compiler for LESS written in PHP.', ), 'psr/log' => array( 'version' => '1.0.0', 'type' => 'library', + 'licenses' => array( 'MIT' ), + 'authors' => array( + array( + 'name' => 'PHP-FIG', + 'homepage' => 'http://www.php-fig.org/', + ), + ), + 'description' => 'Common interface for logging libraries', ), 'oojs/oojs-ui' => array( 'version' => '0.6.0', 'type' => 'library', + 'licenses' => array( 'MIT' ), + 'authors' => array(), + 'description' => '', ), 'composer/installers' => array( 'version' => '1.0.19', 'type' => 'composer-installer', + 'licenses' => array( 'MIT' ), + 'authors' => array( + array( + 'name' => 'Kyle Robinson Young', + 'email' => 'kyle@dontkry.com', + 'homepage' => 'https://github.com/shama', + ), + ), + 'description' => 'A multi-framework Composer library installer', ), 'mediawiki/translate' => array( 'version' => '2014.12', 'type' => 'mediawiki-extension', + 'licenses' => array( 'GPL-2.0+' ), + 'authors' => array( + array( + 'name' => 'Niklas Laxström', + 'email' => 'niklas.laxstrom@gmail.com', + 'role' => 'Lead nitpicker', + ), + array( + 'name' => 'Siebrand Mazeland', + 'email' => 's.mazeland@xs4all.nl', + 'role' => 'Developer', + ), + ), + 'description' => 'The only standard solution to translate any kind of text with an avant-garde web interface within MediaWiki, including your documentation and software', ), 'mediawiki/universal-language-selector' => array( 'version' => '2014.12', 'type' => 'mediawiki-extension', + 'licenses' => array( 'GPL-2.0+', 'MIT' ), + 'authors' => array(), + 'description' => 'The primary aim is to allow users to select a language and configure its support in an easy way. Main features are language selection, input methods and web fonts.', ), ), $lock->getInstalledDependencies(), false, true ); } diff --git a/tests/phpunit/includes/logging/BlockLogFormatterTest.php b/tests/phpunit/includes/logging/BlockLogFormatterTest.php new file mode 100644 index 00000000..c7dc641d --- /dev/null +++ b/tests/phpunit/includes/logging/BlockLogFormatterTest.php @@ -0,0 +1,372 @@ + 'block', + 'action' => 'block', + 'comment' => 'Block comment', + 'user' => 0, + 'user_text' => 'Sysop', + 'namespace' => NS_USER, + 'title' => 'Logtestuser', + 'params' => array( + '5::duration' => 'infinite', + '6::flags' => 'anononly', + ), + ), + array( + 'text' => 'Sysop blocked Logtestuser with an expiry time of indefinite (anonymous users only)', + 'api' => array( + 'duration' => 'infinite', + 'flags' => array( 'anononly' ), + ), + ), + ), + + // Old legacy log + array( + array( + 'type' => 'block', + 'action' => 'block', + 'comment' => 'Block comment', + 'user' => 0, + 'user_text' => 'Sysop', + 'namespace' => NS_USER, + 'title' => 'Logtestuser', + 'params' => array( + 'infinite', + 'anononly', + ), + ), + array( + 'legacy' => true, + 'text' => 'Sysop blocked Logtestuser with an expiry time of indefinite (anonymous users only)', + 'api' => array( + 'duration' => 'infinite', + 'flags' => array( 'anononly' ), + ), + ), + ), + + // Old legacy log without flag + array( + array( + 'type' => 'block', + 'action' => 'block', + 'comment' => 'Block comment', + 'user' => 0, + 'user_text' => 'Sysop', + 'namespace' => NS_USER, + 'title' => 'Logtestuser', + 'params' => array( + 'infinite', + ), + ), + array( + 'legacy' => true, + 'text' => 'Sysop blocked Logtestuser with an expiry time of indefinite', + 'api' => array( + 'duration' => 'infinite', + 'flags' => array(), + ), + ), + ), + + // Very old legacy log without duration + array( + array( + 'type' => 'block', + 'action' => 'block', + 'comment' => 'Block comment', + 'user' => 0, + 'user_text' => 'Sysop', + 'namespace' => NS_USER, + 'title' => 'Logtestuser', + 'params' => array(), + ), + array( + 'legacy' => true, + 'text' => 'Sysop blocked Logtestuser with an expiry time of indefinite', + 'api' => array( + 'duration' => 'infinite', + 'flags' => array(), + ), + ), + ), + ); + } + + /** + * @dataProvider provideBlockLogDatabaseRows + */ + public function testBlockLogDatabaseRows( $row, $extra ) { + $this->doTestLogFormatter( $row, $extra ); + } + + /** + * Provide different rows from the logging table to test + * for backward compatibility. + * Do not change the existing data, just add a new database row + */ + public static function provideReblockLogDatabaseRows() { + return array( + // Current log format + array( + array( + 'type' => 'block', + 'action' => 'reblock', + 'comment' => 'Block comment', + 'user' => 0, + 'user_text' => 'Sysop', + 'namespace' => NS_USER, + 'title' => 'Logtestuser', + 'params' => array( + '5::duration' => 'infinite', + '6::flags' => 'anononly', + ), + ), + array( + 'text' => 'Sysop changed block settings for Logtestuser with an expiry time of' + . ' indefinite (anonymous users only)', + 'api' => array( + 'duration' => 'infinite', + 'flags' => array( 'anononly' ), + ), + ), + ), + + // Old log + array( + array( + 'type' => 'block', + 'action' => 'reblock', + 'comment' => 'Block comment', + 'user' => 0, + 'user_text' => 'Sysop', + 'namespace' => NS_USER, + 'title' => 'Logtestuser', + 'params' => array( + 'infinite', + 'anononly', + ), + ), + array( + 'legacy' => true, + 'text' => 'Sysop changed block settings for Logtestuser with an expiry time of' + . ' indefinite (anonymous users only)', + 'api' => array( + 'duration' => 'infinite', + 'flags' => array( 'anononly' ), + ), + ), + ), + + // Older log without flag + array( + array( + 'type' => 'block', + 'action' => 'reblock', + 'comment' => 'Block comment', + 'user' => 0, + 'user_text' => 'Sysop', + 'namespace' => NS_USER, + 'title' => 'Logtestuser', + 'params' => array( + 'infinite', + ) + ), + array( + 'legacy' => true, + 'text' => 'Sysop changed block settings for Logtestuser with an expiry time of indefinite', + 'api' => array( + 'duration' => 'infinite', + 'flags' => array(), + ), + ), + ), + ); + } + + /** + * @dataProvider provideReblockLogDatabaseRows + */ + public function testReblockLogDatabaseRows( $row, $extra ) { + $this->doTestLogFormatter( $row, $extra ); + } + + /** + * Provide different rows from the logging table to test + * for backward compatibility. + * Do not change the existing data, just add a new database row + */ + public static function provideUnblockLogDatabaseRows() { + return array( + // Current log format + array( + array( + 'type' => 'block', + 'action' => 'unblock', + 'comment' => 'Block comment', + 'user' => 0, + 'user_text' => 'Sysop', + 'namespace' => NS_USER, + 'title' => 'Logtestuser', + 'params' => array(), + ), + array( + 'text' => 'Sysop unblocked Logtestuser', + 'api' => array(), + ), + ), + ); + } + + /** + * @dataProvider provideUnblockLogDatabaseRows + */ + public function testUnblockLogDatabaseRows( $row, $extra ) { + $this->doTestLogFormatter( $row, $extra ); + } + + /** + * Provide different rows from the logging table to test + * for backward compatibility. + * Do not change the existing data, just add a new database row + */ + public static function provideSuppressBlockLogDatabaseRows() { + return array( + // Current log format + array( + array( + 'type' => 'suppress', + 'action' => 'block', + 'comment' => 'Block comment', + 'user' => 0, + 'user_text' => 'Sysop', + 'namespace' => NS_USER, + 'title' => 'Logtestuser', + 'params' => array( + '5::duration' => 'infinite', + '6::flags' => 'anononly', + ), + ), + array( + 'text' => 'Sysop blocked Logtestuser with an expiry time of indefinite (anonymous users only)', + 'api' => array( + 'duration' => 'infinite', + 'flags' => array( 'anononly' ), + ), + ), + ), + + // legacy log + array( + array( + 'type' => 'suppress', + 'action' => 'block', + 'comment' => 'Block comment', + 'user' => 0, + 'user_text' => 'Sysop', + 'namespace' => NS_USER, + 'title' => 'Logtestuser', + 'params' => array( + 'infinite', + 'anononly', + ), + ), + array( + 'legacy' => true, + 'text' => 'Sysop blocked Logtestuser with an expiry time of indefinite (anonymous users only)', + 'api' => array( + 'duration' => 'infinite', + 'flags' => array( 'anononly' ), + ), + ), + ), + ); + } + + /** + * @dataProvider provideSuppressBlockLogDatabaseRows + */ + public function testSuppressBlockLogDatabaseRows( $row, $extra ) { + $this->doTestLogFormatter( $row, $extra ); + } + + /** + * Provide different rows from the logging table to test + * for backward compatibility. + * Do not change the existing data, just add a new database row + */ + public static function provideSuppressReblockLogDatabaseRows() { + return array( + // Current log format + array( + array( + 'type' => 'suppress', + 'action' => 'reblock', + 'comment' => 'Block comment', + 'user' => 0, + 'user_text' => 'Sysop', + 'namespace' => NS_USER, + 'title' => 'Logtestuser', + 'params' => array( + '5::duration' => 'infinite', + '6::flags' => 'anononly', + ), + ), + array( + 'text' => 'Sysop changed block settings for Logtestuser with an expiry time of' + . ' indefinite (anonymous users only)', + 'api' => array( + 'duration' => 'infinite', + 'flags' => array( 'anononly' ), + ), + ), + ), + + // Legacy format + array( + array( + 'type' => 'suppress', + 'action' => 'reblock', + 'comment' => 'Block comment', + 'user' => 0, + 'user_text' => 'Sysop', + 'namespace' => NS_USER, + 'title' => 'Logtestuser', + 'params' => array( + 'infinite', + 'anononly', + ), + ), + array( + 'legacy' => true, + 'text' => 'Sysop changed block settings for Logtestuser with an expiry time of' + . ' indefinite (anonymous users only)', + 'api' => array( + 'duration' => 'infinite', + 'flags' => array( 'anononly' ), + ), + ), + ), + ); + } + + /** + * @dataProvider provideSuppressReblockLogDatabaseRows + */ + public function testSuppressReblockLogDatabaseRows( $row, $extra ) { + $this->doTestLogFormatter( $row, $extra ); + } +} diff --git a/tests/phpunit/includes/logging/DeleteLogFormatterTest.php b/tests/phpunit/includes/logging/DeleteLogFormatterTest.php new file mode 100644 index 00000000..28e7efaf --- /dev/null +++ b/tests/phpunit/includes/logging/DeleteLogFormatterTest.php @@ -0,0 +1,527 @@ + 'delete', + 'action' => 'delete', + 'comment' => 'delete comment', + 'namespace' => NS_MAIN, + 'title' => 'Page', + 'params' => array(), + ), + array( + 'text' => 'User deleted page Page', + 'api' => array(), + ), + ), + + // Legacy format + array( + array( + 'type' => 'delete', + 'action' => 'delete', + 'comment' => 'delete comment', + 'namespace' => NS_MAIN, + 'title' => 'Page', + 'params' => array(), + ), + array( + 'legacy' => true, + 'text' => 'User deleted page Page', + 'api' => array(), + ), + ), + ); + } + + /** + * @dataProvider provideDeleteLogDatabaseRows + */ + public function testDeleteLogDatabaseRows( $row, $extra ) { + $this->doTestLogFormatter( $row, $extra ); + } + + /** + * Provide different rows from the logging table to test + * for backward compatibility. + * Do not change the existing data, just add a new database row + */ + public static function provideRestoreLogDatabaseRows() { + return array( + // Current format + array( + array( + 'type' => 'delete', + 'action' => 'restore', + 'comment' => 'delete comment', + 'namespace' => NS_MAIN, + 'title' => 'Page', + 'params' => array(), + ), + array( + 'text' => 'User restored page Page', + 'api' => array(), + ), + ), + + // Legacy format + array( + array( + 'type' => 'delete', + 'action' => 'restore', + 'comment' => 'delete comment', + 'namespace' => NS_MAIN, + 'title' => 'Page', + 'params' => array(), + ), + array( + 'legacy' => true, + 'text' => 'User restored page Page', + 'api' => array(), + ), + ), + ); + } + + /** + * @dataProvider provideRestoreLogDatabaseRows + */ + public function testRestoreLogDatabaseRows( $row, $extra ) { + $this->doTestLogFormatter( $row, $extra ); + } + + /** + * Provide different rows from the logging table to test + * for backward compatibility. + * Do not change the existing data, just add a new database row + */ + public static function provideRevisionLogDatabaseRows() { + return array( + // Current format + array( + array( + 'type' => 'delete', + 'action' => 'revision', + 'comment' => 'delete comment', + 'namespace' => NS_MAIN, + 'title' => 'Page', + 'params' => array( + '4::type' => 'archive', + '5::ids' => array( '1', '3', '4' ), + '6::ofield' => '1', + '7::nfield' => '2', + ), + ), + array( + 'text' => 'User changed visibility of 3 revisions on page Page: edit summary ' + . 'hidden and content unhidden', + 'api' => array( + 'type' => 'archive', + 'ids' => array( '1', '3', '4' ), + 'old' => array( + 'bitmask' => 1, + 'content' => true, + 'comment' => false, + 'user' => false, + 'restricted' => false, + ), + 'new' => array( + 'bitmask' => 2, + 'content' => false, + 'comment' => true, + 'user' => false, + 'restricted' => false, + ), + ), + ), + ), + + // Legacy format + array( + array( + 'type' => 'delete', + 'action' => 'revision', + 'comment' => 'delete comment', + 'namespace' => NS_MAIN, + 'title' => 'Page', + 'params' => array( + 'archive', + '1,3,4', + 'ofield=1', + 'nfield=2', + ), + ), + array( + 'legacy' => true, + 'text' => 'User changed visibility of 3 revisions on page Page: edit summary ' + . 'hidden and content unhidden', + 'api' => array( + 'type' => 'archive', + 'ids' => array( '1', '3', '4' ), + 'old' => array( + 'bitmask' => 1, + 'content' => true, + 'comment' => false, + 'user' => false, + 'restricted' => false, + ), + 'new' => array( + 'bitmask' => 2, + 'content' => false, + 'comment' => true, + 'user' => false, + 'restricted' => false, + ), + ), + ), + ), + ); + } + + /** + * @dataProvider provideRevisionLogDatabaseRows + */ + public function testRevisionLogDatabaseRows( $row, $extra ) { + $this->doTestLogFormatter( $row, $extra ); + } + + /** + * Provide different rows from the logging table to test + * for backward compatibility. + * Do not change the existing data, just add a new database row + */ + public static function provideEventLogDatabaseRows() { + return array( + // Current format + array( + array( + 'type' => 'delete', + 'action' => 'event', + 'comment' => 'delete comment', + 'namespace' => NS_MAIN, + 'title' => 'Page', + 'params' => array( + '4::ids' => array( '1', '3', '4' ), + '5::ofield' => '1', + '6::nfield' => '2', + ), + ), + array( + 'text' => 'User changed visibility of 3 log events on Page: edit summary hidden ' + . 'and content unhidden', + 'api' => array( + 'type' => 'logging', + 'ids' => array( '1', '3', '4' ), + 'old' => array( + 'bitmask' => 1, + 'content' => true, + 'comment' => false, + 'user' => false, + 'restricted' => false, + ), + 'new' => array( + 'bitmask' => 2, + 'content' => false, + 'comment' => true, + 'user' => false, + 'restricted' => false, + ), + ), + ), + ), + + // Legacy format + array( + array( + 'type' => 'delete', + 'action' => 'event', + 'comment' => 'delete comment', + 'namespace' => NS_MAIN, + 'title' => 'Page', + 'params' => array( + '1,3,4', + 'ofield=1', + 'nfield=2', + ), + ), + array( + 'legacy' => true, + 'text' => 'User changed visibility of 3 log events on Page: edit summary hidden ' + . 'and content unhidden', + 'api' => array( + 'type' => 'logging', + 'ids' => array( '1', '3', '4' ), + 'old' => array( + 'bitmask' => 1, + 'content' => true, + 'comment' => false, + 'user' => false, + 'restricted' => false, + ), + 'new' => array( + 'bitmask' => 2, + 'content' => false, + 'comment' => true, + 'user' => false, + 'restricted' => false, + ), + ), + ), + ), + ); + } + + /** + * @dataProvider provideEventLogDatabaseRows + */ + public function testEventLogDatabaseRows( $row, $extra ) { + $this->doTestLogFormatter( $row, $extra ); + } + + /** + * Provide different rows from the logging table to test + * for backward compatibility. + * Do not change the existing data, just add a new database row + */ + public static function provideSuppressRevisionLogDatabaseRows() { + return array( + // Current format + array( + array( + 'type' => 'suppress', + 'action' => 'revision', + 'comment' => 'Suppress comment', + 'namespace' => NS_MAIN, + 'title' => 'Page', + 'params' => array( + '4::type' => 'archive', + '5::ids' => array( '1', '3', '4' ), + '6::ofield' => '1', + '7::nfield' => '10', + ), + ), + array( + 'text' => 'User secretly changed visibility of 3 revisions on page Page: edit ' + . 'summary hidden, content unhidden and applied restrictions to administrators', + 'api' => array( + 'type' => 'archive', + 'ids' => array( '1', '3', '4' ), + 'old' => array( + 'bitmask' => 1, + 'content' => true, + 'comment' => false, + 'user' => false, + 'restricted' => false, + ), + 'new' => array( + 'bitmask' => 10, + 'content' => false, + 'comment' => true, + 'user' => false, + 'restricted' => true, + ), + ), + ), + ), + + // Legacy format + array( + array( + 'type' => 'suppress', + 'action' => 'revision', + 'comment' => 'Suppress comment', + 'namespace' => NS_MAIN, + 'title' => 'Page', + 'params' => array( + 'archive', + '1,3,4', + 'ofield=1', + 'nfield=10', + ), + ), + array( + 'legacy' => true, + 'text' => 'User secretly changed visibility of 3 revisions on page Page: edit ' + . 'summary hidden, content unhidden and applied restrictions to administrators', + 'api' => array( + 'type' => 'archive', + 'ids' => array( '1', '3', '4' ), + 'old' => array( + 'bitmask' => 1, + 'content' => true, + 'comment' => false, + 'user' => false, + 'restricted' => false, + ), + 'new' => array( + 'bitmask' => 10, + 'content' => false, + 'comment' => true, + 'user' => false, + 'restricted' => true, + ), + ), + ), + ), + ); + } + + /** + * @dataProvider provideSuppressRevisionLogDatabaseRows + */ + public function testSuppressRevisionLogDatabaseRows( $row, $extra ) { + $this->doTestLogFormatter( $row, $extra ); + } + + /** + * Provide different rows from the logging table to test + * for backward compatibility. + * Do not change the existing data, just add a new database row + */ + public static function provideSuppressEventLogDatabaseRows() { + return array( + // Current format + array( + array( + 'type' => 'suppress', + 'action' => 'event', + 'comment' => 'Suppress comment', + 'namespace' => NS_MAIN, + 'title' => 'Page', + 'params' => array( + '4::ids' => array( '1', '3', '4' ), + '5::ofield' => '1', + '6::nfield' => '10', + ), + ), + array( + 'text' => 'User secretly changed visibility of 3 log events on Page: edit ' + . 'summary hidden, content unhidden and applied restrictions to administrators', + 'api' => array( + 'type' => 'logging', + 'ids' => array( '1', '3', '4' ), + 'old' => array( + 'bitmask' => 1, + 'content' => true, + 'comment' => false, + 'user' => false, + 'restricted' => false, + ), + 'new' => array( + 'bitmask' => 10, + 'content' => false, + 'comment' => true, + 'user' => false, + 'restricted' => true, + ), + ), + ), + ), + + // Legacy format + array( + array( + 'type' => 'suppress', + 'action' => 'event', + 'comment' => 'Suppress comment', + 'namespace' => NS_MAIN, + 'title' => 'Page', + 'params' => array( + '1,3,4', + 'ofield=1', + 'nfield=10', + ), + ), + array( + 'legacy' => true, + 'text' => 'User secretly changed visibility of 3 log events on Page: edit ' + . 'summary hidden, content unhidden and applied restrictions to administrators', + 'api' => array( + 'type' => 'logging', + 'ids' => array( '1', '3', '4' ), + 'old' => array( + 'bitmask' => 1, + 'content' => true, + 'comment' => false, + 'user' => false, + 'restricted' => false, + ), + 'new' => array( + 'bitmask' => 10, + 'content' => false, + 'comment' => true, + 'user' => false, + 'restricted' => true, + ), + ), + ), + ), + ); + } + + /** + * @dataProvider provideSuppressEventLogDatabaseRows + */ + public function testSuppressEventLogDatabaseRows( $row, $extra ) { + $this->doTestLogFormatter( $row, $extra ); + } + + /** + * Provide different rows from the logging table to test + * for backward compatibility. + * Do not change the existing data, just add a new database row + */ + public static function provideSuppressDeleteLogDatabaseRows() { + return array( + // Current format + array( + array( + 'type' => 'suppress', + 'action' => 'delete', + 'comment' => 'delete comment', + 'namespace' => NS_MAIN, + 'title' => 'Page', + 'params' => array(), + ), + array( + 'text' => 'User suppressed page Page', + 'api' => array(), + ), + ), + + // Legacy format + array( + array( + 'type' => 'suppress', + 'action' => 'delete', + 'comment' => 'delete comment', + 'namespace' => NS_MAIN, + 'title' => 'Page', + 'params' => array(), + ), + array( + 'legacy' => true, + 'text' => 'User suppressed page Page', + 'api' => array(), + ), + ), + ); + } + + /** + * @dataProvider provideSuppressDeleteLogDatabaseRows + */ + public function testSuppressDeleteLogDatabaseRows( $row, $extra ) { + $this->doTestLogFormatter( $row, $extra ); + } +} diff --git a/tests/phpunit/includes/logging/LogFormatterTest.php b/tests/phpunit/includes/logging/LogFormatterTest.php index 515990e6..844c9afb 100644 --- a/tests/phpunit/includes/logging/LogFormatterTest.php +++ b/tests/phpunit/includes/logging/LogFormatterTest.php @@ -1,4 +1,5 @@ recache( $wgLang->getCode() ); $this->user = User::newFromName( 'Testuser' ); - $this->title = Title::newMainPage(); + $this->title = Title::newFromText( 'SomeTitle' ); + $this->target = Title::newFromText( 'TestTarget' ); $this->context = new RequestContext(); $this->context->setUser( $this->user ); $this->context->setTitle( $this->title ); $this->context->setLanguage( $wgLang ); + + $this->user_comment = ''; } protected function tearDown() { @@ -292,4 +306,309 @@ class LogFormatterTest extends MediaWikiLangTestCase { array( '4:user-link:key', 'foo', array( 'key' => 'Foo' ) ), ); } + + /** + * @covers LogFormatter::getIRCActionComment + * @covers LogFormatter::getIRCActionText + */ + public function testIrcMsgForLogTypeBlock() { + $sep = $this->context->msg( 'colon-separator' )->text(); + + # block/block + $this->assertIRCComment( + $this->context->msg( 'blocklogentry', 'SomeTitle', 'duration', '(flags)' )->plain() + . $sep . $this->user_comment, + 'block', 'block', + array( + '5::duration' => 'duration', + '6::flags' => 'flags', + ), + $this->user_comment + ); + # block/block - legacy + $this->assertIRCComment( + $this->context->msg( 'blocklogentry', 'SomeTitle', 'duration', '(flags)' )->plain() + . $sep . $this->user_comment, + 'block', 'block', + array( + 'duration', + 'flags', + ), + $this->user_comment, + '', + true + ); + # block/unblock + $this->assertIRCComment( + $this->context->msg( 'unblocklogentry', 'SomeTitle' )->plain() . $sep . $this->user_comment, + 'block', 'unblock', + array(), + $this->user_comment + ); + # block/reblock + $this->assertIRCComment( + $this->context->msg( 'reblock-logentry', 'SomeTitle', 'duration', '(flags)' )->plain() + . $sep . $this->user_comment, + 'block', 'reblock', + array( + '5::duration' => 'duration', + '6::flags' => 'flags', + ), + $this->user_comment + ); + } + + /** + * @covers LogFormatter::getIRCActionComment + * @covers LogFormatter::getIRCActionText + */ + public function testIrcMsgForLogTypeDelete() { + $sep = $this->context->msg( 'colon-separator' )->text(); + + # delete/delete + $this->assertIRCComment( + $this->context->msg( 'deletedarticle', 'SomeTitle' )->plain() . $sep . $this->user_comment, + 'delete', 'delete', + array(), + $this->user_comment + ); + + # delete/restore + $this->assertIRCComment( + $this->context->msg( 'undeletedarticle', 'SomeTitle' )->plain() . $sep . $this->user_comment, + 'delete', 'restore', + array(), + $this->user_comment + ); + } + + /** + * @covers LogFormatter::getIRCActionComment + * @covers LogFormatter::getIRCActionText + */ + public function testIrcMsgForLogTypeNewusers() { + $this->assertIRCComment( + 'New user account', + 'newusers', 'newusers', + array() + ); + $this->assertIRCComment( + 'New user account', + 'newusers', 'create', + array() + ); + $this->assertIRCComment( + 'created new account SomeTitle', + 'newusers', 'create2', + array() + ); + $this->assertIRCComment( + 'Account created automatically', + 'newusers', 'autocreate', + array() + ); + } + + /** + * @covers LogFormatter::getIRCActionComment + * @covers LogFormatter::getIRCActionText + */ + public function testIrcMsgForLogTypeMove() { + $move_params = array( + '4::target' => $this->target->getPrefixedText(), + '5::noredir' => 0, + ); + $sep = $this->context->msg( 'colon-separator' )->text(); + + # move/move + $this->assertIRCComment( + $this->context->msg( '1movedto2', 'SomeTitle', 'TestTarget' ) + ->plain() . $sep . $this->user_comment, + 'move', 'move', + $move_params, + $this->user_comment + ); + + # move/move_redir + $this->assertIRCComment( + $this->context->msg( '1movedto2_redir', 'SomeTitle', 'TestTarget' ) + ->plain() . $sep . $this->user_comment, + 'move', 'move_redir', + $move_params, + $this->user_comment + ); + } + + /** + * @covers LogFormatter::getIRCActionComment + * @covers LogFormatter::getIRCActionText + */ + public function testIrcMsgForLogTypePatrol() { + # patrol/patrol + $this->assertIRCComment( + $this->context->msg( 'patrol-log-line', 'revision 777', '[[SomeTitle]]', '' )->plain(), + 'patrol', 'patrol', + array( + '4::curid' => '777', + '5::previd' => '666', + '6::auto' => 0, + ) + ); + } + + /** + * @covers LogFormatter::getIRCActionComment + * @covers LogFormatter::getIRCActionText + */ + public function testIrcMsgForLogTypeProtect() { + $protectParams = array( + '[edit=sysop] (indefinite) ‎[move=sysop] (indefinite)' + ); + $sep = $this->context->msg( 'colon-separator' )->text(); + + # protect/protect + $this->assertIRCComment( + $this->context->msg( 'protectedarticle', 'SomeTitle ' . $protectParams[0] ) + ->plain() . $sep . $this->user_comment, + 'protect', 'protect', + $protectParams, + $this->user_comment + ); + + # protect/unprotect + $this->assertIRCComment( + $this->context->msg( 'unprotectedarticle', 'SomeTitle' )->plain() . $sep . $this->user_comment, + 'protect', 'unprotect', + array(), + $this->user_comment + ); + + # protect/modify + $this->assertIRCComment( + $this->context->msg( 'modifiedarticleprotection', 'SomeTitle ' . $protectParams[0] ) + ->plain() . $sep . $this->user_comment, + 'protect', 'modify', + $protectParams, + $this->user_comment + ); + + # protect/move_prot + $this->assertIRCComment( + $this->context->msg( 'movedarticleprotection', 'SomeTitle', 'OldTitle' ) + ->plain() . $sep . $this->user_comment, + 'protect', 'move_prot', + array( + '4::oldtitle' => 'OldTitle' + ), + $this->user_comment + ); + } + + /** + * @covers LogFormatter::getIRCActionComment + * @covers LogFormatter::getIRCActionText + */ + public function testIrcMsgForLogTypeUpload() { + $sep = $this->context->msg( 'colon-separator' )->text(); + + # upload/upload + $this->assertIRCComment( + $this->context->msg( 'uploadedimage', 'SomeTitle' )->plain() . $sep . $this->user_comment, + 'upload', 'upload', + array(), + $this->user_comment + ); + + # upload/overwrite + $this->assertIRCComment( + $this->context->msg( 'overwroteimage', 'SomeTitle' )->plain() . $sep . $this->user_comment, + 'upload', 'overwrite', + array(), + $this->user_comment + ); + } + + /** + * @covers LogFormatter::getIRCActionComment + * @covers LogFormatter::getIRCActionText + */ + public function testIrcMsgForLogTypeMerge() { + $sep = $this->context->msg( 'colon-separator' )->text(); + + # merge/merge + $this->assertIRCComment( + $this->context->msg( 'pagemerge-logentry', 'SomeTitle', 'Dest', 'timestamp' )->plain() + . $sep . $this->user_comment, + 'merge', 'merge', + array( + '4::dest' => 'Dest', + '5::mergepoint' => 'timestamp', + ), + $this->user_comment + ); + } + + /** + * @covers LogFormatter::getIRCActionComment + * @covers LogFormatter::getIRCActionText + */ + public function testIrcMsgForLogTypeImport() { + $sep = $this->context->msg( 'colon-separator' )->text(); + + # import/upload + $msg = $this->context->msg( 'import-logentry-upload', 'SomeTitle' )->plain() . + $sep . + $this->user_comment; + $this->assertIRCComment( + $msg, + 'import', 'upload', + array(), + $this->user_comment + ); + + # import/interwiki + $msg = $this->context->msg( 'import-logentry-interwiki', 'SomeTitle' )->plain() . + $sep . + $this->user_comment; + $this->assertIRCComment( + $msg, + 'import', 'interwiki', + array(), + $this->user_comment + ); + } + + /** + * @param string $expected Expected IRC text without colors codes + * @param string $type Log type (move, delete, suppress, patrol ...) + * @param string $action A log type action + * @param array $params + * @param string $comment (optional) A comment for the log action + * @param string $msg (optional) A message for PHPUnit :-) + */ + protected function assertIRCComment( $expected, $type, $action, $params, + $comment = null, $msg = '', $legacy = false + ) { + $logEntry = new ManualLogEntry( $type, $action ); + $logEntry->setPerformer( $this->user ); + $logEntry->setTarget( $this->title ); + if ( $comment !== null ) { + $logEntry->setComment( $comment ); + } + $logEntry->setParameters( $params ); + $logEntry->setLegacy( $legacy ); + + $formatter = LogFormatter::newFromEntry( $logEntry ); + $formatter->setContext( $this->context ); + + // Apply the same transformation as done in IRCColourfulRCFeedFormatter::getLine for rc_comment + $ircRcComment = IRCColourfulRCFeedFormatter::cleanupForIRC( $formatter->getIRCActionComment() ); + + $this->assertEquals( + $expected, + $ircRcComment, + $msg + ); + } + } diff --git a/tests/phpunit/includes/logging/LogFormatterTestCase.php b/tests/phpunit/includes/logging/LogFormatterTestCase.php new file mode 100644 index 00000000..e88452b7 --- /dev/null +++ b/tests/phpunit/includes/logging/LogFormatterTestCase.php @@ -0,0 +1,65 @@ +expandDatabaseRow( $row, $this->isLegacy( $extra ) ); + + $formatter = LogFormatter::newFromRow( $row ); + + $this->assertEquals( + $extra['text'], + self::removeSomeHtml( $formatter->getActionText() ), + 'Action text is equal to expected text' + ); + + $this->assertSame( // ensure types and array key order + $extra['api'], + self::removeApiMetaData( $formatter->formatParametersForApi() ), + 'Api log params is equal to expected array' + ); + } + + protected function isLegacy( $extra ) { + return isset( $extra['legacy'] ) && $extra['legacy']; + } + + protected function expandDatabaseRow( $data, $legacy ) { + return array( + // no log_id because no insert in database + 'log_type' => $data['type'], + 'log_action' => $data['action'], + 'log_timestamp' => isset( $data['timestamp'] ) ? $data['timestamp'] : wfTimestampNow(), + 'log_user' => isset( $data['user'] ) ? $data['user'] : 0, + 'log_user_text' => isset( $data['user_text'] ) ? $data['user_text'] : 'User', + 'log_namespace' => isset( $data['namespace'] ) ? $data['namespace'] : NS_MAIN, + 'log_title' => isset( $data['title'] ) ? $data['title'] : 'Main_Page', + 'log_page' => isset( $data['page'] ) ? $data['page'] : 0, + 'log_comment' => isset( $data['comment'] ) ? $data['comment'] : '', + 'log_params' => $legacy + ? LogPage::makeParamBlob( $data['params'] ) + : LogEntryBase::makeParamBlob( $data['params'] ), + 'log_deleted' => isset( $data['deleted'] ) ? $data['deleted'] : 0, + ); + } + + private static function removeSomeHtml( $html ) { + $html = str_replace( '"', '"', $html ); + return trim( preg_replace( '/<(a|span)[^>]*>([^<]*)<\/\1>/', '$2', $html ) ); + } + + private static function removeApiMetaData( $val ) { + if ( is_array( $val ) ) { + unset( $val['_element'] ); + unset( $val['_type'] ); + foreach ( $val as $key => $value ) { + $val[$key] = self::removeApiMetaData( $value ); + } + } + return $val; + } +} diff --git a/tests/phpunit/includes/logging/MergeLogFormatterTest.php b/tests/phpunit/includes/logging/MergeLogFormatterTest.php new file mode 100644 index 00000000..2ff0ddf5 --- /dev/null +++ b/tests/phpunit/includes/logging/MergeLogFormatterTest.php @@ -0,0 +1,67 @@ + 'merge', + 'action' => 'merge', + 'comment' => 'Merge comment', + 'namespace' => NS_MAIN, + 'title' => 'OldPage', + 'params' => array( + '4::dest' => 'NewPage', + '5::mergepoint' => '20140804160710', + ), + ), + array( + 'text' => 'User merged OldPage into NewPage (revisions up to 16:07, 4 August 2014)', + 'api' => array( + 'dest_ns' => 0, + 'dest_title' => 'NewPage', + 'mergepoint' => '2014-08-04T16:07:10Z', + ), + ), + ), + + // Legacy format + array( + array( + 'type' => 'merge', + 'action' => 'merge', + 'comment' => 'merge comment', + 'namespace' => NS_MAIN, + 'title' => 'OldPage', + 'params' => array( + 'NewPage', + '20140804160710', + ), + ), + array( + 'legacy' => true, + 'text' => 'User merged OldPage into NewPage (revisions up to 16:07, 4 August 2014)', + 'api' => array( + 'dest_ns' => 0, + 'dest_title' => 'NewPage', + 'mergepoint' => '2014-08-04T16:07:10Z', + ), + ), + ), + ); + } + + /** + * @dataProvider provideMergeLogDatabaseRows + */ + public function testMergeLogDatabaseRows( $row, $extra ) { + $this->doTestLogFormatter( $row, $extra ); + } +} diff --git a/tests/phpunit/includes/logging/MoveLogFormatterTest.php b/tests/phpunit/includes/logging/MoveLogFormatterTest.php new file mode 100644 index 00000000..fdc4b7e1 --- /dev/null +++ b/tests/phpunit/includes/logging/MoveLogFormatterTest.php @@ -0,0 +1,270 @@ + 'move', + 'action' => 'move', + 'comment' => 'move comment with redirect', + 'namespace' => NS_MAIN, + 'title' => 'OldPage', + 'params' => array( + '4::target' => 'NewPage', + '5::noredir' => '0', + ), + ), + array( + 'text' => 'User moved page OldPage to NewPage', + 'api' => array( + 'target_ns' => 0, + 'target_title' => 'NewPage', + 'suppressredirect' => false, + ), + ), + ), + + // Current format - without redirect + array( + array( + 'type' => 'move', + 'action' => 'move', + 'comment' => 'move comment', + 'namespace' => NS_MAIN, + 'title' => 'OldPage', + 'params' => array( + '4::target' => 'NewPage', + '5::noredir' => '1', + ), + ), + array( + 'text' => 'User moved page OldPage to NewPage without leaving a redirect', + 'api' => array( + 'target_ns' => 0, + 'target_title' => 'NewPage', + 'suppressredirect' => true, + ), + ), + ), + + // legacy format - with redirect + array( + array( + 'type' => 'move', + 'action' => 'move', + 'comment' => 'move comment', + 'namespace' => NS_MAIN, + 'title' => 'OldPage', + 'params' => array( + 'NewPage', + '', + ), + ), + array( + 'legacy' => true, + 'text' => 'User moved page OldPage to NewPage', + 'api' => array( + 'target_ns' => 0, + 'target_title' => 'NewPage', + 'suppressredirect' => false, + ), + ), + ), + + // legacy format - without redirect + array( + array( + 'type' => 'move', + 'action' => 'move', + 'comment' => 'move comment', + 'namespace' => NS_MAIN, + 'title' => 'OldPage', + 'params' => array( + 'NewPage', + '1', + ), + ), + array( + 'legacy' => true, + 'text' => 'User moved page OldPage to NewPage without leaving a redirect', + 'api' => array( + 'target_ns' => 0, + 'target_title' => 'NewPage', + 'suppressredirect' => true, + ), + ), + ), + + // old format without flag for redirect suppression + array( + array( + 'type' => 'move', + 'action' => 'move', + 'comment' => 'move comment', + 'namespace' => NS_MAIN, + 'title' => 'OldPage', + 'params' => array( + 'NewPage', + ), + ), + array( + 'legacy' => true, + 'text' => 'User moved page OldPage to NewPage', + 'api' => array( + 'target_ns' => 0, + 'target_title' => 'NewPage', + 'suppressredirect' => false, + ), + ), + ), + ); + } + + /** + * @dataProvider provideMoveLogDatabaseRows + */ + public function testMoveLogDatabaseRows( $row, $extra ) { + $this->doTestLogFormatter( $row, $extra ); + } + + /** + * Provide different rows from the logging table to test + * for backward compatibility. + * Do not change the existing data, just add a new database row + */ + public static function provideMoveRedirLogDatabaseRows() { + return array( + // Current format - with redirect + array( + array( + 'type' => 'move', + 'action' => 'move_redir', + 'comment' => 'move comment with redirect', + 'namespace' => NS_MAIN, + 'title' => 'OldPage', + 'params' => array( + '4::target' => 'NewPage', + '5::noredir' => '0', + ), + ), + array( + 'text' => 'User moved page OldPage to NewPage over redirect', + 'api' => array( + 'target_ns' => 0, + 'target_title' => 'NewPage', + 'suppressredirect' => false, + ), + ), + ), + + // Current format - without redirect + array( + array( + 'type' => 'move', + 'action' => 'move_redir', + 'comment' => 'move comment', + 'namespace' => NS_MAIN, + 'title' => 'OldPage', + 'params' => array( + '4::target' => 'NewPage', + '5::noredir' => '1', + ), + ), + array( + 'text' => 'User moved page OldPage to NewPage over a redirect without leaving a redirect', + 'api' => array( + 'target_ns' => 0, + 'target_title' => 'NewPage', + 'suppressredirect' => true, + ), + ), + ), + + // legacy format - with redirect + array( + array( + 'type' => 'move', + 'action' => 'move_redir', + 'comment' => 'move comment', + 'namespace' => NS_MAIN, + 'title' => 'OldPage', + 'params' => array( + 'NewPage', + '', + ), + ), + array( + 'legacy' => true, + 'text' => 'User moved page OldPage to NewPage over redirect', + 'api' => array( + 'target_ns' => 0, + 'target_title' => 'NewPage', + 'suppressredirect' => false, + ), + ), + ), + + // legacy format - without redirect + array( + array( + 'type' => 'move', + 'action' => 'move_redir', + 'comment' => 'move comment', + 'namespace' => NS_MAIN, + 'title' => 'OldPage', + 'params' => array( + 'NewPage', + '1', + ), + ), + array( + 'legacy' => true, + 'text' => 'User moved page OldPage to NewPage over a redirect without leaving a redirect', + 'api' => array( + 'target_ns' => 0, + 'target_title' => 'NewPage', + 'suppressredirect' => true, + ), + ), + ), + + // old format without flag for redirect suppression + array( + array( + 'type' => 'move', + 'action' => 'move_redir', + 'comment' => 'move comment', + 'namespace' => NS_MAIN, + 'title' => 'OldPage', + 'params' => array( + 'NewPage', + ), + ), + array( + 'legacy' => true, + 'text' => 'User moved page OldPage to NewPage over redirect', + 'api' => array( + 'target_ns' => 0, + 'target_title' => 'NewPage', + 'suppressredirect' => false, + ), + ), + ), + ); + } + + /** + * @dataProvider provideMoveRedirLogDatabaseRows + */ + public function testMoveRedirLogDatabaseRows( $row, $extra ) { + $this->doTestLogFormatter( $row, $extra ); + } +} diff --git a/tests/phpunit/includes/logging/NewUsersLogFormatterTest.php b/tests/phpunit/includes/logging/NewUsersLogFormatterTest.php new file mode 100644 index 00000000..5b03370d --- /dev/null +++ b/tests/phpunit/includes/logging/NewUsersLogFormatterTest.php @@ -0,0 +1,207 @@ +mergeMwGlobalArrayValue( 'wgLogActionsHandlers', array( + 'newusers/newusers' => 'NewUsersLogFormatter', + 'newusers/create' => 'NewUsersLogFormatter', + 'newusers/create2' => 'NewUsersLogFormatter', + 'newusers/byemail' => 'NewUsersLogFormatter', + 'newusers/autocreate' => 'NewUsersLogFormatter', + ) ); + } + + /** + * Provide different rows from the logging table to test + * for backward compatibility. + * Do not change the existing data, just add a new database row + */ + public static function provideNewUsersLogDatabaseRows() { + return array( + // Only old logs + array( + array( + 'type' => 'newusers', + 'action' => 'newusers', + 'comment' => 'newusers comment', + 'user' => 0, + 'user_text' => 'New user', + 'namespace' => NS_USER, + 'title' => 'New user', + 'params' => array(), + ), + array( + 'legacy' => true, + 'text' => 'User account New user was created', + 'api' => array(), + ), + ), + ); + } + + /** + * @dataProvider provideNewUsersLogDatabaseRows + */ + public function testNewUsersLogDatabaseRows( $row, $extra ) { + $this->doTestLogFormatter( $row, $extra ); + } + + /** + * Provide different rows from the logging table to test + * for backward compatibility. + * Do not change the existing data, just add a new database row + */ + public static function provideCreateLogDatabaseRows() { + return array( + // Current format + array( + array( + 'type' => 'newusers', + 'action' => 'create', + 'comment' => 'newusers comment', + 'user' => 0, + 'user_text' => 'New user', + 'namespace' => NS_USER, + 'title' => 'New user', + 'params' => array( + '4::userid' => 1, + ), + ), + array( + 'text' => 'User account New user was created', + 'api' => array( + 'userid' => 1, + ), + ), + ), + ); + } + + /** + * @dataProvider provideCreateLogDatabaseRows + */ + public function testCreateLogDatabaseRows( $row, $extra ) { + $this->doTestLogFormatter( $row, $extra ); + } + + /** + * Provide different rows from the logging table to test + * for backward compatibility. + * Do not change the existing data, just add a new database row + */ + public static function provideCreate2LogDatabaseRows() { + return array( + // Current format + array( + array( + 'type' => 'newusers', + 'action' => 'create2', + 'comment' => 'newusers comment', + 'user' => 0, + 'user_text' => 'User', + 'namespace' => NS_USER, + 'title' => 'UTSysop', + 'params' => array( + '4::userid' => 1, + ), + ), + array( + 'text' => 'User account UTSysop was created by User', + 'api' => array( + 'userid' => 1, + ), + ), + ), + ); + } + + /** + * @dataProvider provideCreate2LogDatabaseRows + */ + public function testCreate2LogDatabaseRows( $row, $extra ) { + $this->doTestLogFormatter( $row, $extra ); + } + + /** + * Provide different rows from the logging table to test + * for backward compatibility. + * Do not change the existing data, just add a new database row + */ + public static function provideByemailLogDatabaseRows() { + return array( + // Current format + array( + array( + 'type' => 'newusers', + 'action' => 'byemail', + 'comment' => 'newusers comment', + 'user' => 0, + 'user_text' => 'Sysop', + 'namespace' => NS_USER, + 'title' => 'UTSysop', + 'params' => array( + '4::userid' => 1, + ), + ), + array( + 'text' => 'User account UTSysop was created by Sysop and password was sent by email', + 'api' => array( + 'userid' => 1, + ), + ), + ), + ); + } + + /** + * @dataProvider provideByemailLogDatabaseRows + */ + public function testByemailLogDatabaseRows( $row, $extra ) { + $this->doTestLogFormatter( $row, $extra ); + } + + /** + * Provide different rows from the logging table to test + * for backward compatibility. + * Do not change the existing data, just add a new database row + */ + public static function provideAutocreateLogDatabaseRows() { + return array( + // Current format + array( + array( + 'type' => 'newusers', + 'action' => 'autocreate', + 'comment' => 'newusers comment', + 'user' => 0, + 'user_text' => 'New user', + 'namespace' => NS_USER, + 'title' => 'New user', + 'params' => array( + '4::userid' => 1, + ), + ), + array( + 'text' => 'User account New user was created automatically', + 'api' => array( + 'userid' => 1, + ), + ), + ), + ); + } + + /** + * @dataProvider provideAutocreateLogDatabaseRows + */ + public function testAutocreateLogDatabaseRows( $row, $extra ) { + $this->doTestLogFormatter( $row, $extra ); + } +} diff --git a/tests/phpunit/includes/logging/PageLangLogFormatterTest.php b/tests/phpunit/includes/logging/PageLangLogFormatterTest.php new file mode 100644 index 00000000..226e492b --- /dev/null +++ b/tests/phpunit/includes/logging/PageLangLogFormatterTest.php @@ -0,0 +1,53 @@ +setMwGlobals( 'wgHooks', array() ); + // Register LogHandler, see $wgPageLanguageUseDB in Setup.php + $this->mergeMwGlobalArrayValue( 'wgLogActionsHandlers', array( + 'pagelang/pagelang' => 'PageLangLogFormatter', + ) ); + } + + /** + * Provide different rows from the logging table to test + * for backward compatibility. + * Do not change the existing data, just add a new database row + */ + public static function providePageLangLogDatabaseRows() { + return array( + // Current format + array( + array( + 'type' => 'pagelang', + 'action' => 'pagelang', + 'comment' => 'page lang comment', + 'namespace' => NS_MAIN, + 'title' => 'Page', + 'params' => array( + '4::oldlanguage' => 'en', + '5::newlanguage' => 'de[def]', + ), + ), + array( + 'text' => 'User changed page language for Page from English (en) to Deutsch (de) [default].', + 'api' => array( + 'oldlanguage' => 'en', + 'newlanguage' => 'de[def]' + ), + ), + ), + ); + } + + /** + * @dataProvider providePageLangLogDatabaseRows + */ + public function testPageLangLogDatabaseRows( $row, $extra ) { + $this->doTestLogFormatter( $row, $extra ); + } +} diff --git a/tests/phpunit/includes/logging/PatrolLogFormatterTest.php b/tests/phpunit/includes/logging/PatrolLogFormatterTest.php new file mode 100644 index 00000000..6e1c5efc --- /dev/null +++ b/tests/phpunit/includes/logging/PatrolLogFormatterTest.php @@ -0,0 +1,118 @@ + 'patrol', + 'action' => 'patrol', + 'comment' => 'patrol comment', + 'namespace' => NS_MAIN, + 'title' => 'Page', + 'params' => array( + '4::curid' => 2, + '5::previd' => 1, + '6::auto' => 0, + ), + ), + array( + 'text' => 'User marked revision 2 of page Page patrolled', + 'api' => array( + 'curid' => 2, + 'previd' => 1, + 'auto' => false, + ), + ), + ), + + // Current format - autopatrol + array( + array( + 'type' => 'patrol', + 'action' => 'patrol', + 'comment' => 'patrol comment', + 'namespace' => NS_MAIN, + 'title' => 'Page', + 'params' => array( + '4::curid' => 2, + '5::previd' => 1, + '6::auto' => 1, + ), + ), + array( + 'text' => 'User automatically marked revision 2 of page Page patrolled', + 'api' => array( + 'curid' => 2, + 'previd' => 1, + 'auto' => true, + ), + ), + ), + + // Legacy format + array( + array( + 'type' => 'patrol', + 'action' => 'patrol', + 'comment' => 'patrol comment', + 'namespace' => NS_MAIN, + 'title' => 'Page', + 'params' => array( + '2', + '1', + '0', + ), + ), + array( + 'legacy' => true, + 'text' => 'User marked revision 2 of page Page patrolled', + 'api' => array( + 'curid' => 2, + 'previd' => 1, + 'auto' => false, + ), + ), + ), + + // Legacy format - autopatrol + array( + array( + 'type' => 'patrol', + 'action' => 'patrol', + 'comment' => 'patrol comment', + 'namespace' => NS_MAIN, + 'title' => 'Page', + 'params' => array( + '2', + '1', + '1', + ), + ), + array( + 'legacy' => true, + 'text' => 'User automatically marked revision 2 of page Page patrolled', + 'api' => array( + 'curid' => 2, + 'previd' => 1, + 'auto' => true, + ), + ), + ), + ); + } + + /** + * @dataProvider providePatrolLogDatabaseRows + */ + public function testPatrolLogDatabaseRows( $row, $extra ) { + $this->doTestLogFormatter( $row, $extra ); + } +} diff --git a/tests/phpunit/includes/logging/ProtectLogFormatterTest.php b/tests/phpunit/includes/logging/ProtectLogFormatterTest.php new file mode 100644 index 00000000..611b2dfc --- /dev/null +++ b/tests/phpunit/includes/logging/ProtectLogFormatterTest.php @@ -0,0 +1,63 @@ + 'protect', + 'action' => 'move_prot', + 'comment' => 'Move comment', + 'namespace' => NS_MAIN, + 'title' => 'NewPage', + 'params' => array( + '4::oldtitle' => 'OldPage', + ), + ), + array( + 'text' => 'User moved protection settings from OldPage to NewPage', + 'api' => array( + 'oldtitle_ns' => 0, + 'oldtitle_title' => 'OldPage', + ), + ), + ), + + // Legacy format + array( + array( + 'type' => 'protect', + 'action' => 'move_prot', + 'comment' => 'Move comment', + 'namespace' => NS_MAIN, + 'title' => 'NewPage', + 'params' => array( + 'OldPage', + ), + ), + array( + 'legacy' => true, + 'text' => 'User moved protection settings from OldPage to NewPage', + 'api' => array( + 'oldtitle_ns' => 0, + 'oldtitle_title' => 'OldPage', + ), + ), + ), + ); + } + + /** + * @dataProvider provideMoveProtLogDatabaseRows + */ + public function testMoveProtLogDatabaseRows( $row, $extra ) { + $this->doTestLogFormatter( $row, $extra ); + } +} diff --git a/tests/phpunit/includes/logging/RightsLogFormatterTest.php b/tests/phpunit/includes/logging/RightsLogFormatterTest.php new file mode 100644 index 00000000..e9577f11 --- /dev/null +++ b/tests/phpunit/includes/logging/RightsLogFormatterTest.php @@ -0,0 +1,157 @@ + 'rights', + 'action' => 'rights', + 'comment' => 'rights comment', + 'user' => 0, + 'user_text' => 'Sysop', + 'namespace' => NS_USER, + 'title' => 'User', + 'params' => array( + '4::oldgroups' => array(), + '5::newgroups' => array( 'sysop', 'bureaucrat' ), + ), + ), + array( + 'text' => 'Sysop changed group membership for User:User from (none) to ' + . 'administrator and bureaucrat', + 'api' => array( + 'oldgroups' => array(), + 'newgroups' => array( 'sysop', 'bureaucrat' ), + ), + ), + ), + + // Legacy format + array( + array( + 'type' => 'rights', + 'action' => 'rights', + 'comment' => 'rights comment', + 'user' => 0, + 'user_text' => 'Sysop', + 'namespace' => NS_USER, + 'title' => 'User', + 'params' => array( + '', + 'sysop, bureaucrat', + ), + ), + array( + 'legacy' => true, + 'text' => 'Sysop changed group membership for User:User from (none) to ' + . 'administrator and bureaucrat', + 'api' => array( + 'oldgroups' => array(), + 'newgroups' => array( 'sysop', 'bureaucrat' ), + ), + ), + ), + + // Really old entry + array( + array( + 'type' => 'rights', + 'action' => 'rights', + 'comment' => 'rights comment', + 'user' => 0, + 'user_text' => 'Sysop', + 'namespace' => NS_USER, + 'title' => 'User', + 'params' => array(), + ), + array( + 'legacy' => true, + 'text' => 'Sysop changed group membership for User:User', + 'api' => array(), + ), + ), + ); + } + + /** + * @dataProvider provideRightsLogDatabaseRows + */ + public function testRightsLogDatabaseRows( $row, $extra ) { + $this->doTestLogFormatter( $row, $extra ); + } + + /** + * Provide different rows from the logging table to test + * for backward compatibility. + * Do not change the existing data, just add a new database row + */ + public static function provideAutopromoteLogDatabaseRows() { + return array( + // Current format + array( + array( + 'type' => 'rights', + 'action' => 'autopromote', + 'comment' => 'rights comment', + 'user' => 0, + 'user_text' => 'Sysop', + 'namespace' => NS_USER, + 'title' => 'Sysop', + 'params' => array( + '4::oldgroups' => array( 'sysop' ), + '5::newgroups' => array( 'sysop', 'bureaucrat' ), + ), + ), + array( + 'text' => 'Sysop was automatically promoted from administrator to ' + . 'administrator and bureaucrat', + 'api' => array( + 'oldgroups' => array( 'sysop' ), + 'newgroups' => array( 'sysop', 'bureaucrat' ), + ), + ), + ), + + // Legacy format + array( + array( + 'type' => 'rights', + 'action' => 'autopromote', + 'comment' => 'rights comment', + 'user' => 0, + 'user_text' => 'Sysop', + 'namespace' => NS_USER, + 'title' => 'Sysop', + 'params' => array( + 'sysop', + 'sysop, bureaucrat', + ), + ), + array( + 'legacy' => true, + 'text' => 'Sysop was automatically promoted from administrator to ' + . 'administrator and bureaucrat', + 'api' => array( + 'oldgroups' => array( 'sysop' ), + 'newgroups' => array( 'sysop', 'bureaucrat' ), + ), + ), + ), + ); + } + + /** + * @dataProvider provideAutopromoteLogDatabaseRows + */ + public function testAutopromoteLogDatabaseRows( $row, $extra ) { + $this->doTestLogFormatter( $row, $extra ); + } +} diff --git a/tests/phpunit/includes/logging/UploadLogFormatterTest.php b/tests/phpunit/includes/logging/UploadLogFormatterTest.php new file mode 100644 index 00000000..12f51613 --- /dev/null +++ b/tests/phpunit/includes/logging/UploadLogFormatterTest.php @@ -0,0 +1,166 @@ + 'upload', + 'action' => 'upload', + 'comment' => 'upload comment', + 'namespace' => NS_FILE, + 'title' => 'File.png', + 'params' => array( + 'img_sha1' => 'hash', + 'img_timestamp' => '20150101000000', + ), + ), + array( + 'text' => 'User uploaded File:File.png', + 'api' => array( + 'img_sha1' => 'hash', + 'img_timestamp' => '2015-01-01T00:00:00Z', + ), + ), + ), + + // Old format without params + array( + array( + 'type' => 'upload', + 'action' => 'upload', + 'comment' => 'upload comment', + 'namespace' => NS_FILE, + 'title' => 'File.png', + 'params' => array(), + ), + array( + 'text' => 'User uploaded File:File.png', + 'api' => array(), + ), + ), + ); + } + + /** + * @dataProvider provideUploadLogDatabaseRows + */ + public function testUploadLogDatabaseRows( $row, $extra ) { + $this->doTestLogFormatter( $row, $extra ); + } + + /** + * Provide different rows from the logging table to test + * for backward compatibility. + * Do not change the existing data, just add a new database row + */ + public static function provideOverwriteLogDatabaseRows() { + return array( + // Current format + array( + array( + 'type' => 'upload', + 'action' => 'overwrite', + 'comment' => 'upload comment', + 'namespace' => NS_FILE, + 'title' => 'File.png', + 'params' => array( + 'img_sha1' => 'hash', + 'img_timestamp' => '20150101000000', + ), + ), + array( + 'text' => 'User uploaded a new version of File:File.png', + 'api' => array( + 'img_sha1' => 'hash', + 'img_timestamp' => '2015-01-01T00:00:00Z', + ), + ), + ), + + // Old format without params + array( + array( + 'type' => 'upload', + 'action' => 'overwrite', + 'comment' => 'upload comment', + 'namespace' => NS_FILE, + 'title' => 'File.png', + 'params' => array(), + ), + array( + 'text' => 'User uploaded a new version of File:File.png', + 'api' => array(), + ), + ), + ); + } + + /** + * @dataProvider provideOverwriteLogDatabaseRows + */ + public function testOverwriteLogDatabaseRows( $row, $extra ) { + $this->doTestLogFormatter( $row, $extra ); + } + + /** + * Provide different rows from the logging table to test + * for backward compatibility. + * Do not change the existing data, just add a new database row + */ + public static function provideRevertLogDatabaseRows() { + return array( + // Current format + array( + array( + 'type' => 'upload', + 'action' => 'revert', + 'comment' => 'upload comment', + 'namespace' => NS_FILE, + 'title' => 'File.png', + 'params' => array( + 'img_sha1' => 'hash', + 'img_timestamp' => '20150101000000', + ), + ), + array( + 'text' => 'User uploaded File:File.png', + 'api' => array( + 'img_sha1' => 'hash', + 'img_timestamp' => '2015-01-01T00:00:00Z', + ), + ), + ), + + // Old format without params + array( + array( + 'type' => 'upload', + 'action' => 'revert', + 'comment' => 'upload comment', + 'namespace' => NS_FILE, + 'title' => 'File.png', + 'params' => array(), + ), + array( + 'text' => 'User uploaded File:File.png', + 'api' => array(), + ), + ), + ); + } + + /** + * @dataProvider provideRevertLogDatabaseRows + */ + public function testRevertLogDatabaseRows( $row, $extra ) { + $this->doTestLogFormatter( $row, $extra ); + } +} diff --git a/tests/phpunit/includes/media/ExifBitmapTest.php b/tests/phpunit/includes/media/ExifBitmapTest.php index 41330f41..adbc9775 100644 --- a/tests/phpunit/includes/media/ExifBitmapTest.php +++ b/tests/phpunit/includes/media/ExifBitmapTest.php @@ -3,7 +3,7 @@ /** * @group Media */ -class ExifBitmapTest extends MediaWikiTestCase { +class ExifBitmapTest extends MediaWikiMediaTestCase { /** * @var ExifBitmapHandler @@ -143,4 +143,41 @@ class ExifBitmapTest extends MediaWikiTestCase { $res = $this->handler->convertMetadataVersion( $metadata, 1 ); $this->assertEquals( $expected, $res ); } + + /** + * @dataProvider provideSwappingICCProfile + * @covers BitmapHandler::swapICCProfile + */ + public function testSwappingICCProfile( $sourceFilename, $controlFilename, $newProfileFilename, $oldProfileName ) { + global $wgExiftool; + + if ( !$wgExiftool || !is_file( $wgExiftool ) ) { + $this->markTestSkipped( "Exiftool not installed, cannot test ICC profile swapping" ); + } + + $this->setMwGlobals( 'wgUseTinyRGBForJPGThumbnails', true ); + + $sourceFilepath = $this->filePath . $sourceFilename; + $controlFilepath = $this->filePath . $controlFilename; + $profileFilepath = $this->filePath . $newProfileFilename; + $filepath = $this->getNewTempFile(); + + copy( $sourceFilepath, $filepath ); + + $file = $this->dataFile( $sourceFilename, 'image/jpeg' ); + $this->handler->swapICCProfile( $filepath, $oldProfileName, $profileFilepath ); + + $this->assertEquals( sha1( file_get_contents( $filepath ) ), sha1( file_get_contents( $controlFilepath ) ) ); + } + + public function provideSwappingICCProfile() { + return array( + // File with sRGB should end up with TinyRGB + array( 'srgb.jpg', 'tinyrgb.jpg', 'tinyrgb.icc', 'IEC 61966-2.1 Default RGB colour space - sRGB' ), + // File with TinyRGB should be left unchanged + array( 'tinyrgb.jpg', 'tinyrgb.jpg', 'tinyrgb.icc', 'IEC 61966-2.1 Default RGB colour space - sRGB' ), + // File with no profile should be left unchanged + array( 'test.jpg', 'test.jpg', 'tinyrgb.icc', 'IEC 61966-2.1 Default RGB colour space - sRGB' ) + ); + } } diff --git a/tests/phpunit/includes/media/FormatMetadataTest.php b/tests/phpunit/includes/media/FormatMetadataTest.php index 54758f94..b666c83c 100644 --- a/tests/phpunit/includes/media/FormatMetadataTest.php +++ b/tests/phpunit/includes/media/FormatMetadataTest.php @@ -36,39 +36,6 @@ class FormatMetadataTest extends MediaWikiMediaTestCase { 'File with invalid date metadata (bug 29471)' ); } - /** - * @param string $filename - * @param int $expected Total image area - * @dataProvider provideFlattenArray - * @covers FormatMetadata::flattenArray - */ - public function testFlattenArray( $vals, $type, $noHtml, $ctx, $expected ) { - $actual = FormatMetadata::flattenArray( $vals, $type, $noHtml, $ctx ); - $this->assertEquals( $expected, $actual ); - } - - public static function provideFlattenArray() { - return array( - array( - array( 1, 2, 3 ), 'ul', false, false, - "
              • 1
              • \n
              • 2
              • \n
              • 3
              ", - ), - array( - array( 1, 2, 3 ), 'ol', false, false, - "
              1. 1
              2. \n
              3. 2
              4. \n
              5. 3
              ", - ), - array( - array( 1, 2, 3 ), 'ul', true, false, - "\n*1\n*2\n*3", - ), - array( - array( 1, 2, 3 ), 'ol', true, false, - "\n#1\n#2\n#3", - ), - // TODO: more test cases - ); - } - /** * @param mixed $input * @param mixed $output diff --git a/tests/phpunit/includes/media/WebPTest.php b/tests/phpunit/includes/media/WebPTest.php new file mode 100644 index 00000000..d36710a3 --- /dev/null +++ b/tests/phpunit/includes/media/WebPTest.php @@ -0,0 +1,127 @@ +tempFileName = tempnam( wfTempDir(), 'WEBP' ); + } + public function tearDown() { + parent::tearDown(); + unlink( $this->tempFileName ); + } + /** + * @dataProvider provideTestExtractMetaData + */ + public function testExtractMetaData( $header, $expectedResult ) { + // Put header into file + file_put_contents( $this->tempFileName, $header ); + + $this->assertEquals( $expectedResult, WebPHandler::extractMetadata( $this->tempFileName ) ); + } + public function provideTestExtractMetaData() { + return array( + // Files from https://developers.google.com/speed/webp/gallery2 + array( "\x52\x49\x46\x46\x90\x68\x01\x00\x57\x45\x42\x50\x56\x50\x38\x4C\x83\x68\x01\x00\x2F\x8F\x01\x4B\x10\x8D\x38\x6C\xDB\x46\x92\xE0\xE0\x82\x7B\x6C", + array( 'compression' => 'lossless', 'width' => 400, 'height' => 301 ) ), + array( "\x52\x49\x46\x46\x64\x5B\x00\x00\x57\x45\x42\x50\x56\x50\x38\x58\x0A\x00\x00\x00\x10\x00\x00\x00\x8F\x01\x00\x2C\x01\x00\x41\x4C\x50\x48\xE5\x0E", + array( 'compression' => 'unknown', 'animated' => false, 'transparency' => true, 'width' => 400, 'height' => 301) ), + array( "\x52\x49\x46\x46\xA8\x72\x00\x00\x57\x45\x42\x50\x56\x50\x38\x4C\x9B\x72\x00\x00\x2F\x81\x81\x62\x10\x8D\x40\x8C\x24\x39\x6E\x73\x73\x38\x01\x96", + array( 'compression' => 'lossless', 'width' => 386, 'height' => 395 ) ), + array( "\x52\x49\x46\x46\xE0\x42\x00\x00\x57\x45\x42\x50\x56\x50\x38\x58\x0A\x00\x00\x00\x10\x00\x00\x00\x81\x01\x00\x8A\x01\x00\x41\x4C\x50\x48\x56\x10", + array( 'compression' => 'unknown', 'animated' => false, 'transparency' => true, 'width' => 386, 'height' => 395 ) ), + array( "\x52\x49\x46\x46\x70\x61\x02\x00\x57\x45\x42\x50\x56\x50\x38\x4C\x63\x61\x02\x00\x2F\x1F\xC3\x95\x10\x8D\xC8\x72\xDB\xC8\x92\x24\xD8\x91\xD9\x91", + array( 'compression' => 'lossless', 'width' => 800, 'height' => 600 ) ), + array( "\x52\x49\x46\x46\x1C\x1D\x01\x00\x57\x45\x42\x50\x56\x50\x38\x58\x0A\x00\x00\x00\x10\x00\x00\x00\x1F\x03\x00\x57\x02\x00\x41\x4C\x50\x48\x25\x8B", + array( 'compression' => 'unknown', 'animated' => false, 'transparency' => true, 'width' => 800, 'height' => 600 ) ), + array( "\x52\x49\x46\x46\xFA\xC5\x00\x00\x57\x45\x42\x50\x56\x50\x38\x4C\xEE\xC5\x00\x00\x2F\xA4\x81\x28\x10\x8D\x40\x68\x24\xC9\x91\xA4\xAE\xF3\x97\x75", + array( 'compression' => 'lossless', 'width' => 421, 'height' => 163 ) ), + array( "\x52\x49\x46\x46\xF6\x5D\x00\x00\x57\x45\x42\x50\x56\x50\x38\x58\x0A\x00\x00\x00\x10\x00\x00\x00\xA4\x01\x00\xA2\x00\x00\x41\x4C\x50\x48\x38\x1A", + array( 'compression' => 'unknown', 'animated' => false, 'transparency' => true, 'width' => 421, 'height' => 163 ) ), + array( "\x52\x49\x46\x46\xC4\x96\x01\x00\x57\x45\x42\x50\x56\x50\x38\x4C\xB8\x96\x01\x00\x2F\x2B\xC1\x4A\x10\x11\x87\x6D\xDB\x48\x12\xFC\x60\xB0\x83\x24", + array( 'compression' => 'lossless', 'width' => 300, 'height' => 300 ) ), + array( "\x52\x49\x46\x46\x0A\x11\x01\x00\x57\x45\x42\x50\x56\x50\x38\x58\x0A\x00\x00\x00\x10\x00\x00\x00\x2B\x01\x00\x2B\x01\x00\x41\x4C\x50\x48\x67\x6E", + array( 'compression' => 'unknown', 'animated' => false, 'transparency' => true, 'width' => 300, 'height' => 300 ) ), + + // Lossy files from https://developers.google.com/speed/webp/gallery1 + array( "\x52\x49\x46\x46\x68\x76\x00\x00\x57\x45\x42\x50\x56\x50\x38\x20\x5C\x76\x00\x00\xD2\xBE\x01\x9D\x01\x2A\x26\x02\x70\x01\x3E\xD5\x4E\x97\x43\xA2", + array( 'compression' => 'lossy', 'width' => 550, 'height' => 368 ) ), + array( "\x52\x49\x46\x46\xB0\xEC\x00\x00\x57\x45\x42\x50\x56\x50\x38\x20\xA4\xEC\x00\x00\xB2\x4B\x02\x9D\x01\x2A\x26\x02\x94\x01\x3E\xD1\x50\x96\x46\x26", + array( 'compression' => 'lossy', 'width' => 550, 'height' => 404 ) ), + array( "\x52\x49\x46\x46\x7A\x19\x03\x00\x57\x45\x42\x50\x56\x50\x38\x20\x6E\x19\x03\x00\xB2\xF8\x09\x9D\x01\x2A\x00\x05\xD0\x02\x3E\xAD\x46\x99\x4A\xA5", + array( 'compression' => 'lossy', 'width' => 1280, 'height' => 720 ) ), + array( "\x52\x49\x46\x46\x44\xB3\x02\x00\x57\x45\x42\x50\x56\x50\x38\x20\x38\xB3\x02\x00\x52\x57\x06\x9D\x01\x2A\x00\x04\x04\x03\x3E\xA5\x44\x96\x49\x26", + array( 'compression' => 'lossy', 'width' => 1024, 'height' => 772) ), + array( "\x52\x49\x46\x46\x02\x43\x01\x00\x57\x45\x42\x50\x56\x50\x38\x20\xF6\x42\x01\x00\x12\xC0\x05\x9D\x01\x2A\x00\x04\xF0\x02\x3E\x79\x34\x93\x47\xA4", + array( 'compression' => 'lossy', 'width' => 1024, 'height' => 752) ), + + // Animated file from https://groups.google.com/a/chromium.org/d/topic/blink-dev/Y8tRC4mdQz8/discussion + array( "\x52\x49\x46\x46\xD0\x0B\x02\x00\x57\x45\x42\x50\x56\x50\x38\x58\x0A\x00\x00\x00\x12\x00\x00\x00\x3F\x01\x00\x3F\x01\x00\x41\x4E", + array( 'compression' => 'unknown', 'animated' => true, 'transparency' => true, 'width' => 320, 'height' => 320 ) ), + + // Error cases + array( '', false ), + array( ' ', false ), + array( 'RIFF ', false ), + array( 'RIFF1234WEBP ', false ), + array( 'RIFF1234WEBPVP8 ', false ), + array( 'RIFF1234WEBPVP8L ', false ), + ); + } + + /** + * @dataProvider provideTestWithFileExtractMetaData + */ + public function testWithFileExtractMetaData( $filename, $expectedResult ) { + $this->assertEquals( $expectedResult, WebPHandler::extractMetadata( $filename ) ); + } + public function provideTestWithFileExtractMetaData() { + return array( + array( __DIR__ . '/../../data/media/2_webp_ll.webp', + array( 'compression' => 'lossless', 'width' => 386, 'height' => 395 ) ), + array( __DIR__ . '/../../data/media/2_webp_a.webp', + array( 'compression' => 'lossy', 'animated' => false, 'transparency' => true, 'width' => 386, 'height' => 395 ) ), + ); + } + + /** + * @dataProvider provideTestGetImageSize + */ + public function testGetImageSize( $path, $expectedResult ) { + $handler = new WebPHandler(); + $this->assertEquals( $expectedResult, $handler->getImageSize( null, $path ) ); + } + public function provideTestGetImageSize() { + return array( + // Public domain files from https://developers.google.com/speed/webp/gallery2 + array( __DIR__ . '/../../data/media/2_webp_a.webp', array( 386, 395 ) ), + array( __DIR__ . '/../../data/media/2_webp_ll.webp', array( 386, 395 ) ), + array( __DIR__ . '/../../data/media/webp_animated.webp', array( 300, 225 ) ), + + // Error cases + array( __FILE__, false ), + ); + } + + /** + * Tests the WebP MIME detection. This should really be a separate test, but sticking it + * here for now. + * + * @dataProvider provideTestGetMimeType + */ + public function testGuessMimeType( $path ) { + $mime = MimeMagic::singleton(); + $this->assertEquals( 'image/webp', $mime->guessMimeType( $path, false ) ); + } + public function provideTestGetMimeType() { + return array( + // Public domain files from https://developers.google.com/speed/webp/gallery2 + array( __DIR__ . '/../../data/media/2_webp_a.webp' ), + array( __DIR__ . '/../../data/media/2_webp_ll.webp' ), + array( __DIR__ . '/../../data/media/webp_animated.webp' ), + ); + } +} + +/* Python code to extract a header and convert to PHP format: + * print '"%s"' % ''.join( '\\x%02X' % ord(c) for c in urllib.urlopen(url).read(36) ) + */ diff --git a/tests/phpunit/includes/media/XMPValidateTest.php b/tests/phpunit/includes/media/XMPValidateTest.php index ebec8f6c..53671d42 100644 --- a/tests/phpunit/includes/media/XMPValidateTest.php +++ b/tests/phpunit/includes/media/XMPValidateTest.php @@ -1,5 +1,7 @@ validateDate( array(), $value, true ); $this->assertEquals( $expected, $value ); } diff --git a/tests/phpunit/includes/objectcache/BagOStuffTest.php b/tests/phpunit/includes/objectcache/BagOStuffTest.php index 4516bb4e..b6840062 100644 --- a/tests/phpunit/includes/objectcache/BagOStuffTest.php +++ b/tests/phpunit/includes/objectcache/BagOStuffTest.php @@ -1,8 +1,10 @@ + * @group BagOStuff */ class BagOStuffTest extends MediaWikiTestCase { + /** @var BagOStuff */ private $cache; protected function setUp() { @@ -136,20 +138,48 @@ class BagOStuffTest extends MediaWikiTestCase { public function testGetMulti() { $value1 = array( 'this' => 'is', 'a' => 'test' ); $value2 = array( 'this' => 'is', 'another' => 'test' ); + $value3 = array( 'testing a key that may be encoded when sent to cache backend' ); $key1 = wfMemcKey( 'test1' ); $key2 = wfMemcKey( 'test2' ); + $key3 = wfMemcKey( 'will-%-encode' ); // internally, MemcachedBagOStuffs will encode to will-%25-encode $this->cache->add( $key1, $value1 ); $this->cache->add( $key2, $value2 ); + $this->cache->add( $key3, $value3 ); $this->assertEquals( - $this->cache->getMulti( array( $key1, $key2 ) ), - array( $key1 => $value1, $key2 => $value2 ) + array( $key1 => $value1, $key2 => $value2, $key3 => $value3 ), + $this->cache->getMulti( array( $key1, $key2, $key3 ) ) ); // cleanup $this->cache->delete( $key1 ); $this->cache->delete( $key2 ); + $this->cache->delete( $key3 ); + } + + /** + * @covers BagOStuff::getScopedLock + */ + public function testGetScopedLock() { + $key = wfMemcKey( 'test' ); + $value1 = $this->cache->getScopedLock( $key, 0 ); + $value2 = $this->cache->getScopedLock( $key, 0 ); + + $this->assertType( 'ScopedCallback', $value1, 'First call returned lock' ); + $this->assertNull( $value2, 'Duplicate call returned no lock' ); + + unset( $value1 ); + + $value3 = $this->cache->getScopedLock( $key, 0 ); + $this->assertType( 'ScopedCallback', $value3, 'Lock returned callback after release' ); + unset( $value3 ); + + $value1 = $this->cache->getScopedLock( $key, 0, 5, 'reentry' ); + $value2 = $this->cache->getScopedLock( $key, 0, 5, 'reentry' ); + + $this->assertType( 'ScopedCallback', $value1, 'First reentrant call returned lock' ); + $this->assertType( 'ScopedCallback', $value1, 'Second reentrant call returned lock' ); } } diff --git a/tests/phpunit/includes/objectcache/MultiWriteBagOStuffTest.php b/tests/phpunit/includes/objectcache/MultiWriteBagOStuffTest.php new file mode 100644 index 00000000..2b66181c --- /dev/null +++ b/tests/phpunit/includes/objectcache/MultiWriteBagOStuffTest.php @@ -0,0 +1,55 @@ +cache1 = new HashBagOStuff(); + $this->cache2 = new HashBagOStuff(); + $this->cache = new MultiWriteBagOStuff( array( + 'caches' => array( $this->cache1, $this->cache2 ), + 'replication' => 'async' + ) ); + } + + public function testSetImmediate() { + $key = wfRandomString(); + $value = wfRandomString(); + $this->cache->set( $key, $value ); + + // Set in tier 1 + $this->assertEquals( $value, $this->cache1->get( $key ), 'Written to tier 1' ); + // Set in tier 2 + $this->assertEquals( $value, $this->cache2->get( $key ), 'Written to tier 2' ); + } + + public function testSetDelayed() { + $key = wfRandomString(); + $value = wfRandomString(); + + // XXX: DeferredUpdates bound to transactions in CLI mode + $dbw = wfGetDB( DB_MASTER ); + $dbw->begin(); + $this->cache->set( $key, $value ); + + // Set in tier 1 + $this->assertEquals( $value, $this->cache1->get( $key ), 'Written to tier 1' ); + // Not yet set in tier 2 + $this->assertEquals( false, $this->cache2->get( $key ), 'Not written to tier 2' ); + + $dbw->commit(); + + // Set in tier 2 + $this->assertEquals( $value, $this->cache2->get( $key ), 'Written to tier 2' ); + } +} diff --git a/tests/phpunit/includes/objectcache/ReplicatedBagOStuffTest.php b/tests/phpunit/includes/objectcache/ReplicatedBagOStuffTest.php new file mode 100644 index 00000000..a419f5b6 --- /dev/null +++ b/tests/phpunit/includes/objectcache/ReplicatedBagOStuffTest.php @@ -0,0 +1,62 @@ +writeCache = new HashBagOStuff(); + $this->readCache = new HashBagOStuff(); + $this->cache = new ReplicatedBagOStuff( array( + 'writeFactory' => $this->writeCache, + 'readFactory' => $this->readCache, + ) ); + } + + /** + * @covers ReplicatedBagOStuff::set + */ + public function testSet() { + $key = wfRandomString(); + $value = wfRandomString(); + $this->cache->set( $key, $value ); + + // Write to master. + $this->assertEquals( $this->writeCache->get( $key ), $value ); + // Don't write to slave. Replication is deferred to backend. + $this->assertEquals( $this->readCache->get( $key ), false ); + } + + /** + * @covers ReplicatedBagOStuff::get + */ + public function testGet() { + $key = wfRandomString(); + + $write = wfRandomString(); + $this->writeCache->set( $key, $write ); + $read = wfRandomString(); + $this->readCache->set( $key, $read ); + + // Read from slave. + $this->assertEquals( $this->cache->get( $key ), $read ); + } + + /** + * @covers ReplicatedBagOStuff::get + */ + public function testGetAbsent() { + $key = wfRandomString(); + $value = wfRandomString(); + $this->writeCache->set( $key, $value ); + + // Don't read from master. No failover if value is absent. + $this->assertEquals( $this->cache->get( $key ), false ); + } +} diff --git a/tests/phpunit/includes/objectcache/WANObjectCacheTest.php b/tests/phpunit/includes/objectcache/WANObjectCacheTest.php new file mode 100644 index 00000000..40ae4613 --- /dev/null +++ b/tests/phpunit/includes/objectcache/WANObjectCacheTest.php @@ -0,0 +1,292 @@ +getCliArg( 'use-wanobjectcache' ) ) { + $name = $this->getCliArg( 'use-wanobjectcache' ); + + $this->cache = ObjectCache::getWANInstance( $name ); + } else { + $this->cache = new WANObjectCache( array( + 'cache' => new HashBagOStuff(), + 'pool' => 'testcache-hash', + 'relayer' => new EventRelayerNull( array() ) + ) ); + } + + $wanCache = TestingAccessWrapper::newFromObject( $this->cache ); + $this->internalCache = $wanCache->cache; + } + + /** + * @dataProvider provider_testSetAndGet + * @covers WANObjectCache::set() + * @covers WANObjectCache::get() + * @param mixed $value + * @param integer $ttl + */ + public function testSetAndGet( $value, $ttl ) { + $key = wfRandomString(); + $this->cache->set( $key, $value, $ttl ); + + $curTTL = null; + $this->assertEquals( $value, $this->cache->get( $key, $curTTL ) ); + if ( is_infinite( $ttl ) || $ttl == 0 ) { + $this->assertTrue( is_infinite( $curTTL ), "Current TTL is infinite" ); + } else { + $this->assertGreaterThan( 0, $curTTL, "Current TTL > 0" ); + $this->assertLessThanOrEqual( $ttl, $curTTL, "Current TTL < nominal TTL" ); + } + } + + public static function provider_testSetAndGet() { + return array( + array( 14141, 3 ), + array( 3535.666, 3 ), + array( array(), 3 ), + array( null, 3 ), + array( '0', 3 ), + array( (object)array( 'meow' ), 3 ), + array( INF, 3 ), + array( '', 3 ), + array( 'pizzacat', INF ), + ); + } + + public function testGetNotExists() { + $key = wfRandomString(); + $curTTL = null; + $value = $this->cache->get( $key, $curTTL ); + + $this->assertFalse( $value, "Non-existing key has false value" ); + $this->assertNull( $curTTL, "Non-existing key has null current TTL" ); + } + + public function testSetOver() { + $key = wfRandomString(); + for ( $i = 0; $i < 3; ++$i ) { + $value = wfRandomString(); + $this->cache->set( $key, $value, 3 ); + + $this->assertEquals( $this->cache->get( $key ), $value ); + } + } + + /** + * @covers WANObjectCache::getWithSetCallback() + */ + public function testGetWithSetCallback() { + $cache = $this->cache; + + $key = wfRandomString(); + $value = wfRandomString(); + $cKey1 = wfRandomString(); + $cKey2 = wfRandomString(); + + $wasSet = 0; + $func = function( $old, &$ttl ) use ( &$wasSet, $value ) { + ++$wasSet; + $ttl = 20; // override with another value + return $value; + }; + + $wasSet = 0; + $v = $cache->getWithSetCallback( $key, $func, 30, array(), array( 'lockTSE' => 5 ) ); + $this->assertEquals( $v, $value ); + $this->assertEquals( 1, $wasSet, "Value regenerated" ); + + $curTTL = null; + $v = $cache->get( $key, $curTTL ); + $this->assertLessThanOrEqual( 20, $curTTL, 'Current TTL between 19-20 (overriden)' ); + $this->assertGreaterThanOrEqual( 19, $curTTL, 'Current TTL between 19-20 (overriden)' ); + + $wasSet = 0; + $v = $cache->getWithSetCallback( $key, $func, 30, array(), array( 'lockTSE' => 5 ) ); + $this->assertEquals( $v, $value ); + $this->assertEquals( 0, $wasSet, "Value not regenerated" ); + + $priorTime = microtime( true ); + usleep( 1 ); + $wasSet = 0; + $v = $cache->getWithSetCallback( $key, $func, 30, array( $cKey1, $cKey2 ) ); + $this->assertEquals( $v, $value ); + $this->assertEquals( 1, $wasSet, "Value regenerated due to check keys" ); + $t1 = $cache->getCheckKeyTime( $cKey1 ); + $this->assertGreaterThanOrEqual( $priorTime, $t1, 'Check keys generated on miss' ); + $t2 = $cache->getCheckKeyTime( $cKey2 ); + $this->assertGreaterThanOrEqual( $priorTime, $t2, 'Check keys generated on miss' ); + + $priorTime = microtime( true ); + $wasSet = 0; + $v = $cache->getWithSetCallback( $key, $func, 30, array( $cKey1, $cKey2 ) ); + $this->assertEquals( $v, $value ); + $this->assertEquals( 1, $wasSet, "Value regenerated due to still-recent check keys" ); + $t1 = $cache->getCheckKeyTime( $cKey1 ); + $this->assertLessThanOrEqual( $priorTime, $t1, 'Check keys did not change again' ); + $t2 = $cache->getCheckKeyTime( $cKey2 ); + $this->assertLessThanOrEqual( $priorTime, $t2, 'Check keys did not change again' ); + + $curTTL = null; + $v = $cache->get( $key, $curTTL, array( $cKey1, $cKey2 ) ); + $this->assertEquals( $v, $value ); + $this->assertLessThanOrEqual( 0, $curTTL, "Value has current TTL < 0 due to check keys" ); + } + + /** + * @covers WANObjectCache::getWithSetCallback() + */ + public function testLockTSE() { + $cache = $this->cache; + $key = wfRandomString(); + $value = wfRandomString(); + + $calls = 0; + $func = function() use ( &$calls, $value ) { + ++$calls; + return $value; + }; + + $cache->delete( $key ); + $ret = $cache->getWithSetCallback( $key, 30, $func, array(), array( 'lockTSE' => 5 ) ); + $this->assertEquals( $value, $ret ); + $this->assertEquals( 1, $calls, 'Value was populated' ); + + // Acquire a lock to verify that getWithSetCallback uses lockTSE properly + $this->internalCache->lock( $key, 0 ); + $ret = $cache->getWithSetCallback( $key, 30, $func, array(), array( 'lockTSE' => 5 ) ); + $this->assertEquals( $value, $ret ); + $this->assertEquals( 1, $calls, 'Callback was not used' ); + } + + /** + * @covers WANObjectCache::getMulti() + */ + public function testGetMulti() { + $cache = $this->cache; + + $value1 = array( 'this' => 'is', 'a' => 'test' ); + $value2 = array( 'this' => 'is', 'another' => 'test' ); + + $key1 = wfRandomString(); + $key2 = wfRandomString(); + $key3 = wfRandomString(); + + $cache->set( $key1, $value1, 5 ); + $cache->set( $key2, $value2, 10 ); + + $curTTLs = array(); + $this->assertEquals( + array( $key1 => $value1, $key2 => $value2 ), + $cache->getMulti( array( $key1, $key2, $key3 ), $curTTLs ) + ); + + $this->assertEquals( 2, count( $curTTLs ), "Two current TTLs in array" ); + $this->assertGreaterThan( 0, $curTTLs[$key1], "Key 1 has current TTL > 0" ); + $this->assertGreaterThan( 0, $curTTLs[$key2], "Key 2 has current TTL > 0" ); + + $cKey1 = wfRandomString(); + $cKey2 = wfRandomString(); + $curTTLs = array(); + $this->assertEquals( + array( $key1 => $value1, $key2 => $value2 ), + $cache->getMulti( array( $key1, $key2, $key3 ), $curTTLs ), + 'Result array populated' + ); + + $priorTime = microtime( true ); + usleep( 1 ); + $curTTLs = array(); + $this->assertEquals( + array( $key1 => $value1, $key2 => $value2 ), + $cache->getMulti( array( $key1, $key2, $key3 ), $curTTLs, array( $cKey1, $cKey2 ) ), + "Result array populated even with new check keys" + ); + $t1 = $cache->getCheckKeyTime( $cKey1 ); + $this->assertGreaterThanOrEqual( $priorTime, $t1, 'Check key 1 generated on miss' ); + $t2 = $cache->getCheckKeyTime( $cKey2 ); + $this->assertGreaterThanOrEqual( $priorTime, $t2, 'Check key 2 generated on miss' ); + $this->assertEquals( 2, count( $curTTLs ), "Current TTLs array set" ); + $this->assertLessThanOrEqual( 0, $curTTLs[$key1], 'Key 1 has current TTL <= 0' ); + $this->assertLessThanOrEqual( 0, $curTTLs[$key2], 'Key 2 has current TTL <= 0' ); + + usleep( 1 ); + $curTTLs = array(); + $this->assertEquals( + array( $key1 => $value1, $key2 => $value2 ), + $cache->getMulti( array( $key1, $key2, $key3 ), $curTTLs, array( $cKey1, $cKey2 ) ), + "Result array still populated even with new check keys" + ); + $this->assertEquals( 2, count( $curTTLs ), "Current TTLs still array set" ); + $this->assertLessThan( 0, $curTTLs[$key1], 'Key 1 has negative current TTL' ); + $this->assertLessThan( 0, $curTTLs[$key2], 'Key 2 has negative current TTL' ); + } + + /** + * @covers WANObjectCache::delete() + */ + public function testDelete() { + $key = wfRandomString(); + $value = wfRandomString(); + $this->cache->set( $key, $value ); + + $curTTL = null; + $v = $this->cache->get( $key, $curTTL ); + $this->assertEquals( $value, $v, "Key was created with value" ); + $this->assertGreaterThan( 0, $curTTL, "Existing key has current TTL > 0" ); + + $this->cache->delete( $key ); + + $curTTL = null; + $v = $this->cache->get( $key, $curTTL ); + $this->assertFalse( $v, "Deleted key has false value" ); + $this->assertLessThan( 0, $curTTL, "Deleted key has current TTL < 0" ); + + $this->cache->set( $key, $value . 'more' ); + $this->assertFalse( $v, "Deleted key is tombstoned and has false value" ); + $this->assertLessThan( 0, $curTTL, "Deleted key is tombstoned and has current TTL < 0" ); + } + + /** + * @covers WANObjectCache::touchCheckKey() + * @covers WANObjectCache::resetCheckKey() + * @covers WANObjectCache::getCheckKeyTime() + */ + public function testTouchKeys() { + $key = wfRandomString(); + + $priorTime = microtime( true ); + usleep( 1 ); + $t0 = $this->cache->getCheckKeyTime( $key ); + $this->assertGreaterThanOrEqual( $priorTime, $t0, 'Check key auto-created' ); + + $priorTime = microtime( true ); + usleep( 1 ); + $this->cache->touchCheckKey( $key ); + $t1 = $this->cache->getCheckKeyTime( $key ); + $this->assertGreaterThanOrEqual( $priorTime, $t1, 'Check key created' ); + + $t2 = $this->cache->getCheckKeyTime( $key ); + $this->assertEquals( $t1, $t2, 'Check key time did not change' ); + + usleep( 1 ); + $this->cache->touchCheckKey( $key ); + $t3 = $this->cache->getCheckKeyTime( $key ); + $this->assertGreaterThan( $t2, $t3, 'Check key time increased' ); + + $t4 = $this->cache->getCheckKeyTime( $key ); + $this->assertEquals( $t3, $t4, 'Check key time did not change' ); + + usleep( 1 ); + $this->cache->resetCheckKey( $key ); + $t5 = $this->cache->getCheckKeyTime( $key ); + $this->assertGreaterThan( $t4, $t5, 'Check key time increased' ); + + $t6 = $this->cache->getCheckKeyTime( $key ); + $this->assertEquals( $t5, $t6, 'Check key time did not change' ); + } +} diff --git a/tests/phpunit/includes/parser/MagicVariableTest.php b/tests/phpunit/includes/parser/MagicVariableTest.php index 17226113..cd54a9e3 100644 --- a/tests/phpunit/includes/parser/MagicVariableTest.php +++ b/tests/phpunit/includes/parser/MagicVariableTest.php @@ -10,6 +10,8 @@ * @copyright Copyright © 2011, Antoine Musso * @file * @todo covers tags + * + * @group Database */ class MagicVariableTest extends MediaWikiTestCase { diff --git a/tests/phpunit/includes/parser/MediaWikiParserTest.php b/tests/phpunit/includes/parser/MediaWikiParserTest.php index df891f5a..96ae3bec 100644 --- a/tests/phpunit/includes/parser/MediaWikiParserTest.php +++ b/tests/phpunit/includes/parser/MediaWikiParserTest.php @@ -91,7 +91,7 @@ class MediaWikiParserTest { // enough to cause there to be separate names for different // things, which is good enough for our purposes. $extensionName = basename( dirname( $fileName ) ); - $testsName = $extensionName . '⁄' . basename( $fileName, '.txt' ); + $testsName = $extensionName . '__' . basename( $fileName, '.txt' ); $escapedFileName = strtr( $fileName, array( "'" => "\\'", '\\' => '\\\\' ) ); $parserTestClassName = ucfirst( $testsName ); // Official spec for class names: http://php.net/manual/en/language.oop5.basic.php diff --git a/tests/phpunit/includes/parser/NewParserTest.php b/tests/phpunit/includes/parser/NewParserTest.php index 91aad10c..df7da98c 100644 --- a/tests/phpunit/includes/parser/NewParserTest.php +++ b/tests/phpunit/includes/parser/NewParserTest.php @@ -91,7 +91,7 @@ class NewParserTest extends MediaWikiTestCase { ); $tmpGlobals['wgForeignFileRepos'] = array(); $tmpGlobals['wgDefaultExternalStore'] = array(); - $tmpGlobals['wgEnableParserCache'] = false; + $tmpGlobals['wgParserCacheType'] = CACHE_NONE; $tmpGlobals['wgCapitalLinks'] = true; $tmpGlobals['wgNoFollowLinks'] = true; $tmpGlobals['wgNoFollowDomainExceptions'] = array(); @@ -106,7 +106,6 @@ class NewParserTest extends MediaWikiTestCase { $tmpGlobals['wgAdaptiveMessageCache'] = true; $tmpGlobals['wgUseDatabaseMessages'] = true; $tmpGlobals['wgLocaltimezone'] = 'UTC'; - $tmpGlobals['wgDeferredUpdateList'] = array(); $tmpGlobals['wgGroupPermissions'] = array( '*' => array( 'createaccount' => true, @@ -160,10 +159,10 @@ class NewParserTest extends MediaWikiTestCase { $this->djVuSupport = new DjVuSupport(); // Tidy support $this->tidySupport = new TidySupport(); + $tmpGlobals['wgTidyConfig'] = null; $tmpGlobals['wgUseTidy'] = false; - $tmpGlobals['wgAlwaysUseTidy'] = false; $tmpGlobals['wgDebugTidy'] = false; - $tmpGlobals['wgTidyConf'] = $IP . '/includes/tidy.conf'; + $tmpGlobals['wgTidyConf'] = $IP . '/includes/tidy/tidy.conf'; $tmpGlobals['wgTidyOpts'] = ''; $tmpGlobals['wgTidyInternal'] = $this->tidySupport->isInternal(); @@ -185,6 +184,8 @@ class NewParserTest extends MediaWikiTestCase { $wgNamespaceAliases['Image'] = $this->savedWeirdGlobals['image_alias']; $wgNamespaceAliases['Image_talk'] = $this->savedWeirdGlobals['image_talk_alias']; + MWTidy::destroySingleton(); + // Restore backends RepoGroup::destroySingleton(); FileBackendGroup::destroySingleton(); @@ -454,6 +455,7 @@ class NewParserTest extends MediaWikiTestCase { $GLOBALS[$var] = $val; } + MWTidy::destroySingleton(); MagicWord::clearCache(); # The entries saved into RepoGroup cache with previous globals will be wrong. diff --git a/tests/phpunit/includes/parser/ParserMethodsTest.php b/tests/phpunit/includes/parser/ParserMethodsTest.php index 1790086a..af143caa 100644 --- a/tests/phpunit/includes/parser/ParserMethodsTest.php +++ b/tests/phpunit/includes/parser/ParserMethodsTest.php @@ -1,5 +1,9 @@ bar" ), array( "foo\nbar" ), array( "foo\rbar" ) ); } - protected function setUp() { - parent::setUp(); - - $this->setMwGlobals( 'wgAlwaysUseTidy', false ); - } - /** * @dataProvider provideValidNames * @covers Parser::setHook diff --git a/tests/phpunit/includes/parser/TidyTest.php b/tests/phpunit/includes/parser/TidyTest.php index f656a74d..5db29080 100644 --- a/tests/phpunit/includes/parser/TidyTest.php +++ b/tests/phpunit/includes/parser/TidyTest.php @@ -7,8 +7,7 @@ class TidyTest extends MediaWikiTestCase { protected function setUp() { parent::setUp(); - $check = MWTidy::tidy( '' ); - if ( strpos( $check, '